From c915400101628b6d3fe9fc28633ed81a226ab698 Mon Sep 17 00:00:00 2001 From: Alex Vandiver Date: Sat, 25 Jun 2022 00:54:09 +0000 Subject: [PATCH] release: Write a tool to automate final release checks and steps. --- docs/subsystems/release-checklist.md | 15 +--- tools/release | 127 +++++++++++++++++++++++++++ 2 files changed, 129 insertions(+), 13 deletions(-) create mode 100644 tools/release diff --git a/docs/subsystems/release-checklist.md b/docs/subsystems/release-checklist.md index be1d09bfde..83e0b4c38c 100644 --- a/docs/subsystems/release-checklist.md +++ b/docs/subsystems/release-checklist.md @@ -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` diff --git a/tools/release b/tools/release new file mode 100644 index 0000000000..f76442cb04 --- /dev/null +++ b/tools/release @@ -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"