Files
buzz/scripts/mobile-release-source.sh
Tom Brow 30ca980b49 feat(release): support version-matched mobile stable branches (#8430)
Mobile candidates currently require the current `main` commit, so a
stable release branch cannot publish through the existing protected tag
workflow.

Add optional `--source-branch mobile-vMAJOR.MINOR` selection while
preserving `main` as the default. Both the command and App-backed
publisher reject a stable branch whose major/minor differs from the
requested version. Candidates retain exact-tip checks and immutable
annotated tags; the private build pipeline is unchanged.

Document the temporary stable-only distribution policy and explicit
per-fix backport decisions. No candidate, build, or upload is triggered
by this change. No duplicate implementation was found among open release
PRs.

Stable publication now checks active review and status-check protection
in both the operator and publisher. The process permits approved
backport PRs and stable-only corrections for regressions caused by
earlier backports. Administrator activation and verification of the
no-bypass ruleset remain outstanding; non-admin API responses hide the
bypass actor list.

### Validation

- Full local `just ci` passed during preparation; the final changes
affect shell release tooling, its workflow inputs, CI path detection,
and documentation.
- Publisher contract passed, including version-matched stable sources
and mismatched branch rejection.
- Operator contract covers default main, a divergent stable commit,
missing or mismatched sources, immutable sequencing, and publication
races. The final operator contract run passed.


- Updated publisher and operator contracts pass, including 17
weakened-policy cases and rejection of unavailable protection. The live,
currently unprotected stable branch is rejected.

---------

Signed-off-by: Tom Brow <tomb@block.xyz>
2026-10-18 18:04:04 -07:00

45 lines
2.0 KiB
Bash

#!/usr/bin/env bash
# Validate an explicitly selected stable branch against the marketing version.
# main remains the default for releases without a stabilization branch.
require_mobile_release_source() {
local version="$1" branch="$2"
if [[ "$branch" == main ]]; then
return 0
fi
if [[ "$branch" != "mobile-v${version%.*}" ]]; then
echo "Source branch must be main or mobile-v${version%.*} for version $version" >&2
return 1
fi
}
# The repository administrator must configure this ruleset without bypass actors.
# GitHub hides that list from non-admin tokens; check the caller's effective
# bypass plus every public policy field on each publication.
require_mobile_release_branch_ruleset() {
local branch="$1" valid
[[ "$branch" != main ]] || return 0
valid="$(gh api repos/block/buzz/rulesets/19321162 --jq '
.target == "branch" and .enforcement == "active"
and .current_user_can_bypass == "never"
and (.conditions.ref_name.include | index("refs/heads/mobile-v*") != null)
and (.conditions.ref_name.exclude == [])
and ((has("bypass_actors") | not) or .bypass_actors == [])
and any(.rules[]; .type == "deletion")
and any(.rules[]; .type == "non_fast_forward")
and any(.rules[]; .type == "pull_request"
and .parameters.required_approving_review_count >= 1
and .parameters.dismiss_stale_reviews_on_push == true
and .parameters.require_last_push_approval == true
and .parameters.required_review_thread_resolution == true)
and any(.rules[]; .type == "required_status_checks"
and .parameters.strict_required_status_checks_policy == true
and ([.parameters.required_status_checks[].context] | index("Mobile") != null)
and ([.parameters.required_status_checks[].context] | index("DCO Check") != null))
')" || { echo "Could not verify mobile stable-branch protection" >&2; return 1; }
[[ "$valid" == true ]] || {
echo "Mobile stable-branch ruleset 19321162 must enforce review and checks on mobile-v* without bypass" >&2
return 1
}
}