From 0a270dcbdd51baa2895634a3baee29373db8337a Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Sat, 8 Aug 2026 23:50:23 -0400 Subject: [PATCH] Record error when setting up repo fails rather than abort entire script. --- example_config.toml | 7 +++ src/command/build/runner.rs | 91 +++++++++++++++++++++++++--------- src/nix_util/high_level.rs | 7 +-- src/nix_util/running_build.rs | 18 ++----- src/nix_util/running_verify.rs | 6 +-- 5 files changed, 85 insertions(+), 44 deletions(-) diff --git a/example_config.toml b/example_config.toml index e979de7..29f2223 100644 --- a/example_config.toml +++ b/example_config.toml @@ -1,5 +1,12 @@ # repo_directory = "/home/nixworker/persist/nix_builder" +[[targets]] + name = "foo" + repo = "https://code.fizz.buzz/talexander/machine_setup.git" + branch = "foo" + path = "nix/configuration" + attr = "nixosConfigurations.odo.config.system.build.toplevel" + [[targets]] name = "odo" repo = "https://code.fizz.buzz/talexander/machine_setup.git" diff --git a/src/command/build/runner.rs b/src/command/build/runner.rs index 3ff03f7..c13eb7d 100644 --- a/src/command/build/runner.rs +++ b/src/command/build/runner.rs @@ -1,4 +1,7 @@ +use std::process::ExitStatus; + use sqlx::Row; +use tracing::error; use tracing::info; use crate::Result; @@ -37,20 +40,46 @@ pub(crate) async fn run_build(args: BuildArgs) -> Result<()> { verify_nix_store().await?; for target_name in args.target { - let target_config = { - let target_config = config.get_target_config(&target_name)?; - if let Some(conf) = target_config { - conf - } else { - return Err(format!("Could not find target {}", target_name).into()); + // Record start of build + let build_id: i64 = sqlx::query( + r#"INSERT INTO build (start_time, target) SELECT unixepoch('now'), ? RETURNING id"#, + ) + .bind(&target_name) + .fetch_one(&db_handle.conn) + .await? + .try_get("id")?; + + // Put the rest into a function + let result = full_build_target(&config, &db_handle, &target_name, build_id).await; + match result { + Ok(exit_status) => { + let update: u64 = sqlx::query( + r#"UPDATE build SET end_time=unixepoch('now'), status=? WHERE id=?"#, + ) + .bind( + exit_status + .code() + .expect("Process should have an exit code."), + ) + .bind(build_id) + .execute(&db_handle.conn) + .await? + .rows_affected(); + assert!(update == 1); + } + Err(e) => { + error!("Error building target {}: {}", target_name, e); + let update: u64 = sqlx::query( + r#"UPDATE build SET end_time=unixepoch('now'), status=? WHERE id=?"#, + ) + .bind(-1) + .bind(build_id) + .execute(&db_handle.conn) + .await? + .rows_affected(); + assert!(update == 1); } }; - - prepare_flake_repo(&config, target_config).await?; - if target_config.get_update() { - run_nix_update(&config, target_config).await?; - } - build_target(&db_handle, &config, target_config).await?; } db_handle.conn.close().await; @@ -58,6 +87,29 @@ pub(crate) async fn run_build(args: BuildArgs) -> Result<()> { Ok(()) } +async fn full_build_target( + config: &Config, + db_handle: &DbHandle, + target_name: &str, + build_id: i64, +) -> Result { + let target_config = { + let target_config = config.get_target_config(&target_name)?; + if let Some(conf) = target_config { + conf + } else { + return Err(format!("Could not find target {}", target_name).into()); + } + }; + + prepare_flake_repo(&config, target_config).await?; + if target_config.get_update() { + run_nix_update(&config, target_config).await?; + } + let exit_status = build_target(&db_handle, &config, target_config, build_id).await?; + Ok(exit_status) +} + async fn prepare_flake_repo(config_root: &Config, target_config: &TargetConfig) -> Result<()> { let repo_directory = target_config.get_repo_directory(config_root)?; assert_directory!( @@ -106,7 +158,8 @@ async fn build_target( db_handle: &DbHandle, config_root: &Config, target_config: &TargetConfig, -) -> Result<()> { + build_id: i64, +) -> Result { let flake_directory = target_config.get_flake_directory(config_root)?; let build_directory = target_config.get_build_directory(config_root)?; assert_directory!( @@ -117,18 +170,10 @@ async fn build_target( let target_name = target_config.get_name()?; - let build_id: i64 = sqlx::query( - r#"INSERT INTO build (start_time, target) SELECT unixepoch('now'), ? RETURNING id"#, - ) - .bind(target_name) - .fetch_one(&db_handle.conn) - .await? - .try_get("id")?; - let flake_lock = parse_flake_lock(&flake_directory).await?; write_input_revs_to_db(db_handle, &flake_lock, build_id).await?; - nixos_build_target( + let exit_status = nixos_build_target( db_handle, build_directory, flake_directory, @@ -138,7 +183,7 @@ async fn build_target( ) .await?; - Ok(()) + Ok(exit_status) } async fn write_input_revs_to_db( diff --git a/src/nix_util/high_level.rs b/src/nix_util/high_level.rs index 9c26faa..0691793 100644 --- a/src/nix_util/high_level.rs +++ b/src/nix_util/high_level.rs @@ -1,6 +1,7 @@ use std::ffi::OsStr; use std::ffi::OsString; use std::path::Path; +use std::process::ExitStatus; use std::process::Stdio; use tokio::process::Command; @@ -19,7 +20,7 @@ pub(crate) async fn nixos_build_target( attr: A, target_name: TN, build_id: i64, -) -> Result<()> +) -> Result where B: AsRef, F: AsRef, @@ -58,9 +59,9 @@ where let child = command.spawn()?; let mut running_build = RunningBuild::new(db_handle, build_id)?; - running_build.run_to_completion(child, target_name).await?; + let exit_status = running_build.run_to_completion(child, target_name).await?; - Ok(()) + Ok(exit_status) } pub(crate) async fn nix_flake_update(flake_path: F) -> Result<()> diff --git a/src/nix_util/running_build.rs b/src/nix_util/running_build.rs index f5b84ef..e411947 100644 --- a/src/nix_util/running_build.rs +++ b/src/nix_util/running_build.rs @@ -1,4 +1,5 @@ use std::borrow::Cow; +use std::process::ExitStatus; use std::time::Duration; use std::time::Instant; use std::time::SystemTime; @@ -43,7 +44,7 @@ impl<'db> RunningBuild<'db> { &mut self, mut child: Child, target_name: TN, - ) -> Result<()> + ) -> Result where TN: AsRef, { @@ -66,20 +67,7 @@ impl<'db> RunningBuild<'db> { let exit_status = exit_status_handle.await?; println!("nix build status was: {}", exit_status); - let update: u64 = - sqlx::query(r#"UPDATE build SET end_time=unixepoch('now'), status=? WHERE id=?"#) - .bind( - exit_status - .code() - .expect("Process should have an exit code."), - ) - .bind(self.build_id) - .execute(&self.db_handle.conn) - .await? - .rows_affected(); - assert!(update == 1); - - Ok(()) + Ok(exit_status) } pub(crate) fn handle_message(&mut self, message: NixMessage) -> Result<()> { diff --git a/src/nix_util/running_verify.rs b/src/nix_util/running_verify.rs index d660fcb..4a91e27 100644 --- a/src/nix_util/running_verify.rs +++ b/src/nix_util/running_verify.rs @@ -71,9 +71,9 @@ impl RunningVerify { }; match message { NixAction::Msg(msg_message) => { - // if msg_message.level > 0 && msg_message.level < 5 { - // eprintln!("LOG MESSAGE {}: {}", msg_message.level, msg_message.msg); - // } + if msg_message.level > 0 && msg_message.level < 4 { + eprintln!("LOG MESSAGE {}: {}", msg_message.level, msg_message.msg); + } } NixAction::Start(activity_start_message) => { // println!("START: {}", serde_json::to_string(&activity_start_message)?);