Skip to content

Commit 34db85d

Browse files
jak-glitchclaude
andcommitted
ci: wire the coco-dev-versions and import-specifiers drift checks into CI (#9649)
Two checks in package.json's `test:ci` had no GitHub Actions job running them, so the two could silently diverge with zero CI signal: - `coco-dev-versions:check` keeps k8s/coco-dev/versions.json and the KBS kustomization in lockstep; its only test exercises the pure core against fabricated inputs and never reads the two real files. - `import-specifiers:check` (#9221) scans src/scripts/test and every packages/* workspace; #9240 and #9249 are two separate drifts that landed after it shipped, precisely because nothing enforced it in CI. - ci.yml: the `changes` job gains a `cocoDev` path filter (k8s/coco-dev/**, scripts/check-coco-dev-versions*.ts) and two named validate-code steps -- `coco-dev-versions:check` gated on cocoDev + the push clause, and `import-specifiers:check` gated on push || backend || mcp || engine || miner || discoveryIndex (every filter covering a scanned root). - check-import-specifiers-script.test.ts: a real-tree regression test that calls findImportSpecifierViolations() with no injected fs and asserts [], matching the real-tree guards on validate-no-hand-written-js and coverage-bolt-on-filenames -- the enforcement path that was missing. actionlint and lint:composite-actions pass on the edited workflow. Closes #9649 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent a013ff5 commit 34db85d

2 files changed

Lines changed: 24 additions & 0 deletions

File tree

.github/workflows/ci.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ jobs:
3838
outputs:
3939
backend: ${{ steps.filter.outputs.backend }}
4040
backendConfig: ${{ steps.filter.outputs.backendConfig }}
41+
cocoDev: ${{ steps.filter.outputs.cocoDev }}
4142
ui: ${{ steps.filter.outputs.ui }}
4243
uiContract: ${{ steps.filter.outputs.uiContract }}
4344
mcp: ${{ steps.filter.outputs.mcp }}
@@ -160,6 +161,11 @@ jobs:
160161
observability:
161162
- 'grafana/dashboards/**'
162163
- 'prometheus/rules/**'
164+
# #9649: the coco-dev version manifest and the KBS kustomization that must stay in lockstep, plus the
165+
# checker itself. Nothing else in the workflow references k8s/, so this is its own narrow filter.
166+
cocoDev:
167+
- 'k8s/coco-dev/**'
168+
- 'scripts/check-coco-dev-versions*.ts'
163169
# The UI's own app code -- triggers the FULL toolchain (lint/typecheck/test/build).
164170
# A dependency bump (package.json/package-lock.json) stays here too since it can break the UI
165171
# build or types in ways only that full toolchain would catch.
@@ -406,6 +412,18 @@ jobs:
406412
- name: Re-gate sort-key check
407413
if: ${{ github.event_name == 'push' || needs.changes.outputs.backend == 'true' }}
408414
run: npm run regate-sort-key:check
415+
# #9649: coco-dev-versions:check keeps k8s/coco-dev/versions.json and the KBS kustomization in lockstep, but
416+
# was wired into test:ci only -- no CI job ran it, and nothing in this workflow references k8s otherwise.
417+
# Gated on the new cocoDev path filter plus the standard push clause every drift step above uses.
418+
- name: Coco-dev versions drift check
419+
if: ${{ github.event_name == 'push' || needs.changes.outputs.cocoDev == 'true' }}
420+
run: npm run coco-dev-versions:check
421+
# #9649: import-specifiers:check (#9221) scans import specifiers across src/scripts/test and every
422+
# packages/* workspace (BUNDLER_ROOTS/NODENEXT_ROOTS), but no CI job ran it -- #9240/#9249 both drifted in
423+
# after it shipped. Gate on every filter covering one of those scanned roots.
424+
- name: Import-specifiers drift check
425+
if: ${{ github.event_name == 'push' || needs.changes.outputs.backend == 'true' || needs.changes.outputs.mcp == 'true' || needs.changes.outputs.engine == 'true' || needs.changes.outputs.miner == 'true' || needs.changes.outputs.discoveryIndex == 'true' }}
426+
run: npm run import-specifiers:check
409427

410428
# #9563: every webhook-owned handler must decide about #9312's redelivery guard out loud. Three had
411429
# silently skipped it -- one writing duplicate permanent suppression rows, two spending a second paid

test/unit/check-import-specifiers-script.test.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,4 +131,10 @@ describe("check-import-specifiers script", () => {
131131
expect(multi.map((v) => v.file)).toEqual(["src/a.ts", "src/z.ts", "src/z.ts"]);
132132
expect(multi.map((v) => v.specifier)).toEqual(["./c.js", "./a.js", "./b.js"]);
133133
});
134+
135+
it("REGRESSION (#9649): the real repo tree has zero import-specifier violations (the guard was wired into test:ci only, so #9240 and #9249 both reached main while it was local-only)", () => {
136+
// No injected listSourceFiles/readFile: runs the real gate against the real src/scripts/test/packages tree,
137+
// matching the real-tree regression guards on validate-no-hand-written-js and coverage-bolt-on-filenames.
138+
expect(findImportSpecifierViolations()).toEqual([]);
139+
});
134140
});

0 commit comments

Comments
 (0)