Skip to content

Commit ea674a6

Browse files
Merge branch 'llvm:main' into solve_external_global_variable_issue
2 parents 63ae5de + 19043b2 commit ea674a6

File tree

14,883 files changed

+1229004
-337938
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

14,883 files changed

+1229004
-337938
lines changed

.ci/all_requirements.txt

Lines changed: 192 additions & 2 deletions
Large diffs are not rendered by default.

.ci/cache_lit_timing_files.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import glob
1818

1919
from google.cloud import storage
20+
from google.api_core import exceptions
2021

2122
GCS_PARALLELISM = 100
2223

@@ -50,7 +51,14 @@ def _maybe_download_timing_file(blob):
5051

5152
def download_timing_files(storage_client, bucket_name: str):
5253
bucket = storage_client.bucket(bucket_name)
53-
blobs = bucket.list_blobs(prefix="lit_timing")
54+
try:
55+
blobs = bucket.list_blobs(prefix="lit_timing")
56+
except exceptions.ClientError as client_error:
57+
print(
58+
"::warning file=cache_lit_timing_files.py::Failed to list blobs "
59+
"in bucket."
60+
)
61+
sys.exit(0)
5462
with multiprocessing.pool.ThreadPool(GCS_PARALLELISM) as thread_pool:
5563
futures = []
5664
for timing_file_blob in blobs:
@@ -60,7 +68,13 @@ def download_timing_files(storage_client, bucket_name: str):
6068
)
6169
)
6270
for future in futures:
63-
future.get()
71+
future.wait()
72+
if not future.successful():
73+
print(
74+
"::warning file=cache_lit_timing_files.py::Failed to "
75+
"download lit timing file."
76+
)
77+
continue
6478
print("Done downloading")
6579

6680

.ci/generate_test_report_github.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,9 @@
44
"""Script to generate a build report for Github."""
55

66
import argparse
7-
import platform
87

98
import generate_test_report_lib
109

11-
PLATFORM_TITLES = {
12-
"Windows": ":window: Windows x64 Test Results",
13-
"Linux": ":penguin: Linux x64 Test Results",
14-
}
1510

1611
if __name__ == "__main__":
1712
parser = argparse.ArgumentParser()
@@ -22,7 +17,9 @@
2217
args = parser.parse_args()
2318

2419
report = generate_test_report_lib.generate_report_from_files(
25-
PLATFORM_TITLES[platform.system()], args.return_code, args.build_test_logs
20+
generate_test_report_lib.compute_platform_title(),
21+
args.return_code,
22+
args.build_test_logs,
2623
)
2724

2825
print(report)

.ci/generate_test_report_lib.py

Lines changed: 85 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,22 @@
33
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
44
"""Library to parse JUnit XML files and return a markdown report."""
55

6+
from typing import TypedDict, Optional
7+
import platform
8+
69
from junitparser import JUnitXml, Failure
710

