forked from coder/coder
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrelease.sh
More file actions
executable file
·191 lines (160 loc) · 5.21 KB
/
release.sh
File metadata and controls
executable file
·191 lines (160 loc) · 5.21 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
#!/usr/bin/env bash
set -euo pipefail
# shellcheck source=scripts/lib.sh
source "$(dirname "${BASH_SOURCE[0]}")/lib.sh"
cdroot
usage() {
cat <<EOH
Usage: ./release.sh [--dry-run] [-h | --help] [--ref <ref>] [--major | --minor | --patch] [--force]
This script should be called to create a new release.
When run, this script will display the new version number and optionally a
preview of the release notes. The new version will be selected automatically
based on if the release contains breaking changes or not. If the release
contains breaking changes, a new minor version will be created. Otherwise, a
new patch version will be created.
To mark a release as containing breaking changes, the commit title should
either contain a known prefix with an exclamation mark ("feat!:",
"feat(api)!:") or the PR that was merged can be tagged with the
"release/breaking" label.
GitHub labels that affect release notes:
- release/breaking: Shown under BREAKING CHANGES, prevents patch release.
- release/experimental: Shown at the bottom under Experimental.
- security: Shown under SECURITY.
Flags:
Set --major or --minor to force a larger version bump, even when there are no
breaking changes. By default a patch version will be created, --patch is no-op.
Set --force force the provided increment to be used (e.g. --patch), even if
there are breaking changes, etc.
Set --ref if you need to specify a specific commit that the new version will
be tagged at, otherwise the latest commit will be used.
Set --dry-run to see what this script would do without making actual changes.
EOH
}
branch=main
dry_run=0
ref=
increment=
force=0
args="$(getopt -o h -l dry-run,help,ref:,major,minor,patch,force -- "$@")"
eval set -- "$args"
while true; do
case "$1" in
--dry-run)
dry_run=1
shift
;;
-h | --help)
usage
exit 0
;;
--ref)
ref="$2"
shift 2
;;
--major | --minor | --patch)
if [[ -n $increment ]]; then
error "Cannot specify multiple version increments."
fi
increment=${1#--}
shift
;;
--force)
force=1
shift
;;
--)
shift
break
;;
*)
error "Unrecognized option: $1"
;;
esac
done
# Check dependencies.
dependencies gh sort
if [[ -z $increment ]]; then
# Default to patch versions.
increment="patch"
fi
# Make sure the repository is up-to-date before generating release notes.
log "Fetching $branch and tags from origin..."
git fetch --quiet --tags origin "$branch"
# Resolve to the latest ref on origin/main unless otherwise specified.
ref=$(git rev-parse --short "${ref:-origin/$branch}")
# Make sure that we're running the latest release script.
if [[ -n $(git diff --name-status origin/"$branch" -- ./scripts/release.sh) ]]; then
error "Release script is out-of-date. Please check out the latest version and try again."
fi
# Check the current version tag from GitHub (by number) using the API to
# ensure no local tags are considered.
log "Checking GitHub for latest release..."
versions_out="$(gh api -H "Accept: application/vnd.github+json" /repos/coder/coder/git/refs/tags -q '.[].ref | split("/") | .[2]' | grep '^v' | sort -r -V)"
mapfile -t versions <<<"$versions_out"
old_version=${versions[0]}
log "Latest release: $old_version"
log
trap 'log "Check commit metadata failed, you can try to set \"export CODER_IGNORE_MISSING_COMMIT_METADATA=1\" and try again, if you know what you are doing."' EXIT
# shellcheck source=scripts/release/check_commit_metadata.sh
source "$SCRIPT_DIR/release/check_commit_metadata.sh" "$old_version" "$ref"
trap - EXIT
tag_version_args=(--old-version "$old_version" --ref "$ref" --"$increment")
if ((force == 1)); then
tag_version_args+=(--force)
fi
log "Executing DRYRUN of release tagging..."
new_version="$(execrelative ./release/tag_version.sh "${tag_version_args[@]}" --dry-run)"
log
read -p "Continue? (y/n) " -n 1 -r continue_release
log
if ! [[ $continue_release =~ ^[Yy]$ ]]; then
exit 0
fi
release_notes="$(execrelative ./release/generate_release_notes.sh --check-for-changelog --old-version "$old_version" --new-version "$new_version" --ref "$ref")"
read -p "Preview release notes? (y/n) " -n 1 -r show_reply
log
if [[ $show_reply =~ ^[Yy]$ ]]; then
log
echo -e "$release_notes\n"
fi
read -p "Create release? (y/n) " -n 1 -r create
log
if ! [[ $create =~ ^[Yy]$ ]]; then
exit 0
fi
log
# Run without dry-run to actually create the tag, note we don't update the
# new_version variable here to ensure we're pushing what we showed before.
maybedryrun "$dry_run" execrelative ./release/tag_version.sh "${tag_version_args[@]}" >/dev/null
maybedryrun "$dry_run" git push --tags -u origin "$new_version"
if ((dry_run)); then
# We can't watch the release.yaml workflow if we're in dry-run mode.
exit 0
fi
log
read -p "Watch release? (y/n) " -n 1 -r watch
log
if ! [[ $watch =~ ^[Yy]$ ]]; then
exit 0
fi
log 'Waiting for job to become "in_progress"...'
# Wait at most 3 minutes (3*60)/3 = 60 for the job to start.
for _ in $(seq 1 60); do
output="$(
# Output:
# 3886828508
# in_progress
gh run list -w release.yaml \
--limit 1 \
--json status,databaseId \
--jq '.[] | (.databaseId | tostring), .status'
)"
mapfile -t run <<<"$output"
if [[ ${run[1]} != "in_progress" ]]; then
sleep 3
continue
fi
gh run watch --exit-status "${run[0]}"
exit 0
done
error "Waiting for job to start timed out."