diff --git a/.github/workflows/unit-selection-evidence.yml b/.github/workflows/unit-selection-evidence.yml index 4ff46be84d0..0385da6c02e 100644 --- a/.github/workflows/unit-selection-evidence.yml +++ b/.github/workflows/unit-selection-evidence.yml @@ -22,16 +22,22 @@ jobs: sparse-checkout: config/scripts/ci-unit-selection-review.mjs sparse-checkout-cone-mode: false persist-credentials: false - - uses: actions/setup-node@v6 - with: - node-version: '24' - uses: actions/download-artifact@v8 with: pattern: unit-shard-node-*-attempt-${{ github.run_attempt }} path: unit-evidence/ - name: Compare selection with full results continue-on-error: true - run: node config/scripts/ci-unit-selection-review.mjs unit-evidence + uses: actions/github-script@v8 + with: + github-token: unused + script: | + const env = { ...process.env } + delete env['INPUT_GITHUB-TOKEN'] + await exec.exec(process.execPath, [ + 'config/scripts/ci-unit-selection-review.mjs', + 'unit-evidence' + ], { env }) - uses: actions/upload-artifact@v7 if: always() continue-on-error: true diff --git a/config/scripts/pr-workflow-parallelism.test.mjs b/config/scripts/pr-workflow-parallelism.test.mjs index 71a36b8c5e4..8d82ceb9364 100644 --- a/config/scripts/pr-workflow-parallelism.test.mjs +++ b/config/scripts/pr-workflow-parallelism.test.mjs @@ -5,6 +5,9 @@ import { describe, expect, it } from 'vitest' const workflow = parse(readFileSync('.github/workflows/pr.yml', 'utf8')) const unitTestWorkflow = parse(readFileSync('.github/workflows/unit-tests.yml', 'utf8')) +const evidenceWorkflow = parse( + readFileSync('.github/workflows/unit-selection-evidence.yml', 'utf8') +) describe('PR workflow parallelism', () => { it('enforces import boundaries in the required static-analysis checks', () => { @@ -48,10 +51,30 @@ describe('PR workflow parallelism', () => { } expect(workflow.jobs.verify.needs).not.toContain('unit_selection_evidence') expect(unitTestWorkflow.jobs.selection_evidence).toBeUndefined() - const evidenceWorkflow = parse( - readFileSync('.github/workflows/unit-selection-evidence.yml', 'utf8') - ) const job = evidenceWorkflow.jobs.selection_evidence expect(job['continue-on-error']).toBe(true) }) + + it('runs the advisory CLI without an action credential and preserves failures', async () => { + const steps = evidenceWorkflow.jobs.selection_evidence.steps + expect(steps.some((step) => step.uses?.startsWith('actions/setup-node@'))).toBe(false) + const comparison = steps.find((step) => step.name === 'Compare selection with full results') + expect(comparison.uses).toBe('actions/github-script@v8') + expect(comparison.with['github-token']).toBe('unused') + const env = { 'INPUT_GITHUB-TOKEN': 'test-token', GITHUB_STEP_SUMMARY: '/tmp/summary' } + const failure = new Error('comparison failed') + const result = runInNewContext(`(async () => { ${comparison.with.script} })()`, { + process: { env, execPath: '/bundled/node24' }, + exec: { + exec: async (command, args, options) => { + expect(command).toBe('/bundled/node24') + expect(args).toEqual(['config/scripts/ci-unit-selection-review.mjs', 'unit-evidence']) + expect(options.env).toEqual({ GITHUB_STEP_SUMMARY: '/tmp/summary' }) + throw failure + } + } + }) + await expect(result).rejects.toBe(failure) + expect(env['INPUT_GITHUB-TOKEN']).toBe('test-token') + }) })