Skip to content

chore: Manage dispatcher releases with Release Please#1462

Merged
hatayama merged 9 commits into
v3-betafrom
feat/dispatcher-release-please
Jul 3, 2026
Merged

chore: Manage dispatcher releases with Release Please#1462
hatayama merged 9 commits into
v3-betafrom
feat/dispatcher-release-please

Conversation

@hatayama

@hatayama hatayama commented Jul 3, 2026

Copy link
Copy Markdown
Owner

Summary

  • Dispatcher version bumps and changelogs are now generated by Release Please, using the same flow as the project runner and the Unity package.
  • Shared-input changes (common module sources, installer scripts) can no longer silently miss a release: a new CI guard requires the matching release trigger stamps, refreshed by one command.

User Impact

  • Before: every dispatcher change needed a manual dispatcherVersion bump, and a common/ change could reach the project runner release while silently missing the dispatcher release (or vice versa).
  • After: merging a dispatcher change produces a Release Please release PR with a generated changelog; merging that release PR publishes dispatcher-v<version> with all assets exactly as before. common/ and installer changes fail PR CI until scripts/stamp-release-inputs.sh marks every affected release.

Changes

  • release-please-config.json gains a third package dispatcher (component dispatcher, prerelease beta, dispatcher-v<version> tags, stamps dispatcher-contract.json $.dispatcherVersion). The manifest is seeded at the current 3.0.1-beta.11 so the tag sequence continues, and dispatcher/CHANGELOG.md anchors future changelogs.
  • sync-release-please-package-releases.sh skips the dispatcher package. dispatcher-publish keeps owning the tag/draft/assets/publish flow; a sync-created release would go public before its assets upload. dispatcher-publish itself needs no changes because its resolve script already treats an existing asset-less release as upload-only work.
  • check-dispatcher-version-bump is replaced by two focused guards: check-release-triggers fails when out-of-package release inputs (non-test common/**/*.go, common/go.mod, common/go.sum, installer scripts) change without a companion change under each consuming package root, and check-dispatcher-contract keeps the dispatcherContractVersion regression detection.
  • scripts/stamp-release-inputs.sh writes shared-inputs-stamp.json under project-runner/ and dispatcher/ from a deterministic hash of the shared inputs (path/content pairs, so renames restamp too).
  • AGENTS.md documents the new rules, and dispatcherVersion joins the release-please-only stamp list.

Verification

  • scripts/check-go-cli.sh (fmt, vet, lint, tests, builds across all four Go modules)
  • scripts/test-release-please-config.sh, test-sync-release-please-package-releases.sh, test-stamp-release-inputs.sh, test-resolve-dispatcher-release-target.sh, test-resolve-native-cli-release-target.sh, test-native-cli-publish-workflow.sh
  • Live guard check: a fake common-only commit fails check-release-triggers with the stamp-command hint, passes after running scripts/stamp-release-inputs.sh, and the branch itself passes both new guards against origin/v3-beta.

Review in cubic

hatayama added 3 commits July 3, 2026 14:33
Add a dispatcher package to release-please-config.json (component
dispatcher, prerelease beta, dispatcher-v<version> tags) with
dispatcher-contract.json dispatcherVersion as a stamped extra-file, seed
the manifest with the current 3.0.1-beta.11 so the tag sequence
continues, and create dispatcher/CHANGELOG.md as the changelog anchor.

The package release sync must skip the dispatcher package: dispatcher-
publish owns the tag/draft/assets/publish flow, and a sync-created
release would go public before its assets are uploaded. dispatcher-
publish itself needs no changes because its resolve script already
treats an existing asset-less release as upload-only work.
release-please now stamps dispatcherVersion, so requiring a manual bump
in every dispatcher PR would fail all of them. The guard splits into two
focused checks:

- check-release-triggers fails when out-of-package release inputs
  (non-test common module sources, installer scripts) change without a
  companion change under each consuming package root, because
  release-please attributes commits by package root path only.
- check-dispatcher-contract keeps the dispatcherContractVersion
  regression detection, including the legacy-path fallback for base refs
  that predate the directory split.

scripts/stamp-release-inputs.sh writes shared-inputs-stamp.json under
project-runner/ and dispatcher/ from a deterministic hash of the shared
inputs, giving common and installer changes a one-command release
trigger. Hashing covers path/content pairs so renames restamp too.
dispatcherVersion joined the release-please stamp list, and the
Dispatcher Release Inputs section now describes the shared-release-input
trigger rules and the stamp command instead of the retired manual bump
requirement.
@coderabbitai

coderabbitai Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

An error occurred during the review process. Please try again later.

📝 Walkthrough

Walkthrough

