| 1 | #!/usr/bin/env bash |
| 2 | # Verify that a stable orchestration produced every public release channel. |
| 3 | set -euo pipefail |
| 4 | |
| 5 | repository="${RELEASE_REPOSITORY:?RELEASE_REPOSITORY is required}" |
| 6 | version="${RELEASE_VERSION:?RELEASE_VERSION is required}" |
| 7 | cli_tag="${CLI_TAG:?CLI_TAG is required}" |
| 8 | desktop_tag="${DESKTOP_TAG:?DESKTOP_TAG is required}" |
| 9 | attempts="${VERIFY_ATTEMPTS:-6}" |
| 10 | delay="${VERIFY_DELAY_SECONDS:-10}" |
| 11 | |
| 12 | if [[ ! "$version" =~ ^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$ ]]; then |
| 13 | echo "::error::RELEASE_VERSION must be stable semver, got: $version" >&2 |
| 14 | exit 1 |
| 15 | fi |
| 16 | if [ "$cli_tag" != "v$version" ] || [ "$desktop_tag" != "desktop-v$version" ]; then |
| 17 | echo "::error::release tags do not match version $version: cli=$cli_tag desktop=$desktop_tag" >&2 |
| 18 | exit 1 |
| 19 | fi |
| 20 | |
| 21 | tmp_dir="$(mktemp -d "${TMPDIR:-/tmp}/reasonix-release-postflight.XXXXXX")" |
| 22 | cleanup() { |
| 23 | case "$tmp_dir" in |
| 24 | */reasonix-release-postflight.*) rm -rf -- "$tmp_dir" ;; |
| 25 | *) echo "refusing to clean unexpected postflight directory: $tmp_dir" >&2 ;; |
| 26 | esac |
| 27 | } |
| 28 | trap cleanup EXIT |
| 29 | |
| 30 | gh release view "$cli_tag" --repo "$repository" --json isDraft,isPrerelease,assets >"$tmp_dir/cli.json" |
| 31 | jq -e ' |
| 32 | .isDraft == false and .isPrerelease == false and |
| 33 | ([.assets[].name] as $names | |
| 34 | ["SHA256SUMS", "reasonix-darwin-amd64.tar.gz", "reasonix-darwin-arm64.tar.gz", |
| 35 | "reasonix-linux-amd64.tar.gz", "reasonix-linux-arm64.tar.gz", |
| 36 | "reasonix-windows-amd64.zip", "reasonix-windows-arm64.zip"] | |
| 37 | all(. as $required | $names | index($required))) |
| 38 | ' "$tmp_dir/cli.json" >/dev/null |
| 39 | |
| 40 | gh release view "$desktop_tag" --repo "$repository" --json isDraft,isPrerelease,assets >"$tmp_dir/desktop.json" |
| 41 | jq -e ' |
| 42 | .isDraft == false and .isPrerelease == false and |
| 43 | ([.assets[].name] as $names | |
| 44 | ($names | index("latest.json")) and |
| 45 | (["Reasonix-darwin-universal.dmg", "Reasonix-linux-amd64.deb", |
| 46 | "Reasonix-linux-amd64.tar.gz", "Reasonix-windows-amd64-installer.exe", |
| 47 | "Reasonix-windows-arm64-installer.exe"] | |
| 48 | all(. as $required | ($names | index($required)) and ($names | index($required + ".minisig"))))) |
| 49 | ' "$tmp_dir/desktop.json" >/dev/null |
| 50 | |
| 51 | for attempt in $(seq 1 "$attempts"); do |
| 52 | latest="$(npm view reasonix dist-tags.latest 2>/dev/null || true)" |
| 53 | if [ "$latest" = "$version" ]; then |
| 54 | echo "stable release postflight OK: cli=$cli_tag desktop=$desktop_tag npm-latest=$latest" |
| 55 | exit 0 |
| 56 | fi |
| 57 | echo "npm latest -> ${latest:-<unreadable>}, want $version (attempt $attempt/$attempts)" |
| 58 | if [ "$attempt" -lt "$attempts" ]; then |
| 59 | sleep "$delay" |
| 60 | fi |
| 61 | done |
| 62 | |
| 63 | echo "::error::npm latest did not reach $version" >&2 |
| 64 | exit 1 |
| 65 |