Skip to content

Cache Twoslash results across documentation builds#949

Open
dahlia wants to merge 1 commit into
fedify-dev:mainfrom
dahlia:docs/cache-twoslash
Open

Cache Twoslash results across documentation builds#949
dahlia wants to merge 1 commit into
fedify-dev:mainfrom
dahlia:docs/cache-twoslash

Conversation

@dahlia

@dahlia dahlia commented Jul 18, 2026

Copy link
Copy Markdown
Member

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:build unusually 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-twoslash to 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:build took 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.

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
@dahlia dahlia added this to the Fedify 2.4 milestone Jul 18, 2026
@dahlia dahlia self-assigned this Jul 18, 2026
@dahlia
dahlia requested review from 2chanhaeng and sij411 as code owners July 18, 2026 10:29
@dahlia dahlia added the component/ci CI/CD workflows and GitHub Actions label Jul 18, 2026
@netlify

netlify Bot commented Jul 18, 2026

Copy link
Copy Markdown

Deploy Preview for fedify-json-schema canceled.

Name Link
🔨 Latest commit 467941e
🔍 Latest deploy log https://app.netlify.com/projects/fedify-json-schema/deploys/6a5b5590d3ad8b0008e51320

@coderabbitai

coderabbitai Bot commented Jul 18, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 728b1803-9084-408f-b85e-370c534ecf49

📥 Commits

Reviewing files that changed from the base of the PR and between 2d46cdb and 467941e.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (5)
  • .github/actions/cache-docs/action.yaml
  • .github/workflows/main.yaml
  • docs/.vitepress/config.mts
  • docs/.vitepress/twoslash-cache.mts
  • docs/package.json

📝 Walkthrough

Walkthrough

Documentation 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.

Changes

Documentation cache integration

Layer / File(s) Summary
Twoslash cache engine
docs/package.json, docs/.vitepress/twoslash-cache.mts
Updates VitePress-related dependencies and adds namespace generation, deterministic entry keys, filesystem persistence, and obsolete-cache pruning.
VitePress cache integration
docs/.vitepress/config.mts
Supplies the new filesystem-backed cache to the Twoslash transformer.
CI cache restore and save
.github/actions/cache-docs/action.yaml, .github/workflows/main.yaml
Adds cache key generation and invokes the shared cache action before PR and publish documentation builds.

Estimated code review effort: 4 (Complex) | ~45 minutes

Suggested labels: component/build

Suggested reviewers: 2chanhaeng, sij411

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
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: caching Twoslash results across documentation builds.
Description check ✅ Passed The description directly matches the PR by explaining the Twoslash cache, GitHub Actions cache, and dependency updates.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

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

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread .github/actions/cache-docs/action.yaml
Comment thread docs/.vitepress/twoslash-cache.mts
Comment thread docs/.vitepress/twoslash-cache.mts
@codecov

codecov Bot commented Jul 18, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ All tests successful. No failed tests found.
see 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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

Labels

component/ci CI/CD workflows and GitHub Actions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant