Skip to content

Commit 1e85a28

Browse files
authored
Better PyPI scripting for releasing versions (#6)
Any tag will create source and wheel distributions on Travis CI and AppVeyor, but only the v0.1.2 formatted tags will get a release on production PyPI. Any other tag, including v0.1.2.dev3, will be uploaded to Test PyPI. Small fixes: The brew installer under OSX now outputs to stderr. This commit also includes some Flake8 fixes.
1 parent ebed62a commit 1e85a28

File tree

5 files changed

+71
-41
lines changed

5 files changed

+71
-41
lines changed

.appveyor/appveyor-bootstrap.py

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
"""
2-
AppVeyor will at least have few Pythons around so there's no point of implementing a bootstrapper in PowerShell.
2+
AppVeyor will at least have few Pythons around so there's no point of
3+
implementing a bootstrapper in PowerShell.
34
4-
This is a port of https://github.com/pypa/python-packaging-user-guide/blob/master/source/code/install.ps1
5-
with various fixes and improvements that just weren't feasible to implement in PowerShell.
5+
This is a port of
6+
https://github.com/pypa/python-packaging-user-guide/blob/master/source/code/install.ps1
7+
with various fixes and improvements that just weren't feasible to
8+
implement in PowerShell.
69
"""
710
from __future__ import print_function
811

@@ -40,15 +43,20 @@
4043
("3.6", "32"): BASE_URL + "3.6.0/python-3.6.0.exe",
4144
}
4245
INSTALL_CMD = {
43-
# Commands are allowed to fail only if they are not the last command. Eg: uninstall (/x) allowed to fail.
46+
# Commands are allowed to fail only if they are not the last command.
47+
# Eg: uninstall (/x) allowed to fail.
4448
"2.6": [["msiexec.exe", "/L*+!", "install.log", "/qn", "/x", "{path}"],
45-
["msiexec.exe", "/L*+!", "install.log", "/qn", "/i", "{path}", "TARGETDIR={home}"]],
49+
["msiexec.exe", "/L*+!", "install.log", "/qn", "/i", "{path}",
50+
"TARGETDIR={home}"]],
4651
"2.7": [["msiexec.exe", "/L*+!", "install.log", "/qn", "/x", "{path}"],
47-
["msiexec.exe", "/L*+!", "install.log", "/qn", "/i", "{path}", "TARGETDIR={home}"]],
52+
["msiexec.exe", "/L*+!", "install.log", "/qn", "/i", "{path}",
53+
"TARGETDIR={home}"]],
4854
"3.3": [["msiexec.exe", "/L*+!", "install.log", "/qn", "/x", "{path}"],
49-
["msiexec.exe", "/L*+!", "install.log", "/qn", "/i", "{path}", "TARGETDIR={home}"]],
55+
["msiexec.exe", "/L*+!", "install.log", "/qn", "/i", "{path}",
56+
"TARGETDIR={home}"]],
5057
"3.4": [["msiexec.exe", "/L*+!", "install.log", "/qn", "/x", "{path}"],
51-
["msiexec.exe", "/L*+!", "install.log", "/qn", "/i", "{path}", "TARGETDIR={home}"]],
58+
["msiexec.exe", "/L*+!", "install.log", "/qn", "/i", "{path}",
59+
"TARGETDIR={home}"]],
5260
"3.5": [["{path}", "/quiet", "TargetDir={home}"]],
5361
"3.6": [["{path}", "/quiet", "TargetDir={home}"]],
5462
}
@@ -82,7 +90,7 @@ def install_python(version, arch, home):
8290
log.info("Running '%s'.", " ".join(cmd))
8391
try:
8492
check_call(cmd)
85-
except Exception as exc:
93+
except Exception:
8694
log.exception("Failed command '%s'.", " ".join(cmd))
8795
if exists("install.log"):
8896
with open("install.log") as fh:
@@ -99,7 +107,7 @@ def download_python(version, arch):
99107
for _ in range(3):
100108
try:
101109
return download_file(URLS[version, arch], "installer.exe")
102-
except Exception as exc:
110+
except Exception:
103111
log.exception("Failed to download.")
104112
log.info("Retrying ...")
105113

@@ -126,6 +134,9 @@ def install_packages(home, *packages):
126134
logging.basicConfig(level=logging.DEBUG,
127135
format="%(message)s")
128136

129-
install_python(environ['PYTHON_VERSION'], environ['PYTHON_ARCH'], environ['PYTHON_HOME'])
137+
install_python(environ['PYTHON_VERSION'],
138+
environ['PYTHON_ARCH'],
139+
environ['PYTHON_HOME'])
130140
install_pip(environ['PYTHON_HOME'])
131-
install_packages(environ['PYTHON_HOME'], "setuptools>=36.4.0", "wheel")
141+
install_packages(environ['PYTHON_HOME'],
142+
"setuptools>=36.4.0", "wheel")