11+
12+
# This data structure should match the definition in llvm-zorg in
13+
# premerge/advisor/advisor_lib.py
14+
# TODO(boomanaiden154): Drop the Optional here and switch to str | None when
15+
# we require Python 3.10.
16+
class FailureExplanation(TypedDict):
17+
name: str
18+
explained: bool
19+
reason: Optional[str]
20+
21+
822
SEE_BUILD_FILE_STR = "Download the build's log file to see the details."
923
UNRELATED_FAILURES_STR = (
1024
"If these failures are unrelated to your changes (for example "
@@ -41,10 +55,12 @@ def _parse_ninja_log(ninja_log: list[str]) -> list[tuple[str, str]]:
4155
# touch test/4.stamp
4256
#
4357
# index will point to the line that starts with Failed:. The progress
44-
# indicator is the line before this ([4/5] test/4.stamp) and contains a pretty
45-
# printed version of the target being built (test/4.stamp). We use this line
46-
# and remove the progress information to get a succinct name for the target.
47-
failing_action = ninja_log[index - 1].split("] ")[1]
58+
# indicator is sometimes the line before this ([4/5] test/4.stamp) and
59+
# will contain a pretty printed version of the target being built
60+
# (test/4.stamp) when accurate. We instead parse the failed line rather
61+
# than the progress indicator as the progress indicator may not be
62+
# aligned with the failure.
63+
failing_action = ninja_log[index].split("FAILED: ")[1]
4864
failure_log = []
4965
while (
5066
index < len(ninja_log)
@@ -80,16 +96,29 @@ def find_failure_in_ninja_logs(ninja_logs: list[list[str]]) -> list[tuple[str, s
8096
return failures
8197

8298

83-
def _format_ninja_failures(ninja_failures: list[tuple[str, str]]) -> list[str]:
84-
"""Formats ninja failures into summary views for the report."""
99+
def _format_failures(
100+
failures: list[tuple[str, str]], failure_explanations: dict[str, FailureExplanation]
101+
) -> list[str]:
102+
"""Formats failures into summary views for the report."""
85103
output = []
86-
for build_failure in ninja_failures:
104+
for build_failure in failures:
87105
failed_action, failure_message = build_failure
106+
failure_explanation = None
107+
if failed_action in failure_explanations:
108+
failure_explanation = failure_explanations[failed_action]
109+
output.append("<details>")
110+
if failure_explanation:
111+
output.extend(
112+
[
113+
f"<summary>{failed_action} (Likely Already Failing)</summary>" "",
114+
failure_explanation["reason"],
115+
"",
116+
]
117+
)
118+
else:
119+
output.extend([f"<summary>{failed_action}</summary>", ""])
88120
output.extend(
89121
[
90-
"<details>",
91-
f"<summary>{failed_action}</summary>",
92-
"",
93122
"```",
94123
failure_message,
95124
"```",
@@ -99,6 +128,24 @@ def _format_ninja_failures(ninja_failures: list[tuple[str, str]]) -> list[str]:
99128
return output
100129

101130

131+
def get_failures(junit_objects) -> dict[str, list[tuple[str, str]]]:
132+
failures = {}
133+
for results in junit_objects:
134+
for testsuite in results:
135+
for test in testsuite:
136+
if (
137+
not test.is_passed
138+
and test.result
139+
and isinstance(test.result[0], Failure)
140+
):
141+
if failures.get(testsuite.name) is None:
142+
failures[testsuite.name] = []
143+
failures[testsuite.name].append(
144+
(test.classname + "/" + test.name, test.result[0].text)
145+
)
146+
return failures
147+
148+
102149
# Set size_limit to limit the byte size of the report. The default is 1MB as this
103150
# is the most that can be put into an annotation. If the generated report exceeds
104151
# this limit and failures are listed, it will be generated again without failures
@@ -112,30 +159,25 @@ def generate_report(
112159
ninja_logs: list[list[str]],
113160
size_limit=1024 * 1024,
114161
list_failures=True,
162+
failure_explanations_list: list[FailureExplanation] = [],
115163
):
116-
failures = {}
164+
failures = get_failures(junit_objects)
117165
tests_run = 0
118166
tests_skipped = 0
119167
tests_failed = 0
120168

169+
failure_explanations: dict[str, FailureExplanation] = {}
170+
for failure_explanation in failure_explanations_list:
171+
if not failure_explanation["explained"]:
172+
continue
173+
failure_explanations[failure_explanation["name"]] = failure_explanation
174+
121175
for results in junit_objects:
122176
for testsuite in results:
123177
tests_run += testsuite.tests
124178
tests_skipped += testsuite.skipped
125179
tests_failed += testsuite.failures
126180

127-
for test in testsuite:
128-
if (
129-
not test.is_passed
130-
and test.result
131-
and isinstance(test.result[0], Failure)
132-
):
133-
if failures.get(testsuite.name) is None:
134-
failures[testsuite.name] = []
135-
failures[testsuite.name].append(
136-
(test.classname + "/" + test.name, test.result[0].text)
137-
)
138-
139181
report = [f"# {title}", ""]
140182

141183
if tests_run == 0:
@@ -168,7 +210,7 @@ def generate_report(
168210
"",
169211
]
170212
)
171-
report.extend(_format_ninja_failures(ninja_failures))
213+
report.extend(_format_failures(ninja_failures, failure_explanations))
172214
report.extend(
173215
[
174216
"",
@@ -204,18 +246,7 @@ def plural(num_tests):
204246

205247
for testsuite_name, failures in failures.items():
206248
report.extend(["", f"### {testsuite_name}"])
207-
for name, output in failures:
208-
report.extend(
209-
[
210-
"<details>",
211-
f"<summary>{name}</summary>",
212-
"",
213-
"```",
214-
output,
215-
"```",
216-
"</details>",
217-
]
218-
)
249+
report.extend(_format_failures(failures, failure_explanations))
219250
elif return_code != 0:
220251
# No tests failed but the build was in a failed state. Bring this to the user's
221252
# attention.
@@ -240,7 +271,7 @@ def plural(num_tests):
240271
"",
241272
]
242273
)
243-
report.extend(_format_ninja_failures(ninja_failures))
274+
report.extend(_format_failures(ninja_failures, failure_explanations))
244275

245276
if failures or return_code != 0:
246277
report.extend(["", UNRELATED_FAILURES_STR])
@@ -258,7 +289,7 @@ def plural(num_tests):
258289
return report
259290

260291

261-
def generate_report_from_files(title, return_code, build_log_files):
292+
def load_info_from_files(build_log_files):
262293
junit_files = [
263294
junit_file for junit_file in build_log_files if junit_file.endswith(".xml")
264295
]
@@ -271,6 +302,19 @@ def generate_report_from_files(title, return_code, build_log_files):
271302
ninja_logs.append(
272303
[log_line.strip() for log_line in ninja_log_file_handle.readlines()]
273304
)
274-
return generate_report(
275-
title, return_code, [JUnitXml.fromfile(p) for p in junit_files], ninja_logs
276-
)
305+
return [JUnitXml.fromfile(p) for p in junit_files], ninja_logs
306+
307+
308+
def generate_report_from_files(title, return_code, build_log_files):
309+
junit_objects, ninja_logs = load_info_from_files(build_log_files)
310+
return generate_report(title, return_code, junit_objects, ninja_logs)
311+
312+
313+
def compute_platform_title() -> str:
314+
logo = ":window:" if platform.system() == "Windows" else ":penguin:"
315+
# On Linux the machine value is x86_64 on Windows it is AMD64.
316+
if platform.machine() == "x86_64" or platform.machine() == "AMD64":
317+
arch = "x64"
318+
else:
319+
arch = platform.machine()
320+
return f"{logo} {platform.system()} {arch} Test Results"

0 commit comments

Comments
 (0)