返回 CodeWhale
verify-release-assets.sh
根目录 / scripts / release / verify-release-assets.sh
1 #!/usr/bin/env bash
2 set -euo pipefail
3
4 script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5 repo_root="$(cd "${script_dir}/../.." && pwd)"
6
7 usage() {
8 cat <<'EOF'
9 usage: scripts/release/verify-release-assets.sh [--allow-npm-binary-mismatch] [VERSION]
10
11 Proves the public GitHub Release assets for VERSION were built from the same
12 tag commit that will be published to Cargo/npm.
13
14 Checks:
15 - local tag vVERSION exists
16 - remote tag vVERSION resolves to the same commit SHA
17 - GitHub Release vVERSION exists
18 - a successful Release workflow run used that SHA
19 - npm/codewhale release:check sees the fresh binary/archive/installer matrix
20 and both required checksum manifests
21
22 Set GH_BIN=/path/to/gh to choose a GitHub CLI binary. Set
23 CODEWHALE_GITHUB_REPO=owner/repo or CODEWHALE_RELEASE_REMOTE=remote to override
24 the default Hmbown/CodeWhale origin check.
25 EOF
26 }
27
28 allow_npm_binary_mismatch=0
29 version=""
30
31 while (($# > 0)); do
32 case "$1" in
33 --allow-npm-binary-mismatch)
34 allow_npm_binary_mismatch=1
35 ;;
36 -h|--help)
37 usage
38 exit 0
39 ;;
40 *)
41 if [[ -n "${version}" ]]; then
42 usage >&2
43 exit 2
44 fi
45 version="$1"
46 ;;
47 esac
48 shift
49 done
50
51 cd "${repo_root}"
52
53 if [[ -z "${version}" ]]; then
54 version="$(grep -E '^version = "' Cargo.toml | head -n1 | sed -E 's/^version = "([^"]+)".*/\1/')"
55 fi
56 version="${version#v}"
57 tag="v${version}"
58
59 if [[ -z "${version}" ]]; then
60 echo "Could not determine release version." >&2
61 exit 1
62 fi
63
64 repo="${CODEWHALE_GITHUB_REPO:-Hmbown/CodeWhale}"
65 remote="${CODEWHALE_RELEASE_REMOTE:-origin}"
66 gh_bin="${GH_BIN:-gh}"
67
68 if ! command -v "${gh_bin}" >/dev/null 2>&1; then
69 echo "GitHub CLI not found: ${gh_bin}" >&2
70 echo "Install gh or set GH_BIN=/path/to/gh." >&2
71 exit 1
72 fi
73
74 local_sha="$(git rev-list -n 1 "${tag}" 2>/dev/null || true)"
75 if [[ -z "${local_sha}" ]]; then
76 echo "Local tag ${tag} does not exist." >&2
77 exit 1
78 fi
79
80 remote_sha="$(git ls-remote --tags "${remote}" "refs/tags/${tag}^{}" | awk 'NR == 1 {print $1}')"
81 if [[ -z "${remote_sha}" ]]; then
82 remote_sha="$(git ls-remote --tags "${remote}" "refs/tags/${tag}" | awk 'NR == 1 {print $1}')"
83 fi
84 if [[ -z "${remote_sha}" ]]; then
85 echo "Remote tag ${tag} does not exist on ${remote}." >&2
86 exit 1
87 fi
88 if [[ "${local_sha}" != "${remote_sha}" ]]; then
89 echo "Tag SHA mismatch for ${tag}:" >&2
90 echo " local : ${local_sha}" >&2
91 echo " remote: ${remote_sha}" >&2
92 exit 1
93 fi
94 echo "Tag check OK: ${tag} -> ${local_sha}"
95
96 release_url="$("${gh_bin}" release view "${tag}" --repo "${repo}" --json url --jq '.url')"
97 if [[ -z "${release_url}" ]]; then
98 echo "GitHub Release ${tag} was not found in ${repo}." >&2
99 exit 1
100 fi
101 echo "GitHub Release OK: ${release_url}"
102
103 run_summary="$(
104 TAG_SHA="${local_sha}" "${gh_bin}" run list \
105 --repo "${repo}" \
106 --workflow "Release" \
107 --limit 100 \
108 --json databaseId,headSha,headBranch,event,conclusion,status,createdAt,updatedAt,url \
109 --jq 'map(select(.headSha == env.TAG_SHA and .conclusion == "success" and (.event == "push" or .event == "workflow_dispatch"))) | sort_by(.updatedAt) | last | if . == null then empty else "\(.databaseId)\t\(.headBranch)\t\(.event)\t\(.url)" end'
110 )"
111 if [[ -z "${run_summary}" ]]; then
112 echo "No successful Release workflow run found in the last 100 Release runs for ${tag} at ${local_sha}." >&2
113 echo "Rerun the Release workflow before publishing Cargo/npm." >&2
114 exit 1
115 fi
116 printf 'Release workflow OK: %s\n' "${run_summary}"
117
118 npm_package_version="$(node -p "require('./npm/codewhale/package.json').version")"
119 npm_binary_version="$(
120 node -p "const p=require('./npm/codewhale/package.json'); p.codewhaleBinaryVersion || p.deepseekBinaryVersion || p.version"
121 )"
122 if [[ "${npm_package_version}" != "${version}" ]]; then
123 echo "npm/codewhale package version ${npm_package_version} does not match ${version}." >&2
124 exit 1
125 fi
126 if [[ "${npm_binary_version}" != "${version}" && "${allow_npm_binary_mismatch}" != "1" ]]; then
127 echo "npm/codewhale codewhaleBinaryVersion ${npm_binary_version} does not match ${version}." >&2
128 echo "Use --allow-npm-binary-mismatch only for an intentional packaging-only npm release." >&2
129 exit 1
130 fi
131
132 (
133 cd npm/codewhale
134 env \
135 -u CODEWHALE_RELEASE_BASE_URL \
136 -u DEEPSEEK_TUI_RELEASE_BASE_URL \
137 -u DEEPSEEK_RELEASE_BASE_URL \
138 -u CODEWHALE_USE_CNB_MIRROR \
139 DEEPSEEK_TUI_VERSION="${version}" \
140 DEEPSEEK_TUI_GITHUB_REPO="${repo}" \
141 CODEWHALE_ALLOW_NPM_BINARY_MISMATCH="${allow_npm_binary_mismatch}" \
142 npm run release:check
143 )
144
145 echo "Release asset gate OK: ${tag} assets match ${local_sha} and npm/codewhale is ready for publish."
146
146 lines BASH