fix: pre-landing review fixes (PR reuse runs main's checkout; sizing experiments are never evidence; a re-run never reuses)

Review-Finding: p1/specialist-batched#1 reader=security
Review-Finding: p1/red-team#1 reader=red-team
Review-Finding: p1/red-team#2 reader=red-team
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
This commit is contained in:
garrytanandcapy-ai[bot] committed 2026-11-03 07:50:52 +00:00
1 parent 560c7c9810
commit 284bd9123d
6 files changed
+45 -17

No files matched your search

+5 -4
View File
@@ -1,8 +1,8 @@
/**
* CI reuse wiring (GSTA-156 P3b) for free-tests.yml and windows-free-tests.yml. Pins the properties that make reuse
* safe: nothing a pull request controls certifies it (a push to main consumes; free-tests.yml's pull_request runs consume
* only through find --pull-request, whose sources and guarded files test/ci-tree-reuse.test.ts pins; dispatch runs never
* consume), the reuse job alone reads Actions with a job-level actions: read,
* only through find --pull-request run from main's checkout, whose sources and guarded files test/ci-tree-reuse.test.ts
* pins; a sizing-experiment dispatch records sizing_experiment and is never evidence; dispatch runs never consume), the reuse job alone reads Actions with a job-level actions: read,
* a skipped or failed reuse job runs every job exactly as before (GitHub skips a job whose needed job was skipped
* unless its condition uses a status function, so every dependent condition starts with !cancelled()), the
* aggregate's reuse branch runs before any download and the strict path is otherwise unchanged, tested-tree is
@@ -52,8 +52,9 @@ for (const [file, spec] of Object.entries(FILES)) {
expect(source).not.toContain('pull_request_target');
const find = jobs.reuse.steps.find((s: any) => s.id === 'find');
expect(find.env).toEqual({ GH_TOKEN: '${{ github.token }}' });
expect(find.run).toBe(`bun run scripts/ci-tree-reuse.ts find --workflow ${file} --profile ${spec.profile}${spec.pullRequest ? ' --pull-request' : ''}`);
expect(find.run).toBe(spec.pullRequest ? `bun --no-env-file --config=/dev/null run scripts/ci-tree-reuse.ts find --workflow ${file} --profile ${spec.profile} --pull-request` : `bun run scripts/ci-tree-reuse.ts find --workflow ${file} --profile ${spec.profile}`);
expect(jobs.reuse.steps[0].with['persist-credentials']).toBe(false);
if (spec.pullRequest) expect(jobs.reuse.steps[0].with.ref).toBe('${{ github.event.pull_request.base.sha || github.sha }}');
expect(Object.keys(jobs.reuse.outputs).sort()).toEqual(['reused', 'run_id', 'run_url', 'tree']);
});
@@ -100,7 +101,7 @@ for (const [file, spec] of Object.entries(FILES)) {
expect(steps.length).toBe(upload + 1);
expect(steps[upload].uses).toStartWith('actions/upload-artifact@');
expect(steps[upload].with['if-no-files-found']).toBe('error');
expect(steps[record].env).toEqual({ PR_HEAD_SHA: '${{ github.event.pull_request.head.sha }}' });
expect(steps[record].env).toEqual({ PR_HEAD_SHA: '${{ github.event.pull_request.head.sha }}', ...(spec.pullRequest ? { SIZING_OVERRIDE: '${{ inputs.free_runner }}${{ inputs.free_shards }}${{ inputs.free_jobs }}' } : {}) });
expect(steps[1].run).toMatch(/set -eu\n(test "\$[A-Z_]+_RESULT" = success\n)+$/);
});
+13 -2
View File
@@ -126,7 +126,7 @@ describe('findPrReuse: a pull request reuses only a run it cannot control', () =
const SELF = 999;
const GUARDED = ['.github/workflows/free-tests.yml', 'scripts/ci-tree-reuse.ts', 'lib/run-evidence.ts'];
interface PrFake { id: number; event: string; branch: string; head: string; conclusion?: string | null; status?: string; started?: string; record?: Partial<TreeRecord> }
interface PrWorld { runs: PrFake[]; trees: Record<string, string>; blobs: Record<string, string>; parents: string[]; headRepo: string }
interface PrWorld { runs: PrFake[]; trees: Record<string, string>; blobs: Record<string, string>; parents: string[]; headRepo: string; attempt?: number }
const blobs = (over: Record<string, string> = {}) => ({ ...Object.fromEntries(GUARDED.flatMap(p => [[`${MERGE}:${p}`, `blob-${p}`], [`${BASE}:${p}`, `blob-${p}`]])), ...over });
const prWorld = (over: Partial<PrWorld> = {}): PrWorld => ({
runs: [{ id: 500, event: 'push', branch: 'main', head: MAIN_HEAD }, { id: SELF, event: 'pull_request', branch: 'feat', head: HEAD, status: 'in_progress', conclusion: null, started: '2026-10-30T11:30:00Z' }],
@@ -148,7 +148,7 @@ describe('findPrReuse: a pull request reuses only a run it cannot control', () =
};
}
const pr = (w: PrWorld) => findPrReuse(prDeps(w), { repo: REPO, base: 'main', workflow: 'free-tests.yml', profileName: 'ci-reuse/free-tests', profile: PROFILE, now: NOW,
pr: { number: 42, mergeSha: MERGE, headSha: HEAD, headRef: 'feat', headRepo: w.headRepo, baseRef: 'main', runId: SELF } });
pr: { number: 42, mergeSha: MERGE, headSha: HEAD, headRef: 'feat', headRepo: w.headRepo, baseRef: 'main', runId: SELF, runAttempt: w.attempt ?? 1 } });
const prWhy = (w: PrWorld) => { const v = pr(w); return v.reused ? 'reused' : v.reason; };
test('a green push run on main at the merge commit\'s exact tree is reused', () => {
@@ -186,6 +186,15 @@ describe('findPrReuse: a pull request reuses only a run it cannot control', () =
expect(prWhy(prWorld({ headRepo: 'someone/gstack' }))).toBe('fork_head');
});
test('a runner-sizing experiment dispatch is never a source (red team p1 #1)', () => {
const v = pr(prWorld({ runs: [{ id: 506, event: 'workflow_dispatch', branch: 'feat', head: HEAD, record: { sizing_experiment: true } }] }));
expect(v).toMatchObject({ reused: false, reason: 'no_verified_run', detail: expect.stringContaining('reason=sizing_experiment') });
});
test('a re-run attempt of the pull request run never reuses, so its own red earlier attempt stays visible (red team p1 #2)', () => {
expect(prWhy(prWorld({ attempt: 2, runs: [{ id: 501, event: 'workflow_dispatch', branch: 'feat', head: HEAD }] }))).toBe('rerun');
});
test('a merge commit that is not base plus this head, or an unreadable one, is refused', () => {
expect(prWhy(prWorld({ parents: [BASE, '6'.repeat(40)] }))).toBe('merge_mismatch');
expect(prWhy(prWorld({ parents: [BASE] }))).toBe('merge_mismatch');
@@ -200,6 +209,8 @@ describe('treeRecord: the tested-tree producer', () => {
expect(treeRecord(env(), { plan, results, os: ['Linux', 'macOS', 'Windows'], tree: TREE })).toEqual({ run_id: 300, run_attempt: 2, event: 'workflow_dispatch', sha: HEAD, head_sha: HEAD, tree: TREE, workflow: '.github/workflows/free-tests.yml', os: ['Linux', 'macOS', 'Windows'], files: ['test/a.test.ts', 'test/b.test.ts', 'test/c.test.ts'], tests: 12 });
expect(treeRecord(env({ GITHUB_EVENT_NAME: 'pull_request', GITHUB_SHA: MERGE, PR_HEAD_SHA: HEAD }), { plan, results, os: ['Windows'], tree: TREE })).toMatchObject({ event: 'pull_request', sha: MERGE, head_sha: HEAD });
expect(treeRecord(env(), { plan, results: [{ outcome: {} }], os: ['Linux'], tree: TREE }).tests).toBe(3);
expect(treeRecord(env({ SIZING_OVERRIDE: '1' }), { plan, results, os: ['Linux'], tree: TREE })).toMatchObject({ sizing_experiment: true });
expect(treeRecord(env({ SIZING_OVERRIDE: '' }), { plan, results, os: ['Linux'], tree: TREE })).not.toHaveProperty('sizing_experiment');
});
test('missing or malformed inputs throw, so the aggregate fails instead of uploading a record', () => {
expect(() => treeRecord(env({ GITHUB_EVENT_NAME: 'pull_request', GITHUB_SHA: MERGE }), { plan, results, os: ['Linux'], tree: TREE })).toThrow(/PR_HEAD_SHA/);