release: Write a tool to automate final release checks and steps.

This commit is contained in:
Alex Vandiver 2022-06-25 00:54:09 +00:00 committed by Alex Vandiver
parent d9958618a9
commit c915400101
2 changed files with 129 additions and 13 deletions

View File

@ -34,7 +34,7 @@ preparing a new release.
- Update the Paper blog post draft with any new commits.
- _Except minor releases:_ Download updated translation strings from
Transifex and commit them.
- Use `build-release-tarball` to generate a release tarball.
- Use `build-release-tarball` to generate a pre-release tarball.
- Test the new tarball extensively, both new install and upgrade from last
release, on Ubuntu 20.04.
- Repeat until release is ready.
@ -56,18 +56,7 @@ preparing a new release.
- Update `ZULIP_VERSION` and `LATEST_RELEASE_VERSION` in `version.py`.
- _Except minor releases:_ Update `API_FEATURE_LEVEL` to a feature
level for the final release, and document a reserved range.
- Tag that commit with an unsigned Git tag named the release number.
- Use `build-release-tarball` to generate a final release tarball.
- Push the tag and release commit.
- Upload the tarball using `tools/upload-release`.
- Post the release by [editing the latest tag on
GitHub](https://github.com/zulip/zulip/tags); use the text from
`changelog.md` for the release notes.
**Note:** This will trigger the [GitHub action](https://github.com/zulip/zulip/blob/main/tools/oneclickapps/README.md)
for updating DigitalOcean one-click app image. The action uses the latest release
tarball published on `download.zulip.com` for creating the image.
- Run `tools/release` with the release version.
- Update the [Docker image](https://github.com/zulip/docker-zulip):
- Update `ZULIP_GIT_REF` in `Dockerfile`
- Update `README.md`

127
tools/release Normal file
View File

@ -0,0 +1,127 @@
#!/usr/bin/env bash
set -eu
cd "$(dirname "$0")/.."
if [ -z "${1:-}" ]; then
echo "Usage: $0 version"
exit 1
fi
fail() {
echo "$1"
exit 1
}
version="$1"
# Check version is a form we expect
[[ "$version" =~ ^[0-9]+\.[0-9]+$ ]] \
|| fail "Version $version does not look like a full release!"
# Check we're on `main` or `\d+\.x`
branch=$(git rev-parse --abbrev-ref HEAD)
[ "$branch" == "main" ] || [[ "$branch" =~ ^[0-9]+\.x$ ]] \
|| fail "Current branch '$branch' is not 'main' or a release branch"
is_major_release=
if [[ "$version" =~ ^[0-9]+\.0$ ]]; then
[ "$branch" == "main" ] \
|| fail "Did not expect $version to be released from $branch"
is_major_release=1
else
[ "$branch" == "$(echo "$version" | perl -ple 's/\..*/.x/')" ] \
|| fail "Did not expect $version to be released from $branch"
fi
# shellcheck source=lib/git-tools.bash
. "$(dirname "$0")"/lib/git-tools.bash
require_clean_work_tree 'build and upload a release'
# Check the commit message
commit_msg=$(git rev-list --format=%B --max-count=1 HEAD | tail -n +2)
[ "$commit_msg" == "Release Zulip Server $version." ] \
|| fail "Expected commit message: Release Zulip Server $version."
# Provision
echo "Provisioning.."
if ! ./tools/provision >/dev/null; then
cat var/log/provision.log
fail "Provisioning failed!"
fi
# Check lint passes for the changelog
./tools/lint --skip gitlint docs/overview/changelog.md \
|| fail "Changelog does not pass lint"
# Check the date is correct for the release
release_line=$(grep -x -E -m 1 -o "### $version -- ([0-9-]+)" docs/overview/changelog.md) \
|| fail "docs/overview/changelog.md does not contain a line for $version"
[ "$release_line" == "### $version -- $(TZ=America/Los_Angeles date +%F)" ] \
|| fail "Date in docs/overview/changelog.md does not match $(date +%F)"
extract_version() {
setting="$1"
value=$(SETTING="$setting" perl -nle 'print $2 if /$ENV{SETTING} = (\"?)([^"]+)\1$/' version.py | head -n1)
[ -n "$value" ] || fail "Could not find $setting in version.py"
echo "$value"
}
# Check ZULIP_VERSION and LATEST_RELEASE_VERSION are set appropriately
[ "$(extract_version "ZULIP_VERSION")" == "$version" ] \
|| fail "ZULIP_VERSION in version.py does not match $version"
[ "$(extract_version "LATEST_RELEASE_VERSION")" == "$version" ] \
|| fail "LATEST_RELEASE_VERSION in version.py does not match $version"
if [ -n "$is_major_release" ]; then
[ "$(extract_version "LATEST_MAJOR_VERSION")" == "$version" ] \
|| fail "LATEST_MAJOR_VERSION in version.py does not match $version"
# Check that there is an API version bump, which is documented
changed_api_level=$(git diff-tree -G API_FEATURE_LEVEL HEAD -- version.py)
[ -n "$changed_api_level" ] || fail "$version did not adjust API_FEATURE_LEVEL in version.py"
feature_level="$(extract_version "API_FEATURE_LEVEL")"
grep -q -F -x "**Feature level $feature_level**" templates/zerver/api/changelog.md \
|| fail "Feature level $feature_level is not documented in templates/zerver/api/changelog.md"
fi
# Check we are auth'd to Github, so we can upload the release
type gh >/dev/null 2>&1 \
|| fail "The 'gh' CLI tool is not installed; see https://cli.github.com/"
gh auth status \
|| fail "Not authenticated to github"
# Extract the changelog, print it
changelog=$(VERSION="$version" perl -nle '$v=quotemeta($ENV{VERSION}); print if $rc = /^### $v/ .. /^#{1,3} (?!$v)/ and $rc !~ /E0/' docs/overview/changelog.md)
echo "$changelog"
echo -e "\n\n(pausing for 15s, ^C to cancel)"
sleep 15
git tag "$version"
# Commits need to be pushed to the remote so that "branched from" is correct
remote="$(git config zulip.zulipRemote)" || remote=upstream
git push "$remote" "$branch:$branch"
OUTDIR=$(mktemp -d)
trap 'rm -r "$OUTDIR"' EXIT
export OUTDIR
./tools/build-release-tarball "$version"
TARBALL="$OUTDIR/zulip-server-$version.tar.gz"
if ! [ -f "$TARBALL" ]; then
echo "Did not find expected $TARBALL!"
exit 1
fi
./tools/upload-release "$TARBALL"
git push "$version"
# Upload to Github
gh release create "$version" \
--title "Zulip Server $version" \
--notes-file <(echo "$changelog") \
"$TARBALL"