zfsbootmenu/releng/tag-release.sh

186 lines
4.8 KiB
Bash
Executable File

#!/bin/bash
# vim: softtabstop=2 shiftwidth=2 expandtab
error () {
echo "$@"
exit 1
}
# Accept optional leading "v" from the release version
release="${1#v}"
if [ -z "${release}" ] || [ $# -ne 1 ]; then
error "USAGE: $0 <release>"
fi
# Validate release
# shellcheck disable=SC2001
if [ -n "$(echo "${release}" | sed 's/[0-9][A-Za-z0-9_.-]*$//')" ]; then
error "ERROR: release must start with a number and contain [A-Za-z0-9_.-]"
fi
# Make sure paths make sense
if [ ! -e bin/generate-zbm ] || [ ! -e docs/CHANGELOG.md ]; then
error "ERROR: run this script from the root of the zfsbootmenu tree"
fi
# Only tag releases from master
if [ "$(git rev-parse --abbrev-ref HEAD)" != "master" ]; then
error "ERROR: will not tag releases on any branch but master"
fi
# Only allow changes to CHANGELOG.md when tagging releases
# shellcheck disable=SC2143
if [ -n "$(git status --porcelain=v1 | grep -v '.. docs/CHANGELOG.md$')" ]; then
error "ERROR: will not tag release with non-changelog changes in tree"
fi
# x86_64 users are the primary consumers of ZFSBootMenu
# Releases should always be done on an x86_64 host, so that .EFI builds take place
arch="$( uname -m )"
if [ "${arch}" != "x86_64" ]; then
error "ERROR: releases must be tagged on x86_64 hosts to build EFI binaries"
fi
# Use github-cli or hub to push the release
if ! command -v gh >/dev/null 2>&1; then
error "ERROR: github-cli is required to tag releases"
fi
# Make sure the tag has a leading "v"
tag="v${release}"
if git tag | grep -q "${tag}$"; then
error "ERROR: desired tag already exists"
fi
echo "Will tag release version ${release} as ${tag}"
# update version in documentation
sed -i "s/^release = '.*'\$/release = '${release}'" docs/conf.py
# Synchronize man pages with POD documentation
if [ ! -x releng/rst2help.sh ]; then
error "ERROR: unable to convert documentation"
fi
if ! out="$( releng/rst2help.sh )" ; then
error "ERROR: ${out}"
fi
if ! out="$( cd docs ; make gen-man )" ; then
error "ERROR: ${out}"
fi
# Generate a short history for CHANGELOG.md
# git log --format="* %h - %s (%an)" v1.4.1..HEAD
# Extract release notes for this version
relnotes=$(mktemp)
# shellcheck disable=SC2064
trap "rm -f ${relnotes}" 0
awk < docs/CHANGELOG.md > "${relnotes}" '
BEGIN{ hdr=0; }
/^# /{
if (hdr) exit 0;
hdr=1;
sub(/^# /, "", $0);
sub(/ \(.*\)$/, "", $0);
}
{
if (hdr < 1) exit 1;
print;
}'
# Make sure release notes refer to this version
if ! (head -n 1 "${relnotes}" | grep -q "ZFSBootMenu ${tag}\b"); then
error "ERROR: Add '# ZFSBootMenu ${tag}' header to docs/CHANGELOG.md"
fi
# Update version in generate-zbm
sed -i bin/generate-zbm -e "s/our \$VERSION.*/our \$VERSION = '${release}';/"
# Push updates for the release
git add bin/generate-zbm docs/ zfsbootmenu/help-files/
git commit -m "Bump to version ${release}"
# Publish release, as prerelease if version contains alphabetics
if echo "${release}" | grep -q "[A-Za-z]"; then
prerelease=( "--prerelease" )
else
prerelease=( )
fi
mkdir -p "releng/assets/${release}"
asset_dir="$( realpath -e "releng/assets/${release}" )"
asset_files=()
assets=()
# Create binary assets
if ! releng/make-binary.sh "${release}"; then
error "ERROR: unable to make release assets, exiting!"
fi
# Copy in any extra assets/files, relative to the project root
# shellcheck disable=SC2043
for extra in bin/zbm-kcl ; do
[ -f "${extra}" ] || error "ERROR: missing ${extra}"
cp "${extra}" "${asset_dir}/"
assets+=( "${extra##*/}" )
done
# Sign the binary assets
if ! releng/sign-assets.sh "${release}"; then
error "ERROR: unable to sign release assets, exiting!"
fi
for style in release recovery; do
assets+=( "zfsbootmenu-${style}-${arch}-v${release}-vmlinuz.EFI" )
assets+=( "zfsbootmenu-${style}-${arch}-v${release}.tar.gz" )
done
for asset in "${assets[@]}" ; do
f="${asset_dir}/${asset}"
[ -f "${f}" ] || error "ERROR: missing release asset ${f}"
asset_files+=( "${f}" )
done
for f in sha256.{txt,sig}; do
[ -f "${asset_dir}/${f}" ] || error "ERROR: missng sum file ${asset_dir}/${f}"
asset_files+=( "${asset_dir}/${f}" )
done
# github-cli does not automatically strip header that hub uses for a title
sed -i '1,/^$/d' "${relnotes}"
echo "Release ${release} ready to push and tag"
while true; do
echo "Continue? [Yes]/No"
read -r response
case "${response}" in
[Yy][Ee][Ss]|[Yy]|"")
break
;;
[Nn][Oo]|[Nn])
error "Release aborted by user request; clean up your local branch!"
;;
*)
echo "Unrecognized response, please answer 'yes' or 'no'"
;;
esac
done
if ! git push; then
error "ERROR: failed to push to default branch; release aborted"
fi
if ! gh release create "${tag}" "${prerelease[@]}" \
-F "${relnotes}" -t "ZFSBootMenu ${tag}" "${asset_files[@]}"; then
error "ERROR: release creation failed"
fi
echo "Pushed and tagged release ${release}"