ci(lint): nx cache + affected, plus the escape-hatch ratchet#2661
ci(lint): nx cache + affected, plus the escape-hatch ratchet#2661jordan-simonovski wants to merge 13 commits into
Conversation
The lint CI job rebuilt and re-linted every package from scratch on each run with no cross-run caching, taking 3-4 minutes. Make the ci:build and ci:lint targets nx-cacheable and wire ci:lint's dependsOn to ^ci:build in nx.json, so a downstream project's tsc/lint is correctly invalidated when an upstream package such as common-utils changes (no false cache hits). Track root tsconfig.base.json via sharedGlobals, and declare the common-utils build output so it can be replayed from cache. In the workflow, persist .nx/cache via actions/cache, checkout with full history, run nx affected -t ci:lint against the PR base on pull_request, and keep a full nx run-many on push. make ci-lint / make ci-build are unchanged and still work locally.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
🔴 Tier 4 — CriticalTouches auth, data models, config, tasks, OTel pipeline, ClickHouse, or CI/CD. Why this tier:
Review process: Deep review from a domain expert. Synchronous walkthrough may be required. Stats
|
|
Placeholder |
Greptile SummaryThis PR makes two complementary CI improvements: nx computation caching (with
Confidence Score: 5/5Safe to merge — changes are confined to CI infrastructure with no impact on application code or data. All changes are CI tooling: nx cache configuration, a new escape-hatch ratchet script, and workflow restructuring. The nx input/output wiring is correct (named inputs are properly defined, No files require special attention. The only items flagged are a now-unneeded Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Push / PR event] --> B{event type?}
B -- pull_request --> C["nx affected -t ci:lint\n--base=origin/BASE_REF"]
B -- push to main/v1 --> D["nx run-many -t ci:lint"]
C --> E[Escape-hatch ratchet\nnode scripts/ci/ratchet.mjs]
D --> E
E --> F{any count > baseline?}
F -- yes --> G[exit 1 — CI fails]
F -- no --> H{any count < baseline?}
H -- yes --> I[warn + exit 0\nrun yarn ratchet:update]
H -- no --> J[ratchet ok — exit 0]
subgraph nx cache
C
D
K[ci:build dependsOn upstream\nserved from .nx/cache on hit]
end
C -. dependsOn .-> K
D -. dependsOn .-> K
Reviews (11): Last reviewed commit: "Merge branch 'main' into jordansimonovsk..." | Re-trigger Greptile |
E2E Test Results✅ All tests passed • 240 passed • 1 skipped • 1049s
Tests ran across 4 shards in parallel. |
Adds scripts/ci/ratchet.mjs, which counts tracked escape hatches (as any, @ts-ignore, eslint-disable) per package and compares them against a committed baseline. Counts above baseline fail CI (a new occurrence was added); counts below baseline also fail, prompting the contributor to run yarn ratchet:update so the improvement is locked in. This two-way-strict behaviour keeps the baseline honest and stops the escape-hatch count from silently creeping up. The check is wired into the ci-lint Makefile target so the existing lint CI job enforces it, and yarn ratchet / yarn ratchet:update scripts are exposed for local use.
Deep ReviewScope: CI lint pipeline — Environment caveat: ✅ No critical issues found. 🟡 P2 — recommended
🔵 P3 nitpicks (2)
Reviewers (6): correctness, reliability, security, maintainability, testing, project-standards. Testing gaps: |
…-nx-cache-affected # Conflicts: # nx.json
Merging main raised the tracked escape-hatch counts above the frozen baseline (notably common-utils as-any 69->116), all from code that landed on main independently of this PR. Regenerate the baseline with `yarn ratchet:update` to lock in current counts, which also captures the reductions in app and cli.
Two related lint-pipeline changes, combined into one PR so the CI lint job stays coherent (they'd otherwise conflict at merge and the ratchet could be silently dropped).
What changed
ci:lint/ci:buildare now cacheable innx.json; thelintjob persists.nx/cache, runsnx affected -t ci:linton PRs (only changed projects) and the fullnx run-manyon push. Locally, a warmci:lintdrops from ~41s to ~0.4s.scripts/ci/ratchet.mjscountsas any/@ts-ignore/eslint-disableper package against a committed baseline; above-baseline fails CI, below-baseline warns (non-fatal). Exposed asyarn ratchet/yarn ratchet:update.node scripts/ci/ratchet.mjs), unconditionally — because the lint job now callsnxdirectly rather thanmake ci-lint, and the ratchet is a whole-repo check that must not be gated bynx affected.Key decisions
ci:lint's inputs include^production, so editingpackages/common-utilsinvalidatespackages/app's cached lint (app'stsctypechecks against it). Verified. The root.prettierrc/.prettierignoreare insharedGlobalsso a root Prettier change busts every project's cached lint too.mainor block other PRs when two count-lowering PRs merge close together. Above-baseline still hard-fails — that's the gate that matters.Impact
affectedon PRs, fullrun-manyon push (nothing skipped on trunk).make ci-lint/make ci-buildunchanged for local use.Implementation detail
ci:lintdependsOn: ["^ci:build"]so upstream builds run first; nx hashes inputs internally, so a restored cache only replays on an input-hash match. Cache keynx-${{ runner.os }}-${{ github.sha }}+ prefix restore.grepexit-2 on a missing/renamed package dir is guarded withexistsSync(returns 0, no crash). Verified: above-baseline exits 1, below-baseline warns + exits 0, at-baseline "ok".