1
- use crate :: { GitHubContext , utils} ;
2
- use serde_yaml:: Value ;
1
+ #[ cfg( test) ]
2
+ mod tests;
3
+
3
4
use std:: collections:: BTreeMap ;
4
- use std:: path:: Path ;
5
5
6
6
use serde_yaml:: Value ;
7
7
@@ -65,13 +65,19 @@ pub struct JobDatabase {
65
65
}
66
66
67
67
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 ( )
68
+ /// Find `auto` jobs that correspond to the passed `pattern`.
69
+ /// Patterns are matched using the glob syntax.
70
+ /// For example `dist-*` matches all jobs starting with `dist-`.
71
+ fn find_auto_jobs_by_pattern ( & self , pattern : & str ) -> Vec < Job > {
72
+ self . auto_jobs
73
+ . iter ( )
74
+ . filter ( |j| glob_match:: glob_match ( pattern, & j. name ) )
75
+ . cloned ( )
76
+ . collect ( )
70
77
}
71
78
}
72
79
73
- pub fn load_job_db ( path : & Path ) -> anyhow:: Result < JobDatabase > {
74
- let db = utils:: read_to_string ( path) ?;
80
+ pub fn load_job_db ( db : & str ) -> anyhow:: Result < JobDatabase > {
75
81
let mut db: Value = serde_yaml:: from_str ( & db) ?;
76
82
77
83
// We need to expand merge keys (<<), because serde_yaml can't deal with them
@@ -114,7 +120,7 @@ pub enum RunType {
114
120
/// Workflows that run after a push to a PR branch
115
121
PullRequest ,
116
122
/// Try run started with @bors try
117
- TryJob { custom_jobs : Option < Vec < String > > } ,
123
+ TryJob { job_patterns : Option < Vec < String > > } ,
118
124
/// Merge attempt workflow
119
125
AutoJob ,
120
126
}
@@ -130,28 +136,29 @@ fn calculate_jobs(
130
136
) -> anyhow:: Result < Vec < GithubActionsJob > > {
131
137
let ( jobs, prefix, base_env) = match run_type {
132
138
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
-
142
- 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
+ RunType :: TryJob { job_patterns } => {
140
+ let jobs = if let Some ( patterns) = job_patterns {
141
+ let mut jobs: Vec < Job > = vec ! [ ] ;
142
+ let mut unknown_patterns = vec ! [ ] ;
143
+ for pattern in patterns {
144
+ let matched_jobs = db. find_auto_jobs_by_pattern ( pattern) ;
145
+ if matched_jobs. is_empty ( ) {
146
+ unknown_patterns. push ( pattern. clone ( ) ) ;
147
147
} else {
148
- unknown_jobs . push ( custom_job . clone ( ) ) ;
148
+ jobs . extend ( matched_jobs ) ;
149
149
}
150
150
}
151
- if !unknown_jobs. is_empty ( ) {
151
+ if !unknown_patterns. is_empty ( ) {
152
+ return Err ( anyhow:: anyhow!(
153
+ "Patterns `{}` did not match any auto jobs" ,
154
+ unknown_patterns. join( ", " )
155
+ ) ) ;
156
+ }
157
+ if jobs. len ( ) > MAX_TRY_JOBS_COUNT {
152
158
return Err ( anyhow:: anyhow!(
153
- "Custom job(s) `{}` not found in auto jobs" ,
154
- unknown_jobs. join( ", " )
159
+ "It is only possible to schedule up to {MAX_TRY_JOBS_COUNT} custom jobs, received {} custom jobs expanded from {} pattern(s)" ,
160
+ jobs. len( ) ,
161
+ patterns. len( )
155
162
) ) ;
156
163
}
157
164
jobs
0 commit comments