fix(sync): authenticate PR creation via a repo-scoped GitHub App - #14
Conversation
The upstream sync has failed every day since 2026-07-03 because the default GITHUB_TOKEN cannot open a PR: the org policy "Allow GitHub Actions to create and approve pull requests" is off org-wide, and the per-repo toggle is overridden by it (the API returns 409 when you try to set it on the repo). #12 made that failure legible; this makes it work. Rather than flip the org setting — which would grant create-AND-self-approve to every workflow in every repo in the org, including the money-handling ones — this workflow now mints a short-lived token from a GitHub App scoped to THIS repo alone, with exactly `pull-requests: write` + `contents: write`. Least privilege; org policy stays locked. Wiring: - Preflight step fails fast with a runbook link if the two secrets are unset, so a misconfiguration is legible instead of surfacing as a create-PR error 8 steps later. - actions/create-github-app-token (SHA-pinned) mints the token BEFORE checkout. - checkout carries `token: ${{ steps.app-token.outputs.token }}`, so the later `git push` is authenticated as the App — which is also what lets CI run on the PR (pushes with the default GITHUB_TOKEN deliberately do not trigger on: pull_request). - all four `GH_TOKEN: ${{ github.token }}` usages now use the App token. Preflight verified by mutation (stubbed env): APP_ID absent / KEY absent -> rc=1 ::error APP_ID present / KEY absent -> rc=1 ::error APP_ID absent / KEY present -> rc=1 ::error APP_ID present / KEY present -> rc=0 YAML parses, bash -n clean across all 13 steps, app-token step precedes checkout. ONE-TIME operator setup (create the App, install on this repo, set two secrets) is in docs/runbooks/sync-upstream-app.md. Until that is done the workflow fails at Preflight with a pointer to the runbook — it does not silently pass. Refs #11. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KGzpyc2HrcU1dHUzYnGXzi
|
Warning Review limit reached
Next review available in: 25 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the 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 configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
🛡️ Sentinel PR review2 file(s) changed · 0 introduced by this diff (secrets+SAST) · dependencies unchanged — SCA/CVE not re-scanned. Advisory — the fail-closed gate is the post-merge pentest. Findings — ranked by criticalityNo issues found on the changed surface. 🤖 Code review (Flynn)
Scan summary
|
Closes the root cause behind #11 (and #12, which made it legible). The upstream sync has failed every day since 2026-07-03 because the default
GITHUB_TOKENcannot open a PR.Why not just flip the org setting
The org policy "Allow GitHub Actions to create and approve pull requests" is off org-wide, and the per-repo toggle is overridden by it (
409 Conflicton write). Turning it on would grant create and self-approve to every workflow in every repo in the org — including the money-handling ones (Akash-Console, control-plane). Weakening org-wide review-gate integrity to serve one dependency-bump sync is disproportionate.This uses a GitHub App scoped to
edge-python-sdkalone, with exactlypull-requests: write+contents: write. Least privilege; org policy stays locked; no other repo gains anything. (Chosen by the repo owner over the org-wide flip.)Wiring
actions/create-github-app-token(SHA-pinnedbcd2ba4…/ v3.2.0) mints the token before checkout.token: ${{ steps.app-token.outputs.token }}, so the latergit pushis the App — which is also what lets CI run on the resulting PR (pushes with the defaultGITHUB_TOKENdeliberately don't triggeron: pull_request).GH_TOKEN: ${{ github.token }}usages now use the App token.Verified
Preflight by mutation (stubbed env):
YAML parses,
bash -nclean across all 13 steps, app-token step precedes checkout, checkout carries the App token.One-time operator setup (before this helps)
docs/runbooks/sync-upstream-app.md— create the App, install on this repo, setSYNC_APP_ID+SYNC_APP_PRIVATE_KEY. Until that's done the workflow fails at Preflight with a pointer to the runbook — it does not silently pass.Separately done as operator cleanup: the 5 stale
sync/upstream-*orphan branches were deleted (their SHAs are recorded for recovery). They predated the #12 hardening and would have reverted it if merged — the 3.1.x ones even carried the oldedge_provider_sdkpackage name from before the rename.