.travis.yml

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,15 @@ env:
1212
- secure: Od+iImlaOP2qzkGstfj3TTmhqWDdtZ1+CGFPJnHzZ9mj9l3Pg1Aek369f1MsGBXZeJqojiTx1xg/XzW3xH39QzbuynMGEFYOAZDnQMJsT990H1vKyHsoQ86t4n0T7FEIs6B5BzP1oDROdADHcxmRQ1BoSvWumbq/isGewArGO0M=
1313
# TWINE_PASSWORD
1414
- secure: cMN061O5PjB3B8+iSEgyo/qe3QPSDW8GaAupYtHKLnxT2M6JiepuVzZL40y9I1QTnZQMf8VIKH7XExLkgyVvbKZyQCctp9tioBBiAafp6uhAQMLSzj1+03gBzaJQJySPMLX4Snfa/TuhOqym5m4kYQTX/p3qCImzkgxWW1SV+rc=
15-
- TWINE_REPOSITORY=https://test.pypi.org/legacy/
16-
- TWINE_REPOSITORY_URL=https://test.pypi.org/legacy/
15+
- TWINE_TEST_REPOSITORY=pypitest
16+
- TWINE_TEST_REPOSITORY_URL=https://test.pypi.org/legacy/
17+
- TWINE_PROD_REPOSITORY=pypi
18+
- TWINE_PROD_REPOSITORY_URL=https://upload.pypi.org/legacy/
1719

1820
stages:
1921
- name: test
2022
- name: deploy
21-
if: type = push AND tag =~ ^v\d+\.\d+\.\d+
23+
if: type = push AND tag IS present
2224

