1
1
use bazelfe_bazel_wrapper:: bep:: build_events:: build_event_server:: BuildEventAction ;
2
2
use bazelfe_core:: bep_junit:: {
3
3
emit_backup_error_data, emit_junit_xml_from_aborted_action, emit_junit_xml_from_failed_action,
4
- label_to_junit_relative_path, suites_with_error_from_xml ,
4
+ label_to_junit_relative_path,
5
5
} ;
6
6
7
7
use bazelfe_bazel_wrapper:: bep:: build_events:: hydrated_stream:: { HydratedInfo , HydratorState } ;
@@ -10,6 +10,7 @@ use clap::Parser;
10
10
use prost:: Message ;
11
11
use std:: collections:: VecDeque ;
12
12
use std:: error:: Error ;
13
+ use std:: os:: unix:: fs:: MetadataExt ;
13
14
use std:: path:: { Path , PathBuf } ;
14
15
15
16
#[ derive( Parser , Debug ) ]
@@ -77,19 +78,26 @@ async fn main() -> Result<(), Box<dyn Error>> {
77
78
let mut failed_actions = Vec :: default ( ) ;
78
79
let mut aborted_actions = Vec :: default ( ) ;
79
80
let mut failed_tests = Vec :: default ( ) ;
81
+ let mut failed_xml_writes = Vec :: default ( ) ;
80
82
for build_event in hydrated_infos. into_iter ( ) {
81
- match build_event {
83
+ match & build_event {
82
84
HydratedInfo :: BazelAbort ( abort_info) => {
83
- emit_junit_xml_from_aborted_action (
85
+ aborted_actions. push ( abort_info. label . clone ( ) ) ;
86
+ match emit_junit_xml_from_aborted_action (
84
87
& abort_info,
85
88
aborted_actions. len ( ) ,
86
89
& opt. junit_output_path ,
87
- ) ;
88
- aborted_actions. push ( abort_info. label ) ;
90
+ ) {
91
+ Ok ( _) => ( ) ,
92
+ Err ( e) => failed_xml_writes. push ( ( build_event, e) ) ,
93
+ }
89
94
}
90
95
HydratedInfo :: ActionFailed ( action_failed) => {
91
- emit_junit_xml_from_failed_action ( & action_failed, & opt. junit_output_path ) ;
92
- failed_actions. push ( action_failed. label ) ;
96
+ failed_actions. push ( action_failed. label . clone ( ) ) ;
97
+ match emit_junit_xml_from_failed_action ( action_failed, & opt. junit_output_path ) {
98
+ Ok ( _) => ( ) ,
99
+ Err ( e) => failed_xml_writes. push ( ( build_event, e) ) ,
100
+ }
93
101
}
94
102
HydratedInfo :: TestResult ( r) => {
95
103
let is_failure = r. test_summary_event . test_status . didnt_pass ( ) ;
@@ -99,35 +107,60 @@ async fn main() -> Result<(), Box<dyn Error>> {
99
107
let output_folder = opt. junit_output_path . join ( label_to_junit_relative_path (
100
108
r. test_summary_event . label . as_str ( ) ,
101
109
) ) ;
102
- std:: fs:: create_dir_all ( & output_folder) . expect ( "Make dir failed" ) ;
103
-
104
- let files: Vec < & str > = r
105
- . test_summary_event
106
- . output_files
107
- . iter ( )
108
- . flat_map ( |e| match e {
109
- bazelfe_protos:: build_event_stream:: file:: File :: Uri ( uri) => {
110
- let p = uri
111
- . strip_prefix ( "file://" )
112
- . unwrap_or_else ( || panic ! ( "Wasn't a local file for {}" , uri) ) ;
113
- if p. ends_with ( "/test.xml" ) {
114
- Some ( p)
115
- } else {
116
- None
110
+
111
+ match std:: fs:: create_dir_all ( & output_folder) {
112
+ Ok ( _) => {
113
+ let files: Vec < & str > = r
114
+ . test_summary_event
115
+ . output_files
116
+ . iter ( )
117
+ . flat_map ( |e| match e {
118
+ bazelfe_protos:: build_event_stream:: file:: File :: Uri ( uri) => {
119
+ let p = uri. strip_prefix ( "file://" ) . unwrap_or_else ( || {
120
+ panic ! ( "Wasn't a local file for {}" , uri)
121
+ } ) ;
122
+ if p. ends_with ( "/test.xml" ) {
123
+ Some ( p)
124
+ } else {
125
+ None
126
+ }
127
+ }
128
+ bazelfe_protos:: build_event_stream:: file:: File :: Contents ( _) => None ,
129
+ } )
130
+ . collect ( ) ;
131
+
132
+ for ( idx, f) in files. into_iter ( ) . enumerate ( ) {
133
+ match std:: fs:: metadata ( f) {
134
+ Ok ( m) => {
135
+ if m. size ( ) > 0 {
136
+ let output_file = output_folder. join ( format ! ( "test.{}.xml" , idx) ) ;
137
+ match std:: fs:: copy ( f, output_file) {
138
+ Ok ( _) => ( ) ,
139
+ Err ( e) =>
140
+ println ! ( "could not access metadata for test result {} at file {}.\n Error {}" ,
141
+ r. test_summary_event. label,
142
+ f,
143
+ e)
144
+ }
117
145
}
146
+ }
147
+ Err ( e) =>
148
+ println ! ( "could not access metadata for test result {} at file {}.\n Error {}" ,
149
+ r. test_summary_event. label,
150
+ f,
151
+ e)
118
152
}
119
- bazelfe_protos:: build_event_stream:: file:: File :: Contents ( _) => None ,
120
- } )
121
- . collect ( ) ;
122
-
123
- if is_failure {
124
- // Some failures don't get to the phase of writing junit output
125
- // this ensures we write something
126
- emit_backup_error_data ( & r, & opt. junit_output_path ) ;
127
- }
128
- for ( idx, f) in files. into_iter ( ) . enumerate ( ) {
129
- let output_file = output_folder. join ( format ! ( "test.{}.xml" , idx) ) ;
130
- std:: fs:: copy ( f, output_file) . unwrap ( ) ;
153
+ }
154
+ if is_failure {
155
+ // Some failures don't get to the phase of writing junit output
156
+ // this ensures we write something
157
+ match emit_backup_error_data ( & r, & opt. junit_output_path ) {
158
+ Ok ( _) => ( ) ,
159
+ Err ( err) => failed_xml_writes. push ( ( build_event, err) ) ,
160
+ }
161
+ }
162
+ }
163
+ Err ( e) => failed_xml_writes. push ( ( build_event, e. into ( ) ) ) ,
131
164
}
132
165
}
133
166
HydratedInfo :: Progress ( _) => ( ) ,
@@ -136,32 +169,53 @@ async fn main() -> Result<(), Box<dyn Error>> {
136
169
}
137
170
}
138
171
139
- if failed_actions. is_empty ( ) && failed_tests. is_empty ( ) && aborted_actions. is_empty ( ) {
140
- println ! ( "Have zero failures, all successful." )
172
+ if failed_actions. is_empty ( )
173
+ && failed_tests. is_empty ( )
174
+ && aborted_actions. is_empty ( )
175
+ && failed_xml_writes. is_empty ( )
176
+ {
177
+ println ! ( "Have zero failures, all successful." ) ;
178
+ Ok ( ( ) )
141
179
} else {
142
180
if !failed_actions. is_empty ( ) {
143
181
println ! ( "Have {} failed actions" , failed_actions. len( ) ) ;
144
- for a in failed_actions. iter ( ) {
182
+ for a in failed_actions {
145
183
println ! ( " - {}" , a) ;
146
184
}
147
185
}
148
186
149
187
if !failed_tests. is_empty ( ) {
150
188
println ! ( "Have {} failed tests" , failed_tests. len( ) ) ;
151
- for a in failed_tests. iter ( ) {
189
+ failed_tests. sort ( ) ;
190
+ for a in failed_tests {
152
191
println ! ( " - {}" , a) ;
153
192
}
154
193
}
155
194
156
195
if !aborted_actions. is_empty ( ) {
157
196
println ! ( "Have {} aborted actions" , aborted_actions. len( ) ) ;
158
- for a in aborted_actions. iter ( ) {
197
+ aborted_actions. sort ( ) ;
198
+ for a in aborted_actions {
199
+ println ! ( " - {}" , a. unwrap_or_else( || "Unknown" . to_string( ) ) ) ;
200
+ }
201
+ }
202
+
203
+ if !failed_xml_writes. is_empty ( ) {
204
+ println ! ( "Got {} xml write failures" , failed_xml_writes. len( ) ) ;
205
+ failed_xml_writes. sort_by ( |p1, p2| p1. 0 . label ( ) . cmp ( & p2. 0 . label ( ) ) ) ;
206
+ for ( r, err) in failed_xml_writes {
159
207
println ! (
160
- " - {}" ,
161
- a. to_owned( ) . unwrap_or_else( || "Unknown" . to_string( ) )
208
+ "Target label = {} failed to write: {}" ,
209
+ r. label( ) . unwrap_or( "<unknown>" ) ,
210
+ err
162
211
) ;
163
212
}
164
213
}
214
+
215
+ let err: Box < dyn Error > = Box :: new ( std:: io:: Error :: new (
216
+ std:: io:: ErrorKind :: Other ,
217
+ "non-zero error count." ,
218
+ ) ) ;
219
+ Err ( err)
165
220
}
166
- Ok ( ( ) )
167
221
}
0 commit comments