Skip to content

Commit 1ab2331

Browse files
committed
Merge remote-tracking branch 'upstream/dev' into dev
2 parents b9dead2 + 2ec2daf commit 1ab2331

File tree

18 files changed

+1681
-102
lines changed

18 files changed

+1681
-102
lines changed

.github/os-matrix.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"linux": [
3+
"ubuntu-22.04",
4+
"ubuntu-24.04"
5+
],
6+
"windows": [
7+
"windows-2022"
8+
]
9+
}
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
import json
2+
import os
3+
import sys
4+
from pathlib import Path
5+
6+
7+
def as_iterable(value):
8+
if value is None:
9+
return []
10+
if isinstance(value, (list, tuple, set)):
11+
return list(value)
12+
return [value]
13+
14+
15+
def main():
16+
workspace = Path(os.getenv("GITHUB_WORKSPACE", Path.cwd()))
17+
os_matrix_path = workspace / ".github" / "os-matrix.json"
18+
repros_path = workspace / "repros.json"
19+
20+
os_matrix = json.loads(os_matrix_path.read_text(encoding="utf-8"))
21+
platform_labels: dict[str, list[str]] = {}
22+
label_platform: dict[str, str] = {}
23+
24+
for platform, labels in os_matrix.items():
25+
normalized = platform.lower()
26+
platform_labels[normalized] = []
27+
for label in labels:
28+
platform_labels[normalized].append(label)
29+
label_platform[label] = normalized
30+
31+
all_labels = set(label_platform.keys())
32+
33+
payload = json.loads(repros_path.read_text(encoding="utf-8"))
34+
repros = payload.get("repros") or []
35+
36+
matrix_entries: list[dict[str, str]] = []
37+
skipped: list[str] = []
38+
unknown_platforms: set[str] = set()
39+
unknown_labels: set[str] = set()
40+
41+
def collect_labels(items, local_unknown):
42+
labels = set()
43+
for item in items:
44+
key = item.lower()
45+
if key in platform_labels:
46+
labels.update(platform_labels[key])
47+
else:
48+
local_unknown.add(key)
49+
unknown_platforms.add(key)
50+
return labels
51+
52+
for repro in repros:
53+
name = repro.get("name") or repro.get("id")
54+
if not name:
55+
continue
56+
57+
supports = as_iterable(repro.get("supports"))
58+
normalized_supports = {str(item).lower() for item in supports if isinstance(item, str)}
59+
60+
local_unknown_platforms: set[str] = set()
61+
local_unknown_labels: set[str] = set()
62+
63+
if not normalized_supports or "any" in normalized_supports:
64+
candidate_labels = set(all_labels)
65+
else:
66+
candidate_labels = collect_labels(normalized_supports, local_unknown_platforms)
67+
68+
os_constraints = repro.get("os") or {}
69+
include_platforms = {
70+
str(item).lower()
71+
for item in as_iterable(os_constraints.get("includePlatforms"))
72+
if isinstance(item, str)
73+
}
74+
include_labels = {
75+
str(item)
76+
for item in as_iterable(os_constraints.get("includeLabels"))
77+
if isinstance(item, str)
78+
}
79+
exclude_platforms = {
80+
str(item).lower()
81+
for item in as_iterable(os_constraints.get("excludePlatforms"))
82+
if isinstance(item, str)
83+
}
84+
exclude_labels = {
85+
str(item)
86+
for item in as_iterable(os_constraints.get("excludeLabels"))
87+
if isinstance(item, str)
88+
}
89+
90+
if include_platforms:
91+
candidate_labels &= collect_labels(include_platforms, local_unknown_platforms)
92+
93+
if include_labels:
94+
recognized_includes = {label for label in include_labels if label in label_platform}
95+
local_unknown_labels.update({label for label in include_labels if label not in label_platform})
96+
unknown_labels.update(local_unknown_labels)
97+
candidate_labels &= recognized_includes if recognized_includes else set()
98+
99+
if exclude_platforms:
100+
candidate_labels -= collect_labels(exclude_platforms, local_unknown_platforms)
101+
102+
if exclude_labels:
103+
recognized_excludes = {label for label in exclude_labels if label in label_platform}
104+
candidate_labels -= recognized_excludes
105+
unrecognized = {label for label in exclude_labels if label not in label_platform}
106+
local_unknown_labels.update(unrecognized)
107+
unknown_labels.update(unrecognized)
108+
109+
candidate_labels &= all_labels
110+
111+
if candidate_labels:
112+
for label in sorted(candidate_labels):
113+
matrix_entries.append(
114+
{
115+
"os": label,
116+
"repro": name,
117+
"platform": label_platform[label],
118+
}
119+
)
120+
else:
121+
reason_segments = []
122+
if normalized_supports:
123+
reason_segments.append(f"supports={sorted(normalized_supports)}")
124+
if os_constraints:
125+
reason_segments.append("os constraints applied")
126+
if local_unknown_platforms:
127+
reason_segments.append(f"unknown platforms={sorted(local_unknown_platforms)}")
128+
if local_unknown_labels:
129+
reason_segments.append(f"unknown labels={sorted(local_unknown_labels)}")
130+
reason = "; ".join(reason_segments) or "no matching runners"
131+
skipped.append(f"{name} ({reason})")
132+
133+
matrix_entries.sort(key=lambda entry: (entry["repro"], entry["os"]))
134+
135+
summary_lines = []
136+
summary_lines.append(f"Total repro jobs: {len(matrix_entries)}")
137+
if skipped:
138+
summary_lines.append("")
139+
summary_lines.append("Skipped repros:")
140+
for item in skipped:
141+
summary_lines.append(f"- {item}")
142+
if unknown_platforms:
143+
summary_lines.append("")
144+
summary_lines.append("Unknown platforms encountered:")
145+
for item in sorted(unknown_platforms):
146+
summary_lines.append(f"- {item}")
147+
if unknown_labels:
148+
summary_lines.append("")
149+
summary_lines.append("Unknown labels encountered:")
150+
for item in sorted(unknown_labels):
151+
summary_lines.append(f"- {item}")
152+
153+
summary_path = os.getenv("GITHUB_STEP_SUMMARY")
154+
if summary_path:
155+
with open(summary_path, "a", encoding="utf-8") as handle:
156+
handle.write("\n".join(summary_lines) + "\n")
157+
158+
outputs_path = os.getenv("GITHUB_OUTPUT")
159+
if not outputs_path:
160+
raise RuntimeError("GITHUB_OUTPUT is not defined.")
161+
162+
with open(outputs_path, "a", encoding="utf-8") as handle:
163+
handle.write("matrix=" + json.dumps({"include": matrix_entries}) + "\n")
164+
handle.write("count=" + str(len(matrix_entries)) + "\n")
165+
handle.write("skipped=" + json.dumps(skipped) + "\n")
166+
167+
168+
if __name__ == "__main__":
169+
try:
170+
main()
171+
except Exception as exc: # pragma: no cover - diagnostic output for CI
172+
print(f"Failed to compose repro matrix: {exc}", file=sys.stderr)
173+
raise

0 commit comments

Comments
 (0)