Skip to content

Commit 58e76ed

Browse files
committed
test(e2e): allow matrix node-version expression in CI hardening check
The supply-chain hardening test required actions/setup-node's node-version to be the literal '22', which blocked broadening test coverage via a Node version matrix. Relax to also accept \${{ matrix.<key> }} when that matrix key resolves to an array that includes '22', so the Node 22 baseline is still enforced while additional versions can be added alongside.
1 parent d7da4d3 commit 58e76ed

1 file changed

Lines changed: 23 additions & 3 deletions

File tree

e2e/tests/supply-chain.e2e.test.ts

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,13 @@ describe('supply chain — pnpm-lock.yaml integrity', () => {
8686

8787
describe('supply chain — CI hardening (.github/workflows/tests.yml)', () => {
8888
const workflow = readYaml('.github/workflows/tests.yml') as {
89-
jobs: Record<string, { steps: Array<{ run?: string; uses?: string; with?: Record<string, unknown> }> }>
89+
jobs: Record<
90+
string,
91+
{
92+
strategy?: { matrix?: Record<string, unknown> }
93+
steps: Array<{ run?: string; uses?: string; with?: Record<string, unknown> }>
94+
}
95+
>
9096
}
9197

9298
it('every `pnpm install` invocation uses --frozen-lockfile', () => {
@@ -104,7 +110,7 @@ describe('supply chain — CI hardening (.github/workflows/tests.yml)', () => {
104110
}
105111
})
106112

107-
it('every pnpm-using job runs on Node 22', () => {
113+
it('every pnpm-using job runs on Node 22 (literal or matrix incl. 22)', () => {
108114
for (const [jobName, job] of Object.entries(workflow.jobs)) {
109115
const usesPnpm = job.steps.some(
110116
(s) =>
@@ -116,7 +122,21 @@ describe('supply chain — CI hardening (.github/workflows/tests.yml)', () => {
116122
(s) => typeof s.uses === 'string' && s.uses.startsWith('actions/setup-node'),
117123
)
118124
expect(setup, `${jobName} uses pnpm but lacks actions/setup-node`).toBeTruthy()
119-
expect(String(setup?.with?.['node-version']), `${jobName} node version`).toBe('22')
125+
const nv = String(setup?.with?.['node-version'])
126+
if (nv === '22') continue
127+
// Allow `${{ matrix.<key> }}` only when that matrix key resolves to
128+
// an array of versions that includes 22 — so the matrix can broaden
129+
// coverage without ever dropping the Node 22 hardening baseline.
130+
const matrixRef = nv.match(/^\$\{\{\s*matrix\.([\w-]+)\s*\}\}$/)
131+
expect(matrixRef, `${jobName} node version: expected '22' or matrix expression, got '${nv}'`).toBeTruthy()
132+
const matrixKey = matrixRef![1]
133+
const versions = job.strategy?.matrix?.[matrixKey]
134+
expect(
135+
Array.isArray(versions),
136+
`${jobName} references matrix.${matrixKey} but no such array on strategy.matrix`,
137+
).toBe(true)
138+
const versionStrings = (versions as unknown[]).map((v) => String(v))
139+
expect(versionStrings, `${jobName} matrix.${matrixKey} must include 22`).toContain('22')
120140
}
121141
})
122142
})

0 commit comments

Comments
 (0)