Files
buzz/scripts/mobile-release.sh
T
cls 9dfa06ffee
Docker image / Build (linux/amd64) (push) Has been cancelled
Docker image / Build (linux/arm64) (push) Has been cancelled
Docker image / Merge release multi-arch manifest (push) Has been cancelled
Docker image / Merge debug multi-arch manifest (push) Has been cancelled
Docker image / Build public push gateway (linux/amd64) (push) Has been cancelled
Docker image / Build public push gateway (linux/arm64) (push) Has been cancelled
Docker image / Publish public push gateway image (push) Has been cancelled
Sprig image / Build (linux/amd64) (push) Has been cancelled
Sprig image / Build (linux/arm64) (push) Has been cancelled
Sprig image / Merge multi-arch manifest (push) Has been cancelled
Harbor Buzz Orchestra / Python tests and lint (push) Has been cancelled
CI / Detect Changed Paths (push) Has been cancelled
CI / Rust Lint (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Desktop Core (push) Has been cancelled
CI / Desktop Smoke E2E (1) (push) Has been cancelled
CI / Desktop Smoke E2E (2) (push) Has been cancelled
CI / Desktop Smoke E2E (3) (push) Has been cancelled
CI / Desktop Smoke E2E (4) (push) Has been cancelled
CI / Desktop (push) Has been cancelled
CI / Desktop E2E Relay (push) Has been cancelled
CI / Desktop E2E Integration (1/2) (push) Has been cancelled
CI / Desktop E2E Integration (2/2) (push) Has been cancelled
CI / Desktop E2E Integration (push) Has been cancelled
CI / Backend Integration (relay e2e) (push) Has been cancelled
CI / Relay E2E (push) Has been cancelled
CI / Web (push) Has been cancelled
CI / Mobile (push) Has been cancelled
CI / Security (push) Has been cancelled
CI / Dead Token Reference Guard (push) Has been cancelled
CI / Server Cross-Compile (aarch64-unknown-linux-musl) (push) Has been cancelled
CI / Server Cross-Compile (x86_64-unknown-linux-musl) (push) Has been cancelled
CI / Windows Rust (x86_64-pc-windows-msvc) (push) Has been cancelled
CI / Desktop Build (macOS) (push) Has been cancelled
helm chart / lint + unittest + render matrix (push) Has been cancelled
helm chart / install on kind (gated) (push) Has been cancelled
helm chart / publish chart to GHCR (push) Has been cancelled
Mesh Lifecycle / Relay-Driven Mesh Lifecycle Smoke (push) Has been cancelled
Sprig / Build (aarch64-unknown-linux-musl) (push) Has been cancelled
Sprig / Build (x86_64-unknown-linux-musl) (push) Has been cancelled
Sprig / Publish rolling release (push) Has been cancelled
Sprig / Publish tagged release (push) Has been cancelled
feat: import Chinese-localized Buzz source snapshot
Signed-off-by: cls_宁波本机 <908705107@qq.com>
2026-08-13 18:34:25 +08:00

170 lines
6.0 KiB
Bash

#!/usr/bin/env bash
set -euo pipefail
usage() {
cat >&2 <<'USAGE'
usage:
scripts/mobile-release.sh candidate X.Y.Z
candidate Publish the next immutable mobile-vX.Y.Z-rc.N candidate tag at the
exact current commit of block/buzz's remote main branch.
USAGE
exit 2
}
fail() {
echo "Error: $*" >&2
exit 1
}
# shellcheck source=scripts/release-rulesets.sh
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/release-rulesets.sh"
require_gh_minimum_version() {
local minimum="2.87.0" version
command -v gh >/dev/null 2>&1 || fail "gh >= $minimum is required"
version="$(gh --version 2>/dev/null | awk 'NR == 1 { print $3 }')" || \
fail "could not determine gh version (gh >= $minimum is required)"
[[ "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || \
fail "gh returned invalid version '$version'"
if ! awk -v current="$version" -v minimum="$minimum" '
BEGIN {
split(current, c, ".")
split(minimum, m, ".")
for (i = 1; i <= 3; i++) {
if ((c[i] + 0) > (m[i] + 0)) exit 0
if ((c[i] + 0) < (m[i] + 0)) exit 1
}
exit 0
}
'; then
fail "gh $version is too old; gh >= $minimum is required"
fi
}
require_clean_semver() {
[[ "$1" =~ ^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$ ]] || \
fail "'$1' is not a mobile release version (expected X.Y.Z)"
}
require_clean_tree() {
git diff --quiet && git diff --cached --quiet && \
[[ -z "$(git status --short --untracked-files=normal)" ]] || \
fail "working tree is dirty; commit or stash changes first"
}
require_annotated_tag() {
local git_dir="$1" object="$2" label="$3"
if [[ "$(git -C "$git_dir" cat-file -t "$object" 2>/dev/null || true)" != "tag" ]]; then
echo "$label must be an annotated tag" >&2
return 1
fi
}
remote_tag_commit_sha() {
local ref="$1" line advertised_oid tmp fetched_oid commit
line="$(git ls-remote --refs origin "$ref")" || return 1
[[ -n "$line" && "$line" != *$'\n'* ]] || return 1
advertised_oid="${line%%$'\t'*}"
tmp="$(mktemp -d)"
git -C "$tmp" init -q
git -C "$tmp" remote add origin "$(git remote get-url origin)"
if ! git -C "$tmp" fetch -q --depth 1 origin "$ref"; then
rm -rf "$tmp"
return 1
fi
fetched_oid="$(git -C "$tmp" rev-parse --verify FETCH_HEAD)"
if [[ "$fetched_oid" != "$advertised_oid" ]]; then
rm -rf "$tmp"
fail "$ref moved while it was being resolved"
fi
if ! require_annotated_tag "$tmp" FETCH_HEAD "$ref"; then
rm -rf "$tmp"
return 1
fi
if ! commit="$(git -C "$tmp" rev-parse --verify 'FETCH_HEAD^{commit}')"; then
rm -rf "$tmp"
return 1
fi
rm -rf "$tmp"
printf '%s' "$commit"
}
remote_main_commit_sha() {
local ref="refs/heads/main" line advertised_oid fetched_oid commit
line="$(git ls-remote --refs origin "$ref")" || return 1
[[ -n "$line" && "$line" != *$'\n'* ]] || return 1
advertised_oid="${line%%$'\t'*}"
git fetch -q --no-tags origin "$ref"
fetched_oid="$(git rev-parse --verify FETCH_HEAD)"
[[ "$fetched_oid" == "$advertised_oid" ]] || \
fail "origin/main moved while it was being resolved"
commit="$(git rev-parse --verify 'FETCH_HEAD^{commit}')" || return 1
[[ "$commit" == "$advertised_oid" ]] || \
fail "origin/main did not resolve directly to a commit"
printf '%s' "$commit"
}
command="${1:-}"
case "$command" in
candidate)
[[ "$#" -eq 2 ]] || usage
version="$2"
require_clean_semver "$version"
require_clean_tree
require_canonical_repository || exit 1
require_gh_minimum_version
local_head_sha="$(git rev-parse --verify 'HEAD^{commit}')" || fail "HEAD is not a commit"
main_sha="$(remote_main_commit_sha)" || fail "origin/main does not exist"
next=1
if ! remote_tags="$(git ls-remote --refs --tags origin "refs/tags/mobile-v${version}-rc.*")"; then
fail "could not list existing candidates for $version"
fi
while IFS=$'\t' read -r _ ref; do
[[ "$ref" =~ ^refs/tags/mobile-v${version//./\.}-rc\.([1-9][0-9]*)$ ]] || continue
number="${BASH_REMATCH[1]}"
(( number >= next )) && next=$((number + 1))
done <<< "$remote_tags"
tag="mobile-v${version}-rc.${next}"
workflow="mobile-release-candidate.yml"
if dispatch_output="$(gh workflow run "$workflow" \
--repo block/buzz \
--ref main \
-f "version=$version" \
-f "candidate_number=$next" \
-f "target_sha=$main_sha" 2>&1)"; then
:
else
if [[ "$dispatch_output" == *"does not have 'workflow_dispatch' trigger"* ]]; then
fail "$workflow is not available on main yet; merge the release-process change before publishing a candidate"
fi
fail "could not dispatch App-backed publication for $tag: $dispatch_output"
fi
run_url="$(printf '%s\n' "$dispatch_output" | awk '/^https:\/\/github\.com\/block\/buzz\/actions\/runs\/[0-9]+$/ { if (found) exit 2; found = $0 } END { if (found) print found }')" || \
fail "GitHub returned multiple workflow run URLs for one candidate dispatch"
[[ -n "$run_url" ]] || \
fail "GitHub accepted the candidate dispatch but returned no workflow run URL"
run_id="${run_url##*/}"
gh run watch "$run_id" --repo block/buzz --exit-status --compact || \
fail "App-backed publication failed: $run_url"
current_main_sha="$(remote_main_commit_sha)" || fail "origin/main does not exist after publication"
[[ "$current_main_sha" == "$main_sha" ]] || \
fail "origin/main moved from requested commit $main_sha to $current_main_sha during publication"
published_sha="$(remote_tag_commit_sha "refs/tags/$tag")" || \
fail "publication completed without exact annotated candidate tag $tag"
[[ "$published_sha" == "$main_sha" ]] || \
fail "$tag resolved to $published_sha instead of requested commit $main_sha"
if [[ "$local_head_sha" != "$main_sha" ]]; then
echo "Note: local HEAD is $local_head_sha; candidate source is current origin/main $main_sha." >&2
fi
printf 'Published %s at origin/main commit %s through buzz-release-bot. Use this exact tag in Release Mobile.\n' \
"$tag" "$main_sha"
;;
*) usage ;;
esac