From 8b93fd02a398c618d07256353e92a099981c7374 Mon Sep 17 00:00:00 2001 From: mengw15 <125719918+mengw15@users.noreply.github.com> Date: Sat, 12 Sep 2026 08:55:43 -0700 Subject: [PATCH 1/2] fix(ci): stop cancelling in-progress Backport Approvals runs Backport Approvals is a required status check, and GitHub takes the latest check run with that name. With cancel-in-progress on, two events close together (a push right after a label or review request) let the newer run cancel the older one, whose cancelled state then landed after the newer run's success and blocked the merge as a failed required check (seen on #8516). The job runs in seconds, so queue instead. Closes #8522. Co-Authored-By: Claude Fable 5 --- .github/workflows/backport-approval-check.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/backport-approval-check.yml b/.github/workflows/backport-approval-check.yml index f37a52505c0..34174b992bb 100644 --- a/.github/workflows/backport-approval-check.yml +++ b/.github/workflows/backport-approval-check.yml @@ -58,7 +58,12 @@ permissions: concurrency: group: backport-approvals-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true + # Queue, never cancel: this is a required status check, and GitHub takes the LATEST + # check run with this name. Two events close together (a push right after a label or + # review request) made the newer run cancel the older one, whose "cancelled" state then + # landed after the newer run's success and blocked the merge as a failed required + # check. The job runs in seconds, so queuing costs nothing. + cancel-in-progress: false jobs: backport-approvals: From 428dfb4ffa755d79a9025a476d3dcc5033a90d89 Mon Sep 17 00:00:00 2001 From: mengw15 <125719918+mengw15@users.noreply.github.com> Date: Sat, 12 Sep 2026 10:32:24 -0700 Subject: [PATCH 2/2] fix(ci): narrow the concurrency comment to the guarantee that holds GitHub keeps at most one running and one pending run per concurrency group and replaces the pending one on a newer event, so 'queue, every run completes' overstated it. What holds and matters: the in-progress run is never cancelled, and a replaced pending run is cancelled before its successor even starts, so the latest check run always ends as a real verdict. A skipped intermediate evaluation loses nothing: the job reads the live labels and reviews at run time. Co-Authored-By: Claude Fable 5 --- .github/workflows/backport-approval-check.yml | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/workflows/backport-approval-check.yml b/.github/workflows/backport-approval-check.yml index 34174b992bb..6f92f08935e 100644 --- a/.github/workflows/backport-approval-check.yml +++ b/.github/workflows/backport-approval-check.yml @@ -58,11 +58,14 @@ permissions: concurrency: group: backport-approvals-${{ github.event.pull_request.number || github.ref }} - # Queue, never cancel: this is a required status check, and GitHub takes the LATEST - # check run with this name. Two events close together (a push right after a label or - # review request) made the newer run cancel the older one, whose "cancelled" state then - # landed after the newer run's success and blocked the merge as a failed required - # check. The job runs in seconds, so queuing costs nothing. + # Never cancel the run in progress: this is a required status check, and GitHub + # takes the LATEST check run with this name -- a cancelled in-progress run's + # terminal state can land after a newer run's success (the job is seconds long) + # and block the merge as a failed required check. GitHub still keeps at most one + # pending run per group and replaces it on a newer event, but a replaced pending + # run is cancelled before its successor even starts, so the last word on the + # commit is always a real verdict. A skipped intermediate event loses nothing: + # the job reads the live labels and reviews at run time, not the event payload. cancel-in-progress: false jobs: