ci: deploy the docs (prod and preview) - #255
Conversation
The site had a `wrangler.jsonc` and nothing that ran it. This points it at the domain and puts the deploy in CI. `packages/docs/wrangler.jsonc` gains the account, the apex as a Custom Domain, and `workers_dev`/`preview_urls` off. Every URL the build emits -- canonicals, OG images, robots.txt, the sitemap, the links inside /llms.txt -- names https://capnweb.com, so a second live origin serving those same pages is a duplicate for crawlers and a link people paste by accident. The account ID is an identifier rather than a credential, and committing it is what stops a deploy from an operator who can see several accounts landing in the wrong one. `deploy-docs.yml` runs on push to main. There is no path filter: the site embeds the library's build output and prints its measured size, so almost any commit changes it, and a redeploy that turns out to be a no-op is cheaper than reasoning about which paths do not. Deploying needs the library built before the site -- the playgrounds vendor `dist/index.js` and the prose substitutes the bundle size -- so the entry point is `npm run deploy:docs` at the root, which does both in order. The `deploy`/`predeploy` pair in `packages/docs` is removed rather than fixed: it built the site against whatever the library happened to be last time, which is exactly the trap the root script exists to close. `test.yml` gains a `build-docs` job. Without it the first place the docs build ever runs is the deploy, and a broken site would be found on main instead of on the pull request.
|
|
@dimitropoulos Bonk workflow failed. Check the logs for details. View workflow run · To retry, trigger Bonk again. |
commit: |
There was a problem hiding this comment.
Pull request overview
This PR wires up continuous deployment for the docs site to https://capnweb.com by adding the necessary Wrangler configuration and GitHub Actions workflows, and by centralizing the build/deploy entrypoint at the repo root to ensure the library is built before the docs.
Changes:
- Add Cloudflare Wrangler config to pin the account, bind the apex custom domain, and disable
workers.dev/preview URLs for the docs Worker. - Add a
Deploy Docsworkflow that builds (library → docs) and deploys on every push tomain(plus manual dispatch), using thedocsenvironment secret. - Add a
build-docsCI job (and rootbuild:docs/deploy:docsscripts) so docs build failures are caught on PRs before they can breakmaindeploys.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| packages/docs/wrangler.jsonc | Pins Cloudflare account + custom domain route; disables non-prod hostnames; keeps static assets configuration. |
| packages/docs/README.md | Updates deployment documentation to reflect CI deploy and root-level deploy script. |
| packages/docs/package.json | Removes package-local deploy scripts to avoid docs builds that skip the library build. |
| package.json | Adds root build:docs and deploy:docs scripts to enforce correct build order and standardize deployment. |
| .github/workflows/test.yml | Adds a PR-time docs build/check job to prevent deploying broken docs from main. |
| .github/workflows/deploy-docs.yml | Adds automated deploy-to-Cloudflare workflow for docs on push to main / manual dispatch. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| - uses: actions/checkout@v7 | ||
|
|
Uses Worker Previews: `wrangler preview` against the same `capnweb-docs` Worker, so a preview is a branch of the production Worker rather than a second Worker to operate. Every pull request from a branch in this repo gets `https://pr-<n>-capnweb-docs.<subdomain>.workers.dev`, commented on the PR, updated on every push, deleted when it closes. `preview_urls` goes back to true. It is not the same switch as `workers_dev`, which the comment it replaces had wrong: `workers_dev` is production's workers.dev copy, which we still do not want, while `preview_urls` is what gives a Preview a hostname at all. With it off, `wrangler preview` succeeds and returns a Preview whose `urls` array is empty, which is a deploy nobody can look at. Production stays off workers.dev either way -- verified. Two parts of the workflow are load-bearing and easy to break: The preview URL is derived before the build, not read back after it. `site` is baked into canonicals, OG URLs, robots.txt and the sitemap at build time, so `DOCS_SITE_URL` has to be set before `astro build` or the preview publishes a sitemap claiming to be capnweb.com. A preview URL is `<preview-name>-<worker-name>.<subdomain>.workers.dev` and all three parts are known in advance, so this is possible; the deploy step reads the URL back anyway and fails if it is not the one the site was built for. `X-Robots-Tag: noindex` is appended to the built `_headers` rather than committed to `public/_headers`, which ships to production too. It is a header rather than a robots.txt `Disallow` because disallowing the crawl would stop a crawler ever reading the noindex, which is how staging sites get indexed as bare URLs anyway. Verified that the appended `/*` block does not clobber the `/_astro/*` immutable rule. Fork pull requests get no preview. They have no access to secrets, and `pull_request_target` would hand a contributor's build scripts a credential that can deploy the real site. `build-docs` in test.yml still checks them. Deleting a preview that is not there exits 1, so cleanup treats `code: 10025` as success -- otherwise every PR that closes without one, including every fork PR and everything opened before today, gets a failed check. wrangler 4.63.0 -> 4.125.0, because `wrangler preview` is a private beta command that does not exist in 4.63.0. That drags `@cloudflare/workers-types` from v4 to v5 as a peer. Both are devDependencies and neither changes the published types; 611 tests pass on the node and workerd projects, and `test:types` is clean. `@cloudflare/vitest-pool-workers` deliberately stays at 0.12.10: 0.22 wants vitest ^4, and a test-framework major is not a Workers dependency bump. Also drops the Cap'n Crunch reference from the wordmark comment.
Each page's "Updated" date comes from `git log -1 --format=%at <file>`. In the default shallow checkout that resolves to the single fetched commit, so every page claims the same timestamp and this job checks a build that is not the one main deploys -- 1787410005 against the real 1787403343 for start/quickstart. Caught by Copilot on #255.
Docs preview
Updates on every push. Deleted when this pull request closes. Not indexed by search engines.
|
The docs site landed in #233 with a
wrangler.jsoncand nothing that ran it. This points it at the domain and puts the deploy in CI.The site is already live at https://capnweb.com -- I deployed it by hand from this branch's config to confirm the wiring before automating it. This PR is the config that produced it, plus the workflow that keeps it current.
Setup required before this can deploy
Two things need repo-admin and Cloudflare dashboard access, so they are not in this PR:
capnwebaccount, scoped toAccount / Workers Scripts / Edit,Zone / Workers Routes / Editoncapnweb.com, andZone / Zone / Readoncapnweb.com.docsGitHub environment on this repo holding it asCLOUDFLARE_API_TOKEN. Separate fromreleaseon purpose -- docs deploys should not go through npm-publish approvals, and release approvals should not be spendable on a docs push.Until both exist the
deployjob fails at the last step. Nothing else is affected, and the currently deployed site stays up: Workers asset deploys are atomic, so a failed run leaves the previous version serving.Previews
Every pull request from a branch in this repo now gets its own copy of the site, via Worker Previews —
wrangler previewagainst the samecapnweb-docsWorker, so a preview is a branch of production rather than a second Worker to operate. This PR's is at https://pr-255-capnweb-docs.capnweb-b14.workers.dev (deployed by hand, since the secret does not exist yet).preview_urlsgoes back totrue. It is not the same switch asworkers_dev, which my first commit had wrong:workers_devis production'sworkers.devcopy, which we still do not want;preview_urlsis what gives a preview a hostname at all. With it off,wrangler previewsucceeds and returns a preview whoseurlsarray is empty. Production stays offworkers.deveither way — verified 404.Two parts of
preview-docs.ymlare load-bearing:siteis baked into canonicals, OG URLs,robots.txtand the sitemap at build time, soDOCS_SITE_URLhas to be set beforeastro buildor the preview publishes a sitemap claiming to be capnweb.com. The deploy step reads the URL back anyway and fails if it is not the one the site was built for.X-Robots-Tag: noindexis appended to the built_headers, not committed topublic/_headers, which ships to production too. A header rather than arobots.txtDisallow, because disallowing the crawl would stop a crawler ever reading the noindex.Fork PRs get no preview — no secrets, and
pull_request_targetwould hand a contributor's build scripts a credential that can deploy the real site. Cleanup treats "preview not found" (code: 10025) as success, or every PR closing without one gets a red X.Dependency bump
wrangler4.63.0 → 4.125.0, becausewrangler previewis a private-beta command that does not exist in 4.63.0. That drags@cloudflare/workers-typesv4 → v5 as a peer. Both are devDependencies and neither changes the published types;testpasses in CI (node, workerd, all four browser projects, bun) andtest:typesis clean.@cloudflare/vitest-pool-workersstays at 0.12.10 on purpose — 0.22 requires vitest ^4, and a test-framework major is not a Workers dependency bump.Beta caveat
Worker Previews are in private beta, and two things in the current docs do not match the shipped CLI. This workflow works around both:
--jsonhas no.preview_urlfield (it is.preview.urls[0], preceded by progress text on stdout), andpreview deletetakes--nameas a flag — the positional is the entry point script, sowrangler preview delete pr-1tries to deploy a Worker calledpr-1.