Skip to content

ci: skip the preview deploy on fork PRs too - #517

Merged
allxsmith merged 2 commits into
mainfrom
ci/398-fork-preview-guard
Aug 14, 2026
Merged

allxsmith merged 2 commits into
mainfrom
ci/398-fork-preview-guard

Conversation

@allxsmith

@allxsmith allxsmith commented Aug 14, 2026 •

Copy link
Copy Markdown
Owner

What #398 asked for, and what is left of it

#398 reported that Test and Preview Deployment went red on every dependabot PR: those runs are scoped to the Dependabot secrets store, so secrets.CLOUDFLARE_API_TOKEN interpolates empty and wrangler-action aborts. The build passed first, so the red X was pure noise that reads as a merge blocker while triaging.

That symptom already shipped fixed, by a different mechanism than the issue proposed:

  • 4a273b8 split build from deploy so build-time code cannot reach the Cloudflare credentials.
  • 6f1351c guarded the deploy job on github.actor != 'dependabot[bot]'.

Confirmed live on the three dependabot PRs opened since — #511, #510, #469: Build preview site passes, Test and Preview Deployment reports skipping, and each run concludes success. The job comment notes the skipped-not-green tradeoff is fine while the check is not required; still true, the main ruleset requires only Build and Test, React 18 compatibility, React 19 compatibility, and Dependency Review.

The case the actor test does not reach

Fork PRs arrive with no secrets too, for the same reason and by design — this workflow is plain pull_request, so a fork head never sees them. But the actor on a fork run is the contributor rather than dependabot, so the job starts and reproduces #398's failure exactly: wrangler on an empty token, then Comment Preview URL, whose write permission GitHub downgrades to read on a fork run whatever the permissions: block asks for.

This PR adds the head-repo guard the other same-repo-only workflows already use (ai-scan.yml, ai-triage.yml, claude-review.yml, story-screenshots.yml). Theirs carry an extra pull_request == null branch only because they also run on issues events; this one runs on pull_request alone, so the PR object is always present.

Security notes

  • No trigger change. Still plain pull_request on main, no pull_request_target. Rule 7 in .github/CLAUDE.md is what makes the fork run secret-less in the first place, and this preserves that rather than working around it.
  • Strictly subtractive. Both clauses only ever cause the job to skip. A fork run gains nothing it does not have today; it just stops starting a deploy it cannot finish.
  • No permissions: change, no allowlist change, no action SHA change, no new repository variable, no verdict or budget path.
  • Adding the Cloudflare credentials to the Dependabot secrets store would also turn the check green and is still deliberately not done, for the reason the job comment already gives.

Verification

  • The run on this PR is the regression test for the path that matters: same-repo branch, human actor, so both clauses are true and Test and Preview Deployment must still run and post a preview URL. If it skips, the condition is wrong.
  • pnpm exec prettier --check passes on the file, which parses the YAML as a side effect. The repo has no actionlint.
  • The fork path itself stays unvalidated until an outside PR arrives — the same caveat CI: Test and Preview Deployment fails on every dependabot PR — guard the wrangler steps on secret presence #398 carried, since a secret-less run cannot be simulated from a same-repo branch.

Closes #398

Summary by CodeRabbit

  • Bug Fixes
    • Prevented deployment attempts for forked and automated dependency-update pull requests when required credentials are unavailable.
    • Improved deployment workflow handling for pull requests from external sources.

The deploy job was guarded on `github.actor != 'dependabot[bot]'`, which
covers the case #398 reported but not the other one that lands here with no
credentials. Fork PRs lose the secrets for the same reason and by design —
this workflow is plain `pull_request`, so a fork head never sees them — but
the actor on those runs is the contributor, not dependabot, so the job
starts and fails exactly as the dependabot runs used to: wrangler aborts on
an empty CLOUDFLARE_API_TOKEN, and Comment Preview URL then fails too, since
GitHub downgrades the job's write permission to read on a fork run whatever
the permissions block asks for.

Adding the head-repo guard the other same-repo-only workflows already use
(ai-scan, ai-triage, claude-review, story-screenshots) turns that red X into
a skip. Theirs carry an extra `pull_request == null` branch because they also
run on issues events; this workflow only runs on pull_request, so the PR
object is always there.

