Skip to content

Commit aa0cde5

Browse files
authored
fix: make release sync_beta deterministic and bump beta post-release (#713)
* fix: make release sync to beta deterministic and bump next beta version * feat: restore client persistence and update notifications * chore: address reviewer nits in sync workflow and update check
1 parent 2a1fe67 commit aa0cde5

File tree

5 files changed

+406
-65
lines changed

5 files changed

+406
-65
lines changed

.github/workflows/release.yml

Lines changed: 102 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -309,47 +309,136 @@ jobs:
309309
contents: write
310310
pull-requests: write
311311
steps:
312-
- name: Checkout main
312+
- name: Checkout beta
313313
uses: actions/checkout@v6
314314
with:
315-
ref: main
315+
ref: beta
316316
fetch-depth: 0
317317

318-
- name: Create PR to merge main into beta
319-
id: sync_pr
318+
- name: Prepare sync branch from beta with merged main
319+
id: sync_branch
320320
env:
321-
GH_TOKEN: ${{ github.token }}
322321
NEW_VERSION: ${{ needs.bump.outputs.new_version }}
323322
shell: bash
324323
run: |
325324
set -euo pipefail
326-
# Check if beta is behind main
327-
git fetch origin beta
325+
git config user.name "GitHub Actions"
326+
git config user.email "[email protected]"
327+
328+
# Fetch both branches so we can build a merge commit in CI.
329+
git fetch origin main beta
328330
if git merge-base --is-ancestor origin/main origin/beta; then
329-
echo "beta is already up to date with main. Skipping PR."
331+
echo "beta is already up to date with main. Skipping sync."
330332
echo "skipped=true" >> "$GITHUB_OUTPUT"
331333
exit 0
332334
fi
333335
336+
SYNC_BRANCH="sync/main-v${NEW_VERSION}-into-beta-${GITHUB_RUN_ID}"
337+
echo "name=$SYNC_BRANCH" >> "$GITHUB_OUTPUT"
338+
echo "skipped=false" >> "$GITHUB_OUTPUT"
339+
340+
git checkout -b "$SYNC_BRANCH" origin/beta
341+
342+
if git merge origin/main --no-ff --no-commit; then
343+
echo "main merged cleanly into sync branch."
344+
else
345+
echo "Merge conflicts detected. Attempting expected conflict resolution for beta version files."
346+
CONFLICTS=$(git diff --name-only --diff-filter=U || true)
347+
if [[ -n "$CONFLICTS" ]]; then
348+
echo "$CONFLICTS"
349+
fi
350+
351+
# Keep beta-side prerelease versions if these files conflict.
352+
for file in MCPForUnity/package.json Server/pyproject.toml; do
353+
if git ls-files -u -- "$file" | grep -q .; then
354+
echo "Keeping beta version for $file"
355+
git checkout --ours -- "$file"
356+
git add "$file"
357+
fi
358+
done
359+
360+
REMAINING=$(git diff --name-only --diff-filter=U || true)
361+
if [[ -n "$REMAINING" ]]; then
362+
echo "Unexpected unresolved conflicts remain:"
363+
echo "$REMAINING"
364+
exit 1
365+
fi
366+
fi
367+
368+
git commit -m "chore: sync main (v${NEW_VERSION}) into beta"
369+
370+
# After releasing X.Y.Z on main, beta should move to X.Y.(Z+1)-beta.1.
371+
IFS='.' read -r MAJOR MINOR PATCH <<< "$NEW_VERSION"
372+
NEXT_PATCH=$((PATCH + 1))
373+
NEXT_BETA_VERSION="${MAJOR}.${MINOR}.${NEXT_PATCH}-beta.1"
374+
echo "beta_version=$NEXT_BETA_VERSION" >> "$GITHUB_OUTPUT"
375+
echo "Setting beta version to $NEXT_BETA_VERSION"
376+
377+
CURRENT_BETA_VERSION=$(jq -r '.version' MCPForUnity/package.json)
378+
if [[ "$CURRENT_BETA_VERSION" != "$NEXT_BETA_VERSION" ]]; then
379+
jq --arg v "$NEXT_BETA_VERSION" '.version = $v' MCPForUnity/package.json > tmp.json
380+
mv tmp.json MCPForUnity/package.json
381+
git add MCPForUnity/package.json
382+
git commit -m "chore: set beta version to ${NEXT_BETA_VERSION} after release v${NEW_VERSION}"
383+
else
384+
echo "Beta version already at target: $NEXT_BETA_VERSION"
385+
fi
386+
387+
echo "Pushing sync branch $SYNC_BRANCH"
388+
git push origin "$SYNC_BRANCH"
389+
390+
- name: Create PR to merge sync branch into beta
391+
if: steps.sync_branch.outputs.skipped != 'true'
392+
id: sync_pr
393+
env:
394+
GH_TOKEN: ${{ github.token }}
395+
NEW_VERSION: ${{ needs.bump.outputs.new_version }}
396+
NEXT_BETA_VERSION: ${{ steps.sync_branch.outputs.beta_version }}
397+
SYNC_BRANCH: ${{ steps.sync_branch.outputs.name }}
398+
shell: bash
399+
run: |
400+
set -euo pipefail
334401
PR_URL=$(gh pr create \
335402
--base beta \
336-
--head main \
403+
--head "$SYNC_BRANCH" \
337404
--title "chore: sync main (v${NEW_VERSION}) into beta" \
338-
--body "Automated sync of version bump from main into beta.")
405+
--body "Automated sync of main back into beta after release v${NEW_VERSION}, including beta version set to ${NEXT_BETA_VERSION}.")
339406
echo "pr_url=$PR_URL" >> "$GITHUB_OUTPUT"
340407
PR_NUMBER=$(echo "$PR_URL" | grep -oE '[0-9]+$')
341408
echo "pr_number=$PR_NUMBER" >> "$GITHUB_OUTPUT"
342-
echo "skipped=false" >> "$GITHUB_OUTPUT"
343409
344410
- name: Merge sync PR
345-
if: steps.sync_pr.outputs.skipped != 'true'
411+
if: steps.sync_branch.outputs.skipped != 'true'
346412
env:
347413
GH_TOKEN: ${{ github.token }}
348414
PR_NUMBER: ${{ steps.sync_pr.outputs.pr_number }}
349415
shell: bash
350416
run: |
351417
set -euo pipefail
352-
gh pr merge "$PR_NUMBER" --merge --no-delete-branch
418+
419+
# Best effort: auto-merge if repository settings allow it.
420+
gh pr merge "$PR_NUMBER" --merge --auto --delete-branch || true
421+
422+
# Retry direct merge for up to 2 minutes while checks settle.
423+
for i in {1..24}; do
424+
STATE=$(gh pr view "$PR_NUMBER" --json state -q '.state')
425+
if [[ "$STATE" == "MERGED" ]]; then
426+
echo "Sync PR merged successfully."
427+
exit 0
428+
fi
429+
430+
if gh pr merge "$PR_NUMBER" --merge --delete-branch >/dev/null 2>&1; then
431+
echo "Sync PR merged successfully."
432+
exit 0
433+
fi
434+
435+
echo "Waiting for sync PR to become mergeable... (state: $STATE)"
436+
sleep 5
437+
done
438+
439+
echo "Sync PR did not merge in time."
440+
gh pr view "$PR_NUMBER" --json state,mergeStateStatus,isDraft -q '{state: .state, mergeStateStatus: .mergeStateStatus, isDraft: .isDraft}'
441+
exit 1
353442
354443
publish_docker:
355444
name: Publish Docker image

0 commit comments

Comments
 (0)