diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..c8572b8 --- /dev/null +++ b/Makefile @@ -0,0 +1,72 @@ +# How to Make a Release +# --------------------- +# +# This file answers the question "how to make a release" hopefully +# better than a document does (only meejah and warner may currently do +# the "upload to PyPI" part anyway) +# + +default: + echo "see Makefile" + +release-clean: + @echo "Cleanup stale release: " `python newest-version.py` + -rm NEWS.md.asc + -rm dist/magic-wormhole-transit-relay-`python newest-version.py`.tar.gz* + -rm dist/magic_wormhole_transit_relay-`python newest-version.py`-py3-none-any.whl* + git tag -d `python newest-version.py` + +# create a branch, like: git checkout -b prepare-release-0.16.0 +# then run these, so CI can run on the release +release: + @echo "Is checkout clean?" + git diff-files --quiet + git diff-index --quiet --cached HEAD -- + + @echo "Install required build software" + python -m pip install --editable .[dev,release] + + @echo "Test README" + python setup.py check -s + + @echo "Is GPG Agent rubnning, and has key?" + gpg --pinentry=loopback -u meejah@meejah.ca --armor --clear-sign NEWS.md + + @echo "Bump version and create tag" + python update-version.py +# python update-version.py --patch # for bugfix release + + @echo "Build and sign wheel" + python setup.py bdist_wheel + gpg --pinentry=loopback -u meejah@meejah.ca --armor --detach-sign dist/magic_wormhole_transit_relay-`git describe --abbrev=0`-py3-none-any.whl + ls dist/*`git describe --abbrev=0`* + + @echo "Build and sign source-dist" + python setup.py sdist + gpg --pinentry=loopback -u meejah@meejah.ca --armor --detach-sign dist/magic-wormhole-transit-relay-`git describe --abbrev=0`.tar.gz + ls dist/*`git describe --abbrev=0`* + +release-test: + gpg --verify dist/magic-wormhole-transit-relay-`git describe --abbrev=0`.tar.gz.asc + gpg --verify dist/magic_wormhole_transit_relay-`git describe --abbrev=0`-py3-none-any.whl.asc + python -m venv testmf_venv + testmf_venv/bin/pip install --upgrade pip + testmf_venv/bin/pip install dist/magic_wormhole_transit_relay-`git describe --abbrev=0`-py3-none-any.whl + testmf_venv/bin/twistd transitrelay --version + testmf_venv/bin/pip uninstall -y magic_wormhole_transit_relay + testmf_venv/bin/pip install dist/magic-wormhole-transit-relay-`git describe --abbrev=0`.tar.gz + testmf_venv/bin/twistd transitrelay --version + rm -rf testmf_venv + +release-upload: + twine upload --username __token__ --password `cat PRIVATE-release-token` dist/magic_wormhole_transit_relay-`git describe --abbrev=0`-py3-none-any.whl dist/magic_wormhole_transit_relay-`git describe --abbrev=0`-py3-none-any.whl.asc dist/magic-wormhole-transit-relay-`git describe --abbrev=0`.tar.gz dist/magic-wormhole-transit-relay-`git describe --abbrev=0`.tar.gz.asc + mv dist/*-`git describe --abbrev=0`.tar.gz.asc signatures/ + mv dist/*-`git describe --abbrev=0`-py3-none-any.whl.asc signatures/ + git add signatures/magic-wormhole-transit-relay-`git describe --abbrev=0`.tar.gz.asc + git add signatures/magic_wormhole_transit_relay-`git describe --abbrev=0`-py3-none-any.whl.asc + git commit -m "signatures for release" + git push origin-push `git describe --abbrev=0` + + +dilation.png: dilation.seqdiag + seqdiag --no-transparency -T png --size 1000x800 -o dilation.png diff --git a/newest-version.py b/newest-version.py new file mode 100644 index 0000000..e2449cb --- /dev/null +++ b/newest-version.py @@ -0,0 +1,23 @@ +# +# print out the most-recent version +# + +from dulwich.repo import Repo +from dulwich.porcelain import tag_list + + +def existing_tags(git): + versions = [ + tuple(map(int, v.decode("utf8").split("."))) + for v in tag_list(git) + ] + return versions + + +def main(): + git = Repo(".") + print("{}.{}.{}".format(*sorted(existing_tags(git))[-1])) + + +if __name__ == "__main__": + main() diff --git a/setup.cfg b/setup.cfg index 1bd2699..f6eefdb 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,3 @@ -[wheel] -universal = 1 - [versioneer] VCS = git versionfile_source = src/wormhole_transit_relay/_version.py diff --git a/setup.py b/setup.py index 7119506..baa040e 100644 --- a/setup.py +++ b/setup.py @@ -24,6 +24,7 @@ extras_require={ ':sys_platform=="win32"': ["pypiwin32"], "dev": ["mock", "tox", "pyflakes"], + "release": ["dulwich", "docutils", "gpg", "wheel"], }, test_suite="wormhole_transit_relay.test", cmdclass=commands, diff --git a/signatures/magic-wormhole-transit-relay-0.4.0.tar.gz.asc b/signatures/magic-wormhole-transit-relay-0.4.0.tar.gz.asc new file mode 100644 index 0000000..f8875a3 --- /dev/null +++ b/signatures/magic-wormhole-transit-relay-0.4.0.tar.gz.asc @@ -0,0 +1,11 @@ +-----BEGIN PGP SIGNATURE----- + +iQFFBAABCgAvFiEEnVor1WiOy4id680/wmAoAxKAaacFAmcsFx0RHG1lZWphaEBt +ZWVqYWguY2EACgkQwmAoAxKAaacIYgf+Il+zhzvG3Wei+KKeJGsTfeoILaJVVr4t ++voTliO8SXFzZZncc/U8PK61yrJcnOf3nivsBa3s9Uin9gUpqKN1RReonX44UTmq +xhi9FlLG/8mta2AzKLIP91w2pcSnzDhez6bb78MbrtEdnI99AKIGd2Mv9Bzl6EbT +AniGPiVLV6f5SugwCONUZFfJSaoYh/0Y1ejgCtCI1QXoYRXEy8HwdIMVfIbuHRNU +3O/mgxnZWEIsx1yfSywPvfc9lf07jc/62098RePUOCujgcWzJFheCrJhrc0vNkPu +91y9RG2MWFW43tNZvCQKdnY4M0UGZKxuiOiSG4dVGwGH4KWlYw/Pjg== +=3FSB +-----END PGP SIGNATURE----- diff --git a/signatures/magic_wormhole_transit_relay-0.4.0-py3-none-any.whl.asc b/signatures/magic_wormhole_transit_relay-0.4.0-py3-none-any.whl.asc new file mode 100644 index 0000000..7f1ec6e --- /dev/null +++ b/signatures/magic_wormhole_transit_relay-0.4.0-py3-none-any.whl.asc @@ -0,0 +1,11 @@ +-----BEGIN PGP SIGNATURE----- + +iQFFBAABCgAvFiEEnVor1WiOy4id680/wmAoAxKAaacFAmcsFx0RHG1lZWphaEBt +ZWVqYWguY2EACgkQwmAoAxKAaacNjQgAzhY5vm9oznD7vF6uESCD71a8PhdSvc5p +rsID9jKv2Kj510FNS56iaTdOamn7NWwooQC3zA+ZEAAlkySm9mSkVWMcho29ESRI +PBn+KyfjANiWfHDqE07SZRwP6PpimcV/tCbxl2MCftMNcZvRXhcUuYLR6LD6EwxX +9V21rjmJy1PyLfiGIKiA32vXoh8OzZQAJ0dc8xaCSi5oQi1VJ4bAklMuCv47eMdD +kZmlkOMLSon482JhoFAyjdBoPsvcatkyEyzu5VrEHp8aIUkcn/4ExIBIrVm8HHkU +xEeAFPWJT45zr7is8Snc88syb+nOdmxtL2byM+7IP4z08kHvQ/ArMg== +=e8y/ +-----END PGP SIGNATURE----- diff --git a/update-version.py b/update-version.py new file mode 100644 index 0000000..8c5f450 --- /dev/null +++ b/update-version.py @@ -0,0 +1,100 @@ +# +# this updates the (tagged) version of the software +# +# it will only update the "minor" version (e.g. 0.12.* -> 0.13.0) +# +# Any "options" are hard-coded in here (e.g. the GnuPG key to use) +# + +import sys +import time +from datetime import datetime + +from dulwich.repo import Repo +from dulwich.porcelain import ( + tag_list, + tag_create, + status, +) + +from twisted.internet.task import ( + react, +) +from twisted.internet.defer import ( + ensureDeferred, +) + +author = "meejah " + + +def existing_tags(git): + versions = [ + tuple(map(int, v.decode("utf8").split("."))) + for v in tag_list(git) + ] + return versions + + +def create_new_version(git, only_patch): + versions = existing_tags(git) + major, minor, patch = sorted(versions)[-1] + if only_patch: + next_version = "{}.{}.{}".format(major, minor, patch + 1) + else: + next_version = "{}.{}.{}".format(major, minor + 1, 0) + return next_version + + +async def main(reactor): + git = Repo(".") + + # including untracked files can be very slow (if there are lots, + # like in virtualenvs) and we don't care anyway + st = status(git, untracked_files="no") + if any(st.staged.values()) or st.unstaged: + print("unclean checkout; aborting") + raise SystemExit(1) + + for arg in sys.argv[1:]: + if arg not in ("--no-tag", "--patch"): + print("unknown arg: {}".format(arg)) + raise SystemExit(2) + + v = create_new_version(git, "--patch" in sys.argv) + if "--no-tag" in sys.argv: + print(v) + return + + print("Latest version: {}.{}.{}".format(*sorted(existing_tags(git))[-1])) + print("New tag will be {}".format(v)) + + # the "tag time" is seconds from the epoch .. we quantize these to + # the start of the day in question, in UTC. + now = datetime.now() + s = now.utctimetuple() + ts = int( + time.mktime( + time.struct_time(( + s.tm_year, s.tm_mon, s.tm_mday, 0, 0, 0, 0, s.tm_yday, 0 + )) + ) + ) + tag_create( + repo=git, + tag=v.encode("utf8"), + author=author.encode("utf8"), + message="release magic-wormhole-{}".format(v).encode("utf8"), + annotated=True, + objectish=b"HEAD", + sign=author.encode("utf8"), + tag_time=ts, + tag_timezone=0, + ) + + print("Tag created locally, it is not pushed") + print("To push it run something like:") + print(" git push origin {}".format(v)) + + +if __name__ == "__main__": + react(lambda r: ensureDeferred(main(r)))