Skip to content

Commit 8e4896f

Browse files
feat(sync-main-to-edge): open a PR when direct push can't fast-forward
The reusable sync workflow relies on aormsby/Fork-Sync-With-Upstream-action to fast-forward upstream -> target. That push fails when the target (edge) branch has diverged from upstream or is protected. Previously the job just failed. Now the sync step is continue-on-error and, on failure, we open a PR upstream -> target instead (idempotent — skips if one is already open, and tolerates the no-diff case). Adds pull-requests: write for PR creation. Co-Authored-By: Agent Alex Picard <alex-nsheaps[bot]@users.noreply.github.com>
1 parent 23d303b commit 8e4896f

1 file changed

Lines changed: 32 additions & 1 deletion

File tree

‎.github/workflows/sync-main-to-edge.yaml‎

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ on:
3232

3333
permissions:
3434
contents: write
35+
pull-requests: write
3536

3637
jobs:
3738
plan:
@@ -127,9 +128,14 @@ jobs:
127128
persist-credentials: false
128129
fetch-depth: 0
129130

131+
# The aormsby action fast-forwards upstream -> target. It fails when the
132+
# branches have diverged or when branch protection rejects the push.
133+
# continue-on-error lets us fall back to opening a PR in that case instead
134+
# of failing the whole job.
130135
- name: Sync upstream changes
131136
if: steps.check.outputs.exists == 'true'
132137
id: sync
138+
continue-on-error: true
133139
uses: aormsby/Fork-Sync-With-Upstream-action@83d78e8c4bf524e79b091cf257deba4dee9e60df # v3.4.3
134140
with:
135141
target_sync_branch: ${{ matrix.target }}
@@ -138,10 +144,35 @@ jobs:
138144
upstream_sync_repo: ${{ github.repository }}
139145
test_mode: ${{ inputs.test_mode }}
140146

147+
# When the direct push could not happen (diverged history or branch
148+
# protection), open a PR upstream -> target instead. Idempotent: skips if
149+
# a PR is already open for the same head/base, and tolerates "no diff".
150+
- name: Open PR if direct sync could not push
151+
if: steps.check.outputs.exists == 'true' && steps.sync.outcome == 'failure'
152+
env:
153+
UPSTREAM: ${{ matrix.upstream }}
154+
TARGET: ${{ matrix.target }}
155+
REPO: ${{ github.repository }}
156+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
157+
run: |
158+
set -euo pipefail
159+
existing=$(gh pr list --repo "$REPO" --base "$TARGET" --head "$UPSTREAM" \
160+
--state open --json number -q '.[0].number' || true)
161+
if [ -n "$existing" ]; then
162+
echo "PR #$existing already open for $UPSTREAM -> $TARGET; nothing to do."
163+
exit 0
164+
fi
165+
gh pr create --repo "$REPO" --base "$TARGET" --head "$UPSTREAM" \
166+
--title "sync: $UPSTREAM -> $TARGET" \
167+
--body "Automated sync could not fast-forward \`$TARGET\` from \`$UPSTREAM\` (diverged history or branch protection). Merging via PR instead." \
168+
|| echo "No PR created (possibly no diff between $UPSTREAM and $TARGET)."
169+
141170
- name: Report
142171
if: steps.check.outputs.exists == 'true'
143172
run: |
144-
if [ "${{ steps.sync.outputs.has_new_commits }}" = "true" ]; then
173+
if [ "${{ steps.sync.outcome }}" = "failure" ]; then
174+
echo "Direct sync could not push ${{ matrix.upstream }} -> ${{ matrix.target }}; opened/ensured a PR instead."
175+
elif [ "${{ steps.sync.outputs.has_new_commits }}" = "true" ]; then
145176
echo "Synced new commits from ${{ matrix.upstream }} into ${{ matrix.target }}."
146177
else
147178
echo "${{ matrix.target }} already up-to-date with ${{ matrix.upstream }}."

0 commit comments

Comments
 (0)