release.py 5.57 KB
Newer Older
1
2
3
4
5
6
#!/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

7
8
9
10
11
12
13
14
This is a fast and dirty script to help release new sbws versions.
It does not intent to cover all possible cases and errors because this is out
of the scope of sbws.
There are other tools [*] that help manage release tags, branches and
changelogs, but we should not add more requirements to sbws to just release a
new version.

This script will:
15
16
17
18
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
19
3. Commit the changelog
20
21
4. Create a version with the tag and sign it
5. Push the commit and tag to the repository
juga's avatar
juga committed
22
6. Obtain the release tarball
23
24
25
26
7. Sign the release tarball
8. Modify the program to the next prerelease version and commit it
9. Push the commit

27
All is done in sequence and doesn't recover from any previous step.
28
29

It assumes that:
30
- the program version can be obtained with ``sbws.__version__``
juga's avatar
juga committed
31
- ``gitchangelog`` and ``semantic_version`` python packages are installed
juga's avatar
juga committed
32
- the official tarball releases are at gitlab.torproject.org
33
34
- the key to sign the release is only one and is available in the system

35
36
37
[*] See for instance https://semantic-release.gitbook.io,
    https://github.com/GitTools/GitVersion

38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
"""
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):
    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 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)])

104
    print("\n3. Commit the changelog")
105
    print("--------------------------")
106
    print("\nCommiting CHANGELOG.rst...")
107
108
109
110
111
112
113
114
115
116
    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")
juga's avatar
juga committed
117
118
119
120
121
122
123
124
125
126
    print("------------------------")
    print("\nPush now so that the Gitlab creates the tarball from the new "
          " commit and tag, eg:")
    print("git push myremote mybranch")
    print("git push myremote --tags")
    input("Press enter when you are done.")

    print("\n6. Obtain the release tarball")
    print("-------------------------------")
    print("Obtaining Gitlab tarball...")
127
    subprocess.call(
juga's avatar
juga committed
128
        "wget https://gitlab.torproject.org/tpo/network-health/sbws/-/archive/v{}/sbws-v{}.tar.gz "
129
        "-O v{}.tar.gz"
juga's avatar
juga committed
130
        .format(release_version, release_version, release_version).split(' ')
131
132
133
134
135
136
137
138
139
140
141
        )

    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(' '))

juga's avatar
juga committed
142
    print("\nUpload the signature manually to Gitlab.")
143
144
145
    input("Press enter when done.")
    print("\nRelease done!!!.")

146
147
148
149
150
151
152
153
154
155
    print("\n8. Create next prerelease branch")
    print("----------------------------------")
    print("\nIf this release happens in a maintainance branch, merge the "
          "the commit to master and push, eg:"
          "git checkout master"
          "git merge --no-ff mybranch"
          "git push myremote master")
    next_branch_version = "maint{}".format(release_version)
    print("And create the next prerelease branch, eg:")
          "git checkout -b {}".format(next_branch_version)
156
157
158
159


if __name__ == "__main__":
    main(sys.argv[1:])