Cache Twoslash results across documentation builds#949
Conversation
Upgrade VitePress and its Twoslash integration so documentation builds can persist type-checking results between runs. Keep Vue aligned with the new VitePress runtime to avoid mixed-version SSR failures. Key entries by source, language, options, runtime, lockfiles, and generated declarations so stale type information is never reused. Restore the same namespace in trusted documentation CI jobs and discard obsolete cache data. Assisted-by: Codex:gpt-5.6-sol
✅ Deploy Preview for fedify-json-schema canceled.
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: ASSERTIVE Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (5)
📝 WalkthroughWalkthroughDocumentation builds now use a deterministic, namespaced Twoslash filesystem cache. VitePress consumes the cache, while PR and publish workflows restore and save it through a shared GitHub composite action. ChangesDocumentation cache integration
Estimated code review effort: 4 (Complex) | ~45 minutes Suggested labels: Suggested reviewers: Sequence Diagram(s)sequenceDiagram
participant GitHubActions
participant CacheDocsAction
participant VitePressBuild
participant TwoslashCache
GitHubActions->>CacheDocsAction: Compute namespace and docs-tree
CacheDocsAction->>GitHubActions: Restore docs/.vitepress/cache
GitHubActions->>VitePressBuild: Run pnpm run build
VitePressBuild->>TwoslashCache: Read or write Twoslash entries
GitHubActions->>CacheDocsAction: Save docs/.vitepress/cache
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Code Review
This pull request introduces a custom caching mechanism for VitePress and Twoslash builds to optimize documentation generation. It adds a new GitHub Action for caching, implements the cache logic in docs/.vitepress/twoslash-cache.mts, integrates it into the VitePress configuration, and updates related dependencies in docs/package.json. Feedback on these changes highlights three key areas for improvement: resolving a syntax error in the GitHub Action by using npx tsx instead of running the TypeScript file directly with node, defensively checking for the existence of environment files to prevent potential ENOENT crashes during build, and implementing a recursion depth limit along with explicit handling for RegExp and Date objects in the cache key normalization function to prevent stack overflows and cache collisions.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
Codecov Report✅ All modified and coverable lines are covered by tests. 🚀 New features to boost your workflow:
|
Fedify's documentation relies on Twoslash for more than 500 TypeScript examples. It catches broken examples during the build and gives readers type information in the rendered pages, but that benefit has made
mise run docs:buildunusually expensive: depending on the machine, a build can spend around ten minutes repeating type analysis that was already completed in the previous run. Removing Twoslash would shorten the build by giving up a useful documentation check, so the better tradeoff is to stop recomputing unchanged results.The cache introduced in docs/.vitepress/twoslash-cache.mts persists Twoslash results across VitePress processes. A cached result is keyed by the source, language, and normalized Twoslash options rather than by source text alone. The files that define the surrounding type environment, including lockfiles, package manifests, the VitePress configuration, and generated declaration files under packages/, are hashed into a separate namespace. Node.js version, operating system, and architecture are part of that namespace as well. This lets repeated builds reuse work while ensuring that a dependency update, compiler setting, or rebuilt package cannot silently reuse type information from an older environment.
Local persistence does not help GitHub Actions because each runner starts without the previous workspace. The composite action in .github/actions/cache-docs/action.yaml therefore restores docs/.vitepress/cache/ only after mise has installed dependencies and generated package declarations, which are needed to calculate the same namespace used by the build. Its outer Actions cache key contains that namespace and the Git tree for docs/, so a new documentation revision can fall back to results from the same type environment while a runtime or declaration change creates a new immutable cache entry. The action is used only by the trusted documentation jobs in .github/workflows/main.yaml; the manually dispatched fork-preview workflow does not restore or save this cache.
The filesystem cache API is available in the current Twoslash integration, so docs/package.json moves
@shikijs/vitepress-twoslashto 4.3.1. VitePress is updated to 2.0.0-alpha.18 at the same time because that release uses the compatible Shiki 4 toolchain. Vue is aligned with the matching 3.5.40 runtime to prevent the server renderer and Twoslash UI dependencies from resolving different Vue versions during static rendering.On the development machine used for verification, a full cold
mise run docs:buildtook 116.64 seconds and the following warm build took 76.32 seconds, a reduction of about 35%. The command still rebuilds the workspace packages and performs the rest of the VitePress pipeline, so the exact saving will vary, but the warm build reused all 539 persisted Twoslash entries without rewriting them.