This PR adds release-trigger and dispatcher-contract guards, generates shared-input stamp files, configures dispatcher as a release-please package, and updates CI workflow and governance documentation.

Changes

Dispatcher release automation

Layer / File(s) Summary
Release trigger guard implementation and tests
tools/release-automation/internal/automation/release_trigger_guard.go, tools/release-automation/internal/automation/release_trigger_guard_test.go, tools/release-automation/cmd/check-release-triggers/main.go
Defines release-trigger matching rules, adds the guard CLI entrypoint, and covers trigger-root requirements, path normalization, and warning formatting in tests.
Dispatcher contract guard implementation and tests
tools/release-automation/internal/automation/dispatcher_contract_guard.go, tools/release-automation/internal/automation/dispatcher_contract_guard_test.go, tools/release-automation/cmd/check-dispatcher-contract/main.go
Defines dispatcher contract guard types and parsing, wires the new guard entrypoint, and adds tests for version decreases, initial introduction, parse validation, and warning formatting.
Shared-inputs stamping script and tests
scripts/stamp-release-inputs.sh, scripts/test-stamp-release-inputs.sh, dispatcher/shared-inputs-stamp.json, project-runner/shared-inputs-stamp.json
Adds the shared-input hashing script, writes dispatcher and project-runner stamp JSON files, and validates hashing behavior with fixture-based shell tests.
Release-please dispatcher package configuration
release-please-config.json, .release-please-manifest.json, dispatcher/CHANGELOG.md, scripts/sync-release-please-package-releases.sh, scripts/test-release-please-config.sh, scripts/test-sync-release-please-package-releases.sh, scripts/sync-published-release-pr-labels.sh, scripts/test-sync-published-release-pr-labels.sh
Updates release-please configuration and manifest entries for dispatcher, adds dispatcher changelog generation, excludes dispatcher from package sync, and expands related shell tests and label mapping.
CI workflow and governance docs
.github/workflows/build-and-test.yml, AGENTS.md
Replaces the workflow dispatcher check step with release-trigger and dispatcher-contract checks, and revises AGENTS.md release governance guidance for stamped fields and shared inputs.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant GitHubActions
  participant check-release-triggers
  participant check-dispatcher-contract
  participant GitRepo
  GitHubActions->>check-release-triggers: run on pull_request
  check-release-triggers->>GitRepo: diff base..head
  GitRepo-->>check-release-triggers: changed files
  check-release-triggers->>check-release-triggers: match shared inputs and trigger roots
  GitHubActions->>check-dispatcher-contract: run on pull_request
  check-dispatcher-contract->>GitRepo: read dispatcher contract at base and head
  GitRepo-->>check-dispatcher-contract: contract JSON
  check-dispatcher-contract->>check-dispatcher-contract: compare dispatcherContractVersion values
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: moving dispatcher release management to Release Please.
Description check ✅ Passed The description is directly related to the changeset and accurately describes the release automation and CI updates.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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/dispatcher-release-please

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.

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

🧹 Nitpick comments (1)
.github/workflows/build-and-test.yml (1)

68-76: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Template-injection pattern replicated from existing steps.

--base "origin/${{ github.base_ref }}" expands the ref directly into the shell command at YAML-render time (flagged by zizmor). This mirrors the existing pattern at lines 54 and 61, so it's not a new risk class introduced here, but each additional occurrence widens the exposed surface. Consider passing the ref via an env: var and referencing $BASE_REF in run: to avoid template expansion into the shell command.

🔒 Proposed fix using env indirection
       - name: Check release triggers
         if: github.event_name == 'pull_request'
         working-directory: tools/release-automation
-        run: go run ./cmd/check-release-triggers --base "origin/${{ github.base_ref }}" --head HEAD
+        env:
+          BASE_REF: ${{ github.base_ref }}
+        run: go run ./cmd/check-release-triggers --base "origin/$BASE_REF" --head HEAD

       - name: Check dispatcher contract
         if: github.event_name == 'pull_request'
         working-directory: tools/release-automation
-        run: go run ./cmd/check-dispatcher-contract --base "origin/${{ github.base_ref }}" --head HEAD
+        env:
+          BASE_REF: ${{ github.base_ref }}
+        run: go run ./cmd/check-dispatcher-contract --base "origin/$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 - 76, The
release-automation workflow steps for Check release triggers and Check
dispatcher contract currently inline github.base_ref directly in the run
command, which repeats the template-injection pattern. Update these steps to
pass the base ref through an env variable on the job/step and reference that
variable in the go run arguments instead of expanding origin/${{ github.base_ref
}} inside the shell command, matching the surrounding workflow style while
avoiding YAML-to-shell interpolation.

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 `@tools/release-automation/internal/automation/dispatcher_contract_guard.go`:
- Around line 131-149: The semver check in ParseDispatcherContractValues is
currently using sharedversion.Compare with the same value twice, which can
incorrectly accept malformed dispatcherVersion values. Replace that check with a
direct semver validation helper in ParseDispatcherContractValues so the
dispatcherVersion field is validated for format before continuing, and keep the
existing error message path in dispatcherContractGuard for invalid values.

