From e79b2ef6b5d3852f168e36810120ccb55e832ba3 Mon Sep 17 00:00:00 2001 From: Archkon <180910180+Archkon@users.noreply.github.com> Date: Sun, 9 Aug 2026 02:28:16 +0800 Subject: [PATCH] fix(ci): ignore superseded GitHub Actions runs A commit can have multiple check suites for the same workflow and event when a branch is force-pushed away from and then back to the same SHA. Select the suite with the highest workflow run number and request only the latest check runs to avoid reporting superseded CI failures. Signed-off-by: Archkon <180910180+Archkon@users.noreply.github.com> --- lib/pr_checker.js | 35 +++++++++++++++++++++++++++-------- lib/queries/PRCommits.gql | 9 ++++++++- 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/lib/pr_checker.js b/lib/pr_checker.js index c4058f12..e28d1616 100644 --- a/lib/pr_checker.js +++ b/lib/pr_checker.js @@ -29,6 +29,30 @@ const FAST_TRACK_RE = /^Fast-track has been requested by @(.+?)\. Please 👍 to const FAST_TRACK_MIN_APPROVALS = 2; const GIT_CONFIG_GUIDE_URL = 'https://github.com/nodejs/node/blob/99b1ada/doc/guides/contributing/pull-requests.md#step-1-fork'; +function getLatestGitHubActionsCheckSuites(checkSuites) { + const latestByWorkflow = new Map(); + + for (const suite of checkSuites) { + const { app, workflowRun } = suite; + + if (app?.slug !== 'github-actions') { + continue; + } + + // Runs triggered by different events are independent and must not + // supersede one another. + const key = `${workflowRun.workflow.id}:${workflowRun.event}`; + const current = latestByWorkflow.get(key); + + if (!current || + workflowRun.runNumber > current.workflowRun.runNumber) { + latestByWorkflow.set(key, suite); + } + } + + return [...latestByWorkflow.values()]; +} + export const PR_CHECK_REASON_CODES = Object.freeze({ CANCELLED_GITHUB_CI: 'cancelled-github-ci', CLOSED: 'closed', @@ -459,14 +483,9 @@ export default class PRChecker { const pendingJobs = []; // GitHub new Check API - for (const { status, conclusion, app, checkRuns } of checkSuites.nodes) { - if (app.slug !== 'github-actions') { - // Ignore all non-github check suites, such as Dependabot and Codecov. - // They are expected to show up on PRs whose head branch is not on a - // fork and never complete. - continue; - } - + const latestCheckSuites = + getLatestGitHubActionsCheckSuites(checkSuites.nodes); + for (const { status, conclusion, app, checkRuns } of latestCheckSuites) { if (status !== 'COMPLETED') { pendingJobs.push({ app: app.slug, status, conclusion }); continue; diff --git a/lib/queries/PRCommits.gql b/lib/queries/PRCommits.gql index 70cf2e4e..9c415c9a 100644 --- a/lib/queries/PRCommits.gql +++ b/lib/queries/PRCommits.gql @@ -32,7 +32,14 @@ query Commits($prid: Int!, $owner: String!, $repo: String!, $after: String) { } conclusion, status, - checkRuns(first: 40) { + workflowRun { + event + runNumber + workflow { + id + } + } + checkRuns(first: 40, filterBy: { checkType: LATEST }) { nodes { name status