~ubuntu-archive/ubuntu-archive-scripts/trunk

« back to all changes in this revision

Viewing changes to generate-team-p-m

  • Committer: Paride Legovini
  • Date: 2025-04-22 11:27:32 UTC
  • Revision ID: paride@ubuntu.com-20250422112732-kp59bwoymhae9rot
plucky->questing

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
import argparse
19
19
from collections import defaultdict, OrderedDict
20
20
import datetime
 
21
import time
21
22
import json
22
23
import os
23
24
import threading
24
25
from urllib.request import urlopen
 
26
import urllib.error
25
27
 
26
28
import attr
27
29
from jinja2 import Environment, FileSystemLoader
28
30
import yaml
 
31
import lzma
29
32
 
30
33
env = Environment(
31
34
    loader=FileSystemLoader(os.path.dirname(os.path.abspath(__file__)) + '/templates'),
122
125
 
123
126
def get_subscribers_json(packages, subscribers_json):
124
127
    if subscribers_json is None:
125
 
        j = urlopen("http://people.canonical.com/~ubuntu-archive/package-team-mapping.json")
 
128
        j = urlopen("https://ubuntu-archive-team.ubuntu.com/package-team-mapping.json")
126
129
    else:
127
130
        j = open(subscribers_json, 'rb')
128
131
    with j:
188
191
    waiting = attr.ib(default=None) # [(source_package_name, arches)]
189
192
    data = attr.ib(default=None) # data for package_in_proposed
190
193
    unsatdepends = attr.ib(default=None) # [string]
 
194
    unsatbuilddep = attr.ib(default=None) # [string]
 
195
    brokenbin = attr.ib(default=None) # [string]
 
196
    componentmismatch = attr.ib(default=None) # [string]
191
197
 
192
198
    _age = attr.ib(default=None)
193
199
 
205
211
        if self._age is not None:
206
212
            return self._age
207
213
        else:
208
 
            return self.data["policy_info"]["age"]["current-age"]
 
214
            try:
 
215
                return self.data["policy_info"]["age"]["current-age"]
 
216
            except KeyError:
 
217
                return -1
209
218
 
210
219
    @age.setter
211
220
    def age(self, val):
234
243
 
235
244
    print("fetching yaml")
236
245
    if args.excuses_yaml:
237
 
        yaml_text = open(args.excuses_yaml).read()
 
246
        if args.excuses_yaml.endswith('.xz'):
 
247
            yaml_text = lzma.open(args.excuses_yaml)
 
248
        else:
 
249
            yaml_text = open(args.excuses_yaml)
238
250
    else:
239
 
        yaml_text = urlopen("https://people.canonical.com/~ubuntu-archive/proposed-migration/update_excuses.yaml").read()
 
251
        try:
 
252
            yaml_text = lzma.open(urlopen("https://ubuntu-archive-team.ubuntu.com/proposed-migration/update_excuses.yaml.xz"))
 
253
        except urllib.error.HTTPError as e:
 
254
            print("Reading fallback yaml (%s)" % e)
 
255
            yaml_text = urlopen("https://ubuntu-archive-team.ubuntu.com/proposed-migration/update_excuses.yaml")
240
256
    print("parsing yaml")
241
257
    # The CSafeLoader is ten times faster than the regular one
242
258
    excuses = yaml.load(yaml_text, Loader=yaml.CSafeLoader)
248
264
        # Missing component means main
249
265
        if item.get('component', 'main') not in components:
250
266
            continue
251
 
        prob = Problem(kind='package-in-proposed', data=item, package_in_proposed=source_package_name)
 
267
        prob = Problem(kind='package-in-proposed', data=defaultdict(dict, item), package_in_proposed=source_package_name)
252
268
        in_proposed_packages[source_package_name] = prob
253
269
        prob.regressions = []
254
270
        prob.waiting = []
 
271
        prob.componentmismatch = []
 
272
        # The verdict entries are not items to list on the report
 
273
        for policy in ['autopkgtest', 'update-excuse', 'block-bugs']:
 
274
            try:
 
275
                del item['policy_info'][policy]['verdict']
 
276
            except KeyError:
 
277
                pass
255
278
        if 'autopkgtest' in item['reason']:
256
279
            for package, results in sorted(item['policy_info']['autopkgtest'].items()):
257
280
                regr_arches = []
269
292
                    prob.regressions.append(regr)
270
293
                if wait_arches:
271
294
                    prob.waiting.append((package + ": " + ", ".join(wait_arches)))
 
295
        if 'depends' in item['reason']:
 
296
            for l in item['excuses']:
 
297
                if 'cannot depend on' in l:
 
298
                    prob.componentmismatch.append(l)
272
299
        if 'dependencies' in item and 'unsatisfiable-dependencies' in item['dependencies']:
273
300
                unsatd = defaultdict(list)
274
301
                for arch, packages in item['dependencies']['unsatisfiable-dependencies'].items():
275
302
                    for p in packages:
276
303
                        unsatd[p].append(arch)
277
304
                prob.unsatdepends = ['{}: {}'.format(p, ', '.join(sorted(arches))) for p, arches in sorted(unsatd.items())]
 
305
        if 'policy_info' in item:
 
306
            if 'build-depends' in item['policy_info'] and 'unsatisfiable-arch-build-depends' in item['policy_info']['build-depends']:
 
307
                    unsatdbd = defaultdict(list)
 
308
                    for arch, packages in item['policy_info']['build-depends']['unsatisfiable-arch-build-depends'].items():
 
309
                        for p in packages:
 
310
                            unsatdbd[p].append(arch)
 
311
                    prob.unsatbuilddep = ['{}: {}'.format(p, ', '.join(sorted(arches))) for p, arches in sorted(unsatdbd.items())]
278
312
 
279
313
    package_to_problems = defaultdict(list)
280
314
 
281
315
    for problem in in_proposed_packages.values():
282
 
        package_to_problems[problem.package_in_proposed].append(problem)
 
316
        # nautilus/riscv64 -> nautilus
 
317
        pkg = problem.package_in_proposed.split('/')[0]
 
318
        package_to_problems[pkg].append(problem)
283
319
        for regression in problem.regressions:
284
320
            if regression.blocking not in in_proposed_packages:
285
321
                continue
306
342
    else:
307
343
        subscribers = get_subscribers_json(set(package_to_problems), args.subscribers_json)
308
344
        for p in set(package_to_problems):
309
 
            if p not in subscribers:
 
345
            pkg = p.split('/')[0]
 
346
            if pkg not in subscribers:
310
347
                subscribers[p] = ['unknown']
311
348
 
312
349
    all_teams = set()
330
367
            all_teams=all_teams,
331
368
            team_to_problems=team_to_problems,
332
369
            team_to_attn_count=team_to_attn_count,
333
 
            now=excuses["generated-date"].strftime("%Y.%m.%d %H:%M:%S")))
 
370
            now=excuses["generated-date"].strftime("%Y.%m.%d %H:%M:%S") + ' ' + time.localtime().tm_zone))
334
371
    if args.yaml_output:
335
372
        team_to_problem_data = {}
336
373
        for t, ps in team_to_problems.items():