fix(release): bind controller continuation to the plan coverage policy (#137109)

The FRV controller validated the normal CI child's dispatch scope without the
sealed plan's coverage policy, so every npm-stable-v1 plan (CI_RELEASE_SCOPE:
npm-stable since #136790) was rejected with "release normal CI dispatch scope
differs from its coverage policy" and `pnpm frv continue --failed` could not
recover a flaky child. Pass plan.coveragePolicy like the workflow-side summary
already does.

Owner: scripts/frv.mjs (same-parent recovery preflight).
Proof: new frv.test.ts case fails before the fix and passes after; 45/45
controller tests pass; observed on Full Release Validation 33722524584.
This commit is contained in:
Peter Steinberger 2026-09-03 00:07:42 -07:00 • committed by GitHub
parent db6dc60d45
commit 6beb5db9e0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 20 additions and 1 deletions

View file

@ -353,6 +353,7 @@ export async function preflightContinuation(
validateReleaseChildDispatchBinding({
child,
log: parentLog,
coveragePolicy: plan.coveragePolicy,
plannedRunAttempt: child.runAttempt,
repository,
targetSha: plan.targetSha,

View file

@ -224,7 +224,7 @@ function rootRun(
function preflightMethods(
children: ReturnType<typeof child>[],
childRun: (entry: ReturnType<typeof child>) => Record<string, unknown>,
options: { failFast?: boolean; childRunIdOverride?: string } = {},
options: { failFast?: boolean; childRunIdOverride?: string; ciReleaseScope?: string } = {},
) {
const byRunId = new Map(children.map((entry) => [entry.runId, entry]));
const parentJobs = [
@ -257,6 +257,9 @@ function preflightMethods(
return [
`TARGET_SHA: ${TARGET_SHA}`,
...(entry.key === "productPerformance" ? ["-f publish_reports=false"] : []),
...(entry.key === "normalCi" && options.ciReleaseScope
? [`CI_RELEASE_SCOPE: ${options.ciReleaseScope}`]
: []),
`Dispatched ${entry.workflow}: https://github.com/${REPOSITORY}/actions/runs/${runId} (attempt 1)`,
].join("\n");
},
@ -591,6 +594,21 @@ describe("FRV continuation preflight", () => {
}),
).rejects.toThrow("release child is not uniquely emitted by its parent job");
});
it("binds the normal CI dispatch scope to the plan's coverage policy", async () => {
const selected = child("normalCi", "101");
const stablePlan = { ...plan([selected]), coveragePolicy: "npm-stable-v1" };
const methods = (scope: string) =>
preflightMethods([selected], (entry) => runFor(entry, 1, "failure"), {
ciReleaseScope: scope,
});
await expect(
preflightContinuation(stablePlan, "77", methods("npm-stable")),
).resolves.toBeDefined();
await expect(preflightContinuation(stablePlan, "77", methods("full"))).rejects.toThrow(
"release normal CI dispatch scope differs from its coverage policy",
);
});
});
describe("FRV same-parent recovery", () => {