You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
245 lines
6.2 KiB
245 lines
6.2 KiB
#!/bin/bash
|
|
set -eu
|
|
cd "$( dirname "${BASH_SOURCE[0]}" )/.."
|
|
|
|
version=
|
|
version_next=
|
|
|
|
main() {
|
|
local opt_auto=0
|
|
while [[ $# -gt 0 ]] ; do
|
|
case $1 in
|
|
-auto)
|
|
opt_auto=1
|
|
;;
|
|
*)
|
|
echo "Usage: $0 [-auto]" >&2
|
|
exit 0
|
|
;;
|
|
esac
|
|
shift
|
|
done
|
|
if [[ "$opt_auto" -eq 1 ]] ; then
|
|
auto_prepare_release
|
|
else
|
|
interactive
|
|
fi
|
|
}
|
|
|
|
auto_prepare_release() {
|
|
echo 'script/release: auto mode for CI, will check or modify version based on tag' >&2
|
|
|
|
assert_tree_clean
|
|
|
|
local is_tag=0
|
|
local version_tag=
|
|
if version_tag=$(git describe --candidates=0 --tags HEAD 2>/dev/null) ; then
|
|
is_tag=1
|
|
version_tag=${version_tag##v}
|
|
version_check "$version_tag"
|
|
fi
|
|
|
|
local last_tag=
|
|
local version_replace=
|
|
if [[ "$is_tag" -eq 0 ]] ; then
|
|
last_tag=$(git tag --sort=-version:refname |head -n1)
|
|
last_tag=${last_tag##v}
|
|
version_replace="${last_tag}.post$(date -u +%y%m%d%H%M)"
|
|
update_version "setup.py" "s/VERSION =.+/VERSION = \"$version_replace\"/"
|
|
update_version "python2/httplib2/__init__.py" "s/__version__ =.+/__version__ = \"$version_replace\"/"
|
|
update_version "python3/httplib2/__init__.py" "s/__version__ =.+/__version__ = \"$version_replace\"/"
|
|
version_check "$version_replace"
|
|
fi
|
|
}
|
|
|
|
interactive() {
|
|
echo 'script/release: interactive mode for creating new tagged releases with human assistance' >&2
|
|
|
|
local branch="${1-$(git symbolic-ref --short HEAD)}"
|
|
version="$(PYTHONPATH=$PWD/python3 python3 -c 'import httplib2; print(httplib2.__version__)')"
|
|
printf "\nbranch: %s httplib2.__version__: '%s'\n" $branch $version >&2
|
|
|
|
if [[ "$branch" != "master" ]] ; then
|
|
echo "Must be on master" >&2
|
|
exit 1
|
|
fi
|
|
assert_tree_clean
|
|
|
|
last_commit_message=$(git show --format="%s" --no-patch HEAD)
|
|
expect_commit_message="v$version release"
|
|
if [[ "$last_commit_message" != "$expect_commit_message" ]] ; then
|
|
printf "Last commit message: '%s' expected: '%s'\n" "$last_commit_message" "$expect_commit_message" >&2
|
|
if confirm "Create release commit? [yN] " ; then
|
|
create_commit
|
|
elif ! confirm "Continue without proper release commit? [yN] " ; then
|
|
exit 1
|
|
fi
|
|
fi
|
|
confirm "Continue? [yN] " || exit 1
|
|
|
|
echo "Creating tag v$version" >&2
|
|
if ! git tag "v$version" ; then
|
|
echo "git tag failed " >&2
|
|
confirm "Continue still? [yN] " || exit 1
|
|
fi
|
|
|
|
echo "Building package" >&2
|
|
find . -name '*.pyc' -o -name '*.pyo' -o -name '*.orig' -delete
|
|
rm -rf python{2,3}/.cache
|
|
rm -rf build dist
|
|
local venv=./venv-release
|
|
if [[ ! -d "$venv" ]] ; then
|
|
virtualenv $venv
|
|
$venv/bin/pip install -U check-manifest pip 'setuptools>=43.0' wheel twine
|
|
fi
|
|
$venv/bin/python setup.py clean --all
|
|
$venv/bin/python setup.py sdist bdist_wheel
|
|
$venv/bin/check-manifest || echo "FIXME check-manifest" >&2
|
|
|
|
if confirm "Upload to PyPI? Use in special situation, normally CI (Travis) will upload to PyPI. [yN] " ; then
|
|
$venv/bin/twine upload dist/* || exit 1
|
|
fi
|
|
|
|
git push --tags
|
|
}
|
|
|
|
create_commit() {
|
|
echo "" >&2
|
|
echo "Plan:" >&2
|
|
echo "1. bump version" >&2
|
|
echo "2. update CHANGELOG" >&2
|
|
echo "3. commit" >&2
|
|
echo "4. run bin/release again" >&2
|
|
echo "" >&2
|
|
|
|
bump_version
|
|
edit_news
|
|
|
|
git diff
|
|
confirm "Ready to commit? [Yn] " || exit 1
|
|
git commit -a -m "v$version_next release"
|
|
|
|
echo "Re-exec $0 to continue" >&2
|
|
exec $0
|
|
}
|
|
|
|
bump_version() {
|
|
local current=$version
|
|
echo "Current version: '$current'" >&2
|
|
echo -n "Enter next version (empty to abort): " >&2
|
|
read version_next
|
|
if [[ -z "$version_next" ]] ; then
|
|
exit 1
|
|
fi
|
|
echo "Next version: '$version_next'" >&2
|
|
|
|
update_version "python3/httplib2/__init__.py" "s/__version__ =.+/__version__ = \"$version_next\"/"
|
|
update_version "python2/httplib2/__init__.py" "s/__version__ =.+/__version__ = \"$version_next\"/"
|
|
update_version "setup.py" "s/VERSION =.+/VERSION = \"$version_next\"/"
|
|
|
|
confirm "Confirm changes? [yN] " || exit 1
|
|
}
|
|
|
|
update_version() {
|
|
local path="$1"
|
|
local sed_expr="$2"
|
|
# sed -E --in-place='' -e "s/VERSION =.+/VERSION = \"$version_replace\"/" setup.py
|
|
# sed -E --in-place='' -e "s/__version__ =.+/__version__ = \"$version_replace\"/" python2/httplib2/__init__.py python3/httplib2/__init__.py
|
|
echo "Updating file '$path'" >&2
|
|
if ! sed -E --in-place='' -e "$sed_expr" "$path" ; then
|
|
echo "sed error $?" >&2
|
|
exit 1
|
|
fi
|
|
assert_modified "$path"
|
|
echo "" >&2
|
|
}
|
|
|
|
edit_news() {
|
|
echo "Changes since last release:" >&2
|
|
git log --format='%h %an %s' "v$version"^.. -- || exit 1
|
|
echo "" >&2
|
|
|
|
patch -p1 <<EOT
|
|
diff a/CHANGELOG b/CHANGELOG
|
|
--- a/CHANGELOG
|
|
+++ b/CHANGELOG
|
|
@@ -0,0 +1,4 @@
|
|
+$version_next
|
|
+
|
|
+ EDIT HERE. Describe important changes and link to more information.
|
|
+
|
|
EOT
|
|
|
|
local editor=$(which edit 2>/dev/null)
|
|
[[ -z "$editor" ]] && editor="$EDITOR"
|
|
if [[ -n "$editor" ]] ; then
|
|
if confirm "Open default editor for CHANGELOG? [Yn] " ; then
|
|
$editor CHANGELOG
|
|
else
|
|
confirm "Edit CHANGELOG manually and press any key"
|
|
fi
|
|
else
|
|
echo "Unable to determine default text editor." >&2
|
|
confirm "Edit CHANGELOG manually and press any key"
|
|
fi
|
|
echo "" >&2
|
|
|
|
assert_modified CHANGELOG
|
|
|
|
echo "" >&2
|
|
confirm "Confirm changes? [yN] " || exit 1
|
|
}
|
|
|
|
assert_modified() {
|
|
local path="$1"
|
|
if git diff --exit-code "$path" ; then
|
|
echo "File '$path' is not modified" >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
assert_tree_clean() {
|
|
if [[ -n "$(git status --short -uall)" ]] ; then
|
|
echo "Tree must be clean. git status:" >&2
|
|
echo "" >&2
|
|
git status --short -uall
|
|
echo "" >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
version_check() {
|
|
local need=$1
|
|
local version_setup=$(fgrep 'VERSION =' setup.py |tr -d " '\"" |cut -d\= -f2)
|
|
local version_py2=$(cd python2 ; python2 -Es -c 'import httplib2;print(httplib2.__version__)')
|
|
local version_py3=$(cd python3 ; python3 -Es -c 'import httplib2;print(httplib2.__version__)')
|
|
if [[ "$version_setup" != "$need" ]] ; then
|
|
echo "error: setup.py VERSION=$version_setup expected=$need" >&1
|
|
exit 1
|
|
fi
|
|
if [[ "$version_py2" != "$need" ]] ; then
|
|
echo "error: python2/httplib2/__init__.py:__version__=$version_py2 expected=$need" >&1
|
|
exit 1
|
|
fi
|
|
if [[ "$version_py3" != "$need" ]] ; then
|
|
echo "error: python3/httplib2/__init__.py:__version__=$version_py3 expected=$need" >&1
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
confirm() {
|
|
local reply
|
|
local prompt="$1"
|
|
read -n1 -p "$prompt" reply >&2
|
|
echo "" >&2
|
|
rc=0
|
|
local default_y=" \[Yn\] $"
|
|
if [[ -z "$reply" ]] && [[ "$prompt" =~ $default_y ]] ; then
|
|
reply="y"
|
|
fi
|
|
[[ "$reply" != "y" ]] && rc=1
|
|
return $rc
|
|
}
|
|
|
|
main "$@"
|