Add Cloudflare Pages docs preview with /preview-docs slash command
Merged
LO
4mo ago+275+275+012345678901234567890123456789-0-0-0123456789
Summary
Adds per-PR documentation previews on Cloudflare Pages so reviewers can see the rendered mkdocs site before merge.
- Auto-preview: PRs from repo admins that touch
docs/**,docs_src/**,mkdocs.ymlorpyproject.tomlbuild and deploy automatically on open and on every push. - Slash command: on any other PR, an admin or maintainer can comment
/preview-docsto trigger a preview. Anyone else gets a polite rejection. - A sticky PR comment carries the preview URL (updated in place on each rebuild).
- A companion workflow deletes the Cloudflare deployments when the PR closes.
Security
mkdocs executes Python from the PR (mkdocstrings imports src/mcp, !!python/name: directives in mkdocs.yml), so the design treats the build as untrusted code:
- An
authorizejob checks the triggering actor's permission before any PR code is fetched. The auto-path keys onevent.sender.login(the pusher), not the PR opener, so a non-admin pushing to an admin's branch does not get an auto-build. - The
buildjob runs PR code with no secrets and uploads the staticsite/as an artifact. Thedeployjob downloads the artifact and runswrangler pages deploy— PR code never shares a runner with the Cloudflare token. .github/zizmor.ymldocuments and suppresses thedangerous-triggersfinding for these two workflows.
Setup required before this takes effect
- Create a Cloudflare Pages project (Direct Upload), e.g.
mcp-python-sdk-docs. - Repo secrets:
CLOUDFLARE_API_TOKEN(scope: Account → Cloudflare Pages → Edit) andCLOUDFLARE_ACCOUNT_ID. - Repo variable:
CLOUDFLARE_PAGES_PROJECT= the project name from step 1.
pull_request_target runs the base branch's workflow, so this only takes effect once merged to main.
Test plan
-
actionlintclean on both new workflows -
zizmor .github/workflows/exits 0 -
uv sync --frozen --group docs && uv run --frozen --no-sync mkdocs buildproducessite/index.html+site/api/locally - After merge + secrets configured: open a small docs PR as an admin → preview comment appears with a working
pr-<n>.<project>.pages.devlink - Push to that PR → comment updates in place
- Comment
/preview-docsfrom a non-admin account on a fork PR → rejection reply - Comment
/preview-docsfrom an admin → preview appears - Close the PR → Cloudflare deployments for
pr-<n>are deleted