@@ -27,14 +27,16 @@ def _parse_ninja_log(ninja_log: list[str]) -> list[tuple[str, str]]:
27
27
# We hit the end of the log without finding a build failure, go to
28
28
# the next log.
29
29
return failures
30
+ # index will point to the line that starts with Failed:. The progress
31
+ # indicator is the line before this and contains a pretty printed version
32
+ # of the target being built. We use this and remove the progress information
33
+ # to get a succinct name for the target.
30
34
failing_action = ninja_log [index - 1 ].split ("] " )[1 ]
31
35
failure_log = []
32
36
while (
33
37
index < len (ninja_log )
34
38
and not ninja_log [index ].startswith ("[" )
35
- and not ninja_log [index ].startswith (
36
- "ninja: build stopped: subcommand failed"
37
- )
39
+ and not ninja_log [index ].startswith ("ninja: build stopped:" )
38
40
and len (failure_log ) < NINJA_LOG_SIZE_THRESHOLD
39
41
):
40
42
failure_log .append (ninja_log [index ])
@@ -46,7 +48,7 @@ def _parse_ninja_log(ninja_log: list[str]) -> list[tuple[str, str]]:
46
48
def find_failure_in_ninja_logs (ninja_logs : list [list [str ]]) -> list [tuple [str , str ]]:
47
49
"""Extracts failure messages from ninja output.
48
50
49
- This patch takes stdout/stderr from ninja in the form of a list of files
51
+ This function takes stdout/stderr from ninja in the form of a list of files
50
52
represented as a list of lines. This function then returns tuples containing
51
53
the name of the target and the error message.
52
54
@@ -65,6 +67,25 @@ def find_failure_in_ninja_logs(ninja_logs: list[list[str]]) -> list[tuple[str, s
65
67
return failures
66
68
67
69
70
+ def _format_ninja_failures (ninja_failures : list [tuple [str , str ]]) -> list [str ]:
71
+ """Formats ninja failures into summary views for the report."""
72
+ output = []
73
+ for build_failure in ninja_failures :
74
+ failed_action , failure_message = build_failure
75
+ output .extend (
76
+ [
77
+ "<details>" ,
78
+ f"<summary>{ failed_action } </summary>" ,
79
+ "" ,
80
+ "```" ,
81
+ failure_message ,
82
+ "```" ,
83
+ "</details>" ,
84
+ ]
85
+ )
86
+ return output
87
+
88
+
68
89
# Set size_limit to limit the byte size of the report. The default is 1MB as this
69
90
# is the most that can be put into an annotation. If the generated report exceeds
70
91
# this limit and failures are listed, it will be generated again without failures
@@ -129,24 +150,12 @@ def generate_report(
129
150
else :
130
151
report .extend (
131
152
[
132
- "The build failed before running any tests. Click on the "
153
+ "The build failed before running any tests. Click on a "
133
154
"failure below to see the details." ,
134
155
"" ,
135
156
]
136
157
)
137
- for build_failure in ninja_failures :
138
- failed_action , failure_message = build_failure
139
- report .extend (
140
- [
141
- "<details>" ,
142
- f"<summary>{ failed_action } </summary>" ,
143
- "" ,
144
- "```" ,
145
- failure_message ,
146
- "```" ,
147
- "</details>" ,
148
- ]
149
- )
158
+ report .extend (_format_ninja_failures (ninja_failures ))
150
159
report .extend (
151
160
[
152
161
"" ,
@@ -203,26 +212,14 @@ def plural(num_tests):
203
212
[
204
213
"" ,
205
214
"All tests passed but another part of the build **failed**. "
206
- "Detailed information about the build failure could not be "
207
- "automatically obtained." ,
215
+ "Information about the build failure could not be automatically "
216
+ "obtained." ,
208
217
"" ,
209
218
SEE_BUILD_FILE_STR ,
210
219
]
211
220
)
212
221
else :
213
- for build_failure in ninja_failures :
214
- failed_action , failure_message = build_failure
215
- report .extend (
216
- [
217
- "<details>" ,
218
- f"<summary>{ failed_action } </summary>" ,
219
- "" ,
220
- "```" ,
221
- failure_message ,
222
- "```" ,
223
- "</details>" ,
224
- ]
225
- )
222
+ report .extend (_format_ninja_failures (ninja_failures ))
226
223
227
224
if failures or return_code != 0 :
228
225
report .extend (["" , UNRELATED_FAILURES_STR ])
0 commit comments