Skip to content

Commit 7119b3e

Browse files
authored
fix: validation-issue-read-v1471 (#759)
1 parent da5dbec commit 7119b3e

11 files changed

Lines changed: 147 additions & 21 deletions

‎.github/workflows/ci.yml‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,9 @@ jobs:
183183
type-check:
184184
name: Type-Check
185185
if: vars.CI_BILLING_PAUSED != 'true'
186+
permissions:
187+
contents: read
188+
issues: read
186189
runs-on: ${{ inputs.runner }}
187190
timeout-minutes: 30
188191
steps:
@@ -226,6 +229,8 @@ jobs:
226229
- name: Type-Check
227230
id: execute
228231
if: steps.applicability.outputs.applicable == 'true' && steps.applicability.outputs.affected != 'false'
232+
env:
233+
GH_TOKEN: ${{ github.token }}
229234
run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" ci type_check
230235
- name: Retain task receipt
231236
if: >-

‎.github/workflows/validation-billing.yml‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,9 @@ jobs:
533533
type-check:
534534
name: Type-Check
535535
if: vars.CI_BILLING_PAUSED != 'true'
536+
permissions:
537+
contents: read
538+
issues: read
536539
runs-on: ${{ inputs.ci-runner }}
537540
timeout-minutes: 30
538541
steps:
@@ -576,6 +579,8 @@ jobs:
576579
- name: Type-Check
577580
id: execute
578581
if: steps.applicability.outputs.applicable == 'true' && steps.applicability.outputs.affected != 'false'
582+
env:
583+
GH_TOKEN: ${{ github.token }}
579584
run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" ci type_check
580585
- name: Retain task receipt
581586
if: >-

‎.github/workflows/validation-no-codeql.yml‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,12 @@ jobs:
104104
ci:
105105
name: CI
106106
if: vars.CI_BILLING_PAUSED != 'true' && (inputs.mode == 'fast' || inputs.mode == 'audit' || inputs.mode == 'release')
107+
# Forward issue-read only to the CI workflow that runs Type-Check.
108+
permissions:
109+
actions: read
110+
contents: read
111+
issues: read
112+
packages: read
107113
uses: ./.github/workflows/ci.yml
108114
with:
109115
runtime-repository: ${{ inputs.runtime-repository }}

‎.github/workflows/validation.yml‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,12 @@ jobs:
104104
ci:
105105
name: CI
106106
if: vars.CI_BILLING_PAUSED != 'true' && (inputs.mode == 'fast' || inputs.mode == 'audit' || inputs.mode == 'release')
107+
# Type-Check reads the issue-backed requirements ledger with github.token.
108+
permissions:
109+
actions: read
110+
contents: read
111+
issues: read
112+
packages: read
107113
uses: ./.github/workflows/ci.yml
108114
with:
109115
runtime-repository: ${{ inputs.runtime-repository }}

‎.github/workflows/validation_audit_self-ci.yml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ jobs:
2222
permissions:
2323
actions: read
2424
contents: read
25+
issues: read
2526
packages: read
2627
security-events: write
2728
uses: 0xPlayerOne/code-foundry/.github/workflows/validation.yml@main

‎.github/workflows/validation_self-ci.yml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ jobs:
7878
permissions:
7979
actions: read
8080
contents: read
81+
issues: read
8182
packages: read
8283
security-events: write
8384
uses: ./.github/workflows/validation.yml

‎src/lib/consumer-qualification.mjs‎

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -166,12 +166,7 @@ function lintContracts(consumer, candidate, destination, actionlint, version) {
166166
// keywords (adea's desktop-shell, for one) stay covered without list
167167
// maintenance. Restore the removal of this exclusion when
168168
// rhysd/actionlint releases post-parallel support.
169-
const pendingParallelSyntax = /(?:^|\n)\s*(?:background|wait|wait-all|cancel|parallel):/m
170-
const workflows = readdirSync(join(destination, '.github/workflows')).filter((name) => {
171-
if (!/\.ya?ml$/.test(name)) return false
172-
const text = readFileSync(join(destination, '.github/workflows', name), 'utf8')
173-
return !pendingParallelSyntax.test(text)
174-
})
169+
const workflows = actionlintEligibleWorkflows(join(destination, '.github/workflows'))
175170
run(
176171
actionlint,
177172
[
@@ -184,6 +179,15 @@ function lintContracts(consumer, candidate, destination, actionlint, version) {
184179
return paths.length
185180
}
186181

182+
/** @param {string} workflowsDirectory */
183+
export function actionlintEligibleWorkflows(workflowsDirectory) {
184+
const pendingParallelSyntax = /^[ \t]*(?:-[ \t]+)?(?:background|wait|wait-all|cancel|parallel):/m
185+
return readdirSync(workflowsDirectory).filter((name) => {
186+
if (!/\.ya?ml$/.test(name)) return false
187+
return !pendingParallelSyntax.test(readFileSync(join(workflowsDirectory, name), 'utf8'))
188+
})
189+
}
190+
187191
/** @param {{ packageFile: string, sourceSha: string, reportPath: string, actionlint?: string }} options */
188192
export function qualifyCandidate(options) {
189193
if (!/^[a-f0-9]{40}$/.test(options.sourceSha))

‎src/lib/merge-queue.mjs‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ on:
110110
permissions:
111111
actions: read
112112
contents: read
113+
issues: read
113114
packages: read
114115
security-events: write
115116

‎src/templates/workflows/validation-audit.yml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ jobs:
2222
permissions:
2323
actions: read
2424
contents: read
25+
issues: read
2526
packages: read
2627
security-events: write
2728
uses: ./.github/workflows/validation.yml

‎test/consumer-qualification.test.mjs‎

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import assert from 'node:assert/strict'
22
import test from 'node:test'
3-
import { mkdtempSync, readFileSync, writeFileSync, rmSync, symlinkSync } from 'node:fs'
3+
import { mkdirSync, mkdtempSync, writeFileSync, rmSync, symlinkSync } from 'node:fs'
44
import { tmpdir } from 'node:os'
55
import { join } from 'node:path'
66
import {
7+
actionlintEligibleWorkflows,
78
digest,
89
FIXTURES,
910
localizeCalls,
@@ -67,19 +68,32 @@ test('candidate source identity is mandatory before any install', () => {
6768
)
6869
})
6970

70-
test('the actionlint pass excludes pending parallel syntax by content, not by filename', () => {
71-
// actionlint v1.7.12 predates the step-parallelism keywords; the
72-
// qualification skips any workflow whose text uses them so
73-
// repository-owned adopters (adea's desktop-shell) stay covered without
74-
// list maintenance.
75-
const source = readFileSync(join(process.cwd(), 'src/lib/consumer-qualification.mjs'), 'utf8')
76-
const line = source
77-
.split('\n')
78-
.find((candidate) => candidate.includes('const pendingParallelSyntax ='))
79-
assert.ok(line, 'the qualification declares the pending-syntax pattern')
80-
for (const keyword of ['background', 'wait', 'wait-all', 'cancel', 'parallel']) {
81-
assert.ok(line.includes(keyword), `the pattern covers ${keyword}`)
71+
test('the actionlint pass filters pending parallel syntax by content, not filename', (t) => {
72+
const workflows = join(temporary(t), '.github', 'workflows')
73+
mkdirSync(workflows, { recursive: true })
74+
const keywords = ['background', 'wait', 'wait-all', 'cancel', 'parallel']
75+
for (const keyword of keywords) {
76+
writeFileSync(
77+
join(workflows, `pending-sequence-${keyword}.yml`),
78+
`jobs:\n check:\n steps:\n - ${keyword}:\n run: echo pending\n`
79+
)
80+
writeFileSync(
81+
join(workflows, `pending-mapping-${keyword}.yaml`),
82+
`workflow:\n ${keyword}:\n enabled: true\n`
83+
)
8284
}
83-
assert.ok(!source.includes("new Set(['validation-billing.yml'])"), 'the filename list is gone')
84-
assert.match(source, /pendingParallelSyntax\.test\(text\)/, 'files are filtered by content')
85+
writeFileSync(
86+
join(workflows, 'validation-billing.yml'),
87+
'jobs:\n check:\n steps:\n - run: echo parallel\n'
88+
)
89+
writeFileSync(
90+
join(workflows, 'validation.yml'),
91+
'jobs:\n check:\n steps:\n - run: echo ok\n'
92+
)
93+
writeFileSync(join(workflows, 'README.md'), 'parallel:\n')
94+
95+
assert.deepEqual(actionlintEligibleWorkflows(workflows).toSorted(), [
96+
'validation-billing.yml',
97+
'validation.yml',
98+
])
8599
})

0 commit comments

Comments
 (0)