@@ -443,7 +443,7 @@ impl<'task> TaskRunner<'task> {
443443 return Err ( TaskRunnerError :: FingerprintCheckFailed {
444444 target : self . task . target . clone ( ) ,
445445 script : check_result. check . get_script ( ) . into ( ) ,
446- error : Box :: new ( output. to_error ( "<check >" , true ) ) ,
446+ error : Box :: new ( output. to_error ( "<fingerprint >" , true ) ) ,
447447 }
448448 . into ( ) ) ;
449449 }
@@ -472,6 +472,8 @@ impl<'task> TaskRunner<'task> {
472472 info. stderr = None ;
473473 }
474474 } ;
475+ } else {
476+ unreachable ! ( ) ;
475477 }
476478
477479 fingerprint
@@ -501,7 +503,11 @@ impl<'task> TaskRunner<'task> {
501503 }
502504
503505 // Execute the task checks first, if any, and exit early if they fail
504- // self.execute_checks().await?;
506+ if self . execute_checks ( ) . await ? {
507+ self . skip ( ) ?;
508+
509+ return Ok ( ( ) ) ;
510+ }
505511
506512 debug ! (
507513 task_target = self . task. target. as_str( ) ,
@@ -584,6 +590,103 @@ impl<'task> TaskRunner<'task> {
584590 Ok ( ( ) )
585591 }
586592
593+ #[ instrument( skip( self ) ) ]
594+ pub async fn execute_checks ( & mut self ) -> miette:: Result < bool > {
595+ let checks = ChecksRunner :: new ( self . app_context , self . project , self . task ) ?
596+ . execute ( vec ! [ TaskCheckType :: Condition , TaskCheckType :: Requirement ] )
597+ . await ?;
598+
599+ if checks. is_empty ( ) {
600+ return Ok ( false ) ;
601+ }
602+
603+ let mut has_conditions = false ;
604+ let mut all_conditions_met = true ;
605+
606+ for check_result in checks {
607+ // If a hard failure, we should abort the runner
608+ if let Some ( error) = check_result. error {
609+ return Err ( error) ;
610+ }
611+
612+ self . operations . push ( check_result. attempt ) ;
613+
614+ match check_result. check {
615+ // Success: Track the skipped state. If all conditions pass, skip running the task.
616+ // Failure: Do not return an error, as the task itself will run instead.
617+ TaskCheck :: Condition ( condition) => {
618+ let passed = check_result
619+ . output
620+ . as_ref ( )
621+ . is_some_and ( |output| output. success ( ) ) ;
622+
623+ trace ! (
624+ task_target = self . task. target. as_str( ) ,
625+ check = condition. script,
626+ passed,
627+ exit_code = check_result
628+ . output
629+ . as_ref( )
630+ . and_then( |output| output. code( ) ) ,
631+ "Checking condition"
632+ ) ;
633+
634+ has_conditions = true ;
635+
636+ if !passed {
637+ all_conditions_met = false ;
638+ }
639+ }
640+ // Success: Continue on to the next check.
641+ // Failure: Return an error, as the task itself should not run.
642+ TaskCheck :: Requirement ( requirement) => {
643+ trace ! (
644+ task_target = self . task. target. as_str( ) ,
645+ check = requirement. script,
646+ exit_code = check_result
647+ . output
648+ . as_ref( )
649+ . and_then( |output| output. code( ) ) ,
650+ "Checking requirement"
651+ ) ;
652+
653+ if let Some ( output) = check_result. output
654+ && !output. success ( )
655+ {
656+ return Err ( TaskRunnerError :: RequirementCheckFailed {
657+ target : self . task . target . clone ( ) ,
658+ script : requirement. script ,
659+ error : Box :: new ( output. to_error ( "<requirement>" , true ) ) ,
660+ }
661+ . into ( ) ) ;
662+ }
663+ }
664+ TaskCheck :: Fingerprint ( _) => {
665+ unreachable ! ( ) ;
666+ }
667+ } ;
668+ }
669+
670+ // Only skip if all conditions pass, otherwise we should run the task as normal
671+ if has_conditions {
672+ if all_conditions_met {
673+ debug ! (
674+ task_target = self . task. target. as_str( ) ,
675+ "Skipping task as all conditional checks have passed"
676+ ) ;
677+
678+ return Ok ( true ) ;
679+ }
680+
681+ debug ! (
682+ task_target = self . task. target. as_str( ) ,
683+ "Will continue to run the task as not all conditional checks have passed"
684+ ) ;
685+ }
686+
687+ Ok ( false )
688+ }
689+
587690 #[ instrument( skip( self ) ) ]
588691 pub fn skip ( & mut self ) -> miette:: Result < ( ) > {
589692 debug ! ( task_target = self . task. target. as_str( ) , "Skipping task" ) ;
0 commit comments