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
|
#!/bin/bash
#
# Prepares a new version release locally, leaving you ready to either:
#
# A. Push and upload it if you're satisfied with the state of git and the
# built distributions, or…
#
# B. Rewind the process if you're not (via devel/rewind-release or
# manually).
#
# If you have GPG and git's user.signingKey option configured, a signed tag
# will be created. Otherwise, an unsigned annotated tag will be used.
#
# The script will prompt you for the new version if you do not provide it as
# the sole argument.
#
set -euo pipefail
devel="$(dirname $0)"
repo="$devel/.."
version_file="$repo/augur/__version__.py"
changes_file="$repo/CHANGES.md"
main() {
assert-clean-working-dir
assert-changelog-has-additions
if [[ $# -gt 0 ]]; then
version="$1"
else
version=$(next-version)
fi
assert-version-is-new $version
update-version $version
update-changelog $version
commit-and-tag $version
build-dist
remind-to-push $version
}
assert-clean-working-dir() {
local status="$(git status --porcelain --untracked-files=no | grep -vwF "$(basename "$changes_file")" || true)"
if [[ -n $status ]]; then
echo "Please commit all changes before releasing:" >&2
echo >&2
echo "$status" >&2
echo >&2
echo "Only $(basename "$changes_file") is allowed to have uncommitted changes." >&2
exit 1
fi
}
assert-changelog-has-additions() {
local current_version="$(read-version)"
local numstat="$(git diff --numstat "$current_version" -- "$changes_file")"
local insertions deletions rest
if [[ -z $numstat ]]; then
insertions=0
deletions=0
else
read -r insertions deletions rest <<<"$numstat"
fi
local net_changed=$(($insertions - $deletions))
if [[ $net_changed -lt 1 ]]; then
echo "It doesn't look like $(basename "$changes_file") was updated; only $insertions - $deletions = $net_changed line(s) were changed." >&2
exit 1
fi
}
assert-version-is-new() {
local current_version="$(read-version)"
local new_version="$1"
if [[ -z $new_version || $new_version == $current_version ]]; then
echo "You must provide a new version!" >&2
exit 1
elif ! version-is-gt $current_version $new_version; then
echo "You must provide a new version greater than the last!" >&2
exit 1
fi
}
version-is-gt() {
python3 /dev/stdin "$1" "$2" <<<"$(cut -c 9- <<<'
from sys import argv, exit
from packaging.version import Version
version = list(map(Version, argv[1:3]))
gt = version[1] > version[0]
exit(int(not gt))
')"
}
next-version() {
local current_version="$(read-version)"
# The ancient version of bash on macOS does not support the -i option, so
# test if it works before using it.
if read -i supported <<<"" 2>/dev/null >&2; then
read -e -p "Current version is $current_version."$'\n'"New version? " -i "$current_version" new_version
else
read -e -p "Current version is $current_version."$'\n'"New version? " new_version
fi
echo "$new_version"
}
update-version() {
local new_version="$1"
local current_version="$(read-version)"
perl -pi -e "s/(?<=^__version__ = ')(.*)(?='$)/$new_version/" "$version_file"
if [[ $new_version != $(read-version) ]]; then
echo "Failed to update $version_file!" >&2
exit 1
fi
}
update-changelog() {
local new_version="$1"
local today="$(date +"%d %B %Y")"
# Remove leading zero from day if present
today="${today#0}"
# Add the new version heading immediately after the __NEXT__ heading,
# preserving the __NEXT__ heading itself.
perl -pi -e "s/(?<=^## __NEXT__$)/\n\n\n## $new_version ($today)/" "$changes_file"
}
commit-and-tag() {
local version="$1"
git commit -m "version $version" "$version_file" "$changes_file"
if [[ -n "$(git config user.signingKey)" ]]; then
git tag -sm "version $version" "$version"
else
git tag -am "version $version" "$version"
fi
}
build-dist() {
rm -rfv build/ dist/ nextstrain_augur.egg-info
python3 -m build
}
remind-to-push() {
local version="$1"
echo
echo
echo "Version updated, committed, and tagged!"
echo
echo "Please remember to push, including tags:"
echo
echo " git push origin master tag $version"
echo
echo "You'll also want to upload the built releases to PyPi:"
echo
echo " twine upload dist/*"
echo
}
read-version() {
python3 -c "exec(open('''$version_file''').read()); print(__version__)"
}
main "$@"
|