11use std:: process:: Command ;
22
3- use clap:: builder:: BoolishValueParser ;
3+ use clap:: builder:: { BoolishValueParser , PossibleValuesParser } ;
44use clap:: Parser ;
55use cross:: { shell:: Verbosity , CommandExt } ;
66use serde:: { Deserialize , Serialize } ;
@@ -61,6 +61,7 @@ impl TargetMatrix {
6161 none : false ,
6262 has_image : true ,
6363 verbose : false ,
64+ tests : vec ! [ "all" . to_owned( ) ] ,
6465 } ,
6566 ) ,
6667 TargetMatrix {
@@ -74,6 +75,8 @@ impl TargetMatrix {
7475 _ => ( vec ! [ ] , TargetMatrixArgs :: default ( ) ) ,
7576 } ;
7677
78+ // only apply ci labels on prs and `/ci try`,
79+ // if the try command is not the default, we don't want to apply ci labels
7780 if matches ! (
7881 self ,
7982 Self {
@@ -83,7 +86,7 @@ impl TargetMatrix {
8386 }
8487 ) || is_default_try
8588 {
86- apply_ci_target_labels ( & prs, & mut app) ?
89+ apply_ci_labels ( & prs, & mut app) ?
8790 }
8891
8992 app. filter ( & mut matrix) ;
@@ -108,13 +111,15 @@ impl TargetMatrix {
108111 . collect :: < Vec < _ > > ( ) ;
109112
110113 let json = serde_json:: to_string ( & matrix) ?;
111- gha_print ( & json) ;
112114 gha_output ( "matrix" , & json) ?;
115+ let tests = serde_json:: to_string ( & app. tests ( ) ?) ?;
116+ gha_output ( "tests" , & tests) ?;
113117 Ok ( ( ) )
114118 }
115119}
116120
117- fn apply_ci_target_labels ( prs : & [ & str ] , app : & mut TargetMatrixArgs ) -> Result < ( ) , eyre:: Error > {
121+ fn apply_ci_labels ( prs : & [ & str ] , app : & mut TargetMatrixArgs ) -> Result < ( ) , eyre:: Error > {
122+ apply_has_no_ci_tests ( prs, app) ?;
118123 apply_has_no_ci_target ( prs, app) ?;
119124
120125 let mut to_add = vec ! [ ] ;
@@ -135,10 +140,22 @@ fn apply_ci_target_labels(prs: &[&str], app: &mut TargetMatrixArgs) -> Result<()
135140 Ok ( ( ) )
136141}
137142
143+ fn apply_has_no_ci_tests ( prs : & [ & str ] , app : & mut TargetMatrixArgs ) -> Result < ( ) , eyre:: Error > {
144+ if !prs. is_empty ( )
145+ && prs. iter ( ) . try_fold ( true , |b, pr| {
146+ Ok :: < _ , eyre:: Report > ( b && has_no_ci_tests_label ( pr) ?)
147+ } ) ?
148+ {
149+ app. none = true ;
150+ app. tests . push ( "none" . to_owned ( ) ) ;
151+ }
152+ Ok ( ( ) )
153+ }
154+
138155fn apply_has_no_ci_target ( prs : & [ & str ] , app : & mut TargetMatrixArgs ) -> Result < ( ) , eyre:: Error > {
139156 if !prs. is_empty ( )
140157 && prs. iter ( ) . try_fold ( true , |b, pr| {
141- Ok :: < _ , eyre:: Report > ( b && has_no_ci_target ( pr) ?)
158+ Ok :: < _ , eyre:: Report > ( b && has_no_ci_target_label ( pr) ?)
142159 } ) ?
143160 {
144161 app. none = true ;
@@ -168,10 +185,14 @@ fn parse_gh_labels(pr: &str) -> cross::Result<Vec<String>> {
168185 Ok ( pr_info. labels . into_iter ( ) . map ( |l| l. name ) . collect ( ) )
169186}
170187
171- fn has_no_ci_target ( pr : & str ) -> cross:: Result < bool > {
188+ fn has_no_ci_target_label ( pr : & str ) -> cross:: Result < bool > {
172189 Ok ( parse_gh_labels ( pr) ?. contains ( & "no-ci-targets" . to_owned ( ) ) )
173190}
174191
192+ fn has_no_ci_tests_label ( pr : & str ) -> cross:: Result < bool > {
193+ Ok ( parse_gh_labels ( pr) ?. contains ( & "no-ci-tests" . to_owned ( ) ) )
194+ }
195+
175196/// Convert a `GITHUB_REF` into it's merge group pr
176197fn process_merge_group ( ref_ : & str ) -> cross:: Result < & str > {
177198 ref_. split ( '/' )
@@ -227,7 +248,7 @@ struct TargetMatrixElement<'a> {
227248 verbose : bool ,
228249}
229250
230- #[ derive( Parser , Debug , Default , PartialEq , Eq ) ]
251+ #[ derive( Parser , Debug , PartialEq , Eq ) ]
231252#[ clap( no_binary_name = true ) ]
232253struct TargetMatrixArgs {
233254 #[ clap( long, short, num_args = 0 ..) ]
@@ -248,6 +269,37 @@ struct TargetMatrixArgs {
248269 has_image : bool ,
249270 #[ clap( long, short) ]
250271 verbose : bool ,
272+ #[ clap( long, value_parser = PossibleValuesParser :: new( & [
273+ "remote" ,
274+ "bisect" ,
275+ "foreign" ,
276+ "docker-in-docker" ,
277+ "podman" ,
278+ "none" ,
279+ "all"
280+ ] ) ,
281+ num_args = 0 ..,
282+ value_delimiter = ',' ,
283+ default_value = "all"
284+ ) ]
285+ tests : Vec < String > ,
286+ }
287+
288+ impl Default for TargetMatrixArgs {
289+ fn default ( ) -> Self {
290+ Self {
291+ target : Vec :: new ( ) ,
292+ std : None ,
293+ cpp : None ,
294+ dylib : None ,
295+ run : None ,
296+ runners : Vec :: new ( ) ,
297+ none : false ,
298+ has_image : false ,
299+ verbose : false ,
300+ tests : vec ! [ "all" . to_owned( ) ] ,
301+ }
302+ }
251303}
252304
253305impl TargetMatrixArgs {
@@ -298,6 +350,43 @@ impl TargetMatrixArgs {
298350 } ) ;
299351 }
300352 }
353+
354+ fn tests ( & self ) -> Result < serde_json:: Value , serde_json:: Error > {
355+ use clap:: CommandFactory ;
356+ use serde:: ser:: SerializeMap ;
357+ struct Ser ( Vec < String > ) ;
358+ impl serde:: Serialize for Ser {
359+ fn serialize < S : serde:: Serializer > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error > {
360+ let mut map = serializer. serialize_map ( Some ( self . 0 . len ( ) ) ) ?;
361+ for e in & self . 0 {
362+ map. serialize_entry ( & e, & true ) ?;
363+ }
364+ map. end ( )
365+ }
366+ }
367+ let mut tests = match (
368+ self . tests . iter ( ) . any ( |t| t == "all" ) ,
369+ self . tests . iter ( ) . any ( |t| t == "none" ) ,
370+ ) {
371+ ( _, true ) => vec ! [ ] ,
372+ ( true , false ) => {
373+ let possible: Vec < String > = Self :: command ( )
374+ . get_arguments ( )
375+ . find ( |arg| arg. get_id ( ) == "tests" )
376+ . expect ( "a `tests` argument should exist" )
377+ . get_possible_values ( )
378+ . into_iter ( )
379+ . map ( |p| p. get_name ( ) . to_owned ( ) )
380+ . collect ( ) ;
381+
382+ possible
383+ }
384+ _ => self . tests . clone ( ) ,
385+ } ;
386+ tests. retain ( |p| p != "all" ) ;
387+ tests. retain ( |p| p != "none" ) ;
388+ serde_json:: to_value ( Ser ( tests) )
389+ }
301390}
302391
303392#[ cfg( test) ]
0 commit comments