Skip to content

fix(ci): regenerate workspace codegen even when the node_modules cache hits - #9976

Merged
JSONbored merged 1 commit into
mainfrom
fix/ci-cache-hit-skips-postinstall-codegen-9975
Jul 31, 2026
Merged

fix(ci): regenerate workspace codegen even when the node_modules cache hits#9976
JSONbored merged 1 commit into
mainfrom
fix/ci-cache-hit-skips-postinstall-codegen-9975

Conversation

@JSONbored

Copy link
Copy Markdown
Owner

Unblocks main and every open PR

main has been red for four consecutive runs with nothing wrong in the tree, and every PR fails validate-code regardless of what it changes — including a test-only PR (#9972) that touches no UI file at all.

Root cause

setup-workspace restores a node_modules cache and, on a hit, skips npm ci entirely. Skipping npm ci skips every workspace lifecycle script — and apps/loopover-ui has one that matters:

"postinstall": "fumadocs-mdx"

That generates .source/, which is the directory tsconfig.json maps collections/* onto:

"collections/*": ["./.source/*"]

.source/ is gitignored and is not among the cached paths (node_modules, apps/*/node_modules, packages/*/node_modules). So on a cache hit the UI typechecks against modules that do not exist:

src/lib/docs-client-loader.tsx(1,32): error TS2307: Cannot find module 'collections/browser'
src/lib/docs-client-loader.tsx(17,24): error TS7031: Binding element 'MDXContent' implicitly has an 'any' type
src/lib/docs-source.server.ts(1,22): error TS2307: Cannot find module 'collections/server'

Why it started when it did

The cache key includes the lockfile. A lockfile change mints a fresh key: the first run misses, installs, generates .source, passes, and saves the cache. Every run afterwards hits and fails. That is exactly the observed pattern — green through 507960134, red from 40133d789 onward, with no relevant change in between.

This is the same shape as the @eslint/js hoist bug the cache step's own comment already documents:

a failure that reproduces on no developer machine, because a real npm ci always creates those directories

Reproduced, then confirmed fixed

Simulating the cache-hit state locally — node_modules intact, .source removed:

$ rm -rf apps/loopover-ui/.source && npm run ui:typecheck
error TS2307: Cannot find module 'collections/browser'
error TS7031: Binding element 'MDXContent' implicitly has an 'any' type
error TS2307: Cannot find module 'collections/server'

$ npm run postinstall --workspace @loopover/ui && npm run ui:typecheck
ui:typecheck PASSES after codegen

Regenerated, not cached

Adding .source to the cache paths looks like the smaller fix and is the wrong one. The cache key derives from manifests + lockfile, while .source derives from source.config.ts and content/docs/**. A cached copy would serve a docs collection generated from different MDX than the commit under test — a stale pass, which is worse than an honest failure. It is cheap to regenerate, so it is regenerated every run.

The step is deliberately unconditional, with a comment saying so, because the obvious "optimisation" of gating it on the cache miss reintroduces the exact bug.

Verification

  • actionlint and lint:composite-actions green
  • Failure reproduced and fix confirmed locally, as above
  • Only apps/loopover-ui declares a lifecycle script (postinstall/prepare) across all workspaces and the root — checked, so this one step covers the whole tree today

Closes #9975

…e hits

main has been red for four consecutive runs with nothing wrong in the tree, and
every PR fails validate-code regardless of what it changes -- including a
test-only PR touching no UI file.

setup-workspace restores a node_modules cache and, on a hit, skips `npm ci`
entirely. Skipping `npm ci` skips every workspace lifecycle script, and
apps/loopover-ui's `postinstall: fumadocs-mdx` is what generates `.source/` --
the directory tsconfig maps `collections/*` onto. `.source/` is gitignored and
is not among the cached paths, so on a cache hit the UI typechecks against
modules that do not exist:

  src/lib/docs-client-loader.tsx(1,32): error TS2307: Cannot find module 'collections/browser'
  src/lib/docs-source.server.ts(1,22):  error TS2307: Cannot find module 'collections/server'

The cache key includes the lockfile, which is why it started when it did: a
lockfile change mints a fresh key, the first run misses and installs and passes
and saves, and every run after it hits and fails. Green through 5079601, red
from 40133d7 on, with no relevant change between them.

Same shape as the @eslint/js hoist bug the cache step already documents -- it
reproduces on no developer machine, because a real `npm ci` always runs
postinstall. Reproduced by simulating the cache-hit state: removing
apps/loopover-ui/.source with node_modules intact gives exactly those errors,
and running the codegen clears them.

REGENERATED, NOT CACHED. Adding `.source` to the cache paths is the smaller fix
and the wrong one: the key derives from the manifests and lockfile, while
`.source` derives from source.config.ts and content/docs/**. A cached copy would
serve a docs collection generated from different MDX than the commit under test
-- a stale pass, which is worse than an honest failure.

Closes #9975
@loopover-orb

loopover-orb Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Warning

⏸️ LoopOver review result - manual review recommended

Review updated: 2026-07-31 01:05:06 UTC

1 file · 1 AI reviewer · no blockers · CI green · clean

⏸️ Suggested Action - Manual Review

  • Touches a guarded path — held for manual review: This PR changes guardrail-protected path(s): .github/actions/setup-workspace/action.yml (matched .github/actions/**).

Review summary
This adds an unconditional 'Generate workspace codegen' step (npm run postinstall --workspace @​loopover/ui) after the existing conditional npm-ci step, so fumadocs-mdx's postinstall always regenerates .source/ regardless of whether the node_modules cache hit and skipped npm ci. The root-cause trace is correct and verifiable from the surrounding file: the cache paths list only node_modules/apps/*/node_modules/packages/*/node_modules, never .source, and .source is what tsconfig.json's collections/* mapping resolves against, so a cache hit previously left .source stale/missing and broke the UI typecheck exactly as described. The fix deliberately regenerates rather than caches .source (explained in the comment: caching it could serve MDX content generated from a different commit), which is the right layer to fix this at, and CI is green on this exact commit.

Nits — 6 non-blocking
  • On a cache miss, npm ci already runs postinstall via normal lifecycle scripts, so this step re-runs fumadocs-mdx a second time unconditionally — harmless since it's idempotent/cheap, but worth a one-line comment noting the intentional redundancy on the miss path too (only the hit path is explained).
  • If another workspace later gains a postinstall script whose output feeds typecheck, this single hardcoded `--workspace @​loopover/ui` call won't cover it; worth a comment flagging that this list may need to grow.
  • Consider a short comment near the new step clarifying it also re-runs (redundantly but safely) on the npm-ci path, not just the cache-hit path, since 'UNCONDITIONAL' could otherwise read as hit-only.
  • If feasible, add a workflow smoke test that forces a cache hit (e.g., pre-seed the cache key) and asserts ui:typecheck passes, to guard against regressing this exact failure mode in the future.
  • PR author also opened the linked issue — Link an issue that was opened by a different contributor, or provide a rationale for why this self-authored issue represents genuine discovery work.
  • Touches a guarded path — held for manual review — A maintainer must review and merge this change.

Decision drivers

  • ✅ Code review — No blockers (1 reviewer)
  • ⚠️ Gate result — Not blocking (Advisory; not blocking this PR.)
Context & advisory signals — never blocks the verdict
Signal Result Evidence
Linked issue ✅ Linked #9975
Related work ✅ No active overlap found No same-issue or scoped active PR overlap found.
Change scope ✅ 20/20 Low review scope from cached public metadata (1 linked issue).
Validation posture ✅ 25/25 PR body includes validation/test evidence.
Contributor workload ✅ 10/10 Author activity: 9 registered-repo PR(s), 8 merged, 281 issue(s).
Contributor context ✅ Confirmed Gittensor contributor JSONbored; Gittensor profile; 9 PR(s), 281 issue(s).
Improvement ℹ️ Insufficient signal risk: clean · value: insufficient-signal
Linked issue satisfaction

Addressed
The PR adds an unconditional 'Generate workspace codegen' step running `npm run postinstall --workspace @​loopover/ui` after the conditional npm ci, directly fixing the cache-hit skip of postinstall codegen that caused the collections/* typecheck failures.

Review context
  • Author: JSONbored
  • Role context: owner (maintainer lane)
  • Public audience mode: oss maintainer
  • Lane context: Repository is configured for direct PR review.
  • Public profile languages: Python, TypeScript, Ruby, Go, MDX, Shell, Solidity, JavaScript
  • Official Gittensor activity: 9 PR(s), 281 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Start here: Treat this as maintainer-lane context rather than normal contributor-lane activity.
Signal definitions
  • Related work = same linked issue, overlapping active PRs, or title/path similarity.
  • Change scope = cached public metadata such as size labels, draft state, and review-burden hints.
  • Validation posture = whether the PR provides enough public validation/test evidence for maintainer review.
  • Contributor workload = public contributor activity and cleanup pressure, not a repo-wide quality failure.
  • Contributor context = public GitHub/Gittensor identity context; non-Gittensor status is not a blocker.
🧪 Chat with LoopOver

Ask LoopOver a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.

  • @loopover ask <question> answers contribution-quality Q&A with source citations and freshness.
  • @loopover chat <question> answers in natural prose from cached decision-pack facts via local inference (maintainer/collaborator; read-only).
  • A plain-language @loopover mention with a real question is routed to the closest matching read-only command automatically — no exact syntax required.

Full command reference: https://loopover.ai/docs/loopover-commands

🧪 Experimental — new and may change.

Decision record
  • action: hold · clause: guardrail_hold
  • config: 38477a6fae368c6926a5ac4470ec6a94f1988d81621a30ba0ee383db4ec430b4 · pack: oss-anti-slop · ci: passed
  • record: 35d6958bb8494708bc62ab65e97f66b0a0c54561dc7f747c92720383c8e0bae9 (schema v6, head 2ae4413)

🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed


💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →.

Checked by LoopOver, a quiet PR intelligence layer for OSS maintainers.

  • Re-run LoopOver review

@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

@codecov

codecov Bot commented Jul 31, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 91.00%. Comparing base (a790a9e) to head (2ae4413).
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #9976      +/-   ##
==========================================
- Coverage   91.88%   91.00%   -0.88%     
==========================================
  Files         928      928              
  Lines      113722   113722              
  Branches    27436    27436              
==========================================
- Hits       104489   103495     -994     
- Misses       7936     9125    +1189     
+ Partials     1297     1102     -195     
Flag Coverage Δ
backend 94.11% <ø> (-1.56%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.
see 3 files with indirect coverage changes

@loopover-orb loopover-orb Bot added the manual-review Gittensor contributor context label Jul 31, 2026
@JSONbored
JSONbored merged commit 2afecb2 into main Jul 31, 2026
8 checks passed
@JSONbored
JSONbored deleted the fix/ci-cache-hit-skips-postinstall-codegen-9975 branch July 31, 2026 01:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

manual-review Gittensor contributor context

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ci: a node_modules cache hit skips postinstall codegen, so every UI typecheck fails on 'collections/*'

1 participant