| 1 | #!/usr/bin/env bash |
| 2 | set -euo pipefail |
| 3 | |
| 4 | repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" |
| 5 | script="${repo_root}/scripts/release/require-rc-receipt.sh" |
| 6 | tmp_dir="$(mktemp -d)" |
| 7 | trap 'rm -rf "${tmp_dir}"' EXIT |
| 8 | |
| 9 | sha="0123456789abcdef0123456789abcdef01234567" |
| 10 | |
| 11 | # Fake gh: answers the two API calls from fixture files and applies the |
| 12 | # caller's --jq filter with the real jq, so the filters themselves are tested. |
| 13 | fake_gh="${tmp_dir}/gh" |
| 14 | cat > "${fake_gh}" <<'EOF' |
| 15 | #!/usr/bin/env bash |
| 16 | set -euo pipefail |
| 17 | [[ "$1" == "api" ]] || { echo "unexpected: $*" >&2; exit 9; } |
| 18 | path="$2" |
| 19 | filter="$4" |
| 20 | case "${path}" in |
| 21 | */workflows/release-candidate.yml/runs\?*) fixture="${FIXTURE_DIR}/runs.json" ;; |
| 22 | */actions/runs/*/jobs\?*) |
| 23 | run_id="${path#*/actions/runs/}" |
| 24 | run_id="${run_id%%/*}" |
| 25 | fixture="${FIXTURE_DIR}/jobs-${run_id}.json" |
| 26 | ;; |
| 27 | *) echo "unexpected path: ${path}" >&2; exit 9 ;; |
| 28 | esac |
| 29 | jq -r "${filter}" "${fixture}" |
| 30 | EOF |
| 31 | chmod +x "${fake_gh}" |
| 32 | export RC_RECEIPT_GH="${fake_gh}" |
| 33 | export FIXTURE_DIR="${tmp_dir}" |
| 34 | |
| 35 | expect_pass() { |
| 36 | local label="$1" |
| 37 | if ! "${script}" owner/repo "${sha}" >"${tmp_dir}/out" 2>&1; then |
| 38 | echo "FAIL (${label}): expected a receipt" >&2 |
| 39 | cat "${tmp_dir}/out" >&2 |
| 40 | exit 1 |
| 41 | fi |
| 42 | } |
| 43 | expect_fail() { |
| 44 | local label="$1" |
| 45 | if "${script}" owner/repo "${2:-${sha}}" >"${tmp_dir}/out" 2>&1; then |
| 46 | echo "FAIL (${label}): expected refusal" >&2 |
| 47 | cat "${tmp_dir}/out" >&2 |
| 48 | exit 1 |
| 49 | fi |
| 50 | } |
| 51 | |
| 52 | # 1. No RC run at all: refuse. |
| 53 | echo '{"workflow_runs":[]}' > "${tmp_dir}/runs.json" |
| 54 | expect_fail "no runs" |
| 55 | grep -q "No green release-candidate run" "${tmp_dir}/out" |
| 56 | |
| 57 | # 2. Green RC run whose Parity job was skipped: refuse. |
| 58 | cat > "${tmp_dir}/runs.json" <<EOF |
| 59 | {"workflow_runs":[{"id":11,"head_sha":"${sha}","conclusion":"success","event":"workflow_dispatch","html_url":"https://example.invalid/11"}]} |
| 60 | EOF |
| 61 | echo '{"jobs":[{"name":"Parity / Workspace parity","conclusion":"skipped"},{"name":"Verify exact candidate web surface","conclusion":"success"}]}' > "${tmp_dir}/jobs-11.json" |
| 62 | expect_fail "parity skipped" |
| 63 | |
| 64 | # 3. A run for a different SHA never counts, even if the API returned it. |
| 65 | cat > "${tmp_dir}/runs.json" <<'EOF' |
| 66 | {"workflow_runs":[{"id":12,"head_sha":"ffffffffffffffffffffffffffffffffffffffff","conclusion":"success","event":"workflow_dispatch","html_url":"https://example.invalid/12"}]} |
| 67 | EOF |
| 68 | echo '{"jobs":[{"name":"Parity / Workspace parity","conclusion":"success"}]}' > "${tmp_dir}/jobs-12.json" |
| 69 | expect_fail "other sha" |
| 70 | |
| 71 | # 4. Green RC run with green Parity on the exact SHA: receipt. |
| 72 | cat > "${tmp_dir}/runs.json" <<EOF |
| 73 | {"workflow_runs":[ |
| 74 | {"id":11,"head_sha":"${sha}","conclusion":"success","event":"workflow_dispatch","html_url":"https://example.invalid/11"}, |
| 75 | {"id":13,"head_sha":"${sha}","conclusion":"success","event":"workflow_dispatch","html_url":"https://example.invalid/13"} |
| 76 | ]} |
| 77 | EOF |
| 78 | echo '{"jobs":[{"name":"Parity / Workspace parity","conclusion":"success"}]}' > "${tmp_dir}/jobs-13.json" |
| 79 | expect_pass "green parity" |
| 80 | grep -q "https://example.invalid/13 (Parity green)" "${tmp_dir}/out" |
| 81 | |
| 82 | # 5. Malformed SHA is rejected before any API call. |
| 83 | expect_fail "short sha" "abc123" |
| 84 | expect_fail "uppercase sha" "0123456789ABCDEF0123456789ABCDEF01234567" |
| 85 | |
| 86 | echo "require-rc-receipt tests passed" |
| 87 |