1- use crate :: { GitHubContext , utils} ;
2- use serde_yaml:: Value ;
1+ #[ cfg( test) ]
2+ mod tests;
3+
34use std:: collections:: BTreeMap ;
4- use std:: path:: Path ;
55
66use serde_yaml:: Value ;
77
@@ -65,13 +65,19 @@ pub struct JobDatabase {
6565}
6666
6767impl 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 ( )
7077 }
7178}
7279
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 > {
7581 let mut db: Value = serde_yaml:: from_str ( & db) ?;
7682
7783 // We need to expand merge keys (<<), because serde_yaml can't deal with them
@@ -114,7 +120,7 @@ pub enum RunType {
114120 /// Workflows that run after a push to a PR branch
115121 PullRequest ,
116122 /// Try run started with @bors try
117- TryJob { custom_jobs : Option < Vec < String > > } ,
123+ TryJob { job_patterns : Option < Vec < String > > } ,
118124 /// Merge attempt workflow
119125 AutoJob ,
120126}
@@ -130,28 +136,29 @@ fn calculate_jobs(
130136) -> anyhow:: Result < Vec < GithubActionsJob > > {
131137 let ( jobs, prefix, base_env) = match run_type {
132138 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 ( ) ) ;
147147 } else {
148- unknown_jobs . push ( custom_job . clone ( ) ) ;
148+ jobs . extend ( matched_jobs ) ;
149149 }
150150 }
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 {
152158 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( )
155162 ) ) ;
156163 }
157164 jobs
0 commit comments