Skip to content

Commit 68f7978

Browse files
committed
feat(label-pr-review-state): check only required steps
1 parent 617ff95 commit 68f7978

1 file changed

Lines changed: 40 additions & 9 deletions

File tree

.github/workflows/label-pr-review-state.yml

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,26 @@ jobs:
7474
}
7575
}
7676
77+
// Fetch required status check names from the branch ruleset.
78+
// Uses the public /rules/branches endpoint — no admin token needed.
79+
// Falls back to blocking on all checks if the endpoint is unavailable.
80+
let requiredCheckNames = null;
81+
try {
82+
const { data: rules } = await github.request(
83+
'GET /repos/{owner}/{repo}/rules/branches/{branch}',
84+
{ owner, repo, branch: 'main' },
85+
);
86+
const statusRule = rules.find(r => r.type === 'required_status_checks');
87+
if (statusRule) {
88+
requiredCheckNames = new Set(
89+
statusRule.parameters.required_status_checks.map(c => c.context),
90+
);
91+
core.info(`Required checks: ${[...requiredCheckNames].join(', ')}`);
92+
}
93+
} catch (err) {
94+
core.warning(`Could not fetch branch rules, falling back to all checks: ${err.message}`);
95+
}
96+
7797
const failures = [];
7898
7999
for (const pr of prs) {
@@ -85,8 +105,9 @@ jobs:
85105
continue;
86106
}
87107
88-
// Check aggregate CI status for the PR's head commit.
89-
// We combine check runs (Actions) and commit statuses (external CIs).
108+
// Check CI status for required checks on the PR's head commit only.
109+
// Scoping to required checks avoids advisory checks (e.g. codecov/patch)
110+
// incorrectly blocking label assignment on otherwise-ready PRs.
90111
const [checkRuns, commitStatusRes] = await Promise.all([
91112
github.paginate(github.rest.checks.listForRef, {
92113
owner, repo, ref: pr.head.sha, per_page: 100,
@@ -96,28 +117,38 @@ jobs:
96117
}),
97118
]);
98119
99-
// Exclude this workflow's own check run to avoid self-referential loops.
100-
const relevantRuns = checkRuns.filter(
101-
run => run.name !== 'Reconcile PR review state labels',
102-
);
120+
// Filter to required checks only (or all checks if rules unavailable).
121+
// Always exclude this workflow's own run to avoid self-referential loops.
122+
const relevantRuns = checkRuns.filter(run => {
123+
if (run.name === 'Reconcile PR review state labels') return false;
124+
return requiredCheckNames ? requiredCheckNames.has(run.name) : true;
125+
});
126+
127+
// For commit statuses (external CIs), there's no per-status name filtering
128+
// available from getCombinedStatusForRef — it aggregates all statuses.
129+
// If required checks are known, we only use commitStatus as a signal when
130+
// no required check runs exist for this ref (i.e. pure status-based CI).
131+
const useCommitStatus = !requiredCheckNames || relevantRuns.length === 0;
103132
104-
core.debug(`PR #${pr.number}: ${relevantRuns.length} check run(s), commit status=${commitStatusRes.data.state}`);
133+
core.debug(`PR #${pr.number}: ${relevantRuns.length} required check run(s), commit status=${commitStatusRes.data.state} (used=${useCommitStatus})`);
105134
for (const run of relevantRuns) {
106135
core.debug(` check: "${run.name}" status=${run.status} conclusion=${run.conclusion}`);
107136
}
108137
109138
const ciPending = relevantRuns.some(
110139
run => run.status === 'queued' || run.status === 'in_progress',
111-
) || commitStatusRes.data.state === 'pending';
140+
) || (useCommitStatus && commitStatusRes.data.state === 'pending');
112141
113142
const ciFailed = !ciPending && (
114143
relevantRuns.some(
115144
run => run.status === 'completed' &&
116145
run.conclusion !== 'success' &&
117146
run.conclusion !== 'skipped' &&
118147
run.conclusion !== 'neutral',
119-
) || commitStatusRes.data.state === 'failure' ||
148+
) || (useCommitStatus && (
149+
commitStatusRes.data.state === 'failure' ||
120150
commitStatusRes.data.state === 'error'
151+
))
121152
);
122153
123154
// While CI is running or has failed, remove state labels and move on.

0 commit comments

Comments
 (0)