Skip to content

ci: deploy the docs (prod and preview) - #255

Open
dimitropoulos wants to merge 6 commits into
mainfrom
docs-deploy
Open

ci: deploy the docs (prod and preview)#255
dimitropoulos wants to merge 6 commits into
mainfrom
docs-deploy

Conversation

@dimitropoulos

@dimitropoulos dimitropoulos commented Aug 22, 2026

Copy link
Copy Markdown
Collaborator

The docs site landed in #233 with a wrangler.jsonc and 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:

  1. A Cloudflare API token on the capnweb account, scoped to Account / Workers Scripts / Edit, Zone / Workers Routes / Edit on capnweb.com, and Zone / Zone / Read on capnweb.com.
  2. A docs GitHub environment on this repo holding it as CLOUDFLARE_API_TOKEN. Separate from release on 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 deploy job 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 Previewswrangler preview against the same capnweb-docs Worker, 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_urls goes back to true. It is not the same switch as workers_dev, which my first commit had wrong: workers_dev is production's workers.dev copy, which we still do not want; 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. Production stays off workers.dev either way — verified 404.

Two parts of preview-docs.yml are load-bearing:

  • 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. 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, not committed to public/_headers, which ships to production too. A header rather than a robots.txt Disallow, because disallowing the crawl would stop a crawler ever reading the noindex.

Fork PRs get no preview — no secrets, and pull_request_target would 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

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 v4 → v5 as a peer. Both are devDependencies and neither changes the published types; test passes in CI (node, workerd, all four browser projects, bun) and test:types is clean. @cloudflare/vitest-pool-workers stays 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: --json has no .preview_url field (it is .preview.urls[0], preceded by progress text on stdout), and preview delete takes --name as a flag — the positional is the entry point script, so wrangler preview delete pr-1 tries to deploy a Worker called pr-1.

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.
Copilot AI lite review requested due to automatic review settings August 22, 2026 13:17
@changeset-bot

changeset-bot Bot commented Aug 22, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: d7cdd75

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@ask-bonk

ask-bonk Bot commented Aug 22, 2026

Copy link
Copy Markdown

github run

@ask-bonk

ask-bonk Bot commented Aug 22, 2026

Copy link
Copy Markdown

@dimitropoulos Bonk workflow failed. Check the logs for details.

View workflow run · To retry, trigger Bonk again.

@pkg-pr-new

pkg-pr-new Bot commented Aug 22, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/cloudflare/capnweb@255
npm i https://pkg.pr.new/cloudflare/capnweb/capnweb-validate@255

commit: d7cdd75

Copilot AI 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.

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 Docs workflow that builds (library → docs) and deploys on every push to main (plus manual dispatch), using the docs environment secret.
  • Add a build-docs CI job (and root build:docs/deploy:docs scripts) so docs build failures are caught on PRs before they can break main deploys.

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.

Comment on lines +37 to +38
- uses: actions/checkout@v7

@dimitropoulos dimitropoulos changed the title ci: deploy the docs site to capnweb.com on every push to main ci: deploy the docs (prod and preview) Aug 22, 2026
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.
@github-actions

github-actions Bot commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

Docs preview

Preview https://255.pr.capnweb.com
This commit https://016ec969.pr.capnweb.com

Updates on every push. Deleted when this pull request closes. Not indexed by search engines.

d7cdd75b8430b6e6b6a0749d014fedc039ed3691

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants