fix(ci): upstream-sync opens a PR instead of pushing to protected main #2
Reference in New Issue
Block a user
Delete Branch "fix/ci-sync-upstream-pr-not-push-main"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Root cause
The scheduled
sync-upstreamjob's final step didgit push origin main.mainis branch-protected, so the push is declined by the pre-receive hook:
This fails the
Update PATCHED_VERSION.mdstep on every scheduled (cron0 9 * * *) run —sync-upstreamhas been red across runs 25→53 — and thefailing commit status turns
main's combined state red. (Thetestjob isgreen since PR #1 pinned upstream; only the sync lane is broken.)
It also violates the org rule "never push direct to
main" — the version bumpshould go through review like any other change.
Fix
Replace the direct push with a PR flow in the
sync-upstreamjob:PATCHED_VERSION.mdbump to a non-protectedsync/upstream-<sha>branch and open a PR via the Gitea API (
base: main). Respects branchprotection; no more declined push.
sync/upstream-<sha>already exists (PR already open).steps.smoke) and surface it inthe PR body, so the known upstream drift (currently the smoke test fails:
Cannot find module '../shared/net/redact-sensitive-url.js'— the overlayneeds a rebase) is flagged for the reviewer instead of silently warned in logs.
permissions: { contents: write, pull-requests: write }to the job.Token note
PR creation uses
secrets.AUTO_SYNC_TOKEN || secrets.GITHUB_TOKEN.AUTO_SYNC_TOKENis the org's existing sync-bot secret (already used by theshared
gitea-merge-queueworkflow). Required action for the repo owner:ensure
AUTO_SYNC_TOKEN(an org/repo Actions secret withwrite:repository)is available to this repo, or the API PR-create step will fall back to the
auto-injected
GITHUB_TOKEN(which may lack PR-create scope). This is a secretavailability concern, not a code change.
Scope
sync-upstreamruns only onschedule, so this doesn't affect PR/push CI. Thetestjob is unchanged.🤖 Generated with Claude Code
Reviewed for correctness.
sync-upstreamjob'sgit push origin mainwas declined by the branch-protection pre-receive hook on every cron run (! [remote rejected] main -> main (pre-receive hook declined)), failing the job and reddening main's combined status.sync/upstream-<sha>branch and opens a PR via the API — respects branch protection and the no-direct-push-to-main rule, and routes the bump through review.git ls-remote --headsshort-circuits if the sync branch already exists; PR-create accepts 201 or 409.set -euo pipefailis safe here — thegit commitalways has a change to commit (a fresh PATCHED_VERSION.md is written immediately before), and the step only runs when sync_needed=true.steps.smoke) and surfaced in the PR body, so the current upstream drift (the redact-sensitive-url module move that fails the MCP test) is flagged for the reviewer rather than buried in a log warning.if: github.event_name == 'schedule'is unchanged → confirmedskipped(not failed) on this PR's pull_request run.testjob untouched and green.Scoped, correct, no regression to PR/push CI. Approve.
Security review.
schedule(not pull_request_target / not from PR-head), so no untrusted PR code executes with the write token.permissions: { contents: write, pull-requests: write }is the minimum needed and scoped to this job.GITEA_TOKENis sourced fromsecrets.AUTO_SYNC_TOKEN || secrets.GITHUB_TOKEN, passed via env (not interpolated into the shell from an untrusted source); the curl uses it as a bearer header. No secret is echoed (only the HTTP code and response body are printed; PR-create response carries no secret). UPSTREAM_SHA/BRANCH are derived from git rev-parse, not attacker-controlled.No security concerns. Approve.
View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.