fix: prefix matching against matrix-expanded job names (#25212)

This commit is contained in:
Liangsheng Yin
2026-05-13 20:02:57 -07:00
committed by GitHub
parent 856f13a916
commit e51bde1e9f
2 changed files with 20 additions and 9 deletions
+13 -6
View File
@@ -89,7 +89,11 @@ runs:
if (spec.exact) {
return jobName === spec.prefix;
}
return jobName === spec.prefix || jobName.startsWith(spec.prefix + ' (');
// Match bare prefix or any GHA-rendered shard suffix. Inline matrix
// produces `<prefix> (<shard>)`; reusable-workflow callers produce
// `<prefix> / <called-job> (<shard>)`. Both have a space after the
// prefix, so a single ' '-delimited check covers both.
return jobName === spec.prefix || jobName.startsWith(spec.prefix + ' ');
};
// Use ETag conditional requests to avoid consuming rate limit when nothing changed.
@@ -177,13 +181,16 @@ runs:
if (matchingJobs.length < spec.expected_count) {
// Job-level `if:` is evaluated before matrix expansion. When it
// evaluates false, GitHub emits exactly one "skipped" entry using
// the un-expanded job name (bare prefix, no " (shard)" suffix)
// instead of N matrix entries. Detect that precise shape so we
// don't poll forever — and so we don't mistake a partially
// evaluates false, GitHub emits exactly one "skipped" entry
// without a "(shard)" suffix instead of N matrix entries. Two
// shapes are possible:
// - inline matrix: `<prefix>`
// - reusable workflow: `<prefix> / <called-job>`
// Both lack the ` (` shard marker. Detect that precise shape so
// we don't poll forever — and so we don't mistake a partially
// materialized dynamic/reusable matrix for a skipped one.
const unexpandedSkip = matchingJobs.length === 1 &&
matchingJobs[0].name === spec.prefix &&
!matchingJobs[0].name.includes(' (') &&
matchingJobs[0].status === 'completed' &&
matchingJobs[0].conclusion === 'skipped';
if (unexpandedSkip) {