245 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
			
		
		
	
	
			245 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
| #!/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 "$@"
 |