Merge ~dannf/canonical-server-hwe-utils:pre-commit into canonical-server-hwe-utils:master
- Git
- lp:~dannf/canonical-server-hwe-utils
- pre-commit
- Merge into master
Proposed by
dann frazier
Status: | Merged |
---|---|
Approved by: | Alexandre Erwin Ittner |
Approved revision: | fe32deedec72a723de836d21e49b32632e8c742a |
Merged at revision: | fe32deedec72a723de836d21e49b32632e8c742a |
Proposed branch: | ~dannf/canonical-server-hwe-utils:pre-commit |
Merge into: | canonical-server-hwe-utils:master |
Diff against target: |
2123 lines (+790/-499) 18 files modified
.pre-commit-config.yaml (+10/-0) labkey (+95/-71) lp-scripts/LaunchpadBugBucketer.py (+5/-5) lp-scripts/bandera-bug-csv-summary.py (+8/-7) lp-scripts/bugreport/bugreport.py (+143/-81) lp-scripts/clone-project-milestones.py (+21/-18) lp-scripts/dump-bug-subscribers.py (+26/-14) lp-scripts/lp-bulk-action.py (+46/-41) lp-scripts/pearl-biweekly-bug-report-csv4.py (+87/-47) lp-scripts/pearl-biweekly-report-csv.py (+78/-40) lp-scripts/pearl-biweekly-report.csv.py (+93/-53) lp-scripts/pearl-bug-csv-summary.py (+8/-7) lp-scripts/pearl-risky-patch-schedule.py (+12/-10) lp-scripts/pearl2-biweekly-report.csv.py (+60/-44) lp-scripts/pearl2-d06-18.04-patch-status.py (+18/-13) lp-scripts/pearl2-tag-ubuntu-18.04.3-risky.py (+14/-10) lp-scripts/project-bug-lint.py (+54/-26) sysadmin-tools/gen_conserver_cf.py (+12/-12) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Alexandre Erwin Ittner | Approve | ||
Review via email:
|
Commit message
Description of the change
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml | |||
2 | 0 | new file mode 100644 | 0 | new file mode 100644 |
3 | index 0000000..5f7fa9a | |||
4 | --- /dev/null | |||
5 | +++ b/.pre-commit-config.yaml | |||
6 | @@ -0,0 +1,10 @@ | |||
7 | 1 | repos: | ||
8 | 2 | - repo: https://github.com/psf/black | ||
9 | 3 | rev: stable | ||
10 | 4 | hooks: | ||
11 | 5 | - id: black | ||
12 | 6 | language_version: python3.8 | ||
13 | 7 | - repo: https://gitlab.com/pycqa/flake8 | ||
14 | 8 | rev: master | ||
15 | 9 | hooks: | ||
16 | 10 | - id: flake8 | ||
17 | diff --git a/labkey b/labkey | |||
18 | index fe3f4ae..47f996b 100755 | |||
19 | --- a/labkey | |||
20 | +++ b/labkey | |||
21 | @@ -9,8 +9,8 @@ import sys | |||
22 | 9 | import yaml | 9 | import yaml |
23 | 10 | 10 | ||
24 | 11 | ProgName = "labkey" | 11 | ProgName = "labkey" |
27 | 12 | Config = os.path.join(os.environ['HOME'], '.config', ProgName) | 12 | Config = os.path.join(os.environ["HOME"], ".config", ProgName) |
28 | 13 | ScaleBotLocal = os.path.join(Config, 'scalebot-repo') | 13 | ScaleBotLocal = os.path.join(Config, "scalebot-repo") |
29 | 14 | 14 | ||
30 | 15 | 15 | ||
31 | 16 | def update(lpid, force): | 16 | def update(lpid, force): |
32 | @@ -22,34 +22,31 @@ def update(lpid, force): | |||
33 | 22 | shutil.rmtree(ScaleBotLocal) | 22 | shutil.rmtree(ScaleBotLocal) |
34 | 23 | 23 | ||
35 | 24 | ScaleBotRemote = "git+ssh://%sgit.launchpad.net/scalebot" % (user) | 24 | ScaleBotRemote = "git+ssh://%sgit.launchpad.net/scalebot" % (user) |
37 | 25 | umaskSav = os.umask(int('077', 8)) | 25 | umaskSav = os.umask(int("077", 8)) |
38 | 26 | if os.path.exists(ScaleBotLocal): | 26 | if os.path.exists(ScaleBotLocal): |
39 | 27 | os.chdir(ScaleBotLocal) | 27 | os.chdir(ScaleBotLocal) |
41 | 28 | subprocess.run(['git', 'pull'], check=True) | 28 | subprocess.run(["git", "pull"], check=True) |
42 | 29 | else: | 29 | else: |
46 | 30 | subprocess.run(['git', 'clone', | 30 | subprocess.run(["git", "clone", ScaleBotRemote, ScaleBotLocal], check=True) |
44 | 31 | ScaleBotRemote, ScaleBotLocal], | ||
45 | 32 | check=True) | ||
47 | 33 | os.umask(umaskSav) | 31 | os.umask(umaskSav) |
48 | 34 | 32 | ||
49 | 35 | 33 | ||
50 | 36 | def loadLabs(): | 34 | def loadLabs(): |
51 | 37 | config = [] | 35 | config = [] |
53 | 38 | labroot = os.path.join(ScaleBotLocal, 'labs') | 36 | labroot = os.path.join(ScaleBotLocal, "labs") |
54 | 39 | for labdir in os.scandir(labroot): | 37 | for labdir in os.scandir(labroot): |
55 | 40 | if not labdir.is_dir(): | 38 | if not labdir.is_dir(): |
56 | 41 | continue | 39 | continue |
57 | 42 | lab = None | 40 | lab = None |
58 | 43 | machines = None | 41 | machines = None |
59 | 44 | for f in os.scandir(labdir): | 42 | for f in os.scandir(labdir): |
62 | 45 | if f.name == 'lab.yaml': | 43 | if f.name == "lab.yaml": |
63 | 46 | with open(f.path, 'r') as stream: | 44 | with open(f.path, "r") as stream: |
64 | 47 | lab = yaml.load(stream, Loader=yaml.SafeLoader) | 45 | lab = yaml.load(stream, Loader=yaml.SafeLoader) |
67 | 48 | elif f.name == 'machines.yaml': | 46 | elif f.name == "machines.yaml": |
68 | 49 | with open(f.path, 'r') as stream: | 47 | with open(f.path, "r") as stream: |
69 | 50 | machines = yaml.load(stream, Loader=yaml.SafeLoader) | 48 | machines = yaml.load(stream, Loader=yaml.SafeLoader) |
72 | 51 | config.append({'lab': lab, | 49 | config.append({"lab": lab, "machines": machines}) |
71 | 52 | 'machines': machines}) | ||
73 | 53 | return config | 50 | return config |
74 | 54 | 51 | ||
75 | 55 | 52 | ||
76 | @@ -58,96 +55,123 @@ class Machine: | |||
77 | 58 | self.name = name | 55 | self.name = name |
78 | 59 | labs = loadLabs() | 56 | labs = loadLabs() |
79 | 60 | for lab in labs: | 57 | for lab in labs: |
81 | 61 | if lab['machines'] is None: | 58 | if lab["machines"] is None: |
82 | 62 | continue | 59 | continue |
86 | 63 | if name in lab['machines'].keys(): | 60 | if name in lab["machines"].keys(): |
87 | 64 | self.data = lab['machines'][name] | 61 | self.data = lab["machines"][name] |
88 | 65 | self.labdata = lab['lab'] | 62 | self.labdata = lab["lab"] |
89 | 66 | return | 63 | return |
91 | 67 | raise KeyError('Machine not found') | 64 | raise KeyError("Machine not found") |
92 | 68 | 65 | ||
93 | 69 | def __repr__(self): | 66 | def __repr__(self): |
94 | 70 | return yaml.dump(self.data, default_flow_style=False) | 67 | return yaml.dump(self.data, default_flow_style=False) |
95 | 71 | 68 | ||
96 | 72 | def _do_ipmitool(self, cmd): | 69 | def _do_ipmitool(self, cmd): |
104 | 73 | bmc = self.data['bmc'] | 70 | bmc = self.data["bmc"] |
105 | 74 | if bmc['type'] != "ipmi": | 71 | if bmc["type"] != "ipmi": |
106 | 75 | raise KeyError('Machine has unknown power type') | 72 | raise KeyError("Machine has unknown power type") |
107 | 76 | subprocess.run(['ipmitool', '-I', 'lanplus', | 73 | subprocess.run( |
108 | 77 | '-H', bmc['address'], | 74 | [ |
109 | 78 | '-U', bmc['user'], | 75 | "ipmitool", |
110 | 79 | '-P', bmc['password']] + cmd, check=True) | 76 | "-I", |
111 | 77 | "lanplus", | ||
112 | 78 | "-H", | ||
113 | 79 | bmc["address"], | ||
114 | 80 | "-U", | ||
115 | 81 | bmc["user"], | ||
116 | 82 | "-P", | ||
117 | 83 | bmc["password"], | ||
118 | 84 | ] | ||
119 | 85 | + cmd, | ||
120 | 86 | check=True, | ||
121 | 87 | ) | ||
122 | 80 | 88 | ||
123 | 81 | def mc_reset(self): | 89 | def mc_reset(self): |
125 | 82 | cmd = ['mc', 'reset', 'cold'] | 90 | cmd = ["mc", "reset", "cold"] |
126 | 83 | self._do_ipmitool(cmd) | 91 | self._do_ipmitool(cmd) |
127 | 84 | 92 | ||
128 | 85 | def power(self, state): | 93 | def power(self, state): |
130 | 86 | cmd = ['chassis', 'power', state] | 94 | cmd = ["chassis", "power", state] |
131 | 87 | self._do_ipmitool(cmd) | 95 | self._do_ipmitool(cmd) |
132 | 88 | 96 | ||
133 | 89 | def open_console(self): | 97 | def open_console(self): |
135 | 90 | ''' | 98 | """ |
136 | 91 | Open an interactive console session to the machine. | 99 | Open an interactive console session to the machine. |
137 | 92 | Currently only supports conserver. | 100 | Currently only supports conserver. |
139 | 93 | ''' | 101 | """ |
140 | 94 | if self.labdata is None: | 102 | if self.labdata is None: |
159 | 95 | raise KeyError('No lab.yaml associated with %s' % (self.name)) | 103 | raise KeyError("No lab.yaml associated with %s" % (self.name)) |
160 | 96 | if 'conserver' not in self.labdata.keys(): | 104 | if "conserver" not in self.labdata.keys(): |
161 | 97 | raise KeyError('No conserver defined for lab %s' % | 105 | raise KeyError("No conserver defined for lab %s" % (self.labdata["name"])) |
162 | 98 | (self.labdata['name'])) | 106 | concfg = self.labdata["conserver"] |
163 | 99 | concfg = self.labdata['conserver'] | 107 | subprocess.run( |
164 | 100 | subprocess.run(['console', '-M%s' % (concfg['master']), | 108 | [ |
165 | 101 | '-p%s' % (concfg['port']), | 109 | "console", |
166 | 102 | self.name], | 110 | "-M%s" % (concfg["master"]), |
167 | 103 | stdin=sys.stdin, stdout=sys.stdout, stderr=sys.stderr) | 111 | "-p%s" % (concfg["port"]), |
168 | 104 | subprocess.run(['console', '-M%s' % (concfg['master']), | 112 | self.name, |
169 | 105 | '-p%s' % (concfg['port']), | 113 | ], |
170 | 106 | self.name], | 114 | stdin=sys.stdin, |
171 | 107 | capture_output=True) | 115 | stdout=sys.stdout, |
172 | 108 | 116 | stderr=sys.stderr, | |
173 | 109 | 117 | ) | |
174 | 110 | if __name__ == '__main__': | 118 | subprocess.run( |
175 | 111 | power_cmds = ['on', 'off', 'cycle', 'mc-reset', 'reset', 'status'] | 119 | [ |
176 | 112 | machine_cmds = power_cmds + ['console', 'show'] | 120 | "console", |
177 | 121 | "-M%s" % (concfg["master"]), | ||
178 | 122 | "-p%s" % (concfg["port"]), | ||
179 | 123 | self.name, | ||
180 | 124 | ], | ||
181 | 125 | capture_output=True, | ||
182 | 126 | ) | ||
183 | 127 | |||
184 | 128 | |||
185 | 129 | if __name__ == "__main__": | ||
186 | 130 | power_cmds = ["on", "off", "cycle", "mc-reset", "reset", "status"] | ||
187 | 131 | machine_cmds = power_cmds + ["console", "show"] | ||
188 | 113 | cmd_help = { | 132 | cmd_help = { |
198 | 114 | 'show': "Show machine configuration", | 133 | "show": "Show machine configuration", |
199 | 115 | 'on': "Power machine on", | 134 | "on": "Power machine on", |
200 | 116 | 'off': "Power machine off", | 135 | "off": "Power machine off", |
201 | 117 | 'cycle': "Power cycle machine", | 136 | "cycle": "Power cycle machine", |
202 | 118 | 'mc-reset': "Perform cold reset of BMC", | 137 | "mc-reset": "Perform cold reset of BMC", |
203 | 119 | 'reset': "Hard reset machine", | 138 | "reset": "Hard reset machine", |
204 | 120 | 'console': "Open a console session", | 139 | "console": "Open a console session", |
205 | 121 | 'status': "Show machine power status", | 140 | "status": "Show machine power status", |
206 | 122 | 'update': "Update cached machine information", | 141 | "update": "Update cached machine information", |
207 | 123 | } | 142 | } |
208 | 124 | 143 | ||
210 | 125 | d = 'Do things with machines in ScaleBot labs' | 144 | d = "Do things with machines in ScaleBot labs" |
211 | 126 | parser = argparse.ArgumentParser(prog=ProgName, description=d) | 145 | parser = argparse.ArgumentParser(prog=ProgName, description=d) |
220 | 127 | subparsers = parser.add_subparsers(help='sub-command help') | 146 | subparsers = parser.add_subparsers(help="sub-command help") |
221 | 128 | update_parser = subparsers.add_parser('update', help=cmd_help['update']) | 147 | update_parser = subparsers.add_parser("update", help=cmd_help["update"]) |
222 | 129 | update_parser.add_argument('-u', dest='lpid', metavar='LPID', | 148 | update_parser.add_argument( |
223 | 130 | required=False, help="Launchpad ID") | 149 | "-u", dest="lpid", metavar="LPID", required=False, help="Launchpad ID" |
224 | 131 | update_parser.add_argument('-f', dest='force', action='store_true', | 150 | ) |
225 | 132 | required=False, | 151 | update_parser.add_argument( |
226 | 133 | help="Flush machine cache before update") | 152 | "-f", |
227 | 134 | update_parser.set_defaults(cmd='update') | 153 | dest="force", |
228 | 154 | action="store_true", | ||
229 | 155 | required=False, | ||
230 | 156 | help="Flush machine cache before update", | ||
231 | 157 | ) | ||
232 | 158 | update_parser.set_defaults(cmd="update") | ||
233 | 135 | for a in machine_cmds: | 159 | for a in machine_cmds: |
234 | 136 | action_parser = subparsers.add_parser(a, help=cmd_help[a]) | 160 | action_parser = subparsers.add_parser(a, help=cmd_help[a]) |
236 | 137 | action_parser.add_argument('machine', metavar='MACHINE') | 161 | action_parser.add_argument("machine", metavar="MACHINE") |
237 | 138 | action_parser.set_defaults(cmd=a) | 162 | action_parser.set_defaults(cmd=a) |
238 | 139 | args = parser.parse_args() | 163 | args = parser.parse_args() |
239 | 140 | 164 | ||
241 | 141 | if args.cmd == 'update': | 165 | if args.cmd == "update": |
242 | 142 | update(lpid=args.lpid, force=args.force) | 166 | update(lpid=args.lpid, force=args.force) |
243 | 143 | sys.exit(0) | 167 | sys.exit(0) |
244 | 144 | 168 | ||
245 | 145 | m = Machine(args.machine) | 169 | m = Machine(args.machine) |
247 | 146 | if args.cmd == 'show': | 170 | if args.cmd == "show": |
248 | 147 | print(m) | 171 | print(m) |
250 | 148 | elif args.cmd == 'mc-reset': | 172 | elif args.cmd == "mc-reset": |
251 | 149 | m.mc_reset() | 173 | m.mc_reset() |
253 | 150 | elif args.cmd == 'console': | 174 | elif args.cmd == "console": |
254 | 151 | m.open_console() | 175 | m.open_console() |
255 | 152 | elif args.cmd in power_cmds: | 176 | elif args.cmd in power_cmds: |
256 | 153 | m.power(args.cmd) | 177 | m.power(args.cmd) |
257 | diff --git a/lp-scripts/LaunchpadBugBucketer.py b/lp-scripts/LaunchpadBugBucketer.py | |||
258 | index 7831132..81e9e99 100644 | |||
259 | --- a/lp-scripts/LaunchpadBugBucketer.py | |||
260 | +++ b/lp-scripts/LaunchpadBugBucketer.py | |||
261 | @@ -49,7 +49,7 @@ class LaunchpadBugBucketer(collections.UserDict): | |||
262 | 49 | requiredTags (:obj:`list` of :obj:`str`): Only bucket bugs that | 49 | requiredTags (:obj:`list` of :obj:`str`): Only bucket bugs that |
263 | 50 | have one or more tags from this list. | 50 | have one or more tags from this list. |
264 | 51 | """ | 51 | """ |
266 | 52 | self.lp = Launchpad.login_with('lpbugs', 'production', version='devel') | 52 | self.lp = Launchpad.login_with("lpbugs", "production", version="devel") |
267 | 53 | self.project = self.lp.projects[project] | 53 | self.project = self.lp.projects[project] |
268 | 54 | self.series = series | 54 | self.series = series |
269 | 55 | self.requiredTags = requiredTags | 55 | self.requiredTags = requiredTags |
270 | @@ -57,8 +57,8 @@ class LaunchpadBugBucketer(collections.UserDict): | |||
271 | 57 | collections.UserDict.__init__(self, self.buckets) | 57 | collections.UserDict.__init__(self, self.buckets) |
272 | 58 | 58 | ||
273 | 59 | def taskToBug(self, task): | 59 | def taskToBug(self, task): |
276 | 60 | bugid = int(task.self_link.split('/')[-1]) | 60 | bugid = int(task.self_link.split("/")[-1]) |
277 | 61 | return(self.lp.bugs[bugid]) | 61 | return self.lp.bugs[bugid] |
278 | 62 | 62 | ||
279 | 63 | def _doBucketing(self): | 63 | def _doBucketing(self): |
280 | 64 | methods = inspect.getmembers(self, predicate=inspect.ismethod) | 64 | methods = inspect.getmembers(self, predicate=inspect.ismethod) |
281 | @@ -72,10 +72,10 @@ class LaunchpadBugBucketer(collections.UserDict): | |||
282 | 72 | if not set(self.requiredTags) & set(bug.tags): | 72 | if not set(self.requiredTags) & set(bug.tags): |
283 | 73 | continue | 73 | continue |
284 | 74 | for mName, mFunc in methods: | 74 | for mName, mFunc in methods: |
286 | 75 | if not mName.startswith('is_'): | 75 | if not mName.startswith("is_"): |
287 | 76 | continue | 76 | continue |
288 | 77 | if mFunc(task): | 77 | if mFunc(task): |
290 | 78 | b = mName[len('is_'):] | 78 | b = mName[len("is_") :] |
291 | 79 | if b not in self.buckets.keys(): | 79 | if b not in self.buckets.keys(): |
292 | 80 | self.buckets[b] = [] | 80 | self.buckets[b] = [] |
293 | 81 | self.buckets[b].append(task) | 81 | self.buckets[b].append(task) |
294 | diff --git a/lp-scripts/bandera-bug-csv-summary.py b/lp-scripts/bandera-bug-csv-summary.py | |||
295 | index 1fae696..05f84aa 100755 | |||
296 | --- a/lp-scripts/bandera-bug-csv-summary.py | |||
297 | +++ b/lp-scripts/bandera-bug-csv-summary.py | |||
298 | @@ -7,18 +7,19 @@ from LaunchpadBugBucketer import LaunchpadBugBucketer | |||
299 | 7 | 7 | ||
300 | 8 | class BanderaBugBucketer(LaunchpadBugBucketer): | 8 | class BanderaBugBucketer(LaunchpadBugBucketer): |
301 | 9 | def __init__(self): | 9 | def __init__(self): |
304 | 10 | LaunchpadBugBucketer.__init__(self, 'bandera', 'ubuntu-16.04', | 10 | LaunchpadBugBucketer.__init__( |
305 | 11 | requiredTags=['patchset']) | 11 | self, "bandera", "ubuntu-16.04", requiredTags=["patchset"] |
306 | 12 | ) | ||
307 | 12 | 13 | ||
308 | 13 | def is_green(self, task): | 14 | def is_green(self, task): |
310 | 14 | if task.status in ['Fix Committed', 'Fix Released']: | 15 | if task.status in ["Fix Committed", "Fix Released"]: |
311 | 15 | return True | 16 | return True |
312 | 16 | return False | 17 | return False |
313 | 17 | 18 | ||
314 | 18 | def is_amber(self, task): | 19 | def is_amber(self, task): |
315 | 19 | if self.is_green(task): | 20 | if self.is_green(task): |
316 | 20 | return False | 21 | return False |
318 | 21 | elif task.milestone and task.milestone.name == 'ubuntu-16.04.3': | 22 | elif task.milestone and task.milestone.name == "ubuntu-16.04.3": |
319 | 22 | return True | 23 | return True |
320 | 23 | return False | 24 | return False |
321 | 24 | 25 | ||
322 | @@ -28,16 +29,16 @@ class BanderaBugBucketer(LaunchpadBugBucketer): | |||
323 | 28 | return True | 29 | return True |
324 | 29 | 30 | ||
325 | 30 | 31 | ||
327 | 31 | if __name__ == '__main__': | 32 | if __name__ == "__main__": |
328 | 32 | parser = argparse.ArgumentParser() | 33 | parser = argparse.ArgumentParser() |
329 | 33 | parser.add_argument("-o", "--outfile") | 34 | parser.add_argument("-o", "--outfile") |
330 | 34 | args = parser.parse_args() | 35 | args = parser.parse_args() |
331 | 35 | 36 | ||
332 | 36 | s = BanderaBugBucketer() | 37 | s = BanderaBugBucketer() |
333 | 37 | 38 | ||
335 | 38 | with open(args.outfile, 'w') as csvfile: | 39 | with open(args.outfile, "w") as csvfile: |
336 | 39 | c = csv.writer(csvfile) | 40 | c = csv.writer(csvfile) |
338 | 40 | c.writerow(['Title', 'Bug ID', 'Importance', 'Status', 'RAG Risk']) | 41 | c.writerow(["Title", "Bug ID", "Importance", "Status", "RAG Risk"]) |
339 | 41 | for bucket in s.keys(): | 42 | for bucket in s.keys(): |
340 | 42 | for task in s[bucket]: | 43 | for task in s[bucket]: |
341 | 43 | bug = s.taskToBug(task) | 44 | bug = s.taskToBug(task) |
342 | diff --git a/lp-scripts/bugreport/bugreport.py b/lp-scripts/bugreport/bugreport.py | |||
343 | index bc347b9..ca9b5b1 100755 | |||
344 | --- a/lp-scripts/bugreport/bugreport.py | |||
345 | +++ b/lp-scripts/bugreport/bugreport.py | |||
346 | @@ -3,7 +3,6 @@ | |||
347 | 3 | # License: GPLv3 | 3 | # License: GPLv3 |
348 | 4 | from launchpadlib.launchpad import Launchpad | 4 | from launchpadlib.launchpad import Launchpad |
349 | 5 | from launchpadlib.uris import LPNET_SERVICE_ROOT | 5 | from launchpadlib.uris import LPNET_SERVICE_ROOT |
350 | 6 | from launchpadlib.credentials import Credentials | ||
351 | 7 | from optparse import OptionParser | 6 | from optparse import OptionParser |
352 | 8 | from re import compile | 7 | from re import compile |
353 | 9 | from datetime import datetime as dt | 8 | from datetime import datetime as dt |
354 | @@ -16,7 +15,7 @@ import sys | |||
355 | 16 | def gen_bug_report(lp, lp_bugs, project, verbose): | 15 | def gen_bug_report(lp, lp_bugs, project, verbose): |
356 | 17 | bug_summary_info = coldict(dict) | 16 | bug_summary_info = coldict(dict) |
357 | 18 | bug_details_info = coldict(dict) | 17 | bug_details_info = coldict(dict) |
359 | 19 | url = compile('https://api.launchpad.net/1.0/~|/') | 18 | url = compile("https://api.launchpad.net/1.0/~|/") |
360 | 20 | 19 | ||
361 | 21 | for task in lp_bugs: | 20 | for task in lp_bugs: |
362 | 22 | bug_info = {} | 21 | bug_info = {} |
363 | @@ -27,13 +26,13 @@ def gen_bug_report(lp, lp_bugs, project, verbose): | |||
364 | 27 | else: | 26 | else: |
365 | 28 | bug_summary_info[task.importance][task.status] = 1 | 27 | bug_summary_info[task.importance][task.status] = 1 |
366 | 29 | 28 | ||
369 | 30 | if '#Bugs Processed' in bug_summary_info[task.importance]: | 29 | if "#Bugs Processed" in bug_summary_info[task.importance]: |
370 | 31 | bug_summary_info[task.importance]['#Bugs Processed'] += 1 | 30 | bug_summary_info[task.importance]["#Bugs Processed"] += 1 |
371 | 32 | else: | 31 | else: |
373 | 33 | bug_summary_info[task.importance]['#Bugs Processed'] = 1 | 32 | bug_summary_info[task.importance]["#Bugs Processed"] = 1 |
374 | 34 | 33 | ||
377 | 35 | if '#Bugs Closed' not in bug_summary_info[task.importance]: | 34 | if "#Bugs Closed" not in bug_summary_info[task.importance]: |
378 | 36 | bug_summary_info[task.importance]['#Bugs Closed'] = 0 | 35 | bug_summary_info[task.importance]["#Bugs Closed"] = 0 |
379 | 37 | 36 | ||
380 | 38 | # A bug could affect multiple projects, we care only whether | 37 | # A bug could affect multiple projects, we care only whether |
381 | 39 | # the project we are tracking is complete. | 38 | # the project we are tracking is complete. |
382 | @@ -42,33 +41,40 @@ def gen_bug_report(lp, lp_bugs, project, verbose): | |||
383 | 42 | if bugtask.bug_target_name in project: | 41 | if bugtask.bug_target_name in project: |
384 | 43 | bug_is_complete = bugtask.is_complete | 42 | bug_is_complete = bugtask.is_complete |
385 | 44 | if verbose is True: | 43 | if verbose is True: |
388 | 45 | bug_subtask.append( | 44 | bug_subtask.append("%s: %s" % (bugtask.bug_target_name, bugtask.status)) |
387 | 46 | '%s: %s' % (bugtask.bug_target_name, bugtask.status)) | ||
389 | 47 | 45 | ||
390 | 48 | if bug_is_complete is True: | 46 | if bug_is_complete is True: |
393 | 49 | if '#Bugs Closed' in bug_summary_info[task.importance]: | 47 | if "#Bugs Closed" in bug_summary_info[task.importance]: |
394 | 50 | bug_summary_info[task.importance]['#Bugs Closed'] += 1 | 48 | bug_summary_info[task.importance]["#Bugs Closed"] += 1 |
395 | 51 | 49 | ||
396 | 52 | if verbose is True: | 50 | if verbose is True: |
397 | 53 | inactive_days = 0 | 51 | inactive_days = 0 |
398 | 54 | if bug_is_complete is not True: | 52 | if bug_is_complete is not True: |
399 | 55 | inactive_days = np.busday_count( | 53 | inactive_days = np.busday_count( |
400 | 56 | task.bug.date_last_updated.strftime("%Y-%m-%d"), | 54 | task.bug.date_last_updated.strftime("%Y-%m-%d"), |
402 | 57 | dt.now().strftime("%Y-%m-%d")) | 55 | dt.now().strftime("%Y-%m-%d"), |
403 | 56 | ) | ||
404 | 58 | 57 | ||
405 | 59 | active_days = np.busday_count( | 58 | active_days = np.busday_count( |
406 | 60 | task.bug.date_created.strftime("%Y-%m-%d"), | 59 | task.bug.date_created.strftime("%Y-%m-%d"), |
408 | 61 | task.bug.date_last_updated.strftime("%Y-%m-%d")) | 60 | task.bug.date_last_updated.strftime("%Y-%m-%d"), |
409 | 61 | ) | ||
410 | 62 | 62 | ||
413 | 63 | assignee = 'Unassigned' if task.assignee_link is None \ | 63 | assignee = ( |
414 | 64 | else url.sub('', task.assignee_link) | 64 | "Unassigned" |
415 | 65 | if task.assignee_link is None | ||
416 | 66 | else url.sub("", task.assignee_link) | ||
417 | 67 | ) | ||
418 | 65 | 68 | ||
419 | 66 | bug_info[task.bug.id] = [ | 69 | bug_info[task.bug.id] = [ |
420 | 67 | task.bug.date_created.strftime("%Y-%m-%d"), | 70 | task.bug.date_created.strftime("%Y-%m-%d"), |
425 | 68 | task.bug.date_last_updated.strftime("%Y-%m-%d"), | 71 | task.bug.date_last_updated.strftime("%Y-%m-%d"), |
426 | 69 | active_days, | 72 | active_days, |
427 | 70 | inactive_days, task.bug.message_count, assignee, | 73 | inactive_days, |
428 | 71 | "''<br>''".join(bug_subtask)] | 74 | task.bug.message_count, |
429 | 75 | assignee, | ||
430 | 76 | "''<br>''".join(bug_subtask), | ||
431 | 77 | ] | ||
432 | 72 | 78 | ||
433 | 73 | bug_details_info[task.importance].update(bug_info) | 79 | bug_details_info[task.importance].update(bug_info) |
434 | 74 | 80 | ||
435 | @@ -76,95 +82,151 @@ def gen_bug_report(lp, lp_bugs, project, verbose): | |||
436 | 76 | 82 | ||
437 | 77 | 83 | ||
438 | 78 | def main(): | 84 | def main(): |
468 | 79 | parser = OptionParser(usage='usage: %prog [options]', version='%prog 1.0') | 85 | parser = OptionParser(usage="usage: %prog [options]", version="%prog 1.0") |
469 | 80 | parser.add_option('-d', '--date', dest='start_date', action='store', | 86 | parser.add_option( |
470 | 81 | default='2017-01-01', | 87 | "-d", |
471 | 82 | type='string', help='start date for bug search') | 88 | "--date", |
472 | 83 | parser.add_option('-p', '--project', dest='project', action='store', | 89 | dest="start_date", |
473 | 84 | default='ubuntu-power-systems', | 90 | action="store", |
474 | 85 | type='string', help='name of the launchpad project') | 91 | default="2017-01-01", |
475 | 86 | parser.add_option('-s', '--status', dest='bug_status', action='store', | 92 | type="string", |
476 | 87 | default=('New,Opinion,Invalid,Won\'t Fix,Expired,' | 93 | help="start date for bug search", |
477 | 88 | 'Confirmed,Triaged,In Progress,Fix Committed,' | 94 | ) |
478 | 89 | 'Fix Released,Incomplete'), | 95 | parser.add_option( |
479 | 90 | type='string', | 96 | "-p", |
480 | 91 | help='bug status (or quoted and comma seperated list)') | 97 | "--project", |
481 | 92 | parser.add_option('-i', '--importance', dest='bug_importance', | 98 | dest="project", |
482 | 93 | default=( | 99 | action="store", |
483 | 94 | 'Unknown,Undecided,Critical,High,Medium,Low,Wishlist'), | 100 | default="ubuntu-power-systems", |
484 | 95 | type='string', | 101 | type="string", |
485 | 96 | help='bug importance (or comma seperated list, no spaces)') | 102 | help="name of the launchpad project", |
486 | 97 | parser.add_option('-t', '--tag', dest='bug_tag', default=None, | 103 | ) |
487 | 98 | help='bug tag (or quoted and comma seperated list)') | 104 | parser.add_option( |
488 | 99 | parser.add_option('-m', '--modify', dest='bug_tag_modify', default='Any', | 105 | "-s", |
489 | 100 | help='search any or all tags (valid args: any or all)') | 106 | "--status", |
490 | 101 | parser.add_option('-v', '--verbose', dest='verbose', action='store_true', | 107 | dest="bug_status", |
491 | 102 | help='verbose output with bug details') | 108 | action="store", |
492 | 103 | parser.add_option('-a', '--author', dest='author', | 109 | default=( |
493 | 104 | default='Manoj Iyer manoj.iyer@canonical.com', | 110 | "New,Opinion,Invalid,Won't Fix,Expired," |
494 | 105 | help='"Firstname Lastname first.last@canonical.com"') | 111 | "Confirmed,Triaged,In Progress,Fix Committed," |
495 | 106 | parser.add_option('-o', '--outfile', dest='outfile', | 112 | "Fix Released,Incomplete" |
496 | 107 | help='filename to store output (default stdout)') | 113 | ), |
497 | 114 | type="string", | ||
498 | 115 | help="bug status (or quoted and comma seperated list)", | ||
499 | 116 | ) | ||
500 | 117 | parser.add_option( | ||
501 | 118 | "-i", | ||
502 | 119 | "--importance", | ||
503 | 120 | dest="bug_importance", | ||
504 | 121 | default=("Unknown,Undecided,Critical,High,Medium,Low,Wishlist"), | ||
505 | 122 | type="string", | ||
506 | 123 | help="bug importance (or comma seperated list, no spaces)", | ||
507 | 124 | ) | ||
508 | 125 | parser.add_option( | ||
509 | 126 | "-t", | ||
510 | 127 | "--tag", | ||
511 | 128 | dest="bug_tag", | ||
512 | 129 | default=None, | ||
513 | 130 | help="bug tag (or quoted and comma seperated list)", | ||
514 | 131 | ) | ||
515 | 132 | parser.add_option( | ||
516 | 133 | "-m", | ||
517 | 134 | "--modify", | ||
518 | 135 | dest="bug_tag_modify", | ||
519 | 136 | default="Any", | ||
520 | 137 | help="search any or all tags (valid args: any or all)", | ||
521 | 138 | ) | ||
522 | 139 | parser.add_option( | ||
523 | 140 | "-v", | ||
524 | 141 | "--verbose", | ||
525 | 142 | dest="verbose", | ||
526 | 143 | action="store_true", | ||
527 | 144 | help="verbose output with bug details", | ||
528 | 145 | ) | ||
529 | 146 | parser.add_option( | ||
530 | 147 | "-a", | ||
531 | 148 | "--author", | ||
532 | 149 | dest="author", | ||
533 | 150 | default="Manoj Iyer manoj.iyer@canonical.com", | ||
534 | 151 | help='"Firstname Lastname first.last@canonical.com"', | ||
535 | 152 | ) | ||
536 | 153 | parser.add_option( | ||
537 | 154 | "-o", | ||
538 | 155 | "--outfile", | ||
539 | 156 | dest="outfile", | ||
540 | 157 | help="filename to store output (default stdout)", | ||
541 | 158 | ) | ||
542 | 108 | 159 | ||
543 | 109 | (options, args) = parser.parse_args() | 160 | (options, args) = parser.parse_args() |
544 | 110 | 161 | ||
545 | 111 | if len(args) is None: | 162 | if len(args) is None: |
546 | 112 | parser.error("No arguments found!") | 163 | parser.error("No arguments found!") |
547 | 113 | 164 | ||
550 | 114 | script_name = sys.argv[0].split("/")[-1].split('.')[0] | 165 | script_name = sys.argv[0].split("/")[-1].split(".")[0] |
551 | 115 | cachedir = os.path.expanduser('~/.launchpadlib/cache') | 166 | cachedir = os.path.expanduser("~/.launchpadlib/cache") |
552 | 116 | 167 | ||
553 | 117 | launchpad = Launchpad.login_with(script_name, LPNET_SERVICE_ROOT, cachedir) | 168 | launchpad = Launchpad.login_with(script_name, LPNET_SERVICE_ROOT, cachedir) |
554 | 118 | lp_project = launchpad.projects[options.project] | 169 | lp_project = launchpad.projects[options.project] |
555 | 119 | 170 | ||
556 | 120 | lp_bugs = [ | 171 | lp_bugs = [ |
572 | 121 | task for task in lp_project.searchTasks( | 172 | task |
573 | 122 | created_since=None if options.start_date is None else | 173 | for task in lp_project.searchTasks( |
574 | 123 | dt.strptime(options.start_date, | 174 | created_since=None |
575 | 124 | '%Y-%m-%d').isoformat(), | 175 | if options.start_date is None |
576 | 125 | status=options.bug_status.split(','), | 176 | else dt.strptime(options.start_date, "%Y-%m-%d").isoformat(), |
577 | 126 | importance=options.bug_importance.title().replace( | 177 | status=options.bug_status.split(","), |
578 | 127 | ' ', '').split(','), | 178 | importance=options.bug_importance.title().replace(" ", "").split(","), |
579 | 128 | tags=None if options.bug_tag is None else | 179 | tags=None if options.bug_tag is None else options.bug_tag.split(","), |
580 | 129 | options.bug_tag.split(','), | 180 | tags_combinator=options.bug_tag_modify.title(), |
581 | 130 | tags_combinator=options.bug_tag_modify.title())] | 181 | ) |
582 | 131 | 182 | ] | |
583 | 132 | with (open(options.outfile, 'w') if options.outfile else sys.stdout) as f: | 183 | |
584 | 133 | f.write("Bug activity in %s project since %s\n\n\n" % (options.project, | 184 | with (open(options.outfile, "w") if options.outfile else sys.stdout) as f: |
585 | 134 | options.start_date)) | 185 | f.write( |
586 | 135 | f.write(" || {:<35} | {:<20} |\n".format('Created By', 'Date')) | 186 | "Bug activity in %s project since %s\n\n\n" |
587 | 187 | % (options.project, options.start_date) | ||
588 | 188 | ) | ||
589 | 189 | f.write(" || {:<35} | {:<20} |\n".format("Created By", "Date")) | ||
590 | 136 | f.write(" | [%s]" % (options.author) + " | %%mtime(%A %B %d, %Y) |\n") | 190 | f.write(" | [%s]" % (options.author) + " | %%mtime(%A %B %d, %Y) |\n") |
591 | 137 | 191 | ||
592 | 138 | if f is not sys.stdout and options.verbose is True: | 192 | if f is not sys.stdout and options.verbose is True: |
597 | 139 | sys.stdout.write("Bug activity in %s project since %s\n" % | 193 | sys.stdout.write( |
598 | 140 | (options.project, options.start_date)) | 194 | "Bug activity in %s project since %s\n" |
599 | 141 | sys.stdout.write("Generating detailed report in %s \n" % | 195 | % (options.project, options.start_date) |
600 | 142 | options.outfile) | 196 | ) |
601 | 197 | sys.stdout.write("Generating detailed report in %s \n" % options.outfile) | ||
602 | 143 | sys.stdout.write("Please wait...\n") | 198 | sys.stdout.write("Please wait...\n") |
603 | 144 | sys.stdout.flush() | 199 | sys.stdout.flush() |
604 | 145 | 200 | ||
608 | 146 | summary_report, detailed_report = gen_bug_report(launchpad, lp_bugs, | 201 | summary_report, detailed_report = gen_bug_report( |
609 | 147 | options.project, | 202 | launchpad, lp_bugs, options.project, options.verbose |
610 | 148 | options.verbose) | 203 | ) |
611 | 149 | 204 | ||
612 | 150 | for k, v in sorted(summary_report.iteritems()): | 205 | for k, v in sorted(summary_report.iteritems()): |
613 | 151 | f.write("\n= Summary of %s bugs =\n" % k) | 206 | f.write("\n= Summary of %s bugs =\n" % k) |
615 | 152 | f.write("|| {:<14} | {:<8} |\n".format('Status', 'Count')) | 207 | f.write("|| {:<14} | {:<8} |\n".format("Status", "Count")) |
616 | 153 | for x, y in sorted(v.iteritems()): | 208 | for x, y in sorted(v.iteritems()): |
617 | 154 | f.write("| {:<15} | {:<8} |\n".format(x, y)) | 209 | f.write("| {:<15} | {:<8} |\n".format(x, y)) |
618 | 155 | if options.verbose is True: | 210 | if options.verbose is True: |
619 | 156 | f.write("== Details on %s bugs ==\n" % k) | 211 | f.write("== Details on %s bugs ==\n" % k) |
627 | 157 | f.write("|| Bug# | Created | Last Updated | Active Period " | 212 | f.write( |
628 | 158 | "| Dormant Period | #Comments | Assignee | Status |\n") | 213 | "|| Bug# | Created | Last Updated | Active Period " |
629 | 159 | 214 | "| Dormant Period | #Comments | Assignee | Status |\n" | |
630 | 160 | for a, b in sorted(detailed_report[k].iteritems(), | 215 | ) |
631 | 161 | key=lambda item: item[1][1], reverse=True): | 216 | |
632 | 162 | f.write("| [%s https://launchpad.net/bugs/%s] | %s |\n" % | 217 | for a, b in sorted( |
633 | 163 | (a, a, ' | '.join(map(str, b)))) | 218 | detailed_report[k].iteritems(), |
634 | 219 | key=lambda item: item[1][1], | ||
635 | 220 | reverse=True, | ||
636 | 221 | ): | ||
637 | 222 | f.write( | ||
638 | 223 | "| [%s https://launchpad.net/bugs/%s] | %s |\n" | ||
639 | 224 | % (a, a, " | ".join(map(str, b))) | ||
640 | 225 | ) | ||
641 | 164 | 226 | ||
642 | 165 | if f is not sys.stdout: | 227 | if f is not sys.stdout: |
643 | 166 | f.close() | 228 | f.close() |
644 | 167 | 229 | ||
645 | 168 | 230 | ||
647 | 169 | if __name__ == '__main__': | 231 | if __name__ == "__main__": |
648 | 170 | main() | 232 | main() |
649 | diff --git a/lp-scripts/clone-project-milestones.py b/lp-scripts/clone-project-milestones.py | |||
650 | index b0783d2..39099ab 100755 | |||
651 | --- a/lp-scripts/clone-project-milestones.py | |||
652 | +++ b/lp-scripts/clone-project-milestones.py | |||
653 | @@ -10,11 +10,11 @@ from launchpadlib.launchpad import Launchpad | |||
654 | 10 | 10 | ||
655 | 11 | 11 | ||
656 | 12 | # These may contain proprietary content, skip them | 12 | # These may contain proprietary content, skip them |
658 | 13 | IgnoredSeries = ['firmware', 'ppa-uose', 'silicon', 'trunk'] | 13 | IgnoredSeries = ["firmware", "ppa-uose", "silicon", "trunk"] |
659 | 14 | 14 | ||
660 | 15 | 15 | ||
661 | 16 | def clone_project_milestones(src, dest, dry_run): | 16 | def clone_project_milestones(src, dest, dry_run): |
663 | 17 | lp = Launchpad.login_with('lpbugs', 'production', version='devel') | 17 | lp = Launchpad.login_with("lpbugs", "production", version="devel") |
664 | 18 | src_project = lp.projects[src] | 18 | src_project = lp.projects[src] |
665 | 19 | dest_project = lp.projects[dest] | 19 | dest_project = lp.projects[dest] |
666 | 20 | for src_series in src_project.series: | 20 | for src_series in src_project.series: |
667 | @@ -22,46 +22,49 @@ def clone_project_milestones(src, dest, dry_run): | |||
668 | 22 | continue | 22 | continue |
669 | 23 | dest_series = dest_project.getSeries(name=src_series.name) | 23 | dest_series = dest_project.getSeries(name=src_series.name) |
670 | 24 | if dest_series: | 24 | if dest_series: |
673 | 25 | logger.warning("Series %s already exists, skipping\n" % | 25 | logger.warning("Series %s already exists, skipping\n" % (dest_series)) |
672 | 26 | (dest_series)) | ||
674 | 27 | else: | 26 | else: |
675 | 28 | logger.info("Creating series %s" % (src_series.name)) | 27 | logger.info("Creating series %s" % (src_series.name)) |
676 | 29 | if not dry_run: | 28 | if not dry_run: |
677 | 30 | dest_series = dest_project.newSeries( | 29 | dest_series = dest_project.newSeries( |
680 | 31 | name=src_series.name, | 30 | name=src_series.name, summary=src_series.summary |
681 | 32 | summary=src_series.summary) | 31 | ) |
682 | 33 | for src_milestone in src_series.all_milestones: | 32 | for src_milestone in src_series.all_milestones: |
683 | 34 | dest_milestone = dest_project.getMilestone(name=src_milestone.name) | 33 | dest_milestone = dest_project.getMilestone(name=src_milestone.name) |
684 | 35 | if dest_milestone: | 34 | if dest_milestone: |
685 | 36 | logger.warning( | 35 | logger.warning( |
688 | 37 | "Project already has milestone %s, skipping\n" % | 36 | "Project already has milestone %s, skipping\n" |
689 | 38 | (dest_milestone.name)) | 37 | % (dest_milestone.name) |
690 | 38 | ) | ||
691 | 39 | else: | 39 | else: |
692 | 40 | logger.info("Creating milestone %s" % (src_milestone.name)) | 40 | logger.info("Creating milestone %s" % (src_milestone.name)) |
693 | 41 | if not dry_run: | 41 | if not dry_run: |
694 | 42 | dest_milestone = dest_series.newMilestone( | 42 | dest_milestone = dest_series.newMilestone( |
695 | 43 | name=src_milestone.name, | 43 | name=src_milestone.name, |
697 | 44 | date_targeted=src_milestone.date_targeted) | 44 | date_targeted=src_milestone.date_targeted, |
698 | 45 | ) | ||
699 | 45 | dest_milestone.is_active = src_milestone.is_active | 46 | dest_milestone.is_active = src_milestone.is_active |
700 | 46 | dest_milestone.lp_save() | 47 | dest_milestone.lp_save() |
701 | 47 | src_release = src_milestone.release | 48 | src_release = src_milestone.release |
702 | 48 | if src_release: | 49 | if src_release: |
706 | 49 | logger.info("Releasing milestone %s on %s " % | 50 | logger.info( |
707 | 50 | (src_milestone.name, | 51 | "Releasing milestone %s on %s " |
708 | 51 | src_milestone.release.date_released)) | 52 | % (src_milestone.name, src_milestone.release.date_released) |
709 | 53 | ) | ||
710 | 52 | if not dry_run: | 54 | if not dry_run: |
711 | 53 | dest_milestone.createProductRelease( | 55 | dest_milestone.createProductRelease( |
713 | 54 | date_released=src_milestone.release.date_released) | 56 | date_released=src_milestone.release.date_released |
714 | 57 | ) | ||
715 | 55 | 58 | ||
716 | 56 | 59 | ||
718 | 57 | if __name__ == '__main__': | 60 | if __name__ == "__main__": |
719 | 58 | parser = argparse.ArgumentParser() | 61 | parser = argparse.ArgumentParser() |
723 | 59 | parser.add_argument('-s', '--source', required=True) | 62 | parser.add_argument("-s", "--source", required=True) |
724 | 60 | parser.add_argument('-d', '--dest', required=True) | 63 | parser.add_argument("-d", "--dest", required=True) |
725 | 61 | parser.add_argument('--dry-run', action='store_true') | 64 | parser.add_argument("--dry-run", action="store_true") |
726 | 62 | args = parser.parse_args() | 65 | args = parser.parse_args() |
727 | 63 | 66 | ||
729 | 64 | logger = logging.getLogger('clone-project-milestones') | 67 | logger = logging.getLogger("clone-project-milestones") |
730 | 65 | logger.setLevel(logging.INFO) | 68 | logger.setLevel(logging.INFO) |
731 | 66 | ch = logging.StreamHandler() | 69 | ch = logging.StreamHandler() |
732 | 67 | formatter = logging.Formatter("%(levelname)s - %(message)s") | 70 | formatter = logging.Formatter("%(levelname)s - %(message)s") |
733 | diff --git a/lp-scripts/dump-bug-subscribers.py b/lp-scripts/dump-bug-subscribers.py | |||
734 | index 061c539..70f8c72 100755 | |||
735 | --- a/lp-scripts/dump-bug-subscribers.py | |||
736 | +++ b/lp-scripts/dump-bug-subscribers.py | |||
737 | @@ -8,42 +8,54 @@ import csv | |||
738 | 8 | from launchpadlib.launchpad import Launchpad | 8 | from launchpadlib.launchpad import Launchpad |
739 | 9 | 9 | ||
740 | 10 | 10 | ||
744 | 11 | bugStatuses = ["New", "Opinion", "Invalid", "Won't Fix", "Expired", | 11 | bugStatuses = [ |
745 | 12 | "Confirmed", "Triaged", "In Progress", "Fix Committed", | 12 | "New", |
746 | 13 | "Fix Released", "Incomplete"] | 13 | "Opinion", |
747 | 14 | "Invalid", | ||
748 | 15 | "Won't Fix", | ||
749 | 16 | "Expired", | ||
750 | 17 | "Confirmed", | ||
751 | 18 | "Triaged", | ||
752 | 19 | "In Progress", | ||
753 | 20 | "Fix Committed", | ||
754 | 21 | "Fix Released", | ||
755 | 22 | "Incomplete", | ||
756 | 23 | ] | ||
757 | 14 | 24 | ||
758 | 15 | 25 | ||
759 | 16 | def taskToBug(task): | 26 | def taskToBug(task): |
762 | 17 | bugid = int(task.self_link.split('/')[-1]) | 27 | bugid = int(task.self_link.split("/")[-1]) |
763 | 18 | return(lp.bugs[bugid]) | 28 | return lp.bugs[bugid] |
764 | 19 | 29 | ||
765 | 20 | 30 | ||
766 | 21 | def getSubscriptionId(subscription_url): | 31 | def getSubscriptionId(subscription_url): |
767 | 22 | lpString = str(subscription_url) | 32 | lpString = str(subscription_url) |
769 | 23 | lpPath = lpString.rsplit('/', 1) | 33 | lpPath = lpString.rsplit("/", 1) |
770 | 24 | return lpPath[-1] | 34 | return lpPath[-1] |
771 | 25 | 35 | ||
772 | 26 | 36 | ||
774 | 27 | if __name__ == '__main__': | 37 | if __name__ == "__main__": |
775 | 28 | parser = argparse.ArgumentParser() | 38 | parser = argparse.ArgumentParser() |
778 | 29 | parser.add_argument("project", help="Launchpad project from which \ | 39 | parser.add_argument( |
779 | 30 | subscribers will be dumped") | 40 | "project", |
780 | 41 | help="Launchpad project from which \ | ||
781 | 42 | subscribers will be dumped", | ||
782 | 43 | ) | ||
783 | 31 | parser.add_argument("-o", "--outfile", help="Output file", required=True) | 44 | parser.add_argument("-o", "--outfile", help="Output file", required=True) |
784 | 32 | args = parser.parse_args() | 45 | args = parser.parse_args() |
785 | 33 | 46 | ||
787 | 34 | lp = Launchpad.login_with('lpbugs', 'production', version='devel') | 47 | lp = Launchpad.login_with("lpbugs", "production", version="devel") |
788 | 35 | project = lp.projects[args.project] | 48 | project = lp.projects[args.project] |
789 | 36 | 49 | ||
791 | 37 | with open(args.outfile, 'w') as csvfile: | 50 | with open(args.outfile, "w") as csvfile: |
792 | 38 | c = csv.writer(csvfile) | 51 | c = csv.writer(csvfile) |
793 | 39 | c.writerow(["Bug", "Title", "Subscribers"]) | 52 | c.writerow(["Bug", "Title", "Subscribers"]) |
795 | 40 | # no way to list all open/closed bugs, so iterate through bug states | 53 | # no way to list all open/closed bugs, so iterate through bug states |
796 | 41 | for bugStatus in bugStatuses: | 54 | for bugStatus in bugStatuses: |
797 | 42 | for task in project.searchTasks(status=bugStatus): | 55 | for task in project.searchTasks(status=bugStatus): |
798 | 43 | output = [] | 56 | output = [] |
799 | 44 | bug = taskToBug(task) | 57 | bug = taskToBug(task) |
802 | 45 | output.append('=HYPERLINK("%s", "LP: #%d")' % | 58 | output.append('=HYPERLINK("%s", "LP: #%d")' % (task.web_link, bug.id)) |
801 | 46 | (task.web_link, bug.id)) | ||
803 | 47 | output.append(bug.title) | 59 | output.append(bug.title) |
804 | 48 | for subscription in bug.subscriptions: | 60 | for subscription in bug.subscriptions: |
805 | 49 | output.append(getSubscriptionId(subscription)) | 61 | output.append(getSubscriptionId(subscription)) |
806 | diff --git a/lp-scripts/lp-bulk-action.py b/lp-scripts/lp-bulk-action.py | |||
807 | index be1b047..acada01 100755 | |||
808 | --- a/lp-scripts/lp-bulk-action.py | |||
809 | +++ b/lp-scripts/lp-bulk-action.py | |||
810 | @@ -5,14 +5,14 @@ import sys | |||
811 | 5 | from launchpadlib.launchpad import Launchpad | 5 | from launchpadlib.launchpad import Launchpad |
812 | 6 | 6 | ||
813 | 7 | Projects = [ | 7 | Projects = [ |
822 | 8 | 'bandera', | 8 | "bandera", |
823 | 9 | 'kunpeng920', | 9 | "kunpeng920", |
824 | 10 | 'pearl', | 10 | "pearl", |
825 | 11 | 'pearl2', | 11 | "pearl2", |
826 | 12 | 'ubuntu-power-systems', | 12 | "ubuntu-power-systems", |
827 | 13 | 'ubuntu-z-systems', | 13 | "ubuntu-z-systems", |
828 | 14 | 'yarmouth', | 14 | "yarmouth", |
829 | 15 | 'yarmouth2', | 15 | "yarmouth2", |
830 | 16 | ] | 16 | ] |
831 | 17 | 17 | ||
832 | 18 | 18 | ||
833 | @@ -20,13 +20,15 @@ def createMilestone(lp, project, series, milestone, date): | |||
834 | 20 | p = lp.projects[project] | 20 | p = lp.projects[project] |
835 | 21 | s = p.getSeries(name=series) | 21 | s = p.getSeries(name=series) |
836 | 22 | if not s: | 22 | if not s: |
839 | 23 | sys.stderr.write("Warning: Project %s has no series %s, skipping\n" % | 23 | sys.stderr.write( |
840 | 24 | (project, series)) | 24 | "Warning: Project %s has no series %s, skipping\n" % (project, series) |
841 | 25 | ) | ||
842 | 25 | return | 26 | return |
843 | 26 | if p.getMilestone(name=milestone): | 27 | if p.getMilestone(name=milestone): |
844 | 27 | sys.stderr.write( | 28 | sys.stderr.write( |
847 | 28 | "Warning: Project %s already has milestone %s, skipping\n" % | 29 | "Warning: Project %s already has milestone %s, skipping\n" |
848 | 29 | (project, milestone)) | 30 | % (project, milestone) |
849 | 31 | ) | ||
850 | 30 | return | 32 | return |
851 | 31 | s.newMilestone(name=milestone, date_targeted=date) | 33 | s.newMilestone(name=milestone, date_targeted=date) |
852 | 32 | 34 | ||
853 | @@ -36,13 +38,14 @@ def releaseMilestone(lp, project, milestone, date): | |||
854 | 36 | m = p.getMilestone(name=milestone) | 38 | m = p.getMilestone(name=milestone) |
855 | 37 | if not m: | 39 | if not m: |
856 | 38 | sys.stderr.write( | 40 | sys.stderr.write( |
859 | 39 | "Warning: Project %s has no milestone %s, skipping\n" % | 41 | "Warning: Project %s has no milestone %s, skipping\n" % (project, milestone) |
860 | 40 | (project, milestone)) | 42 | ) |
861 | 41 | return | 43 | return |
862 | 42 | if m.release: | 44 | if m.release: |
863 | 43 | sys.stderr.write( | 45 | sys.stderr.write( |
866 | 44 | "Warning: Milestone %s in project %s is already released\n" % | 46 | "Warning: Milestone %s in project %s is already released\n" |
867 | 45 | (milestone, project)) | 47 | % (milestone, project) |
868 | 48 | ) | ||
869 | 46 | return | 49 | return |
870 | 47 | m.createProductRelease(date_released=date) | 50 | m.createProductRelease(date_released=date) |
871 | 48 | 51 | ||
872 | @@ -52,8 +55,9 @@ def updateMilestone(lp, project, milestone, date): | |||
873 | 52 | m = p.getMilestone(name=milestone) | 55 | m = p.getMilestone(name=milestone) |
874 | 53 | if not m: | 56 | if not m: |
875 | 54 | sys.stderr.write( | 57 | sys.stderr.write( |
878 | 55 | "Warning: Project %s does not have milestone %s, skipping\n" % | 58 | "Warning: Project %s does not have milestone %s, skipping\n" |
879 | 56 | (project, milestone)) | 59 | % (project, milestone) |
880 | 60 | ) | ||
881 | 57 | return | 61 | return |
882 | 58 | m.date_targeted = date | 62 | m.date_targeted = date |
883 | 59 | m.lp_save() | 63 | m.lp_save() |
884 | @@ -63,51 +67,52 @@ def createSeries(lp, project, series, summary): | |||
885 | 63 | p = lp.projects[project] | 67 | p = lp.projects[project] |
886 | 64 | if p.getSeries(name=series): | 68 | if p.getSeries(name=series): |
887 | 65 | sys.stderr.write( | 69 | sys.stderr.write( |
890 | 66 | "Warning: Project %s already has series %s, skipping\n" % | 70 | "Warning: Project %s already has series %s, skipping\n" % (project, series) |
891 | 67 | (project, series)) | 71 | ) |
892 | 68 | return | 72 | return |
893 | 69 | p.newSeries(name=series, summary=summary) | 73 | p.newSeries(name=series, summary=summary) |
894 | 70 | 74 | ||
895 | 71 | 75 | ||
897 | 72 | if __name__ == '__main__': | 76 | if __name__ == "__main__": |
898 | 73 | parser = argparse.ArgumentParser() | 77 | parser = argparse.ArgumentParser() |
900 | 74 | subparsers = parser.add_subparsers(dest='cmd') | 78 | subparsers = parser.add_subparsers(dest="cmd") |
901 | 75 | subparsers.required = True | 79 | subparsers.required = True |
904 | 76 | createMilestoneParser = subparsers.add_parser('create-milestone', | 80 | createMilestoneParser = subparsers.add_parser( |
905 | 77 | help="Create Milestone") | 81 | "create-milestone", help="Create Milestone" |
906 | 82 | ) | ||
907 | 78 | createMilestoneParser.add_argument("-s", "--series", required=True) | 83 | createMilestoneParser.add_argument("-s", "--series", required=True) |
908 | 79 | createMilestoneParser.add_argument("-d", "--date", required=True) | 84 | createMilestoneParser.add_argument("-d", "--date", required=True) |
909 | 80 | createMilestoneParser.add_argument("milestone") | 85 | createMilestoneParser.add_argument("milestone") |
911 | 81 | createMilestoneParser.set_defaults(cmd='create-milestone') | 86 | createMilestoneParser.set_defaults(cmd="create-milestone") |
912 | 82 | 87 | ||
915 | 83 | releaseMilestoneParser = subparsers.add_parser('release-milestone', | 88 | releaseMilestoneParser = subparsers.add_parser( |
916 | 84 | help="Release Milestone") | 89 | "release-milestone", help="Release Milestone" |
917 | 90 | ) | ||
918 | 85 | releaseMilestoneParser.add_argument("-d", "--date", required=True) | 91 | releaseMilestoneParser.add_argument("-d", "--date", required=True) |
919 | 86 | releaseMilestoneParser.add_argument("milestone") | 92 | releaseMilestoneParser.add_argument("milestone") |
921 | 87 | releaseMilestoneParser.set_defaults(cmd='release-milestone') | 93 | releaseMilestoneParser.set_defaults(cmd="release-milestone") |
922 | 88 | 94 | ||
925 | 89 | releaseMilestoneParser = subparsers.add_parser('update-milestone', | 95 | releaseMilestoneParser = subparsers.add_parser( |
926 | 90 | help="Update Milestone") | 96 | "update-milestone", help="Update Milestone" |
927 | 97 | ) | ||
928 | 91 | releaseMilestoneParser.add_argument("-d", "--date", required=True) | 98 | releaseMilestoneParser.add_argument("-d", "--date", required=True) |
929 | 92 | releaseMilestoneParser.add_argument("milestone") | 99 | releaseMilestoneParser.add_argument("milestone") |
931 | 93 | releaseMilestoneParser.set_defaults(cmd='update-milestone') | 100 | releaseMilestoneParser.set_defaults(cmd="update-milestone") |
932 | 94 | 101 | ||
935 | 95 | createSeriesParser = subparsers.add_parser('create-series', | 102 | createSeriesParser = subparsers.add_parser("create-series", help="Create Series") |
934 | 96 | help="Create Series") | ||
936 | 97 | createSeriesParser.add_argument("-s", "--summary", required=True) | 103 | createSeriesParser.add_argument("-s", "--summary", required=True) |
937 | 98 | createSeriesParser.add_argument("series") | 104 | createSeriesParser.add_argument("series") |
939 | 99 | createSeriesParser.set_defaults(cmd='create-series') | 105 | createSeriesParser.set_defaults(cmd="create-series") |
940 | 100 | args = parser.parse_args() | 106 | args = parser.parse_args() |
941 | 101 | 107 | ||
943 | 102 | lp = Launchpad.login_with('lpbugs', 'production', version='devel') | 108 | lp = Launchpad.login_with("lpbugs", "production", version="devel") |
944 | 103 | 109 | ||
945 | 104 | for project in Projects: | 110 | for project in Projects: |
950 | 105 | if args.cmd == 'create-milestone': | 111 | if args.cmd == "create-milestone": |
951 | 106 | createMilestone(lp, project, args.series, | 112 | createMilestone(lp, project, args.series, args.milestone, args.date) |
952 | 107 | args.milestone, args.date) | 113 | elif args.cmd == "create-series": |
949 | 108 | elif args.cmd == 'create-series': | ||
953 | 109 | createSeries(lp, project, args.series, args.summary) | 114 | createSeries(lp, project, args.series, args.summary) |
955 | 110 | elif args.cmd == 'release-milestone': | 115 | elif args.cmd == "release-milestone": |
956 | 111 | releaseMilestone(lp, project, args.milestone, args.date) | 116 | releaseMilestone(lp, project, args.milestone, args.date) |
958 | 112 | elif args.cmd == 'update-milestone': | 117 | elif args.cmd == "update-milestone": |
959 | 113 | updateMilestone(lp, project, args.milestone, args.date) | 118 | updateMilestone(lp, project, args.milestone, args.date) |
960 | diff --git a/lp-scripts/pearl-biweekly-bug-report-csv4.py b/lp-scripts/pearl-biweekly-bug-report-csv4.py | |||
961 | index 6590ecf..1295c43 100755 | |||
962 | --- a/lp-scripts/pearl-biweekly-bug-report-csv4.py | |||
963 | +++ b/lp-scripts/pearl-biweekly-bug-report-csv4.py | |||
964 | @@ -1,74 +1,93 @@ | |||
965 | 1 | #!/usr/bin/python3 | ||
966 | 1 | # Change History | 2 | # Change History |
967 | 2 | # Modify encode utf_8 to byte code in Rationale/Comment | 3 | # Modify encode utf_8 to byte code in Rationale/Comment |
969 | 3 | # Add Date_created column for creating date for bug | 4 | # Add Date_created column for creating date for bug |
970 | 4 | # Add Scope column for showing impact for all arc or arch-arm64 or D05 Boad only | 5 | # Add Scope column for showing impact for all arc or arch-arm64 or D05 Boad only |
971 | 5 | 6 | ||
972 | 6 | #!/usr/bin/python3 | ||
973 | 7 | |||
974 | 8 | import argparse | 7 | import argparse |
975 | 9 | import csv | 8 | import csv |
976 | 10 | from launchpadlib.launchpad import Launchpad | 9 | from launchpadlib.launchpad import Launchpad |
977 | 11 | 10 | ||
980 | 12 | rationaleSectionHeader="[16.04.3 Risk Comments]" | 11 | rationaleSectionHeader = "[16.04.3 Risk Comments]" |
981 | 13 | rationaleBoilerplate="Still under investigation, not yet root-caused." | 12 | rationaleBoilerplate = "Still under investigation, not yet root-caused." |
982 | 13 | |||
983 | 14 | 14 | ||
984 | 15 | def taskToBug(task): | 15 | def taskToBug(task): |
987 | 16 | bugid = int(task.self_link.split('/')[-1]) | 16 | bugid = int(task.self_link.split("/")[-1]) |
988 | 17 | return(lp.bugs[bugid]) | 17 | return lp.bugs[bugid] |
989 | 18 | |||
990 | 18 | 19 | ||
991 | 19 | def ownerFromStatus(status): | 20 | def ownerFromStatus(status): |
994 | 20 | if 'Incomplete' in status: | 21 | if "Incomplete" in status: |
995 | 21 | owner='Huawei' | 22 | owner = "Huawei" |
996 | 22 | else: | 23 | else: |
999 | 23 | owner='Canonical' | 24 | owner = "Canonical" |
1000 | 24 | return(owner) | 25 | return owner |
1001 | 26 | |||
1002 | 25 | 27 | ||
1003 | 26 | def rationaleFromDescription(des): | 28 | def rationaleFromDescription(des): |
1007 | 27 | export_rationale_flag=0 # Flag to detect the start of the "[16.04.3 Risk Comments]" section | 29 | export_rationale_flag = ( |
1008 | 28 | rationale="" | 30 | 0 # Flag to detect the start of the "[16.04.3 Risk Comments]" section |
1009 | 29 | for des_line in des.splitlines(): # Loop through the bug description line-by-line looking for sections to export | 31 | ) |
1010 | 32 | rationale = "" | ||
1011 | 33 | for ( | ||
1012 | 34 | des_line | ||
1013 | 35 | ) in ( | ||
1014 | 36 | des.splitlines() | ||
1015 | 37 | ): # Loop through the bug description line-by-line looking for sections to export | ||
1016 | 30 | if des_line == rationaleSectionHeader: | 38 | if des_line == rationaleSectionHeader: |
1018 | 31 | export_rationale_flag=1 | 39 | export_rationale_flag = 1 |
1019 | 32 | else: | 40 | else: |
1023 | 33 | if export_rationale_flag==1: | 41 | if export_rationale_flag == 1: |
1024 | 34 | if des_line=="": | 42 | if des_line == "": |
1025 | 35 | export_rationale_flag=0 | 43 | export_rationale_flag = 0 |
1026 | 36 | else: | 44 | else: |
1029 | 37 | rationale+=des_line | 45 | rationale += des_line |
1030 | 38 | return(rationale) | 46 | return rationale |
1031 | 39 | 47 | ||
1032 | 40 | 48 | ||
1033 | 41 | def checkScopeTags(tags): | 49 | def checkScopeTags(tags): |
1035 | 42 | scopeTags = ['scope-arch-all', 'scope-arch-arm64', 'scope-d05-only'] | 50 | scopeTags = ["scope-arch-all", "scope-arch-arm64", "scope-d05-only"] |
1036 | 43 | scope = set(scopeTags).intersection(tags) | 51 | scope = set(scopeTags).intersection(tags) |
1037 | 44 | for i in scope: | 52 | for i in scope: |
1039 | 45 | return(i) | 53 | return i |
1040 | 46 | 54 | ||
1042 | 47 | return('Unknown') | 55 | return "Unknown" |
1043 | 48 | 56 | ||
1044 | 49 | 57 | ||
1046 | 50 | if __name__ == '__main__': | 58 | if __name__ == "__main__": |
1047 | 51 | parser = argparse.ArgumentParser() | 59 | parser = argparse.ArgumentParser() |
1048 | 52 | parser.add_argument("-o", "--outfile", required=True) | 60 | parser.add_argument("-o", "--outfile", required=True) |
1049 | 53 | args = parser.parse_args() | 61 | args = parser.parse_args() |
1050 | 54 | 62 | ||
1052 | 55 | lp = Launchpad.login_with('lpbugs', 'production', version='devel') | 63 | lp = Launchpad.login_with("lpbugs", "production", version="devel") |
1053 | 56 | 64 | ||
1055 | 57 | pearl = lp.projects['pearl'] | 65 | pearl = lp.projects["pearl"] |
1056 | 58 | 66 | ||
1058 | 59 | with open(args.outfile, 'w') as csvfile: | 67 | with open(args.outfile, "w") as csvfile: |
1059 | 60 | c = csv.writer(csvfile) | 68 | c = csv.writer(csvfile) |
1062 | 61 | c.writerow(["Title", "Link", "Status", "Milestone", "Scope","Rationale/Comment", "Owner", "DateCreated"]) | 69 | c.writerow( |
1063 | 62 | # First pass: patchset bugs | 70 | [ |
1064 | 71 | "Title", | ||
1065 | 72 | "Link", | ||
1066 | 73 | "Status", | ||
1067 | 74 | "Milestone", | ||
1068 | 75 | "Scope", | ||
1069 | 76 | "Rationale/Comment", | ||
1070 | 77 | "Owner", | ||
1071 | 78 | "DateCreated", | ||
1072 | 79 | ] | ||
1073 | 80 | ) | ||
1074 | 81 | # First pass: patchset bugs | ||
1075 | 63 | for series in pearl.series: | 82 | for series in pearl.series: |
1077 | 64 | if series.name not in ['ubuntu-16.04']: | 83 | if series.name not in ["ubuntu-16.04"]: |
1078 | 65 | continue | 84 | continue |
1081 | 66 | # First pass, phase one: search for the 'open' bugs | 85 | # First pass, phase one: search for the 'open' bugs |
1082 | 67 | for task in series.searchTasks(): | 86 | for task in series.searchTasks(): |
1083 | 68 | bug = taskToBug(task) | 87 | bug = taskToBug(task) |
1084 | 69 | # All kernel patchset bugs in the pearl project are tagged 'upstream-risky' | 88 | # All kernel patchset bugs in the pearl project are tagged 'upstream-risky' |
1087 | 70 | # if 'upstream-risky' not in bug.tags: | 89 | # if 'upstream-risky' not in bug.tags: |
1088 | 71 | # continue | 90 | # continue |
1089 | 72 | if task.milestone is None: | 91 | if task.milestone is None: |
1090 | 73 | milestone = "TBD" | 92 | milestone = "TBD" |
1091 | 74 | else: | 93 | else: |
1092 | @@ -76,18 +95,29 @@ if __name__ == '__main__': | |||
1093 | 76 | link = '=HYPERLINK("%s", "LP: #%d")' % (task.web_link, bug.id) | 95 | link = '=HYPERLINK("%s", "LP: #%d")' % (task.web_link, bug.id) |
1094 | 77 | rationale = rationaleFromDescription(bug.description) | 96 | rationale = rationaleFromDescription(bug.description) |
1095 | 78 | if (not rationale) and (task.milestone is None): | 97 | if (not rationale) and (task.milestone is None): |
1103 | 79 | rationale=rationaleBoilerplate | 98 | rationale = rationaleBoilerplate |
1104 | 80 | scope = checkScopeTags(bug.tags) | 99 | scope = checkScopeTags(bug.tags) |
1105 | 81 | owner = ownerFromStatus(task.status) | 100 | owner = ownerFromStatus(task.status) |
1106 | 82 | date_created = bug.date_created.strftime("%Y/%m/%d") | 101 | date_created = bug.date_created.strftime("%Y/%m/%d") |
1107 | 83 | c.writerow([bug.title, link, task.status, milestone, scope, rationale.encode('utf_8'), owner, date_created]) | 102 | c.writerow( |
1108 | 84 | 103 | [ | |
1109 | 85 | # First pass, phase two: Fix Released bugs | 104 | bug.title, |
1110 | 105 | link, | ||
1111 | 106 | task.status, | ||
1112 | 107 | milestone, | ||
1113 | 108 | scope, | ||
1114 | 109 | rationale.encode("utf_8"), | ||
1115 | 110 | owner, | ||
1116 | 111 | date_created, | ||
1117 | 112 | ] | ||
1118 | 113 | ) | ||
1119 | 114 | |||
1120 | 115 | # First pass, phase two: Fix Released bugs | ||
1121 | 86 | for task in series.searchTasks(status="Fix Released"): | 116 | for task in series.searchTasks(status="Fix Released"): |
1122 | 87 | bug = taskToBug(task) | 117 | bug = taskToBug(task) |
1123 | 88 | # All kernel patchset bugs in the pearl project are tagged 'upstream-risky' | 118 | # All kernel patchset bugs in the pearl project are tagged 'upstream-risky' |
1126 | 89 | # if not 'upstream-risky' not in bug.tags: | 119 | # if not 'upstream-risky' not in bug.tags: |
1127 | 90 | # continue | 120 | # continue |
1128 | 91 | if task.milestone is None: | 121 | if task.milestone is None: |
1129 | 92 | milestone = "TBD" | 122 | milestone = "TBD" |
1130 | 93 | else: | 123 | else: |
1131 | @@ -95,9 +125,19 @@ if __name__ == '__main__': | |||
1132 | 95 | link = '=HYPERLINK("%s", "LP: #%d")' % (task.web_link, bug.id) | 125 | link = '=HYPERLINK("%s", "LP: #%d")' % (task.web_link, bug.id) |
1133 | 96 | rationale = rationaleFromDescription(bug.description) | 126 | rationale = rationaleFromDescription(bug.description) |
1134 | 97 | if (not rationale) and (task.milestone is None): | 127 | if (not rationale) and (task.milestone is None): |
1136 | 98 | rationale=rationaleBoilerplate | 128 | rationale = rationaleBoilerplate |
1137 | 99 | scope = checkScopeTags(bug.tags) | 129 | scope = checkScopeTags(bug.tags) |
1138 | 100 | owner = ownerFromStatus(task.status) | 130 | owner = ownerFromStatus(task.status) |
1142 | 101 | date_created = bug.date_created.strftime("%Y/%m/%d") | 131 | date_created = bug.date_created.strftime("%Y/%m/%d") |
1143 | 102 | c.writerow([bug.title, link, task.status, milestone, scope, rationale.encode('utf_8'), owner, date_created]) | 132 | c.writerow( |
1144 | 103 | 133 | [ | |
1145 | 134 | bug.title, | ||
1146 | 135 | link, | ||
1147 | 136 | task.status, | ||
1148 | 137 | milestone, | ||
1149 | 138 | scope, | ||
1150 | 139 | rationale.encode("utf_8"), | ||
1151 | 140 | owner, | ||
1152 | 141 | date_created, | ||
1153 | 142 | ] | ||
1154 | 143 | ) | ||
1155 | diff --git a/lp-scripts/pearl-biweekly-report-csv.py b/lp-scripts/pearl-biweekly-report-csv.py | |||
1156 | index 2006490..5da289d 100755 | |||
1157 | --- a/lp-scripts/pearl-biweekly-report-csv.py | |||
1158 | +++ b/lp-scripts/pearl-biweekly-report-csv.py | |||
1159 | @@ -4,57 +4,76 @@ import argparse | |||
1160 | 4 | import csv | 4 | import csv |
1161 | 5 | from launchpadlib.launchpad import Launchpad | 5 | from launchpadlib.launchpad import Launchpad |
1162 | 6 | 6 | ||
1165 | 7 | rationaleSectionHeader="[16.04.3 Risk Comments]" | 7 | rationaleSectionHeader = "[16.04.3 Risk Comments]" |
1166 | 8 | rationaleBoilerplate="Still under investigation, not yet root-caused." | 8 | rationaleBoilerplate = "Still under investigation, not yet root-caused." |
1167 | 9 | |||
1168 | 9 | 10 | ||
1169 | 10 | def taskToBug(task): | 11 | def taskToBug(task): |
1172 | 11 | bugid = int(task.self_link.split('/')[-1]) | 12 | bugid = int(task.self_link.split("/")[-1]) |
1173 | 12 | return(lp.bugs[bugid]) | 13 | return lp.bugs[bugid] |
1174 | 14 | |||
1175 | 13 | 15 | ||
1176 | 14 | def ownerFromStatus(status): | 16 | def ownerFromStatus(status): |
1179 | 15 | if 'Incomplete' in status: | 17 | if "Incomplete" in status: |
1180 | 16 | owner='Huawei' | 18 | owner = "Huawei" |
1181 | 17 | else: | 19 | else: |
1184 | 18 | owner='Canonical' | 20 | owner = "Canonical" |
1185 | 19 | return(owner) | 21 | return owner |
1186 | 22 | |||
1187 | 20 | 23 | ||
1188 | 21 | def rationaleFromDescription(des): | 24 | def rationaleFromDescription(des): |
1192 | 22 | export_rationale_flag=0 # Flag to detect the start of the "[16.04.3 Risk Comments]" section | 25 | export_rationale_flag = ( |
1193 | 23 | rationale="" | 26 | 0 # Flag to detect the start of the "[16.04.3 Risk Comments]" section |
1194 | 24 | for des_line in des.splitlines(): # Loop through the bug description line-by-line looking for sections to export | 27 | ) |
1195 | 28 | rationale = "" | ||
1196 | 29 | for ( | ||
1197 | 30 | des_line | ||
1198 | 31 | ) in ( | ||
1199 | 32 | des.splitlines() | ||
1200 | 33 | ): # Loop through the bug description line-by-line looking for sections to export | ||
1201 | 25 | if des_line == rationaleSectionHeader: | 34 | if des_line == rationaleSectionHeader: |
1203 | 26 | export_rationale_flag=1 | 35 | export_rationale_flag = 1 |
1204 | 27 | else: | 36 | else: |
1208 | 28 | if export_rationale_flag==1: | 37 | if export_rationale_flag == 1: |
1209 | 29 | if des_line=="": | 38 | if des_line == "": |
1210 | 30 | export_rationale_flag=0 | 39 | export_rationale_flag = 0 |
1211 | 31 | else: | 40 | else: |
1214 | 32 | rationale+=des_line | 41 | rationale += des_line |
1215 | 33 | return(rationale) | 42 | return rationale |
1216 | 34 | 43 | ||
1219 | 35 | 44 | ||
1220 | 36 | if __name__ == '__main__': | 45 | if __name__ == "__main__": |
1221 | 37 | parser = argparse.ArgumentParser() | 46 | parser = argparse.ArgumentParser() |
1222 | 38 | parser.add_argument("-o", "--outfile", required=True) | 47 | parser.add_argument("-o", "--outfile", required=True) |
1223 | 39 | args = parser.parse_args() | 48 | args = parser.parse_args() |
1224 | 40 | 49 | ||
1226 | 41 | lp = Launchpad.login_with('lpbugs', 'production', version='devel') | 50 | lp = Launchpad.login_with("lpbugs", "production", version="devel") |
1227 | 42 | 51 | ||
1229 | 43 | pearl = lp.projects['pearl'] | 52 | pearl = lp.projects["pearl"] |
1230 | 44 | 53 | ||
1232 | 45 | with open(args.outfile, 'w') as csvfile: | 54 | with open(args.outfile, "w") as csvfile: |
1233 | 46 | c = csv.writer(csvfile) | 55 | c = csv.writer(csvfile) |
1236 | 47 | c.writerow(["Title", "Link", "Status", "Milestone", "Rationale/Comment", "Owner", "DateCreated"]) | 56 | c.writerow( |
1237 | 48 | # First pass: patchset bugs | 57 | [ |
1238 | 58 | "Title", | ||
1239 | 59 | "Link", | ||
1240 | 60 | "Status", | ||
1241 | 61 | "Milestone", | ||
1242 | 62 | "Rationale/Comment", | ||
1243 | 63 | "Owner", | ||
1244 | 64 | "DateCreated", | ||
1245 | 65 | ] | ||
1246 | 66 | ) | ||
1247 | 67 | # First pass: patchset bugs | ||
1248 | 49 | for series in pearl.series: | 68 | for series in pearl.series: |
1250 | 50 | if series.name not in ['ubuntu-16.04']: | 69 | if series.name not in ["ubuntu-16.04"]: |
1251 | 51 | continue | 70 | continue |
1254 | 52 | # First pass, phase one: search for the 'open' bugs | 71 | # First pass, phase one: search for the 'open' bugs |
1255 | 53 | for task in series.searchTasks(): | 72 | for task in series.searchTasks(): |
1256 | 54 | bug = taskToBug(task) | 73 | bug = taskToBug(task) |
1257 | 55 | # All kernel patchset bugs in the pearl project are tagged 'upstream-risky' | 74 | # All kernel patchset bugs in the pearl project are tagged 'upstream-risky' |
1260 | 56 | # if 'upstream-risky' not in bug.tags: | 75 | # if 'upstream-risky' not in bug.tags: |
1261 | 57 | # continue | 76 | # continue |
1262 | 58 | if task.milestone is None: | 77 | if task.milestone is None: |
1263 | 59 | milestone = "TBD" | 78 | milestone = "TBD" |
1264 | 60 | else: | 79 | else: |
1265 | @@ -62,17 +81,27 @@ if __name__ == '__main__': | |||
1266 | 62 | link = '=HYPERLINK("%s", "LP: #%d")' % (task.web_link, bug.id) | 81 | link = '=HYPERLINK("%s", "LP: #%d")' % (task.web_link, bug.id) |
1267 | 63 | rationale = rationaleFromDescription(bug.description) | 82 | rationale = rationaleFromDescription(bug.description) |
1268 | 64 | if (not rationale) and (task.milestone is None): | 83 | if (not rationale) and (task.milestone is None): |
1270 | 65 | rationale=rationaleBoilerplate | 84 | rationale = rationaleBoilerplate |
1271 | 66 | owner = ownerFromStatus(task.status) | 85 | owner = ownerFromStatus(task.status) |
1274 | 67 | date_created = bug.date_created.strftime("%Y/%m/%d") | 86 | date_created = bug.date_created.strftime("%Y/%m/%d") |
1275 | 68 | c.writerow([bug.title, link, task.status, milestone, rationale.encode('utf_8'), owner, date_created]) | 87 | c.writerow( |
1276 | 88 | [ | ||
1277 | 89 | bug.title, | ||
1278 | 90 | link, | ||
1279 | 91 | task.status, | ||
1280 | 92 | milestone, | ||
1281 | 93 | rationale.encode("utf_8"), | ||
1282 | 94 | owner, | ||
1283 | 95 | date_created, | ||
1284 | 96 | ] | ||
1285 | 97 | ) | ||
1286 | 69 | 98 | ||
1289 | 70 | # First pass, phase two: Fix Released bugs | 99 | # First pass, phase two: Fix Released bugs |
1290 | 71 | for task in series.searchTasks(status="Fix Released"): | 100 | for task in series.searchTasks(status="Fix Released"): |
1291 | 72 | bug = taskToBug(task) | 101 | bug = taskToBug(task) |
1292 | 73 | # All kernel patchset bugs in the pearl project are tagged 'upstream-risky' | 102 | # All kernel patchset bugs in the pearl project are tagged 'upstream-risky' |
1295 | 74 | # if not 'upstream-risky' not in bug.tags: | 103 | # if not 'upstream-risky' not in bug.tags: |
1296 | 75 | # continue | 104 | # continue |
1297 | 76 | if task.milestone is None: | 105 | if task.milestone is None: |
1298 | 77 | milestone = "TBD" | 106 | milestone = "TBD" |
1299 | 78 | else: | 107 | else: |
1300 | @@ -80,8 +109,17 @@ if __name__ == '__main__': | |||
1301 | 80 | link = '=HYPERLINK("%s", "LP: #%d")' % (task.web_link, bug.id) | 109 | link = '=HYPERLINK("%s", "LP: #%d")' % (task.web_link, bug.id) |
1302 | 81 | rationale = rationaleFromDescription(bug.description) | 110 | rationale = rationaleFromDescription(bug.description) |
1303 | 82 | if (not rationale) and (task.milestone is None): | 111 | if (not rationale) and (task.milestone is None): |
1305 | 83 | rationale=rationaleBoilerplate | 112 | rationale = rationaleBoilerplate |
1306 | 84 | owner = ownerFromStatus(task.status) | 113 | owner = ownerFromStatus(task.status) |
1310 | 85 | date_created = bug.date_created.strftime("%Y/%m/%d") | 114 | date_created = bug.date_created.strftime("%Y/%m/%d") |
1311 | 86 | c.writerow([bug.title, link, task.status, milestone, rationale.encode('utf_8'), owner, date_created]) | 115 | c.writerow( |
1312 | 87 | 116 | [ | |
1313 | 117 | bug.title, | ||
1314 | 118 | link, | ||
1315 | 119 | task.status, | ||
1316 | 120 | milestone, | ||
1317 | 121 | rationale.encode("utf_8"), | ||
1318 | 122 | owner, | ||
1319 | 123 | date_created, | ||
1320 | 124 | ] | ||
1321 | 125 | ) | ||
1322 | diff --git a/lp-scripts/pearl-biweekly-report.csv.py b/lp-scripts/pearl-biweekly-report.csv.py | |||
1323 | index 454c993..bfebacc 100644 | |||
1324 | --- a/lp-scripts/pearl-biweekly-report.csv.py | |||
1325 | +++ b/lp-scripts/pearl-biweekly-report.csv.py | |||
1326 | @@ -1,80 +1,99 @@ | |||
1327 | 1 | #!/usr/bin/python3 | ||
1328 | 1 | # Change History | 2 | # Change History |
1329 | 2 | # Modify encode utf_8 to byte code in Rationale/Comment | 3 | # Modify encode utf_8 to byte code in Rationale/Comment |
1331 | 3 | # Add Date_created column for creating date for bug | 4 | # Add Date_created column for creating date for bug |
1332 | 4 | # Add Scope column for showing impact for all arc or arch-arm64 or D05 Boad only | 5 | # Add Scope column for showing impact for all arc or arch-arm64 or D05 Boad only |
1333 | 5 | 6 | ||
1334 | 6 | #!/usr/bin/python3 | ||
1335 | 7 | |||
1336 | 8 | import argparse | 7 | import argparse |
1337 | 9 | import csv | 8 | import csv |
1338 | 10 | from launchpadlib.launchpad import Launchpad | 9 | from launchpadlib.launchpad import Launchpad |
1339 | 11 | 10 | ||
1342 | 12 | rationaleSectionHeader="[16.04.3 Risk Comments]" | 11 | rationaleSectionHeader = "[16.04.3 Risk Comments]" |
1343 | 13 | rationaleBoilerplate="Still under investigation, not yet root-caused." | 12 | rationaleBoilerplate = "Still under investigation, not yet root-caused." |
1344 | 13 | |||
1345 | 14 | 14 | ||
1346 | 15 | def taskToBug(task): | 15 | def taskToBug(task): |
1349 | 16 | bugid = int(task.self_link.split('/')[-1]) | 16 | bugid = int(task.self_link.split("/")[-1]) |
1350 | 17 | return(lp.bugs[bugid]) | 17 | return lp.bugs[bugid] |
1351 | 18 | |||
1352 | 18 | 19 | ||
1353 | 19 | def ownerFromStatus(status): | 20 | def ownerFromStatus(status): |
1356 | 20 | if 'Incomplete' in status: | 21 | if "Incomplete" in status: |
1357 | 21 | owner='Huawei' | 22 | owner = "Huawei" |
1358 | 22 | else: | 23 | else: |
1361 | 23 | owner='Canonical' | 24 | owner = "Canonical" |
1362 | 24 | return(owner) | 25 | return owner |
1363 | 26 | |||
1364 | 25 | 27 | ||
1365 | 26 | def rationaleFromDescription(des): | 28 | def rationaleFromDescription(des): |
1369 | 27 | export_rationale_flag=0 # Flag to detect the start of the "[16.04.3 Risk Comments]" section | 29 | export_rationale_flag = ( |
1370 | 28 | rationale="" | 30 | 0 # Flag to detect the start of the "[16.04.3 Risk Comments]" section |
1371 | 29 | for des_line in des.splitlines(): # Loop through the bug description line-by-line looking for sections to export | 31 | ) |
1372 | 32 | rationale = "" | ||
1373 | 33 | for ( | ||
1374 | 34 | des_line | ||
1375 | 35 | ) in ( | ||
1376 | 36 | des.splitlines() | ||
1377 | 37 | ): # Loop through the bug description line-by-line looking for sections to export | ||
1378 | 30 | if des_line == rationaleSectionHeader: | 38 | if des_line == rationaleSectionHeader: |
1380 | 31 | export_rationale_flag=1 | 39 | export_rationale_flag = 1 |
1381 | 32 | else: | 40 | else: |
1385 | 33 | if export_rationale_flag==1: | 41 | if export_rationale_flag == 1: |
1386 | 34 | if des_line=="": | 42 | if des_line == "": |
1387 | 35 | export_rationale_flag=0 | 43 | export_rationale_flag = 0 |
1388 | 36 | else: | 44 | else: |
1391 | 37 | rationale+=des_line | 45 | rationale += des_line |
1392 | 38 | return(rationale) | 46 | return rationale |
1393 | 39 | 47 | ||
1394 | 40 | 48 | ||
1395 | 41 | def checkScopeTags(tags): | 49 | def checkScopeTags(tags): |
1397 | 42 | scopeTags = ['scope-arch-all', 'scope-arch-arm64', 'scope-d05-only'] | 50 | scopeTags = ["scope-arch-all", "scope-arch-arm64", "scope-d05-only"] |
1398 | 43 | scope = set(scopeTags).intersection(tags) | 51 | scope = set(scopeTags).intersection(tags) |
1399 | 44 | for i in scope: | 52 | for i in scope: |
1407 | 45 | if i == 'scope-arch-all': | 53 | if i == "scope-arch-all": |
1408 | 46 | i = 'Generic' | 54 | i = "Generic" |
1409 | 47 | elif i == 'scope-arch-arm64': | 55 | elif i == "scope-arch-arm64": |
1410 | 48 | i = 'ARM64 generic' | 56 | i = "ARM64 generic" |
1411 | 49 | elif i == 'scope-d05-only': | 57 | elif i == "scope-d05-only": |
1412 | 50 | i = 'D05 only' | 58 | i = "D05 only" |
1413 | 51 | return(i) | 59 | return i |
1414 | 52 | 60 | ||
1416 | 53 | return('Unknown') | 61 | return "Unknown" |
1417 | 54 | 62 | ||
1418 | 55 | 63 | ||
1420 | 56 | if __name__ == '__main__': | 64 | if __name__ == "__main__": |
1421 | 57 | parser = argparse.ArgumentParser() | 65 | parser = argparse.ArgumentParser() |
1422 | 58 | parser.add_argument("-o", "--outfile", required=True) | 66 | parser.add_argument("-o", "--outfile", required=True) |
1423 | 59 | args = parser.parse_args() | 67 | args = parser.parse_args() |
1424 | 60 | 68 | ||
1426 | 61 | lp = Launchpad.login_with('lpbugs', 'production', version='devel') | 69 | lp = Launchpad.login_with("lpbugs", "production", version="devel") |
1427 | 62 | 70 | ||
1429 | 63 | pearl = lp.projects['pearl'] | 71 | pearl = lp.projects["pearl"] |
1430 | 64 | 72 | ||
1432 | 65 | with open(args.outfile, 'w') as csvfile: | 73 | with open(args.outfile, "w") as csvfile: |
1433 | 66 | c = csv.writer(csvfile) | 74 | c = csv.writer(csvfile) |
1436 | 67 | c.writerow(["Title", "Link", "Status", "Milestone", "Scope","Rationale/Comment", "Owner", "DateCreated"]) | 75 | c.writerow( |
1437 | 68 | # First pass: patchset bugs | 76 | [ |
1438 | 77 | "Title", | ||
1439 | 78 | "Link", | ||
1440 | 79 | "Status", | ||
1441 | 80 | "Milestone", | ||
1442 | 81 | "Scope", | ||
1443 | 82 | "Rationale/Comment", | ||
1444 | 83 | "Owner", | ||
1445 | 84 | "DateCreated", | ||
1446 | 85 | ] | ||
1447 | 86 | ) | ||
1448 | 87 | # First pass: patchset bugs | ||
1449 | 69 | for series in pearl.series: | 88 | for series in pearl.series: |
1451 | 70 | if series.name not in ['ubuntu-16.04']: | 89 | if series.name not in ["ubuntu-16.04"]: |
1452 | 71 | continue | 90 | continue |
1455 | 72 | # First pass, phase one: search for the 'open' bugs | 91 | # First pass, phase one: search for the 'open' bugs |
1456 | 73 | for task in series.searchTasks(): | 92 | for task in series.searchTasks(): |
1457 | 74 | bug = taskToBug(task) | 93 | bug = taskToBug(task) |
1458 | 75 | # All kernel patchset bugs in the pearl project are tagged 'upstream-risky' | 94 | # All kernel patchset bugs in the pearl project are tagged 'upstream-risky' |
1461 | 76 | # if 'upstream-risky' not in bug.tags: | 95 | # if 'upstream-risky' not in bug.tags: |
1462 | 77 | # continue | 96 | # continue |
1463 | 78 | if task.milestone is None: | 97 | if task.milestone is None: |
1464 | 79 | milestone = "TBD" | 98 | milestone = "TBD" |
1465 | 80 | else: | 99 | else: |
1466 | @@ -82,18 +101,29 @@ if __name__ == '__main__': | |||
1467 | 82 | link = '=HYPERLINK("%s", "LP: #%d")' % (task.web_link, bug.id) | 101 | link = '=HYPERLINK("%s", "LP: #%d")' % (task.web_link, bug.id) |
1468 | 83 | rationale = rationaleFromDescription(bug.description) | 102 | rationale = rationaleFromDescription(bug.description) |
1469 | 84 | if (not rationale) and (task.milestone is None): | 103 | if (not rationale) and (task.milestone is None): |
1477 | 85 | rationale=rationaleBoilerplate | 104 | rationale = rationaleBoilerplate |
1478 | 86 | scope = checkScopeTags(bug.tags) | 105 | scope = checkScopeTags(bug.tags) |
1479 | 87 | owner = ownerFromStatus(task.status) | 106 | owner = ownerFromStatus(task.status) |
1480 | 88 | date_created = bug.date_created.strftime("%Y/%m/%d") | 107 | date_created = bug.date_created.strftime("%Y/%m/%d") |
1481 | 89 | c.writerow([bug.title, link, task.status, milestone, scope, rationale.encode('utf_8'), owner, date_created]) | 108 | c.writerow( |
1482 | 90 | 109 | [ | |
1483 | 91 | # First pass, phase two: Fix Released bugs | 110 | bug.title, |
1484 | 111 | link, | ||
1485 | 112 | task.status, | ||
1486 | 113 | milestone, | ||
1487 | 114 | scope, | ||
1488 | 115 | rationale.encode("utf_8"), | ||
1489 | 116 | owner, | ||
1490 | 117 | date_created, | ||
1491 | 118 | ] | ||
1492 | 119 | ) | ||
1493 | 120 | |||
1494 | 121 | # First pass, phase two: Fix Released bugs | ||
1495 | 92 | for task in series.searchTasks(status="Fix Released"): | 122 | for task in series.searchTasks(status="Fix Released"): |
1496 | 93 | bug = taskToBug(task) | 123 | bug = taskToBug(task) |
1497 | 94 | # All kernel patchset bugs in the pearl project are tagged 'upstream-risky' | 124 | # All kernel patchset bugs in the pearl project are tagged 'upstream-risky' |
1500 | 95 | # if not 'upstream-risky' not in bug.tags: | 125 | # if not 'upstream-risky' not in bug.tags: |
1501 | 96 | # continue | 126 | # continue |
1502 | 97 | if task.milestone is None: | 127 | if task.milestone is None: |
1503 | 98 | milestone = "TBD" | 128 | milestone = "TBD" |
1504 | 99 | else: | 129 | else: |
1505 | @@ -101,9 +131,19 @@ if __name__ == '__main__': | |||
1506 | 101 | link = '=HYPERLINK("%s", "LP: #%d")' % (task.web_link, bug.id) | 131 | link = '=HYPERLINK("%s", "LP: #%d")' % (task.web_link, bug.id) |
1507 | 102 | rationale = rationaleFromDescription(bug.description) | 132 | rationale = rationaleFromDescription(bug.description) |
1508 | 103 | if (not rationale) and (task.milestone is None): | 133 | if (not rationale) and (task.milestone is None): |
1510 | 104 | rationale=rationaleBoilerplate | 134 | rationale = rationaleBoilerplate |
1511 | 105 | scope = checkScopeTags(bug.tags) | 135 | scope = checkScopeTags(bug.tags) |
1512 | 106 | owner = ownerFromStatus(task.status) | 136 | owner = ownerFromStatus(task.status) |
1516 | 107 | date_created = bug.date_created.strftime("%Y/%m/%d") | 137 | date_created = bug.date_created.strftime("%Y/%m/%d") |
1517 | 108 | c.writerow([bug.title, link, task.status, milestone, scope, rationale.encode('utf_8'), owner, date_created]) | 138 | c.writerow( |
1518 | 109 | 139 | [ | |
1519 | 140 | bug.title, | ||
1520 | 141 | link, | ||
1521 | 142 | task.status, | ||
1522 | 143 | milestone, | ||
1523 | 144 | scope, | ||
1524 | 145 | rationale.encode("utf_8"), | ||
1525 | 146 | owner, | ||
1526 | 147 | date_created, | ||
1527 | 148 | ] | ||
1528 | 149 | ) | ||
1529 | diff --git a/lp-scripts/pearl-bug-csv-summary.py b/lp-scripts/pearl-bug-csv-summary.py | |||
1530 | index a1a0b35..ad4a049 100755 | |||
1531 | --- a/lp-scripts/pearl-bug-csv-summary.py | |||
1532 | +++ b/lp-scripts/pearl-bug-csv-summary.py | |||
1533 | @@ -7,18 +7,19 @@ from LaunchpadBugBucketer import LaunchpadBugBucketer | |||
1534 | 7 | 7 | ||
1535 | 8 | class PearlBugBucketer(LaunchpadBugBucketer): | 8 | class PearlBugBucketer(LaunchpadBugBucketer): |
1536 | 9 | def __init__(self): | 9 | def __init__(self): |
1539 | 10 | LaunchpadBugBucketer.__init__(self, 'pearl', 'ubuntu-16.04', | 10 | LaunchpadBugBucketer.__init__( |
1540 | 11 | requiredTags=['upstream-risky']) | 11 | self, "pearl", "ubuntu-16.04", requiredTags=["upstream-risky"] |
1541 | 12 | ) | ||
1542 | 12 | 13 | ||
1543 | 13 | def is_green(self, task): | 14 | def is_green(self, task): |
1545 | 14 | if task.status in ['Fix Committed', 'Fix Released']: | 15 | if task.status in ["Fix Committed", "Fix Released"]: |
1546 | 15 | return True | 16 | return True |
1547 | 16 | return False | 17 | return False |
1548 | 17 | 18 | ||
1549 | 18 | def is_amber(self, task): | 19 | def is_amber(self, task): |
1550 | 19 | if self.is_green(task): | 20 | if self.is_green(task): |
1551 | 20 | return False | 21 | return False |
1553 | 21 | elif task.milestone and task.milestone.name == 'ubuntu-16.04.3': | 22 | elif task.milestone and task.milestone.name == "ubuntu-16.04.3": |
1554 | 22 | return True | 23 | return True |
1555 | 23 | return False | 24 | return False |
1556 | 24 | 25 | ||
1557 | @@ -28,16 +29,16 @@ class PearlBugBucketer(LaunchpadBugBucketer): | |||
1558 | 28 | return True | 29 | return True |
1559 | 29 | 30 | ||
1560 | 30 | 31 | ||
1562 | 31 | if __name__ == '__main__': | 32 | if __name__ == "__main__": |
1563 | 32 | parser = argparse.ArgumentParser() | 33 | parser = argparse.ArgumentParser() |
1564 | 33 | parser.add_argument("-o", "--outfile") | 34 | parser.add_argument("-o", "--outfile") |
1565 | 34 | args = parser.parse_args() | 35 | args = parser.parse_args() |
1566 | 35 | 36 | ||
1567 | 36 | s = PearlBugBucketer() | 37 | s = PearlBugBucketer() |
1568 | 37 | 38 | ||
1570 | 38 | with open(args.outfile, 'w') as csvfile: | 39 | with open(args.outfile, "w") as csvfile: |
1571 | 39 | c = csv.writer(csvfile) | 40 | c = csv.writer(csvfile) |
1573 | 40 | c.writerow(['Title', 'Bug ID', 'Importance', 'Status', 'RAG Risk']) | 41 | c.writerow(["Title", "Bug ID", "Importance", "Status", "RAG Risk"]) |
1574 | 41 | for bucket in s.keys(): | 42 | for bucket in s.keys(): |
1575 | 42 | for task in s[bucket]: | 43 | for task in s[bucket]: |
1576 | 43 | bug = s.taskToBug(task) | 44 | bug = s.taskToBug(task) |
1577 | diff --git a/lp-scripts/pearl-risky-patch-schedule.py b/lp-scripts/pearl-risky-patch-schedule.py | |||
1578 | index a22f493..01d546e 100755 | |||
1579 | --- a/lp-scripts/pearl-risky-patch-schedule.py | |||
1580 | +++ b/lp-scripts/pearl-risky-patch-schedule.py | |||
1581 | @@ -4,29 +4,31 @@ import argparse | |||
1582 | 4 | import csv | 4 | import csv |
1583 | 5 | from launchpadlib.launchpad import Launchpad | 5 | from launchpadlib.launchpad import Launchpad |
1584 | 6 | 6 | ||
1585 | 7 | |||
1586 | 7 | def taskToBug(task): | 8 | def taskToBug(task): |
1591 | 8 | bugid = int(task.self_link.split('/')[-1]) | 9 | bugid = int(task.self_link.split("/")[-1]) |
1592 | 9 | return(lp.bugs[bugid]) | 10 | return lp.bugs[bugid] |
1593 | 10 | 11 | ||
1594 | 11 | if __name__ == '__main__': | 12 | |
1595 | 13 | if __name__ == "__main__": | ||
1596 | 12 | parser = argparse.ArgumentParser() | 14 | parser = argparse.ArgumentParser() |
1597 | 13 | parser.add_argument("-o", "--outfile", required=True) | 15 | parser.add_argument("-o", "--outfile", required=True) |
1598 | 14 | args = parser.parse_args() | 16 | args = parser.parse_args() |
1599 | 15 | 17 | ||
1601 | 16 | lp = Launchpad.login_with('lpbugs', 'production', version='devel') | 18 | lp = Launchpad.login_with("lpbugs", "production", version="devel") |
1602 | 17 | 19 | ||
1604 | 18 | pearl = lp.projects['pearl'] | 20 | pearl = lp.projects["pearl"] |
1605 | 19 | 21 | ||
1607 | 20 | with open(args.outfile, 'w') as csvfile: | 22 | with open(args.outfile, "w") as csvfile: |
1608 | 21 | c = csv.writer(csvfile) | 23 | c = csv.writer(csvfile) |
1609 | 22 | for series in pearl.series: | 24 | for series in pearl.series: |
1611 | 23 | if series.name not in ['ubuntu-17.04']: | 25 | if series.name not in ["ubuntu-17.04"]: |
1612 | 24 | continue | 26 | continue |
1614 | 25 | for task in series.searchTasks(): | 27 | for task in series.searchTasks(): |
1615 | 26 | bug = taskToBug(task) | 28 | bug = taskToBug(task) |
1616 | 27 | # All kernel patchset bugs in the pearl project are tagged | 29 | # All kernel patchset bugs in the pearl project are tagged |
1617 | 28 | # 'upstream-risky' | 30 | # 'upstream-risky' |
1619 | 29 | if 'upstream-risky' not in bug.tags: | 31 | if "upstream-risky" not in bug.tags: |
1620 | 30 | continue | 32 | continue |
1621 | 31 | if task.milestone is None: | 33 | if task.milestone is None: |
1622 | 32 | date = "TBD" | 34 | date = "TBD" |
1623 | diff --git a/lp-scripts/pearl2-biweekly-report.csv.py b/lp-scripts/pearl2-biweekly-report.csv.py | |||
1624 | index b005620..a5a75d9 100755 | |||
1625 | --- a/lp-scripts/pearl2-biweekly-report.csv.py | |||
1626 | +++ b/lp-scripts/pearl2-biweekly-report.csv.py | |||
1627 | @@ -10,94 +10,110 @@ import argparse | |||
1628 | 10 | import csv | 10 | import csv |
1629 | 11 | from launchpadlib.launchpad import Launchpad | 11 | from launchpadlib.launchpad import Launchpad |
1630 | 12 | 12 | ||
1633 | 13 | rationaleSectionHeader="[18.04.1 Risk Comments]" | 13 | rationaleSectionHeader = "[18.04.1 Risk Comments]" |
1634 | 14 | rationaleBoilerplate="Still under investigation, not yet root-caused." | 14 | rationaleBoilerplate = "Still under investigation, not yet root-caused." |
1635 | 15 | |||
1636 | 15 | 16 | ||
1637 | 16 | def taskToBug(task): | 17 | def taskToBug(task): |
1640 | 17 | bugid = int(task.self_link.split('/')[-1]) | 18 | bugid = int(task.self_link.split("/")[-1]) |
1641 | 18 | return(lp.bugs[bugid]) | 19 | return lp.bugs[bugid] |
1642 | 20 | |||
1643 | 19 | 21 | ||
1644 | 20 | def ownerFromStatus(status): | 22 | def ownerFromStatus(status): |
1647 | 21 | if 'Incomplete' in status: | 23 | if "Incomplete" in status: |
1648 | 22 | owner='Huawei' | 24 | owner = "Huawei" |
1649 | 23 | else: | 25 | else: |
1652 | 24 | owner='Canonical' | 26 | owner = "Canonical" |
1653 | 25 | return(owner) | 27 | return owner |
1654 | 28 | |||
1655 | 26 | 29 | ||
1656 | 27 | def rationaleFromDescription(des): | 30 | def rationaleFromDescription(des): |
1660 | 28 | export_rationale_flag=0 # Flag to detect the start of the "[18.04.1 Risk Comments]" section | 31 | export_rationale_flag = ( |
1661 | 29 | rationale="" | 32 | 0 # Flag to detect the start of the "[18.04.1 Risk Comments]" section |
1662 | 30 | for des_line in des.splitlines(): # Loop through the bug description line-by-line looking for sections to export | 33 | ) |
1663 | 34 | rationale = "" | ||
1664 | 35 | for ( | ||
1665 | 36 | des_line | ||
1666 | 37 | ) in ( | ||
1667 | 38 | des.splitlines() | ||
1668 | 39 | ): # Loop through the bug description line-by-line looking for sections to export | ||
1669 | 31 | if des_line == rationaleSectionHeader: | 40 | if des_line == rationaleSectionHeader: |
1671 | 32 | export_rationale_flag=1 | 41 | export_rationale_flag = 1 |
1672 | 33 | else: | 42 | else: |
1676 | 34 | if export_rationale_flag==1: | 43 | if export_rationale_flag == 1: |
1677 | 35 | if des_line=="": | 44 | if des_line == "": |
1678 | 36 | export_rationale_flag=0 | 45 | export_rationale_flag = 0 |
1679 | 37 | else: | 46 | else: |
1682 | 38 | rationale+=des_line | 47 | rationale += des_line |
1683 | 39 | return(rationale) | 48 | return rationale |
1684 | 40 | 49 | ||
1685 | 41 | 50 | ||
1686 | 42 | def checkScopeTags(tags): | 51 | def checkScopeTags(tags): |
1688 | 43 | scopeTags = ['scope-arch-all', 'scope-arch-arm64', 'scope-d06-only'] | 52 | scopeTags = ["scope-arch-all", "scope-arch-arm64", "scope-d06-only"] |
1689 | 44 | scope = set(scopeTags).intersection(tags) | 53 | scope = set(scopeTags).intersection(tags) |
1690 | 45 | for i in scope: | 54 | for i in scope: |
1698 | 46 | if i == 'scope-arch-all': | 55 | if i == "scope-arch-all": |
1699 | 47 | i = 'Generic' | 56 | i = "Generic" |
1700 | 48 | elif i == 'scope-arch-arm64': | 57 | elif i == "scope-arch-arm64": |
1701 | 49 | i = 'ARM64 generic' | 58 | i = "ARM64 generic" |
1702 | 50 | elif i == 'scope-d06-only': | 59 | elif i == "scope-d06-only": |
1703 | 51 | i = 'D06 only' | 60 | i = "D06 only" |
1704 | 52 | return(i) | 61 | return i |
1705 | 62 | |||
1706 | 63 | return "Unknown" | ||
1707 | 53 | 64 | ||
1708 | 54 | return('Unknown') | ||
1709 | 55 | 65 | ||
1710 | 56 | def getMilestones(series_array): | 66 | def getMilestones(series_array): |
1712 | 57 | milestones=[] | 67 | milestones = [] |
1713 | 58 | for series in series_array: | 68 | for series in series_array: |
1715 | 59 | milestone_url=series['milestone_link'] | 69 | milestone_url = series["milestone_link"] |
1716 | 60 | if milestone_url is not None: | 70 | if milestone_url is not None: |
1718 | 61 | milestone_name=milestone_url.rsplit('/',1) | 71 | milestone_name = milestone_url.rsplit("/", 1) |
1719 | 62 | milestones.append(milestone_name[-1]) | 72 | milestones.append(milestone_name[-1]) |
1720 | 63 | return milestones | 73 | return milestones |
1721 | 64 | 74 | ||
1722 | 75 | |||
1723 | 65 | def getUoseMilestone(series_array): | 76 | def getUoseMilestone(series_array): |
1726 | 66 | milestones=getMilestones(series_array) | 77 | milestones = getMilestones(series_array) |
1727 | 67 | uose_milestone="" | 78 | uose_milestone = "" |
1728 | 68 | for milestone in milestones: | 79 | for milestone in milestones: |
1729 | 69 | if "uose" in milestone: | 80 | if "uose" in milestone: |
1731 | 70 | uose_milestone=milestone | 81 | uose_milestone = milestone |
1732 | 71 | return uose_milestone | 82 | return uose_milestone |
1733 | 72 | 83 | ||
1734 | 73 | 84 | ||
1736 | 74 | if __name__ == '__main__': | 85 | if __name__ == "__main__": |
1737 | 75 | parser = argparse.ArgumentParser() | 86 | parser = argparse.ArgumentParser() |
1738 | 76 | parser.add_argument("-o", "--outfile", required=True) | 87 | parser.add_argument("-o", "--outfile", required=True) |
1739 | 77 | args = parser.parse_args() | 88 | args = parser.parse_args() |
1740 | 78 | 89 | ||
1742 | 79 | lp = Launchpad.login_with('lpbugs', 'production', version='devel') | 90 | lp = Launchpad.login_with("lpbugs", "production", version="devel") |
1743 | 80 | 91 | ||
1745 | 81 | pearl = lp.projects['pearl2'] | 92 | pearl = lp.projects["pearl2"] |
1746 | 82 | 93 | ||
1748 | 83 | with open(args.outfile, 'w') as csvfile: | 94 | with open(args.outfile, "w") as csvfile: |
1749 | 84 | c = csv.writer(csvfile) | 95 | c = csv.writer(csvfile) |
1752 | 85 | c.writerow(["Title", "Link", "Status", "Milestone", "Owner", "DateCreated","Comments"]) | 96 | c.writerow( |
1753 | 86 | # First pass: search for the 'open' bugs | 97 | ["Title", "Link", "Status", "Milestone", "Owner", "DateCreated", "Comments"] |
1754 | 98 | ) | ||
1755 | 99 | # First pass: search for the 'open' bugs | ||
1756 | 87 | for task in pearl.searchTasks(): | 100 | for task in pearl.searchTasks(): |
1758 | 88 | uose_milestone=getUoseMilestone(task.related_tasks.entries) | 101 | uose_milestone = getUoseMilestone(task.related_tasks.entries) |
1759 | 89 | bug = taskToBug(task) | 102 | bug = taskToBug(task) |
1760 | 90 | link = '=HYPERLINK("%s", "LP: #%d")' % (task.web_link, bug.id) | 103 | link = '=HYPERLINK("%s", "LP: #%d")' % (task.web_link, bug.id) |
1761 | 91 | owner = ownerFromStatus(task.status) | 104 | owner = ownerFromStatus(task.status) |
1762 | 92 | date_created = bug.date_created.strftime("%Y/%m/%d") | 105 | date_created = bug.date_created.strftime("%Y/%m/%d") |
1764 | 93 | c.writerow([bug.title, link, task.status, uose_milestone, owner, date_created]) | 106 | c.writerow( |
1765 | 107 | [bug.title, link, task.status, uose_milestone, owner, date_created] | ||
1766 | 108 | ) | ||
1767 | 94 | 109 | ||
1769 | 95 | # Second pass: search for the 'Fix Released' bugs | 110 | # Second pass: search for the 'Fix Released' bugs |
1770 | 96 | for task in pearl.searchTasks(status="Fix Released"): | 111 | for task in pearl.searchTasks(status="Fix Released"): |
1771 | 97 | bug = taskToBug(task) | 112 | bug = taskToBug(task) |
1773 | 98 | uose_milestone=getUoseMilestone(task.related_tasks.entries) | 113 | uose_milestone = getUoseMilestone(task.related_tasks.entries) |
1774 | 99 | link = '=HYPERLINK("%s", "LP: #%d")' % (task.web_link, bug.id) | 114 | link = '=HYPERLINK("%s", "LP: #%d")' % (task.web_link, bug.id) |
1775 | 100 | owner = ownerFromStatus(task.status) | 115 | owner = ownerFromStatus(task.status) |
1776 | 101 | date_created = bug.date_created.strftime("%Y/%m/%d") | 116 | date_created = bug.date_created.strftime("%Y/%m/%d") |
1779 | 102 | c.writerow([bug.title, link, task.status, uose_milestone, owner, date_created]) | 117 | c.writerow( |
1780 | 103 | 118 | [bug.title, link, task.status, uose_milestone, owner, date_created] | |
1781 | 119 | ) | ||
1782 | diff --git a/lp-scripts/pearl2-d06-18.04-patch-status.py b/lp-scripts/pearl2-d06-18.04-patch-status.py | |||
1783 | index 2d56d05..79316bc 100755 | |||
1784 | --- a/lp-scripts/pearl2-d06-18.04-patch-status.py | |||
1785 | +++ b/lp-scripts/pearl2-d06-18.04-patch-status.py | |||
1786 | @@ -2,29 +2,34 @@ | |||
1787 | 2 | 2 | ||
1788 | 3 | import argparse | 3 | import argparse |
1789 | 4 | import csv | 4 | import csv |
1790 | 5 | import string | ||
1791 | 6 | from launchpadlib.launchpad import Launchpad | 5 | from launchpadlib.launchpad import Launchpad |
1792 | 7 | 6 | ||
1793 | 7 | |||
1794 | 8 | def taskToBug(task): | 8 | def taskToBug(task): |
1797 | 9 | bugid = int(task.self_link.split('/')[-1]) | 9 | bugid = int(task.self_link.split("/")[-1]) |
1798 | 10 | return(lp.bugs[bugid]) | 10 | return lp.bugs[bugid] |
1799 | 11 | 11 | ||
1800 | 12 | 12 | ||
1804 | 13 | Pre18041Milestones = ['ubuntu-18.04-ga', 'ubuntu-18.04-sru-1', | 13 | Pre18041Milestones = [ |
1805 | 14 | 'ubuntu-18.04-sru-2', 'ubuntu-18.04-sru-3', | 14 | "ubuntu-18.04-ga", |
1806 | 15 | 'ubuntu-18.04-sru-4', 'ubuntu-18.04.1'] | 15 | "ubuntu-18.04-sru-1", |
1807 | 16 | "ubuntu-18.04-sru-2", | ||
1808 | 17 | "ubuntu-18.04-sru-3", | ||
1809 | 18 | "ubuntu-18.04-sru-4", | ||
1810 | 19 | "ubuntu-18.04.1", | ||
1811 | 20 | ] | ||
1812 | 16 | 21 | ||
1814 | 17 | if __name__ == '__main__': | 22 | if __name__ == "__main__": |
1815 | 18 | parser = argparse.ArgumentParser() | 23 | parser = argparse.ArgumentParser() |
1816 | 19 | parser.add_argument("-o", "--outfile", required=True) | 24 | parser.add_argument("-o", "--outfile", required=True) |
1817 | 20 | args = parser.parse_args() | 25 | args = parser.parse_args() |
1818 | 21 | 26 | ||
1820 | 22 | lp = Launchpad.login_with('lpbugs', 'production', version='devel') | 27 | lp = Launchpad.login_with("lpbugs", "production", version="devel") |
1821 | 23 | 28 | ||
1824 | 24 | pearl = lp.projects['pearl2'] | 29 | pearl = lp.projects["pearl2"] |
1825 | 25 | series = pearl.getSeries(name='ubuntu-18.04') | 30 | series = pearl.getSeries(name="ubuntu-18.04") |
1826 | 26 | 31 | ||
1828 | 27 | with open(args.outfile, 'w') as csvfile: | 32 | with open(args.outfile, "w") as csvfile: |
1829 | 28 | c = csv.writer(csvfile) | 33 | c = csv.writer(csvfile) |
1830 | 29 | c.writerow(["Title", "Link", "Status", "Expected"]) | 34 | c.writerow(["Title", "Link", "Status", "Expected"]) |
1831 | 30 | for task in series.searchTasks(status=[]): | 35 | for task in series.searchTasks(status=[]): |
1832 | @@ -34,8 +39,8 @@ if __name__ == '__main__': | |||
1833 | 34 | # patches will land in, or it should be tagged as risky. | 39 | # patches will land in, or it should be tagged as risky. |
1834 | 35 | if task.status in ["Invalid", "Won't Fix"]: | 40 | if task.status in ["Invalid", "Won't Fix"]: |
1835 | 36 | continue | 41 | continue |
1838 | 37 | if task.status == 'Incomplete': | 42 | if task.status == "Incomplete": |
1839 | 38 | if 'needs-sru-justification' in bug.tags: | 43 | if "needs-sru-justification" in bug.tags: |
1840 | 39 | expected = "Needs SRU Justification" | 44 | expected = "Needs SRU Justification" |
1841 | 40 | else: | 45 | else: |
1842 | 41 | expected = "Need input from HiSilicon" | 46 | expected = "Need input from HiSilicon" |
1843 | diff --git a/lp-scripts/pearl2-tag-ubuntu-18.04.3-risky.py b/lp-scripts/pearl2-tag-ubuntu-18.04.3-risky.py | |||
1844 | index a29014e..01dc923 100755 | |||
1845 | --- a/lp-scripts/pearl2-tag-ubuntu-18.04.3-risky.py | |||
1846 | +++ b/lp-scripts/pearl2-tag-ubuntu-18.04.3-risky.py | |||
1847 | @@ -30,7 +30,7 @@ def get_risk(bug): | |||
1848 | 30 | for r in RiskyTagMap.keys(): | 30 | for r in RiskyTagMap.keys(): |
1849 | 31 | if RiskyTagMap[r] in bug.tags: | 31 | if RiskyTagMap[r] in bug.tags: |
1850 | 32 | # Only one tag should be found | 32 | # Only one tag should be found |
1852 | 33 | assert(found is None) | 33 | assert found is None |
1853 | 34 | found = r | 34 | found = r |
1854 | 35 | return found | 35 | return found |
1855 | 36 | 36 | ||
1856 | @@ -42,8 +42,7 @@ def set_risk(bug, risk): | |||
1857 | 42 | continue | 42 | continue |
1858 | 43 | rmtag = RiskyTagMap[r] | 43 | rmtag = RiskyTagMap[r] |
1859 | 44 | if rmtag in bug.tags: | 44 | if rmtag in bug.tags: |
1862 | 45 | sys.stderr.write("Removing %s tag from %s\n" % | 45 | sys.stderr.write("Removing %s tag from %s\n" % (rmtag, bug.web_link)) |
1861 | 46 | (rmtag, bug.web_link)) | ||
1863 | 47 | newtags = list(bug.tags) | 46 | newtags = list(bug.tags) |
1864 | 48 | newtags.remove(rmtag) | 47 | newtags.remove(rmtag) |
1865 | 49 | bug.tags = newtags | 48 | bug.tags = newtags |
1866 | @@ -55,10 +54,10 @@ def set_risk(bug, risk): | |||
1867 | 55 | bug.lp_save() | 54 | bug.lp_save() |
1868 | 56 | 55 | ||
1869 | 57 | 56 | ||
1872 | 58 | if __name__ == '__main__': | 57 | if __name__ == "__main__": |
1873 | 59 | lp = Launchpad.login_with('lpbugs', 'production', version='devel') | 58 | lp = Launchpad.login_with("lpbugs", "production", version="devel") |
1874 | 60 | 59 | ||
1876 | 61 | pearl2 = lp.projects['pearl2'] | 60 | pearl2 = lp.projects["pearl2"] |
1877 | 62 | target_milestone = "ubuntu-18.04.3" | 61 | target_milestone = "ubuntu-18.04.3" |
1878 | 63 | target_date = None | 62 | target_date = None |
1879 | 64 | # Find the target date of our milestone. We can compare this with | 63 | # Find the target date of our milestone. We can compare this with |
1880 | @@ -68,9 +67,9 @@ if __name__ == '__main__': | |||
1881 | 68 | if m.name in [target_milestone]: | 67 | if m.name in [target_milestone]: |
1882 | 69 | target_date = m.date_targeted | 68 | target_date = m.date_targeted |
1883 | 70 | break | 69 | break |
1885 | 71 | assert(target_date is not None) | 70 | assert target_date is not None |
1886 | 72 | 71 | ||
1888 | 73 | series = pearl2.getSeries(name='ubuntu-18.04-hwe') | 72 | series = pearl2.getSeries(name="ubuntu-18.04-hwe") |
1889 | 74 | for task in series.searchTasks(): | 73 | for task in series.searchTasks(): |
1890 | 75 | if task.milestone is not None: | 74 | if task.milestone is not None: |
1891 | 76 | tdelta = task.milestone.date_targeted - target_date | 75 | tdelta = task.milestone.date_targeted - target_date |
1892 | @@ -85,8 +84,13 @@ if __name__ == '__main__': | |||
1893 | 85 | continue | 84 | continue |
1894 | 86 | # Now process the ones w/ no milestone set. | 85 | # Now process the ones w/ no milestone set. |
1895 | 87 | # These by definition should all have milestones set. | 86 | # These by definition should all have milestones set. |
1898 | 88 | assert(task.status not in ["Opinion", "Invalid", "Won't Fix", | 87 | assert task.status not in [ |
1899 | 89 | "Fix Committed", "Fix Released"]) | 88 | "Opinion", |
1900 | 89 | "Invalid", | ||
1901 | 90 | "Won't Fix", | ||
1902 | 91 | "Fix Committed", | ||
1903 | 92 | "Fix Released", | ||
1904 | 93 | ] | ||
1905 | 90 | if task.status == "Incomplete": | 94 | if task.status == "Incomplete": |
1906 | 91 | set_risk(task.bug, Risky.HIGH) | 95 | set_risk(task.bug, Risky.HIGH) |
1907 | 92 | continue | 96 | continue |
1908 | diff --git a/lp-scripts/project-bug-lint.py b/lp-scripts/project-bug-lint.py | |||
1909 | index 48f81db..5f62a01 100755 | |||
1910 | --- a/lp-scripts/project-bug-lint.py | |||
1911 | +++ b/lp-scripts/project-bug-lint.py | |||
1912 | @@ -8,33 +8,42 @@ import sys | |||
1913 | 8 | class BugProperty: | 8 | class BugProperty: |
1914 | 9 | def __init__(self, property): | 9 | def __init__(self, property): |
1915 | 10 | self.index = self.PropertyList.index(property) | 10 | self.index = self.PropertyList.index(property) |
1917 | 11 | 11 | ||
1918 | 12 | def __eq__(self, other): | 12 | def __eq__(self, other): |
1920 | 13 | return(self.index == other.index) | 13 | return self.index == other.index |
1921 | 14 | 14 | ||
1922 | 15 | def __ne__(self, other): | 15 | def __ne__(self, other): |
1924 | 16 | return(self.index != other.index) | 16 | return self.index != other.index |
1925 | 17 | 17 | ||
1926 | 18 | def __lt__(self, other): | 18 | def __lt__(self, other): |
1928 | 19 | return(self.index < other.index) | 19 | return self.index < other.index |
1929 | 20 | 20 | ||
1930 | 21 | def __le__(self, other): | 21 | def __le__(self, other): |
1932 | 22 | return(self.index <= other.index) | 22 | return self.index <= other.index |
1933 | 23 | 23 | ||
1934 | 24 | def __gt__(self, other): | 24 | def __gt__(self, other): |
1936 | 25 | return(self.index > other.index) | 25 | return self.index > other.index |
1937 | 26 | 26 | ||
1938 | 27 | def __ge__(self, other): | 27 | def __ge__(self, other): |
1940 | 28 | return(self.index >= other.index) | 28 | return self.index >= other.index |
1941 | 29 | 29 | ||
1942 | 30 | def __repr__(self): | 30 | def __repr__(self): |
1944 | 31 | return(self.PropertyList[self.index]) | 31 | return self.PropertyList[self.index] |
1945 | 32 | 32 | ||
1946 | 33 | 33 | ||
1947 | 34 | class BugStatus(BugProperty): | 34 | class BugStatus(BugProperty): |
1951 | 35 | PropertyList = ['New', 'Incomplete', 'Opinion', 'Invalid', | 35 | PropertyList = [ |
1952 | 36 | 'Won\'t Fix', 'Confirmed', 'Triaged', 'In Progress', | 36 | "New", |
1953 | 37 | 'Fix Committed', 'Fix Released'] | 37 | "Incomplete", |
1954 | 38 | "Opinion", | ||
1955 | 39 | "Invalid", | ||
1956 | 40 | "Won't Fix", | ||
1957 | 41 | "Confirmed", | ||
1958 | 42 | "Triaged", | ||
1959 | 43 | "In Progress", | ||
1960 | 44 | "Fix Committed", | ||
1961 | 45 | "Fix Released", | ||
1962 | 46 | ] | ||
1963 | 38 | 47 | ||
1964 | 39 | # min/max could ideally be in the baseclass, but I don't know | 48 | # min/max could ideally be in the baseclass, but I don't know |
1965 | 40 | # how to do that and stil refer to the correct PropertyList | 49 | # how to do that and stil refer to the correct PropertyList |
1966 | @@ -45,12 +54,12 @@ class BugStatus(BugProperty): | |||
1967 | 45 | return BugStatus(BugStatus.PropertyList[-1]) | 54 | return BugStatus(BugStatus.PropertyList[-1]) |
1968 | 46 | 55 | ||
1969 | 47 | def isTerminalState(self): | 56 | def isTerminalState(self): |
1972 | 48 | terminalStates = ['Fix Released', 'Invalid', 'Won\'t Fix'] | 57 | terminalStates = ["Fix Released", "Invalid", "Won't Fix"] |
1973 | 49 | return(self.PropertyList[self.index] in terminalStates) | 58 | return self.PropertyList[self.index] in terminalStates |
1974 | 59 | |||
1975 | 50 | 60 | ||
1976 | 51 | class BugImportance(BugProperty): | 61 | class BugImportance(BugProperty): |
1979 | 52 | PropertyList = ['Undecided', 'Wishlist', 'Low', | 62 | PropertyList = ["Undecided", "Wishlist", "Low", "Medium", "High", "Critical"] |
1978 | 53 | 'Medium', 'High', 'Critical'] | ||
1980 | 54 | 63 | ||
1981 | 55 | # min/max could ideally be in the baseclass, but I don't know | 64 | # min/max could ideally be in the baseclass, but I don't know |
1982 | 56 | # how to do that and stil refer to the correct PropertyList | 65 | # how to do that and stil refer to the correct PropertyList |
1983 | @@ -60,11 +69,13 @@ class BugImportance(BugProperty): | |||
1984 | 60 | def max(): | 69 | def max(): |
1985 | 61 | return BugImportance(BugImportance.PropertyList[-1]) | 70 | return BugImportance(BugImportance.PropertyList[-1]) |
1986 | 62 | 71 | ||
1987 | 72 | |||
1988 | 63 | class BugTask: | 73 | class BugTask: |
1989 | 64 | def __init__(self, lptask): | 74 | def __init__(self, lptask): |
1990 | 65 | self.status = BugStatus(lptask.status) | 75 | self.status = BugStatus(lptask.status) |
1991 | 66 | self.importance = BugImportance(lptask.importance) | 76 | self.importance = BugImportance(lptask.importance) |
1992 | 67 | 77 | ||
1993 | 78 | |||
1994 | 68 | class Bug: | 79 | class Bug: |
1995 | 69 | def __init__(self): | 80 | def __init__(self): |
1996 | 70 | self.defaultTask = None | 81 | self.defaultTask = None |
1997 | @@ -80,24 +91,29 @@ class Bug: | |||
1998 | 80 | self.targetedTasks[series] = BugTask(task) | 91 | self.targetedTasks[series] = BugTask(task) |
1999 | 81 | 92 | ||
2000 | 82 | def getTargetedTasks(self): | 93 | def getTargetedTasks(self): |
2002 | 83 | return(self.targetedTasks) | 94 | return self.targetedTasks |
2003 | 95 | |||
2004 | 84 | 96 | ||
2005 | 85 | def checkScopeTags(lpbug): | 97 | def checkScopeTags(lpbug): |
2007 | 86 | scopeTags = ['scope-arch-all', 'scope-arch-arm64', 'scope-d05-only'] | 98 | scopeTags = ["scope-arch-all", "scope-arch-arm64", "scope-d05-only"] |
2008 | 87 | common = set(scopeTags).intersection(lpbug.tags) | 99 | common = set(scopeTags).intersection(lpbug.tags) |
2009 | 88 | if len(common) == 0: | 100 | if len(common) == 0: |
2010 | 89 | sys.stdout.write("http://launchpad.net/bugs/%d has no scope tag\n" % (bugid)) | 101 | sys.stdout.write("http://launchpad.net/bugs/%d has no scope tag\n" % (bugid)) |
2011 | 90 | if len(common) > 1: | 102 | if len(common) > 1: |
2013 | 91 | sys.stdout.write("http://launchpad.net/bugs/%d has multiple scope tags\n" % (bugid)) | 103 | sys.stdout.write( |
2014 | 104 | "http://launchpad.net/bugs/%d has multiple scope tags\n" % (bugid) | ||
2015 | 105 | ) | ||
2016 | 106 | |||
2017 | 92 | 107 | ||
2018 | 93 | def taskToBugId(task): | 108 | def taskToBugId(task): |
2020 | 94 | return(int(task.self_link.split('/')[-1])) | 109 | return int(task.self_link.split("/")[-1]) |
2021 | 110 | |||
2022 | 95 | 111 | ||
2024 | 96 | if __name__ == '__main__': | 112 | if __name__ == "__main__": |
2025 | 97 | parser = argparse.ArgumentParser() | 113 | parser = argparse.ArgumentParser() |
2026 | 98 | parser.add_argument("-p", "--project", required=True) | 114 | parser.add_argument("-p", "--project", required=True) |
2027 | 99 | args = parser.parse_args() | 115 | args = parser.parse_args() |
2029 | 100 | lp = Launchpad.login_with('lpbugs', 'production', version='devel') | 116 | lp = Launchpad.login_with("lpbugs", "production", version="devel") |
2030 | 101 | project = lp.projects[args.project] | 117 | project = lp.projects[args.project] |
2031 | 102 | 118 | ||
2032 | 103 | bugs = {} | 119 | bugs = {} |
2033 | @@ -114,7 +130,10 @@ if __name__ == '__main__': | |||
2034 | 114 | if bugid in bugs.keys(): | 130 | if bugid in bugs.keys(): |
2035 | 115 | bugs[bugid].addTargetedTask(series.name, task) | 131 | bugs[bugid].addTargetedTask(series.name, task) |
2036 | 116 | else: | 132 | else: |
2038 | 117 | sys.stderr.write("WARNING: http://launchpad.net/bugs/%d does not have a default task\n" % (bugid)) | 133 | sys.stderr.write( |
2039 | 134 | "WARNING: http://launchpad.net/bugs/%d does not have a default task\n" | ||
2040 | 135 | % (bugid) | ||
2041 | 136 | ) | ||
2042 | 118 | 137 | ||
2043 | 119 | # Now process them. | 138 | # Now process them. |
2044 | 120 | for bugid in bugs.keys(): | 139 | for bugid in bugs.keys(): |
2045 | @@ -123,7 +142,10 @@ if __name__ == '__main__': | |||
2046 | 123 | if len(targetedTasks) == 0: | 142 | if len(targetedTasks) == 0: |
2047 | 124 | defaultStatus = bug.getDefaultTask().status | 143 | defaultStatus = bug.getDefaultTask().status |
2048 | 125 | if not defaultStatus.isTerminalState(): | 144 | if not defaultStatus.isTerminalState(): |
2050 | 126 | sys.stderr.write("WARNING: http://launchpad.net/bugs/%d only has a default task\n" % (bugid)) | 145 | sys.stderr.write( |
2051 | 146 | "WARNING: http://launchpad.net/bugs/%d only has a default task\n" | ||
2052 | 147 | % (bugid) | ||
2053 | 148 | ) | ||
2054 | 127 | continue | 149 | continue |
2055 | 128 | 150 | ||
2056 | 129 | statusList = [] | 151 | statusList = [] |
2057 | @@ -144,10 +166,16 @@ if __name__ == '__main__': | |||
2058 | 144 | currentStatus = defaultTask.status | 166 | currentStatus = defaultTask.status |
2059 | 145 | currentImportance = defaultTask.importance | 167 | currentImportance = defaultTask.importance |
2060 | 146 | if targetStatus and targetStatus != currentStatus: | 168 | if targetStatus and targetStatus != currentStatus: |
2062 | 147 | sys.stdout.write("http://launchpad.net/bugs/%d status %s -> %s\n" % (bugid, currentStatus, targetStatus)) | 169 | sys.stdout.write( |
2063 | 170 | "http://launchpad.net/bugs/%d status %s -> %s\n" | ||
2064 | 171 | % (bugid, currentStatus, targetStatus) | ||
2065 | 172 | ) | ||
2066 | 148 | if targetImportance != currentImportance: | 173 | if targetImportance != currentImportance: |
2068 | 149 | sys.stdout.write("http://launchpad.net/bugs/%d importance %s -> %s\n" % (bugid, currentImportance, targetImportance)) | 174 | sys.stdout.write( |
2069 | 175 | "http://launchpad.net/bugs/%d importance %s -> %s\n" | ||
2070 | 176 | % (bugid, currentImportance, targetImportance) | ||
2071 | 177 | ) | ||
2072 | 150 | 178 | ||
2074 | 151 | if args.project == 'pearl': | 179 | if args.project == "pearl": |
2075 | 152 | if not defaultTask.status.isTerminalState(): | 180 | if not defaultTask.status.isTerminalState(): |
2076 | 153 | checkScopeTags(lp.bugs[bugid]) | 181 | checkScopeTags(lp.bugs[bugid]) |
2077 | diff --git a/sysadmin-tools/gen_conserver_cf.py b/sysadmin-tools/gen_conserver_cf.py | |||
2078 | index 065a30b..7153ed7 100755 | |||
2079 | --- a/sysadmin-tools/gen_conserver_cf.py | |||
2080 | +++ b/sysadmin-tools/gen_conserver_cf.py | |||
2081 | @@ -47,30 +47,30 @@ console {srv} {{ | |||
2082 | 47 | exec ipmitool -I lanplus -H {addr} -U {user} -P {pwd} sol activate; | 47 | exec ipmitool -I lanplus -H {addr} -U {user} -P {pwd} sol activate; |
2083 | 48 | }}""" | 48 | }}""" |
2084 | 49 | 49 | ||
2086 | 50 | if __name__ == '__main__': | 50 | if __name__ == "__main__": |
2087 | 51 | arg_parser = argparse.ArgumentParser() | 51 | arg_parser = argparse.ArgumentParser() |
2088 | 52 | arg_parser.add_argument("machines_yaml", help="Lab's machines.yaml file") | 52 | arg_parser.add_argument("machines_yaml", help="Lab's machines.yaml file") |
2091 | 53 | arg_parser.add_argument("-o", "--outfile", help="Output filename", | 53 | arg_parser.add_argument("-o", "--outfile", help="Output filename", required=True) |
2090 | 54 | required=True) | ||
2092 | 55 | args = arg_parser.parse_args() | 54 | args = arg_parser.parse_args() |
2093 | 56 | 55 | ||
2094 | 57 | with open(args.machines_yaml) as f: | 56 | with open(args.machines_yaml) as f: |
2095 | 58 | machines = yaml.safe_load(f) | 57 | machines = yaml.safe_load(f) |
2096 | 59 | 58 | ||
2098 | 60 | with open(args.outfile, 'w') as outfile: | 59 | with open(args.outfile, "w") as outfile: |
2099 | 61 | outfile.write(header.format(progname=arg_parser.prog)) | 60 | outfile.write(header.format(progname=arg_parser.prog)) |
2100 | 62 | for server in machines: | 61 | for server in machines: |
2101 | 63 | # bmc is required for conserver to attach | 62 | # bmc is required for conserver to attach |
2103 | 64 | if ("bmc" not in machines[server]): | 63 | if "bmc" not in machines[server]: |
2104 | 65 | continue | 64 | continue |
2105 | 66 | bmc_info = machines[server]["bmc"] | 65 | bmc_info = machines[server]["bmc"] |
2106 | 67 | # type is required so the conserver knows how to attach | 66 | # type is required so the conserver knows how to attach |
2108 | 68 | if ("type" not in bmc_info): | 67 | if "type" not in bmc_info: |
2109 | 69 | continue | 68 | continue |
2116 | 70 | if (bmc_info["type"] == "ipmi"): | 69 | if bmc_info["type"] == "ipmi": |
2117 | 71 | addr = bmc_info["address"].replace('#', '\\#') | 70 | addr = bmc_info["address"].replace("#", "\\#") |
2118 | 72 | user = bmc_info["user"].replace('#', '\\#') | 71 | user = bmc_info["user"].replace("#", "\\#") |
2119 | 73 | pwd = bmc_info["password"].replace('#', '\\#') | 72 | pwd = bmc_info["password"].replace("#", "\\#") |
2120 | 74 | outfile.write(ipmi_sol_entry.format(srv=server, addr=addr, | 73 | outfile.write( |
2121 | 75 | user=user, pwd=pwd)) | 74 | ipmi_sol_entry.format(srv=server, addr=addr, user=user, pwd=pwd) |
2122 | 75 | ) | ||
2123 | 76 | outfile.write(footer.format()) | 76 | outfile.write(footer.format()) |
The python-black + pre-commit that we already agreed upon and code reformatting. Clear approval!