Skip to content

Commit 04eac90

Browse files
Merge pull request #7465 from Shopify/solid-knip
Check JSON response for knip to avoid false positives
2 parents bafe6e4 + 365f6ee commit 04eac90

2 files changed

Lines changed: 42 additions & 1 deletion

File tree

.github/workflows/tests-pr.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ jobs:
8787
with:
8888
node-version: ${{ env.DEFAULT_NODE_VERSION }}
8989
- name: Run knip
90-
run: pnpm knip
90+
run: node bin/run-knip-ci.js
9191

9292
graphql-schema:
9393
# Skip on dependabot PRs (no access to required secrets) and on PRs opened

bin/run-knip-ci.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import {spawnSync} from 'node:child_process'
2+
3+
// Run knip with the JSON reporter so a successful run still emits structured
4+
// output (e.g. {"files":[],"issues":[]}). An empty stdout therefore indicates
5+
// knip did not actually analyze the codebase — a silent-pass mode previously
6+
// observed — and must be treated as a failure to avoid false-green builds.
7+
const knip = spawnSync('pnpm', ['--silent', 'knip', '--reporter', 'json'], {
8+
encoding: 'utf8',
9+
})
10+
11+
if (knip.error) {
12+
console.error(`::error::failed to spawn knip: ${knip.error.message}`)
13+
process.exit(1)
14+
}
15+
16+
let report
17+
try {
18+
report = JSON.parse(knip.stdout)
19+
} catch {
20+
console.error(
21+
`::error::knip exited ${knip.status} but produced no parseable JSON output. Failing CI to avoid a false green.`,
22+
)
23+
console.error('Raw stdout:')
24+
console.error(knip.stdout)
25+
console.error('Raw stderr:')
26+
console.error(knip.stderr)
27+
process.exit(1)
28+
}
29+
30+
if (!Array.isArray(report.files) || !Array.isArray(report.issues)) {
31+
console.error('::error::knip output had unexpected shape')
32+
console.error(JSON.stringify(report))
33+
process.exit(1)
34+
}
35+
36+
if (knip.status !== 0) {
37+
// Findings: re-run with the default reporter so the log is human-readable.
38+
spawnSync('pnpm', ['knip'], {stdio: 'inherit'})
39+
}
40+
41+
process.exit(knip.status ?? 1)

0 commit comments

Comments
 (0)