blob: 1bc3b905ef7f2025bf905bc9d1086240035d3769 [file] [log] [blame]
Adrià Vilanova Martínezac4a6442022-05-15 19:05:13 +02001#!/usr/bin/env python3
Adrià Vilanova Martínezf19ea432024-01-23 20:20:52 +01002# Copyright 2022 The Chromium Authors
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
Adrià Vilanova Martínezac4a6442022-05-15 19:05:13 +02005
6"""Script to launch the Monorail release tarball builder.
7
8It can be used to build a tarball with Monorail code based on a release branch
9(i.e. `refs/releases/monorail/...`). It triggers a go/monorail-release-tarballs
10build that uploads the release tarball and triggers its deployment to
11monorail-dev, after which it can be promoted to monorail-prod.
12
13See go/monorail-deploy for more details.
14"""
15
16import argparse
17import json
18import subprocess
19import sys
Adrià Vilanova Martínezde942802022-07-15 14:06:55 +020020from six.moves.urllib import error
21from six.moves.urllib import request
Adrià Vilanova Martínezac4a6442022-05-15 19:05:13 +020022
23
24INFRA_GIT = 'https://chromium.googlesource.com/infra/infra'
25TARBALL_BUILDER = 'infra-internal/monorail-release/monorail-release-tarballs'
26
27
28def resolve_commit(ref):
29 """Queries gitiles for a commit hash matching the given infra.git ref.
30
31 Args:
32 ref: a `refs/...` ref to resolve into a commit.
33
34 Returns:
35 None if there's no such ref, a gitiles commit URL otherwise.
36 """
37 try:
Adrià Vilanova Martínezde942802022-07-15 14:06:55 +020038 resp = request.urlopen('%s/+/%s?format=JSON' % (INFRA_GIT, ref))
39 except error.HTTPError as exc:
Adrià Vilanova Martínezac4a6442022-05-15 19:05:13 +020040 if exc.code == 404:
41 return None
42 raise
43
44 # Gitiles JSON responses start with XSS-protection header.
45 blob = resp.read()
46 if blob.startswith(b')]}\''):
47 blob = blob[4:]
48
49 commit = json.loads(blob)['commit']
50 return '%s/+/%s' % (INFRA_GIT, commit)
51
52
53def ensure_logged_in():
54 """Ensures `bb` tool is in PATH and the caller is logged in there.
55
56 Returns:
57 True if logged in, False if not and we should abort.
58 """
59 try:
60 proc = subprocess.run(['bb', 'auth-info'], capture_output=True)
61 except OSError:
62 print(
63 'Could not find `bb` tool in PATH. It comes with depot_tools. '
64 'Make sure depot_tools is in PATH and up-to-date, then try again.')
65 return False
66
67 if proc.returncode == 0:
68 return True # already logged in
69
70 # Launch interactive login process.
71 proc = subprocess.run(['bb', 'auth-login'])
72 if proc.returncode != 0:
73 print('Failed to login')
74 return False
75 return True
76
77
78def submit_build(ref, commit):
79 """Submits a Monorail tarball builder build via `bb` tool.
80
81 Args:
82 ref: a `refs/...` ref with the code to build.
83 commit: a gitiles commit matching this ref.
84
85 Returns:
86 None if failed, a URL to the pending build otherwise.
87 """
88 cmd = ['bb', 'add', '-json', '-ref', ref, '-commit', commit, TARBALL_BUILDER]
89 proc = subprocess.run(cmd, capture_output=True)
90 if proc.returncode != 0:
91 print(
92 'Failed to schedule the build:\n%s'
93 % proc.stderr.decode('utf-8').strip())
94 return None
95 build_id = json.loads(proc.stdout)['id']
96 return 'https://ci.chromium.org/b/%s' % build_id
97
98
99def main():
100 parser = argparse.ArgumentParser(
101 description='Submits a request to build Monorail tarball for LUCI CD.')
102 parser.add_argument(
103 'branch', type=str,
104 help='a branch to build from: refs/releases/monorail/<num> or just <num>')
105 parser.add_argument(
106 '--silent', action='store_true',
107 help='disable interactive prompts')
108 args = parser.parse_args()
109
110 ref = args.branch
111 if not ref.startswith('refs/'):
112 ref = 'refs/releases/monorail/' + ref
113
114 # `bb add` call wants a concrete git commit SHA1 as input.
115 commit = resolve_commit(ref)
116 if not commit:
117 print('No such release branch: %s' % ref)
118 return 1
119
120 # Give a chance to confirm this is the commit we want to build.
121 if not args.silent:
122 print(
123 'Will submit a request to build a Monorail code tarball from %s:\n'
124 ' %s\n\n'
125 'You may be asked to sign in with your google.com account if it is '
126 'the first time you are using this script.\n'
127 % (ref, commit)
128 )
129 if input('Proceed [Y/n]? ') not in ('', 'Y', 'y'):
130 return 0
131
132 # Submit the build via `bb` tool.
133 if not args.silent and not ensure_logged_in():
134 return 1
135 build_url = submit_build(ref, commit)
136 if not build_url:
137 return 1
138
139 print(
140 '\nScheduled the build: %s\n'
141 '\n'
142 'When it completes it will trigger deployment of this release to '
143 'monorail-dev. You can then promote it to production using the same '
144 'procedure as with regular releases built from `main` branch.\n'
145 '\n'
146 'Note that if the produced release tarball is 100%% identical to any '
147 'previously built tarball (e.g. there were no cherry-picks into the '
148 'release branch since it was cut from `main`), an existing tarball and '
149 'its version name will be reused.'
150 % build_url
151 )
152 return 0
153
154
155if __name__ == '__main__':
156 sys.exit(main())