Merge main into push iOS blockers

Co-authored-by: Tom Brow <tomb@block.xyz>
Signed-off-by: Tom Brow <tomb@block.xyz>
This commit is contained in:
npub1tquskdu6yc4h8l7xxtceculxw600grekeq0xg2ukqfrwl7vrzg3quz3gmp
2026-07-31 18:43:16 -07:00
co-authored by Tom Brow
32 changed files with 5554 additions and 162 deletions
+1 -1
View File
@@ -71,7 +71,7 @@ cat >"$body" <<EOF
- **Previous desktop release:** \`$previous_tag\`
- **Proposed immutable tag:** \`desktop-v$version\`
This PR must be merged with **Create a merge commit**. Squash/rebase, stale-head approval, incomplete notes, or a candidate mismatch produce no tag.
This PR must be **squash merged** only after the Desktop Release Candidate check passes. The branch must remain based directly on current \`main\`; stale base, payload drift, incomplete notes, or an unauthorized merge produce no tag.
The checked-in changelog accounts for every non-merge commit in the release range. Publication remains bound to the immutable candidate tag.
EOF
+69
View File
@@ -0,0 +1,69 @@
#!/usr/bin/env bash
set -euo pipefail
repo_root=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
tmp=$(mktemp -d)
trap 'rm -rf "$tmp"' EXIT
mkdir -p "$tmp/bin"
cat >"$tmp/bin/gh" <<'GH'
#!/usr/bin/env bash
set -euo pipefail
printf '%q ' "$@" >>"$GH_CALLS"
printf '\n' >>"$GH_CALLS"
[[ "${1:-}" == api ]] || { echo "expected gh api" >&2; exit 91; }
if [[ "${2:-}" == graphql ]]; then
expected_query='query($owner:String!,$repo:String!,$number:Int!){repository(owner:$owner,name:$repo){pullRequest(number:$number){reviewDecision}}}'
[[ "$#" -eq 12 && "$3" == -f && "$4" == "query=$expected_query" &&
"$5" == -F && "$6" == owner=block &&
"$7" == -F && "$8" == repo=buzz &&
"$9" == -F && "${10}" == number=123 &&
"${11}" == --jq && "${12}" == '.data.repository.pullRequest' ]] || {
echo "GraphQL call does not match the deployed query contract" >&2; exit 92;
}
if [[ -n "${REVIEW_DECISION:-}" ]]; then printf '%s\n' "$REVIEW_DECISION"; else printf '%s\n' '{"reviewDecision":"APPROVED"}'; fi
elif [[ "$#" -eq 4 && "$2" == --paginate && "$3" == --slurp && "$4" == "repos/block/buzz/pulls/123/reviews?per_page=100&page=1" ]]; then
[[ "${GH_FAIL_REVIEWS:-false}" != true ]] || { echo "simulated reviews API failure" >&2; exit 94; }
if [[ -n "${REVIEWS:-}" ]]; then printf '%s\n' "$REVIEWS"; else printf '%s\n' '[[],[{"state":"APPROVED","commit_id":"head","author_association":"MEMBER"}]]'; fi
else
echo "unexpected or malformed gh call: $*" >&2
exit 95
fi
GH
chmod +x "$tmp/bin/gh"
run_authorization() {
(cd "$repo_root" && PATH="$tmp/bin:$PATH" GH_CALLS="$tmp/calls" GH_TOKEN=test \
GITHUB_REPOSITORY=block/buzz PR_NUMBER=123 PR_HEAD_SHA=head \
REVIEW_DECISION="${REVIEW_DECISION-}" REVIEWS="${REVIEWS-}" GH_FAIL_REVIEWS="${GH_FAIL_REVIEWS-false}" \
scripts/verify-desktop-release-authorization.sh)
}
: >"$tmp/calls"
run_authorization
! grep -Fq 'rule-suites' "$tmp/calls"
for invalid in \
'[[{"state":"APPROVED","commit_id":"stale","author_association":"MEMBER"}]]' \
'[[{"state":"APPROVED","commit_id":"head","author_association":"NONE"}]]' \
'[[{"state":"CHANGES_REQUESTED","commit_id":"head","author_association":"MEMBER"}]]'; do
: >"$tmp/calls"
if REVIEWS="$invalid" run_authorization >/dev/null 2>&1; then
echo "invalid approval was accepted: $invalid" >&2
exit 1
fi
done
: >"$tmp/calls"
if REVIEW_DECISION='{"reviewDecision":"CHANGES_REQUESTED"}' run_authorization >/dev/null 2>&1; then
echo "changes-requested review decision was accepted" >&2
exit 1
fi
: >"$tmp/calls"
if GH_FAIL_REVIEWS=true run_authorization >/dev/null 2>&1; then
echo "reviews API failure was ignored" >&2
exit 1
fi
echo "desktop release authorization passed"
+15 -1
View File
@@ -62,8 +62,22 @@ grep -q 'permission-contents: write' "$auto_tag"
grep -q 'GH_TOKEN:.*steps\.release-tagger\.outputs\.token' "$auto_tag"
grep -Fq 'git/refs' "$auto_tag"
grep -Fq 'TAG_PREFIX="desktop-v"' "$auto_tag"
grep -Fq 'target_sha=${{ github.event.pull_request.head.sha }}' "$auto_tag"
grep -Fq 'target_sha=${{ github.event.pull_request.merge_commit_sha }}' "$auto_tag"
grep -Fq 'scripts/verify-desktop-release-merge.sh' "$auto_tag"
grep -Fq 'current \`main\`' "$repo_root/scripts/prepare-desktop-release.sh"
if grep -Fq 'current `main`' "$repo_root/scripts/prepare-desktop-release.sh"; then
echo "desktop release PR body contains executable command substitution" >&2
exit 1
fi
"$repo_root/scripts/test-desktop-release-authorization.sh"
if rg -q 'rule-suites|desktop-release-bypass-authorized|MERGED_BY' \
"$repo_root/scripts/verify-desktop-release-merge.sh" \
"$repo_root/scripts/verify-desktop-release-authorization.sh" \
"$auto_tag"; then
echo "desktop auto-tag still depends on unavailable rule-suite authorization" >&2
exit 1
fi
review_filter="$repo_root/scripts/review-decision-approved.jq"
for fixture in \
'{"reviewDecision":"CHANGES_REQUESTED"}' \
+15
View File
@@ -0,0 +1,15 @@
#!/usr/bin/env bash
set -euo pipefail
: "${PR_HEAD_SHA:?}"
: "${PR_NUMBER:?}"
: "${GITHUB_REPOSITORY:?}"
: "${GH_TOKEN:?}"
review="$(gh api graphql -f query='query($owner:String!,$repo:String!,$number:Int!){repository(owner:$owner,name:$repo){pullRequest(number:$number){reviewDecision}}}' -F owner="${GITHUB_REPOSITORY%/*}" -F repo="${GITHUB_REPOSITORY#*/}" -F number="$PR_NUMBER" --jq '.data.repository.pullRequest')"
reviews="$(gh api --paginate --slurp "repos/$GITHUB_REPOSITORY/pulls/$PR_NUMBER/reviews?per_page=100&page=1")"
valid_approvals="$(jq --arg sha "$PR_HEAD_SHA" '[.[][] | select(.state == "APPROVED" and .commit_id == $sha and (.author_association == "MEMBER" or .author_association == "OWNER" or .author_association == "COLLABORATOR"))] | length' <<<"$reviews")"
if ! jq -e -f scripts/review-decision-approved.jq <<<"$review" >/dev/null || [[ "$valid_approvals" -eq 0 ]]; then
echo "release lacks an exact-head approval" >&2
exit 1
fi
+11 -12
View File
@@ -21,6 +21,7 @@ required_checks=(
"Relay E2E"
"Desktop Build (macOS)"
"DCO Check"
"Desktop Release Candidate"
)
expected_branch="version-bump/$VERSION"
@@ -30,21 +31,19 @@ expected_branch="version-bump/$VERSION"
git fetch origin "$MERGE_SHA" "$PR_HEAD_SHA" refs/heads/main:refs/remotes/origin/main --no-tags
mapfile -t parents < <(git show -s --format='%P' "$MERGE_SHA" | tr ' ' '\n')
[[ "${#parents[@]}" -eq 2 ]] || { echo "desktop release was not merged with a true merge commit" >&2; exit 1; }
[[ "${parents[1]}" == "$PR_HEAD_SHA" ]] || { echo "merge parent 2 is not the reviewed candidate" >&2; exit 1; }
git merge-base --is-ancestor "$PR_HEAD_SHA" origin/main || { echo "candidate is not reachable from current main" >&2; exit 1; }
[[ "${#parents[@]}" -eq 1 ]] || { echo "desktop release was not squash merged" >&2; exit 1; }
base_sha="$(git show "$PR_HEAD_SHA:.release/desktop-candidate.json" | jq -r .base_sha)"
[[ "${parents[0]}" == "$base_sha" ]] || { echo "squash parent is not the frozen candidate base" >&2; exit 1; }
[[ "$(git show -s --format=%T "$MERGE_SHA")" == "$(git show -s --format=%T "$PR_HEAD_SHA")" ]] || {
echo "squash tree differs from the validated candidate" >&2
exit 1
}
git merge-base --is-ancestor "$MERGE_SHA" origin/main || { echo "squash commit is not reachable from current main" >&2; exit 1; }
git checkout --detach "$PR_HEAD_SHA"
scripts/desktop_release.py validate --candidate "$PR_HEAD_SHA" --version "$VERSION" --repo "$GITHUB_REPOSITORY"
review=$(gh api graphql -f query='query($owner:String!,$repo:String!,$number:Int!){repository(owner:$owner,name:$repo){pullRequest(number:$number){reviewDecision}}}' -F owner="${GITHUB_REPOSITORY%/*}" -F repo="${GITHUB_REPOSITORY#*/}" -F number="$PR_NUMBER" --jq '.data.repository.pullRequest')
jq -e -f scripts/review-decision-approved.jq <<<"$review" >/dev/null || {
echo "pull request effective review decision is not APPROVED" >&2
exit 1
}
reviews="$(gh api --paginate "repos/$GITHUB_REPOSITORY/pulls/$PR_NUMBER/reviews?per_page=100")"
valid_approvals="$(jq --arg sha "$PR_HEAD_SHA" '[.[] | select(.state == "APPROVED" and .commit_id == $sha and (.author_association == "MEMBER" or .author_association == "OWNER" or .author_association == "COLLABORATOR"))] | length' <<<"$reviews")"
[[ "$valid_approvals" -gt 0 ]] || { echo "candidate lacks an exact-head approval from a repository member or collaborator" >&2; exit 1; }
scripts/verify-desktop-release-authorization.sh
checks="$(gh api --paginate --slurp "repos/$GITHUB_REPOSITORY/commits/$PR_HEAD_SHA/check-runs?per_page=100")"
for required in "${required_checks[@]}"; do
@@ -59,4 +58,4 @@ jq -e '(.total_count == 0) or (.state == "success")' <<<"$status" >/dev/null ||
exit 1
}
echo "verified reviewed desktop candidate $PR_HEAD_SHA at merge $MERGE_SHA"
echo "verified desktop candidate $PR_HEAD_SHA at squash $MERGE_SHA"