Revamp the release script: drop invoke and use tox directly

Following the lead from tox, use a simple Python script instead of depending
on ``invoke``.

Other changes:

* Some colors using ``colorama``.
* Run ``pre-commit`` before the final commit to ensure everything is neatly
  formatted.
* Drop generating local tag: legacy from the time we used ``devpi`` as staging
  area, currently we no longer use it, and we should push a
  tag from the last HEAD of the PR always to ensure it is correct.
This commit is contained in:
Bruno Oliveira 2018-07-14 10:21:31 -03:00
parent 0565a7a4e1
commit a0b0c37feb
7 changed files with 55 additions and 72 deletions

View File

@ -18,19 +18,11 @@ taking a lot of time to make a new one.
Ensure your are in a clean work tree. Ensure your are in a clean work tree.
#. Install development dependencies in a virtual environment with:: #. Using ``tox``, generate docs, changelog, announcements::
$ pip3 install -U -r tasks/requirements.txt $ tox -e release -- <VERSION>
#. Generate docs, changelog, announcements, and a **local** tag::
$ invoke generate.pre-release <VERSION>
#. Execute pre-commit on all files to ensure the docs are conformant and commit your results::
$ pre-commit run --all-files
$ git commit -am "Fix files with pre-commit"
This will generate a commit with all the changes ready for pushing.
#. Open a PR for this branch targeting ``master``. #. Open a PR for this branch targeting ``master``.

View File

@ -1,14 +1,13 @@
""" """
Invoke development tasks. Invoke development tasks.
""" """
import argparse
from colorama import init, Fore
from pathlib import Path from pathlib import Path
from subprocess import check_output, check_call from subprocess import check_output, check_call, call
import invoke
@invoke.task(help={"version": "version being released"}) def announce(version):
def announce(ctx, version):
"""Generates a new release announcement entry in the docs.""" """Generates a new release announcement entry in the docs."""
# Get our list of authors # Get our list of authors
stdout = check_output(["git", "describe", "--abbrev=0", "--tags"]) stdout = check_output(["git", "describe", "--abbrev=0", "--tags"])
@ -38,7 +37,7 @@ def announce(ctx, version):
"../doc/en/announce/release-{}.rst".format(version) "../doc/en/announce/release-{}.rst".format(version)
) )
target.write_text(text, encoding="UTF-8") target.write_text(text, encoding="UTF-8")
print("[generate.announce] Generated {}".format(target.name)) print(f"{Fore.CYAN}[generate.announce] {Fore.RESET}Generated {target.name}")
# Update index with the new release entry # Update index with the new release entry
index_path = Path(__file__).parent.joinpath("../doc/en/announce/index.rst") index_path = Path(__file__).parent.joinpath("../doc/en/announce/index.rst")
@ -50,69 +49,63 @@ def announce(ctx, version):
if line != new_line: if line != new_line:
lines.insert(index, new_line) lines.insert(index, new_line)
index_path.write_text("\n".join(lines) + "\n", encoding="UTF-8") index_path.write_text("\n".join(lines) + "\n", encoding="UTF-8")
print("[generate.announce] Updated {}".format(index_path.name)) print(
f"{Fore.CYAN}[generate.announce] {Fore.RESET}Updated {index_path.name}"
)
else: else:
print( print(
"[generate.announce] Skip {} (already contains release)".format( f"{Fore.CYAN}[generate.announce] {Fore.RESET}Skip {index_path.name} (already contains release)"
index_path.name
)
) )
break break
check_call(["git", "add", str(target)]) check_call(["git", "add", str(target)])
@invoke.task() def regen():
def regen(ctx):
"""Call regendoc tool to update examples and pytest output in the docs.""" """Call regendoc tool to update examples and pytest output in the docs."""
print("[generate.regen] Updating docs") print(f"{Fore.CYAN}[generate.regen] {Fore.RESET}Updating docs")
check_call(["tox", "-e", "regen"]) check_call(["tox", "-e", "regen"])
@invoke.task() def fix_formatting():
def make_tag(ctx, version): """Runs pre-commit in all files to ensure they are formatted correctly"""
"""Create a new, local tag for the release, only if the repository is clean.""" print(
from git import Repo f"{Fore.CYAN}[generate.fix linting] {Fore.RESET}Fixing formatting using pre-commit"
)
repo = Repo(".") call(["pre-commit", "run", "--all-files"])
if repo.is_dirty():
print("Current repository is dirty. Please commit any changes and try again.")
raise invoke.Exit(code=2)
tag_names = [x.name for x in repo.tags]
if version in tag_names:
print("[generate.make_tag] Delete existing tag {}".format(version))
repo.delete_tag(version)
print("[generate.make_tag] Create tag {}".format(version))
repo.create_tag(version)
@invoke.task(help={"version": "version being released"}) def pre_release(version):
def pre_release(ctx, version):
"""Generates new docs, release announcements and creates a local tag.""" """Generates new docs, release announcements and creates a local tag."""
announce(ctx, version) announce(version)
regen(ctx) regen()
changelog(ctx, version, write_out=True) changelog(version, write_out=True)
fix_formatting()
msg = "Preparing release version {}".format(version) msg = "Preparing release version {}".format(version)
check_call(["git", "commit", "-a", "-m", msg]) check_call(["git", "commit", "-a", "-m", msg])
make_tag(ctx, version)
print() print()
print("[generate.pre_release] Please push your branch and open a PR.") print(f"{Fore.CYAN}[generate.pre_release] {Fore.GREEN}All done!")
print()
print(f"Please push your branch and open a PR.")
@invoke.task( def changelog(version, write_out=False):
help={
"version": "version being released",
"write_out": "write changes to the actual changelog",
}
)
def changelog(ctx, version, write_out=False):
if write_out: if write_out:
addopts = [] addopts = []
else: else:
addopts = ["--draft"] addopts = ["--draft"]
check_call(["towncrier", "--yes", "--version", version] + addopts) check_call(["towncrier", "--yes", "--version", version] + addopts)
def main():
init(autoreset=True)
parser = argparse.ArgumentParser()
parser.add_argument("version", help="Release version")
options = parser.parse_args()
pre_release(options.version)
if __name__ == "__main__":
main()

View File

@ -1,10 +0,0 @@
"""
Invoke tasks to help with pytest development and release process.
"""
import invoke
from . import generate
ns = invoke.Collection(generate)

View File

@ -1,6 +0,0 @@
-e .
gitpython
invoke
towncrier
tox
wheel

14
tox.ini
View File

@ -176,6 +176,20 @@ commands =
coverage report -m coverage report -m
coveralls coveralls
[testenv:release]
decription = do a release, required posarg of the version number
basepython = python3.6
skipsdist = True
usedevelop = True
passenv = *
deps =
colorama
gitpython
pre-commit
towncrier
wheel
commands = python scripts/release.py {posargs}
[pytest] [pytest]
minversion = 2.0 minversion = 2.0
plugins = pytester plugins = pytester