Execute CI pipeline inline on push
trigger_ref now calls Run::execute with the validated pipeline
and secrets from the global config, instead of just validating
and immediately marking the run complete. Validation failures
still transition the run through Active → Failed.

Assisted-by: GLM-5.1 via pi
change tnkulonsyqpqyqznwvqzxxznrvqlylnq
commit 7bf3c15b69fc00ee0f7a8456739a4367f0e9642e
author Alpha Chen <alpha@kejadlen.dev>
date
parent xwtpwktp
diff --git a/src/ci/mod.rs b/src/ci/mod.rs
index f309132..8896598 100644
--- a/src/ci/mod.rs
+++ b/src/ci/mod.rs
@@ -1,5 +1,7 @@
 //! CI: trigger runs from push events, validate the job graph.
 
+use std::collections::HashMap;
+
 mod lua;
 mod pipeline;
 mod run;
@@ -111,8 +113,16 @@ pub fn trigger(quire: &crate::Quire, event: &PushEvent) {
         }
     };
 
+    let secrets = match quire.global_config() {
+        Ok(config) => config.secrets,
+        Err(e) => {
+            tracing::error!(repo = %event.repo, %e, "failed to load global config");
+            return;
+        }
+    };
+
     for push_ref in event.updated_refs() {
-        if let Err(e) = trigger_ref(&repo, event.pushed_at, push_ref) {
+        if let Err(e) = trigger_ref(&repo, event.pushed_at, push_ref, &secrets) {
             tracing::error!(
                 repo = %event.repo,
                 sha = %push_ref.new_sha, // cov-excl-line
@@ -124,7 +134,12 @@ pub fn trigger(quire: &crate::Quire, event: &PushEvent) {
 }
 
 /// Create and run CI for a single updated ref.
-fn trigger_ref(repo: &Repo, pushed_at: jiff::Timestamp, push_ref: &PushRef) -> Result<()> {
+fn trigger_ref(
+    repo: &Repo,
+    pushed_at: jiff::Timestamp,
+    push_ref: &PushRef,
+    secrets: &HashMap<String, crate::secret::SecretString>,
+) -> Result<()> {
     let ci = repo.ci();
 
     let Some(source) = ci.source(&push_ref.new_sha)? else {
@@ -146,18 +161,17 @@ fn trigger_ref(repo: &Repo, pushed_at: jiff::Timestamp, push_ref: &PushRef) -> R
         "created CI run"
     );
 
-    run.transition(RunState::Active)?;
-
     let name = CI_FNL.to_string();
-
-    match Pipeline::load(&source, &name) {
-        Ok(_pipeline) => run.transition(RunState::Complete)?,
+    let pipeline = match Pipeline::load(&source, &name) {
+        Ok(p) => p,
         Err(e) => {
+            run.transition(RunState::Active)?;
             run.transition(RunState::Failed)?;
             return Err(e);
         }
-    }
+    };
 
+    run.execute(pipeline, secrets.clone())?;
     Ok(())
 }
 
@@ -328,7 +342,8 @@ mod tests {
             r#ref: "refs/heads/main".to_string(),
         };
 
-        trigger_ref(&repo, pushed_at, &push_ref).expect("trigger_ref should succeed");
+        trigger_ref(&repo, pushed_at, &push_ref, &HashMap::new())
+            .expect("trigger_ref should succeed");
 
         // Verify a run was created in complete/.
         let runs = repo.runs();
@@ -348,7 +363,8 @@ mod tests {
             r#ref: "refs/heads/main".to_string(),
         };
 
-        trigger_ref(&repo, pushed_at, &push_ref).expect("should succeed without ci.fnl");
+        trigger_ref(&repo, pushed_at, &push_ref, &HashMap::new())
+            .expect("should succeed without ci.fnl");
     }
 
     #[test]
@@ -364,7 +380,7 @@ mod tests {
             r#ref: "refs/heads/main".to_string(),
         };
 
-        let result = trigger_ref(&repo, pushed_at, &push_ref);
+        let result = trigger_ref(&repo, pushed_at, &push_ref, &HashMap::new());
         assert!(result.is_err(), "invalid pipeline should fail");
     }