mirror of
https://github.com/block/buzz.git
synced 2026-10-27 04:30:52 +00:00
fix(release): keep mobile candidates pinned as branches advance (#8454)
Mobile candidate publication currently fails if the source branch advances after selection, and the operator can report failure even after the correct immutable tag was created. It also prevents releasing an explicitly selected historical baseline. Add `--commit FULL_SHA` and independently verify in the operator and publisher that the selected commit belongs to the selected source branch's history. Compare immutable SHAs, keep the candidate pinned through publication, and verify the resulting annotated tag instead of requiring the branch to remain stationary. Stable-branch review/check protection and immutable-tag permissions remain enforced. Without `--commit`, selection still defaults to the current source tip. ### Validation - Updated operator and publisher contracts pass: historical main/stable selection, branch advancement during publication, unrelated or missing commits, ancestry lookup failure, and unchanged tag/sequence checks. - Removing ancestry enforcement causes the unrelated-history regression to fail. - Live read-only ancestry verification accepts the original 0.24 baseline. Local publication stops at the existing App-permission check; no tag or build was created. - Full local `just ci` passed. Signed-off-by: Tom Brow <tomb@block.xyz>
This commit is contained in:
@@ -18,7 +18,7 @@ on:
|
||||
default: main
|
||||
type: string
|
||||
target_sha:
|
||||
description: Exact current source branch commit
|
||||
description: Pinned commit in the selected source branch history
|
||||
required: true
|
||||
type: string
|
||||
|
||||
|
||||
26
RELEASING.md
26
RELEASING.md
@@ -135,11 +135,13 @@ release notes and require operators to upgrade before distributing these clients
|
||||
1. **Publish a candidate.** From a clean checkout whose `origin` is the
|
||||
canonical `block/buzz` repository, run
|
||||
`scripts/mobile-release.sh candidate X.Y.Z`. The script resolves and fetches
|
||||
the exact current `origin/main` commit, derives the next number from exact
|
||||
a snapshot of `origin/main`, derives the next number from exact
|
||||
remote tags for that marketing version, and publishes an annotated
|
||||
`mobile-vX.Y.Z-rc.N` tag there through the dedicated `buzz-release-bot`
|
||||
GitHub App. It never uses the operator's checked-out commit and never moves
|
||||
an existing candidate.
|
||||
an existing candidate. To select a historical commit, add `--commit FULL_SHA`.
|
||||
Both operator and publisher require that commit to be in the selected source
|
||||
branch's history. Later branch advances do not change or invalidate the tag.
|
||||
2. **Build the exact tag.** Enter the candidate tag as `mobile_ref` in the
|
||||
private Buzz mobile Buildkite pipeline. OSS CI deliberately cannot trigger
|
||||
that private pipeline. The tag supplies both source commit and release
|
||||
@@ -168,7 +170,9 @@ scripts/mobile-release.sh candidate 0.25.0 --source-branch mobile-v0.25
|
||||
The branch must match the marketing version's major and minor components:
|
||||
`mobile-v0.25` accepts 0.25.x, but rejects 0.26.x and 1.25.x. Without the option,
|
||||
the source remains `main`. Both the operator and publisher validate the source;
|
||||
a missing branch or changed tip fails rather than falling back to `main`.
|
||||
a missing branch or a commit outside its history fails rather than falling back
|
||||
to `main`. `--commit FULL_SHA` also works with a stable source branch, whose
|
||||
review and check protections remain required.
|
||||
The GitHub workflow itself continues to run from reviewed `main`. The private
|
||||
pipeline still builds only the resulting immutable candidate tag.
|
||||
|
||||
@@ -191,7 +195,8 @@ Never merge `main` wholesale.
|
||||
Remote agents and App Clip are post-conference work. There is no preselected
|
||||
fix list and no requirement to create a stable branch for every minor release.
|
||||
|
||||
The initial 0.25.0 candidate uses an empty commit above that baseline to verify
|
||||
The initial 0.25.0 candidate pins that baseline with `--commit`. The second
|
||||
candidate uses an empty commit above that baseline to verify
|
||||
that the existing pipeline builds a commit outside `main`. Verify identical
|
||||
source trees, absence of that commit from remote `main`, and the exact tag,
|
||||
commit, marketing version and build number in the uploaded artifacts. Upload
|
||||
@@ -394,14 +399,13 @@ option for a stable release. The command publishes a new immutable RC tag at the
|
||||
remote commit. Continue referring to each tested or shipped platform artifact by
|
||||
its own exact tag.
|
||||
|
||||
### `scripts/mobile-release.sh candidate` fails because the source branch moved during publication
|
||||
### The source branch advances during candidate publication
|
||||
|
||||
The App-backed workflow may already have published the requested immutable RC
|
||||
at the prior source branch tip before the operator command detects the race. Do not
|
||||
move or delete that tag, and do not treat it as the candidate for the current
|
||||
source branch. Inspect the run URL from the command output, then rerun
|
||||
`scripts/mobile-release.sh candidate <version>` to publish the next RC from the
|
||||
new current source branch tip, preserving the source-branch option.
|
||||
Publication remains pinned to the selected SHA. The publisher verifies that it
|
||||
is an ancestor of a resolved source-branch snapshot, then creates and verifies
|
||||
an immutable annotated tag for that exact SHA. The operator verifies the tag,
|
||||
not the branch's later tip. A newer commit does not require retrying or creating
|
||||
another candidate. Missing or unverifiable ancestry still fails closed.
|
||||
|
||||
### A mobile candidate command selects the wrong RC number
|
||||
|
||||
|
||||
@@ -42,3 +42,17 @@ require_mobile_release_branch_ruleset() {
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
# Compare immutable SHAs, not a mutable branch name. The selected branch may
|
||||
# advance after this snapshot without changing the authorized candidate source.
|
||||
require_mobile_release_commit_ancestor() {
|
||||
local target_sha="$1" source_sha="$2" merge_base
|
||||
merge_base="$(gh api "repos/block/buzz/compare/$target_sha...$source_sha" --jq .merge_base_commit.sha)" || {
|
||||
echo "Could not verify candidate source ancestry" >&2
|
||||
return 1
|
||||
}
|
||||
[[ "$merge_base" == "$target_sha" ]] || {
|
||||
echo "Candidate commit $target_sha is not in selected source history at $source_sha" >&2
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,10 +4,10 @@ set -euo pipefail
|
||||
usage() {
|
||||
cat >&2 <<'USAGE'
|
||||
usage:
|
||||
scripts/mobile-release.sh candidate X.Y.Z [--source-branch mobile-vX.Y]
|
||||
scripts/mobile-release.sh candidate X.Y.Z [--source-branch mobile-vX.Y] [--commit FULL_SHA]
|
||||
|
||||
candidate Publish the next immutable mobile-vX.Y.Z-rc.N candidate tag at the
|
||||
exact current remote source commit (main unless --source-branch is set).
|
||||
selected commit in source history (defaults to the current source tip).
|
||||
USAGE
|
||||
exit 2
|
||||
}
|
||||
@@ -94,16 +94,12 @@ remote_tag_commit_sha() {
|
||||
}
|
||||
|
||||
remote_source_commit_sha() {
|
||||
local ref="refs/heads/$MOBILE_RELEASE_SOURCE_BRANCH" 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/$MOBILE_RELEASE_SOURCE_BRANCH moved while it was being resolved"
|
||||
local ref="refs/heads/$MOBILE_RELEASE_SOURCE_BRANCH" fetched_oid commit
|
||||
# Fetch a single snapshot. A later branch advance does not invalidate it.
|
||||
git fetch -q --no-tags origin "$ref" || return 1
|
||||
fetched_oid="$(git rev-parse --verify FETCH_HEAD)" || return 1
|
||||
commit="$(git rev-parse --verify 'FETCH_HEAD^{commit}')" || return 1
|
||||
[[ "$commit" == "$advertised_oid" ]] || \
|
||||
[[ "$commit" == "$fetched_oid" ]] || \
|
||||
fail "origin/$MOBILE_RELEASE_SOURCE_BRANCH did not resolve directly to a commit"
|
||||
printf '%s' "$commit"
|
||||
}
|
||||
@@ -111,13 +107,31 @@ remote_source_commit_sha() {
|
||||
command="${1:-}"
|
||||
case "$command" in
|
||||
candidate)
|
||||
[[ "$#" -eq 2 || "$#" -eq 4 ]] || usage
|
||||
[[ "$#" -ge 2 ]] || usage
|
||||
version="$2"
|
||||
shift 2
|
||||
MOBILE_RELEASE_SOURCE_BRANCH=main
|
||||
if [[ "$#" -eq 4 ]]; then
|
||||
[[ "$3" == --source-branch ]] || usage
|
||||
MOBILE_RELEASE_SOURCE_BRANCH="$4"
|
||||
fi
|
||||
requested_sha=""
|
||||
source_option_seen=false
|
||||
commit_option_seen=false
|
||||
while [[ "$#" -gt 0 ]]; do
|
||||
[[ "$#" -ge 2 ]] || usage
|
||||
case "$1" in
|
||||
--source-branch)
|
||||
[[ "$source_option_seen" == false ]] || usage
|
||||
source_option_seen=true
|
||||
MOBILE_RELEASE_SOURCE_BRANCH="$2"
|
||||
;;
|
||||
--commit)
|
||||
[[ "$commit_option_seen" == false ]] || usage
|
||||
commit_option_seen=true
|
||||
requested_sha="$2"
|
||||
[[ "$requested_sha" =~ ^[0-9a-f]{40}$ ]] || fail "--commit requires a full commit SHA"
|
||||
;;
|
||||
*) usage ;;
|
||||
esac
|
||||
shift 2
|
||||
done
|
||||
require_clean_semver "$version"
|
||||
require_mobile_release_source "$version" "$MOBILE_RELEASE_SOURCE_BRANCH" || exit 1
|
||||
require_clean_tree
|
||||
@@ -126,7 +140,9 @@ case "$command" in
|
||||
require_mobile_release_branch_ruleset "$MOBILE_RELEASE_SOURCE_BRANCH" || exit 1
|
||||
|
||||
local_head_sha="$(git rev-parse --verify 'HEAD^{commit}')" || fail "HEAD is not a commit"
|
||||
source_sha="$(remote_source_commit_sha)" || fail "origin/$MOBILE_RELEASE_SOURCE_BRANCH does not exist"
|
||||
source_tip="$(remote_source_commit_sha)" || fail "origin/$MOBILE_RELEASE_SOURCE_BRANCH does not exist"
|
||||
source_sha="${requested_sha:-$source_tip}"
|
||||
require_mobile_release_commit_ancestor "$source_sha" "$source_tip" || exit 1
|
||||
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"
|
||||
@@ -161,17 +177,14 @@ case "$command" in
|
||||
gh run watch "$run_id" --repo block/buzz --exit-status --compact || \
|
||||
fail "App-backed publication failed: $run_url"
|
||||
|
||||
current_source_sha="$(remote_source_commit_sha)" || fail "origin/$MOBILE_RELEASE_SOURCE_BRANCH does not exist after publication"
|
||||
[[ "$current_source_sha" == "$source_sha" ]] || \
|
||||
fail "origin/$MOBILE_RELEASE_SOURCE_BRANCH moved from requested commit $source_sha to $current_source_sha during publication"
|
||||
published_sha="$(remote_tag_commit_sha "refs/tags/$tag")" || \
|
||||
fail "publication completed without exact annotated candidate tag $tag"
|
||||
[[ "$published_sha" == "$source_sha" ]] || \
|
||||
fail "$tag resolved to $published_sha instead of requested commit $source_sha"
|
||||
if [[ "$local_head_sha" != "$source_sha" ]]; then
|
||||
echo "Note: local HEAD is $local_head_sha; candidate source is current origin/$MOBILE_RELEASE_SOURCE_BRANCH $source_sha." >&2
|
||||
echo "Note: local HEAD is $local_head_sha; candidate source is pinned from origin/$MOBILE_RELEASE_SOURCE_BRANCH $source_sha." >&2
|
||||
fi
|
||||
printf 'Published %s at origin/%s commit %s through buzz-release-bot. Use this exact tag in Release Mobile.\n' \
|
||||
printf 'Published %s at pinned origin/%s commit %s through buzz-release-bot. Use this exact tag in Release Mobile.\n' \
|
||||
"$tag" "$MOBILE_RELEASE_SOURCE_BRANCH" "$source_sha"
|
||||
;;
|
||||
|
||||
|
||||
@@ -31,12 +31,12 @@ require_mobile_release_branch_ruleset "$MOBILE_RELEASE_SOURCE_BRANCH" || exit 1
|
||||
|
||||
source_sha="$(gh api "repos/$repo/git/ref/heads/$MOBILE_RELEASE_SOURCE_BRANCH" --jq .object.sha)" || \
|
||||
fail "could not resolve $repo $MOBILE_RELEASE_SOURCE_BRANCH"
|
||||
[[ "$source_sha" == "$target_sha" ]] || \
|
||||
fail "$repo $MOBILE_RELEASE_SOURCE_BRANCH moved from requested commit $target_sha to $source_sha"
|
||||
[[ "$source_sha" =~ ^[0-9a-f]{40}$ ]] || fail "GitHub returned an invalid source commit SHA"
|
||||
commit_sha="$(gh api "repos/$repo/commits/$target_sha" --jq .sha)" || \
|
||||
fail "$target_sha is not a commit in $repo"
|
||||
[[ "$commit_sha" == "$target_sha" ]] || \
|
||||
fail "GitHub resolved requested commit $target_sha as $commit_sha"
|
||||
require_mobile_release_commit_ancestor "$target_sha" "$source_sha" || exit 1
|
||||
|
||||
refs="$(
|
||||
gh api --paginate "repos/$repo/git/matching-refs/tags/mobile-v${version}-rc." --jq '.[].ref'
|
||||
|
||||
@@ -35,6 +35,21 @@ case "${1:-}:${2:-}" in
|
||||
api:repos/block/buzz/git/ref/heads/main) printf '%s\n' "$GH_TARGET_SHA" ;;
|
||||
api:repos/block/buzz/git/ref/heads/mobile-v1.2) printf '%s\n' "$GH_STABLE_SHA" ;;
|
||||
api:repos/block/buzz/git/ref/heads/*) printf '%s\n' "$GH_MISMATCH_SHA" ;;
|
||||
api:repos/block/buzz/compare/*)
|
||||
[[ "${GH_COMPARE_FAIL:-}" != 1 ]] || exit 1
|
||||
pair="${2##*/}"
|
||||
base="${pair%%...*}"; tip="${pair##*...}"
|
||||
if [[ -n "${GH_EXPECT_COMPARE:-}" ]]; then
|
||||
[[ "$pair" == "$GH_EXPECT_COMPARE" ]] || exit 1
|
||||
fi
|
||||
if [[ -n "${GH_COMPARE_BASE_SHA:-}" ]]; then
|
||||
printf '%s\n' "$GH_COMPARE_BASE_SHA"
|
||||
elif [[ "$base" == "$tip" ]]; then
|
||||
printf '%s\n' "$base"
|
||||
else
|
||||
printf '%s\n' 9999999999999999999999999999999999999999
|
||||
fi
|
||||
;;
|
||||
api:repos/block/buzz/commits/*) printf '%s\n' "${2##*/}" ;;
|
||||
api:--paginate)
|
||||
[[ "$3" == "repos/block/buzz/git/matching-refs/tags/mobile-v1.2.3-rc." ]]
|
||||
@@ -116,8 +131,9 @@ if GH_TAG_EXCLUDES=refs/tags/mobile-v0.0.0 "$publisher" 1.2.3 1 "$GH_TARGET_SHA"
|
||||
exit 1
|
||||
fi
|
||||
if GH_TARGET_SHA=3333333333333333333333333333333333333333 \
|
||||
GH_ANNOTATED_TARGET_SHA=1111111111111111111111111111111111111111 \
|
||||
"$publisher" 1.2.3 1 1111111111111111111111111111111111111111 main >/dev/null 2>&1; then
|
||||
echo "publisher accepted a moved main branch" >&2
|
||||
echo "publisher accepted a commit outside main history" >&2
|
||||
exit 1
|
||||
fi
|
||||
if GH_EXISTING_REFS=$'refs/tags/mobile-v1.2.3-rc.1\n' \
|
||||
@@ -164,6 +180,25 @@ if GITHUB_REPOSITORY=attacker/buzz "$publisher" 1.2.3 1 "$GH_TARGET_SHA" main >/
|
||||
fi
|
||||
|
||||
GH_ANNOTATED_TARGET_SHA="$GH_STABLE_SHA" "$publisher" 1.2.3 1 "$GH_STABLE_SHA" mobile-v1.2
|
||||
# Old commits are accepted only when the immutable compare proves ancestry.
|
||||
old_sha=6666666666666666666666666666666666666666
|
||||
for source in main mobile-v1.2; do
|
||||
tip="$GH_TARGET_SHA"
|
||||
[[ "$source" != mobile-v1.2 ]] || tip="$GH_STABLE_SHA"
|
||||
GH_COMPARE_BASE_SHA="$old_sha" GH_EXPECT_COMPARE="$old_sha...$tip" GH_ANNOTATED_TARGET_SHA="$old_sha" \
|
||||
"$publisher" 1.2.3 1 "$old_sha" "$source"
|
||||
before_calls="$(wc -l < "$GH_CALLS")"
|
||||
for mode in unrelated unavailable; do
|
||||
if GH_COMPARE_FAIL="$([[ "$mode" == unavailable ]] && echo 1 || echo 0)" \
|
||||
GH_COMPARE_BASE_SHA="$GH_MISMATCH_SHA" GH_ANNOTATED_TARGET_SHA="$old_sha" \
|
||||
"$publisher" 1.2.3 1 "$old_sha" "$source" >/dev/null 2>&1; then
|
||||
echo "publisher accepted $mode ancestry for $source" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
[[ "$(wc -l < "$GH_CALLS")" == "$before_calls" ]]
|
||||
done
|
||||
|
||||
for source in mobile-v1.3 mobile-v2.2 mobile-v01.2 arbitrary ''; do
|
||||
if GH_ANNOTATED_TARGET_SHA="$GH_MISMATCH_SHA" "$publisher" 1.2.3 1 "$GH_MISMATCH_SHA" "$source" >/dev/null 2>&1; then
|
||||
echo "publisher accepted mismatched source '$source'" >&2
|
||||
|
||||
@@ -32,7 +32,13 @@ case "${1:-}:${2:-}" in
|
||||
*) exit 2 ;;
|
||||
esac
|
||||
;;
|
||||
api:repos/block/buzz/compare/*)
|
||||
[[ "${GH_COMPARE_FAIL:-}" != 1 ]] || exit 1
|
||||
pair="${2##*/}"
|
||||
git --git-dir="$GH_REMOTE" merge-base "${pair%%...*}" "${pair##*...}"
|
||||
;;
|
||||
workflow:run)
|
||||
printf '%s\n' attempted >> "$GH_WORKFLOW_ATTEMPTS"
|
||||
if [[ "${GH_WORKFLOW_DISPATCH_FAIL:-}" == "1" ]]; then
|
||||
printf '%s\n' "${GH_WORKFLOW_DISPATCH_ERROR:-dispatch failed}" >&2
|
||||
exit 1
|
||||
@@ -58,7 +64,7 @@ case "${1:-}:${2:-}" in
|
||||
shift
|
||||
done
|
||||
[[ -n "$version" && -n "$number" && -n "$sha" && -n "$source_branch" ]] || exit 1
|
||||
[[ "$(git --git-dir="$GH_REMOTE" rev-parse "refs/heads/$source_branch")" == "$sha" ]] || exit 1
|
||||
git --git-dir="$GH_REMOTE" merge-base --is-ancestor "$sha" "refs/heads/$source_branch" || exit 1
|
||||
printf '%s\t%s\t%s\n' "$version" "$number" "$sha" >> "$GH_WORKFLOW_CAPTURE"
|
||||
if [[ "${GH_WORKFLOW_NO_URL:-}" == "1" ]]; then
|
||||
exit 0
|
||||
@@ -93,6 +99,7 @@ chmod +x "$bin/gh"
|
||||
|
||||
export PATH="$bin:$PATH"
|
||||
export GH_WORKFLOW_CAPTURE="$tmp/workflow-dispatches"
|
||||
export GH_WORKFLOW_ATTEMPTS="$tmp/workflow-attempts"
|
||||
export GH_WORKTREE="$work"
|
||||
export GH_REMOTE="$remote"
|
||||
|
||||
@@ -150,7 +157,7 @@ if git -C "$operator" cat-file -e "$remote_main_sha^{commit}" 2>/dev/null; then
|
||||
fail "stale-clone fixture already contains the remote-only commit"
|
||||
fi
|
||||
run_release "$operator" candidate 1.2.3 > "$tmp/stale-output" 2> "$tmp/stale-error"
|
||||
grep -Fq "Note: local HEAD is $(git -C "$operator" rev-parse HEAD); candidate source is current origin/main $remote_main_sha." \
|
||||
grep -Fq "Note: local HEAD is $(git -C "$operator" rev-parse HEAD); candidate source is pinned from origin/main $remote_main_sha." \
|
||||
"$tmp/stale-error"
|
||||
cat "$tmp/stale-output"
|
||||
[[ "$(git --git-dir="$remote" rev-parse 'refs/tags/mobile-v1.2.3-rc.1^{commit}')" == \
|
||||
@@ -262,19 +269,40 @@ if GH_TAG_VERIFY_LIGHTWEIGHT=1 run_release "$operator" candidate 9.9.2 >/dev/nul
|
||||
fi
|
||||
[[ "$(git --git-dir="$remote" cat-file -t refs/tags/mobile-v9.9.2-rc.1)" == commit ]]
|
||||
|
||||
# The publisher and operator both reject a main-tip race. The immutable tag may
|
||||
# already exist at the prior tip, but the operator must not report it as a
|
||||
# current-main candidate.
|
||||
# Advancing main during publication must not invalidate the pinned tag.
|
||||
pre_race_main_sha="$(git --git-dir="$remote" rev-parse refs/heads/main)"
|
||||
if GH_MAIN_MOVE_DURING_WORKFLOW=1 run_release "$operator" candidate 9.9.3 > "$tmp/main-race-output" 2>&1; then
|
||||
fail "candidate succeeded after main moved during publication"
|
||||
fi
|
||||
GH_MAIN_MOVE_DURING_WORKFLOW=1 run_release "$operator" candidate 9.9.3 > "$tmp/main-race-output" 2>&1
|
||||
post_race_main_sha="$(git --git-dir="$remote" rev-parse refs/heads/main)"
|
||||
[[ "$pre_race_main_sha" != "$post_race_main_sha" ]]
|
||||
[[ "$(git --git-dir="$remote" rev-parse 'refs/tags/mobile-v9.9.3-rc.1^{commit}')" == \
|
||||
"$pre_race_main_sha" ]]
|
||||
grep -Fq "origin/main moved from requested commit $pre_race_main_sha to $post_race_main_sha during publication" \
|
||||
"$tmp/main-race-output"
|
||||
[[ "$(git --git-dir="$remote" rev-parse 'refs/tags/mobile-v9.9.3-rc.1^{commit}')" == "$pre_race_main_sha" ]]
|
||||
grep -Fq 'Published mobile-v9.9.3-rc.1' "$tmp/main-race-output"
|
||||
|
||||
# Explicit historical source remains pinned even when the source branch advances.
|
||||
run_release "$operator" candidate 7.7.0 --commit "$remote_main_sha"
|
||||
[[ "$(git --git-dir="$remote" rev-parse 'refs/tags/mobile-v7.7.0-rc.1^{commit}')" == "$remote_main_sha" ]]
|
||||
run_release "$operator" candidate 1.2.5 --commit "$remote_main_sha" --source-branch mobile-v1.2
|
||||
[[ "$(git --git-dir="$remote" rev-parse 'refs/tags/mobile-v1.2.5-rc.1^{commit}')" == "$remote_main_sha" ]]
|
||||
before_attempts="$(wc -l < "$GH_WORKFLOW_ATTEMPTS")"
|
||||
before_dispatches="$(wc -l < "$GH_WORKFLOW_CAPTURE")"
|
||||
if run_release "$operator" candidate 7.7.1 --commit "$stable_sha" >/dev/null 2>&1; then
|
||||
fail "accepted a commit outside main history"
|
||||
fi
|
||||
if run_release "$operator" candidate 1.2.6 --source-branch mobile-v1.2 --commit "$new_main_sha" >/dev/null 2>&1; then
|
||||
fail "accepted a main-only commit outside stable history"
|
||||
fi
|
||||
for invalid_sha in main HEAD deadbeef 9999999999999999999999999999999999999999 ''; do
|
||||
if run_release "$operator" candidate 7.7.1 --commit "$invalid_sha" >/dev/null 2>&1; then
|
||||
fail "accepted invalid or absent commit '$invalid_sha'"
|
||||
fi
|
||||
done
|
||||
if GH_COMPARE_FAIL=1 run_release "$operator" candidate 7.7.1 --commit "$remote_main_sha" >/dev/null 2>&1; then
|
||||
fail "accepted unavailable ancestry evidence"
|
||||
fi
|
||||
if run_release "$operator" candidate 7.7.1 --commit "$remote_main_sha" --commit "$new_main_sha" >/dev/null 2>&1; then
|
||||
fail "accepted duplicate commit options"
|
||||
fi
|
||||
[[ "$(wc -l < "$GH_WORKFLOW_ATTEMPTS")" == "$before_attempts" ]]
|
||||
[[ "$(wc -l < "$GH_WORKFLOW_CAPTURE")" == "$before_dispatches" ]]
|
||||
|
||||
# Publishing through a fork is rejected and unsupported gh versions fail before
|
||||
# dispatching any candidate publication.
|
||||
|
||||
Reference in New Issue
Block a user