Skip to content

ci/docs: deploy documentation site on Cloudflare with PR previews - #225

Merged
ifireball merged 2 commits into
fullsend-ai:mainfrom
ifireball:ifireball/site-cloudflare-workers
Apr 15, 2026
Merged

ci/docs: deploy documentation site on Cloudflare with PR previews#225
ifireball merged 2 commits into
fullsend-ai:mainfrom
ifireball:ifireball/site-cloudflare-workers

Conversation

@ifireball

@ifireball ifireball commented Apr 12, 2026

Copy link
Copy Markdown
Member

Summary

Moves documentation site hosting to Cloudflare Workers with GitHub Deployments so each open pull request can publish its own preview URL. Reviewers can validate rendered docs, links, and layout in a browser instead of relying only on Markdown and workflow diffs.

What changed

  • Replace .github/workflows/mindmap.yml with site-build.yml and site-deploy.yml.
  • Add site/wrangler.toml and site/public/ for static assets.
  • Add docs/site-deployment.md (operator runbook) and design/spec material under docs/superpowers/.

Ran make lint locally before pushing, as recommended in CONTRIBUTING.md.

@ifireball
ifireball force-pushed the ifireball/site-cloudflare-workers branch from e413c1b to ef21046 Compare April 12, 2026 07:58
@ifireball ifireball changed the title ci/docs: publish documentation site on Cloudflare Workers ci/docs: deploy documentation site on Cloudflare with PR previews Apr 12, 2026
Host the static documentation site on Cloudflare Workers and wire GitHub
Deployments so each pull request can publish an isolated preview URL.
Reviewers can open the rendered site for a change instead of inferring
layout and navigation from diffs alone.

This removes the GitHub Pages mindmap workflow in favor of site build and
deploy workflows, adds site/wrangler.toml, operator guidance in
docs/site-deployment.md, and design/spec notes under docs/superpowers/.
@ifireball
ifireball force-pushed the ifireball/site-cloudflare-workers branch from ef21046 to 5b24708 Compare April 12, 2026 07:59
@ifireball ifireball self-assigned this Apr 12, 2026
@ifireball
ifireball marked this pull request as ready for review April 12, 2026 08:03

@waynesun09 waynesun09 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall the two-workflow pattern is well-designed — fork safety, secret isolation, and artifact flow are solid. A few items to address before merging:

Must fix:

  • --assets public CLI flag on versions upload may override wrangler.toml asset config (including not_found_handling), creating divergence between preview and production
  • Verify deployment-url output from wrangler-action for versions upload --preview-alias returns the alias URL, not the internal versioned URL

Should fix:

  • URL parsing fallback matches workers.dev as substring — tighten to \.workers\.dev
  • Preview alias uses workflow_run.id instead of PR number — creates stale alias sprawl
  • per_page: 100 on comment listing may miss marker comment on busy PRs
  • Fork PR number resolution silently skips on ambiguous match — use core.warning
  • Plan doc references site-github-pages.yml but the deleted file is mindmap.yml

Comment thread .github/workflows/site-deploy.yml Outdated
fi
if [ -z "$url" ]; then
comb="${OUT_PROD:-}${ERR_PROD:-}${OUT_PR:-}${ERR_PR:-}"
url=$(printf '%s' "$comb" | grep -oE 'https://[a-zA-Z0-9._/?#&=%_-]+' | grep 'workers.dev' | head -1 || true)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security — URL parsing matches workers.dev as substring

grep 'workers.dev' would also match deceptive domains like evil-workers.dev.attacker.com. This URL ends up as environment_url in a GitHub Deployment and rendered as a clickable link in the PR comment.

Suggest tightening to:

grep -E '\.workers\.dev(/|$)'

Comment thread .github/workflows/site-deploy.yml Outdated
Comment on lines +59 to +63
command: >-
versions upload
--name="${{ vars.CLOUDFLARE_PROJECT_NAME }}"
--assets public
--preview-alias pr-${{ github.event.workflow_run.id }}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent asset config between preview and production paths

The preview command passes --assets public explicitly here, but the production deploy (line 48) does NOT pass --assets and relies on wrangler.toml's [assets] directory = "./public". Two concerns:

  1. The CLI --assets flag may override the entire asset config block from wrangler.toml, meaning not_found_handling = "single-page-application" might not apply to previews.
  2. Behavior divergence between preview and production — what reviewers see in preview may not match what ships to production.

Consider removing --assets public and letting wrangler.toml govern both paths consistently, or verify that the CLI flag preserves the [assets] table settings.

Comment thread .github/workflows/site-deploy.yml Outdated
versions upload
--name="${{ vars.CLOUDFLARE_PROJECT_NAME }}"
--assets public
--preview-alias pr-${{ github.event.workflow_run.id }}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Preview alias uses workflow_run.id instead of PR number

pr-${{ github.event.workflow_run.id }} produces aliases like pr-12345678901 which are not human-readable and create a new alias on every re-run (stale alias sprawl). Using the resolved PR number instead (e.g., pr-225) would produce stable, predictable preview URLs.

