Skip to content

feat: add per-PR documentation preview deployments#333

Open
Nonnyjoe wants to merge 2 commits into
mainfrom
feat/preview-for-pr
Open

feat: add per-PR documentation preview deployments#333
Nonnyjoe wants to merge 2 commits into
mainfrom
feat/preview-for-pr

Conversation

@Nonnyjoe
Copy link
Copy Markdown
Member

@Nonnyjoe Nonnyjoe commented Jun 3, 2026

Summary

Adds per-PR documentation preview deployments: every pull request is built and published to a unique, navigable URL so reviewers can see exactly how the change renders before merging.

  • Production is unaffected. docs.cartesi.io stays on AWS Amplify. Previews are served from a separate origin on GitHub Pages: https://<owner>.github.io/<repo>/pr-preview/pr-<N>/.
  • Safe for pull requests from forks — no PAT and no secrets required.

How it works (two-workflow split)

A forked PR's workflow gets a read-only token and no secrets by design. To support fork previews securely, the work is split:

  1. preview-build.yml (pull_request) — runs untrusted PR code with contents: read and no secrets. It builds the site (pointed at the Pages sub-path via DOCS_URL/DOCS_BASE_URL) and uploads it as an artifact. Replaces the build-only build.yml so each PR builds once.
  2. preview-deploy.yml (workflow_run) — runs from the default branch in the trusted base-repo context, so it has write access. It downloads the already-built artifact, publishes it to the gh-pages branch under pr-preview/pr-<N>/, posts a sticky PR comment with the URL, and removes the preview when the PR closes. It never executes PR code — only the inert static artifact — so this is safe for forked PRs.

pull_request_target is deliberately not used. The deploy job validates the PR number (which arrives via the artifact) before using it in any path/API call, and serializes writes to gh-pages.

Changes

File Change
.github/workflows/preview-build.yml New — untrusted PR build → artifact (read-only, no secrets)
.github/workflows/preview-deploy.yml New — trusted publish to gh-pages, sticky comment, teardown on close
.github/workflows/build.yml Removed — folded into preview-build to avoid building twice
docusaurus.config.js url/baseUrl made env-overridable; defaults unchanged (docs.cartesi.io, /)
src/pages/index.js Homepage redirect resolved via useBaseUrl (no-op in prod)
src/components/SelectVersion/DropdownVersion.js Version-plugin detection resolved relative to baseUrl (no-op in prod)

The last two are required for previews to be navigable under a sub-path; both are no-ops in production (where baseUrl is /).

One-time setup

Previews activate only after the workflows are on the default branch (this PR) and:

  1. Settings → Actions → General → Workflow permissions → "Read and write" (lets the deploy job push to gh-pages and comment).
  2. After the first preview deploy creates the gh-pages branch: Settings → Pages → Source = gh-pages / / (root). Enabling Pages does not affect Amplify or docs.cartesi.io (separate origin).
  3. Update branch protection from the old Build status check, to preview-build.

Build every pull request and publish it to a unique, navigable GitHub Pages URL so
reviewers can see the rendered docs before merging. Production (AWS Amplify at
docs.cartesi.io) is unaffected; previews are served from a separate origin
(https://<owner>.github.io/<repo>/pr-preview/pr-<N>/).

Fork-safe by design (no PAT or secrets), via a two-workflow split:

- .github/workflows/preview-build.yml (pull_request): builds the PR with a read-only
  token and NO access to secrets, then uploads the static site as an artifact.
  Replaces the build-only build.yml so each PR builds exactly once.
- .github/workflows/preview-deploy.yml (workflow_run): runs from the default branch in
  the trusted base-repo context, downloads the artifact, publishes it to the gh-pages
  branch under pr-preview/pr-<N>/, posts a sticky comment with the URL, and removes the
  preview when the PR is closed. It never executes PR code, so previews work for pull
  requests from forks without exposing any secret.
- docusaurus.config.js: url/baseUrl are now env-overridable (DOCS_URL/DOCS_BASE_URL) and
  default to docs.cartesi.io and "/", so local builds and Amplify are unchanged.
- src/pages/index.js and src/components/SelectVersion/DropdownVersion.js: resolve the
  homepage redirect and the version dropdown against baseUrl so they work under the
  preview sub-path. Both are no-ops in production (baseUrl "/").

One-time setup (maintainer):
- Settings -> Actions -> General -> Workflow permissions: "Read and write".
- After the first preview deploy creates the gh-pages branch, set Settings -> Pages
  source to the gh-pages branch (root).
- If branch protection requires the old "Build" check, update it to "preview-build".
…aren't empty

The plugin keyed its URL map on doc.permalink, which includes the site baseUrl.
Under a sub-path baseUrl (GitHub Pages PR previews at /<repo>/pr-preview/pr-<N>/),
postBuild wrote each page's full .md to a baseUrl-nested dead path, so the URL
people request (.../page.md) only got the title-only generated-index stub.

Normalize permalinks to baseUrl-relative in buildUrlMap — one change that fixes
the .md output paths, the llms.txt index/alias route matching, and the
llms-full.txt page URLs. No-op at baseUrl "/", so production is unchanged.
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