Skip to content

feat: Let uloop launchers use project-pinned CLI versions#1413

Merged
hatayama merged 8 commits into
v3-betafrom
feat/split-dispatcher-release
Jun 27, 2026
Merged

feat: Let uloop launchers use project-pinned CLI versions#1413
hatayama merged 8 commits into
v3-betafrom
feat/split-dispatcher-release

Conversation

@hatayama

@hatayama hatayama commented Jun 27, 2026

Copy link
Copy Markdown
Owner

Summary

  • The global uloop launcher can remain installed while each Unity project runs the CLI version pinned by that project.
  • Dispatcher releases are published separately, with beta update metadata and bridge assets so existing beta installs can move into the split release model.

User Impact

  • Users no longer need to replace the global launcher every time only the project CLI changes.
  • Existing beta launchers can self-update instead of getting stuck when a project requires dispatcher 3.0.0.
  • Unity setup now distinguishes dispatcher installs from legacy CLI binaries, reducing false positives during PATH setup.

Changes

  • Split native CLI and dispatcher contract metadata, binaries, release assets, and publish workflows.
  • Added dispatcher release packaging, verification, target resolution, and version-bump checks.
  • Updated installer, updater, and release automation paths for dispatcher-specific releases.
  • Added legacy-compatible CLI release assets so older beta launchers can update safely.

Verification

  • scripts/check-go-cli.sh
  • scripts/package-go-cli.sh && scripts/verify-native-cli-release-assets.sh
  • scripts/package-dispatcher.sh && scripts/verify-dispatcher-release-assets.sh
  • scripts/test-resolve-dispatcher-release-target.sh && scripts/test-sync-release-please-package-releases.sh && scripts/test-dispatcher-publish-workflow.sh
  • scripts/test-resolve-native-cli-release-target.sh && scripts/test-native-cli-publish-workflow.sh
  • Unity compile with zero warnings
  • Targeted EditMode tests for CLI install, setup, detection, and pin sync
  • /Users/a12115/dotfiles/.claude/skills/autoreview/scripts/autoreview --mode branch --base origin/v3-beta

Review in cubic

hatayama added 5 commits June 27, 2026 09:51
Give the long-lived dispatcher its own contract, assets, and publish workflow so regular CLI releases can ship only the project-local binary. Point setup/update/install flows at dispatcher releases, keep real CLI downloads on cli-v tags, and add guards/tests so dispatcher-facing changes require an intentional dispatcherVersion bump.
Parse dispatcher version JSON from the global uloop command and only allow dispatcher detections to satisfy path setup. Legacy pre-split CLIs can still surface their version for UI context, but no longer provide protocol compatibility that would block the required dispatcher update.
Start the dispatcher stream at 3.0.0 so pre-split 3.0.0-beta global binaries compare older and enter the self-update path. Also mirror the native CLI release tag integrity check in dispatcher publishing so uploaded assets cannot drift from the tag target.
Create and publish dispatcher *-beta.* tags with GitHub prerelease metadata so installer channel selection keeps distinguishing stable and beta releases.
Publish legacy uloop-* archives on CLI releases so existing beta dispatchers can reach the split dispatcher stream through their old self-update path.
@coderabbitai

coderabbitai Bot commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@hatayama, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 8 minutes and 8 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more credits in the billing tab to continue.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a7e53c7a-2497-4c0c-9be6-38b6401ac2da

📥 Commits

Reviewing files that changed from the base of the PR and between d44b8ec and f7fc82f.

📒 Files selected for processing (15)
  • .github/workflows/dispatcher-publish.yml
  • Assets/Tests/Editor/CliInstallationDetectorTests.cs
  • Packages/src/Editor/Domain/CliConstants.cs
  • Packages/src/Editor/Infrastructure/CLI/CliInstallationDetector.cs
  • cli/internal/automation/dispatcher_version_bump_guard.go
  • cli/internal/automation/dispatcher_version_bump_guard_test.go
  • cli/internal/cli/help_test.go
  • cli/internal/cli/run_help.go
  • cli/internal/cli/update_test.go
  • cli/internal/update/command.go
  • scripts/resolve-dispatcher-release-target.sh
  • scripts/sync-release-please-package-releases.sh
  • scripts/test-dispatcher-publish-workflow.sh
  • scripts/test-resolve-dispatcher-release-target.sh
  • scripts/test-sync-release-please-package-releases.sh