Both clauses only ever narrow what runs. The trigger is untouched and stays
plain `pull_request` — the fork run has no secrets to reach in the first
place, which is the property this preserves rather than works around.

Unvalidatable until an outside PR arrives, same caveat #398 carried: a
secret-less run cannot be simulated from a same-repo branch, where both
clauses are true and the preview must still deploy as before.

Closes #398
Copilot AI balanced review requested due to automatic review settings August 14, 2026 04:05
@coderabbitai

coderabbitai Bot commented Aug 14, 2026 •

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@allxsmith, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 49 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: b30c9fdd-0069-45e7-9ab3-062cccbc810c

📥 Commits

Reviewing files that changed from the base of the PR and between df961bd and 3d87464.

📒 Files selected for processing (1)
  • .github/workflows/test-deploy.yml

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 7fbf9976-97dd-4538-be3a-4f55347485c4

📥 Commits

Reviewing files that changed from the base of the PR and between 49f35a9 and df961bd.

📒 Files selected for processing (1)
  • .github/workflows/test-deploy.yml

Walkthrough

The deployment job now excludes Dependabot pull requests and pull requests from fork repositories. Workflow comments document the related secret and permission limitations.

Changes

Deployment guards

Layer / File(s) Summary
Restrict pull request deployments
.github/workflows/test-deploy.yml
The workflow documents fork pull request secret and permission limits. The deployment condition now requires both a non-Dependabot actor and a matching head repository.

Estimated code review effort: 2 (Simple) | ~5 minutes

Merge Risk: ⚪ Minimal · up to df961

The workflow now avoids starting preview deployments that cannot access required secrets on fork pull requests while preserving previews for same-repository changes. No actionable merge-blocking risk remains after normal checks and review.

Possibly related PRs

  • allxsmith/bestax#316: Updates workflow conditions to restrict execution for fork and Dependabot pull requests.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly states that preview deployments are skipped for fork pull requests, matching the primary workflow change.
Description check ✅ Passed The description explains the problem, implementation, security impact, verification, and linked issue, although it does not follow every template section.
Linked Issues check ✅ Passed The workflow extends secret-less deployment protection to fork pull requests while preserving builds and same-repository preview deployments required by #398.
Out of Scope Changes check ✅ Passed The changes are limited to the preview deployment workflow guard and related comments; no unrelated code or configuration changes are described.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ci/398-fork-preview-guard

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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

Prevents fork PRs from attempting credentialed preview deployments while preserving build validation.

Changes:

  • Adds a same-repository guard to the deployment job.
  • Documents fork security behavior.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread .github/workflows/test-deploy.yml Outdated
Comment on lines +96 to +98
# `permissions:` block below says. Same idiom as ai-scan.yml,
# ai-triage.yml, claude-review.yml and story-screenshots.yml; they carry an
# extra `pull_request == null` branch only because they also run on issues.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Correct, and fixed in 3d87464. Verified each of the four: ai-scan.yml (issues + pull_request) and ai-triage.yml (pull_request + issues) carry the null branch; claude-review.yml (pull_request only) and story-screenshots.yml (workflow_dispatch + pull_request) use the bare head-repo check, which is the form this job copies.

The comment now names the two groups separately. Worth fixing at any size, since a security comment that misdescribes its own mechanism is what stops the next reader verifying it.

@github-actions

Copy link
Copy Markdown
Contributor

Preview Deployment

Preview URL: https://4f513156.bestax.pages.dev

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Deep review — 0 blocking · 1 advisory

# Severity Area Finding Location
1 🔵 Advisory Robustness The in-file comment says all four cited workflows "carry an extra pull_request == null branch only because they also run on issues" — but only ai-scan.yml/ai-triage.yml do; claude-review.yml and story-screenshots.yml neither run on issues nor carry that branch (the same idiom this PR copies from claude-review.yml directly). .github/workflows/test-deploy.yml:96-98

