diff --git a/.github/actions/check-stage-health/action.yml b/.github/actions/check-stage-health/action.yml index 290d3c73e..af5dc376d 100644 --- a/.github/actions/check-stage-health/action.yml +++ b/.github/actions/check-stage-health/action.yml @@ -77,9 +77,13 @@ runs: const rootCauseFailures = jobs.filter(j => { if (j.status !== 'completed' || j.conclusion !== 'failure') return false; // h20 runners are flaky (dirty GPU state from prior runs); their failures - // should not cascade fast-fail to other stages. Exact match avoids - // accidentally matching the h200 job names. - if (j.name === 'stage-c-test-8-gpu-h20') { + // should not cascade fast-fail to other stages. j.name shape from + // listJobsForWorkflowRun: "" + optional " / " + // + optional " ()". Split off the base job key before exact + // match so we cover both inline + reusable forms without confusing + // 'h20' with the 'h200' prefix. + const baseName = j.name.split(/[ /]/)[0]; + if (baseName === 'stage-c-test-8-gpu-h20') { return false; } // If the failing step is the health check, it's a cascade — skip it diff --git a/.github/actions/wait-for-jobs/action.yml b/.github/actions/wait-for-jobs/action.yml index c3200853a..240deb0c4 100644 --- a/.github/actions/wait-for-jobs/action.yml +++ b/.github/actions/wait-for-jobs/action.yml @@ -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 ` ()`; reusable-workflow callers produce + // ` / ()`. 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: `` + // - reusable workflow: ` / ` + // 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) {