返回 DeepSeek-Reasonix
decide-cli-release-publication.sh
根目录 / scripts / decide-cli-release-publication.sh
1 #!/usr/bin/env bash
2 set -euo pipefail
3
4 channel="${1:-}"
5 tag="${2:-}"
6 repository="${3:-}"
7 release_json="${4:-}"
8 checksums="${5:-}"
9
10 stable_tag_pattern='^v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$'
11 preview_tag_pattern='^v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)-preview\.(0|[1-9][0-9]*)$'
12 release_tag_pattern='^v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-([0-9A-Za-z-]+)(\.[0-9A-Za-z-]+)*)?)?$'
13
14 case "$channel" in
15 stable)
16 tag_pattern="$stable_tag_pattern"
17 expected_prerelease=false
18 ;;
19 preview)
20 tag_pattern="$preview_tag_pattern"
21 expected_prerelease=true
22 ;;
23 any)
24 tag_pattern="$release_tag_pattern"
25 expected_prerelease=any
26 ;;
27 *)
28 echo "CLI publication channel must be stable, preview, or any: $channel" >&2
29 exit 2
30 ;;
31 esac
32
33 if [[ ! "$tag" =~ $tag_pattern ]]; then
34 echo "invalid $channel CLI publication tag: $tag" >&2
35 exit 1
36 fi
37 if [[ ! "$repository" =~ ^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$ ]]; then
38 echo "invalid GitHub repository: $repository" >&2
39 exit 1
40 fi
41
42 if [ "$release_json" = "-" ]; then
43 echo publish
44 exit 0
45 fi
46 if [ ! -f "$release_json" ]; then
47 echo "CLI GitHub release record does not exist: $release_json" >&2
48 exit 1
49 fi
50 if [ ! -f "$checksums" ]; then
51 echo "CLI GitHub release checksum asset does not exist: $checksums" >&2
52 exit 1
53 fi
54
55 required_assets='[
56 "reasonix-darwin-amd64.tar.gz",
57 "reasonix-darwin-arm64.tar.gz",
58 "reasonix-linux-amd64.tar.gz",
59 "reasonix-linux-arm64.tar.gz",
60 "reasonix-windows-amd64.zip",
61 "reasonix-windows-arm64.zip",
62 "SHA256SUMS"
63 ]'
64
65 jq -e \
66 --arg tag "$tag" \
67 --arg repository "$repository" \
68 --arg expected_prerelease "$expected_prerelease" \
69 --argjson required "$required_assets" '
70 (type == "object") and
71 (.tag_name == $tag) and
72 (.draft == false) and
73 (if $expected_prerelease == "any"
74 then (.prerelease | type == "boolean")
75 else (.prerelease == ($expected_prerelease == "true"))
76 end) and
77 (.html_url == ("https://github.com/" + $repository + "/releases/tag/" + $tag)) and
78 (.assets | type == "array") and
79 (.assets | length == ($required | length)) and
80 ((.assets | map(.name) | sort) == ($required | sort)) and
81 (.assets | all(
82 (type == "object") and
83 (.state == "uploaded") and
84 (.size | type == "number" and . > 0 and . <= 1073741824 and floor == .) and
85 (.browser_download_url ==
86 ("https://github.com/" + $repository + "/releases/download/" + $tag + "/" + .name)) and
87 (.digest | type == "string" and test("^sha256:[0-9a-f]{64}$"))
88 ))
89 ' "$release_json" >/dev/null || {
90 echo "existing CLI GitHub release is incomplete or does not match approved release $tag" >&2
91 exit 1
92 }
93
94 expected_checksums="$(mktemp)"
95 actual_checksums="$(mktemp)"
96 trap 'rm -f "$expected_checksums" "$actual_checksums"' EXIT
97
98 jq -r '
99 .assets[] |
100 select(.name != "SHA256SUMS") |
101 ((.digest | sub("^sha256:"; "")) + " " + .name)
102 ' "$release_json" | LC_ALL=C sort >"$expected_checksums"
103
104 if ! awk '
105 BEGIN { valid = 1 }
106 $0 !~ /^[0-9a-f]{64} reasonix-(darwin|linux|windows)-(amd64|arm64)\.(tar\.gz|zip)$/ {
107 valid = 0
108 }
109 { print }
110 END { if (NR != 6 || !valid) exit 1 }
111 ' "$checksums" | LC_ALL=C sort >"$actual_checksums"; then
112 echo "existing CLI SHA256SUMS is malformed or incomplete" >&2
113 exit 1
114 fi
115
116 if ! cmp -s "$expected_checksums" "$actual_checksums"; then
117 echo "existing CLI SHA256SUMS does not match GitHub asset digests" >&2
118 exit 1
119 fi
120
121 checksum_asset_digest="$(
122 jq -er '.assets[] | select(.name == "SHA256SUMS") | .digest | sub("^sha256:"; "")' \
123 "$release_json"
124 )"
125 downloaded_checksum_digest="$(shasum -a 256 "$checksums" | awk '{print $1}')"
126 if [ "$downloaded_checksum_digest" != "$checksum_asset_digest" ]; then
127 echo "downloaded CLI SHA256SUMS digest does not match GitHub release metadata" >&2
128 exit 1
129 fi
130
131 echo reuse
132
132 lines BASH