Skip to content

Run lint and compile once and share one dependency cache - #1495

Merged
cristianrgreco merged 5 commits into
mainfrom
claude/lint-whole-repo
Oct 12, 2026
Merged

cristianrgreco merged 5 commits into
mainfrom
claude/lint-whole-repo

Conversation

@cristianrgreco

@cristianrgreco cristianrgreco commented Oct 10, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Three changes to the Checks workflow, one commit each:

  1. One Lint job for the whole repository, replacing the per-module matrix. lint:ci is now biome ci --error-on-warnings ..
  2. One Compile job for the whole repository, replacing the per-module matrix. It runs npm run check-compiles (tsc -b packages/testcontainers packages/modules/*).
  3. One shared dependency cache. npm-setup always runs npm ci for every workspace, with one cache key per runner OS and architecture, Node version and lockfile (npm-v3-<os>-<arch>-node-<version>-<lockfile hash>). Its only input is now node-version: the workspace and runner inputs and the workspace_path output are gone, and test-template.yml works out the path of the package under test itself.

After this, every job that installs dependencies (Lint, Compile, the smoke tests and the test jobs) restores the same cache.

Lint has no if, so it runs on every change the workflow covers. Compile is still skipped when no package changed. Smoke tests and tests are still gated by which packages changed.

Why

Lint and Compile. Biome checks all 456 files in about a second, and a clean whole-repository build takes about 1.7s locally. On a recent all-green run of Checks:

Jobs Runner time
Lint 44 1171s
Compile 44 415s

Nearly all of that was runner start-up and per-module installs, and every Compile job rebuilt testcontainers before checking its own module.

Cache.

Per-package caches (now) Shared cache (this PR)
Entries 97 2 (Node 22.x and 24.x)
Storage 6.4 GB about 0.9 GB
Size restored per job 56 MB median, 344 MB largest 445 MB

The repository is over GitHub's 10 GB Actions cache limit (10.8 GB), so caches are being evicted and jobs fall back to npm ci. On that same run, the install step in the 176 test jobs took 7s at the median and up to 32s.

What doesn't change

  • Type errors caught. Compile checks the same 44 projects as before, test files included, each from its tsconfig.json. It doesn't catch more than before either: no module depends on another module, and a change to testcontainers or a shared file already recompiled every package.
  • Lint findings. noFloatingPromises is type-aware, so I checked whether it needs each module's dependencies installed. It doesn't: with a probe file in a module, Biome reports an unawaited local async function and an unawaited GenericContainer.start(), and doesn't report an unawaited pg or node:timers/promises call. The result is the same with pg, @types/pg or @types/node removed from node_modules.

Trade-offs

  • About 4s more per job on a cache hit. Restoring the shared cache took 11s on CI, against the 7s median today. Across 176 test jobs that's roughly 12 more runner-minutes per full run, on top of about 190.
  • Test jobs no longer run with only their own module's dependencies installed. That isolation could catch a module importing a package that only another module declares. Biome's noUndeclaredDependencies rule now reports undeclared imports statically.
  • The smoke tests' prune step sees more installed packages. npm prune --omit=dev --workspace packages/testcontainers removes the same 11 packages after either install (336 to 325 with a testcontainers-only install, 1126 to 1115 with a full one). The one case that's weaker: a package testcontainers needs at runtime but lists only as a dev dependency now goes unnoticed if any module also depends on it, where before only the root counted. The step never gave a production-only environment: vitest, TypeScript and Biome stay installed after it either way.
  • First run after a lockfile change: the jobs for a Node version all miss at once and each runs npm ci (35s on CI) until one saves the cache. Today every job also misses on a lockfile change, since each per-package key includes the lockfile hash.

Verification

  • npm run lint:ci: passes on the whole repository. With a file containing an unawaited local promise added under a module, it exits 1.
  • npm run check-compiles from a clean state: passes. With a test file containing a type error added under a module, it exits 2 and reports TS2322 for that file.
  • The smoke tests' prune step was run locally after both kinds of install, with the results above.
  • action.yml, checks.yml and test-template.yml parse. npm run format: no fixes applied.
  • CI: an earlier revision of the same three changes passed Checks in full: Lint, the single Compile job, the three smoke-test jobs and all 176 test jobs, using the shared cache and the new test-path expression.

Why this isn't breaking

CI-only. No package source, dependency or published file changes.

The check names change from Lint (<module>) and Compile (<module>) to Lint and Compile. main has no branch protection or required status checks, so nothing needs updating.

@cristianrgreco cristianrgreco added maintenance Improvements that do not change functionality patch Backward compatible bug fix labels Oct 10, 2026
@cristianrgreco
cristianrgreco added this pull request to stack #1498 October 10, 2026 20:35
Comment thread .github/workflows/checks.yml Outdated
Replace the per-module lint matrix with one job that runs Biome over the
whole repository.
Replace the per-module compile matrix with one job that runs
`npm run check-compiles`, a project-references build of every package.
npm-setup installs every workspace when it isn't given one.
Make npm-setup always install every workspace, so every job restores the
same cache per Node version instead of one per package. The test jobs
resolve the path of the package under test themselves.
@cristianrgreco
cristianrgreco removed this pull request from stack #1498 October 11, 2026 18:15
@cristianrgreco
cristianrgreco changed the base branch from claude/knip-5dccc1 to main October 11, 2026 18:15
@cristianrgreco
cristianrgreco added this pull request to stack #1501 October 11, 2026 18:15
@cristianrgreco
cristianrgreco removed this pull request from stack #1501 October 11, 2026 18:26
@cristianrgreco cristianrgreco changed the title Run lint once for the whole repository Run lint and compile once and share one dependency cache Oct 11, 2026
There is only one kind of install now, so the key no longer needs a
segment to tell them apart.
Use the built-in runner context instead of a `runner` input, so callers
only pass the Node version.
@cristianrgreco
cristianrgreco marked this pull request as ready for review October 12, 2026 12:35
@cristianrgreco
cristianrgreco merged commit 4a81ef0 into main Oct 12, 2026
191 checks passed
@cristianrgreco
cristianrgreco deleted the claude/lint-whole-repo branch October 12, 2026 12:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

maintenance Improvements that do not change functionality patch Backward compatible bug fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant