77//! the contributor does ADO REST + git fetch deepening work that
88//! adds startup latency, so most agents shouldn't pay for it.
99//!
10- //! Runtime gate: `or(eq(Build.Reason, 'IndividualCI'),
11- //! eq(Build.Reason, 'BatchedCI'))`. Skips PRs, scheduled runs, and
10+ //! Runtime gate: `and(succeeded(), or(eq(Build.Reason, 'IndividualCI'),
11+ //! eq(Build.Reason, 'BatchedCI'))) `. Skips PRs, scheduled runs, and
1212//! resource triggers at zero cost.
1313//!
1414//! ## Artefacts (staged by the bundle on success)
@@ -52,7 +52,7 @@ use crate::compile::ir::condition::{Condition, Expr};
5252use crate :: compile:: ir:: step:: { BashStep , Step } ;
5353use crate :: compile:: types:: CiPushContextConfig ;
5454
55- use super :: contributor:: ContextContributor ;
55+ use super :: contributor:: { ContextContributor , succeeded_and } ;
5656
5757/// CI-push-context contributor.
5858pub ( super ) struct CiPushContextContributor {
@@ -99,7 +99,7 @@ impl ContextContributor for CiPushContextContributor {
9999 "Stage ci-push execution context (aw-context/ci-push/*)" ,
100100 script,
101101 )
102- . with_condition ( Condition :: Or ( vec ! [
102+ . with_condition ( succeeded_and ( Condition :: Or ( vec ! [
103103 Condition :: Eq (
104104 Expr :: Variable ( "Build.Reason" . to_string( ) ) ,
105105 Expr :: Literal ( "IndividualCI" . to_string( ) ) ,
@@ -108,7 +108,7 @@ impl ContextContributor for CiPushContextContributor {
108108 Expr :: Variable ( "Build.Reason" . to_string( ) ) ,
109109 Expr :: Literal ( "BatchedCI" . to_string( ) ) ,
110110 ) ,
111- ] ) ) ,
111+ ] ) ) ) ,
112112 Bundle :: ExecContextCiPush ,
113113 TokenSource :: SystemAccessToken ,
114114 ) ;
@@ -177,10 +177,14 @@ mod tests {
177177 Step :: Bash ( b) => b,
178178 other => panic ! ( "expected Bash, got {other:?}" ) ,
179179 } ;
180- // Condition: or(eq(Build.Reason, IndividualCI),
181- // eq(Build.Reason, BatchedCI))
180+ // Condition: and(succeeded(), or(eq(Build.Reason, IndividualCI),
181+ // eq(Build.Reason, BatchedCI) ))
182182 match & bash. condition {
183- Some ( Condition :: Or ( clauses) ) => {
183+ Some ( Condition :: And ( parts) ) => {
184+ assert ! ( matches!( parts. as_slice( ) , [ Condition :: Succeeded , _] ) ) ;
185+ let Condition :: Or ( clauses) = & parts[ 1 ] else {
186+ panic ! ( "expected Or trigger condition, got {:?}" , parts[ 1 ] ) ;
187+ } ;
184188 assert_eq ! ( clauses. len( ) , 2 ) ;
185189 let reasons: Vec < & str > = clauses
186190 . iter ( )
@@ -192,7 +196,7 @@ mod tests {
192196 assert ! ( reasons. contains( & "IndividualCI" ) ) ;
193197 assert ! ( reasons. contains( & "BatchedCI" ) ) ;
194198 }
195- other => panic ! ( "expected Or condition, got {other:?}" ) ,
199+ other => panic ! ( "expected succeeded And condition, got {other:?}" ) ,
196200 }
197201
198202 // Trust boundary: bearer present, projected as a secret via the
0 commit comments