fix: sync-upstream workflow silently fails to open PRs, leaving fork behind - #1
Conversation
The workflow's permissions block was missing issues: write, so `gh label create sync` failed every run (silently, via 2>/dev/null || true). That left the `sync` label missing, which made the follow-up `gh pr create --label sync` fail too (also swallowed by `|| true`). Net effect: the job reported success every day while never actually opening a sync PR, so main stayed pinned to upstream commit e46364b (2026-06-17) even as upstream moved 14 commits ahead. - Grant issues: write so label creation actually succeeds. - Use `gh label create --force` instead of swallowing stderr, so the step is idempotent without hiding real errors. - After `gh pr create`, verify a PR actually exists for the branch and fail the job loudly if not, instead of silently continuing. - Surface (rather than swallow) auto-merge failures as a warning, so a disabled "Allow auto-merge" repo setting is visible in the logs.
|
Important Review skippedAuto reviews are limited based on label configuration. 🏷️ Required labels (at least one) (1)
Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yml Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Note
|
The follow-up workflow_dispatch run after #1 merged failed hard on `gh label create`: HTTP 403: Resource not accessible by integration (https://api.github.com/repos/cursor/plugins/labels) Note the URL: gh was targeting cursor/plugins, not this fork. This job adds a remote literally named `upstream` pointing at cursor/plugins (to fetch its history for the rebase), and gh's implicit repo resolution prefers a remote named "upstream" over "origin" when no --repo/GH_REPO is given — a classic gotcha for exactly this fork+ upstream-remote layout. So every unscoped `gh label create`/`gh pr create`/`gh pr list`/`gh pr merge` call in this workflow has actually been aimed at cursor/plugins the whole time, where this token has no access whatsoever. That's the real reason label/PR creation always failed — the previous fix (#1) just stopped hiding it. Set GH_REPO: ${{ github.repository }} at the job level so every `gh` call is unambiguously pinned to this fork regardless of which git remotes exist.
The follow-up workflow_dispatch run after #1 merged failed hard on `gh label create`: HTTP 403: Resource not accessible by integration (https://api.github.com/repos/cursor/plugins/labels) Note the URL: gh was targeting cursor/plugins, not this fork. This job adds a remote literally named `upstream` pointing at cursor/plugins (to fetch its history for the rebase), and gh's implicit repo resolution prefers a remote named "upstream" over "origin" when no --repo/GH_REPO is given — a classic gotcha for exactly this fork+ upstream-remote layout. So every unscoped `gh label create`/`gh pr create`/`gh pr list`/`gh pr merge` call in this workflow has actually been aimed at cursor/plugins the whole time, where this token has no access whatsoever. That's the real reason label/PR creation always failed — the previous fix (#1) just stopped hiding it. Set GH_REPO: ${{ github.repository }} at the job level so every `gh` call is unambiguously pinned to this fork regardless of which git remotes exist.
Summary
The
Sync upstreamworkflow has reported green on every scheduled run, butmainhas been stuck on upstream commite46364b(2026-06-17, cursor#135) while the real upstream is now 14 commits / a month ahead at3fe2823(2026-07-14, cursor#156). The workflow never surfaced this because every failure-prone step was wrapped in|| true.Root cause, confirmed from the job logs of run 29565251942:
permissions:block grantedcontents: writeandpull-requests: write, but notissues: write— whichgh label createneeds. That call has been failing on every run, invisibly, because it was piped through2>/dev/null || true.synclabel never actually got created (confirmed via the API —synclabel does not exist in this repo), the subsequentgh pr create --label syncfailed too — also swallowed by|| true.sync/*branch every day (see e.g.sync/pstack-parity-sweep-with-the-private-skill-tree-156-14-commitscurrently in the branch list), but no PR has ever been created —gh pr list --state allreturns zero results for this repo.gh pr merge --autothen silently no-ops too. The job exits 0 throughout, so the run shows "success" while nothing actually syncs.Changes
issues: writeto workflow permissions, so label creation actually succeeds.gh label createto--force(idempotent update-or-create) instead of swallowing stderr — keeps the "already exists" case silent while letting genuine errors surface.gh pr create, verify a PR actually exists for the branch (gh pr view) and fail the job loudly if not, instead of continuing silently on failure.gh pr merge --autointo a visible::warning::annotation instead of a silent no-op, in case auto-merge is also disabled at the repo level.Follow-up for a repo admin
Please double check Settings → General → Pull Requests → "Allow auto-merge" is enabled on this repo. The workflow calls
gh pr merge --auto --rebase, and if that setting is off, PRs will now be created correctly but will need to be merged manually (the new warning annotation will call this out in the run logs if it happens).Test plan
.github/workflows/sync-upstream.ymlYAML parses successfully.synclabel is created.