summaryrefslogtreecommitdiffstats
path: root/release/sign-launcher.py
diff options
context:
space:
mode:
authorMike Frysinger <vapier@google.com>2020-02-20 15:13:51 -0500
committerDavid Pursehouse <dpursehouse@collab.net>2020-02-21 05:20:58 +0000
commit8c268c0e7bd18d1e2f4f526cd406c569312a5f23 (patch)
treee10fd5adc97ec9321c6a351134a1d031e1ac0adf /release/sign-launcher.py
parentd9254599f9bb47632313ecb90c5f281ceca5da3a (diff)
downloadgit-repo-8c268c0e7bd18d1e2f4f526cd406c569312a5f23.tar.gz
release: import some helper scripts for managing official releases
Change-Id: I9abebfef5ad19f6a637bc3b12effea9dd6d0269d Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/256234 Tested-by: Mike Frysinger <vapier@google.com> Reviewed-by: David Pursehouse <dpursehouse@collab.net>
Diffstat (limited to 'release/sign-launcher.py')
-rwxr-xr-xrelease/sign-launcher.py114
1 files changed, 114 insertions, 0 deletions
diff --git a/release/sign-launcher.py b/release/sign-launcher.py
new file mode 100755
index 00000000..ba5e490c
--- /dev/null
+++ b/release/sign-launcher.py
@@ -0,0 +1,114 @@
1#!/usr/bin/env python3
2# Copyright (C) 2020 The Android Open Source Project
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16"""Helper tool for signing repo launcher scripts correctly.
17
18This is intended to be run only by the official Repo release managers.
19"""
20
21import argparse
22import os
23import subprocess
24import sys
25
26import util
27
28
29def sign(opts):
30 """Sign the launcher!"""
31 output = ''
32 for key in opts.keys:
33 # We use ! at the end of the key so that gpg uses this specific key.
34 # Otherwise it uses the key as a lookup into the overall key and uses the
35 # default signing key. i.e. It will see that KEYID_RSA is a subkey of
36 # another key, and use the primary key to sign instead of the subkey.
37 cmd = ['gpg', '--homedir', opts.gpgdir, '-u', f'{key}!', '--batch', '--yes',
38 '--armor', '--detach-sign', '--output', '-', opts.launcher]
39 ret = util.run(opts, cmd, encoding='utf-8', stdout=subprocess.PIPE)
40 output += ret.stdout
41
42 # Save the combined signatures into one file.
43 with open(f'{opts.launcher}.asc', 'w', encoding='utf-8') as fp:
44 fp.write(output)
45
46
47def check(opts):
48 """Check the signature."""
49 util.run(opts, ['gpg', '--verify', f'{opts.launcher}.asc'])
50
51
52def postmsg(opts):
53 """Helpful info to show at the end for release manager."""
54 print(f"""
55Repo launcher bucket:
56 gs://git-repo-downloads/
57
58To upload this launcher directly:
59 gsutil cp -a public-read {opts.launcher} {opts.launcher}.asc gs://git-repo-downloads/
60
61NB: You probably want to upload it with a specific version first, e.g.:
62 gsutil cp -a public-read {opts.launcher} gs://git-repo-downloads/repo-3.0
63 gsutil cp -a public-read {opts.launcher}.asc gs://git-repo-downloads/repo-3.0.asc
64""")
65
66
67def get_parser():
68 """Get a CLI parser."""
69 parser = argparse.ArgumentParser(description=__doc__)
70 parser.add_argument('-n', '--dry-run',
71 dest='dryrun', action='store_true',
72 help='show everything that would be done')
73 parser.add_argument('--gpgdir',
74 default=os.path.join(util.HOMEDIR, '.gnupg', 'repo'),
75 help='path to dedicated gpg dir with release keys '
76 '(default: ~/.gnupg/repo/)')
77 parser.add_argument('--keyid', dest='keys', default=[], action='append',
78 help='alternative signing keys to use')
79 parser.add_argument('launcher',
80 default=os.path.join(util.TOPDIR, 'repo'), nargs='?',
81 help='the launcher script to sign')
82 return parser
83
84
85def main(argv):
86 """The main func!"""
87 parser = get_parser()
88 opts = parser.parse_args(argv)
89
90 if not os.path.exists(opts.gpgdir):
91 parser.error(f'--gpgdir does not exist: {opts.gpgdir}')
92 if not os.path.exists(opts.launcher):
93 parser.error(f'launcher does not exist: {opts.launcher}')
94
95 opts.launcher = os.path.relpath(opts.launcher)
96 print(f'Signing "{opts.launcher}" launcher script and saving to '
97 f'"{opts.launcher}.asc"')
98
99 if opts.keys:
100 print(f'Using custom keys to sign: {" ".join(opts.keys)}')
101 else:
102 print('Using official Repo release keys to sign')
103 opts.keys = [util.KEYID_DSA, util.KEYID_RSA, util.KEYID_ECC]
104 util.import_release_key(opts)
105
106 sign(opts)
107 check(opts)
108 postmsg(opts)
109
110 return 0
111
112
113if __name__ == '__main__':
114 sys.exit(main(sys.argv[1:]))