Merge ~fourdollars/pc-enablement/+git/oem-scripts:master into ~oem-solutions-engineers/pc-enablement/+git/oem-scripts: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)
Reviewer Review Type Date Requested Status
Yuan-Chen Cheng (community) Approve
Review via email: mp+408091@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Shih-Yuan Lee (fourdollars) wrote :

[BOT]
$ cat oem-scripts-1.12-5f2b26c-in-docker-focal-summary.log
autopkgtest-collect-credentials PASS
autopkgtest-oem-scripts-auto PASS
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-merge-proposal PASS
run-autopkgtest PASS
setup-apt-dir PASS
mir-bug SKIP exit status 77 and marked as skippable
git-url-insteadof-setting PASS
lp-dl-attm PASS
recovery-from-iso.sh PASS
mir-bug-verification PASS
https://paste.ubuntu.com/p/b7GVnfyvkN/ oem-scripts-1.12-5f2b26c-in-docker-focal-complete.log

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-engineers, ubuntu-desktop, etc, can we start to put those string into const variable, so that the source code editor will tell us we have typo.

I mean something like:

OEM_TEAM = "oem-solutions-engineers"

person=lp.people[OEM_TEAM]

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

Subscribers

People subscribed via source and target branches