1
- use crate :: { GitHubContext , utils} ;
2
- use serde_yaml:: Value ;
3
1
use std:: collections:: BTreeMap ;
4
- use std:: path:: Path ;
5
2
6
3
use serde_yaml:: Value ;
7
4
@@ -65,13 +62,19 @@ pub struct JobDatabase {
65
62
}
66
63
67
64
impl JobDatabase {
68
- fn find_auto_job_by_name ( & self , name : & str ) -> Option < Job > {
69
- self . auto_jobs . iter ( ) . find ( |j| j. name == name) . cloned ( )
65
+ /// Find `auto` jobs that correspond to the passed `pattern`.
66
+ /// Patterns are matched using the glob syntax.
67
+ /// For example `dist-*` matches all jobs starting with `dist-`.
68
+ fn find_auto_jobs_by_patter ( & self , pattern : & str ) -> Vec < Job > {
69
+ self . auto_jobs
70
+ . iter ( )
71
+ . filter ( |j| glob_match:: glob_match ( pattern, & j. name ) )
72
+ . cloned ( )
73
+ . collect ( )
70
74
}
71
75
}
72
76
73
- pub fn load_job_db ( path : & Path ) -> anyhow:: Result < JobDatabase > {
74
- let db = utils:: read_to_string ( path) ?;
77
+ pub fn load_job_db ( db : & str ) -> anyhow:: Result < JobDatabase > {
75
78
let mut db: Value = serde_yaml:: from_str ( & db) ?;
76
79
77
80
// We need to expand merge keys (<<), because serde_yaml can't deal with them
@@ -114,7 +117,7 @@ pub enum RunType {
114
117
/// Workflows that run after a push to a PR branch
115
118
PullRequest ,
116
119
/// Try run started with @bors try
117
- TryJob { custom_jobs : Option < Vec < String > > } ,
120
+ TryJob { job_patterns : Option < Vec < String > > } ,
118
121
/// Merge attempt workflow
119
122
AutoJob ,
120
123
}
@@ -130,28 +133,29 @@ fn calculate_jobs(
130
133
) -> anyhow:: Result < Vec < GithubActionsJob > > {
131
134
let ( jobs, prefix, base_env) = match run_type {
132
135
RunType :: PullRequest => ( db. pr_jobs . clone ( ) , "PR" , & db. envs . pr_env ) ,
133
- RunType :: TryJob { custom_jobs } => {
134
- let jobs = if let Some ( custom_jobs) = custom_jobs {
135
- if custom_jobs. len ( ) > MAX_TRY_JOBS_COUNT {
136
- return Err ( anyhow:: anyhow!(
137
- "It is only possible to schedule up to {MAX_TRY_JOBS_COUNT} custom jobs, received {} custom jobs" ,
138
- custom_jobs. len( )
139
- ) ) ;
140
- }
141
-
136
+ RunType :: TryJob { job_patterns } => {
137
+ let jobs = if let Some ( patterns) = job_patterns {
142
138
let mut jobs = vec ! [ ] ;
143
- let mut unknown_jobs = vec ! [ ] ;
144
- for custom_job in custom_jobs {
145
- if let Some ( job) = db. find_auto_job_by_name ( custom_job) {
146
- jobs. push ( job) ;
139
+ let mut unknown_patterns = vec ! [ ] ;
140
+ for pattern in patterns {
141
+ let matched_jobs = db. find_auto_jobs_by_patter ( pattern) ;
142
+ if matched_jobs. is_empty ( ) {
143
+ unknown_patterns. push ( pattern. clone ( ) ) ;
147
144
} else {
148
- unknown_jobs . push ( custom_job . clone ( ) ) ;
145
+ jobs . extend ( matched_jobs ) ;
149
146
}
150
147
}
151
- if !unknown_jobs. is_empty ( ) {
148
+ if !unknown_patterns. is_empty ( ) {
149
+ return Err ( anyhow:: anyhow!(
150
+ "Patterns `{}` did not match any auto jobs" ,
151
+ unknown_patterns. join( ", " )
152
+ ) ) ;
153
+ }
154
+ if jobs. len ( ) > MAX_TRY_JOBS_COUNT {
152
155
return Err ( anyhow:: anyhow!(
153
- "Custom job(s) `{}` not found in auto jobs" ,
154
- unknown_jobs. join( ", " )
156
+ "It is only possible to schedule up to {MAX_TRY_JOBS_COUNT} custom jobs, received {} custom jobs expanded from {} pattern(s)" ,
157
+ jobs. len( ) ,
158
+ patterns. len( )
155
159
) ) ;
156
160
}
157
161
jobs
@@ -231,3 +235,75 @@ pub fn find_linux_job<'a>(jobs: &'a [Job], name: &str) -> anyhow::Result<&'a Job
231
235
232
236
Ok ( job)
233
237
}
238
+
239
+ #[ cfg( test) ]
240
+ mod tests {
241
+ use crate :: jobs:: { JobDatabase , load_job_db} ;
242
+
243
+ #[ test]
244
+ fn lookup_job_pattern ( ) {
245
+ let db = load_job_db (
246
+ r#"
247
+ envs:
248
+ pr:
249
+ try:
250
+ auto:
251
+
252
+ pr:
253
+ try:
254
+ auto:
255
+ - name: dist-a
256
+ os: ubuntu
257
+ env: {}
258
+ - name: dist-a-alt
259
+ os: ubuntu
260
+ env: {}
261
+ - name: dist-b
262
+ os: ubuntu
263
+ env: {}
264
+ - name: dist-b-alt
265
+ os: ubuntu
266
+ env: {}
267
+ - name: test-a
268
+ os: ubuntu
269
+ env: {}
270
+ - name: test-a-alt
271
+ os: ubuntu
272
+ env: {}
273
+ - name: test-i686
274
+ os: ubuntu
275
+ env: {}
276
+ - name: dist-i686
277
+ os: ubuntu
278
+ env: {}
279
+ - name: test-msvc-i686-1
280
+ os: ubuntu
281
+ env: {}
282
+ - name: test-msvc-i686-2
283
+ os: ubuntu
284
+ env: {}
285
+ "# ,
286
+ )
287
+ . unwrap ( ) ;
288
+ check_pattern (
289
+ & db,
290
+ "dist-*" ,
291
+ & [ "dist-a" , "dist-a-alt" , "dist-b" , "dist-b-alt" , "dist-i686" ] ,
292
+ ) ;
293
+ check_pattern ( & db, "*-alt" , & [ "dist-a-alt" , "dist-b-alt" , "test-a-alt" ] ) ;
294
+ check_pattern ( & db, "dist*-alt" , & [ "dist-a-alt" , "dist-b-alt" ] ) ;
295
+ check_pattern (
296
+ & db,
297
+ "*i686*" ,
298
+ & [ "test-i686" , "dist-i686" , "test-msvc-i686-1" , "test-msvc-i686-2" ] ,
299
+ ) ;
300
+ }
301
+
302
+ #[ track_caller]
303
+ fn check_pattern ( db : & JobDatabase , pattern : & str , expected : & [ & str ] ) {
304
+ let jobs =
305
+ db. find_auto_jobs_by_patter ( pattern) . into_iter ( ) . map ( |j| j. name ) . collect :: < Vec < _ > > ( ) ;
306
+
307
+ assert_eq ! ( jobs, expected) ;
308
+ }
309
+ }
0 commit comments