aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/releases.txt40
-rw-r--r--tools/finalize.py59
-rw-r--r--tox.ini7
3 files changed, 73 insertions, 33 deletions
diff --git a/docs/releases.txt b/docs/releases.txt
index 98ba39e8..35b415c2 100644
--- a/docs/releases.txt
+++ b/docs/releases.txt
@@ -3,39 +3,13 @@ Release Process
===============
In order to allow for rapid, predictable releases, Setuptools uses a
-mechanical technique for releases, enacted by Travis following a
-successful build of a tagged release per
-`PyPI deployment <https://docs.travis-ci.com/user/deployment/pypi>`_.
-
-Prior to cutting a release, please use `towncrier`_ to update
-``CHANGES.rst`` to summarize the changes since the last release.
-To update the changelog:
-
-1. Install towncrier via ``pip install towncrier`` if not already installed.
-2. Preview the new ``CHANGES.rst`` entry by running
- ``towncrier --draft --version {new.version.number}`` (enter the desired
- version number for the next release). If any changes are needed, make
- them and generate a new preview until the output is acceptable. Run
- ``git add`` for any modified files.
-3. Run ``towncrier --version {new.version.number}`` to stage the changelog
- updates in git.
-4. Verify that there are no remaining ``changelog.d/*.rst`` files. If a
- file was named incorrectly, it may be ignored by towncrier.
-5. Review the updated ``CHANGES.rst`` file. If any changes are needed,
- make the edits and stage them via ``git add CHANGES.rst``.
-
-Once the changelog edits are staged and ready to commit, cut a release by
-installing and running ``bump2version --allow-dirty {part}`` where ``part``
-is major, minor, or patch based on the scope of the changes in the
-release. Then, push the commits to the master branch::
-
- $ git push origin master
- $ git push --tags
-
-If tests pass, the release will be uploaded to PyPI (from the Python 3.6
-tests).
-
-.. _towncrier: https://pypi.org/project/towncrier/
+mechanical technique for releases, enacted on tagged commits by
+continuous integration.
+
+To finalize a release, run ``tox -e finalize``, review, then push
+the changes.
+
+If tests pass, the release will be uploaded to PyPI.
Release Frequency
-----------------
diff --git a/tools/finalize.py b/tools/finalize.py
new file mode 100644
index 00000000..3b66341a
--- /dev/null
+++ b/tools/finalize.py
@@ -0,0 +1,59 @@
+"""
+Finalize the repo for a release. Invokes towncrier and bumpversion.
+"""
+
+__requires__ = ['bump2version', 'towncrier']
+
+
+import subprocess
+import pathlib
+import re
+import sys
+
+
+def release_kind():
+ """
+ Determine which release to make based on the files in the
+ changelog.
+ """
+ # use min here as 'major' < 'minor' < 'patch'
+ return min(
+ 'major' if 'breaking' in file.name else
+ 'minor' if 'change' in file.name else
+ 'patch'
+ for file in pathlib.Path('changelog.d').iterdir()
+ )
+
+
+bump_version_command = [
+ sys.executable,
+ '-m', 'bumpversion',
+ release_kind(),
+]
+
+
+def get_version():
+ cmd = bump_version_command + ['--dry-run', '--verbose']
+ out = subprocess.check_output(cmd, text=True)
+ return re.search('^new_version=(.*)', out, re.MULTILINE).group(1)
+
+
+def update_changelog():
+ cmd = [
+ sys.executable, '-m',
+ 'towncrier',
+ '--version', get_version(),
+ '--yes',
+ ]
+ subprocess.check_call(cmd)
+
+
+def bump_version():
+ cmd = bump_version_command + ['--allow-dirty']
+ subprocess.check_call(cmd)
+
+
+if __name__ == '__main__':
+ print("Cutting release at", get_version())
+ update_changelog()
+ bump_version()
diff --git a/tox.ini b/tox.ini
index 1ebb922b..17201ca2 100644
--- a/tox.ini
+++ b/tox.ini
@@ -60,6 +60,13 @@ source=
omit=
*/_vendor/*
+[testenv:finalize]
+deps =
+ towncrier
+ bump2version
+commands =
+ python tools/finalize.py
+
[testenv:release]
skip_install = True
deps =