-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrelease
More file actions
executable file
·224 lines (201 loc) · 7.23 KB
/
Copy pathrelease
File metadata and controls
executable file
·224 lines (201 loc) · 7.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
#!/usr/bin/env bash
# Repository-owned release policy guard for the Base Bash v2 release line.
release_script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)" || exit 1
# shellcheck source=release-version-policy.sh
source "$release_script_dir/release-version-policy.sh" || exit 1
release_usage() {
cat >&2 << 'EOF'
Usage:
scripts/release <check|plan|notes|refs|publish> --version <version> [options]
Allowed release identifiers:
2.MINOR.PATCH
2.MINOR.PATCH-alpha.N
2.MINOR.PATCH-beta.N
2.MINOR.PATCH-rc.N
MINOR and PATCH are non-negative integers without leading zeroes. N is a
positive integer without leading zeroes. Stable and approved prerelease
publication use the same verified-artifact and immutable-tag gates.
The refs command is a read-only preflight that fails closed when the candidate
tag already exists locally or on origin. Published tags are immutable.
EOF
}
release_error() {
printf 'ERROR: %s\n' "$*" >&2
}
release_check_tag_refs() {
local repo_root="$1"
local tag_name="$2"
local remote_refs=""
local git_status
if ! command -v git > /dev/null 2>&1; then
release_error "Git is required to inspect release tag '$tag_name'."
return 1
fi
if git -C "$repo_root" show-ref --verify --quiet "refs/tags/$tag_name"; then
release_error "Release tag '$tag_name' already exists in the local repository."
release_error "Remove only a confirmed stale local ref before retrying; never retag a published release."
return 1
else
git_status=$?
if ((git_status != 1)); then
release_error "Unable to inspect the local release tag '$tag_name' (git status $git_status)."
return 1
fi
fi
if ! remote_refs="$(git -C "$repo_root" ls-remote --tags origin "refs/tags/$tag_name" 2> /dev/null)"; then
release_error "Unable to inspect release tag '$tag_name' on origin; refusing to continue."
return 1
fi
if [[ -n "$remote_refs" ]]; then
release_error "Release tag '$tag_name' already exists on origin."
release_error "Published tags are immutable; choose a new policy-compliant release identifier."
return 1
fi
printf 'Release tag %s is absent locally and on origin.\n' "$tag_name"
}
main() {
local canonical_manifest
local command="${1-}"
local manifest_value=""
local version=""
local dry_run=0
local index
local release_driver="${BASE_BASH_RELEASE_BASECTL:-basectl}"
local script_dir repo_root
local -a arguments=("$@")
local -a delegated_arguments=()
local seen_dry_run=0
local seen_format=0
local seen_manifest=0
local seen_version=0
local seen_yes=0
case "$command" in
check | plan | notes | refs | publish) ;;
"" | -h | --help | help)
release_usage
return 2
;;
*)
release_error "Unknown release command '$command'."
release_usage
return 2
;;
esac
script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)" || return 1
repo_root="$(cd -- "$script_dir/.." && pwd -P)" || return 1
canonical_manifest="$repo_root/base_manifest.yaml"
if [[ ! -f "$canonical_manifest" ]]; then
release_error "Canonical release manifest was not found at '$canonical_manifest'."
return 1
fi
index=1
while ((index < ${#arguments[@]})); do
case "${arguments[$index]}" in
--version)
if ((seen_version)); then
release_error "Option '--version' may be provided only once."
return 2
fi
seen_version=1
index=$((index + 1))
if ((index >= ${#arguments[@]})) || [[ -z "${arguments[$index]}" ]]; then
release_error "Option '--version' requires an argument."
return 2
fi
version="${arguments[$index]}"
;;
--manifest)
if ((seen_manifest)); then
release_error "Option '--manifest' may be provided only once."
return 2
fi
seen_manifest=1
index=$((index + 1))
if ((index >= ${#arguments[@]})) || [[ -z "${arguments[$index]}" ]]; then
release_error "Option '--manifest' requires an argument."
return 2
fi
manifest_value="${arguments[$index]}"
if [[ "$manifest_value" != "base_manifest.yaml" &&
"$manifest_value" != "./base_manifest.yaml" &&
"$manifest_value" != "$canonical_manifest" ]]; then
release_error "Release operations must use the canonical manifest at '$canonical_manifest'."
return 1
fi
;;
--format)
if [[ "$command" != "check" ]]; then
release_error "Option '--format' is only supported by release check."
return 2
fi
if ((seen_format)); then
release_error "Option '--format' may be provided only once."
return 2
fi
seen_format=1
index=$((index + 1))
if ((index >= ${#arguments[@]})) || [[ -z "${arguments[$index]}" ]]; then
release_error "Option '--format' requires an argument."
return 2
fi
;;
--dry-run)
if [[ "$command" != "publish" ]]; then
release_error "Option '--dry-run' is only supported by release publish."
return 2
fi
if ((seen_dry_run)); then
release_error "Option '--dry-run' may be provided only once."
return 2
fi
seen_dry_run=1
dry_run=1
;;
--yes)
if [[ "$command" != "publish" ]]; then
release_error "Option '--yes' is only supported by release publish."
return 2
fi
if ((seen_yes)); then
release_error "Option '--yes' may be provided only once."
return 2
fi
seen_yes=1
;;
-h | --help)
release_usage
return 0
;;
*)
release_error "Unknown release $command option '${arguments[$index]}'."
return 2
;;
esac
index=$((index + 1))
done
if [[ -z "$version" ]]; then
release_error "Release commands require --version."
return 2
fi
base_bash_release_version_supported "$version" || {
release_error "Version '$version' is outside the supported Base Bash v2 release policy."
release_error "Use 2.MINOR.PATCH or an approved alpha.N, beta.N, or rc.N prerelease."
return 1
}
if [[ "$command" == "refs" ]]; then
release_check_tag_refs "$repo_root" "v$version"
return $?
fi
if [[ "$command" == "publish" && "$dry_run" -eq 0 ]]; then
release_check_tag_refs "$repo_root" "v$version" || return $?
fi
delegated_arguments=("$@")
if ((seen_manifest == 0)); then
delegated_arguments+=(--manifest "$canonical_manifest")
fi
(
cd -- "$repo_root" || exit 1
"$release_driver" release "${delegated_arguments[@]}"
)
}
main "$@"