Skip to content

chore(scripts): type-check the deploy + secret-rotation tier via @ts-check#378

Merged
isuttell merged 1 commit into
mainfrom
chore/scripts-tscheck
Jun 5, 2026
Merged

chore(scripts): type-check the deploy + secret-rotation tier via @ts-check#378
isuttell merged 1 commit into
mainfrom
chore/scripts-tscheck

Conversation

@isuttell

@isuttell isuttell commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

What

Type-checks the scripts/ decision-logic tier without converting .mjs to .ts (no transpile in the deploy hot path). Adds // @ts-check + a relaxed tsconfig.scripts.json over the deploy orchestrators and the pure scripts/lib/ modules, wired as pnpm typecheck:scripts into pnpm verify — and therefore into CI Validate.

This is the typing follow-up to the scripts coverage work (#373). Same scoping principle: gate the decision-logic tier, leave the integration scripts out.

Scope (11 files)

tsconfig.scripts.json lists exactly the files that opt in with // @ts-check:

  • scripts/deploy.mjs, scripts/deploy-pr-preview.mjs
  • the 9 pure scripts/lib/ modules (rotation profiles/audit/engine, secret routing/values, env loaders, hyperdrive guard, wrangler env vars)

Posture is deliberately relaxed vs tsconfig.base.json (noImplicitAny off, strict off) so un-annotated params don't force a .ts conversion. The goal is catching real bugs, not 100% annotation.

Two real type smells found + fixed (deploy.mjs, JSDoc-only, no runtime change)

checkJs immediately earned its keep on the production deploy path:

  1. buildProvisionPlan monkey-patched a .missingProvider array onto a Map instance, then read it back in reportMissingProviderSecrets. Works at runtime, but untyped. Now declared via @type {Map<string, string[]> & { missingProvider?: string[] }}.
  2. fail() calls process.exit(1) but wasn't typed as never, so the target union guard didn't narrow and the createSecretPlanner({ target }) call was a type error. Annotated @returns {never}.

Why smoke/integration scripts are out of scope

They read await res.json() (typed unknown) throughout — ~120 errors that are all false positives on the same tier already excluded from unit coverage in vitest.scripts.config.ts. Forcing them to zero would mean casting every HTTP-response read across files we run via pnpm smoke:*, not pnpm test. To bring a file under the gate later: add // @ts-check, list it in tsconfig.scripts.json, make pnpm typecheck:scripts pass.

Verification

  • pnpm typecheck:scripts → exit 0.
  • Gate bites: injecting mkdirSync(12345, { recursive: "yes" }) into an in-scope file produces TS2769 No overload matches this call; file restores clean.
  • pnpm test:scripts → 168 tests pass (deploy + rotation covered).
  • biome / knip / dupes / format:docs:check all clean on the touched files.

Policy documented in scripts/README.md ("Typing policy").

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Documentation

    • Updated quality command documentation with new type-checking command for scripts.
    • Added typing policy section describing type-checking approach for development scripts.
  • Chores

    • Enabled TypeScript type-checking for scripts directory with dedicated configuration.
    • Added type-checking directives across deployment and utility scripts.
    • Enhanced infrastructure for audit logging and secret value resolution in deployment workflows.

@coderabbitai

coderabbitai Bot commented Jun 5, 2026

Copy link
Copy Markdown

Wondering what really moved? Review this PR in Change Stack to inspect semantic changes, definitions, and references.

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 43ee9d6d-b26e-4338-800f-6ef812919da2

📥 Commits

Reviewing files that changed from the base of the PR and between 0c9242b and 52b5b6a.

📒 Files selected for processing (15)
  • README.md
  • package.json
  • scripts/README.md
  • scripts/deploy-pr-preview.mjs
  • scripts/deploy.mjs
  • scripts/lib/hyperdrive-branch-guard.mjs
  • scripts/lib/load-env-files.mjs
  • scripts/lib/local-env-secrets.mjs
  • scripts/lib/rotation-audit.mjs
  • scripts/lib/rotation-profiles.mjs
  • scripts/lib/secret-routing.mjs
  • scripts/lib/secret-values.mjs
  • scripts/lib/versioned-secret-rotation.mjs
  • scripts/lib/wrangler-env-vars.mjs
  • tsconfig.scripts.json

Walkthrough

This PR establishes TypeScript type-checking infrastructure for the scripts/ directory while keeping scripts as plain ESM (.mjs files). A new tsconfig.scripts.json is introduced with relaxed settings for decision-logic script validation using // @ts-check and JSDoc annotations. The `typecheck:scripts` npm script is added to `package.json` and integrated into the `verify` workflow. Existing scripts are annotated with `// `@ts-check directives and type hints. Two new modules—secret-values.mjs and rotation-audit.mjs—are added with type-checking enabled. Documentation is updated to explain the typing policy and exclusion criteria.

Possibly related PRs

  • zaks-io/insecur#3: Establishes pnpm verify as the standard verification gate that this PR now extends with typecheck:scripts.
  • zaks-io/agent-paste#141: Modifies the same README.md "Quality" checklist and package.json verify script in overlapping CI verification flow.
  • zaks-io/agent-paste#332: Refactors the deploy secret-planning logic in scripts/deploy.mjs that this PR now annotates with JSDoc type information.

Comment @coderabbitai help to get the list of available commands and usage tips.

…check

Type-check the scripts/ decision-logic tier without converting .mjs to .ts
(no transpile in the deploy hot path). Adds `// @ts-check` + a relaxed
tsconfig.scripts.json (noImplicitAny off) over the deploy orchestrators and
the pure scripts/lib/ modules, wired as `pnpm typecheck:scripts` into
`pnpm verify` (and so into CI Validate).

checkJs surfaced two real type smells in deploy.mjs, fixed in JSDoc with no
runtime change:
  - buildProvisionPlan monkey-patched a `.missingProvider` array onto a Map;
    now declared via @type so the reader is type-safe.
  - fail() is annotated @returns {never} so the target-union guard narrows.

Smoke/integration scripts are out of scope on purpose: they read
`await res.json()` (typed unknown) throughout — all false positives on the
same tier already excluded from unit coverage. Adding a file to the gate
means giving it `// @ts-check` and listing it in tsconfig.scripts.json.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@isuttell isuttell merged commit 51cbc9f into main Jun 5, 2026
9 of 10 checks passed
@isuttell isuttell deleted the chore/scripts-tscheck branch June 5, 2026 22:01
@github-actions

github-actions Bot commented Jun 5, 2026

Copy link
Copy Markdown

agent-paste PR preview resources were cleaned up. The shared Preview GitHub Environment is retained for future preview deploys.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant