fix: make release sync_beta deterministic and bump beta post-release#713
Conversation
Reviewer's GuideUpdates the release sync_beta job to merge main into a temporary branch off beta with deterministic conflict handling for version files, bump beta’s MCPForUnity/package.json to the next patch prerelease after a release, and make the sync PR creation/merge more robust and auto-merge friendly. Sequence diagram for updated sync_beta workflow interactionssequenceDiagram
participant Workflow as sync_beta_job
participant Git as Git_CLI
participant GH as GitHub_CLI
participant Repo as GitHub_Repo
participant PR as Sync_PR
Workflow->>Git: checkout beta (actions/checkout)
Workflow->>Git: fetch origin main beta
Git-->>Workflow: branches main, beta
Workflow->>Git: merge-base --is-ancestor origin/main origin/beta
alt beta up to date
Git-->>Workflow: true
Workflow->>Workflow: mark skipped=true
else beta behind main
Git-->>Workflow: false
Workflow->>Git: create branch sync/main-vNEW_VERSION-into-beta-RUN_ID from origin/beta
Workflow->>Git: merge origin/main --no-ff --no-commit
alt merge clean
Git-->>Workflow: success
else merge conflicts
Git-->>Workflow: conflicts
Workflow->>Git: list conflicted files
Workflow->>Git: for each version file
Workflow->>Git: git checkout --ours MCPForUnity/package.json
Workflow->>Git: git checkout --ours Server/pyproject.toml
Workflow->>Git: git add version files
Workflow->>Git: ensure no remaining conflicts
end
Workflow->>Git: git commit chore: sync main (vNEW_VERSION) into beta
Workflow->>Workflow: compute NEXT_BETA_VERSION = X.Y.(Z+1)-beta.1
Workflow->>Repo: read MCPForUnity/package.json version
alt version != NEXT_BETA_VERSION
Repo-->>Workflow: current beta version
Workflow->>Repo: update package.json version to NEXT_BETA_VERSION
Workflow->>Git: git add MCPForUnity/package.json
Workflow->>Git: git commit chore: set beta version to NEXT_BETA_VERSION
else version already correct
Repo-->>Workflow: NEXT_BETA_VERSION
Workflow->>Workflow: skip extra commit
end
Workflow->>Git: git push origin SYNC_BRANCH
Git-->>Repo: push sync branch
Workflow->>GH: gh pr create base=beta head=SYNC_BRANCH
GH-->>PR: create PR with title and body
PR-->>Workflow: pr_url, pr_number
Workflow->>GH: gh pr merge PR_NUMBER --merge --auto --delete-branch
alt auto merge succeeds
GH-->>Workflow: PR merged
else auto merge fails or pending checks
loop up to 24 attempts
Workflow->>GH: gh pr view PR_NUMBER --json state
GH-->>Workflow: state (e.g. OPEN)
alt state == MERGED
Workflow->>Workflow: exit success
else not merged yet
Workflow->>GH: gh pr merge PR_NUMBER --merge --delete-branch
alt direct merge succeeds
GH-->>Workflow: PR merged
Workflow->>Workflow: exit success
else still not mergeable
Workflow->>Workflow: sleep 5 seconds
end
end
end
Workflow->>GH: final view of PR state
Workflow->>Workflow: fail job if PR not merged
end
end
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
Caution Review failedThe pull request is closed. 📝 WalkthroughWalkthroughImplements beta-aware package update checks in the Unity editor, makes client-config dropdown matching more robust, registers an EditorPref key, and overhauls the release workflow to sync main→beta via a dedicated sync branch with merge conflict handling, version preservation/bump, PR creation, resilient auto-merge polling, tagging, and cleanup. Changes
Sequence DiagramsequenceDiagram
actor Workflow as GitHub Workflow
participant Git as Git
participant MergeHandler as MergeHandler
participant Versioner as Versioner
participant PR as PR Service
Workflow->>Git: fetch origin/main and origin/beta
Git-->>Workflow: branches fetched
Workflow->>Git: compare commits (is beta behind main?)
alt beta up-to-date
Workflow->>Workflow: skip sync
else beta behind
Workflow->>Git: create SYNC_BRANCH from origin/beta
Git-->>Workflow: SYNC_BRANCH created
Workflow->>Git: merge origin/main into SYNC_BRANCH (no-ff, no-commit)
Git-->>MergeHandler: conflict?
alt conflicts
MergeHandler->>MergeHandler: preserve beta prerelease entries (package.json/pyproject)
MergeHandler->>Git: stage resolved files / abort if unresolved
else clean merge
Git-->>Workflow: merge successful
end
Workflow->>Versioner: compute next beta version (X.Y.(Z+1)-beta.1)
Versioner-->>Workflow: updated files
Workflow->>Git: push SYNC_BRANCH
Workflow->>PR: create PR (SYNC_BRANCH → beta) with NEXT_BETA_VERSION output
PR-->>Workflow: PR created
Workflow->>PR: attempt auto-merge
alt auto-merge fails
PR->>PR: poll for mergeability / retry direct merge (up to ~2 min)
end
PR-->>Workflow: PR merged
Workflow->>Git: fetch main, create release tag, delete temp branches
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In @.github/workflows/release.yml:
- Around line 377-385: The workflow updates MCPForUnity/package.json to
NEXT_BETA_VERSION but does not update Server/pyproject.toml, causing a mismatch;
modify the release job to also parse NEXT_BETA_VERSION into a PEP 440 prerelease
string and inline-update Server/pyproject.toml (do not call
tools/update_versions.py), e.g., read NEXT_BETA_VERSION, convert the semver
prerelease suffix into PEP 440 format, replace the version field in
Server/pyproject.toml accordingly, git add/commit the file along with
MCPForUnity/package.json, and ensure commit message references NEW_VERSION and
NEXT_BETA_VERSION for clarity.
🧹 Nitpick comments (2)
.github/workflows/release.yml (2)
342-342: Nit:-mmessage is ignored when--no-commitis used.The commit message on this line is never used because
--no-commitprevents the merge from committing. The actual commit message is supplied on line 368. Consider removing-m "..."here to avoid confusion.Suggested diff
- if git merge origin/main --no-ff --no-commit -m "chore: sync main (v${NEW_VERSION}) into beta"; then + if git merge origin/main --no-ff --no-commit; then
410-441: Merge retry logic is solid; consider adding a sync branch cleanup step.The retry pattern with direct merge attempts is a pragmatic approach given GitHub's eventually-consistent mergeability status. However, unlike the
bumpjob (line 286–294) which has anif: always()cleanup step for its temporary branch, there's no equivalent here for the sync branch. If the merge fails at line 441, the branch and open PR remain.This is acceptable since the branch name includes
GITHUB_RUN_ID(no collisions) and leaving the PR open aids manual investigation — but adding a cleanup step would keep the repo tidy.Optional: add cleanup step
- name: Clean up sync branch if: always() && steps.sync_branch.outputs.skipped != 'true' env: GH_TOKEN: ${{ github.token }} SYNC_BRANCH: ${{ steps.sync_branch.outputs.name }} shell: bash run: | set -euo pipefail git push origin --delete "$SYNC_BRANCH" || true
| CURRENT_BETA_VERSION=$(jq -r '.version' MCPForUnity/package.json) | ||
| if [[ "$CURRENT_BETA_VERSION" != "$NEXT_BETA_VERSION" ]]; then | ||
| jq --arg v "$NEXT_BETA_VERSION" '.version = $v' MCPForUnity/package.json > tmp.json | ||
| mv tmp.json MCPForUnity/package.json | ||
| git add MCPForUnity/package.json | ||
| git commit -m "chore: set beta version to ${NEXT_BETA_VERSION} after release v${NEW_VERSION}" | ||
| else | ||
| echo "Beta version already at target: $NEXT_BETA_VERSION" | ||
| fi |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
echo "=== Check Server/pyproject.toml version format ==="
if [ -f "Server/pyproject.toml" ]; then
cat -n Server/pyproject.toml | head -40
else
echo "File not found at Server/pyproject.toml"
fiRepository: CoplayDev/unity-mcp
Length of output: 1835
🏁 Script executed:
#!/bin/bash
echo "=== Check tools/update_versions.py ==="
if [ -f "tools/update_versions.py" ]; then
cat -n tools/update_versions.py
else
echo "File not found at tools/update_versions.py"
fiRepository: CoplayDev/unity-mcp
Length of output: 11660
🏁 Script executed:
#!/bin/bash
echo "=== Examine the sync_beta job in .github/workflows/release.yml ==="
if [ -f ".github/workflows/release.yml" ]; then
# Get lines around 370-388 for full context
sed -n '350,400p' .github/workflows/release.yml | cat -n
else
echo "Workflow file not found"
fiRepository: CoplayDev/unity-mcp
Length of output: 2653
🏁 Script executed:
#!/bin/bash
echo "=== Check if there are any other version management patterns ==="
rg -n "version\s*=" --type toml --type json | head -20Repository: CoplayDev/unity-mcp
Length of output: 169
Server/pyproject.toml is not updated to the next beta version, creating a version mismatch on the beta branch.
After this step, MCPForUnity/package.json will be set to X.Y.(Z+1)-beta.1, but Server/pyproject.toml will remain at the release version X.Y.Z. Both files should be updated consistently.
Note: tools/update_versions.py is designed for release versions only and does not support prerelease formats, so it cannot be used directly here. Instead, manually update pyproject.toml with the proper PEP 440 prerelease format.
Suggested fix: also update pyproject.toml
CURRENT_BETA_VERSION=$(jq -r '.version' MCPForUnity/package.json)
if [[ "$CURRENT_BETA_VERSION" != "$NEXT_BETA_VERSION" ]]; then
jq --arg v "$NEXT_BETA_VERSION" '.version = $v' MCPForUnity/package.json > tmp.json
mv tmp.json MCPForUnity/package.json
git add MCPForUnity/package.json
+
+ # Keep pyproject.toml in sync (PEP 440 prerelease format)
+ PYPI_BETA_VERSION="${MAJOR}.${MINOR}.${NEXT_PATCH}b1"
+ sed -i "s/^version = .*/version = \"${PYPI_BETA_VERSION}\"/" Server/pyproject.toml
+ git add Server/pyproject.toml
+
git commit -m "chore: set beta version to ${NEXT_BETA_VERSION} after release v${NEW_VERSION}"
else
echo "Beta version already at target: $NEXT_BETA_VERSION"
fi📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| CURRENT_BETA_VERSION=$(jq -r '.version' MCPForUnity/package.json) | |
| if [[ "$CURRENT_BETA_VERSION" != "$NEXT_BETA_VERSION" ]]; then | |
| jq --arg v "$NEXT_BETA_VERSION" '.version = $v' MCPForUnity/package.json > tmp.json | |
| mv tmp.json MCPForUnity/package.json | |
| git add MCPForUnity/package.json | |
| git commit -m "chore: set beta version to ${NEXT_BETA_VERSION} after release v${NEW_VERSION}" | |
| else | |
| echo "Beta version already at target: $NEXT_BETA_VERSION" | |
| fi | |
| CURRENT_BETA_VERSION=$(jq -r '.version' MCPForUnity/package.json) | |
| if [[ "$CURRENT_BETA_VERSION" != "$NEXT_BETA_VERSION" ]]; then | |
| jq --arg v "$NEXT_BETA_VERSION" '.version = $v' MCPForUnity/package.json > tmp.json | |
| mv tmp.json MCPForUnity/package.json | |
| git add MCPForUnity/package.json | |
| # Keep pyproject.toml in sync (PEP 440 prerelease format) | |
| PYPI_BETA_VERSION="${MAJOR}.${MINOR}.${NEXT_PATCH}b1" | |
| sed -i "s/^version = .*/version = \"${PYPI_BETA_VERSION}\"/" Server/pyproject.toml | |
| git add Server/pyproject.toml | |
| git commit -m "chore: set beta version to ${NEXT_BETA_VERSION} after release v${NEW_VERSION}" | |
| else | |
| echo "Beta version already at target: $NEXT_BETA_VERSION" | |
| fi |
🤖 Prompt for AI Agents
In @.github/workflows/release.yml around lines 377 - 385, The workflow updates
MCPForUnity/package.json to NEXT_BETA_VERSION but does not update
Server/pyproject.toml, causing a mismatch; modify the release job to also parse
NEXT_BETA_VERSION into a PEP 440 prerelease string and inline-update
Server/pyproject.toml (do not call tools/update_versions.py), e.g., read
NEXT_BETA_VERSION, convert the semver prerelease suffix into PEP 440 format,
replace the version field in Server/pyproject.toml accordingly, git add/commit
the file along with MCPForUnity/package.json, and ensure commit message
references NEW_VERSION and NEXT_BETA_VERSION for clarity.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@MCPForUnity/Editor/Services/PackageUpdateService.cs`:
- Around line 120-143: GetPrereleaseRank currently returns 5 for unknown labels
which incorrectly ranks unrecognized prerelease labels above rc; change the
switch default in GetPrereleaseRank to return 0 so unknown labels sort
conservatively below alpha/beta/rc (keep the existing check for null/empty
returning 0). Update any comment or docstring near GetPrereleaseRank if present
to reflect that unknown prerelease labels are treated as lowest priority.
🧹 Nitpick comments (2)
MCPForUnity/Editor/Services/PackageUpdateService.cs (1)
145-187: Consider caching the compiledRegexas a static field.
TryParseVersionrecompiles the regex on each call. While not a hot path today, astatic readonly RegexwithRegexOptions.Compiledis a low-effort improvement that prevents future performance surprises if call frequency increases.Proposed refactor
+ private static readonly Regex VersionRegex = new Regex( + @"^(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)(?:-(?<label>[A-Za-z]+)(?:\.(?<number>\d+))?)?$", + RegexOptions.Compiled); + private static bool TryParseVersion(string version, out ParsedVersion parsed) { parsed = default; if (string.IsNullOrWhiteSpace(version)) { return false; } string normalized = version.Trim().TrimStart('v', 'V'); - var match = Regex.Match( - normalized, - @"^(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)(?:-(?<label>[A-Za-z]+)(?:\.(?<number>\d+))?)?$"); + var match = VersionRegex.Match(normalized);MCPForUnity/Editor/Windows/MCPForUnityEditorWindow.cs (1)
325-328:QueueUpdateCheck()on line 327 is redundant —RefreshAllData()on line 326 already calls it.The dedup guard makes this harmless, but the explicit call reads as intentional when it's actually a no-op. Consider removing it to avoid confusion.
Proposed cleanup
// Initial updates RefreshAllData(); - QueueUpdateCheck(); }
| private static int GetPrereleaseRank(string label) | ||
| { | ||
| if (string.IsNullOrEmpty(label)) | ||
| { | ||
| return 0; | ||
| } | ||
|
|
||
| switch (label.ToLowerInvariant()) | ||
| { | ||
| case "a": | ||
| case "alpha": | ||
| return 1; | ||
| case "b": | ||
| case "beta": | ||
| return 2; | ||
| case "rc": | ||
| return 3; | ||
| case "preview": | ||
| case "pre": | ||
| return 4; | ||
| default: | ||
| return 5; | ||
| } | ||
| } |
There was a problem hiding this comment.
Default prerelease rank of 5 for unrecognized labels ranks them higher than rc.
Unknown prerelease labels (e.g., a typo like "gama") would be treated as newer than rc.1, which is counterintuitive. Consider using a lower default (e.g., 0) so unrecognized labels sort conservatively below alpha.
Proposed fix
default:
- return 5;
+ return 0;🤖 Prompt for AI Agents
In `@MCPForUnity/Editor/Services/PackageUpdateService.cs` around lines 120 - 143,
GetPrereleaseRank currently returns 5 for unknown labels which incorrectly ranks
unrecognized prerelease labels above rc; change the switch default in
GetPrereleaseRank to return 0 so unknown labels sort conservatively below
alpha/beta/rc (keep the existing check for null/empty returning 0). Update any
comment or docstring near GetPrereleaseRank if present to reflect that unknown
prerelease labels are treated as lowest priority.
What this PR does
1)
release.ymlsync back tobetais deterministicsync_betanow creates a dedicated sync branch frombeta, then mergesmaininto it in CI.betavalues for:MCPForUnity/package.jsonServer/pyproject.toml2) Post-release beta version is explicitly bumped
X.Y.Zonmain, sync setsbetatoX.Y.(Z+1)-beta.1.beta=9.4.1-beta.6main:9.4.1beta=9.4.2-beta.13) Client dropdown persistence is fixed
newValue(instead of relying on a potentially stale index during callbacks).Idmatching and normalized fallback matching for compatibility.LastSelectedClientIdis now visible in the EditorPrefs inspector window for debugging.4) Update notification feature is wired back up and branch-aware
MCPForUnityEditorWindowis now actively driven byPackageUpdateService.#mainchecks GitHubmain#beta(or prerelease fallback) checks GitHubbeta-beta.N,-alpha.N,-rc.N, etc.).Why
main -> betaPRs were frequently unmergeable due to intentional version divergence.Validation notes
Summary by CodeRabbit
New Features
Bug Fixes
Chores