Overall: The change is sound and low-risk. It adds a single &&-clause head-repo guard (github.event.pull_request.head.repo.full_name == github.repository) to the test-deploy job's if:, which only ever narrows what runs — a fork PR that today reproduces #398's failure (wrangler on an empty CLOUDFLARE_API_TOKEN, then a Comment Preview URL step that can't write on a fork run) now skips instead. The idiom is verified byte-for-byte identical to claude-review.yml:50, the trigger stays plain pull_request (rule 7 preserved — no pull_request_target, no permissions:/allowlist/SHA change), and prettier --check passes (parsing the YAML as a side effect). The riskiest thing here is nothing structural — it's the fork path staying empirically unvalidated until an outside PR lands, exactly the caveat #398 already carried. The human should focus first on confirming this PR's own run (same-repo, human actor -> both clauses true) still deploys and posts a preview URL; that is the regression test that matters.

Residual risk:

  • Other secret-less pull_request runs slipping through — GitHub scopes secrets away in only two cases: Dependabot's separate secret store (covered by the pre-existing github.actor != 'dependabot[bot]' clause) and fork heads (covered by the new guard). No third secret-less path exists on plain pull_request; other same-repo bot/human actors get the Actions store and deploy correctly, which is intended.
  • Deleted-fork edge (head.repo null) — if the fork repo is gone, github.event.pull_request.head.repo.full_name resolves to null, which != github.repository, so the job skips — the safe direction.
  • Skip vs. required-check — this job is not in the main ruleset's required set (Build and Test, React 18/19, Dependency Review), so a fork PR skipping it does not wedge merge; build still runs and catches build breakage. The comment already flags the "move the gate to steps if ever promoted to required" follow-up.

🏄 Chill little one-line patch, dude — it just tells the deploy job to stay on the beach when there's no secrets in the water, same wave every other same-repo workflow is already riding. Totally good to go; only ripple is a comment that name-drops two workflows that don't actually carry the branch it says they do. No worries, ship it.

Copilot and the deep review both caught the same overstatement. The comment
said the four cited workflows carry an extra `pull_request == null` branch
because they also run on issues, but only ai-scan and ai-triage do —
claude-review and story-screenshots run on pull_request alone and use the
bare head-repo check, which is the form this job copies.

Small as it is, a wrong claim in a security comment is the failure the
review checklist ends on: the next reader stops verifying once a comment
has misdescribed its own mechanism.
Copilot AI review requested due to automatic review settings August 14, 2026 04:16
@allxsmith

Copy link
Copy Markdown
Owner Author

Review round 1 addressed — 3d87464

Deep review advisory 1 / Copilot inline (test-deploy.yml:96-98) — valid, fixed.

The comment claimed all four cited workflows carry an extra pull_request == null branch "only because they also run on issues". Only two do. Verified each against its on: block:

workflow triggers null branch
ai-scan.yml issues + pull_request yes
ai-triage.yml pull_request + issues yes
claude-review.yml pull_request only no
story-screenshots.yml workflow_dispatch + pull_request no

The comment now names the two groups separately and says which form this job copies (the bare one, from claude-review.yml). Comment-only change — the guard expression is untouched.

Small, but worth a commit rather than a shrug: the review checklist in .github/CLAUDE.md ends on exactly this failure, and the reason is that a security comment which misdescribes its own mechanism is what stops the next reader from checking.

No other findings. The deep review reported 0 blocking, CodeRabbit generated no actionable comments, and its three residual-risk notes are observations I agree with rather than requests — in particular that a deleted fork head resolves head.repo.full_name to null, which fails the equality and skips, the safe direction.

The regression test that mattered already passed on the previous head: same-repo, human actor, so both clauses are true and Test and Preview Deployment ran and deployed (22s), posting the preview URL comment above. This push re-runs it.

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

Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.

@allxsmith
allxsmith merged commit c3a6390 into main Aug 14, 2026
22 checks passed
@allxsmith
allxsmith deleted the ci/398-fork-preview-guard branch August 14, 2026 04:19
@github-actions

Copy link
Copy Markdown
Contributor

Preview Deployment

Preview URL: https://0145d1a6.bestax.pages.dev

@bestax-release-bot

Copy link
Copy Markdown

🎉 This PR is included in version 5.11.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

@bestax-release-bot

Copy link
Copy Markdown

🎉 This PR is included in version 2.0.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

@bestax-release-bot

Copy link
Copy Markdown

🎉 This PR is included in version 4.1.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

@bestax-release-bot

Copy link
Copy Markdown

🎉 This PR is included in version 1.0.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CI: Test and Preview Deployment fails on every dependabot PR — guard the wrangler steps on secret presence

2 participants