[tor-commits] [sbws/maint-1.1] new: scripts: Add script to help new releases.

juga at torproject.org juga at torproject.org
Tue Aug 11 13:51:35 UTC 2020


commit f5d236b570e16e87bf38053fadfb40cbe387b051
Author: juga0 <juga at riseup.net>
Date:   Wed Feb 6 18:52:55 2019 +0000

    new: scripts: Add script to help new releases.
---
 scripts/maint/release.py | 204 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 204 insertions(+)

diff --git a/scripts/maint/release.py b/scripts/maint/release.py
new file mode 100755
index 0000000..01e63e8
--- /dev/null
+++ b/scripts/maint/release.py
@@ -0,0 +1,204 @@
+#!/usr/bin/env python3
+# Copyright 2019 juga (juga at riseup dot net), CC0 license.
+"""Script to help release new versions.
+
+usage: release.py GPG_KEY_IDENTIFIER
+
+It will:
+0. Detect the current program version
+1. Ask which version to release
+2. Update the changelog automatically with ``gitchangelog``
+   and leave the option to user to manually edit it
+3. Modify the program version to release version,
+   commit it and commit changelog
+4. Create a version with the tag and sign it
+5. Push the commit and tag to the repository
+6. Obtain the release tarball from Github
+7. Sign the release tarball
+8. Modify the program to the next prerelease version and commit it
+9. Push the commit
+
+All in sequence and doesn't recover from any previous step.
+
+It assumes that:
+- the program version is in ``__init__.py.__version__``
+- gitchangelog and semantic_version are installed
+- we are in the master branch
+- the remote repository to push is origin
+- the next prerelease version is the release version + "-dev0"
+- the official releases tarballs are in Github (because no access to dist.tpo)
+- the key to sign the release is only one and is available in the system
+
+"""
+import re
+import subprocess
+import sys
+try:
+    import semantic_version
+except ImportError:
+    print("Please, install semantic_version")
+    sys.exit(1)
+try:
+    import gitchangelog  # noqa
+except ImportError:
+    print("Please, install gitchangelog")
+    sys.exit(1)
+
+import sbws
+
+
+def obtain_release_version(version):
+    # Ensure this is a prerelease version (eg 1.0.3-dev0)
+    assert version.prerelease
+    release_type_dict = {
+        1: version.next_patch(),
+        2: version.next_minor(),
+        3: version.next_major(),
+    }
+    print("Current prerelease version: ", version)
+    print("which version would you like to release?:")
+    print("1. to patch release: ", release_type_dict[1])
+    print("2. to minor release: ", release_type_dict[2])
+    print("3. to major release: ", release_type_dict[3])
+    release_type = int(input())
+    try:
+        return release_type_dict[release_type]
+    except KeyError:
+        print("Invalid release.")
+        sys.exit(1)
+
+
+def replace_version(old_version, new_version):
+    with open(sbws.__file__, 'r+') as f:
+        text = f.read()
+        text = re.sub(str(old_version), str(new_version), text)
+        f.seek(0)
+        f.write(text)
+        f.truncate()
+
+
+def obtain_next_prerelease_version(release_version):
+    # Assuming that we are only jumping from release to `-dev0`
+    next_prerelease_version = semantic_version.Version(
+        str(release_version.next_patch()) + "-dev0"
+        )
+    return next_prerelease_version
+
+
+def main(args):
+    print(__doc__)
+    try:
+        keyid = args[0]
+    except IndexError:
+        print("Please, pass a GPG key identifier as argument.")
+        sys.exit(1)
+    print("1. Which version to release")
+    print("---------------------------")
+    current_version = semantic_version.Version(sbws.__version__)
+    release_version = obtain_release_version(current_version)
+
+    print("\n2. Update changelog")
+    print("-------------------")
+    print("Creating tag v{} so that gitchangelog will create the new section "
+          "with the correct new tag...".format(release_version))
+    subprocess.call(['git', 'tag', 'v{}'.format(release_version),
+                     '-m', '\"Release version {}.\"'.format(release_version)])
+
+    print("\nUpdating the changelog automatically...")
+    subprocess.call('gitchangelog'.split(' '))
+
+    print("\nEdit the changelog manually to remove merge commits and "
+          "leave only the apropiate paragraph for every bug/feature.")
+    input("Press enter when done.\n")
+
+    print("\nRemoving the tag...")
+    subprocess.call(['git', 'tag', '-d', 'v{}'.format(release_version)])
+
+    print("\n3. Modify program version")
+    print("--------------------------")
+    print("\nReplacing __init__.py version with the release version...")
+    replace_version(current_version, release_version)
+
+    print("\nCommiting __init__.py and CHANGELOG.rst...")
+    subprocess.call(['git', 'commit',
+                     '-am', '"Release version {}."'.format(release_version)])
+
+    print("\n4. Create tag and sign it")
+    print("--------------------------")
+    print("\nCreating the final tag and signing it...")
+    subprocess.call(['git', 'tag', '-s', 'v{}'.format(release_version),
+                     '-m', '"Release version {}."'.format(release_version)])
+
+    print("\n5. Push commit and tag")
+    print("----------------------")
+    print("\nPush now so that the Github tarball will have the"
+          " correct tag...")
+    input("Press enter when you are sure everything is correct.")
+    subprocess.call(['git', 'push', 'origin', 'master'])
+
+    # While we use Github releases and not dist.tpo
+    print("\n6. Create release tarball")
+    print("-------------------------")
+
+    print("\nCreating a release tarball...")
+    subprocess.call(
+        "git archive --format=tar.gz --prefix=sbws-{}/ "
+        "-o v{}.tar.gz v{}"
+        .format(release_version, release_version, release_version).split(' ')
+    )
+    print("\nCreating tarball hash file...")
+    fd = open('v{}.tar.gz.sha256'.format(release_version), 'w')
+    subprocess.call("sha256sum v{}.tar.gz".format(release_version).split(' '),
+                    stdout=fd)
+    fd.close()
+
+    print("Obtaining Github tarball...")
+    # This will overwrite local tarball, but that's fine since the hash file
+    # won't be overwritten.
+    subprocess.call(
+        "wget https://github.com/torproject/sbws/archive/v{}.tar.gz "
+        "-O v{}.tar.gz"
+        .format(release_version, release_version).split(' ')
+        )
+
+    print("Verifying Github tarball and local one are the same...")
+    try:
+        subprocess.check_call("sha256sum -c v{}.tar.gz.sha256"
+                              .format(release_version).split(' '))
+    except subprocess.CalledProcessError:
+        print("Tarballs are not the same")
+        sys.exit(1)
+
+    print("\n7. Create the tarball signature")
+    print("-------------------------------")
+    print("Creating detached signature...")
+    subprocess.call("gpg --default-key {} "
+                    "--output v{}.tar.gz.asc "
+                    "--detach-sign v{}.tar.gz"
+                    .format(keyid, release_version, release_version)
+                    .split(' '))
+
+    print("\nUpload the signature manually to Github.")
+    input("Press enter when done.")
+    print("\nRelease done!!!.")
+
+    print("\n8. Create next prerelease version")
+    print("---------------------------------")
+    next_prerelease_version = obtain_next_prerelease_version(release_version)
+    print("\nReplacing the version in the program with "
+          "the next prerelease version...")
+    replace_version(release_version, next_prerelease_version)
+
+    print("\nCommitting the prerelease version...")
+    subprocess.call(['git', 'commit',
+                     '-am', '"Bump to {}."'.format(next_prerelease_version)])
+
+    print("\n9. Push commit")
+    print("--------------")
+    input("Press enter when you are sure everything is correct.")
+    subprocess.call(['git', 'push', 'origin', 'master'])
+    print("Done!")
+
+
+if __name__ == "__main__":
+    main(sys.argv[1:])





More information about the tor-commits mailing list