This would require resolving the PR number before the wrangler step — a structural change, but worth considering since the PR number resolution logic already exists later in the workflow.

if: >-
(steps.cf-prod.outcome == 'success' || steps.cf-preview.outcome == 'success')
env:
URL_PROD: ${{ steps.cf-prod.outputs.deployment-url }}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verify deployment-url output for versions upload

wrangler-action extracts deployment-url from wrangler's structured output. For wrangler deploy this reliably returns the production URL, but for versions upload --preview-alias it's unclear whether the output contains the alias URL (e.g., pr-XXX.<worker>.workers.dev) or the internal versioned URL. If it returns the versioned URL, the preview comment will show a less stable link. The grep fallback at line 84 helps but depends on wrangler output format. Worth validating with a test run.

Comment thread .github/workflows/site-deploy.yml Outdated
owner,
repo,
issue_number: prNumber,
per_page: 100,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

per_page: 100 may miss existing marker comment

On heavily-discussed PRs with 100+ comments (e.g., bot activity from multiple tools), the marker comment could be on a later page, causing a duplicate comment to be created. Consider paginating or documenting this as a known limitation.

Comment thread .github/workflows/site-deploy.yml Outdated
Comment on lines +135 to +149
let prNumber = run.pull_requests?.[0]?.number;
if (!prNumber) {
const head = `${run.head_repository.owner.login}:${run.head_branch}`;
const { data: prs } = await github.rest.pulls.list({
owner,
repo,
state: 'open',
head,
per_page: 100,
});
if (prs.length !== 1) {
core.info(`Skipping PR comment: expected 1 open PR for head=${head}, found ${prs.length}`);
return;
}
prNumber = prs[0].number;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR number resolution unreliable for fork PRs

workflow_run.pull_requests is documented as empty when head and base repos differ (fork PRs). The pulls.list fallback with head=owner:branch is generally correct, but silently skips the comment if the fork owner has multiple open PRs from the same branch name. Consider logging a warning (core.warning) instead of core.info so this is more visible in the Actions log.

| `.github/workflows/site-deploy.yml` | Checkout + artifact → `site/public/`, `wrangler deploy` / `versions upload`, GitHub Deployment + PR comment |
| `site/wrangler.toml` | Worker name placeholder, `assets.directory = public`, SPA `not_found_handling`, `preview_urls` |
| `site/public/.gitkeep` | Keeps `public/` in git; CI overwrites with artifact contents |
| `.github/workflows/site-github-pages.yml` | **Removed** (replaced by `site-build.yml` / `site-deploy.yml`) |

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrong filename — references site-github-pages.yml but the actual deleted file is mindmap.yml. This appears in the file map and again in Task 3 (lines 118, 122, 127).

- Resolve PR number early for stable --preview-alias pr-<n>; fall back to
  workflow_run.id with a warning when multiple open PRs share the same head.
- Drop --assets public from versions upload so wrangler.toml governs SPA
  not_found_handling for preview and production.
- Tighten workers.dev URL extraction to avoid deceptive hostnames.
- Paginate PR comment search; gate deployment script on meta success; warn
  when preview URL omits the alias token (versioned URL hint).
- Fix plan/spec/runbook: removed workflow was mindmap.yml; document alias
  behavior.

Made-with: Cursor
@ifireball

Copy link
Copy Markdown
Member Author

Pushed 7a395b7 addressing @waynesun09’s review:

Must fix

  • Dropped --assets public from versions upload so site/wrangler.toml [assets] (including not_found_handling) applies to previews the same as production.
  • Added a Validate preview Workers URL step: if deployment-url does not contain the preview-alias token (e.g. pr-225), the job emits an ::warning:: so logs flag a possible versioned URL vs alias hostname (without failing the deploy).

Should fix

  • URL fallback grep now requires \.workers\.dev(/|$) so deceptive hostnames are not picked up.
  • Preview alias uses resolved PR number when unique; only falls back to workflow_run.id when pulls.list finds multiple open PRs for the same head (with core.warning).
  • PR comment listing paginates (up to 20×100 comments) to find the marker.
  • Ambiguous / missing PR for the comment path uses core.warning (no silent info).
  • Plan/spec/runbook: removed workflow is mindmap.yml, not site-github-pages.yml; docs describe alias + fallback.

CI lint / build (Build Site) are green on this push. Please take another look when you have a moment.

@ifireball
ifireball requested a review from waynesun09 April 14, 2026 08:02

@waynesun09 waynesun09 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All 7 items from my previous review are resolved in 7a395b7. Verified each fix against the current diff:

  • --assets public dropped — wrangler.toml governs both paths consistently
  • Preview URL validation step added (warns if alias token missing, doesn't block)
  • URL grep anchored to \.workers\.dev(/|$)
  • PR number resolved before wrangler step — stable pr-<number> aliases, fallback to workflow_run.id only on ambiguous head with core.warning
  • Comment listing paginates (20×100)
  • Ambiguous/missing PR uses core.warning throughout
  • Plan/spec/runbook corrected to reference mindmap.yml

Clean restructuring, no new issues.

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.

4 participants