Repository: electron/electron
Pull request: ci: reapply patches if PR base branch updates them

Backport of #49516

See that PR for details.


Notes: none <!-- Please add a one-line description for app developers to read in the release notes, or 'none' if no notes relevant to app developers. Examples and help on special cases: https://github.com/electron/clerk/blob/main/README.md#examples -->


Changed files:
filename: .github/workflows/build.yml
patch: @@ -56,6 +56,7 @@ jobs:
         src: ${{ steps.filter.outputs.src }}
         build-image-sha: ${{ steps.set-output.outputs.build-image-sha }}
         docs-only: ${{ steps.set-output.outputs.docs-only }}
+        has-patches: ${{ steps.filter.outputs.patches }}
     steps:
     - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
       with:
@@ -72,6 +73,9 @@ jobs:
             - CODE_OF_CONDUCT.md
           src:
             - '!docs/**'
+          patches:
+            - DEPS
+            - 'patches/**'
     - name: Set Outputs for Build Image SHA & Docs Only
       id: set-output
       run: |
@@ -104,6 +108,41 @@ jobs:
       container: '{"image":"ghcr.io/electron/build:${{ needs.checkout-linux.outputs.build-image-sha }}","options":"--user root","volumes":["/mnt/cross-instance-cache:/mnt/cross-instance-cache"]}'
     secrets: inherit
 
+  # Apply Patches Job
+  apply-patches:
+    needs: setup
+    if: ${{ needs.setup.outputs.has-patches == 'true' }}
+    runs-on: electron-arc-centralus-linux-amd64-32core
+    permissions:
+      contents: read
+    container:
+      image: ghcr.io/electron/build:${{ needs.setup.outputs.build-image-sha }}
+      options: --user root
+      volumes:
+        - /mnt/cross-instance-cache:/mnt/cross-instance-cache
+        - /var/run/sas:/var/run/sas
+    env:
+      CHROMIUM_GIT_COOKIE: ${{ secrets.CHROMIUM_GIT_COOKIE }}
+      GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True'
+    steps:
+    - name: Checkout Electron
+      uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
+      with:
+        path: src/electron
+        fetch-depth: 0
+        ref: ${{ github.event.pull_request.head.sha }}
+    - name: Rebase onto Base Branch
+      working-directory: src/electron
+      run: |
+        git config user.email "electron@github.com"
+        git config user.name "Electron Bot"
+        git fetch origin ${{ github.event.pull_request.base.ref }}
+        git rebase origin/${{ github.event.pull_request.base.ref }}
+    - name: Checkout & Sync & Save
+      uses: ./src/electron/.github/actions/checkout
+      with:
+        target-platform: linux
+
   # Checkout Jobs
   checkout-macos:
     needs: setup

filename: .github/workflows/rerun-apply-patches.yml
patch: @@ -0,0 +1,69 @@
+name: Rerun PR Apply Patches
+
+on:
+  push:
+    branches:
+      - main
+      - '[1-9][0-9]-x-y'
+    paths:
+      - 'DEPS'
+      - 'patches/**'
+
+permissions: {}
+
+jobs:
+  rerun-apply-patches:
+    runs-on: ubuntu-latest
+    permissions:
+      contents: read
+      actions: write
+      pull-requests: read
+    steps:
+      - name: Find PRs and Rerun Apply Patches
+        env:
+          GH_REPO: ${{ github.repository }}
+          GH_TOKEN: ${{ github.token }}
+        run: |
+          BRANCH="${GITHUB_REF#refs/heads/}"
+
+          # Find all open PRs targeting this branch
+          PRS=$(gh pr list --base "$BRANCH" --state open --limit 250 --json number)
+
+          echo "$PRS" | jq -c '.[]' | while read -r pr; do
+            PR_NUMBER=$(echo "$pr" | jq -r '.number')
+            echo "Processing PR #${PR_NUMBER}"
+
+            # Find the apply-patches job check for this PR
+            CHECK=$(gh pr checks "$PR_NUMBER" --json link,name,state,workflow --jq '[.[] | select(.workflow == "Build" and .name == "apply-patches")] | first')
+
+            if [ -z "$CHECK" ] || [ "$CHECK" = "null" ]; then
+              echo "  No apply-patches job found for PR #${PR_NUMBER}"
+              continue
+            fi
+
+            STATE=$(echo "$CHECK" | jq -r '.state')
+            if [ "$STATE" = "SKIPPED" ]; then
+              echo "  apply-patches job was skipped for PR #${PR_NUMBER} (no patches)"
+              continue
+            fi
+
+            LINK=$(echo "$CHECK" | jq -r '.link')
+
+            # Extract the run ID from the link (format: .../runs/RUN_ID/job/JOB_ID)
+            RUN_ID=$(echo "$LINK" | grep -oE 'runs/[0-9]+' | cut -d'/' -f2)
+
+            if [ -z "$RUN_ID" ]; then
+              echo "  Could not extract run ID from link: ${LINK}"
+              continue
+            fi
+
+            # Get the job database ID for the apply-patches job
+            JOB_ID=$(gh run view "$RUN_ID" --json jobs --jq '.jobs[] | select(.name == "apply-patches") | .databaseId')
+
+            if [ -z "$JOB_ID" ]; then
+              echo "  Could not find apply-patches job ID for run: ${RUN_ID}"
+              continue
+            fi
+
+            gh run rerun "$RUN_ID" --job "$JOB_ID"
+          done