Repository: electron/electron
Pull request: ci: rework reapply patches

#### Description of Change

<!--
Thank you for your Pull Request. Please provide a description above and review
the requirements below.

Contributors guide: https://github.com/electron/electron/blob/main/CONTRIBUTING.md
-->

#49516 didn't survive first contact, due to some flawed assumptions. `gh run rerun` will fail if the job/workflow is already running, and you can't cancel an individual job, only a full workflow. That means the previous approach of having `apply-patches` as a job inside the `build.yml` workflow isn't workable because there's no way to cancel and re-run just that job without canceling the whole workflow, and we want to avoid re-running the full build.

This PR reworks the approach to put `apply-patches` in a new workflow that runs against PRs that touch patches or `DEPS`, and updates `rerun-apply-patches.yml` to cancel the workflow if it's in-progress, wait for it to finish canceling, and then rerun the whole workflow.

#### Checklist
<!-- Remove items that do not apply. For completed items, change [ ] to [x]. -->

- [x] PR description included

#### Release Notes

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/apply-patches.yml
patch: @@ -0,0 +1,72 @@
+name: Apply Patches
+
+on:
+  pull_request:
+
+permissions: {}
+
+concurrency:
+  group: apply-patches-${{ github.ref }}
+  cancel-in-progress: true
+
+jobs:
+  setup:
+    if: github.repository == 'electron/electron'
+    runs-on: ubuntu-slim
+    permissions:
+      contents: read
+      pull-requests: read
+    outputs:
+      has-patches: ${{ steps.filter.outputs.patches }}
+    steps:
+    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
+      with:
+        persist-credentials: false
+        ref: ${{ github.event.pull_request.head.sha }}
+    # Use dorny/paths-filter instead of the path filter under the on: pull_request: block
+    # so that the output can be used to conditionally run the apply-patches job, which lets
+    # the job be marked as a required status check (conditional skip counts as a success).
+    - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
+      id: filter
+      with:
+        filters: |
+          patches:
+            - DEPS
+            - 'patches/**'
+
+  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:a82b87d7a4f5ff0cab61405f8151ac4cf4942aeb
+      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@de0fac2e4500dabe0009e67214ff5f5447ce83dd
+      with:
+        path: src/electron
+        fetch-depth: 0
+        persist-credentials: false
+        ref: ${{ github.event.pull_request.head.sha }}
+    - name: Rebase onto Base Branch
+      working-directory: src/electron
+      env:
+        BASE_REF: ${{ github.event.pull_request.base.ref }}
+      run: |
+        git config user.email "electron@github.com"
+        git config user.name "Electron Bot"
+        git fetch origin ${BASE_REF}
+        git rebase origin/${BASE_REF}
+    - name: Checkout & Sync & Save
+      uses: ./src/electron/.github/actions/checkout
+      with:
+        target-platform: linux

filename: .github/workflows/build.yml
patch: @@ -57,7 +57,6 @@ 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@de0fac2e4500dabe0009e67214ff5f5447ce83dd
       with:
@@ -74,9 +73,6 @@ jobs:
             - CODE_OF_CONDUCT.md
           src:
             - '!docs/**'
-          patches:
-            - DEPS
-            - 'patches/**'
     - name: Set Outputs for Build Image SHA & Docs Only
       id: set-output
       run: |
@@ -109,41 +105,6 @@ 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@de0fac2e4500dabe0009e67214ff5f5447ce83dd
-      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: @@ -15,8 +15,9 @@ jobs:
   rerun-apply-patches:
     runs-on: ubuntu-latest
     permissions:
-      contents: read
       actions: write
+      checks: read
+      contents: read
       pull-requests: read
     steps:
       - name: Find PRs and Rerun Apply Patches
@@ -33,11 +34,11 @@ jobs:
             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')
+            # Find the Apply Patches workflow check for this PR
+            CHECK=$(gh pr checks "$PR_NUMBER" --json link,name,state,workflow --jq '[.[] | select(.workflow == "Apply Patches" and .name == "apply-patches")] | first')
 
             if [ -z "$CHECK" ] || [ "$CHECK" = "null" ]; then
-              echo "  No apply-patches job found for PR #${PR_NUMBER}"
+              echo "  No Apply Patches workflow found for PR #${PR_NUMBER}"
               continue
             fi
 
@@ -57,13 +58,14 @@ jobs:
               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')
+            # Check if the workflow is currently in progress
+            RUN_STATUS=$(gh run view "$RUN_ID" --json status --jq '.status')
 
-            if [ -z "$JOB_ID" ]; then
-              echo "  Could not find apply-patches job ID for run: ${RUN_ID}"
-              continue
+            if [ "$RUN_STATUS" = "in_progress" ] || [ "$RUN_STATUS" = "queued" ] || [ "$RUN_STATUS" = "waiting" ]; then
+              echo "  Workflow run ${RUN_ID} is ${RUN_STATUS}, cancelling..."
+              gh run cancel "$RUN_ID" --force
+              gh run watch "$RUN_ID"
             fi
 
-            gh run rerun "$RUN_ID" --job "$JOB_ID"
+            gh run rerun "$RUN_ID"
           done