Skip to content

docs(ci): mermaid renders broken (Playwright missing) + missing Astro build cache #132

Description

@EricAndrechek

Two related issues with the docs site build under CI, surfaced while
investigating CI speed in #129. Filing together because they share
context (Astro/Starlight + ARC runner pods) and a future implementer
will likely want to address them in the same PR.

Context for a fresh implementer

WaveHouse's docs site lives under docs/ and is built with
Astro 6 + Starlight 0.38. The make build-docs target runs
pnpm --dir docs build which invokes astro build. CI runs this as
part of make ci on every PR and every push to main.

Astro's build is a pipeline: it walks the content collection under
docs/src/content/docs/, runs each Markdown / MDX file through a chain
of remark/rehype plugins, and emits static HTML+assets to docs/dist/.
The plugin chain is configured in docs/astro.config.mjs:

rehypePlugins: [[rehypeMermaid, { strategy: \"inline-svg\" }], rehypeKatex]

The runner pods are self-hosted ARC pods labelled `[wave-rf-runners]`,
built from a custom image. Pods are ephemeral — anything not in the
image or restored from cache must be installed by the workflow itself
on each run. The relevant CI config is:

  • `.github/workflows/ci.yml` — main pipeline (one job: `make ci`)
  • `.github/actions/setup-env/action.yml` — composite restoring the
    three caches (Go module+build, golangci-lint, pnpm store)

Cache traffic routes to an on-prem
`falcondev-oss/github-actions-cache-server` over LAN — fast, but
"cached" means "explicitly added to one of those cache entries."
Nothing else persists between runs.


Issue 1: rehype-mermaid silently fails — Playwright Chromium missing

Symptom

Mermaid code fences in any `.md` / `.mdx` file under `docs/src/content/docs/`
do not render to SVG diagrams in the built site. The published
docs at `https://wavehouse.dev\` show mermaid blocks as raw code blocks
(or empty, depending on how the fallback behaves), not as the
rendered diagrams the author wrote.

CI does not catch this. The docs build step finishes successfully and
the rest of the pipeline is green. The failure is invisible without
inspecting the build log or comparing the published site to the
source.

Evidence (from CI log, run 25811690215 step "Run CI pipeline")

```
browserType.launch: Executable doesn't exist at
/home/runner/.cache/ms-playwright/chromium_headless_shell-1223/
chrome-headless-shell-linux64/chrome-headless-shell
╔═══════════════════════════════════════════════════════════╗
║ Looks like Playwright Test or Playwright was just installed║
║ or updated. Please run the following command to download ║
║ new browsers: ║
║ ║
║ pnpm exec playwright install ║
║ ║
╚═══════════════════════════════════════════════════════════╝
at getBrowser (/home/runner/_work/WaveHouse/WaveHouse/docs/
node_modules/.pnpm/mermaid-isomorphic@3.1.0_playwright@1.60.0/
node_modules/mermaid-isomorphic/dist/mermaid-isomorphic.js:93:39)
```

Why it's silent

`rehype-mermaid` delegates to `mermaid-isomorphic`, which launches
a headless Chromium via `@playwright/test` to render each mermaid
diagram to SVG at build time. The Playwright library is in
`node_modules` (pulled via the docs lockfile), but the browser
binaries
are downloaded separately to `~/.cache/ms-playwright/`
by `playwright install`. That install step is never run in our
CI today, so the browser binary is missing.

When the browser launch fails, `rehype-mermaid` swallows the error
per-block and leaves the mermaid source untransformed. Astro's build
continues, the rest of the content is fine, and the build exits 0 — so
CI reports green. The mermaid block reaches the published HTML
unrendered.

Where to look

  • `docs/astro.config.mjs` — `rehypePlugins` line configures
    rehype-mermaid with `strategy: "inline-svg"`.
  • `docs/package.json` — `playwright` is a devDependency
    (`^1.59.1`); `rehype-mermaid` (`^3.0.0`) is a runtime dep.
  • Any `.md` / `.mdx` file under `docs/src/content/docs/` with a
    ````mermaid```` fenced block — those are the affected source files.
  • `Makefile` target `build-docs` (line ~378) — runs
    `cd docs && pnpm build`.

How to reproduce locally

  1. `cd docs && pnpm install --frozen-lockfile`
  2. Skip `pnpm exec playwright install` so you're in the same
    broken state as CI.
  3. `pnpm build`
  4. Open any `docs/dist/**/index.html` that contained a mermaid block.
    The block is missing or rendered as text.

After fix: the same HTML page should contain an inline `` for
each mermaid diagram.

What a fix should achieve

  • mermaid blocks render to inline SVG in the built site
  • Whatever browser-install step is added does not re-download
    Chromium on every CI run (browsers are ~150 MB; cold-pull every PR
    would add 30-60s per run)
  • The CI step is reproducible locally — a contributor running
    `make build-docs` after a clean checkout should produce a working
    build the same way CI does (this is the "Local-First Validation"
    principle from AGENTS.md)
  • If a future code change accidentally breaks the rendering pipeline
    again, the failure should be loud (i.e., consider whether CI should
    grep the built HTML for stranded mermaid source, or run the docs
    build with a fail-on-warn flag if Astro/rehype-mermaid offers one)

I'm explicitly not prescribing a solution here — there are several
reasonable shapes (install browsers in the runner image, install +
cache via the workflow, swap to a strategy that doesn't need a browser,
etc.). Implementer's call.


Issue 2: docs build has no incremental cache in CI

Context

Astro 4+ writes a content-collection cache to a project-local cache
directory between builds. On a warm cache, content that hasn't
changed since the last build is reused (parsed AST, frontmatter,
generated routes) instead of being re-processed. Cold builds redo
everything.

Our CI runs `astro build` from scratch on every PR push. The cache
directory isn't restored or saved by `.github/actions/setup-env`,
so every docs build is effectively cold. For a docs-heavy PR this
is fine; for the typical PR (no docs changes), the entire docs
content-pipeline is re-executed unnecessarily.

Where caching is configured today

`.github/actions/setup-env/action.yml` restores three caches:
Go module+build, golangci-lint, pnpm store. The pnpm store cache
covers npm packages but not Astro's intermediate build state —
those live outside the pnpm store, inside the project tree (or
inside `node_modules` but in dirs pnpm install doesn't manage).

Saves are gated in `.github/workflows/ci.yml` on cache-hit !=
'true' so a same-key re-push is a no-op.

What a fix should achieve

  • A warm docs build (no source file changes vs. cache key) takes
    measurably less wall time than today
  • Cache key invalidates on changes that should require a from-
    scratch rebuild (Astro version, plugin config, etc.) — a stale
    cache producing wrong output is worse than no cache
  • Cache size stays bounded (don't accumulate stale content
    indefinitely)
  • The change should compose cleanly with the pnpm-store cache fix
    in ci: kill coverage Docker pull on PR runs + tighten claude-review group #129 — the resolved store path lives on a different mount than
    the project tree, so don't accidentally re-introduce the
    "path-doesn't-exist" silent-fail pattern that bug had

Implementer should verify the actual cache location Astro/Starlight
uses (it can vary by version and by content-layer mode) before
choosing what to cache.


Related

Activity

  1. added
    bugSomething isn't working
    area/docsDocumentation, site/, README
    area/infraCI, build, deploy, Docker, release
    on May 13, 2026
  2. coderabbitai commented on May 13, 2026

    @coderabbitai
    🔗 Related PRs

    Wave-RF/custom-images#5 - fix(runner): rebase on falcondev fork to fix self-hosted cache routing [closed]


    📝 Issue Planner

    Check the box below or use the @coderabbitai plan command to generate an implementation plan and prompts that you can use with your favorite coding assistant.

    • Create Plan

    🧪 Issue enrichment is currently in open beta.

    You can configure auto-planning by selecting labels in the issue_enrichment configuration.

    To disable automatic issue enrichment, add the following to your .coderabbit.yaml:

    issue_enrichment:
      auto_enrich:
        enabled: false

    💬 Have feedback or questions? Drop into our discord!

  3. moved this from Backlog to In progress in WaveHouse Task Boardon May 19, 2026
  4. added a commit that references this issue on May 19, 2026
    559bfb3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area/docsDocumentation, site/, READMEarea/infraCI, build, deploy, Docker, releasebugSomething isn't working

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions