Merge ~fourdollars/pc-enablement/+git/oem-scripts:master into ~oem-solutions-engineers/pc-enablement/+git/oem-scripts:master
- Git
- lp:~fourdollars/pc-enablement/+git/oem-scripts
- master
- Merge into master
Proposed by
Shih-Yuan Lee
Status: | Merged |
---|---|
Approved by: | Shih-Yuan Lee |
Approved revision: | 5f2b26c9833fef47f9124fc73869a0499b654bcf |
Merged at revision: | 1f693f0f12cf4a0ddf0d75d43353c62b89bb19ae |
Proposed branch: | ~fourdollars/pc-enablement/+git/oem-scripts:master |
Merge into: | ~oem-solutions-engineers/pc-enablement/+git/oem-scripts:master |
Diff against target: |
697 lines (+559/-37) 9 files modified
bootstrap-meta (+420/-0) debian/changelog (+14/-0) debian/tests/bootstrap-meta (+58/-0) debian/tests/control (+1/-0) mir-bug (+8/-37) oem-meta-package.sru.jinja2 (+24/-0) oem_scripts/LaunchpadLogin.py (+3/-0) oem_scripts/__init__.py (+30/-0) setup.py (+1/-0) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Yuan-Chen Cheng (community) | Approve | ||
Review via email: mp+408091@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Revision history for this message
Shih-Yuan Lee (fourdollars) wrote : | # |
Revision history for this message
Yuan-Chen Cheng (ycheng-twn) wrote : | # |
Well, the code looks fine, however, there are some nice to have change:
1. For get meta pkg name from group and platform name, can we refactor so that it's a function call that can be re-use?
2. for project oem-priority, team name oem-solutions-
I mean something like:
OEM_TEAM = "oem-solutions-
person=
3. "focal" is hardcoded, it will be easier to be changed if it's a variable.
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | diff --git a/bootstrap-meta b/bootstrap-meta | |||
2 | 0 | new file mode 100755 | 0 | new file mode 100755 |
3 | index 0000000..03549a3 | |||
4 | --- /dev/null | |||
5 | +++ b/bootstrap-meta | |||
6 | @@ -0,0 +1,420 @@ | |||
7 | 1 | #!/usr/bin/env python3 | ||
8 | 2 | # -*- coding: utf-8 -*- | ||
9 | 3 | # Copyright (C) 2021 Canonical Ltd. | ||
10 | 4 | # Author: Shih-Yuan Lee (FourDollars) <sylee@canonical.com> | ||
11 | 5 | # | ||
12 | 6 | # This program is free software; you can redistribute it and/or modify | ||
13 | 7 | # it under the terms of the GNU General Public License as published by | ||
14 | 8 | # the Free Software Foundation; either version 3 of the License, or | ||
15 | 9 | # (at your option) any later version. | ||
16 | 10 | # | ||
17 | 11 | # This program is distributed in the hope that it will be useful, | ||
18 | 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | 14 | # GNU General Public License for more details. | ||
21 | 15 | # | ||
22 | 16 | # You should have received a copy of the GNU General Public License | ||
23 | 17 | # along with this program; if not, write to the Free Software | ||
24 | 18 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
25 | 19 | |||
26 | 20 | import argparse | ||
27 | 21 | import collections | ||
28 | 22 | import jinja2 | ||
29 | 23 | import json | ||
30 | 24 | import oem_scripts | ||
31 | 25 | import re | ||
32 | 26 | |||
33 | 27 | from copy import copy | ||
34 | 28 | from logging import info, warning, error | ||
35 | 29 | from oem_scripts import SUBSCRIBER_LIST, TAG_LIST, remove_prefix, yes_or_ask | ||
36 | 30 | from oem_scripts.LaunchpadLogin import LaunchpadLogin | ||
37 | 31 | from oem_scripts.logging import setup_logging | ||
38 | 32 | |||
39 | 33 | |||
40 | 34 | class BootstrapMeta(object): | ||
41 | 35 | def __init__(self, platformJson, lp, kernel_meta): | ||
42 | 36 | self.kernel_meta = kernel_meta | ||
43 | 37 | self.lp = lp | ||
44 | 38 | self.json = json.load(platformJson) | ||
45 | 39 | self.project = self.json["project"] | ||
46 | 40 | self.group = self.json["group"] | ||
47 | 41 | self.platform = self.json["platform"] | ||
48 | 42 | |||
49 | 43 | if self.json["project"] == "somerville": | ||
50 | 44 | self.meta = "oem-somerville-" + self.json["platform"] + "-meta" | ||
51 | 45 | elif self.json["project"] == "stella": | ||
52 | 46 | self.meta = ( | ||
53 | 47 | "oem-stella." | ||
54 | 48 | + self.json["group"] | ||
55 | 49 | + "." | ||
56 | 50 | + self.json["platform"] | ||
57 | 51 | + "-meta" | ||
58 | 52 | ) | ||
59 | 53 | elif self.json["project"] == "sutton": | ||
60 | 54 | self.meta = ( | ||
61 | 55 | "oem-sutton." | ||
62 | 56 | + self.json["group"] | ||
63 | 57 | + "." | ||
64 | 58 | + self.json["platform"] | ||
65 | 59 | + "-meta" | ||
66 | 60 | ) | ||
67 | 61 | else: | ||
68 | 62 | raise Exception("Not supported") | ||
69 | 63 | |||
70 | 64 | def create_bug(self, title, description, importance, status): | ||
71 | 65 | project = lp.projects["oem-priority"] | ||
72 | 66 | bug = self.lp.bugs.createBug( | ||
73 | 67 | description=description, | ||
74 | 68 | target=project, | ||
75 | 69 | title=title, | ||
76 | 70 | information_type="Public", | ||
77 | 71 | tags=TAG_LIST, | ||
78 | 72 | ) | ||
79 | 73 | info("meta package public bug: " + bug.web_link) | ||
80 | 74 | |||
81 | 75 | for task in bug.bug_tasks: | ||
82 | 76 | task.status = status | ||
83 | 77 | task.importance = importance | ||
84 | 78 | # Assign to reporter by default | ||
85 | 79 | task.assignee = lp.me | ||
86 | 80 | task.lp_save() | ||
87 | 81 | |||
88 | 82 | # Subscribe the oem-solutions-engineers | ||
89 | 83 | bug.subscribe(person=lp.people["oem-solutions-engineers"]) | ||
90 | 84 | bug.lp_save() | ||
91 | 85 | |||
92 | 86 | return bug | ||
93 | 87 | |||
94 | 88 | def _grouping_market_names(self, market_names: list, maxsplit=1) -> str: | ||
95 | 89 | # Remove empty item | ||
96 | 90 | while "" in market_names: | ||
97 | 91 | market_names.remove("") | ||
98 | 92 | tmp = collections.defaultdict(list) | ||
99 | 93 | space_in_model = False | ||
100 | 94 | try: | ||
101 | 95 | for market_name in sorted(market_names): | ||
102 | 96 | if maxsplit == 1: | ||
103 | 97 | name, model = market_name.split(maxsplit=maxsplit) | ||
104 | 98 | tmp[name].append(model) | ||
105 | 99 | if " " in model: | ||
106 | 100 | space_in_model = True | ||
107 | 101 | elif maxsplit == 2: | ||
108 | 102 | brand, name, model = market_name.split(maxsplit=maxsplit) | ||
109 | 103 | tmp[brand + " " + name].append(model) | ||
110 | 104 | if " " in model: | ||
111 | 105 | space_in_model = True | ||
112 | 106 | except ValueError: | ||
113 | 107 | return ", ".join(sorted(market_names)) | ||
114 | 108 | |||
115 | 109 | if space_in_model: | ||
116 | 110 | return ", ".join( | ||
117 | 111 | f"{name} {', '.join(models)}" for name, models in tmp.items() | ||
118 | 112 | ) | ||
119 | 113 | else: | ||
120 | 114 | return ", ".join( | ||
121 | 115 | f"{name} {'/'.join(models)}" for name, models in tmp.items() | ||
122 | 116 | ) | ||
123 | 117 | |||
124 | 118 | def parse_market_name(self): | ||
125 | 119 | if self.project == "somerville": | ||
126 | 120 | self.market_name = self._grouping_market_names(self.json["productnames"]) | ||
127 | 121 | if not self.market_name.startswith("Dell "): | ||
128 | 122 | self.market_name = "Dell " + self.market_name | ||
129 | 123 | elif self.project == "stella": | ||
130 | 124 | self.market_name = self._grouping_market_names( | ||
131 | 125 | self.json["productnames"], maxsplit=2 | ||
132 | 126 | ) | ||
133 | 127 | self.market_name = remove_prefix(self.market_name, "HP ") | ||
134 | 128 | if not self.market_name.startswith("HP "): | ||
135 | 129 | self.market_name = "HP " + self.market_name | ||
136 | 130 | elif self.project == "sutton": | ||
137 | 131 | self.market_name = self._grouping_market_names(self.json["productnames"]) | ||
138 | 132 | if not self.market_name.startswith("Lenovo "): | ||
139 | 133 | self.market_name = "Lenovo " + self.market_name | ||
140 | 134 | else: | ||
141 | 135 | raise Exception("Not supported") | ||
142 | 136 | |||
143 | 137 | |||
144 | 138 | class BootstrapMetaMIR(BootstrapMeta): | ||
145 | 139 | def __init__(self, platformJson, lp, kernel_meta): | ||
146 | 140 | super().__init__(platformJson, lp, kernel_meta) | ||
147 | 141 | |||
148 | 142 | def _read_from_template(self, marketName, oemMetaPackage, kernelMeta): | ||
149 | 143 | env = jinja2.Environment( | ||
150 | 144 | loader=jinja2.FileSystemLoader(["./", "/usr/share/oem-scripts"]) | ||
151 | 145 | ) | ||
152 | 146 | template = env.get_template("oem-meta-package.mir.jinja2") | ||
153 | 147 | return template.render( | ||
154 | 148 | metaPkgName=self.market_name, | ||
155 | 149 | branchName=self.branch, | ||
156 | 150 | oemCodenameNogroup=self.project, | ||
157 | 151 | deviceName=self.device_name, | ||
158 | 152 | ) | ||
159 | 153 | |||
160 | 154 | def create(self): | ||
161 | 155 | title = f"[DRAFT][MIR] {self.meta}" | ||
162 | 156 | description = "[DRAFT]" + self._read_from_template() | ||
163 | 157 | super().create_bug( | ||
164 | 158 | title, description, importance="Critical", status="Confirmed" | ||
165 | 159 | ) | ||
166 | 160 | |||
167 | 161 | def update(self): | ||
168 | 162 | pass | ||
169 | 163 | |||
170 | 164 | |||
171 | 165 | class BootstrapMetaSRU(BootstrapMeta): | ||
172 | 166 | def __init__(self, platformJson, lp, kernel_meta, output): | ||
173 | 167 | super().__init__(platformJson, lp, kernel_meta) | ||
174 | 168 | self.parse_market_name() | ||
175 | 169 | self.pattern = re.compile( | ||
176 | 170 | rf".*Update the hardware support for .* in {self.meta}.*" | ||
177 | 171 | ) | ||
178 | 172 | self.output = output | ||
179 | 173 | |||
180 | 174 | def _read_from_template(self): | ||
181 | 175 | env = jinja2.Environment( | ||
182 | 176 | loader=jinja2.FileSystemLoader(["./", "/usr/share/oem-scripts"]) | ||
183 | 177 | ) | ||
184 | 178 | template = env.get_template("oem-meta-package.sru.jinja2") | ||
185 | 179 | return template.render( | ||
186 | 180 | marketName=self.market_name, | ||
187 | 181 | oemMetaPackage=self.meta, | ||
188 | 182 | kernelMeta=self.kernel_meta, | ||
189 | 183 | ) | ||
190 | 184 | |||
191 | 185 | def create(self, importance="High", status="Confirmed"): | ||
192 | 186 | project = lp.projects[f"ubuntu/focal/+source/{self.meta}"] | ||
193 | 187 | tasks = project.searchTasks() | ||
194 | 188 | for task in tasks: | ||
195 | 189 | bug = task.bug | ||
196 | 190 | if self.pattern.match(bug.title): | ||
197 | 191 | if self.output: | ||
198 | 192 | self.output.write(f"{bug.id}\n") | ||
199 | 193 | if lp.service_root != "https://api.launchpad.net/": | ||
200 | 194 | error(f'{bug.web_link} - "{bug.title}" has been created.') | ||
201 | 195 | else: | ||
202 | 196 | error(f'LP: #{bug.id} - "{bug.title}" has been created.') | ||
203 | 197 | exit(1) | ||
204 | 198 | title = ( | ||
205 | 199 | f"[DRAFT] Update the hardware support for {self.market_name} in {self.meta}" | ||
206 | 200 | ) | ||
207 | 201 | description = "[DRAFT]" + self._read_from_template() | ||
208 | 202 | bug = super().create_bug( | ||
209 | 203 | title, description, importance=importance, status=status | ||
210 | 204 | ) | ||
211 | 205 | if self.output: | ||
212 | 206 | self.output.write(f"{bug.id}\n") | ||
213 | 207 | task = bug.addTask(target=lp.projects[f"ubuntu/+source/{self.meta}"]) | ||
214 | 208 | task.status = "Won't Fix" | ||
215 | 209 | task.lp_save() | ||
216 | 210 | task = bug.addTask(target=lp.projects[f"ubuntu/focal/+source/{self.meta}"]) | ||
217 | 211 | task.status = status | ||
218 | 212 | task.importance = importance | ||
219 | 213 | task.assignee = lp.me | ||
220 | 214 | task.lp_save() | ||
221 | 215 | |||
222 | 216 | def update(self, release=False, ready=False, yes=False): | ||
223 | 217 | project = lp.projects[f"ubuntu/focal/+source/{self.meta}"] | ||
224 | 218 | tasks = project.searchTasks() | ||
225 | 219 | candidate = None | ||
226 | 220 | for task in tasks: | ||
227 | 221 | bug = task.bug | ||
228 | 222 | if self.pattern.match(bug.title): | ||
229 | 223 | if yes_or_ask( | ||
230 | 224 | yes, | ||
231 | 225 | f'Do you want to update LP: #{bug.id} - "{bug.title}" for {self.kernel_meta}?', | ||
232 | 226 | ): | ||
233 | 227 | candidate = bug | ||
234 | 228 | |||
235 | 229 | if candidate is None: | ||
236 | 230 | warning("Please use create-sru-bug to create the SRU bug first.") | ||
237 | 231 | exit(1) | ||
238 | 232 | else: | ||
239 | 233 | bug = candidate | ||
240 | 234 | if self.output: | ||
241 | 235 | self.output.write(f"{bug.id}\n") | ||
242 | 236 | |||
243 | 237 | bug.title = f"Update the hardware support for {self.market_name} in {self.meta}" | ||
244 | 238 | bug.description = self._read_from_template() | ||
245 | 239 | bug.lp_save() | ||
246 | 240 | |||
247 | 241 | subscriptions = list(map(lambda x: x.person.name, bug.subscriptions)) | ||
248 | 242 | tags = copy(bug.tags) | ||
249 | 243 | if ready or release: | ||
250 | 244 | for subscriber in SUBSCRIBER_LIST: | ||
251 | 245 | if subscriber not in subscriptions: | ||
252 | 246 | bug.subscribe(person=lp.people[subscriber]) | ||
253 | 247 | if "oem-solutions-engineers" not in subscriptions: | ||
254 | 248 | bug.subscribe(person=lp.people["oem-solutions-engineers"]) | ||
255 | 249 | if release: | ||
256 | 250 | if "oem-done-upload" not in tags: | ||
257 | 251 | tags.append("oem-done-upload") | ||
258 | 252 | if "oem-needs-upload" in tags: | ||
259 | 253 | tags.remove("oem-needs-upload") | ||
260 | 254 | if "ubuntu-desktop" not in subscriptions: | ||
261 | 255 | bug.subscribe(person=lp.people["ubuntu-desktop"]) | ||
262 | 256 | if "ubuntu-sponsors" in subscriptions: | ||
263 | 257 | bug.unsubscribe(person=lp.people["ubuntu-sponsors"]) | ||
264 | 258 | if "ubuntu-sru" not in subscriptions: | ||
265 | 259 | bug.subscribe(person=lp.people["ubuntu-sru"]) | ||
266 | 260 | elif ready: | ||
267 | 261 | if "oem-done-upload" in tags: | ||
268 | 262 | tags.remove("oem-done-upload") | ||
269 | 263 | if "oem-needs-upload" not in tags: | ||
270 | 264 | tags.append("oem-needs-upload") | ||
271 | 265 | if "ubuntu-desktop" not in subscriptions: | ||
272 | 266 | bug.subscribe(person=lp.people["ubuntu-desktop"]) | ||
273 | 267 | if "ubuntu-sponsors" not in subscriptions: | ||
274 | 268 | bug.subscribe(person=lp.people["ubuntu-sponsors"]) | ||
275 | 269 | if "ubuntu-sru" in subscriptions: | ||
276 | 270 | bug.unsubscribe(person=lp.people["ubuntu-sru"]) | ||
277 | 271 | else: | ||
278 | 272 | if "oem-done-upload" in tags: | ||
279 | 273 | tags.remove("oem-done-upload") | ||
280 | 274 | if "oem-needs-upload" in tags: | ||
281 | 275 | tags.remove("oem-needs-upload") | ||
282 | 276 | if "ubuntu-desktop" in subscriptions: | ||
283 | 277 | bug.unsubscribe(person=lp.people["ubuntu-desktop"]) | ||
284 | 278 | if "ubuntu-sponsors" in subscriptions: | ||
285 | 279 | bug.unsubscribe(person=lp.people["ubuntu-sponsors"]) | ||
286 | 280 | if "ubuntu-sru" in subscriptions: | ||
287 | 281 | bug.unsubscribe(person=lp.people["ubuntu-sru"]) | ||
288 | 282 | for tag in bug.tags: | ||
289 | 283 | if tag.startswith("oem-scripts-"): | ||
290 | 284 | if tag[len("oem-scripts-") :] != oem_scripts.__version__: | ||
291 | 285 | tags.remove(tag) | ||
292 | 286 | for tag in TAG_LIST: | ||
293 | 287 | if tag not in tags: | ||
294 | 288 | tags.append(tag) | ||
295 | 289 | bug.tags = tags | ||
296 | 290 | bug.lp_save() | ||
297 | 291 | |||
298 | 292 | for task in bug.bug_tasks: | ||
299 | 293 | if ( | ||
300 | 294 | task.bug_target_name == "oem-priority" | ||
301 | 295 | or task.bug_target_name == "oem-somerville-varys-meta (Ubuntu Focal)" | ||
302 | 296 | ): | ||
303 | 297 | if release: | ||
304 | 298 | task.status = "In Progress" | ||
305 | 299 | elif ready: | ||
306 | 300 | task.status = "Triaged" | ||
307 | 301 | else: | ||
308 | 302 | task.status = "Confirmed" | ||
309 | 303 | elif task.bug_target_name == "oem-somerville-varys-meta (Ubuntu)": | ||
310 | 304 | task.status = "Won't Fix" | ||
311 | 305 | task.lp_save() | ||
312 | 306 | |||
313 | 307 | if lp.service_root != "https://api.launchpad.net/": | ||
314 | 308 | info(f'{bug.web_link} - "{bug.title}" has been updated.') | ||
315 | 309 | else: | ||
316 | 310 | info(f'LP: #{bug.id} - "{bug.title}" has been updated.') | ||
317 | 311 | |||
318 | 312 | |||
319 | 313 | parser = argparse.ArgumentParser( | ||
320 | 314 | formatter_class=argparse.RawDescriptionHelpFormatter, | ||
321 | 315 | epilog=""" | ||
322 | 316 | examples: | ||
323 | 317 | bootstrap-meta create-mir-bug platformJSON [WIP] | ||
324 | 318 | bootstrap-meta update-mir-bug platformJSON [WIP] | ||
325 | 319 | bootstrap-meta update-mir-git platformJSON [WIP] | ||
326 | 320 | bootstrap-meta create-sru-bug platformJSON [--kernel linux-generic-hwe-20.04] | ||
327 | 321 | bootstrap-meta update-sru-bug platformJSON [--kernel linux-generic-hwe-20.04] [--yes] [--ready|--release] | ||
328 | 322 | bootstrap-meta update-sru-git platformJSON [WIP]""", | ||
329 | 323 | ) | ||
330 | 324 | |||
331 | 325 | parser.add_argument("-d", "--debug", help="print debug messages", action="store_true") | ||
332 | 326 | parser.add_argument( | ||
333 | 327 | "-q", "--quiet", help="Don't print info messages", action="store_true" | ||
334 | 328 | ) | ||
335 | 329 | |||
336 | 330 | subparsers = parser.add_subparsers(dest="subcommand") | ||
337 | 331 | |||
338 | 332 | create_mir_bug = subparsers.add_parser("create-mir-bug", help="[-h] platformJSON") | ||
339 | 333 | create_mir_bug.add_argument( | ||
340 | 334 | "json", | ||
341 | 335 | help="Specify the platform json of the OEM metapackage.", | ||
342 | 336 | type=argparse.FileType("r", encoding="UTF-8"), | ||
343 | 337 | ) | ||
344 | 338 | |||
345 | 339 | update_mir_bug = subparsers.add_parser("update-mir-bug", help="[-h] platformJSON") | ||
346 | 340 | update_mir_bug.add_argument( | ||
347 | 341 | "json", | ||
348 | 342 | help="Specify the platform json of the OEM metapackage.", | ||
349 | 343 | type=argparse.FileType("r", encoding="UTF-8"), | ||
350 | 344 | ) | ||
351 | 345 | |||
352 | 346 | create_sru_bug = subparsers.add_parser("create-sru-bug", help="[-h] platformJSON") | ||
353 | 347 | create_sru_bug.add_argument( | ||
354 | 348 | "json", | ||
355 | 349 | help="Specify the platform json of the OEM metapackage in Ubuntu archive.", | ||
356 | 350 | type=argparse.FileType("r", encoding="UTF-8"), | ||
357 | 351 | ) | ||
358 | 352 | create_sru_bug.add_argument( | ||
359 | 353 | "--kernel", | ||
360 | 354 | default="linux-generic-hwe-20.04", | ||
361 | 355 | help="Specify the kernel meta of the OEM metapackage that is targeting on.", | ||
362 | 356 | ) | ||
363 | 357 | create_sru_bug.add_argument( | ||
364 | 358 | "-o", | ||
365 | 359 | "--output", | ||
366 | 360 | help="Specify a file name to write the bug number.", | ||
367 | 361 | type=argparse.FileType("w", encoding="UTF-8"), | ||
368 | 362 | ) | ||
369 | 363 | |||
370 | 364 | update_sru_bug = subparsers.add_parser( | ||
371 | 365 | "update-sru-bug", | ||
372 | 366 | help="[-h] platformJSON [--kernel linux-generic-hwe-20.04] [--yes] [--ready|--release]", | ||
373 | 367 | ) | ||
374 | 368 | update_sru_bug.add_argument( | ||
375 | 369 | "json", | ||
376 | 370 | help="Specify the platform json of the OEM metapackage in Ubuntu archive.", | ||
377 | 371 | type=argparse.FileType("r", encoding="UTF-8"), | ||
378 | 372 | ) | ||
379 | 373 | update_sru_bug.add_argument( | ||
380 | 374 | "--kernel", | ||
381 | 375 | default="linux-generic-hwe-20.04", | ||
382 | 376 | help="Specify the kernel meta of the OEM metapackage that is targeting on.", | ||
383 | 377 | ) | ||
384 | 378 | update_sru_bug.add_argument( | ||
385 | 379 | "--release", | ||
386 | 380 | action="store_true", | ||
387 | 381 | help="Update the bug when the OEM metapackage has been uploaded into the queue for releasing.", | ||
388 | 382 | ) | ||
389 | 383 | update_sru_bug.add_argument( | ||
390 | 384 | "--ready", | ||
391 | 385 | action="store_true", | ||
392 | 386 | help="Update the bug when the OEM metapackage is ready to upload.", | ||
393 | 387 | ) | ||
394 | 388 | update_sru_bug.add_argument( | ||
395 | 389 | "--yes", help="Say yes for all prompts.", action="store_true" | ||
396 | 390 | ) | ||
397 | 391 | update_sru_bug.add_argument( | ||
398 | 392 | "-o", | ||
399 | 393 | "--output", | ||
400 | 394 | help="Specify a file name to write the bug number.", | ||
401 | 395 | type=argparse.FileType("w", encoding="UTF-8"), | ||
402 | 396 | ) | ||
403 | 397 | |||
404 | 398 | args = parser.parse_args() | ||
405 | 399 | setup_logging(debug=args.debug, quiet=args.quiet) | ||
406 | 400 | |||
407 | 401 | if args.subcommand: | ||
408 | 402 | login = LaunchpadLogin() | ||
409 | 403 | lp = login.lp | ||
410 | 404 | lp.service_root = login.service_root | ||
411 | 405 | lp.service_version = login.service_version | ||
412 | 406 | |||
413 | 407 | # if args.subcommand == "create-mir-bug": | ||
414 | 408 | # mirbug = BootstrapMetaMIR(args.json, lp, args.kernel) | ||
415 | 409 | # mirbug.create() | ||
416 | 410 | # elif args.subcommand == "update-mir-bug": | ||
417 | 411 | # mirbug = BootstrapMetaMIR(args.json, lp, args.kernel) | ||
418 | 412 | # mirbug.update() | ||
419 | 413 | if args.subcommand == "create-sru-bug": | ||
420 | 414 | srubug = BootstrapMetaSRU(args.json, lp, args.kernel, args.output) | ||
421 | 415 | srubug.create() | ||
422 | 416 | elif args.subcommand == "update-sru-bug": | ||
423 | 417 | srubug = BootstrapMetaSRU(args.json, lp, args.kernel, args.output) | ||
424 | 418 | srubug.update(release=args.release, ready=args.ready, yes=args.yes) | ||
425 | 419 | else: | ||
426 | 420 | parser.print_help() | ||
427 | diff --git a/debian/changelog b/debian/changelog | |||
428 | index 4896fc6..6ef7544 100644 | |||
429 | --- a/debian/changelog | |||
430 | +++ b/debian/changelog | |||
431 | @@ -1,3 +1,17 @@ | |||
432 | 1 | oem-scripts (1.12) UNRELEASED; urgency=medium | ||
433 | 2 | |||
434 | 3 | * bootstrap-meta, | ||
435 | 4 | debian/tests/bootstrap-meta, | ||
436 | 5 | debian/tests/control, | ||
437 | 6 | mir-bug, | ||
438 | 7 | oem-meta-package.sru.jinja2, | ||
439 | 8 | oem_scripts/LaunchpadLogin.py, | ||
440 | 9 | oem_scripts/__init__.py, | ||
441 | 10 | setup.py: Add the bootstrap-meta tool to deal with OEM metapackages SRU | ||
442 | 11 | bugs. | ||
443 | 12 | |||
444 | 13 | -- Shih-Yuan Lee (FourDollars) <sylee@canonical.com> Thu, 02 Sep 2021 14:55:10 +0800 | ||
445 | 14 | |||
446 | 1 | oem-scripts (1.11) focal; urgency=medium | 15 | oem-scripts (1.11) focal; urgency=medium |
447 | 2 | 16 | ||
448 | 3 | * debian/control, | 17 | * debian/control, |
449 | diff --git a/debian/tests/bootstrap-meta b/debian/tests/bootstrap-meta | |||
450 | 4 | new file mode 100644 | 18 | new file mode 100644 |
451 | index 0000000..f0ec33f | |||
452 | --- /dev/null | |||
453 | +++ b/debian/tests/bootstrap-meta | |||
454 | @@ -0,0 +1,58 @@ | |||
455 | 1 | #!/bin/bash | ||
456 | 2 | |||
457 | 3 | set -euo pipefail | ||
458 | 4 | IFS=$'\n\t' | ||
459 | 5 | |||
460 | 6 | export LAUNCHPAD_API="https://api.staging.launchpad.net/" | ||
461 | 7 | |||
462 | 8 | cat > fossa-varys.json <<ENDLINE | ||
463 | 9 | { | ||
464 | 10 | "group": "", | ||
465 | 11 | "platform": "varys", | ||
466 | 12 | "productnames": [ | ||
467 | 13 | "Precision 5550" | ||
468 | 14 | ], | ||
469 | 15 | "project": "somerville" | ||
470 | 16 | } | ||
471 | 17 | ENDLINE | ||
472 | 18 | |||
473 | 19 | cleanup() { | ||
474 | 20 | echo "= cleanup =" | ||
475 | 21 | if [ -f "bugid" ]; then | ||
476 | 22 | BUG_ID=$(cat bugid) | ||
477 | 23 | rm bugid | ||
478 | 24 | fi | ||
479 | 25 | if [ -f "$BUG_ID.json" ]; then | ||
480 | 26 | jq -C -S < "$BUG_ID.json" | ||
481 | 27 | rm "$BUG_ID.json" | ||
482 | 28 | lp-bug cleanup --yes "$BUG_ID" | ||
483 | 29 | fi | ||
484 | 30 | } | ||
485 | 31 | |||
486 | 32 | trap cleanup EXIT INT TERM | ||
487 | 33 | |||
488 | 34 | bootstrap-meta create-sru-bug fossa-varys.json --kernel linux-oem-20.04 --output bugid | ||
489 | 35 | BUG_ID=$(cat bugid) | ||
490 | 36 | launchpad-api get "bugs/$BUG_ID" > "$BUG_ID.json" | ||
491 | 37 | jq -r .description < "$BUG_ID.json" | grep "Precision 5550" | ||
492 | 38 | jq -r .description < "$BUG_ID.json" | grep linux-oem-20.04 | ||
493 | 39 | jq -r '.tags|join(" ")' < "$BUG_ID.json" | grep oem-meta-packages | ||
494 | 40 | |||
495 | 41 | if bootstrap-meta create-sru-bug fossa-varys.json --kernel linux-oem-20.04 --output bugid; then | ||
496 | 42 | echo "It is expected to return failed." | ||
497 | 43 | exit 1 | ||
498 | 44 | fi | ||
499 | 45 | |||
500 | 46 | bootstrap-meta update-sru-bug fossa-varys.json --kernel linux-oem-20.04b --yes | ||
501 | 47 | launchpad-api get "bugs/$BUG_ID" > "$BUG_ID.json" | ||
502 | 48 | jq -r .description < "$BUG_ID.json" | grep linux-oem-20.04b | ||
503 | 49 | |||
504 | 50 | bootstrap-meta update-sru-bug fossa-varys.json --kernel linux-oem-20.04c --yes --ready | ||
505 | 51 | launchpad-api get "bugs/$BUG_ID" > "$BUG_ID.json" | ||
506 | 52 | jq -r .description < "$BUG_ID.json" | grep linux-oem-20.04c | ||
507 | 53 | jq -r '.tags|join(" ")' < "$BUG_ID.json" | grep oem-needs-upload | ||
508 | 54 | |||
509 | 55 | bootstrap-meta update-sru-bug fossa-varys.json --kernel linux-oem-20.04d --yes --release | ||
510 | 56 | launchpad-api get "bugs/$BUG_ID" > "$BUG_ID.json" | ||
511 | 57 | jq -r .description < "$BUG_ID.json" | grep linux-oem-20.04d | ||
512 | 58 | jq -r '.tags|join(" ")' < "$BUG_ID.json" | grep oem-done-upload | ||
513 | diff --git a/debian/tests/control b/debian/tests/control | |||
514 | index 1f9da74..a9a549d 100644 | |||
515 | --- a/debian/tests/control | |||
516 | +++ b/debian/tests/control | |||
517 | @@ -10,6 +10,7 @@ Tests: | |||
518 | 10 | Depends: @, ubuntu-dev-tools, git-buildpackage | 10 | Depends: @, ubuntu-dev-tools, git-buildpackage |
519 | 11 | 11 | ||
520 | 12 | Tests: | 12 | Tests: |
521 | 13 | bootstrap-meta, | ||
522 | 13 | bug-bind, | 14 | bug-bind, |
523 | 14 | get-private-ppa, | 15 | get-private-ppa, |
524 | 15 | jq-lp, | 16 | jq-lp, |
525 | diff --git a/mir-bug b/mir-bug | |||
526 | index d90e130..be49cb3 100755 | |||
527 | --- a/mir-bug | |||
528 | +++ b/mir-bug | |||
529 | @@ -33,23 +33,17 @@ import subprocess | |||
530 | 33 | from copy import copy | 33 | from copy import copy |
531 | 34 | from glob import glob | 34 | from glob import glob |
532 | 35 | from logging import debug, info, warning, error, critical | 35 | from logging import debug, info, warning, error, critical |
533 | 36 | from oem_scripts import ( | ||
534 | 37 | SUBSCRIBER_LIST, | ||
535 | 38 | TAG_LIST, | ||
536 | 39 | ALLOWED_KERNEL_META_LIST, | ||
537 | 40 | remove_prefix, | ||
538 | 41 | yes_or_ask, | ||
539 | 42 | ) | ||
540 | 36 | from oem_scripts.LaunchpadLogin import LaunchpadLogin | 43 | from oem_scripts.LaunchpadLogin import LaunchpadLogin |
541 | 37 | from oem_scripts.logging import setup_logging | 44 | from oem_scripts.logging import setup_logging |
542 | 38 | from tempfile import TemporaryDirectory | 45 | from tempfile import TemporaryDirectory |
543 | 39 | 46 | ||
544 | 40 | ALLOWED_KERNEL_META_LIST = ( | ||
545 | 41 | "linux-oem-20.04c", | ||
546 | 42 | "linux-oem-20.04b", | ||
547 | 43 | "linux-oem-20.04", | ||
548 | 44 | "linux-generic-hwe-20.04", | ||
549 | 45 | ) | ||
550 | 46 | SUBSCRIBER_LIST = ("oem-solutions-engineers", "ubuntu-sponsors", "ubuntu-desktop") | ||
551 | 47 | TAG_LIST = [ | ||
552 | 48 | "oem-meta-packages", | ||
553 | 49 | "oem-priority", | ||
554 | 50 | f"oem-scripts-{oem_scripts.__version__}", | ||
555 | 51 | ] | ||
556 | 52 | |||
557 | 53 | parser = argparse.ArgumentParser( | 47 | parser = argparse.ArgumentParser( |
558 | 54 | formatter_class=argparse.RawDescriptionHelpFormatter, | 48 | formatter_class=argparse.RawDescriptionHelpFormatter, |
559 | 55 | epilog=""" | 49 | epilog=""" |
560 | @@ -154,11 +148,6 @@ setup_logging(debug=args.debug, quiet=args.quiet) | |||
561 | 154 | pattern = re.compile(r".*\[MIR\]\W*oem-([^-]*)-(.*)-meta\W*") | 148 | pattern = re.compile(r".*\[MIR\]\W*oem-([^-]*)-(.*)-meta\W*") |
562 | 155 | 149 | ||
563 | 156 | 150 | ||
564 | 157 | # Python 3.9 supports this. | ||
565 | 158 | def remove_prefix(s, prefix): | ||
566 | 159 | return s[len(prefix) :] if s.startswith(prefix) else s | ||
567 | 160 | |||
568 | 161 | |||
569 | 162 | def _grouping_market_names(market_names: list, maxsplit=1) -> str: | 151 | def _grouping_market_names(market_names: list, maxsplit=1) -> str: |
570 | 163 | # Remove empty item | 152 | # Remove empty item |
571 | 164 | while "" in market_names: | 153 | while "" in market_names: |
572 | @@ -345,20 +334,6 @@ def collect_bugs(lp, output): | |||
573 | 345 | output.write("\n") | 334 | output.write("\n") |
574 | 346 | 335 | ||
575 | 347 | 336 | ||
576 | 348 | def yes_or_ask(yes: bool, message: str) -> bool: | ||
577 | 349 | if yes: | ||
578 | 350 | print(f"> \033[1;34m{message}\033[1;0m (y/n) y") | ||
579 | 351 | return True | ||
580 | 352 | while True: | ||
581 | 353 | res = input(f"> \033[1;34m{message}\033[1;0m (y/n) ").lower() | ||
582 | 354 | if res not in {"y", "n"}: | ||
583 | 355 | continue | ||
584 | 356 | if res == "y": | ||
585 | 357 | return True | ||
586 | 358 | else: | ||
587 | 359 | return False | ||
588 | 360 | |||
589 | 361 | |||
590 | 362 | def update_bug( | 337 | def update_bug( |
591 | 363 | lp, | 338 | lp, |
592 | 364 | bug_number: int, | 339 | bug_number: int, |
593 | @@ -713,11 +688,7 @@ def check_and_update_bug_subscriptions(lp, bug, update=False, yes=False) -> bool | |||
594 | 713 | else: | 688 | else: |
595 | 714 | result = False | 689 | result = False |
596 | 715 | if args.ready: | 690 | if args.ready: |
602 | 716 | for subscriber in ( | 691 | for subscriber in SUBSCRIBER_LIST: |
598 | 717 | "oem-solutions-engineers", | ||
599 | 718 | "ubuntu-sponsors", | ||
600 | 719 | "ubuntu-desktop", | ||
601 | 720 | ): | ||
603 | 721 | if subscriber not in subscriptions: | 692 | if subscriber not in subscriptions: |
604 | 722 | error(f"'{subscriber}' is not in the subscriptions.") | 693 | error(f"'{subscriber}' is not in the subscriptions.") |
605 | 723 | if update and yes_or_ask( | 694 | if update and yes_or_ask( |
606 | diff --git a/oem-meta-package.sru.jinja2 b/oem-meta-package.sru.jinja2 | |||
607 | 724 | new file mode 100644 | 695 | new file mode 100644 |
608 | index 0000000..88f8661 | |||
609 | --- /dev/null | |||
610 | +++ b/oem-meta-package.sru.jinja2 | |||
611 | @@ -0,0 +1,24 @@ | |||
612 | 1 | [Impact] | ||
613 | 2 | |||
614 | 3 | * It should have no impact at all because these changes shall have been applied and verified in the corresponding OEM archive before this SRU process. | ||
615 | 4 | |||
616 | 5 | [Test Plan] | ||
617 | 6 | |||
618 | 7 | * Install Ubuntu 20.04.x LTS on {{ marketName }} and remove {{ oemMetaPackage }} manually if any. | ||
619 | 8 | |||
620 | 9 | * Enable focal-proposed and execute the update-manager. | ||
621 | 10 | |||
622 | 11 | * The update-manager should show "Hardware support for {{ marketName }}". If not, please change "When there are security updates" and "When there are other updates" in the Updates of software-properties-gtk to "Display immediately", install the older firefox by `sudo apt install firefox=75.0+build3-0ubuntu1` and reboot the system to wait for the update-manager pop up automatically. | ||
623 | 12 | |||
624 | 13 | * After it installed {{ oemMetaPackage }} by update-manager and reboot the system, you should see the system booting from the {{ kernelMeta }} kernel. | ||
625 | 14 | |||
626 | 15 | [Where problems could occur] | ||
627 | 16 | |||
628 | 17 | * {{ oemMetaPackage }} is installed but it is not updated to the version in the corresponding OEM archive. | ||
629 | 18 | |||
630 | 19 | * The update-manager didn't show "Hardware support for {{ marketName }}" at all. | ||
631 | 20 | |||
632 | 21 | [Other Info] | ||
633 | 22 | |||
634 | 23 | * You can see all {{ oemMetaPackage }} versions on https://people.ubuntu.com/~fourdollars/oem-meta-packages/. | ||
635 | 24 | * I have used ppa:oem-solutions-engineers/oem-projects-meta to verify it before this SRU process. | ||
636 | diff --git a/oem_scripts/LaunchpadLogin.py b/oem_scripts/LaunchpadLogin.py | |||
637 | index 01bae8b..d2fa68e 100644 | |||
638 | --- a/oem_scripts/LaunchpadLogin.py | |||
639 | +++ b/oem_scripts/LaunchpadLogin.py | |||
640 | @@ -67,6 +67,9 @@ class LaunchpadLogin: | |||
641 | 67 | else: | 67 | else: |
642 | 68 | service_root = "production" | 68 | service_root = "production" |
643 | 69 | 69 | ||
644 | 70 | self.service_root = lookup_service_root(service_root) | ||
645 | 71 | self.service_version = version | ||
646 | 72 | |||
647 | 70 | oem_scripts_config_ini = os.path.join( | 73 | oem_scripts_config_ini = os.path.join( |
648 | 71 | os.environ["HOME"], ".config/oem-scripts/config.ini" | 74 | os.environ["HOME"], ".config/oem-scripts/config.ini" |
649 | 72 | ) | 75 | ) |
650 | diff --git a/oem_scripts/__init__.py b/oem_scripts/__init__.py | |||
651 | index 2bfacd2..4052759 100644 | |||
652 | --- a/oem_scripts/__init__.py | |||
653 | +++ b/oem_scripts/__init__.py | |||
654 | @@ -1 +1,31 @@ | |||
655 | 1 | __version__ = "1.11" | 1 | __version__ = "1.11" |
656 | 2 | |||
657 | 3 | ALLOWED_KERNEL_META_LIST = ( | ||
658 | 4 | "linux-oem-20.04c", | ||
659 | 5 | "linux-oem-20.04b", | ||
660 | 6 | "linux-oem-20.04", | ||
661 | 7 | "linux-generic-hwe-20.04", | ||
662 | 8 | ) | ||
663 | 9 | |||
664 | 10 | SUBSCRIBER_LIST = ("oem-solutions-engineers", "ubuntu-sponsors", "ubuntu-desktop") | ||
665 | 11 | |||
666 | 12 | TAG_LIST = ["oem-meta-packages", "oem-priority", f"oem-scripts-{__version__}"] | ||
667 | 13 | |||
668 | 14 | |||
669 | 15 | # Python 3.9 supports this. | ||
670 | 16 | def remove_prefix(s, prefix): | ||
671 | 17 | return s[len(prefix) :] if s.startswith(prefix) else s | ||
672 | 18 | |||
673 | 19 | |||
674 | 20 | def yes_or_ask(yes: bool, message: str) -> bool: | ||
675 | 21 | if yes: | ||
676 | 22 | print(f"> \033[1;34m{message}\033[1;0m (y/n) y") | ||
677 | 23 | return True | ||
678 | 24 | while True: | ||
679 | 25 | res = input(f"> \033[1;34m{message}\033[1;0m (y/n) ").lower() | ||
680 | 26 | if res not in {"y", "n"}: | ||
681 | 27 | continue | ||
682 | 28 | if res == "y": | ||
683 | 29 | return True | ||
684 | 30 | else: | ||
685 | 31 | return False | ||
686 | diff --git a/setup.py b/setup.py | |||
687 | index 81004d7..ace90b3 100644 | |||
688 | --- a/setup.py | |||
689 | +++ b/setup.py | |||
690 | @@ -34,6 +34,7 @@ Also there is a meta package oem-dev-tools that installs all scripts""", | |||
691 | 34 | author="Commercial Engineering", | 34 | author="Commercial Engineering", |
692 | 35 | author_email="commercial-engineering@canonical.com", | 35 | author_email="commercial-engineering@canonical.com", |
693 | 36 | scripts=[ | 36 | scripts=[ |
694 | 37 | "bootstrap-meta", | ||
695 | 37 | "copyPackage.py", | 38 | "copyPackage.py", |
696 | 38 | "get-oem-auth-token", | 39 | "get-oem-auth-token", |
697 | 39 | "get-oemshare-auth-token", | 40 | "get-oemshare-auth-token", |
[BOT] 1.12-5f2b26c- in-docker- focal-summary. log collect- credentials PASS oem-scripts- auto PASS merge-proposal PASS insteadof- setting PASS from-iso. sh PASS verification PASS /paste. ubuntu. com/p/b7GVnfyvk N/ oem-scripts- 1.12-5f2b26c- in-docker- focal-complete. log
$ cat oem-scripts-
autopkgtest-
autopkgtest-
pkg-somerville-meta PASS
pkg-stella-meta PASS
pkg-sutton-meta PASS
bootstrap-meta PASS
bug-bind PASS
get-private-ppa PASS
jq-lp PASS
launchpad-api PASS
lp-bug PASS
oem-meta-packages PASS
pkg-list PASS
review-
run-autopkgtest PASS
setup-apt-dir PASS
mir-bug SKIP exit status 77 and marked as skippable
git-url-
lp-dl-attm PASS
recovery-
mir-bug-
https:/