mit einem Klick
release
// Drive the full release process end-to-end across gradle-plugins, CLI, step, and steplib repos. Use when the user asks to release, publish, or deploy a new version.
// Drive the full release process end-to-end across gradle-plugins, CLI, step, and steplib repos. Use when the user asks to release, publish, or deploy a new version.
| name | release |
| description | Drive the full release process end-to-end across gradle-plugins, CLI, step, and steplib repos. Use when the user asks to release, publish, or deploy a new version. |
| user_invocable | true |
Releasing a new version is a multi-step process across several repositories.
IMPORTANT: Drive the ENTIRE process end-to-end in a single conversation. Use the Bitrise MCP server to monitor build statuses (poll every 30s), check for triggered workflows in downstream repos, and move to the next step as soon as the previous one completes. Do not stop and wait for the user between steps.
The install/installer.sh script and the binaries attached to every CLI GitHub release are on the critical path of every Bitrise build — not just builds that opt into the build cache. The Bitrise default workflow runs the gradle-mirrors activation step (and other CLI-driven steps) unconditionally, and each of those pipes installer.sh to sh and fetches the platform tarball + checksum from the latest non-prerelease GitHub release. If any of these break — installer script, binaries, checksum file, the wrong release marked as latest — the CLI install fails, the mirror activation soft-fails, and Maven Central requests bypass the Bitrise proxy on the entire fleet.
That failure mode caused the 2026-04-28 Maven Central rate-limit incident.
Concrete rules:
--prerelease (see step 6). The installer ignores prereleases when resolving latest, so an empty / half-uploaded release cannot poison builds.latest. If goreleaser fails midway, leave the release as prerelease until you have manually verified the assets list is complete.release workflow as a drop-everything-and-fix incident. Don't move on to step releases until the CLI release workflow is green AND the v2.6.x release has all 8 expected assets (6 platform tarballs, checksums.txt, both verification XMLs).pr-release-check-{linux,mac} workflows) but a real Bitrise build is still the canonical smoke test.install/installer.sh to GAR twice: once as installer.sh:<tag>:installer.sh (immutable, audit trail) and once as installer.sh:latest-pointer:installer.sh + installer.sh:latest-pointer:VERSION (mutable pointer + bare semver, refreshed via delete-then-upload each release). GAR rejects the literal latest as a reserved version_id, so the mutable view uses latest-pointer. The latest-pointer view is the documented carve-out from the #327 immutability rule — safe because it's only consulted when the primary GitHub path is already failing. After every release, the verify-release workflow runs (chained after release via the release-and-verify pipeline) and executes scripts/verify_release.sh to assert the GH happy path and the GAR-only fallback both work end-to-end. Verification failures post to Slack and can be retried independently of release without re-cutting the tag.bitrise-io/homebrew-bitrise-build-cache is a nice-to-have publication target, not part of the install flow used by Bitrise builds. The "Publish Homebrew formula" step in bitrise.yml's release workflow runs goreleaser with only the brew publisher and is marked is_skippable: true, so a tap-permission failure (e.g. 404 from PUT /Formula/bitrise-build-cache.rb) won't break the release.
If the brew step fails:
installer.sh:<tag> + installer.sh:latest-pointer:{installer.sh,VERSION}) succeeded, and the chained verify-release workflow (running scripts/verify_release.sh) passed — all critical. A verify-release failure does NOT mean re-cut the tag — fix the underlying issue and re-run the verify-release workflow alone via the Bitrise UI.GIT_BOT_USER_ACCESS_TOKEN not being a collaborator with push access on bitrise-io/homebrew-bitrise-build-cache. Add them in the tap repo's settings.A release can be triggered by:
bitrise-io/gradle-plugins triggers the publish pipeline, which auto-triggers the CLI's update_plugins workflow. Start from Step 1.| App | Bitrise App ID | GitHub Repo |
|---|---|---|
| gradle-plugins | cdb16849-294e-48c4-8623-18ade050bd0e | bitrise-io/gradle-plugins |
| bitrise-build-cache-cli | 1a2ddc0a-bab0-4db1-9b78-4c13aae180ba | bitrise-io/bitrise-build-cache-cli |
| Gradle step (unified CI) | 48fa8fbee698622c | bitrise-steplib/bitrise-step-activate-gradle-remote-cache |
| Xcode step (unified CI) | 48fa8fbee698622c | bitrise-steplib/bitrise-step-activate-build-cache-for-xcode |
| Gradle features step (unified CI) | 48fa8fbee698622c | bitrise-steplib/bitrise-step-activate-gradle-features |
| React Native features step (unified CI) | 48fa8fbee698622c | bitrise-steplib/bitrise-step-activate-react-native-features |
| Steplib | — | bitrise-io/bitrise-steplib |
Merging a PR to main in bitrise-io/gradle-plugins triggers the publish-all pipeline on the gradle-plugins Bitrise app. Only release modules that have version bumps in their gradle.properties.
Each publish workflow automatically checks if its module's VERSION_NAME was bumped in the current commit. If not, it skips publishing and exits successfully. No need to manually abort workflows.
Poll the publish build(s) every ~30 seconds until they complete. Report status to the user.
The publish pipeline should automatically trigger an update_plugins workflow in the CLI app 1a2ddc0a-bab0-4db1-9b78-4c13aae180ba. Check for running builds in that app. If the workflow wasn't triggered, manually trigger update_plugins.
The update_plugins workflow creates a PR in bitrise-io/bitrise-build-cache-cli. Monitor the CI pipeline. If there are flaky cache hit rate failures, rebuild them (see "Flaky E2E tests" below). Once all checks pass:
gh pr review --approve --repo bitrise-io/bitrise-build-cache-cli <PR_NUMBER>
gh pr merge --merge --auto --repo bitrise-io/bitrise-build-cache-cli <PR_NUMBER>
NEVER use --admin to bypass checks — always wait for CI to go green before merging.
Create a GitHub release in bitrise-build-cache-cli.
--prerelease. The release workflow uploads the binaries asynchronously; until those land, the release is empty. Marking it as latest (or as a regular release) at create-time makes a binary-less release "current," which breaks any consumer that downloads the latest asset. A separate CI job promotes the release out of prerelease once the binaries are appended.--latest. Without --latest, GitHub will not auto-promote a prerelease; with --latest it would, defeating the prerelease gate.gh release create vX.Y.Z --repo bitrise-io/bitrise-build-cache-cli --title vX.Y.Z --prerelease --notes "..."The CLI release triggers auto-update PRs in four step repos (all use unified CI app 48fa8fbee698622c). The PR title will be "feat: Release new CLI". Monitor CI on all four, then approve and merge:
bitrise-steplib/bitrise-step-activate-gradle-remote-cache — released for every CLI version.bitrise-steplib/bitrise-step-activate-build-cache-for-xcode — released for every CLI version.bitrise-steplib/bitrise-step-activate-react-native-features — released, but releases are not 1:1 with CLI releases (each step release usually catches up across several intervening CLI patch versions; release when CLI changes matter for RN, e.g. an Xcode or Gradle-side improvement that RN builds benefit from).bitrise-steplib/bitrise-step-activate-gradle-features — truly experimental, no GitHub release flow yet (only a single early steplib PR exists). Merge the auto-update PR but do not cut a GitHub release until that changes.# For each step repo:
gh pr review --approve --repo <REPO> <PR_NUMBER>
gh pr merge --squash --auto --repo <REPO> <PR_NUMBER>
Always wait for CI to pass. Use --squash (merge commits are not allowed on these repos).
Create GitHub releases for whichever of the four step repos the user actually wants to release (default: Gradle step + Xcode step; React Native features step when the CLI change is RN-relevant). The Gradle features step does not have a GitHub release flow yet — skip it.
After the step releases, PRs appear in bitrise-io/bitrise-steplib for each released step. They may need a rebase.
gh pr review --approve --repo bitrise-io/bitrise-steplib <PR_NUMBER>
gh pr merge --squash --auto --repo bitrise-io/bitrise-steplib <PR_NUMBER>
Always wait for CI to pass — never bypass branch protection. The steplib repo requires squash merges (merge commits are blocked).
The CLI repo's features-e2e pipeline includes cache hit rate assertions. If a test (e.g., feature-e2e-gradle-7) fails with cacheHitRate: want != 0, got 0, it's likely because the cache items were evicted since the last run, or because of co-located caches across multiple data centers (builds may land on a different DC than the one that has the warm cache). Keep rebuilding the failed workflows — it may take 2-3 attempts to get a green build. This is not a real failure.
/scripts/https://github.com/bitrise-io/bitrise-build-cache-cli/tree/main/scripts48fa8fbee698622c — just wait for the auto-update PR and steplib PR.