@@ -14,6 +14,13 @@ use std::io::BufWriter;
14
14
use std:: time:: { Duration , Instant , SystemTime } ;
15
15
use sysinfo:: { CpuExt , System , SystemExt } ;
16
16
17
+ // Update this number whenever a breaking change is made to the build metrics.
18
+ //
19
+ // Versions:
20
+ // 0: initial version
21
+ // 1: replaced JsonNode::Test with JsonNode::TestSuite
22
+ const CURRENT_METADATA_VERSION : usize = 1 ;
23
+
17
24
pub ( crate ) struct BuildMetrics {
18
25
state : RefCell < MetricsState > ,
19
26
}
@@ -145,7 +152,20 @@ impl BuildMetrics {
145
152
// Some of our CI builds consist of multiple independent CI invocations. Ensure all the
146
153
// previous invocations are still present in the resulting file.
147
154
let mut invocations = match std:: fs:: read ( & dest) {
148
- Ok ( contents) => t ! ( serde_json:: from_slice:: <JsonRoot >( & contents) ) . invocations ,
155
+ Ok ( contents) => {
156
+ // We first parse just the metadata_version field to have the check succeed even if
157
+ // the rest of the contents are not valid anymore.
158
+ let version: OnlyMetadataVersion = t ! ( serde_json:: from_slice( & contents) ) ;
159
+ if version. metadata_version == CURRENT_METADATA_VERSION {
160
+ t ! ( serde_json:: from_slice:: <JsonRoot >( & contents) ) . invocations
161
+ } else {
162
+ println ! (
163
+ "warning: overriding existing build/metrics.json, as it's not \
164
+ compatible with build metrics format version {CURRENT_METADATA_VERSION}."
165
+ ) ;
166
+ Vec :: new ( )
167
+ }
168
+ }
149
169
Err ( err) => {
150
170
if err. kind ( ) != std:: io:: ErrorKind :: NotFound {
151
171
panic ! ( "failed to open existing metrics file at {}: {err}" , dest. display( ) ) ;
@@ -163,7 +183,8 @@ impl BuildMetrics {
163
183
children : steps. into_iter ( ) . map ( |step| self . prepare_json_step ( step) ) . collect ( ) ,
164
184
} ) ;
165
185
166
- let json = JsonRoot { system_stats, invocations } ;
186
+ let json =
187
+ JsonRoot { metadata_version : CURRENT_METADATA_VERSION , system_stats, invocations } ;
167
188
168
189
t ! ( std:: fs:: create_dir_all( dest. parent( ) . unwrap( ) ) ) ;
169
190
let mut file = BufWriter :: new ( t ! ( File :: create( & dest) ) ) ;
@@ -214,6 +235,8 @@ struct StepMetrics {
214
235
#[ derive( Serialize , Deserialize ) ]
215
236
#[ serde( rename_all = "snake_case" ) ]
216
237
struct JsonRoot {
238
+ #[ serde( default ) ] // For version 0 the field was not present.
239
+ metadata_version : usize ,
217
240
system_stats : JsonInvocationSystemStats ,
218
241
invocations : Vec < JsonInvocation > ,
219
242
}
@@ -299,3 +322,9 @@ struct JsonInvocationSystemStats {
299
322
struct JsonStepSystemStats {
300
323
cpu_utilization_percent : f64 ,
301
324
}
325
+
326
+ #[ derive( Deserialize ) ]
327
+ struct OnlyMetadataVersion {
328
+ #[ serde( default ) ] // For version 0 the field was not present.
329
+ metadata_version : usize ,
330
+ }
0 commit comments