-
-
Notifications
You must be signed in to change notification settings - Fork 85
/
prepare-release
executable file
·148 lines (130 loc) · 5.23 KB
/
prepare-release
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
#! /usr/bin/env zsh
set -eu -o pipefail -o null_glob
# Check if exactly one argument was passed: the new version.
if (( $# != 1 )) || [[ "$1" == "--help" ]]; then
>&2 {
echo "Usage: $0 <version>"
echo " version: The new version, e.g., v1.0.0 or v1.0.0-rc1"
}
exit 1
fi
# Check if all required tools are available.
for binary in 'cmake' 'gh' 'rsync' 'git' 'perl' 'jq' 'yarn'; do
if ! command -v "${binary}" 2>&1 >/dev/null; then
>&2 echo "Error: ${binary} not in PATH"
exit 1
fi
done
# To simplify this script, we require a clean working directoy.
if ! [ -z "$(git status --porcelain)" ]; then
>&2 echo "Error: working directory unclean"
exit 1
fi
# Determine the source directory.
source_dir="$(git -C "$(dirname "$0:A")" rev-parse --show-toplevel)"
# Determine the last version including release candidates, the last version
# excluding release candidates and the new version.
last_rc_version="$(git -C "${source_dir}" describe --abbrev=0 --match='v[0-9]*')"
last_version="$(git -C "${source_dir}" describe --abbrev=0 --match='v[0-9]*' --exclude='*-rc*')"
new_version="$1"
new_version_major_minor="${new_version%.*}"
if [[ "${new_version}" == *"-rc"* ]]; then
rc="${new_version#}"
new_version_major_minor="${new_version%.*}-${new_version##*-}"
fi
# Determine the build directory.
build_dir=$(mktemp -d 2>/dev/null || mktemp -d -t "build-${new_version}")
# Check that the new version does not exist already.
if [ -d "${source_dir}/changelog/${new_version}" ]; then
>&2 echo "Error: changelog/${new_version} already exists"
exit 1
fi
# A variable to build a nice commit message.
things_done=""
# Create a new branch that bases off of current origin/main.
git fetch origin main
git switch -C "topic/release-${new_version}" origin/main
# Update the version.
version_json="$(jq --arg v "${new_version#v}" '."tenzir-version" = $v' version.json)"
echo -E "${version_json}" > version.json
things_done+="
* Updated \`/version.json\` to \`${new_version}\`."
# If the new version is not a release candidate, change mentions of the version
# in README.md as well, and create a new docs version.
# TODO: Re-enable the check.
# if [[ "${new_version}" != *"-rc"* ]]; then
if [[ true ]]; then
perl -i -pe "s/${last_version}/${new_version}/g" "${source_dir}/README.md"
pushd "${source_dir}/web"
# In the documentation on docs.tenzir.com we tag using the major and minor
# version only, ignoring the patch version. This means that for a patch
# version we must override the existing release, which per the Docusaurus
# docs[^1] is possible by deleting the existing version and then cutting it
# again. Since deleting a non-existing version is a no-op we just always do
# that.
# ^1: https://docusaurus.io/docs/versioning#deleting-an-existing-version
#
# This bit removes the already tagged version:
new_version_name="Tenzir ${new_version_major_minor}"
jq "map(select(. | startswith(\"${new_version_name%-*}\") | not))" < versions.json > versions.json.tmp
mv -f versions.json.tmp versions.json
things_done+="
* Generated a new entry in the docs version selector list."
if [ -d "versioned_docs/version-${new_version_name%-*}"* ]; then
things_done+="
* Removed the docs for the previous release candidate."
else
fi
# The `|| true`s in the next two lines work around a `zsh` behavior where
# a globbed `rm` fails if the glob doesn't match anything.
rm -rf "versioned_docs/version-${new_version_name%-*}"* || true
rm -rf "versioned_sidebars/version-${new_version_name%-*}"*-sidebars.json || true
# And this actually cuts a new docs version:
yarn install --frozen-lockfile
yarn docusaurus docs:version "${new_version_name}"
popd
fi
# Copy the next changelog directory.
if [ -d "${source_dir}/changelog/next" ]; then
for entry in "${source_dir}/changelog/next/"**/*.md; do
if [[ "$entry" != "${entry/--*.md/.md}" ]]; then
mv "$entry" "${entry/--*.md/.md}"
fi
done
rsync -avzh "${source_dir}/changelog/next/" \
"${source_dir}/changelog/${new_version}"
rm -r "${source_dir}/changelog/next"
things_done+="
* Moved all changelog entries from \`/changelog/next\` to \`/changelog/${new_version}\`."
fi
# If the previous release was an rc as well, merge the changelog directories.
if [[ "${last_rc_version}" == *"-rc"* ]]; then
if [ -d "${source_dir}/changelog/${last_rc_version}" ]; then
rsync -avzh "${source_dir}/changelog/${last_rc_version}/" \
"${source_dir}/changelog/${new_version}"
rm -r "${source_dir}/changelog/${last_rc_version}"
fi
things_done+="
* Moved all changelog entries from \`/changelog/${last_rc_version}\` to \`/changelog/${new_version}\`."
fi
# Update version of Python bindings.
pushd "${source_dir}/python"
poetry version "${new_version#v}"
popd
things_done+="
* Updated the python bindings version in \`/python/pyproject.toml\` to \`${new_version}\`."
# Commit and open a PR against tenzir/tenzir.
pushd "${source_dir}"
git add --all
git commit -F- <<EOF
Prepare repository for Tenzir ${new_version}
This commit was created with \`/scripts/prepare-release\`.
Here is a high-level summary of the changes:
${things_done}
EOF
# Assume that tenzir/tenzir is the 'origin' repo to avoid another prompt.
git push -u origin HEAD
gh pr create --web
popd
# Switch back to the branch we started on.
git switch -