chore: standardize release process#209
Merged
Merged
Conversation
Adds the shared release infrastructure (prepare-release, release-<ecosystem>, pr-title-check workflows + modules.json + generate-changelog.sh) so this repo's release flow matches the other Mixpanel SDK repositories. See: https://www.notion.so/348e0ba925628029af63c779caa835f9
The previous form `select($t | startswith(.value.tag_prefix))` rebinds the context inside `select` so `.value` is no longer the entry — jq errors with "Cannot index string with string \"value\"" and every tag push fails. Bind the prefix first via `.value.tag_prefix as $p` so the comparison runs against the captured variable.
The legacy scripts/release.py bumped both package.json and the `MixpanelUnityVersion` constant in Mixpanel/MixpanelAPI.cs (the value the SDK reports as `$lib_version` on every event sent to Mixpanel). The first pass of the standardized prepare-release workflow only bumped package.json, so the C# constant would lag behind every release and the SDK would report a stale version to Mixpanel. Mirror the Flutter PR's `version_files` mechanism: list extra files in modules.json, do a literal `OLD_VERSION -> VERSION` replace in the prepare workflow, and refuse to publish in release-upm.yml if any version_files entry contains a semver-shaped string other than the tag version. For mixpanel-unity, version_files is `["Mixpanel/MixpanelAPI.cs"]` — verified that file contains exactly one X.Y.Z literal so the strict validation works.
…ease flow The standardization PR replaces scripts/release.py and the legacy .github/workflows/release.yml with a two-step prepare-release + release-upm flow. Update both AI-agent context files so future automated edits don't fall back to the old script and the deleted workflow. Both docs now point at the Unity Release Runbook on Notion as the canonical reference.
The script is fully replaced by the prepare-release.yml + release-upm.yml workflows. Leaving it in tree just gives contributors and AI agents a second, broken way to cut a release. Remove the script, its .meta sidecar, the now-empty scripts/ directory, and the AGENTS.md reference that still pointed at it. Also fix a stale line in CLAUDE.md that suggested rebuilding .unitypackage assets via "scripts under scripts/" — the script never did that; .unitypackage exports come from the Unity Editor's Assets → Export Package… menu.
Aligns the changelog-section extraction with the deployed mixpanel-android release workflow, which uses a sed range. The Python regex implementation was an accident of port-time authorship; sed is the proven approach in the gold-standard Maven Central pipeline. Uses `\@...@` as the sed address delimiter so tags containing `/` (e.g. `openfeature/v0.1.0`) don't conflict with the default `/`. Behavior is otherwise preserved: file-based release_notes.md output, fallback to "Release $TAG" placeholder when the section is missing or empty, and the two-step structure for log visibility in the workflow run.
Aligns with the Android fleet's convention of allowing `feat(all): ...`, `fix(all): ...`, `chore(all): ...` for cross-cutting changes that should appear in every module's changelog. The shared generate-changelog.sh already matches `all` (it was copied verbatim from mixpanel-android), so this regex change is the only piece needed to make the end-to-end flow accept `all`-scoped PR titles. For single-module repos, `feat(all): foo` is functionally equivalent to `feat(<only-module>): foo` — kept for fleet-wide consistency.
c8fad23 to
e6ef2b8
Compare
Mirrors the same fix applied to mixpanel-flutter and mixpanel-react-native. Previously the generator required every commit to be scoped to either `<module>` or `all` — meaning a perfectly valid bare-titled PR like `feat: add foo` would silently drop out of the changelog despite passing the pr-title-check workflow (which accepts bare titles). Split the rule so it matches pr-title-check semantics: - feat / fix: bare, scoped to the current module, or scoped to `all` - chore: explicit scope required — bare `chore:` is the convention for changes intentionally hidden from the changelog (release prep, CI tweaks, lockfile bumps, internal docs) Other-module scopes (e.g. `feat(other):`) remain excluded from this module's changelog, as before. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
rahul-mixpanel
approved these changes
May 20, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Standardizes this repo's release process to match the rest of the Mixpanel SDK fleet, per the SDK Release Process Standardization Effort.
After merge, releases follow a uniform two-step ceremony:
prepare-release.yml) — opens a release PR with the version bump, changelog section, and README header line updated.release-upm.ymlvalidates, gates on thereleaseGitHub environment for human approval, and publishes (where applicable for this ecosystem).What's added
.github/modules.json— single source of truth for module config (paths, tag prefixes, package names).github/workflows/prepare-release.yml— manual dispatch, opens release PR.github/workflows/release-upm.yml— tag-triggered publish workflow.github/workflows/pr-title-check.yml— conventional-commit enforcement (regex built frommodules.json).github/scripts/generate-changelog.sh— shared changelog generator (verbatim from mixpanel-android)CHANGELOG.mdper module where missinganalytics(com.mixpanel.unityUPM package).github/workflows/release.yml(heinrichreimer/github-changelog-generator-action) — fully superseded by the new tag-triggeredrelease-upm.ymlExamples.unitypackageandTests.unitypackageas GitHub release assets.unitypackagefiles are NOT rebuilt by CI (Unity license required). If a release includes Examples/Tests changes, maintainers must rebuild the.unitypackagelocally before tagging — runbook documents thisscripts/release.pyis now superseded but intentionally left in place; can be deprecated in a follow-up.CLAUDE.mdand.github/copilot-instructions.mdstill reference the old release flow and would benefit from a follow-up updateHow releases work after this lands
Full ceremony, one-time setup, and PR title conventions: Unity Release Runbook
One-time setup before the first release
The runbook lists the full setup. The work that requires repo-admin access (cannot be done in this PR):
releasewith required reviewer(s)Validate PR titlecheck)Read and write permissionsandAllow GitHub Actions to create and approve pull requests(needed byprepare-release.yml'sgh pr create)Notes
fix:commit correcting a jq tag-resolution snippet (the same bug exists in the WIP Flutter/RN PRs and should be back-ported there).