1#!/bin/bash 2 3set -ex 4 5function get_source_version() { 6 grep "__version__ = '.*'" python/google/protobuf/__init__.py | sed -r "s/__version__ = '(.*)'/\1/" 7} 8 9function run_install_test() { 10 local VERSION=$1 11 local PYTHON=$2 12 local PYPI=$3 13 14 virtualenv --no-site-packages -p `which $PYTHON` test-venv 15 16 # Intentionally put a broken protoc in the path to make sure installation 17 # doesn't require protoc installed. 18 touch test-venv/bin/protoc 19 chmod +x test-venv/bin/protoc 20 21 source test-venv/bin/activate 22 pip install -i ${PYPI} protobuf==${VERSION} --no-cache-dir 23 deactivate 24 rm -fr test-venv 25} 26 27 28[ $# -lt 1 ] && { 29 echo "Usage: $0 VERSION [" 30 echo "" 31 echo "Examples:" 32 echo " Test 3.3.0 release using version number 3.3.0.dev1:" 33 echo " $0 3.0.0 dev1" 34 echo " Actually release 3.3.0 to PyPI:" 35 echo " $0 3.3.0" 36 exit 1 37} 38VERSION=$1 39DEV=$2 40 41# Make sure we are in a protobuf source tree. 42[ -f "python/google/protobuf/__init__.py" ] || { 43 echo "This script must be ran under root of protobuf source tree." 44 exit 1 45} 46 47# Make sure all files are world-readable. 48find python -type d -exec chmod a+r,a+x {} + 49find python -type f -exec chmod a+r {} + 50umask 0022 51 52# Check that the supplied version number matches what's inside the source code. 53SOURCE_VERSION=`get_source_version` 54 55[ "${VERSION}" == "${SOURCE_VERSION}" -o "${VERSION}.${DEV}" == "${SOURCE_VERSION}" ] || { 56 echo "Version number specified on the command line ${VERSION} doesn't match" 57 echo "the actual version number in the source code: ${SOURCE_VERSION}" 58 exit 1 59} 60 61TESTING_ONLY=1 62TESTING_VERSION=${VERSION}.${DEV} 63if [ -z "${DEV}" ]; then 64 read -p "You are releasing ${VERSION} to PyPI. Are you sure? [y/n]" -r 65 echo 66 if [[ ! $REPLY =~ ^[Yy]$ ]]; then 67 exit 1 68 fi 69 TESTING_ONLY=0 70 TESTING_VERSION=${VERSION} 71else 72 # Use dev version number for testing. 73 sed -i -r "s/__version__ = '.*'/__version__ = '${VERSION}.${DEV}'/" python/google/protobuf/__init__.py 74fi 75 76cd python 77 78# Run tests locally. 79python setup.py build 80python setup.py test 81 82# Deploy source package to testing PyPI 83python setup.py sdist upload -r https://test.pypi.org/legacy/ 84 85# Test locally with different python versions. 86run_install_test ${TESTING_VERSION} python2.7 https://test.pypi.org/simple 87run_install_test ${TESTING_VERSION} python3 https://test.pypi.org/simple 88 89# Deploy egg/wheel packages to testing PyPI and test again. 90python setup.py bdist_egg bdist_wheel upload -r https://test.pypi.org/legacy/ 91 92run_install_test ${TESTING_VERSION} python2.7 https://test.pypi.org/simple 93run_install_test ${TESTING_VERSION} python3 https://test.pypi.org/simple 94 95echo "All install tests have passed using testing PyPI." 96 97if [ $TESTING_ONLY -eq 0 ]; then 98 read -p "Publish to PyPI? [y/n]" -r 99 echo 100 if [[ ! $REPLY =~ ^[Yy]$ ]]; then 101 exit 1 102 fi 103 echo "Publishing to PyPI..." 104 # Be sure to run build before sdist, because otherwise sdist will not include 105 # well-known types. 106 python setup.py clean build sdist upload 107 # Be sure to run clean before bdist_xxx, because otherwise bdist_xxx will 108 # include files you may not want in the package. E.g., if you have built 109 # and tested with --cpp_implemenation, bdist_xxx will include the _message.so 110 # file even when you no longer pass the --cpp_implemenation flag. See: 111 # https://github.com/protocolbuffers/protobuf/issues/3042 112 python setup.py clean build bdist_egg bdist_wheel upload 113else 114 # Set the version number back (i.e., remove dev suffix). 115 sed -i -r "s/__version__ = '.*'/__version__ = '${VERSION}'/" google/protobuf/__init__.py 116fi 117