返回 CodeWhale
require-rc-receipt.sh
根目录 / scripts / release / require-rc-receipt.sh
1 #!/usr/bin/env bash
2 # Refuse a release unless a green release-candidate run validated the exact
3 # commit, including its Parity job.
4 #
5 # Usage: require-rc-receipt.sh <owner/repo> <40-char sha>
6 #
7 # The receipt is a completed, successful `release-candidate.yml` run for
8 # <sha>, dispatched by hand, whose Parity job (the shared
9 # release-parity.yml gate) concluded success. A green run whose Parity job
10 # was skipped is not a receipt. Requires `gh` authenticated with actions:read.
11 #
12 # RC_RECEIPT_GH overrides the gh executable (tests only).
13 set -euo pipefail
14
15 repo="${1:-}"
16 sha="${2:-}"
17 gh_bin="${RC_RECEIPT_GH:-gh}"
18
19 if [[ -z "${repo}" || -z "${sha}" ]]; then
20 echo "usage: $0 <owner/repo> <sha>" >&2
21 exit 2
22 fi
23 if ! [[ "${repo}" =~ ^[A-Za-z0-9._-]+/[A-Za-z0-9._-]+$ ]]; then
24 echo "::error::Repository '${repo}' must be owner/name." >&2
25 exit 2
26 fi
27 if [[ "${#sha}" -ne 40 || "${sha}" =~ [^0-9a-f] ]]; then
28 echo "::error::Release SHA must be a full 40-character lowercase commit SHA, got '${sha}'." >&2
29 exit 2
30 fi
31
32 # sha is validated hex, so it is safe to place inside the jq program.
33 runs="$("${gh_bin}" api \
34 "repos/${repo}/actions/workflows/release-candidate.yml/runs?head_sha=${sha}&status=success&per_page=100" \
35 --jq ".workflow_runs[] | select(.head_sha == \"${sha}\" and .conclusion == \"success\" and .event == \"workflow_dispatch\") | [.id, .html_url] | @tsv")"
36
37 while IFS=$'\t' read -r run_id run_url; do
38 [[ -n "${run_id}" ]] || continue
39 if ! [[ "${run_id}" =~ ^[0-9]+$ ]]; then
40 echo "::error::Unexpected run id '${run_id}' from the Actions API." >&2
41 exit 1
42 fi
43 # Jobs from a reusable workflow are named "<caller name> / <job name>".
44 parity_green="$("${gh_bin}" api \
45 "repos/${repo}/actions/runs/${run_id}/jobs?filter=latest&per_page=100" \
46 --jq '[.jobs[] | select((.name == "Parity" or (.name | startswith("Parity / "))) and .conclusion == "success")] | length')"
47 if [[ "${parity_green}" =~ ^[0-9]+$ && "${parity_green}" -gt 0 ]]; then
48 echo "Release-candidate receipt for ${sha}: ${run_url} (Parity green)"
49 exit 0
50 fi
51 echo "::warning::Release-candidate run ${run_url} is green but has no successful Parity job; it is not a receipt." >&2
52 done <<< "${runs}"
53
54 echo "::error::No green release-candidate run with a passing Parity job for ${sha}. Validate that exact commit first: gh workflow run release-candidate.yml --ref main -f expected_sha=${sha} (use the release tag as --ref if main has moved past it), wait for it to go green, then re-run this Release. Never move a tag to a different SHA to get past this." >&2
55 exit 1
56
56 lines BASH