@@ -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