1
- use std:: collections:: HashMap ;
2
- use std:: path:: Path ;
1
+ use std:: collections:: BTreeMap ;
2
+ use std:: path:: { Path , PathBuf } ;
3
3
use std:: process:: Command ;
4
4
5
5
use anyhow:: Context ;
@@ -17,13 +17,13 @@ struct Job {
17
17
name : String ,
18
18
/// GitHub runner on which the job should be executed
19
19
os : String ,
20
- env : HashMap < String , Value > ,
20
+ env : BTreeMap < String , Value > ,
21
21
/// Should the job be only executed on a specific channel?
22
22
#[ serde( default ) ]
23
23
only_on_channel : Option < String > ,
24
24
/// Rest of attributes that will be passed through to GitHub actions
25
25
#[ serde( flatten) ]
26
- extra_keys : HashMap < String , Value > ,
26
+ extra_keys : BTreeMap < String , Value > ,
27
27
}
28
28
29
29
impl Job {
@@ -44,11 +44,11 @@ impl Job {
44
44
#[ derive( serde:: Deserialize , Debug ) ]
45
45
struct JobEnvironments {
46
46
#[ serde( rename = "pr" ) ]
47
- pr_env : HashMap < String , Value > ,
47
+ pr_env : BTreeMap < String , Value > ,
48
48
#[ serde( rename = "try" ) ]
49
- try_env : HashMap < String , Value > ,
49
+ try_env : BTreeMap < String , Value > ,
50
50
#[ serde( rename = "auto" ) ]
51
- auto_env : HashMap < String , Value > ,
51
+ auto_env : BTreeMap < String , Value > ,
52
52
}
53
53
54
54
#[ derive( serde:: Deserialize , Debug ) ]
@@ -71,7 +71,7 @@ impl JobDatabase {
71
71
}
72
72
73
73
fn load_job_db ( path : & Path ) -> anyhow:: Result < JobDatabase > {
74
- let db = std :: fs :: read_to_string ( path) ?;
74
+ let db = read_to_string ( path) ?;
75
75
let mut db: Value = serde_yaml:: from_str ( & db) ?;
76
76
77
77
// We need to expand merge keys (<<), because serde_yaml can't deal with them
@@ -92,9 +92,9 @@ struct GithubActionsJob {
92
92
/// prefix (PR/try/auto).
93
93
full_name : String ,
94
94
os : String ,
95
- env : HashMap < String , String > ,
95
+ env : BTreeMap < String , String > ,
96
96
#[ serde( flatten) ]
97
- extra_keys : HashMap < String , serde_json:: Value > ,
97
+ extra_keys : BTreeMap < String , serde_json:: Value > ,
98
98
}
99
99
100
100
/// Type of workflow that is being executed on CI
@@ -116,27 +116,17 @@ struct GitHubContext {
116
116
117
117
impl GitHubContext {
118
118
fn get_run_type ( & self ) -> Option < RunType > {
119
- if self . event_name == "pull_request" {
120
- return Some ( RunType :: PullRequest ) ;
121
- } else if self . event_name == "push" {
122
- let is_try_build =
123
- [ "refs/heads/try" , "refs/heads/try-perf" , "refs/heads/automation/bors/try" ]
124
- . iter ( )
125
- . any ( |r| * * r == self . branch_ref ) ;
126
- // Unrolled branch from a rollup for testing perf
127
- // This should **not** allow custom try jobs
128
- let is_unrolled_perf_build = self . branch_ref == "refs/heads/try-perf" ;
129
- if is_try_build {
130
- let custom_jobs =
131
- if !is_unrolled_perf_build { Some ( self . get_custom_jobs ( ) ) } else { None } ;
132
- return Some ( RunType :: TryJob { custom_jobs } ) ;
133
- }
134
-
135
- if self . branch_ref == "refs/heads/auto" {
136
- return Some ( RunType :: AutoJob ) ;
119
+ match ( self . event_name . as_str ( ) , self . branch_ref . as_str ( ) ) {
120
+ ( "pull_request" , _) => Some ( RunType :: PullRequest ) ,
121
+ ( "push" , "refs/heads/try-perf" ) => Some ( RunType :: TryJob { custom_jobs : None } ) ,
122
+ ( "push" , "refs/heads/try" | "refs/heads/automation/bors/try" ) => {
123
+ let custom_jobs = self . get_custom_jobs ( ) ;
124
+ let custom_jobs = if !custom_jobs. is_empty ( ) { Some ( custom_jobs) } else { None } ;
125
+ Some ( RunType :: TryJob { custom_jobs } )
137
126
}
127
+ ( "push" , "refs/heads/auto" ) => Some ( RunType :: AutoJob ) ,
128
+ _ => None ,
138
129
}
139
- None
140
130
}
141
131
142
132
/// Tries to parse names of specific CI jobs that should be executed in the form of
@@ -175,7 +165,7 @@ fn skip_jobs(jobs: Vec<Job>, channel: &str) -> Vec<Job> {
175
165
. collect ( )
176
166
}
177
167
178
- fn to_string_map ( map : & HashMap < String , Value > ) -> HashMap < String , String > {
168
+ fn to_string_map ( map : & BTreeMap < String , Value > ) -> BTreeMap < String , String > {
179
169
map. iter ( )
180
170
. map ( |( key, value) | {
181
171
(
@@ -232,7 +222,7 @@ fn calculate_jobs(
232
222
let jobs = jobs
233
223
. into_iter ( )
234
224
. map ( |job| {
235
- let mut env: HashMap < String , String > = to_string_map ( base_env) ;
225
+ let mut env: BTreeMap < String , String > = to_string_map ( base_env) ;
236
226
env. extend ( to_string_map ( & job. env ) ) ;
237
227
let full_name = format ! ( "{prefix} - {}" , job. name) ;
238
228
@@ -312,9 +302,9 @@ fn run_workflow_locally(db: JobDatabase, job_type: JobType, name: String) -> any
312
302
JobType :: Auto => & db. auto_jobs ,
313
303
JobType :: PR => & db. pr_jobs ,
314
304
} ;
315
- let job = find_linux_job ( & jobs, & name) . with_context ( || format ! ( "Cannot find job {name}" ) ) ?;
305
+ let job = find_linux_job ( jobs, & name) . with_context ( || format ! ( "Cannot find job {name}" ) ) ?;
316
306
317
- let mut custom_env: HashMap < String , String > = HashMap :: new ( ) ;
307
+ let mut custom_env: BTreeMap < String , String > = BTreeMap :: new ( ) ;
318
308
// Replicate src/ci/scripts/setup-environment.sh
319
309
// Adds custom environment variables to the job
320
310
if name. starts_with ( "dist-" ) {
@@ -340,7 +330,10 @@ fn run_workflow_locally(db: JobDatabase, job_type: JobType, name: String) -> any
340
330
enum Args {
341
331
/// Calculate a list of jobs that should be executed on CI.
342
332
/// Should only be used on CI inside GitHub actions.
343
- CalculateJobMatrix ,
333
+ CalculateJobMatrix {
334
+ #[ clap( long) ]
335
+ jobs_file : Option < PathBuf > ,
336
+ } ,
344
337
/// Execute a given CI job locally.
345
338
#[ clap( name = "run-local" ) ]
346
339
RunJobLocally {
@@ -362,19 +355,29 @@ enum JobType {
362
355
363
356
fn main ( ) -> anyhow:: Result < ( ) > {
364
357
let args = Args :: parse ( ) ;
365
- let db = load_job_db ( Path :: new ( JOBS_YML_PATH ) ) . context ( "Cannot load jobs.yml" ) ?;
358
+ let default_jobs_file = Path :: new ( JOBS_YML_PATH ) ;
359
+ let load_db = |jobs_path| load_job_db ( jobs_path) . context ( "Cannot load jobs.yml" ) ;
366
360
367
361
match args {
368
- Args :: CalculateJobMatrix => {
362
+ Args :: CalculateJobMatrix { jobs_file } => {
363
+ let jobs_path = jobs_file. as_deref ( ) . unwrap_or ( default_jobs_file) ;
369
364
let gh_ctx = load_github_ctx ( )
370
365
. context ( "Cannot load environment variables from GitHub Actions" ) ?;
371
- let channel = std :: fs :: read_to_string ( Path :: new ( CI_DIRECTORY ) . join ( "channel" ) )
366
+ let channel = read_to_string ( Path :: new ( CI_DIRECTORY ) . join ( "channel" ) )
372
367
. context ( "Cannot read channel file" ) ?;
373
368
374
- calculate_job_matrix ( db, gh_ctx, & channel) . context ( "Failed to calculate job matrix" ) ?;
369
+ calculate_job_matrix ( load_db ( jobs_path) ?, gh_ctx, & channel)
370
+ . context ( "Failed to calculate job matrix" ) ?;
371
+ }
372
+ Args :: RunJobLocally { job_type, name } => {
373
+ run_workflow_locally ( load_db ( default_jobs_file) ?, job_type, name) ?
375
374
}
376
- Args :: RunJobLocally { job_type, name } => run_workflow_locally ( db, job_type, name) ?,
377
375
}
378
376
379
377
Ok ( ( ) )
380
378
}
379
+
380
+ fn read_to_string < P : AsRef < Path > > ( path : P ) -> anyhow:: Result < String > {
381
+ let error = format ! ( "Cannot read file {:?}" , path. as_ref( ) ) ;
382
+ std:: fs:: read_to_string ( path) . context ( error)
383
+ }
0 commit comments