---

Nitpick comments:
In @.github/workflows/build-and-test.yml:
- Around line 68-76: The release-automation workflow steps for Check release
triggers and Check dispatcher contract currently inline github.base_ref directly
in the run command, which repeats the template-injection pattern. Update these
steps to pass the base ref through an env variable on the job/step and reference
that variable in the go run arguments instead of expanding origin/${{
github.base_ref }} inside the shell command, matching the surrounding workflow
style while avoiding YAML-to-shell interpolation.
🪄 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: b8c234f0-ec82-4afc-968d-25c4bd23aa64

📥 Commits

Reviewing files that changed from the base of the PR and between 1efab44 and c5cb696.

📒 Files selected for processing (20)
  • .github/workflows/build-and-test.yml
  • .release-please-manifest.json
  • AGENTS.md
  • dispatcher/CHANGELOG.md
  • dispatcher/shared-inputs-stamp.json
  • project-runner/shared-inputs-stamp.json
  • release-please-config.json
  • scripts/stamp-release-inputs.sh
  • scripts/sync-release-please-package-releases.sh
  • scripts/test-release-please-config.sh
  • scripts/test-stamp-release-inputs.sh
  • scripts/test-sync-release-please-package-releases.sh
  • tools/release-automation/cmd/check-dispatcher-contract/main.go
  • tools/release-automation/cmd/check-release-triggers/main.go
  • tools/release-automation/internal/automation/dispatcher_contract_guard.go
  • tools/release-automation/internal/automation/dispatcher_contract_guard_test.go
  • tools/release-automation/internal/automation/dispatcher_version_bump_guard.go
  • tools/release-automation/internal/automation/dispatcher_version_bump_guard_test.go
  • tools/release-automation/internal/automation/release_trigger_guard.go
  • tools/release-automation/internal/automation/release_trigger_guard_test.go
💤 Files with no reviewable changes (2)
  • tools/release-automation/internal/automation/dispatcher_version_bump_guard.go
  • tools/release-automation/internal/automation/dispatcher_version_bump_guard_test.go

CI gofumpt rejects a blank line between an err-returning assignment and
its err check. The local source check missed these because the new test
file was still untracked when it ran.

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

2 issues found and verified against the latest diff

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread scripts/test-stamp-release-inputs.sh
Comment thread scripts/test-stamp-release-inputs.sh Outdated
Review feedback on the stamp-release-inputs test: the installer-only
scenario changed only install.sh, so dropping install.ps1 from the
dispatcher stamp inputs would regress unnoticed on Windows; a dedicated
ps1-only case now guards that path. run_stamp also dumps its captured
stdout/stderr on failure because the temp files vanish with the cleanup
trap, which left CI failures undiagnosable.
hatayama added 4 commits July 3, 2026 16:21
release_tag_from_body only knew unity-package and uloop-project-runner,
so a merged dispatcher release PR resolved to an empty tag, fell through
the title fallback (branch-scoped titles carry no version), and stayed
stuck on "autorelease: pending" forever. Map dispatcher summaries to
dispatcher-v<version> so the repair step promotes them like the other
components.
POSIX pipelines report only the last command's status, so a mid-list
git hash-object failure previously let `git hash-object --stdin` hash
the truncated manifest and write a plausible-looking but wrong stamp
with exit 0. Route the manifest through a command substitution so any
hash failure aborts the run before a stamp is written. The manifest
format is unchanged, so existing stamp hashes stay stable (verified by
restamping this checkout with no diff).
The guard only compares dispatcherContractVersion; the DispatcherVersion
field was parsed and semver-validated but never consumed by the analyze,
needs-action, or warning paths. The format check also duplicated
TestDispatcherContractProvidesRuntimeVersion in the dispatcher module,
which already pins the semver format of the same contract file on every
PR. Keep only the dispatcherContractVersion extraction the guard uses.
The trigger rules are re-encoded as shell in stamp-release-inputs.sh.
With two rules the cross-references and the stamp behavior tests keep
the implementations aligned; record the agreed follow-up that a third
rule should bring an equivalence test between the two encodings.
@hatayama
hatayama merged commit 39b6ea5 into v3-beta Jul 3, 2026
10 checks passed
@hatayama
hatayama deleted the feat/dispatcher-release-please branch July 3, 2026 07:40
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