@@ -14,6 +14,13 @@ use std::io::BufWriter;
1414use std:: time:: { Duration , Instant , SystemTime } ;
1515use sysinfo:: { CpuExt , System , SystemExt } ;
1616
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+
1724pub ( crate ) struct BuildMetrics {
1825 state : RefCell < MetricsState > ,
1926}
@@ -145,7 +152,20 @@ impl BuildMetrics {
145152 // Some of our CI builds consist of multiple independent CI invocations. Ensure all the
146153 // previous invocations are still present in the resulting file.
147154 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+ }
149169 Err ( err) => {
150170 if err. kind ( ) != std:: io:: ErrorKind :: NotFound {
151171 panic ! ( "failed to open existing metrics file at {}: {err}" , dest. display( ) ) ;
@@ -163,7 +183,8 @@ impl BuildMetrics {
163183 children : steps. into_iter ( ) . map ( |step| self . prepare_json_step ( step) ) . collect ( ) ,
164184 } ) ;
165185
166- let json = JsonRoot { system_stats, invocations } ;
186+ let json =
187+ JsonRoot { metadata_version : CURRENT_METADATA_VERSION , system_stats, invocations } ;
167188
168189 t ! ( std:: fs:: create_dir_all( dest. parent( ) . unwrap( ) ) ) ;
169190 let mut file = BufWriter :: new ( t ! ( File :: create( & dest) ) ) ;
@@ -214,6 +235,8 @@ struct StepMetrics {
214235#[ derive( Serialize , Deserialize ) ]
215236#[ serde( rename_all = "snake_case" ) ]
216237struct JsonRoot {
238+ #[ serde( default ) ] // For version 0 the field was not present.
239+ metadata_version : usize ,
217240 system_stats : JsonInvocationSystemStats ,
218241 invocations : Vec < JsonInvocation > ,
219242}
@@ -299,3 +322,9 @@ struct JsonInvocationSystemStats {
299322struct JsonStepSystemStats {
300323 cpu_utilization_percent : f64 ,
301324}
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