fix(ci): typecheck the celilo hook scripts, and fix the 18 errors behind it #54
No reviewers
Labels
No labels
area/auth
area/backend
area/ci
area/deploy
area/e2e
area/frontend
area/shared
blocked
good-first-issue
needs-info
priority/high
priority/low
priority/medium
type/bug
type/chore
type/docs
type/feature
type/tech-debt
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
celilo/lunacycle!54
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "typecheck-celilo-scripts"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #52. Done in the order agreed: fix the errors, then add the tsconfig, then wire it into the gate.
celilo/scripts/had notsconfig.jsonand was in none of the four projectsbun run typecheckcompiles. The code that runs against the fleet during install, health check, backup and restore had never been throughtsc.bun testruns it, but bun strips types without checking them, so a greentest:hooksproved nothing about types.The three that were real
These are live code, not test scaffolding, and they're the point of the issue.
1 & 2 — two
Browsertypes (health-check.ts:410,smoke-handler.ts:100). Root cause was a version skew, not a cast:celilo/scriptspinnedplaywright-coreat~1.55.1while the root pinned~1.60.0.scripts/smoke/spa-smoke.tstypes itsbrowserparameter against the root copy; the hook launched one from its own bundled copy. TwoBrowsers, one call, and 1.60 addedbind/unbind.Fixed by aligning the pin to
~1.60.0rather than by loosening a type. Nothing chose 1.55.1 deliberately — it's the version root was on when the pin was written. Aligning also puts the production smoke check on the same playwright the e2e suite validates against, which it should have been all along.Note this ships a runtime dependency change.
celilo/scripts/node_modulesis bundled into the.netapp, so merging this eventually puts playwright-core 1.60.0 on the fleet — andauto_upgradeis on for lunacycle with a 15m poll, so CD will take it. The health-check hook is what launches that browser, so a bad bump shows up as a failed deploy rather than silent drift.3 —
Fetchervstypeof fetch(health-check.ts:459).ApiSmokeOptions.fetchImplwas typedtypeof fetch, which carriespreconnect. The injectable fetchers the seam exists for — celilo'sFetcher, test doubles — are plain functions without it. So the health-check hook could not pass its own injected fetch into its own smoke helper: a DI seam that rejected the thing it was built to accept. Now typed as the call signaturerunApiSmokeactually uses.The fifteen that were drift
Spies that had stopped matching the interfaces they name:
FsOpsgainedwriteFile,LunacycleHealthCheckDepsandLunacycleSetupWebDepsgainedsecrets,IdpCapabilitygainedlist_tokens/revoke_token.Was anything silently passing? No — and I checked rather than assumed. Each hook genuinely never calls the missing member, so the tests were testing what they claimed; they just no longer described the type. Rather than take that on faith I stubbed
FsOps.writeFileon the backup/restore spies and the two idp methods to throw instead of no-op. All 62 hook tests still pass, which is now evidence rather than an assertion.The
secretsdrift did surface something real, though it's a coverage hole rather than a false pass: every call site inhealth-check.test.tspassessecrets: {}, so every test takes the!botPasswordskip branch and the entire mint-token → SPA/API/WS smoke path has no unit coverage at all. Out of scope here, filed as #53 with the seams that make it testable.The tsconfig
Inlines celilo's
modules/tsconfig.scripts.base.json— a standalone module repo cannot extend a file that lives inside the celilo checkout. Two deliberate choices carried over or added:pathsfor@celilo/capabilities(celilo's own comment explains why): the hooks must resolve it from this directory'spackage.json, exactly as they do on the fleet. Mapping it elsewhere would typecheck against code the module never runs.typeRoots, not fromcelilo/scripts/package.json. That directory'snode_modulesis bundled into the.netappand shipped to the fleet, where nothing ever runstsc—@types/*there would be dead weight on every deploy.The gate
typechecknow ends intypecheck:hooks, which installscelilo/scripts' deps before runningtsc -p celilo/scripts, mirroring whattest:hooksalready does. That makes it work on a fresh checkout regardless of where it sits inpr-validate's step order, so no workflow reordering was needed — verified by deletingcelilo/scripts/node_modulesand running it cold.Proved it fails. Appended
const x: number = "not a number";tohealth-check.ts:bun run typecheckexits 2 and names the file and line. Removed it: exits 0. (Checked the exit code, not just the printed output — a gate that prints errors and exits 0 is not a gate.)Gates
lint— exit 0typecheck— exit 0, now including 16 hook files that had never been compiledtest:unit— 117 pass, 0 fail, 3 todotest:hooks— 62 pass, 0 failtest:seed— 1 pass, 0 failUpstream
The scaffolder gap behind this is filed as celilo#881 —
scaffold_moduleemits noscripts/tsconfig.json, so every operator-owned module starts un-typecheckable and celilo only warns about it.🤖 Generated with Claude Code