Last active
December 15, 2016 16:55
-
-
Save nZac/81005986c72d2bbfcc10f8764cedd2da to your computer and use it in GitHub Desktop.
Release PyPI Project
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash -e | |
# | |
# Author: Nick Zaccardi <[email protected]> | |
# | |
# This script is designed to help release packages to PyPI faster. It tries its | |
# best to walk you through all the steps to release a source packages and a | |
# binary wheel package. | |
# | |
# The script does the following | |
# | |
# 1. Updates your version file ($SRC_DIR/version.py) | |
# 2. Adds any merge commits since the last tag to the changelog.rst file | |
# 3. Commits, tags and pushes those changes to the upstream repository | |
# 4. Creates, signs, and pushes the packages to PyPi | |
# HELPER FUNCTIONS | |
confirm () { | |
read -r -p "${1:-Are you sure?} [y/N]: " response | |
case $response in | |
[yY][eE][sS]|[yY]) | |
true | |
;; | |
*) | |
false | |
;; | |
esac | |
} | |
echoerr() { printf "%s\n" "$*" >&2; } | |
# ENVIRONMENT CHECKS... Fail quick | |
test -z "$(git status --porcelain)" || { echoerr "ERROR: Unclean head."; exit 1; } | |
test -n "$1" || { echoerr "ERROR: Pass the directory of the package as the first param to this script"; exit 1; } | |
# Setup some vars for use later | |
HAS_GPG=$(command -v gpg 2>&1>/dev/null) | |
# Determine the source directory from the first argument passed in | |
SRC_DIR=$1 | |
# The setup.py file should have everything we need | |
PROJECT_NAME=$(python setup.py --name) | |
REPO_URL=$(python setup.py --url 2>/dev/null) | |
CURRENT_VERSION=$(python setup.py -V) | |
# First things first, ask for the new version | |
echo -n "Enter new version number (current $CURRENT_VERSION): "; read -r NEW_VERSION | |
if confirm "Update version file?"; then | |
echo "VERSION = '$NEW_VERSION'" > "$SRC_DIR/version.py" | |
fi | |
# Figure out the changelog updates based on the merge commits in the history | |
# since the last tag. Then we link them to the web repo (Github normally) so | |
# that you get quick access to what changed. | |
if confirm "Update changelog?"; then | |
CURRENT_GIT_TAG=$(git describe --tags --abbrev=0) | |
GIT_CHANGELOG=$(git log --merges --pretty=format:"* %s (%h_)" "$CURRENT_GIT_TAG..HEAD") | |
GIT_CHANGELOG_LINKS=$(git log --merges --pretty=format:".. _%h: $REPO_URL/commit/%h" "$CURRENT_GIT_TAG..HEAD") | |
CHANGELOG_HEADER="$NEW_VERSION - $(date +%Y-%m-%d)" | |
{ | |
echo -e "$CHANGELOG_HEADER" | |
echo -e "##################\n" | |
echo -e "$GIT_CHANGELOG\n" | |
echo -e "$GIT_CHANGELOG_LINKS\n\n" | |
cat changelog.rst | |
} > tmp | |
# Allow the release manager to make any tweaks to the changelog | |
$EDITOR changelog.rst | |
mv tmp changelog.rst | |
fi | |
# Show what has changed since we started, should be just a few files | |
git status | |
# Committing will add any files created by this process (version and changlog) | |
# and then tag (optionally signing) then push to the upstream repo of your | |
# choice. You might want a CI process to run | |
if confirm "Commit?"; then | |
git add . | |
git commit --quiet -m "Version Bump $NEW_VERSION" | |
if $HAS_GPG; then | |
GPG_TTY=$(tty) git tag --sign -m "Version Bump $NEW_VERSION" "$NEW_VERSION" | |
else | |
git tag -m "Version Bump $NEW_VERSION" "$NEW_VERSION" | |
fi | |
if confirm "Push to Git remote?"; then | |
echo -n "Which remote should I push to?"; read -r UPSTREAM | |
git push --tags "$UPSTREAM" master | |
fi | |
fi | |
# Construct the package, optionally signing and pushing that package to PyPI it | |
# will install twine and ensure wheel is installed | |
if confirm "Build Package?"; then | |
rm -rf dist build | |
pip --quiet install twine wheel | |
python setup.py --quiet sdist bdist_wheel | |
if $HAS_GPG && confirm "Sign sdist and wheel?"; then | |
GPG_TTY=$(tty) gpg --detach-sign -a "dist/$PROJECT_NAME-$(python setup.py -V).tar.gz" | |
GPG_TTY=$(tty) gpg --detach-sign -a "dist/$PROJECT_NAME-$(python setup.py -V)-py2.py3-none-any.whl" | |
fi | |
if confirm "Push to PyPI?"; then | |
twine upload dist/* | |
fi | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Follow development here: https://github.com/nZac/dotfiles/blob/master/bin/pyrelease