/
generate_release_notes.sh
executable file
·206 lines (182 loc) · 5.02 KB
/
generate_release_notes.sh
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
#!/usr/bin/env bash
# Usage: ./generate_release_notes.sh --old-version <old version> --new-version <new version> --ref <ref>
#
# Example: ./generate_release_notes.sh --old-version v0.13.0 --new-version v0.13.1 --ref 1e6b244c
#
# This script generates release notes for the given version. It will generate
# release notes for all commits between the old version and the new version.
#
# Ref must be set to the commit that the new version will be tagget at. This
# is used to determine the commits that are included in the release. If the
# commit is already tagged, ref can be set to the tag name.
set -euo pipefail
# shellcheck source=scripts/lib.sh
source "$(dirname "$(dirname "${BASH_SOURCE[0]}")")/lib.sh"
old_version=
new_version=
ref=
mainline=1
args="$(getopt -o '' -l old-version:,new-version:,ref:,mainline,stable -- "$@")"
eval set -- "${args}"
while true; do
case "$1" in
--old-version)
old_version="$2"
shift 2
;;
--new-version)
new_version="$2"
shift 2
;;
--ref)
ref="$2"
shift 2
;;
--mainline)
mainline=1
shift
;;
--stable)
mainline=0
shift
;;
--)
shift
break
;;
*)
error "Unrecognized option: $1"
;;
esac
done
# Check dependencies.
dependencies gh sort
# Authticate gh CLI
gh_auth
if [[ -z ${old_version} ]]; then
error "No old version specified"
fi
if [[ -z ${new_version} ]]; then
error "No new version specified"
fi
if [[ ${new_version} != v* ]]; then
error "New version must start with a v"
fi
if [[ -z ${ref} ]]; then
error "No ref specified"
fi
# shellcheck source=scripts/release/check_commit_metadata.sh
source "${SCRIPT_DIR}/check_commit_metadata.sh" "${old_version}" "${ref}"
# Sort commits by title prefix, then by date, only return sha at the end.
git_show_out="$(
{
echo "${COMMIT_METADATA_COMMITS[@]}" |
tr ' ' '\n' |
xargs git show --no-patch --pretty=format:"%ct %h %s"
} | sort -k3,3 -k1,1n | cut -d' ' -f2
)"
mapfile -t commits <<<"${git_show_out}"
# From: https://github.com/commitizen/conventional-commit-types
# NOTE(mafredri): These need to be supported in check_commit_metadata.sh as well.
declare -a section_order=(
breaking
security
feat
fix
docs
refactor
perf
test
build
ci
chore
revert
other
experimental
)
declare -A section_titles=(
[breaking]='BREAKING CHANGES'
[security]='SECURITY'
[feat]='Features'
[fix]='Bug fixes'
[docs]='Documentation'
[refactor]='Code refactoring'
[perf]='Performance improvements'
[test]='Tests'
[build]='Builds'
[ci]='Continuous integration'
[chore]='Chores'
[revert]='Reverts'
[other]='Other changes'
[experimental]='Experimental changes'
)
# Verify that all items in section_order exist as keys in section_titles and
# vice-versa.
for cat in "${section_order[@]}"; do
if [[ " ${!section_titles[*]} " != *" ${cat} "* ]]; then
error "BUG: category ${cat} does not exist in section_titles"
fi
done
for cat in "${!section_titles[@]}"; do
if [[ " ${section_order[*]} " != *" ${cat} "* ]]; then
error "BUG: Category ${cat} does not exist in section_order"
fi
done
for commit in "${commits[@]}"; do
title=${COMMIT_METADATA_TITLE[${commit}]}
if [[ -v COMMIT_METADATA_HUMAN_TITLE[${commit}] ]]; then
title=${COMMIT_METADATA_HUMAN_TITLE[${commit}]}
fi
if [[ ${title} =~ \(#[0-9]*\)$ ]]; then
title="${title%)}, ${commit})"
else
title="${title} (${commit})"
fi
line="- ${title}"
line=${line//) (/, )}
if [[ -v COMMIT_METADATA_AUTHORS[${commit}] ]]; then
line+=" (${COMMIT_METADATA_AUTHORS[${commit}]})"
fi
# Default to "other" category.
cat=other
for c in "${!section_titles[@]}"; do
if [[ ${c} == "${COMMIT_METADATA_CATEGORY[${commit}]}" ]]; then
cat=${c}
break
fi
done
declare "${cat}"_changelog+="${line}"$'\n'
done
changelog="$(
for cat in "${section_order[@]}"; do
changes="$(eval "echo -e \"\${${cat}_changelog:-}\"")"
if ((${#changes} > 0)); then
echo -e "\n### ${section_titles["${cat}"]}\n"
if [[ ${cat} == experimental ]]; then
echo -e "These changes are feature-flagged and can be enabled with the \`--experiments\` server flag. They may change or be removed in future releases.\n"
fi
echo -e "${changes}"
fi
done
)"
image_tag="$(execrelative ../image_tag.sh --version "${new_version}")"
blurb=
stable_since=
if ((mainline)); then
blurb="
> [!NOTE]
> This is a mainline Coder release. We advise enterprise customers without a staging environment to install our [latest stable release](https://github.com/coder/coder/releases/latest) while we refine this version. Learn more about our [Release Schedule](https://coder.com/docs/v2/latest/install/releases).
"
else
# Date format: April 23, 2024
d=$(date +'%B %d, %Y')
stable_since="> ## Stable (since ${d})"$'\n\n'
fi
echo -e "${stable_since}## Changelog
${blurb}${changelog}
Compare: [\`${old_version}...${new_version}\`](https://github.com/coder/coder/compare/${old_version}...${new_version})
## Container image
- \`docker pull ${image_tag}\`
## Install/upgrade
Refer to our docs to [install](https://coder.com/docs/v2/latest/install) or [upgrade](https://coder.com/docs/v2/latest/admin/upgrade) Coder, or use a release asset below.
"