Skip to content

Instantly share code, notes, and snippets.

@mverleg
Created October 26, 2019 13:05
Show Gist options
  • Save mverleg/9be2079975dfcf9b6442dc2f7ce2cbb9 to your computer and use it in GitHub Desktop.
Save mverleg/9be2079975dfcf9b6442dc2f7ce2cbb9 to your computer and use it in GitHub Desktop.
Bash script to create a Python release. Uploads to the test server first, signs uploads, verifies install after upload, and some other checks.
function python_release() {
##
## Upload a new release for a python package
##
## Requirements:
## - ~/.pypirc exists and contains both testpypi and pypi
## - Active virtual environment
## - setup.py exists
##
## Besides the above, will verify that:
## - Upload to testpypi works, before attempting pypi
## - Install of the package works after upload
##
## Usage:
## Just call `python_release` in the project directory
##
if [[ ! -w "$(which python)" ]]
then
echo "not in a virtual environment?" 1>&2
return 1
fi
pypi_conf_pth="$HOME/.pypirc"
if [[ ! -e "$pypi_conf_pth" ]]
then
echo "config file not found: $pypi_conf_pth" 1>&2
return 2
fi
chmod 700 "$pypi_conf_pth"
if [[ ! -e "setup.py" ]]
then
echo "setup.py file not found" 1>&2
return 3
fi
package_name="$(python setup.py --name)"
package_version="$(python setup.py --version)"
if [[ -z "$package_name" || -z "$package_version" ]]
then
echo "could not determine package name/version (found ${package_name}==${package_version})" 1>&2
return 4
fi
echo "package: ${package_name}==${package_version}"
if [[ -e dist ]]
then
echo "removing old releases in dist/*"
rm -rf dist/ || return 5
fi
echo "creating new source release"
python setup.py clean sdist || return 6
echo "create new wheel release"
python setup.py bdist_wheel || return 7
echo "install twine in the environment"
pip install --upgrade pip twine || return 8
echo "doing TEST upload"
echo "note that accounts may be deleted after a while, go to https://test.pypi.org/account/register/"
twine upload --sign --repository testpypi dist/* || return 9
echo "uploading (check .pypirc in case of problems)"
twine upload --sign --repository pypi dist/* || return 10
echo "test that package can now be installed"
package_test_dir="/tmp/$USER/pip_package_test"
mkdir -m 700 -p "$package_test_dir" || return 11
pip install --target "$package_test_dir" --upgrade "${package_name}==${package_version}"
package_was_installed="$?"
echo "cleaning up test install (${package_test_dir})"
rm -rf "$package_test_dir" || return 12
if [[ "$package_was_installed" -ne "0" ]]
then
echo "FAILED TO INSTALL ${package_name}==${package_version} (status=${package_was_installed})" 1>&2
return 13
fi
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment