ADR-0061: Regenerate rendered docs on main in CI, not in the pre-commit hook
| State | Accepted |
| Architectural Significance | LOW |
| Domain | Data Platform |
| Document version | 0.1 |
Reference
Amends ADR-0059 (public documentation rendering pipeline: self-hosted rustdoc
into docs/site/api/ and mdBook into docs/site/reference/, regenerated locally
and committed). Interacts with ADR-0052 (Cloudflare Pages serves docs/site/
verbatim via Git integration, build command NONE) — unchanged by this ADR.
Context
ADR-0059 has the .githooks/pre-commit hook regenerate the rendered surfaces —
docs/site/api/ (rustdoc, ~705 files) and docs/site/reference/ (mdBook, ~63
files) — and commit them in the same commit as the source change, so
Cloudflare (which serves the tree verbatim) is always current.
That made every branch mutate ~768 generated files. Two branches that each touch
a crate or a doc regenerate overlapping subsets, so they conflict on merge —
and did: a routine feature PR hit 74 generated-file conflicts (api/*,
reference/searchindex.js), dwarfing the 13 real code conflicts. The generated
tree is a pure function of the source; a hand-resolved merge of it carries no
information and is pure toil (and risks a corrupt, half-merged rendered page).
Decision
Stop regenerating the rendered surfaces in the pre-commit hook. Regenerate them
once, on main, in CI after each merge, and commit them back.
- The
.githooks/pre-commithook keeps the graphify map sync (small, canonical) but no longer runsgen-api-docs.sh/gen-reference-book.sh. Branches therefore never mutatedocs/site/apiordocs/site/reference, so PRs cannot conflict on them. - A new workflow
.github/workflows/docs-regen.yml(pushtomain, guarded to the paths that affect the rendered output) runs the same two scripts whole-workspace, refreshes the hand-authoredindex.htmlcounts thatcheck-docs-sync.shgates, and commits the result back tomainwith a[skip ci]message (so the bot commit does not re-trigger the workflow). Aconcurrencygroup serialises regens. - The files stay tracked and Cloudflare’s Git-integration deploy (ADR-0052) is
unchanged — it still serves the committed
docs/site/verbatim; only the writer moved from every developer’s commit to one post-merge CI job.
Options considered + consequences
Option 1 (chosen) — Regenerate on main in CI, keep the files tracked
- Pros: eliminates the entire class of generated-doc merge conflict with no
change to the Cloudflare deploy model or any new secret; the rendered site stays
in the repo (diffable, servable verbatim);
index.htmlcounts self-heal so a PR that adds a crate/ADR no longer has to hand-edit them. - Cons: the ~768 files remain in the repo (history churn moves to a post-merge
bot commit); the deployed site is briefly stale between a merge and the regen
job finishing; the bot needs permission to push to
main. - Cost: one CI job per docs-affecting merge (~a couple of minutes).
Option 2 — Untrack the generated trees; build + deploy from CI via Wrangler
- Pros: the generated artifacts leave the repo entirely (no churn, no tracked build output).
- Cons: replaces ADR-0052’s Cloudflare Git-integration with a Wrangler
direct-upload deploy, needs a
CLOUDFLARE_API_TOKENsecret, and is a larger change to a working deploy path. - Recommendation: rejected for now as disproportionate; revisit if the tracked generated tree becomes a repo-size problem. Recorded so the trade-off is explicit.
Option 3 — Do nothing; keep resolving the conflicts by hand
- Rejected: the conflicts are pure toil on a generated artifact and recur on every docs-touching PR.
Operational note
The regen job pushes to main, so it authenticates as a dedicated GitHub App
(Contents:write, installed on this repo) rather than the default GITHUB_TOKEN:
the job mints a short-lived installation token with actions/create-github-app-token
and pushes as the App’s bot identity. That bot must be added to main’s ruleset /
branch-protection bypass list, or the push to the protected branch is rejected.
Secrets required: DOCS_APP_ID, DOCS_APP_PRIVATE_KEY. If the bypass is ever
withdrawn, switch the final step to open a PR instead of pushing directly.
Document version history
| Version | Date | Notes |
|---|---|---|
| 0.1 | 2026-08-05 | Initial draft alongside the pipeline change; amends ADR-0059. |