##// END OF EJS Templates
automation: support running against Python 3.9...
Gregory Szorc -
r46285:64a94234 default
parent child Browse files
Show More
@@ -1,548 +1,548 b''
1 # cli.py - Command line interface for automation
1 # cli.py - Command line interface for automation
2 #
2 #
3 # Copyright 2019 Gregory Szorc <gregory.szorc@gmail.com>
3 # Copyright 2019 Gregory Szorc <gregory.szorc@gmail.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 # no-check-code because Python 3 native.
8 # no-check-code because Python 3 native.
9
9
10 import argparse
10 import argparse
11 import concurrent.futures as futures
11 import concurrent.futures as futures
12 import os
12 import os
13 import pathlib
13 import pathlib
14 import time
14 import time
15
15
16 from . import (
16 from . import (
17 aws,
17 aws,
18 HGAutomation,
18 HGAutomation,
19 linux,
19 linux,
20 try_server,
20 try_server,
21 windows,
21 windows,
22 )
22 )
23
23
24
24
25 SOURCE_ROOT = pathlib.Path(
25 SOURCE_ROOT = pathlib.Path(
26 os.path.abspath(__file__)
26 os.path.abspath(__file__)
27 ).parent.parent.parent.parent
27 ).parent.parent.parent.parent
28 DIST_PATH = SOURCE_ROOT / 'dist'
28 DIST_PATH = SOURCE_ROOT / 'dist'
29
29
30
30
31 def bootstrap_linux_dev(
31 def bootstrap_linux_dev(
32 hga: HGAutomation, aws_region, distros=None, parallel=False
32 hga: HGAutomation, aws_region, distros=None, parallel=False
33 ):
33 ):
34 c = hga.aws_connection(aws_region)
34 c = hga.aws_connection(aws_region)
35
35
36 if distros:
36 if distros:
37 distros = distros.split(',')
37 distros = distros.split(',')
38 else:
38 else:
39 distros = sorted(linux.DISTROS)
39 distros = sorted(linux.DISTROS)
40
40
41 # TODO There is a wonky interaction involving KeyboardInterrupt whereby
41 # TODO There is a wonky interaction involving KeyboardInterrupt whereby
42 # the context manager that is supposed to terminate the temporary EC2
42 # the context manager that is supposed to terminate the temporary EC2
43 # instance doesn't run. Until we fix this, make parallel building opt-in
43 # instance doesn't run. Until we fix this, make parallel building opt-in
44 # so we don't orphan instances.
44 # so we don't orphan instances.
45 if parallel:
45 if parallel:
46 fs = []
46 fs = []
47
47
48 with futures.ThreadPoolExecutor(len(distros)) as e:
48 with futures.ThreadPoolExecutor(len(distros)) as e:
49 for distro in distros:
49 for distro in distros:
50 fs.append(e.submit(aws.ensure_linux_dev_ami, c, distro=distro))
50 fs.append(e.submit(aws.ensure_linux_dev_ami, c, distro=distro))
51
51
52 for f in fs:
52 for f in fs:
53 f.result()
53 f.result()
54 else:
54 else:
55 for distro in distros:
55 for distro in distros:
56 aws.ensure_linux_dev_ami(c, distro=distro)
56 aws.ensure_linux_dev_ami(c, distro=distro)
57
57
58
58
59 def bootstrap_windows_dev(hga: HGAutomation, aws_region, base_image_name):
59 def bootstrap_windows_dev(hga: HGAutomation, aws_region, base_image_name):
60 c = hga.aws_connection(aws_region)
60 c = hga.aws_connection(aws_region)
61 image = aws.ensure_windows_dev_ami(c, base_image_name=base_image_name)
61 image = aws.ensure_windows_dev_ami(c, base_image_name=base_image_name)
62 print('Windows development AMI available as %s' % image.id)
62 print('Windows development AMI available as %s' % image.id)
63
63
64
64
65 def build_inno(
65 def build_inno(
66 hga: HGAutomation,
66 hga: HGAutomation,
67 aws_region,
67 aws_region,
68 python_version,
68 python_version,
69 arch,
69 arch,
70 revision,
70 revision,
71 version,
71 version,
72 base_image_name,
72 base_image_name,
73 ):
73 ):
74 c = hga.aws_connection(aws_region)
74 c = hga.aws_connection(aws_region)
75 image = aws.ensure_windows_dev_ami(c, base_image_name=base_image_name)
75 image = aws.ensure_windows_dev_ami(c, base_image_name=base_image_name)
76 DIST_PATH.mkdir(exist_ok=True)
76 DIST_PATH.mkdir(exist_ok=True)
77
77
78 with aws.temporary_windows_dev_instances(c, image, 't3.medium') as insts:
78 with aws.temporary_windows_dev_instances(c, image, 't3.medium') as insts:
79 instance = insts[0]
79 instance = insts[0]
80
80
81 windows.synchronize_hg(SOURCE_ROOT, revision, instance)
81 windows.synchronize_hg(SOURCE_ROOT, revision, instance)
82
82
83 for py_version in python_version:
83 for py_version in python_version:
84 for a in arch:
84 for a in arch:
85 windows.build_inno_installer(
85 windows.build_inno_installer(
86 instance.winrm_client,
86 instance.winrm_client,
87 py_version,
87 py_version,
88 a,
88 a,
89 DIST_PATH,
89 DIST_PATH,
90 version=version,
90 version=version,
91 )
91 )
92
92
93
93
94 def build_wix(
94 def build_wix(
95 hga: HGAutomation,
95 hga: HGAutomation,
96 aws_region,
96 aws_region,
97 python_version,
97 python_version,
98 arch,
98 arch,
99 revision,
99 revision,
100 version,
100 version,
101 base_image_name,
101 base_image_name,
102 ):
102 ):
103 c = hga.aws_connection(aws_region)
103 c = hga.aws_connection(aws_region)
104 image = aws.ensure_windows_dev_ami(c, base_image_name=base_image_name)
104 image = aws.ensure_windows_dev_ami(c, base_image_name=base_image_name)
105 DIST_PATH.mkdir(exist_ok=True)
105 DIST_PATH.mkdir(exist_ok=True)
106
106
107 with aws.temporary_windows_dev_instances(c, image, 't3.medium') as insts:
107 with aws.temporary_windows_dev_instances(c, image, 't3.medium') as insts:
108 instance = insts[0]
108 instance = insts[0]
109
109
110 windows.synchronize_hg(SOURCE_ROOT, revision, instance)
110 windows.synchronize_hg(SOURCE_ROOT, revision, instance)
111
111
112 for py_version in python_version:
112 for py_version in python_version:
113 for a in arch:
113 for a in arch:
114 windows.build_wix_installer(
114 windows.build_wix_installer(
115 instance.winrm_client,
115 instance.winrm_client,
116 py_version,
116 py_version,
117 a,
117 a,
118 DIST_PATH,
118 DIST_PATH,
119 version=version,
119 version=version,
120 )
120 )
121
121
122
122
123 def build_windows_wheel(
123 def build_windows_wheel(
124 hga: HGAutomation,
124 hga: HGAutomation,
125 aws_region,
125 aws_region,
126 python_version,
126 python_version,
127 arch,
127 arch,
128 revision,
128 revision,
129 base_image_name,
129 base_image_name,
130 ):
130 ):
131 c = hga.aws_connection(aws_region)
131 c = hga.aws_connection(aws_region)
132 image = aws.ensure_windows_dev_ami(c, base_image_name=base_image_name)
132 image = aws.ensure_windows_dev_ami(c, base_image_name=base_image_name)
133 DIST_PATH.mkdir(exist_ok=True)
133 DIST_PATH.mkdir(exist_ok=True)
134
134
135 with aws.temporary_windows_dev_instances(c, image, 't3.medium') as insts:
135 with aws.temporary_windows_dev_instances(c, image, 't3.medium') as insts:
136 instance = insts[0]
136 instance = insts[0]
137
137
138 windows.synchronize_hg(SOURCE_ROOT, revision, instance)
138 windows.synchronize_hg(SOURCE_ROOT, revision, instance)
139
139
140 for py_version in python_version:
140 for py_version in python_version:
141 for a in arch:
141 for a in arch:
142 windows.build_wheel(
142 windows.build_wheel(
143 instance.winrm_client, py_version, a, DIST_PATH
143 instance.winrm_client, py_version, a, DIST_PATH
144 )
144 )
145
145
146
146
147 def build_all_windows_packages(
147 def build_all_windows_packages(
148 hga: HGAutomation, aws_region, revision, version, base_image_name
148 hga: HGAutomation, aws_region, revision, version, base_image_name
149 ):
149 ):
150 c = hga.aws_connection(aws_region)
150 c = hga.aws_connection(aws_region)
151 image = aws.ensure_windows_dev_ami(c, base_image_name=base_image_name)
151 image = aws.ensure_windows_dev_ami(c, base_image_name=base_image_name)
152 DIST_PATH.mkdir(exist_ok=True)
152 DIST_PATH.mkdir(exist_ok=True)
153
153
154 with aws.temporary_windows_dev_instances(c, image, 't3.medium') as insts:
154 with aws.temporary_windows_dev_instances(c, image, 't3.medium') as insts:
155 instance = insts[0]
155 instance = insts[0]
156
156
157 winrm_client = instance.winrm_client
157 winrm_client = instance.winrm_client
158
158
159 windows.synchronize_hg(SOURCE_ROOT, revision, instance)
159 windows.synchronize_hg(SOURCE_ROOT, revision, instance)
160
160
161 for py_version in ("2.7", "3.7", "3.8"):
161 for py_version in ("2.7", "3.7", "3.8", "3.9"):
162 for arch in ("x86", "x64"):
162 for arch in ("x86", "x64"):
163 windows.purge_hg(winrm_client)
163 windows.purge_hg(winrm_client)
164 windows.build_wheel(
164 windows.build_wheel(
165 winrm_client,
165 winrm_client,
166 python_version=py_version,
166 python_version=py_version,
167 arch=arch,
167 arch=arch,
168 dest_path=DIST_PATH,
168 dest_path=DIST_PATH,
169 )
169 )
170
170
171 for py_version in (2, 3):
171 for py_version in (2, 3):
172 for arch in ('x86', 'x64'):
172 for arch in ('x86', 'x64'):
173 windows.purge_hg(winrm_client)
173 windows.purge_hg(winrm_client)
174 windows.build_inno_installer(
174 windows.build_inno_installer(
175 winrm_client, py_version, arch, DIST_PATH, version=version
175 winrm_client, py_version, arch, DIST_PATH, version=version
176 )
176 )
177 windows.build_wix_installer(
177 windows.build_wix_installer(
178 winrm_client, py_version, arch, DIST_PATH, version=version
178 winrm_client, py_version, arch, DIST_PATH, version=version
179 )
179 )
180
180
181
181
182 def terminate_ec2_instances(hga: HGAutomation, aws_region):
182 def terminate_ec2_instances(hga: HGAutomation, aws_region):
183 c = hga.aws_connection(aws_region, ensure_ec2_state=False)
183 c = hga.aws_connection(aws_region, ensure_ec2_state=False)
184 aws.terminate_ec2_instances(c.ec2resource)
184 aws.terminate_ec2_instances(c.ec2resource)
185
185
186
186
187 def purge_ec2_resources(hga: HGAutomation, aws_region):
187 def purge_ec2_resources(hga: HGAutomation, aws_region):
188 c = hga.aws_connection(aws_region, ensure_ec2_state=False)
188 c = hga.aws_connection(aws_region, ensure_ec2_state=False)
189 aws.remove_resources(c)
189 aws.remove_resources(c)
190
190
191
191
192 def run_tests_linux(
192 def run_tests_linux(
193 hga: HGAutomation,
193 hga: HGAutomation,
194 aws_region,
194 aws_region,
195 instance_type,
195 instance_type,
196 python_version,
196 python_version,
197 test_flags,
197 test_flags,
198 distro,
198 distro,
199 filesystem,
199 filesystem,
200 ):
200 ):
201 c = hga.aws_connection(aws_region)
201 c = hga.aws_connection(aws_region)
202 image = aws.ensure_linux_dev_ami(c, distro=distro)
202 image = aws.ensure_linux_dev_ami(c, distro=distro)
203
203
204 t_start = time.time()
204 t_start = time.time()
205
205
206 ensure_extra_volume = filesystem not in ('default', 'tmpfs')
206 ensure_extra_volume = filesystem not in ('default', 'tmpfs')
207
207
208 with aws.temporary_linux_dev_instances(
208 with aws.temporary_linux_dev_instances(
209 c, image, instance_type, ensure_extra_volume=ensure_extra_volume
209 c, image, instance_type, ensure_extra_volume=ensure_extra_volume
210 ) as insts:
210 ) as insts:
211
211
212 instance = insts[0]
212 instance = insts[0]
213
213
214 linux.prepare_exec_environment(
214 linux.prepare_exec_environment(
215 instance.ssh_client, filesystem=filesystem
215 instance.ssh_client, filesystem=filesystem
216 )
216 )
217 linux.synchronize_hg(SOURCE_ROOT, instance, '.')
217 linux.synchronize_hg(SOURCE_ROOT, instance, '.')
218 t_prepared = time.time()
218 t_prepared = time.time()
219 linux.run_tests(instance.ssh_client, python_version, test_flags)
219 linux.run_tests(instance.ssh_client, python_version, test_flags)
220 t_done = time.time()
220 t_done = time.time()
221
221
222 t_setup = t_prepared - t_start
222 t_setup = t_prepared - t_start
223 t_all = t_done - t_start
223 t_all = t_done - t_start
224
224
225 print(
225 print(
226 'total time: %.1fs; setup: %.1fs; tests: %.1fs; setup overhead: %.1f%%'
226 'total time: %.1fs; setup: %.1fs; tests: %.1fs; setup overhead: %.1f%%'
227 % (t_all, t_setup, t_done - t_prepared, t_setup / t_all * 100.0)
227 % (t_all, t_setup, t_done - t_prepared, t_setup / t_all * 100.0)
228 )
228 )
229
229
230
230
231 def run_tests_windows(
231 def run_tests_windows(
232 hga: HGAutomation,
232 hga: HGAutomation,
233 aws_region,
233 aws_region,
234 instance_type,
234 instance_type,
235 python_version,
235 python_version,
236 arch,
236 arch,
237 test_flags,
237 test_flags,
238 base_image_name,
238 base_image_name,
239 ):
239 ):
240 c = hga.aws_connection(aws_region)
240 c = hga.aws_connection(aws_region)
241 image = aws.ensure_windows_dev_ami(c, base_image_name=base_image_name)
241 image = aws.ensure_windows_dev_ami(c, base_image_name=base_image_name)
242
242
243 with aws.temporary_windows_dev_instances(
243 with aws.temporary_windows_dev_instances(
244 c, image, instance_type, disable_antivirus=True
244 c, image, instance_type, disable_antivirus=True
245 ) as insts:
245 ) as insts:
246 instance = insts[0]
246 instance = insts[0]
247
247
248 windows.synchronize_hg(SOURCE_ROOT, '.', instance)
248 windows.synchronize_hg(SOURCE_ROOT, '.', instance)
249 windows.run_tests(
249 windows.run_tests(
250 instance.winrm_client, python_version, arch, test_flags
250 instance.winrm_client, python_version, arch, test_flags
251 )
251 )
252
252
253
253
254 def publish_windows_artifacts(
254 def publish_windows_artifacts(
255 hg: HGAutomation,
255 hg: HGAutomation,
256 aws_region,
256 aws_region,
257 version: str,
257 version: str,
258 pypi: bool,
258 pypi: bool,
259 mercurial_scm_org: bool,
259 mercurial_scm_org: bool,
260 ssh_username: str,
260 ssh_username: str,
261 ):
261 ):
262 windows.publish_artifacts(
262 windows.publish_artifacts(
263 DIST_PATH,
263 DIST_PATH,
264 version,
264 version,
265 pypi=pypi,
265 pypi=pypi,
266 mercurial_scm_org=mercurial_scm_org,
266 mercurial_scm_org=mercurial_scm_org,
267 ssh_username=ssh_username,
267 ssh_username=ssh_username,
268 )
268 )
269
269
270
270
271 def run_try(hga: HGAutomation, aws_region: str, rev: str):
271 def run_try(hga: HGAutomation, aws_region: str, rev: str):
272 c = hga.aws_connection(aws_region, ensure_ec2_state=False)
272 c = hga.aws_connection(aws_region, ensure_ec2_state=False)
273 try_server.trigger_try(c, rev=rev)
273 try_server.trigger_try(c, rev=rev)
274
274
275
275
276 def get_parser():
276 def get_parser():
277 parser = argparse.ArgumentParser()
277 parser = argparse.ArgumentParser()
278
278
279 parser.add_argument(
279 parser.add_argument(
280 '--state-path',
280 '--state-path',
281 default='~/.hgautomation',
281 default='~/.hgautomation',
282 help='Path for local state files',
282 help='Path for local state files',
283 )
283 )
284 parser.add_argument(
284 parser.add_argument(
285 '--aws-region', help='AWS region to use', default='us-west-2',
285 '--aws-region', help='AWS region to use', default='us-west-2',
286 )
286 )
287
287
288 subparsers = parser.add_subparsers()
288 subparsers = parser.add_subparsers()
289
289
290 sp = subparsers.add_parser(
290 sp = subparsers.add_parser(
291 'bootstrap-linux-dev', help='Bootstrap Linux development environments',
291 'bootstrap-linux-dev', help='Bootstrap Linux development environments',
292 )
292 )
293 sp.add_argument(
293 sp.add_argument(
294 '--distros', help='Comma delimited list of distros to bootstrap',
294 '--distros', help='Comma delimited list of distros to bootstrap',
295 )
295 )
296 sp.add_argument(
296 sp.add_argument(
297 '--parallel',
297 '--parallel',
298 action='store_true',
298 action='store_true',
299 help='Generate AMIs in parallel (not CTRL-c safe)',
299 help='Generate AMIs in parallel (not CTRL-c safe)',
300 )
300 )
301 sp.set_defaults(func=bootstrap_linux_dev)
301 sp.set_defaults(func=bootstrap_linux_dev)
302
302
303 sp = subparsers.add_parser(
303 sp = subparsers.add_parser(
304 'bootstrap-windows-dev',
304 'bootstrap-windows-dev',
305 help='Bootstrap the Windows development environment',
305 help='Bootstrap the Windows development environment',
306 )
306 )
307 sp.add_argument(
307 sp.add_argument(
308 '--base-image-name',
308 '--base-image-name',
309 help='AMI name of base image',
309 help='AMI name of base image',
310 default=aws.WINDOWS_BASE_IMAGE_NAME,
310 default=aws.WINDOWS_BASE_IMAGE_NAME,
311 )
311 )
312 sp.set_defaults(func=bootstrap_windows_dev)
312 sp.set_defaults(func=bootstrap_windows_dev)
313
313
314 sp = subparsers.add_parser(
314 sp = subparsers.add_parser(
315 'build-all-windows-packages', help='Build all Windows packages',
315 'build-all-windows-packages', help='Build all Windows packages',
316 )
316 )
317 sp.add_argument(
317 sp.add_argument(
318 '--revision', help='Mercurial revision to build', default='.',
318 '--revision', help='Mercurial revision to build', default='.',
319 )
319 )
320 sp.add_argument(
320 sp.add_argument(
321 '--version', help='Mercurial version string to use',
321 '--version', help='Mercurial version string to use',
322 )
322 )
323 sp.add_argument(
323 sp.add_argument(
324 '--base-image-name',
324 '--base-image-name',
325 help='AMI name of base image',
325 help='AMI name of base image',
326 default=aws.WINDOWS_BASE_IMAGE_NAME,
326 default=aws.WINDOWS_BASE_IMAGE_NAME,
327 )
327 )
328 sp.set_defaults(func=build_all_windows_packages)
328 sp.set_defaults(func=build_all_windows_packages)
329
329
330 sp = subparsers.add_parser(
330 sp = subparsers.add_parser(
331 'build-inno', help='Build Inno Setup installer(s)',
331 'build-inno', help='Build Inno Setup installer(s)',
332 )
332 )
333 sp.add_argument(
333 sp.add_argument(
334 '--python-version',
334 '--python-version',
335 help='Which version of Python to target',
335 help='Which version of Python to target',
336 choices={2, 3},
336 choices={2, 3},
337 type=int,
337 type=int,
338 nargs='*',
338 nargs='*',
339 default=[3],
339 default=[3],
340 )
340 )
341 sp.add_argument(
341 sp.add_argument(
342 '--arch',
342 '--arch',
343 help='Architecture to build for',
343 help='Architecture to build for',
344 choices={'x86', 'x64'},
344 choices={'x86', 'x64'},
345 nargs='*',
345 nargs='*',
346 default=['x64'],
346 default=['x64'],
347 )
347 )
348 sp.add_argument(
348 sp.add_argument(
349 '--revision', help='Mercurial revision to build', default='.',
349 '--revision', help='Mercurial revision to build', default='.',
350 )
350 )
351 sp.add_argument(
351 sp.add_argument(
352 '--version', help='Mercurial version string to use in installer',
352 '--version', help='Mercurial version string to use in installer',
353 )
353 )
354 sp.add_argument(
354 sp.add_argument(
355 '--base-image-name',
355 '--base-image-name',
356 help='AMI name of base image',
356 help='AMI name of base image',
357 default=aws.WINDOWS_BASE_IMAGE_NAME,
357 default=aws.WINDOWS_BASE_IMAGE_NAME,
358 )
358 )
359 sp.set_defaults(func=build_inno)
359 sp.set_defaults(func=build_inno)
360
360
361 sp = subparsers.add_parser(
361 sp = subparsers.add_parser(
362 'build-windows-wheel', help='Build Windows wheel(s)',
362 'build-windows-wheel', help='Build Windows wheel(s)',
363 )
363 )
364 sp.add_argument(
364 sp.add_argument(
365 '--python-version',
365 '--python-version',
366 help='Python version to build for',
366 help='Python version to build for',
367 choices={'2.7', '3.7', '3.8'},
367 choices={'2.7', '3.7', '3.8', '3.9'},
368 nargs='*',
368 nargs='*',
369 default=['3.8'],
369 default=['3.8'],
370 )
370 )
371 sp.add_argument(
371 sp.add_argument(
372 '--arch',
372 '--arch',
373 help='Architecture to build for',
373 help='Architecture to build for',
374 choices={'x86', 'x64'},
374 choices={'x86', 'x64'},
375 nargs='*',
375 nargs='*',
376 default=['x64'],
376 default=['x64'],
377 )
377 )
378 sp.add_argument(
378 sp.add_argument(
379 '--revision', help='Mercurial revision to build', default='.',
379 '--revision', help='Mercurial revision to build', default='.',
380 )
380 )
381 sp.add_argument(
381 sp.add_argument(
382 '--base-image-name',
382 '--base-image-name',
383 help='AMI name of base image',
383 help='AMI name of base image',
384 default=aws.WINDOWS_BASE_IMAGE_NAME,
384 default=aws.WINDOWS_BASE_IMAGE_NAME,
385 )
385 )
386 sp.set_defaults(func=build_windows_wheel)
386 sp.set_defaults(func=build_windows_wheel)
387
387
388 sp = subparsers.add_parser('build-wix', help='Build WiX installer(s)')
388 sp = subparsers.add_parser('build-wix', help='Build WiX installer(s)')
389 sp.add_argument(
389 sp.add_argument(
390 '--python-version',
390 '--python-version',
391 help='Which version of Python to target',
391 help='Which version of Python to target',
392 choices={2, 3},
392 choices={2, 3},
393 type=int,
393 type=int,
394 nargs='*',
394 nargs='*',
395 default=[3],
395 default=[3],
396 )
396 )
397 sp.add_argument(
397 sp.add_argument(
398 '--arch',
398 '--arch',
399 help='Architecture to build for',
399 help='Architecture to build for',
400 choices={'x86', 'x64'},
400 choices={'x86', 'x64'},
401 nargs='*',
401 nargs='*',
402 default=['x64'],
402 default=['x64'],
403 )
403 )
404 sp.add_argument(
404 sp.add_argument(
405 '--revision', help='Mercurial revision to build', default='.',
405 '--revision', help='Mercurial revision to build', default='.',
406 )
406 )
407 sp.add_argument(
407 sp.add_argument(
408 '--version', help='Mercurial version string to use in installer',
408 '--version', help='Mercurial version string to use in installer',
409 )
409 )
410 sp.add_argument(
410 sp.add_argument(
411 '--base-image-name',
411 '--base-image-name',
412 help='AMI name of base image',
412 help='AMI name of base image',
413 default=aws.WINDOWS_BASE_IMAGE_NAME,
413 default=aws.WINDOWS_BASE_IMAGE_NAME,
414 )
414 )
415 sp.set_defaults(func=build_wix)
415 sp.set_defaults(func=build_wix)
416
416
417 sp = subparsers.add_parser(
417 sp = subparsers.add_parser(
418 'terminate-ec2-instances',
418 'terminate-ec2-instances',
419 help='Terminate all active EC2 instances managed by us',
419 help='Terminate all active EC2 instances managed by us',
420 )
420 )
421 sp.set_defaults(func=terminate_ec2_instances)
421 sp.set_defaults(func=terminate_ec2_instances)
422
422
423 sp = subparsers.add_parser(
423 sp = subparsers.add_parser(
424 'purge-ec2-resources', help='Purge all EC2 resources managed by us',
424 'purge-ec2-resources', help='Purge all EC2 resources managed by us',
425 )
425 )
426 sp.set_defaults(func=purge_ec2_resources)
426 sp.set_defaults(func=purge_ec2_resources)
427
427
428 sp = subparsers.add_parser('run-tests-linux', help='Run tests on Linux',)
428 sp = subparsers.add_parser('run-tests-linux', help='Run tests on Linux',)
429 sp.add_argument(
429 sp.add_argument(
430 '--distro',
430 '--distro',
431 help='Linux distribution to run tests on',
431 help='Linux distribution to run tests on',
432 choices=linux.DISTROS,
432 choices=linux.DISTROS,
433 default='debian10',
433 default='debian10',
434 )
434 )
435 sp.add_argument(
435 sp.add_argument(
436 '--filesystem',
436 '--filesystem',
437 help='Filesystem type to use',
437 help='Filesystem type to use',
438 choices={'btrfs', 'default', 'ext3', 'ext4', 'jfs', 'tmpfs', 'xfs'},
438 choices={'btrfs', 'default', 'ext3', 'ext4', 'jfs', 'tmpfs', 'xfs'},
439 default='default',
439 default='default',
440 )
440 )
441 sp.add_argument(
441 sp.add_argument(
442 '--instance-type',
442 '--instance-type',
443 help='EC2 instance type to use',
443 help='EC2 instance type to use',
444 default='c5.9xlarge',
444 default='c5.9xlarge',
445 )
445 )
446 sp.add_argument(
446 sp.add_argument(
447 '--python-version',
447 '--python-version',
448 help='Python version to use',
448 help='Python version to use',
449 choices={
449 choices={
450 'system2',
450 'system2',
451 'system3',
451 'system3',
452 '2.7',
452 '2.7',
453 '3.5',
453 '3.5',
454 '3.6',
454 '3.6',
455 '3.7',
455 '3.7',
456 '3.8',
456 '3.8',
457 'pypy',
457 'pypy',
458 'pypy3.5',
458 'pypy3.5',
459 'pypy3.6',
459 'pypy3.6',
460 },
460 },
461 default='system2',
461 default='system2',
462 )
462 )
463 sp.add_argument(
463 sp.add_argument(
464 'test_flags',
464 'test_flags',
465 help='Extra command line flags to pass to run-tests.py',
465 help='Extra command line flags to pass to run-tests.py',
466 nargs='*',
466 nargs='*',
467 )
467 )
468 sp.set_defaults(func=run_tests_linux)
468 sp.set_defaults(func=run_tests_linux)
469
469
470 sp = subparsers.add_parser(
470 sp = subparsers.add_parser(
471 'run-tests-windows', help='Run tests on Windows',
471 'run-tests-windows', help='Run tests on Windows',
472 )
472 )
473 sp.add_argument(
473 sp.add_argument(
474 '--instance-type', help='EC2 instance type to use', default='t3.medium',
474 '--instance-type', help='EC2 instance type to use', default='t3.medium',
475 )
475 )
476 sp.add_argument(
476 sp.add_argument(
477 '--python-version',
477 '--python-version',
478 help='Python version to use',
478 help='Python version to use',
479 choices={'2.7', '3.5', '3.6', '3.7', '3.8'},
479 choices={'2.7', '3.5', '3.6', '3.7', '3.8', '3.9'},
480 default='2.7',
480 default='2.7',
481 )
481 )
482 sp.add_argument(
482 sp.add_argument(
483 '--arch',
483 '--arch',
484 help='Architecture to test',
484 help='Architecture to test',
485 choices={'x86', 'x64'},
485 choices={'x86', 'x64'},
486 default='x64',
486 default='x64',
487 )
487 )
488 sp.add_argument(
488 sp.add_argument(
489 '--test-flags', help='Extra command line flags to pass to run-tests.py',
489 '--test-flags', help='Extra command line flags to pass to run-tests.py',
490 )
490 )
491 sp.add_argument(
491 sp.add_argument(
492 '--base-image-name',
492 '--base-image-name',
493 help='AMI name of base image',
493 help='AMI name of base image',
494 default=aws.WINDOWS_BASE_IMAGE_NAME,
494 default=aws.WINDOWS_BASE_IMAGE_NAME,
495 )
495 )
496 sp.set_defaults(func=run_tests_windows)
496 sp.set_defaults(func=run_tests_windows)
497
497
498 sp = subparsers.add_parser(
498 sp = subparsers.add_parser(
499 'publish-windows-artifacts',
499 'publish-windows-artifacts',
500 help='Publish built Windows artifacts (wheels, installers, etc)',
500 help='Publish built Windows artifacts (wheels, installers, etc)',
501 )
501 )
502 sp.add_argument(
502 sp.add_argument(
503 '--no-pypi',
503 '--no-pypi',
504 dest='pypi',
504 dest='pypi',
505 action='store_false',
505 action='store_false',
506 default=True,
506 default=True,
507 help='Skip uploading to PyPI',
507 help='Skip uploading to PyPI',
508 )
508 )
509 sp.add_argument(
509 sp.add_argument(
510 '--no-mercurial-scm-org',
510 '--no-mercurial-scm-org',
511 dest='mercurial_scm_org',
511 dest='mercurial_scm_org',
512 action='store_false',
512 action='store_false',
513 default=True,
513 default=True,
514 help='Skip uploading to www.mercurial-scm.org',
514 help='Skip uploading to www.mercurial-scm.org',
515 )
515 )
516 sp.add_argument(
516 sp.add_argument(
517 '--ssh-username', help='SSH username for mercurial-scm.org',
517 '--ssh-username', help='SSH username for mercurial-scm.org',
518 )
518 )
519 sp.add_argument(
519 sp.add_argument(
520 'version', help='Mercurial version string to locate local packages',
520 'version', help='Mercurial version string to locate local packages',
521 )
521 )
522 sp.set_defaults(func=publish_windows_artifacts)
522 sp.set_defaults(func=publish_windows_artifacts)
523
523
524 sp = subparsers.add_parser(
524 sp = subparsers.add_parser(
525 'try', help='Run CI automation against a custom changeset'
525 'try', help='Run CI automation against a custom changeset'
526 )
526 )
527 sp.add_argument('-r', '--rev', default='.', help='Revision to run CI on')
527 sp.add_argument('-r', '--rev', default='.', help='Revision to run CI on')
528 sp.set_defaults(func=run_try)
528 sp.set_defaults(func=run_try)
529
529
530 return parser
530 return parser
531
531
532
532
533 def main():
533 def main():
534 parser = get_parser()
534 parser = get_parser()
535 args = parser.parse_args()
535 args = parser.parse_args()
536
536
537 local_state_path = pathlib.Path(os.path.expanduser(args.state_path))
537 local_state_path = pathlib.Path(os.path.expanduser(args.state_path))
538 automation = HGAutomation(local_state_path)
538 automation = HGAutomation(local_state_path)
539
539
540 if not hasattr(args, 'func'):
540 if not hasattr(args, 'func'):
541 parser.print_help()
541 parser.print_help()
542 return
542 return
543
543
544 kwargs = dict(vars(args))
544 kwargs = dict(vars(args))
545 del kwargs['func']
545 del kwargs['func']
546 del kwargs['state_path']
546 del kwargs['state_path']
547
547
548 args.func(automation, **kwargs)
548 args.func(automation, **kwargs)
General Comments 0
You need to be logged in to leave comments. Login now