2325
os:
2426
- linux
@@ -39,23 +41,23 @@ python:
3941
before_install:
4042
- if [[ $TRAVIS_OS_NAME == "osx" ]]; then
4143
echo "Updating brew packages.";
42-
brew update || travis_terminate 1;
44+
brew update 1>&2 || travis_terminate 1;
4345
if [[ $TRAVIS_PYTHON_VERSION == "2.7" ]]; then
4446
echo "Installing python 2.";
45-
brew upgrade python2 || travis_terminate 1;
47+
brew upgrade python2 1>&2 || travis_terminate 1;
4648
virtualenv venv -p python2;
4749
elif [[ $TRAVIS_PYTHON_VERSION == "3.6" ]]; then
4850
echo "Installing python 3.";
49-
brew install python3 || travis_terminate 1;
51+
brew install python3 1>&2 || travis_terminate 1;
5052
virtualenv venv -p python3;
5153
fi;
5254
source venv/bin/activate || travis_terminate 1;
5355
python --version || travis_terminate 1;
5456
fi
55-
- if [[ $TRAVIS_PULL_REQUEST == false && $TRAVIS_TAG =~ v[0-9]+\.[0-9]+\.[0-9]+ ]]; then
57+
- if [[ $TRAVIS_PULL_REQUEST == false && -n $TRAVIS_TAG ]]; then
5658
if [[ $TRAVIS_OS_NAME == "osx" ]]; then
5759
echo "Installing pandoc.";
58-
brew install pandoc || travis_terminate 1;
60+
brew install pandoc 1>&2 || travis_terminate 1;
5961
fi;
6062
echo "Installing pypandoc.";
6163
pip install pypandoc || travis_terminate 1;
@@ -67,15 +69,15 @@ install:
6769
script:
6870
- python setup.py test || travis_terminate 1
6971
# Need to pick a Python version to create the source distribution.
70-
- if [[ $TRAVIS_PYTHON_VERSION == "3.6" && $TRAVIS_OS_NAME == linux && $TRAVIS_PULL_REQUEST == false && $TRAVIS_TAG =~ v[0-9]+\.[0-9]+\.[0-9]+ ]]; then
72+
- if [[ $TRAVIS_PYTHON_VERSION == "3.6" && $TRAVIS_OS_NAME == linux && $TRAVIS_PULL_REQUEST == false && -n $TRAVIS_TAG ]]; then
7173
echo "Creating source distribution.";
7274
python setup.py sdist || travis_terminate 1;
7375
else
7476
echo "Skip creation of source distribution.";
7577
fi
7678
# Binary wheels for Linux that are too platform specific are not allowed to
7779
# be uploaded on PyPI. As we need to compile C code, we only create them on OSX.
78-
- if [[ $TRAVIS_OS_NAME == osx && $TRAVIS_PULL_REQUEST == false && $TRAVIS_TAG =~ v[0-9]+\.[0-9]+\.[0-9]+ ]]; then
80+
- if [[ $TRAVIS_OS_NAME == osx && $TRAVIS_PULL_REQUEST == false && -n $TRAVIS_TAG ]]; then
7981
echo "Creating binary distribution wheel.";
8082
python setup.py bdist_wheel || travis_terminate 1;
8183
else
@@ -124,9 +126,17 @@ jobs:
124126
script:
125127
- echo "Check build status."
126128
- python .travis/travis-release.py || travis_terminate 1
127-
- echo "Deploy to PyPI stage."
129+
- echo "Installing Twine."
128130
- pip install twine || travis_terminate 1
129-
- twine upload dist/* --skip-existing || travis_terminate 1
131+
- if [[ $TRAVIS_PULL_REQUEST == false && -n $TRAVIS_TAG ]]; then
132+
if [[ $TRAVIS_TAG =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
133+
echo "Deploy to production PyPI.";
134+
twine upload -r $TWINE_PROD_REPOSITORY --repository-url $TWINE_PROD_REPOSITORY_URL dist/* --skip-existing || travis_terminate 1;
135+
else
136+
echo "Deploy to test PyPI.";
137+
twine upload -r $TWINE_TEST_REPOSITORY --repository-url $TWINE_TEST_REPOSITORY_URL dist/* --skip-existing || travis_terminate 1;
138+
fi;
139+
fi
130140

131141
notifications:
132142
email:

.travis/travis-release.py

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import json
33
import logging
44
import os
5+
import re
56
import shutil
67
import stat
78

@@ -77,7 +78,7 @@ def api_request(url, token):
7778
request.add_header('Authorization', 'token {}'.format(token))
7879
response = urlopen(request)
7980
break
80-
except Exception as exc:
81+
except Exception:
8182
log.exception("Failed to call API.")
8283
log.info("Retrying ...")
8384
sleep(i)
@@ -240,18 +241,30 @@ def check_appveyor_tagged_build(url, tag, token):
240241

241242

242243
def check_code_version(filenames, tag):
243-
"""Check if the asset filenames relate to the tag version."""
244-
wheel_part = "-{}-".format(tag[1:])
245-
targz_part = "-{}.tar.gz".format(tag[1:])
244+
"""Check if the asset filenames relate to the tag version.
245+
246+
When tag is in the form v0.1.2 the first character is stripped.
247+
248+
Raises ReleaseVersionException when the tag is not found in any
249+
of the asset file names.
250+
"""
251+
if re.match(r"v\d+\.\d+\.\d+", tag) is not None:
252+
file_tag = tag[1:]
253+
else:
254+
file_tag = tag
255+
wheel_part = "-{}-".format(file_tag)
256+
targz_part = "-{}.tar.gz".format(file_tag)
246257
for filename in filenames:
247258
if (filename[-4:] == '.whl') and (wheel_part not in filename):
248-
log.info("Filename '%s' does not correspond "
249-
"to tag '%s'.", filename, tag)
250-
return False
259+
log.error("Filename '%s' does not correspond "
260+
"to tag '%s'.", filename, tag)
261+
raise ReleaseVersionException("Version mismatch "
262+
"between code and tag")
251263
if (filename[-7:] == '.tar.gz') and (targz_part not in filename):
252-
log.info("Filename '%s' does not correspond "
253-
"to tag '%s'.", filename, tag)
254-
return False
264+
log.error("Filename '%s' does not correspond "
265+
"to tag '%s'.", filename, tag)
266+
raise ReleaseVersionException("Version mismatch "
267+
"between code and tag")
255268
return True
256269

257270

@@ -273,6 +286,4 @@ def check_code_version(filenames, tag):
273286
gh_url, tag,
274287
gh_token)
275288
log.info("All assets downloaded for tagged release '%s'.", tag)
276-
if not check_code_version(filenames, tag):
277-
raise ReleaseVersionException("Version mismatch "
278-
"between code and tag")
289+
check_code_version(filenames, tag)

appveyor.yml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,7 @@ test_script:
8888

8989
after_test:
9090
- ps: |
91-
if ($env:APPVEYOR_REPO_TAG -and
92-
$env:APPVEYOR_REPO_TAG_NAME -match "v\d\.\d\.\d")
93-
{
91+
if ($env:APPVEYOR_REPO_TAG -eq $true) {
9492
Write-Host "Installing pandoc."
9593
cinst --no-progress pandoc
9694
if ($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode) }

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from io import open
99

1010

11-
VERSION = '1.0.0.dev2'
11+
VERSION = '1.0.0.dev3'
1212
GITHUB_URL = 'https://github.com/oohlaf/python-whirlpool'
1313
DOWNLOAD_URL = '{}/archive/{}.zip'.format(GITHUB_URL, VERSION)
1414

0 commit comments

Comments
 (0)