feat: add PR preview deployments via Cloudflare Pages#300
feat: add PR preview deployments via Cloudflare Pages#300
Conversation
- Add pages-preview.yml workflow that builds site on PRs and deploys to Cloudflare Pages with a "Development Preview" banner injected into all HTML pages. Each PR gets a unique preview URL posted as a comment. - Fix MkDocs strict-mode failures: replace 3 broken relative links in getting_started.md with GitHub URLs, fix docstring indentation in messenger.py (griffe warning). - Document PR Preview workflow in CLAUDE.md.
Pre-reviewed by 7 agents, 7 findings addressed: - Fix expression injection via github.head_ref (use env var) - Fix expression injection via deployment-url output (use process.env) - Add fork PR guard to skip deploy when secrets unavailable - Remove unused artifact-uploaded output - Use lambda in re.sub to prevent backslash misfire - Port inline comments from pages.yml for consistency - Fix CLAUDE.md wording about deploy job behavior
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.OpenSSF Scorecard
Scanned Files
|
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request significantly enhances the development workflow by integrating automated preview deployments for every pull request. This change allows developers and reviewers to easily visualize and interact with the proposed changes in a live environment before merging, thereby improving the quality assurance process and accelerating feedback cycles. Highlights
Changelog
Ignored Files
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
Preview DeploymentURL: https://db785235.preview-dp2.pages.dev Built from commit |
There was a problem hiding this comment.
Code Review
This pull request introduces a new workflow for deploying PR previews to Cloudflare Pages, a valuable addition for reviewing changes. The security considerations for the new workflow are well-described. The documentation updates are helpful, but I've identified an opportunity for improvement in docs/getting_started.md where the use of absolute URLs pointing to the main branch could be replaced with a more version-aware linking strategy. The minor docstring fix is a good correction.
| - [CONTRIBUTING.md](https://github.com/Aureliolo/synthorg/blob/main/.github/CONTRIBUTING.md) — branch, commit, and PR workflow | ||
| - [CLAUDE.md](https://github.com/Aureliolo/synthorg/blob/main/CLAUDE.md) — code conventions and quick command reference | ||
| - [DESIGN_SPEC.md](https://github.com/Aureliolo/synthorg/blob/main/DESIGN_SPEC.md) — full high-level design specification |
There was a problem hiding this comment.
While using absolute URLs to GitHub fixes the broken link issue with mkdocs --strict, it introduces a new problem: these links are now hardcoded to the main branch. This means that when viewing documentation for a specific version (e.g., a release tag or a feature branch in a PR preview), these links will incorrectly point to the main branch's version of the files, not the version corresponding to the documentation being viewed.
A more robust solution would be to use relative links that are correctly resolved by MkDocs. If the files are intended to be part of the documentation, consider moving or linking them into the docs directory. Alternatively, you could explore MkDocs plugins like mkdocs-redirects or mkdocs-awesome-pages-plugin to handle linking to files outside the docs_dir correctly.
| - [CONTRIBUTING.md](https://github.com/Aureliolo/synthorg/blob/main/.github/CONTRIBUTING.md) — branch, commit, and PR workflow | ||
| - [CLAUDE.md](https://github.com/Aureliolo/synthorg/blob/main/CLAUDE.md) — code conventions and quick command reference | ||
| - [DESIGN_SPEC.md](https://github.com/Aureliolo/synthorg/blob/main/DESIGN_SPEC.md) — full high-level design specification |
There was a problem hiding this comment.
Absolute links hardcoded to main branch
The links now resolve to github.com/.../blob/main/.... While this fixes the MkDocs --strict build failure (the files live outside the docs/ hierarchy), every PR preview will point visitors to the main branch version of CONTRIBUTING.md, CLAUDE.md, and DESIGN_SPEC.md rather than to the PR's own content. This is especially misleading in the context of this PR, where the preview is intended to show the state of a branch. Consider whether the intent is to always reflect the latest main content (in which case this is fine) or whether these should be included in the docs hierarchy or linked differently.
Prompt To Fix With AI
This is a comment left during a code review.
Path: docs/getting_started.md
Line: 153-155
Comment:
**Absolute links hardcoded to `main` branch**
The links now resolve to `github.com/.../blob/main/...`. While this fixes the MkDocs `--strict` build failure (the files live outside the `docs/` hierarchy), every PR preview will point visitors to the `main` branch version of `CONTRIBUTING.md`, `CLAUDE.md`, and `DESIGN_SPEC.md` rather than to the PR's own content. This is especially misleading in the context of this PR, where the preview is intended to show the state of a branch. Consider whether the intent is to always reflect the latest `main` content (in which case this is fine) or whether these should be included in the docs hierarchy or linked differently.
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
Pull request overview
Adds a pull-request preview deployment pipeline for the docs + site build, enabling per-PR Cloudflare Pages previews and surfacing the preview URL back on the PR. Also includes small documentation fixes to keep MkDocs --strict and docstring parsing happy.
Changes:
- Add
.github/workflows/pages-preview.ymlto build MkDocs + Astro on PRs, inject a preview banner, deploy to Cloudflare Pages, and comment the preview URL. - Fix broken “Next Steps” links in
docs/getting_started.mdthat caused MkDocs strict build failures. - Fix docstring indentation in
src/ai_company/communication/messenger.pyand document PR preview behavior inCLAUDE.md.
Reviewed changes
Copilot reviewed 3 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
.github/workflows/pages-preview.yml |
New PR workflow to build, banner-inject, deploy to Cloudflare Pages, and comment the preview URL |
docs/getting_started.md |
Updates “Next Steps” links to avoid MkDocs strict link failures |
src/ai_company/communication/messenger.py |
Docstring indentation adjustment to address parser warnings |
CLAUDE.md |
Adds CI documentation describing PR preview deployments and requirements |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| - ".github/workflows/pages-preview.yml" | ||
|
|
||
| permissions: {} | ||
|
|
There was a problem hiding this comment.
This workflow lacks a concurrency block. Other workflows in this repo define concurrency (e.g., .github/workflows/ci.yml and pages.yml) to prevent overlapping runs; without it, repeated pushes to the same PR can trigger multiple builds/deploys and race to update the PR comment, increasing cost and making the latest preview harder to identify. Add a concurrency group keyed by workflow + PR number (and typically cancel in-progress for PR events).
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.event.pull_request.number }} | |
| cancel-in-progress: true |
.github/workflows/pages-preview.yml
Outdated
| const { data: comments } = await github.rest.issues.listComments({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| issue_number: context.issue.number, | ||
| }); |
There was a problem hiding this comment.
issues.listComments is called without pagination/per_page, so it will only scan the first page of comments. On PRs with many comments, this can fail to find the existing “## Preview Deployment” comment and create duplicates. Use per_page: 100 and paginate (e.g., via github.paginate) before searching for the existing comment.
| const { data: comments } = await github.rest.issues.listComments({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| }); | |
| const comments = await github.paginate( | |
| github.rest.issues.listComments, | |
| { | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| per_page: 100, | |
| } | |
| ); |
.github/workflows/pages-preview.yml
Outdated
| const body = [ | ||
| '## Preview Deployment', | ||
| '', | ||
| `**URL:** ${url}`, | ||
| '', | ||
| `Built from commit \`${context.sha.substring(0, 7)}\``, |
There was a problem hiding this comment.
For pull_request events, context.sha typically refers to the synthetic merge commit (refs/pull/.../merge), not the PR head commit. The comment may therefore report a SHA that doesn’t match what contributors expect. Prefer using the PR head SHA from the event payload (e.g., context.payload.pull_request.head.sha) when generating the “Built from commit …” line.
| const body = [ | |
| '## Preview Deployment', | |
| '', | |
| `**URL:** ${url}`, | |
| '', | |
| `Built from commit \`${context.sha.substring(0, 7)}\``, | |
| const prHeadSha = context.payload?.pull_request?.head?.sha; | |
| const effectiveSha = prHeadSha || context.sha; | |
| const body = [ | |
| '## Preview Deployment', | |
| '', | |
| `**URL:** ${url}`, | |
| '', | |
| `Built from commit \`${effectiveSha.substring(0, 7)}\``, |
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ❌ Deployment failed View logs |
preview | 532bcbf | Mar 11 2026, 04:12 PM |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (4)
📜 Recent review details⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
🧰 Additional context used📓 Path-based instructions (3).github/workflows/*.yml📄 CodeRabbit inference engine (CLAUDE.md)
Files:
**/*.py📄 CodeRabbit inference engine (CLAUDE.md)
Files:
src/**/*.py📄 CodeRabbit inference engine (CLAUDE.md)
Files:
🧠 Learnings (11)📓 Common learnings📚 Learning: 2026-03-11T15:09:59.075ZApplied to files:
📚 Learning: 2026-03-11T15:09:59.075ZApplied to files:
📚 Learning: 2026-03-11T15:09:59.075ZApplied to files:
📚 Learning: 2026-03-11T15:09:59.075ZApplied to files:
📚 Learning: 2026-03-11T15:09:59.075ZApplied to files:
📚 Learning: 2026-03-11T15:09:59.075ZApplied to files:
📚 Learning: 2026-03-11T15:09:59.075ZApplied to files:
📚 Learning: 2026-03-11T15:09:59.075ZApplied to files:
📚 Learning: 2026-03-11T15:09:59.075ZApplied to files:
📚 Learning: 2026-03-11T15:09:59.075ZApplied to files:
🔇 Additional comments (10)
📝 WalkthroughSummary by CodeRabbit
WalkthroughThis pull request introduces a new GitHub Actions workflow for generating PR preview sites, updates documentation describing the preview workflow and deployment process, fixes documentation links from relative to absolute GitHub URLs, and makes a minor formatting adjustment to a docstring. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes 🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
✨ Simplify code
Comment |
- Add concurrency group to cancel stale preview builds on rapid pushes - Paginate listComments to avoid missing existing preview comment - Use PR head SHA instead of merge commit SHA in preview comment
| uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7 | ||
| with: | ||
| name: preview-site | ||
| path: _site | ||
| retention-days: 5 | ||
|
|
||
| deploy-preview: | ||
| name: Deploy Preview | ||
| needs: build | ||
| if: github.event.pull_request.head.repo.full_name == github.repository | ||
| runs-on: ubuntu-latest | ||
| permissions: | ||
| contents: read | ||
| pull-requests: write | ||
| deployments: write | ||
| steps: | ||
| - name: Download preview artifact | ||
| uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8 |
There was a problem hiding this comment.
Artifact upload/download version mismatch
upload-artifact is pinned at v7 while download-artifact is pinned at v8. These are different major versions. GitHub's artifact actions historically introduced breaking format changes across major versions (notably from v3→v4), and mixing major versions between the upload and download steps of the same workflow run risks a format incompatibility that would silently produce a corrupted or empty artifact download — failing the deployment without a clear error.
Both pins should be aligned to the same major version. The existing pages.yml workflow sidesteps this entirely by using actions/upload-pages-artifact (which pairs with the GitHub Pages deploy action), so there's no prior art in this repo to lean on. Align both to the same version, e.g.:
- name: Upload preview artifact
uses: actions/upload-artifact@<sha> # v8
with:
name: preview-site
path: _site
retention-days: 5and
- name: Download preview artifact
uses: actions/download-artifact@<sha> # v8
with:
name: preview-site
path: _sitePrompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/pages-preview.yml
Line: 105-122
Comment:
**Artifact upload/download version mismatch**
`upload-artifact` is pinned at `v7` while `download-artifact` is pinned at `v8`. These are different major versions. GitHub's artifact actions historically introduced breaking format changes across major versions (notably from v3→v4), and mixing major versions between the upload and download steps of the same workflow run risks a format incompatibility that would silently produce a corrupted or empty artifact download — failing the deployment without a clear error.
Both pins should be aligned to the same major version. The existing `pages.yml` workflow sidesteps this entirely by using `actions/upload-pages-artifact` (which pairs with the GitHub Pages deploy action), so there's no prior art in this repo to lean on. Align both to the same version, e.g.:
```yaml
- name: Upload preview artifact
uses: actions/upload-artifact@<sha> # v8
with:
name: preview-site
path: _site
retention-days: 5
```
and
```yaml
- name: Download preview artifact
uses: actions/download-artifact@<sha> # v8
with:
name: preview-site
path: _site
```
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
Pull request overview
Copilot reviewed 3 out of 4 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| permissions: | ||
| contents: read | ||
| pull-requests: write | ||
| deployments: write |
There was a problem hiding this comment.
deploy-preview requests deployments: write, but this workflow doesn't appear to use the GitHub Deployments API (it only downloads an artifact, deploys to Cloudflare, and posts a PR comment). Consider removing deployments: write to keep the job least-privileged, or add a note/step showing why it's required.
| deployments: write |
|
Closing — will recreate with all review feedback incorporated in a clean PR. |
## Summary - **New workflow**: `.github/workflows/pages-preview.yml` — builds MkDocs + Astro on PRs, injects "Development Preview" banner, deploys to Cloudflare Pages - Each PR gets a unique preview URL at `pr-<number>.synthorg-pr-preview.pages.dev` - Preview URL auto-commented on the PR (paginated comment search, updates existing comment on re-push) - **Security hardened**: env vars for expression injection mitigation, fork PR guard, SHA-pinned actions, `persist-credentials: false`, least-privilege permissions - **Bug fixes**: 3 broken links in `docs/getting_started.md` (MkDocs `--strict`), docstring indentation in `messenger.py` (griffe warning) - **Docs**: CLAUDE.md CI section updated with PR Preview details ## Review feedback incorporated All valid findings from PR #300 reviewers (Gemini, Greptile, Copilot) addressed: - Concurrency group with cancel-in-progress (Greptile + Copilot) - Paginated `listComments` to avoid missing existing comment (Copilot) - PR head SHA instead of merge commit SHA in comment (Copilot) - Removed unused `deployments: write` permission (Copilot) - Wrangler run step instead of action (fixes env var expansion bug) - PR number in URL instead of branch slug (cleaner, shorter) Dismissed: absolute links to main in getting_started.md (intentional — files outside docs/ hierarchy) ## Test plan - [ ] Verify workflow triggers on PR with docs/site/mkdocs changes - [ ] Verify MkDocs + Astro build succeeds - [ ] Verify preview banner appears on all HTML pages - [ ] Verify Cloudflare Pages deployment succeeds - [ ] Verify preview URL comment appears on PR with correct SHA - [ ] Verify concurrency cancels stale builds on rapid push - [ ] Verify fork PRs skip deploy job gracefully 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Summary
.github/workflows/pages-preview.yml— builds MkDocs + Astro site on PRs, injects a visible "Development Preview" banner, and deploys to Cloudflare Pagespersist-credentials: falsedocs/getting_started.md(MkDocs--strictfailures), fixed docstring indentation inmessenger.py(griffe parser warning)CLAUDE.mdCI documentationDetails
github.event.pull_request.head.repo.full_name == github.repository)CLOUDFLARE_API_TOKEN+CLOUDFLARE_ACCOUNT_IDrepository secretscloudflare/wrangler-action@v3.14.1(SHA-pinned)Test plan
--strictflagPre-reviewed by 8 agents, 7 findings addressed.
🤖 Generated with Claude Code