返回 CodeWhale
validate-crate-publish-order.test.sh
根目录 / scripts / release / validate-crate-publish-order.test.sh
1 #!/usr/bin/env bash
2 set -euo pipefail
3
4 script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5 tmp_dir="$(mktemp -d)"
6 trap 'rm -rf "${tmp_dir}"' EXIT
7
8 metadata_file="${tmp_dir}/metadata.json"
9 cat >"${metadata_file}" <<'JSON'
10 {
11 "workspace_members": ["build", "core", "tui", "app", "cli"],
12 "packages": [
13 {
14 "id": "build",
15 "name": "codewhale-build-support",
16 "version": "0.9.5",
17 "dependencies": []
18 },
19 {
20 "id": "core",
21 "name": "codewhale-core",
22 "version": "0.9.5",
23 "dependencies": [
24 {"name": "codewhale-cli", "path": "/workspace/cli", "kind": "dev"}
25 ]
26 },
27 {
28 "id": "tui",
29 "name": "codewhale-tui",
30 "version": "0.9.5",
31 "dependencies": [
32 {"name": "codewhale-build-support", "path": "/workspace/build", "kind": "build"},
33 {"name": "codewhale-core", "path": "/workspace/core", "kind": null}
34 ]
35 },
36 {
37 "id": "app",
38 "name": "codewhale-app-server",
39 "version": "0.9.5",
40 "dependencies": [
41 {"name": "codewhale-core", "path": "/workspace/core", "kind": null}
42 ]
43 },
44 {
45 "id": "cli",
46 "name": "codewhale-cli",
47 "version": "0.9.5",
48 "dependencies": [
49 {"name": "codewhale-tui", "path": "/workspace/tui", "kind": null},
50 {"name": "codewhale-app-server", "path": "/workspace/app", "kind": null}
51 ]
52 }
53 ]
54 }
55 JSON
56
57 expect_validation_failure() {
58 local label="$1"
59 local expected="$2"
60 local fixture="$3"
61 shift 3
62
63 local output="${tmp_dir}/${label}.txt"
64 if python3 "${script_dir}/validate-crate-publish-order.py" \
65 --metadata-file "${fixture}" "$@" >"${output}" 2>&1; then
66 echo "${label} unexpectedly passed" >&2
67 exit 1
68 fi
69 grep -F "${expected}" "${output}" >/dev/null
70 if grep -F "Traceback" "${output}" >/dev/null; then
71 echo "${label} emitted an unhandled traceback" >&2
72 exit 1
73 fi
74 }
75
76 expect_validation_failure \
77 duplicate-crate \
78 "publish package list contains duplicates: codewhale-core" \
79 "${metadata_file}" \
80 codewhale-build-support \
81 codewhale-core \
82 codewhale-core \
83 codewhale-tui \
84 codewhale-app-server \
85 codewhale-cli
86
87 expect_validation_failure \
88 missing-crate \
89 "publish package list is missing workspace crates: codewhale-app-server" \
90 "${metadata_file}" \
91 codewhale-build-support \
92 codewhale-core \
93 codewhale-tui \
94 codewhale-cli
95
96 expect_validation_failure \
97 extra-crate \
98 "publish package list contains non-workspace crates: codewhale-extra" \
99 "${metadata_file}" \
100 codewhale-build-support \
101 codewhale-core \
102 codewhale-tui \
103 codewhale-app-server \
104 codewhale-cli \
105 codewhale-extra
106
107 mixed_metadata_file="${tmp_dir}/mixed-metadata.json"
108 python3 - "${metadata_file}" "${mixed_metadata_file}" <<'PY'
109 import pathlib
110 import sys
111
112 source = pathlib.Path(sys.argv[1]).read_text(encoding="utf-8")
113 mixed = source.replace('"version": "0.9.5"', '"version": "0.9.4"', 1)
114 if mixed == source:
115 raise SystemExit("failed to create mixed-version Cargo metadata fixture")
116 pathlib.Path(sys.argv[2]).write_text(mixed, encoding="utf-8")
117 PY
118 expect_validation_failure \
119 mixed-versions \
120 "workspace packages have mixed versions: 0.9.4, 0.9.5" \
121 "${mixed_metadata_file}" \
122 codewhale-build-support \
123 codewhale-core \
124 codewhale-tui \
125 codewhale-app-server \
126 codewhale-cli
127
128 nonrelease_metadata_file="${tmp_dir}/nonrelease-metadata.json"
129 cat >"${nonrelease_metadata_file}" <<'JSON'
130 {
131 "workspace_members": ["helper", "core"],
132 "packages": [
133 {
134 "id": "helper",
135 "name": "internal-helper",
136 "version": "0.9.5",
137 "dependencies": []
138 },
139 {
140 "id": "core",
141 "name": "codewhale-core",
142 "version": "0.9.5",
143 "dependencies": [
144 {"name": "internal-helper", "path": "/workspace/helper", "kind": null}
145 ]
146 }
147 ]
148 }
149 JSON
150 expect_validation_failure \
151 nonrelease-workspace-dependency \
152 "codewhale-core depends on workspace crate internal-helper [normal], which is not in the codewhale-* release inventory" \
153 "${nonrelease_metadata_file}" \
154 codewhale-core
155
156 bad_output="${tmp_dir}/bad-order.txt"
157 if python3 "${script_dir}/validate-crate-publish-order.py" \
158 --metadata-file "${metadata_file}" \
159 codewhale-build-support \
160 codewhale-tui \
161 codewhale-core \
162 codewhale-app-server \
163 codewhale-cli >"${bad_output}" 2>&1; then
164 echo "v0.9.5 publication order unexpectedly passed" >&2
165 exit 1
166 fi
167 grep -F \
168 "codewhale-tui (position 2) depends on codewhale-core (position 3) [normal]" \
169 "${bad_output}" >/dev/null
170
171 good_output="${tmp_dir}/good-order.txt"
172 python3 "${script_dir}/validate-crate-publish-order.py" \
173 --metadata-file "${metadata_file}" \
174 codewhale-build-support \
175 codewhale-core \
176 codewhale-tui \
177 codewhale-app-server \
178 codewhale-cli >"${good_output}"
179 grep -F $'version\t0.9.5\t' "${good_output}" >/dev/null
180 grep -F $'crate\tcodewhale-core\t1' "${good_output}" >/dev/null
181
182 # Keep the checked-in order synchronized with the live locked workspace graph.
183 # shellcheck source=scripts/release/crates.sh
184 source "${script_dir}/crates.sh"
185 python3 "${script_dir}/validate-crate-publish-order.py" \
186 "${release_crates[@]}" >"${tmp_dir}/workspace-order.txt"
187
188 echo "crate publication order validation tests passed"
189
189 lines BASH