📝 Walkthrough

Walkthrough

The PR separates dispatcher contract/version metadata from the CLI contract, switches editor and CLI flows to dispatcher-specific versions and tags, adds dispatcher version-bump and minimum-version guards, and introduces dispatcher publish, verification, and sync scripts.

Changes

Dispatcher release flow

Layer / File(s) Summary
Contracts and version pins
cli/contract.go, cli/contract.json, cli/dispatcher-contract.json, cli/contract_test.go, Packages/src/Editor/Domain/CliConstants.cs, Packages/src/cli-pin.json, .uloop/cli-pin.json, cli/protocol_version_consistency_test.go
CLI and dispatcher contract shapes, shared constants, and pin files now separate dispatcher metadata from the CLI contract and validate the new dispatcher fields.
Editor setup and installation
Packages/src/Editor/Application/CliSetupApplicationService.cs, Assets/Tests/Editor/CliSetupApplicationServiceTests.cs, Packages/src/Editor/Infrastructure/CLI/CliInstallationDetector.cs, Assets/Tests/Editor/CliInstallationDetectorTests.cs, Packages/src/Editor/Infrastructure/CLI/NativeCliInstaller.cs, Assets/Tests/Editor/NativeCliInstallerTests.cs
Editor setup, detection, and installer logic now use dispatcher-specific versions, tags, and protocol detection.
CLI runtime and updates
cli/internal/cli/*, cli/internal/update/*
Dispatcher info output, update selection, tag normalization, pin parsing, and archive extraction now use dispatcher metadata throughout the CLI runtime and update helpers.
Automation guards and PR checks
cli/cmd/check-dispatcher-version-bump/main.go, cli/internal/automation/*, .github/workflows/build-and-test.yml
The new dispatcher version-bump guard, minimum-version guard, protocol asset requirements, and release-PR flow are wired into automation and CI.
Release packaging and publish scripts
.github/workflows/dispatcher-publish.yml, .github/workflows/native-cli-publish.yml, scripts/package-*.sh, scripts/resolve-*.sh, scripts/sync-release-please-package-releases.sh, scripts/verify-*.sh, scripts/install.sh, scripts/test-*.sh
Dispatcher release packaging, target resolution, publish orchestration, asset verification, release syncing, and the related shell tests now target dispatcher artifacts.

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~90+ minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 8.10% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: letting launchers use project-pinned CLI versions.
Description check ✅ Passed The description is directly about dispatcher/CLI split releases and project-pinned versions, matching the changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/split-dispatcher-release

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

5 issues found across 60 files

Note: This PR contains a large number of files. cubic only reviews up to 40 files per PR, so some files may not have been reviewed. cubic prioritizes the most important files to review.
On a pro plan you can use ultrareview for larger PRs.

Re-trigger cubic

Comment thread Packages/src/Editor/Infrastructure/CLI/CliInstallationDetector.cs
Comment thread cli/internal/automation/dispatcher_version_bump_guard.go Outdated
Comment thread Packages/src/Editor/Infrastructure/CLI/NativeCliInstaller.cs
Comment thread scripts/resolve-dispatcher-release-target.sh
Comment thread scripts/sync-release-please-package-releases.sh Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
cli/internal/cli/dispatcher_pin.go (1)

155-174: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Keep the CliConstants.cs fallback compatible with older packages.

This fallback path is what lets the dispatcher work with legacy project layouts that do not have a dispatcher pin yet. Requiring MINIMUM_REQUIRED_DISPATCHER_VERSION here turns those projects into a hard error during loadDispatcherPin, so the launcher can no longer start them at all. Please keep the new constant optional in this fallback path and derive MinimumDispatcherVersion from the existing CLI minimum when it is absent.

🩹 Suggested fix
 	dispatcherVersionMatch := dispatcherMinimumVersionPattern.FindStringSubmatch(text)
-	if len(dispatcherVersionMatch) != 2 {
-		return dispatcherPin{}, fmt.Errorf("%s does not define MINIMUM_REQUIRED_DISPATCHER_VERSION", constantsPath)
-	}
-	minimumDispatcherVersion := normalizeDispatcherVersion(dispatcherVersionMatch[1])
-	if err := validateDispatcherCLIVersion(minimumDispatcherVersion); err != nil {
-		return dispatcherPin{}, fmt.Errorf("%s defines invalid MINIMUM_REQUIRED_DISPATCHER_VERSION: %w", constantsPath, err)
+	minimumDispatcherVersion := cliVersion
+	if len(dispatcherVersionMatch) == 2 {
+		minimumDispatcherVersion = normalizeDispatcherVersion(dispatcherVersionMatch[1])
+		if err := validateDispatcherCLIVersion(minimumDispatcherVersion); err != nil {
+			return dispatcherPin{}, fmt.Errorf("%s defines invalid MINIMUM_REQUIRED_DISPATCHER_VERSION: %w", constantsPath, err)
+		}
 	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cli/internal/cli/dispatcher_pin.go` around lines 155 - 174, The
`loadDispatcherPin` fallback path in `dispatcher_pin.go` should stay compatible
with legacy `CliConstants.cs` files that do not define
`MINIMUM_REQUIRED_DISPATCHER_VERSION`. Update the parsing logic so this constant
is optional in the fallback branch: if it is missing, derive
`MinimumDispatcherVersion` from the existing CLI minimum instead of returning an
error. Keep the validation for the new constant when present, and adjust the
`dispatcherPin` construction so older packages still load successfully.
🧹 Nitpick comments (1)
.github/workflows/build-and-test.yml (1)

68-71: 🔒 Security & Privacy | 🔵 Trivial | 💤 Low value

Consider passing github.base_ref via env instead of inlining it in run.

zizmor flags template expansion of ${{ github.base_ref }} directly into the shell command. While base_ref is the upstream PR base branch (must already exist, so the practical risk is low and this mirrors the existing steps at Lines 54 and 61), moving it into an env var avoids the injection class entirely.

🔒 Optional hardening
       - name: Check dispatcher version bump
         if: github.event_name == 'pull_request'
         working-directory: cli
-        run: go run ./cmd/check-dispatcher-version-bump --base "origin/${{ github.base_ref }}" --head HEAD
+        env:
+          BASE_REF: origin/${{ github.base_ref }}
+        run: go run ./cmd/check-dispatcher-version-bump --base "$BASE_REF" --head HEAD
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/build-and-test.yml around lines 68 - 71, The dispatcher
version bump step in the workflow is expanding github.base_ref directly inside
the shell command, which should be avoided. Move github.base_ref into an env
variable on the Check dispatcher version bump step, then reference that env var
in the go run invocation for cmd/check-dispatcher-version-bump so the command no
longer inlines the template expression.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Assets/Tests/Editor/CliInstallationDetectorTests.cs`:
- Around line 213-229: The CLI installation test is only asserting presence of
the protocol value and can miss dispatcher contract-generation mismatches.
Update the assertion in CliInstallationDetectorTests around
ParseShellCliInstallationOutput to verify the parsed DispatcherContractVersion
exactly, or compare it against a dispatcher-specific required contract constant
instead of CliConstants.REQUIRED_CLI_PROTOCOL_VERSION. Also add a negative test
case in the same CliInstallationDetector test area that fails when the
dispatcher contract version differs from the required generation.

In `@cli/internal/cli/run_help.go`:
- Around line 63-69: Update printLauncherHelp so the help text matches the new
split model: the description passed into printMainHelp should no longer say
"Native CLI" now that this entrypoint shows dispatcherVersion. Use a
launcher/dispatcher-oriented description that clearly distinguishes it from the
Unity tool CLI, and keep the change localized to printLauncherHelp and any
related help wording it feeds into printMainHelp.

In `@cli/internal/update/command.go`:
- Line 69: The target normalization path in the update command is preserving the
legacy CLI prefix, which causes dispatcher targets to be built with an extra cli
marker. Update the logic around DispatcherReleaseTag and NormalizeTargetVersion
so legacy inputs like cli-v3.0.0 are stripped to the base version before the
dispatcher tag is assembled, ensuring migrated commands resolve to
dispatcher-v3.0.0.

In `@Packages/src/Editor/Infrastructure/CLI/CliInstallationDetector.cs`:
- Around line 390-405: The ParseDispatcherContract method is ignoring the parsed
dispatcher protocol version and always returning
CliConstants.REQUIRED_CLI_PROTOCOL_VERSION, which hides mismatches. Update the
CliInstallationDetector.ParseDispatcherContract logic to use
dispatcherContractVersion after ReadProtocolVersion succeeds, and only return a
successful CliInstallationDetection when the parsed protocol matches the
required version; otherwise return the failure/null detection path. Keep the
existing null/empty checks on dispatcherVersion and dispatcherContractVersion,
but ensure the returned detection reflects the actual parsed protocol value
rather than a constant.

In `@Packages/src/Editor/Infrastructure/CLI/NativeCliInstaller.cs`:
- Around line 957-965: Update the release-tag normalization logic in
NativeCliInstaller.BuildReleaseTag so legacy cli-v... tags are rewritten to the
dispatcher prefix instead of being blindly prefixed. In the BuildReleaseTag
flow, keep the existing DispatcherReleaseTagPrefix passthrough, then add a
specific branch for the old CliConstants.RELEASE_TAG_PREFIX that replaces it
with CliConstants.DISPATCHER_RELEASE_TAG_PREFIX before the final bare-v
fallback. This ensures values like cli-v3.0.0 map to the correct dispatcher tag
rather than dispatcher-vcli-v3.0.0.

In `@scripts/verify-native-cli-release-assets.sh`:
- Around line 6-11: The advertised required asset set in the release
verification script is missing the legacy uloop bridge archives, even though the
completeness check still expects them. Update the EXPECTED_ASSETS list in
verify-native-cli-release-assets.sh to include the legacy uloop-* tar/zip
artifacts and their .sha256 files, or refactor the script to maintain separate
local and remote required asset lists while keeping the older-beta-launcher
bridge assets required by the readiness check.

---

Outside diff comments:
In `@cli/internal/cli/dispatcher_pin.go`:
- Around line 155-174: The `loadDispatcherPin` fallback path in
`dispatcher_pin.go` should stay compatible with legacy `CliConstants.cs` files
that do not define `MINIMUM_REQUIRED_DISPATCHER_VERSION`. Update the parsing
logic so this constant is optional in the fallback branch: if it is missing,
derive `MinimumDispatcherVersion` from the existing CLI minimum instead of
returning an error. Keep the validation for the new constant when present, and
adjust the `dispatcherPin` construction so older packages still load
successfully.

---

Nitpick comments:
In @.github/workflows/build-and-test.yml:
- Around line 68-71: The dispatcher version bump step in the workflow is
expanding github.base_ref directly inside the shell command, which should be
avoided. Move github.base_ref into an env variable on the Check dispatcher
version bump step, then reference that env var in the go run invocation for
cmd/check-dispatcher-version-bump so the command no longer inlines the template
expression.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 4c43d7bb-18a7-487e-a749-55e5e82ee620

📥 Commits

Reviewing files that changed from the base of the PR and between 1f69e08 and 69768ed.

⛔ Files ignored due to path filters (3)
  • scripts/check-release-installer.ps1 is excluded by none and included by none
  • scripts/install.ps1 is excluded by none and included by none
  • scripts/test-check-release-installer.ps1 is excluded by none and included by none
📒 Files selected for processing (57)
  • .github/workflows/build-and-test.yml
  • .github/workflows/dispatcher-publish.yml
  • .github/workflows/native-cli-publish.yml
  • .uloop/cli-pin.json
  • Assets/Tests/Editor/CliInstallationDetectorTests.cs
  • Assets/Tests/Editor/CliSetupApplicationServiceTests.cs
  • Assets/Tests/Editor/NativeCliInstallerTests.cs
  • Packages/src/Editor/Application/CliSetupApplicationService.cs
  • Packages/src/Editor/Domain/CliConstants.cs
  • Packages/src/Editor/Infrastructure/CLI/CliInstallationDetector.cs
  • Packages/src/Editor/Infrastructure/CLI/NativeCliInstaller.cs
  • Packages/src/cli-pin.json
  • cli/cmd/check-dispatcher-version-bump/main.go
  • cli/contract.go
  • cli/contract.json
  • cli/contract_test.go
  • cli/dispatcher-contract.json
  • cli/internal/automation/dispatcher_minimum_version_guard.go
  • cli/internal/automation/dispatcher_minimum_version_guard_test.go
  • cli/internal/automation/dispatcher_version_bump_guard.go
  • cli/internal/automation/dispatcher_version_bump_guard_test.go
  • cli/internal/automation/protocol_minimum_version_guard.go
  • cli/internal/automation/protocol_minimum_version_guard_test.go
  • cli/internal/automation/release_pr_checks.go
  • cli/internal/automation/release_pr_checks_test.go
  • cli/internal/automation/release_pr_dispatcher_sync.go
  • cli/internal/cli/dispatcher.go
  • cli/internal/cli/dispatcher_download.go
  • cli/internal/cli/dispatcher_pin.go
  • cli/internal/cli/dispatcher_test.go
  • cli/internal/cli/run.go
  • cli/internal/cli/run_dispatch.go
  • cli/internal/cli/run_help.go
  • cli/internal/cli/tools.go
  • cli/internal/cli/update.go
  • cli/internal/cli/update_test.go
  • cli/internal/update/command.go
  • cli/internal/update/installer.go
  • cli/internal/update/installer_test.go
  • cli/protocol_version_consistency_test.go
  • scripts/install.sh
  • scripts/package-dispatcher.sh
  • scripts/package-go-cli.sh
  • scripts/resolve-dispatcher-release-target.sh
  • scripts/resolve-native-cli-release-target.sh
  • scripts/sync-release-please-package-releases.sh
  • scripts/test-dispatcher-publish-workflow.sh
  • scripts/test-install-release-filter.sh
  • scripts/test-native-cli-publish-workflow.sh
  • scripts/test-release-please-config.sh
  • scripts/test-resolve-dispatcher-release-target.sh
  • scripts/test-resolve-native-cli-release-target.sh
  • scripts/test-sync-release-please-package-releases.sh
  • scripts/test-verify-dispatcher-release-assets.sh
  • scripts/test-verify-native-cli-release-assets.sh
  • scripts/verify-dispatcher-release-assets.sh
  • scripts/verify-native-cli-release-assets.sh
💤 Files with no reviewable changes (6)
  • cli/internal/automation/release_pr_dispatcher_sync.go
  • cli/contract.json
  • scripts/resolve-native-cli-release-target.sh
  • cli/internal/automation/release_pr_checks.go
  • scripts/test-native-cli-publish-workflow.sh
  • .github/workflows/native-cli-publish.yml

Comment thread Assets/Tests/Editor/CliInstallationDetectorTests.cs
Comment thread cli/internal/cli/run_help.go
Comment thread cli/internal/update/command.go
Comment thread Packages/src/Editor/Infrastructure/CLI/CliInstallationDetector.cs
Comment thread Packages/src/Editor/Infrastructure/CLI/NativeCliInstaller.cs
Comment thread scripts/verify-native-cli-release-assets.sh
hatayama added 2 commits June 27, 2026 11:36
Prevent the split release tests from depending on CLI and dispatcher versions being different, and keep legacy CLI tag inputs from generating invalid dispatcher installer tags.

- restore coverage for bridge archives that contain both dispatcher and real CLI binaries
- document why setup reports dispatcher releases through existing CLI setup APIs
Tighten dispatcher contract compatibility checks, preserve failed release-asset list commands as not-ready states, and normalize migrated CLI release tags before dispatcher updates.

- reject mismatched dispatcher contract generations during setup detection
- fail dispatcher version guards on unexpected base read errors
- clarify launcher help text for the split dispatcher model
Use the existing dispatcher release tag commit when a release already exists so asset-only follow-up publishes do not compare a stable tag against a later branch head. Also serialize dispatcher publish runs per branch and keep draft state under RUNNER_TEMP.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant