]> git.proxmox.com Git - debcargo-conf.git/blame - dev/rust-excuses.py
dev/list-outdated.sh: script to scan for outdated crates
[debcargo-conf.git] / dev / rust-excuses.py
CommitLineData
d8ce2152
XL
1#!/usr/bin/pypy3
2# pypy3 runs faster than python3
3#
43ed93d8
SL
4# the excuses file can be found here:
5# https://release.debian.org/britney/excuses.yaml
1db6a00b 6
00c29ce1
XL
7import re
8import subprocess
1db6a00b
XL
9import sys
10import yaml
11
60c13697 12if len(sys.argv) != 4:
b4000f35
SL
13 print(
14 """Generates dot files to show the migration deps
60c13697 15Usage: %s excuses.dot excuses_arch.dot regressions.list
7f8aa2ce
SL
16
17Expects excuses.yaml in the current dir
b4000f35
SL
18 """
19 % sys.argv[0]
20 )
7f8aa2ce
SL
21 sys.exit(0)
22
1db6a00b
XL
23print("parsing excuses.yaml...", file=sys.stderr)
24with open("excuses.yaml") as fp:
78e0158a 25 y = yaml.load(fp, Loader=yaml.FullLoader)
1db6a00b
XL
26
27excuses = {}
28for e in y["sources"]:
b4000f35 29 excuses[e["source"]] = e
1db6a00b 30
00c29ce1 31print("generating dot files...", file=sys.stderr)
1db6a00b
XL
32rust_excuses = open(sys.argv[1], "w")
33rust_excuses_arch = open(sys.argv[2], "w")
60c13697 34rust_regressions = open(sys.argv[3], "w")
1db6a00b
XL
35
36already_seen = set()
37
00c29ce1 38def edge_dep(name, dep):
b4000f35
SL
39 return " ".join(['"%s"' % name, "->", '"%s"' % dep])
40
00c29ce1 41def edge_dep_label(name, dep, label):
b4000f35
SL
42 return " ".join(['"%s"' % name, "->", '"%s"' % dep, '[label="%s"]' % label])
43
1db6a00b 44def print_all(*args, **kwargs):
b4000f35
SL
45 print(*args, **kwargs, file=rust_excuses)
46 print(*args, **kwargs, file=rust_excuses_arch)
47
00c29ce1
XL
48is_in_debian_cache = {}
49def is_in_debian(src):
b4000f35
SL
50 global is_in_debian_cache
51 if src not in is_in_debian_cache:
52 n = subprocess.check_output(
53 "apt-cache showsrc %s 2>/dev/null | grep ^Package: | wc -l" % src,
54 shell=True,
55 )
56 is_in_debian_cache[src] = int(n.strip())
57 x = is_in_debian_cache[src]
58 return x
59
00c29ce1 60
d8ce2152
XL
61BG_NOT_IN_DEBIAN = "#cc0000"
62BG_OLD_IN_DEBIAN = "#ffcc66"
63BG_TOO_NEW = "#66ff99"
a2ba87f9 64BG_MISC_WAIT = "#ffcc99"
d8ce2152 65BG_MISC_FAIL = "#ff6666"
508cd1b3 66BG_SOURCEONLY = "#9999ff"
a2ba87f9 67VERDICT_FAIL = ("REJECTED_CANNOT_DETERMINE_IF_PERMANENT", "REJECTED_NEEDS_APPROVAL", "REJECTED_PERMANENTLY")
d8ce2152 68
1db6a00b 69def traverse(name, arch="", d=0):
b4000f35
SL
70 if name in already_seen:
71 return
72 already_seen.add(name)
73 dependencies = excuses.get(name, {}).get("dependencies", {})
74
75 edges = set()
76 for arch, deps in dependencies.get("unsatisfiable-dependencies", {}).items():
77 for dep in deps:
78 vers = ""
79 if dep.startswith("librust-"):
80 try:
81 results = re.match(r"librust-(\S+?)(-[.0-9]+)?(\+\S*)?-dev", dep)
82 dep = "rust-" + results.group(1)
83 if results.group(2):
84 vers = results.group(2)
85 except Exception:
86 print(dep, file=sys.stderr)
87 raise
88 edges.add(edge_dep_label(name, dep, vers))
89 print(
90 edge_dep_label(name, dep, "%s/%s" % (vers, arch) if vers else arch),
91 file=rust_excuses_arch,
92 )
93 if dep not in already_seen:
94 if is_in_debian(dep):
d8ce2152 95 print_all('"%s" [fillcolor="%s",style=filled]' % (dep, BG_OLD_IN_DEBIAN))
b4000f35 96 else:
d8ce2152 97 print_all('"%s" [fillcolor="%s",style=filled]' % (dep, BG_NOT_IN_DEBIAN))
b4000f35
SL
98 for edge in edges:
99 print(edge, file=rust_excuses)
100
101 for dep in dependencies.get("migrate-after", []) + dependencies.get(
102 "blocked-by", []
103 ):
104 if "/" in dep:
105 dep, arch = dep.split("/")
106 print(edge_dep_label(name, dep, arch), file=rust_excuses_arch)
107 else:
108 print_all(edge_dep(name, dep))
109 traverse(dep, arch, d + 1)
110
d8ce2152 111 policy = excuses.get(name, {}).get("policy_info", {})
a2ba87f9 112 failed = {k: v["verdict"] for (k, v) in policy.items() if v.get("verdict", "") != "PASS"}
d8ce2152
XL
113 attrs = {"shape": "box"}
114 if "age" in failed:
a2ba87f9 115 del failed["age"]
d8ce2152 116 attrs.update({ "fillcolor": BG_TOO_NEW, "style": "filled" })
60c13697
XL
117 if "autopkgtest" in failed:
118 for k, v in policy["autopkgtest"].items():
119 if k == "verdict": continue
120 for uu in v.values():
121 if "REGRESSION" in uu:
122 for u in uu:
123 if u and u.startswith("https://ci.debian.net/data/autopkgtest/testing"):
124 print(u, file=rust_regressions)
d8ce2152 125 if failed:
a2ba87f9
XL
126 if list(failed.keys()) == ["builtonbuildd"]:
127 bg = BG_SOURCEONLY
128 attrs.update({ "label": "\\N\\nneeds source-only upload" })
129 elif any(v in VERDICT_FAIL for v in failed.values()):
130 bg = BG_MISC_FAIL
131 attrs.update({ "label": "\\N\\nfailed: %s" % ",".join(failed.keys()) })
132 else:
133 bg = BG_MISC_WAIT
134 attrs.update({ "label": "\\N\\nwaiting: %s" % ",".join(failed.keys()) })
508cd1b3 135 attrs.update({ "fillcolor": bg, "style": "filled" })
d8ce2152 136 print_all('"%s" [%s]' % (name, ",".join("%s=\"%s\"" % p for p in attrs.items())))
b4000f35
SL
137
138
139# import code
140# code.interact(local=locals())
141
d166a967 142
1db6a00b
XL
143print_all("digraph {")
144for s in excuses.keys():
b4000f35
SL
145 if s.startswith("rust-"):
146 traverse(s)
1db6a00b 147print_all("}")