|
1 # cli.py - Command line interface for automation |
|
2 # |
|
3 # Copyright 2019 Gregory Szorc <gregory.szorc@gmail.com> |
|
4 # |
|
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. |
|
7 |
|
8 # no-check-code because Python 3 native. |
|
9 |
|
10 import argparse |
|
11 import os |
|
12 import pathlib |
|
13 |
|
14 from . import ( |
|
15 aws, |
|
16 HGAutomation, |
|
17 windows, |
|
18 ) |
|
19 |
|
20 |
|
21 SOURCE_ROOT = pathlib.Path(os.path.abspath(__file__)).parent.parent.parent.parent |
|
22 DIST_PATH = SOURCE_ROOT / 'dist' |
|
23 |
|
24 |
|
25 def bootstrap_windows_dev(hga: HGAutomation, aws_region): |
|
26 c = hga.aws_connection(aws_region) |
|
27 image = aws.ensure_windows_dev_ami(c) |
|
28 print('Windows development AMI available as %s' % image.id) |
|
29 |
|
30 |
|
31 def build_inno(hga: HGAutomation, aws_region, arch, revision, version): |
|
32 c = hga.aws_connection(aws_region) |
|
33 image = aws.ensure_windows_dev_ami(c) |
|
34 DIST_PATH.mkdir(exist_ok=True) |
|
35 |
|
36 with aws.temporary_windows_dev_instances(c, image, 't3.medium') as insts: |
|
37 instance = insts[0] |
|
38 |
|
39 windows.synchronize_hg(SOURCE_ROOT, revision, instance) |
|
40 |
|
41 for a in arch: |
|
42 windows.build_inno_installer(instance.winrm_client, a, |
|
43 DIST_PATH, |
|
44 version=version) |
|
45 |
|
46 |
|
47 def build_wix(hga: HGAutomation, aws_region, arch, revision, version): |
|
48 c = hga.aws_connection(aws_region) |
|
49 image = aws.ensure_windows_dev_ami(c) |
|
50 DIST_PATH.mkdir(exist_ok=True) |
|
51 |
|
52 with aws.temporary_windows_dev_instances(c, image, 't3.medium') as insts: |
|
53 instance = insts[0] |
|
54 |
|
55 windows.synchronize_hg(SOURCE_ROOT, revision, instance) |
|
56 |
|
57 for a in arch: |
|
58 windows.build_wix_installer(instance.winrm_client, a, |
|
59 DIST_PATH, version=version) |
|
60 |
|
61 |
|
62 def build_windows_wheel(hga: HGAutomation, aws_region, arch, revision): |
|
63 c = hga.aws_connection(aws_region) |
|
64 image = aws.ensure_windows_dev_ami(c) |
|
65 DIST_PATH.mkdir(exist_ok=True) |
|
66 |
|
67 with aws.temporary_windows_dev_instances(c, image, 't3.medium') as insts: |
|
68 instance = insts[0] |
|
69 |
|
70 windows.synchronize_hg(SOURCE_ROOT, revision, instance) |
|
71 |
|
72 for a in arch: |
|
73 windows.build_wheel(instance.winrm_client, a, DIST_PATH) |
|
74 |
|
75 |
|
76 def build_all_windows_packages(hga: HGAutomation, aws_region, revision): |
|
77 c = hga.aws_connection(aws_region) |
|
78 image = aws.ensure_windows_dev_ami(c) |
|
79 DIST_PATH.mkdir(exist_ok=True) |
|
80 |
|
81 with aws.temporary_windows_dev_instances(c, image, 't3.medium') as insts: |
|
82 instance = insts[0] |
|
83 |
|
84 winrm_client = instance.winrm_client |
|
85 |
|
86 windows.synchronize_hg(SOURCE_ROOT, revision, instance) |
|
87 |
|
88 for arch in ('x86', 'x64'): |
|
89 windows.purge_hg(winrm_client) |
|
90 windows.build_wheel(winrm_client, arch, DIST_PATH) |
|
91 windows.purge_hg(winrm_client) |
|
92 windows.build_inno_installer(winrm_client, arch, DIST_PATH) |
|
93 windows.purge_hg(winrm_client) |
|
94 windows.build_wix_installer(winrm_client, arch, DIST_PATH) |
|
95 |
|
96 |
|
97 def terminate_ec2_instances(hga: HGAutomation, aws_region): |
|
98 c = hga.aws_connection(aws_region) |
|
99 aws.terminate_ec2_instances(c.ec2resource) |
|
100 |
|
101 |
|
102 def purge_ec2_resources(hga: HGAutomation, aws_region): |
|
103 c = hga.aws_connection(aws_region) |
|
104 aws.remove_resources(c) |
|
105 |
|
106 |
|
107 def run_tests_windows(hga: HGAutomation, aws_region, instance_type, |
|
108 python_version, arch, test_flags): |
|
109 c = hga.aws_connection(aws_region) |
|
110 image = aws.ensure_windows_dev_ami(c) |
|
111 |
|
112 with aws.temporary_windows_dev_instances(c, image, instance_type, |
|
113 disable_antivirus=True) as insts: |
|
114 instance = insts[0] |
|
115 |
|
116 windows.synchronize_hg(SOURCE_ROOT, '.', instance) |
|
117 windows.run_tests(instance.winrm_client, python_version, arch, |
|
118 test_flags) |
|
119 |
|
120 |
|
121 def get_parser(): |
|
122 parser = argparse.ArgumentParser() |
|
123 |
|
124 parser.add_argument( |
|
125 '--state-path', |
|
126 default='~/.hgautomation', |
|
127 help='Path for local state files', |
|
128 ) |
|
129 parser.add_argument( |
|
130 '--aws-region', |
|
131 help='AWS region to use', |
|
132 default='us-west-1', |
|
133 ) |
|
134 |
|
135 subparsers = parser.add_subparsers() |
|
136 |
|
137 sp = subparsers.add_parser( |
|
138 'bootstrap-windows-dev', |
|
139 help='Bootstrap the Windows development environment', |
|
140 ) |
|
141 sp.set_defaults(func=bootstrap_windows_dev) |
|
142 |
|
143 sp = subparsers.add_parser( |
|
144 'build-all-windows-packages', |
|
145 help='Build all Windows packages', |
|
146 ) |
|
147 sp.add_argument( |
|
148 '--revision', |
|
149 help='Mercurial revision to build', |
|
150 default='.', |
|
151 ) |
|
152 sp.set_defaults(func=build_all_windows_packages) |
|
153 |
|
154 sp = subparsers.add_parser( |
|
155 'build-inno', |
|
156 help='Build Inno Setup installer(s)', |
|
157 ) |
|
158 sp.add_argument( |
|
159 '--arch', |
|
160 help='Architecture to build for', |
|
161 choices={'x86', 'x64'}, |
|
162 nargs='*', |
|
163 default=['x64'], |
|
164 ) |
|
165 sp.add_argument( |
|
166 '--revision', |
|
167 help='Mercurial revision to build', |
|
168 default='.', |
|
169 ) |
|
170 sp.add_argument( |
|
171 '--version', |
|
172 help='Mercurial version string to use in installer', |
|
173 ) |
|
174 sp.set_defaults(func=build_inno) |
|
175 |
|
176 sp = subparsers.add_parser( |
|
177 'build-windows-wheel', |
|
178 help='Build Windows wheel(s)', |
|
179 ) |
|
180 sp.add_argument( |
|
181 '--arch', |
|
182 help='Architecture to build for', |
|
183 choices={'x86', 'x64'}, |
|
184 nargs='*', |
|
185 default=['x64'], |
|
186 ) |
|
187 sp.add_argument( |
|
188 '--revision', |
|
189 help='Mercurial revision to build', |
|
190 default='.', |
|
191 ) |
|
192 sp.set_defaults(func=build_windows_wheel) |
|
193 |
|
194 sp = subparsers.add_parser( |
|
195 'build-wix', |
|
196 help='Build WiX installer(s)' |
|
197 ) |
|
198 sp.add_argument( |
|
199 '--arch', |
|
200 help='Architecture to build for', |
|
201 choices={'x86', 'x64'}, |
|
202 nargs='*', |
|
203 default=['x64'], |
|
204 ) |
|
205 sp.add_argument( |
|
206 '--revision', |
|
207 help='Mercurial revision to build', |
|
208 default='.', |
|
209 ) |
|
210 sp.add_argument( |
|
211 '--version', |
|
212 help='Mercurial version string to use in installer', |
|
213 ) |
|
214 sp.set_defaults(func=build_wix) |
|
215 |
|
216 sp = subparsers.add_parser( |
|
217 'terminate-ec2-instances', |
|
218 help='Terminate all active EC2 instances managed by us', |
|
219 ) |
|
220 sp.set_defaults(func=terminate_ec2_instances) |
|
221 |
|
222 sp = subparsers.add_parser( |
|
223 'purge-ec2-resources', |
|
224 help='Purge all EC2 resources managed by us', |
|
225 ) |
|
226 sp.set_defaults(func=purge_ec2_resources) |
|
227 |
|
228 sp = subparsers.add_parser( |
|
229 'run-tests-windows', |
|
230 help='Run tests on Windows', |
|
231 ) |
|
232 sp.add_argument( |
|
233 '--instance-type', |
|
234 help='EC2 instance type to use', |
|
235 default='t3.medium', |
|
236 ) |
|
237 sp.add_argument( |
|
238 '--python-version', |
|
239 help='Python version to use', |
|
240 choices={'2.7', '3.5', '3.6', '3.7', '3.8'}, |
|
241 default='2.7', |
|
242 ) |
|
243 sp.add_argument( |
|
244 '--arch', |
|
245 help='Architecture to test', |
|
246 choices={'x86', 'x64'}, |
|
247 default='x64', |
|
248 ) |
|
249 sp.add_argument( |
|
250 '--test-flags', |
|
251 help='Extra command line flags to pass to run-tests.py', |
|
252 ) |
|
253 sp.set_defaults(func=run_tests_windows) |
|
254 |
|
255 return parser |
|
256 |
|
257 |
|
258 def main(): |
|
259 parser = get_parser() |
|
260 args = parser.parse_args() |
|
261 |
|
262 local_state_path = pathlib.Path(os.path.expanduser(args.state_path)) |
|
263 automation = HGAutomation(local_state_path) |
|
264 |
|
265 if not hasattr(args, 'func'): |
|
266 parser.print_help() |
|
267 return |
|
268 |
|
269 kwargs = dict(vars(args)) |
|
270 del kwargs['func'] |
|
271 del kwargs['state_path'] |
|
272 |
|
273 args.func(automation, **kwargs) |