Files
nix_builder/src/command/build/runner.rs

168 lines
4.7 KiB
Rust
Raw Normal View History

use sqlx::Row;
use tracing::info;
2026-02-14 22:15:09 -05:00
use crate::Result;
use crate::cli::parameters::BuildArgs;
use crate::config::Config;
use crate::config::TargetConfig;
2026-02-14 22:15:09 -05:00
use crate::database::db_handle::DbHandle;
2026-02-14 16:00:37 -05:00
use crate::fs_util::assert_directory;
use crate::fs_util::is_git_repo;
use crate::git_util::git_force_into_state;
use crate::git_util::git_init_at_rev;
use crate::nix_util::FlakeLock;
2026-06-25 18:25:02 -04:00
use crate::nix_util::nix_flake_update;
2026-02-14 19:20:52 -05:00
use crate::nix_util::nixos_build_target;
use crate::nix_util::parse_flake_lock;
2026-02-14 22:15:09 -05:00
pub(crate) async fn run_build(args: BuildArgs) -> Result<()> {
println!("{:?}", args);
let config = Config::load_from_file(args.config).await?;
println!("{:?}", config);
2026-02-14 22:15:09 -05:00
let database_path = config.get_database_path()?;
let database_parent = database_path
.parent()
.expect("Database should exist in a folder.");
let database_path = database_path.to_string_lossy();
assert_directory!(
database_parent,
"Creating database directory {}",
database_parent.to_string_lossy()
);
let db_handle = DbHandle::new(Some(database_path)).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());
}
};
2026-02-14 16:00:37 -05:00
prepare_flake_repo(&config, target_config).await?;
2026-06-25 18:25:02 -04:00
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;
Ok(())
}
2026-02-14 22:15:09 -05:00
async fn prepare_flake_repo(config_root: &Config, target_config: &TargetConfig) -> Result<()> {
2026-02-14 19:20:52 -05:00
let repo_directory = target_config.get_repo_directory(config_root)?;
2026-02-14 16:00:37 -05:00
assert_directory!(
2026-02-14 19:20:52 -05:00
&repo_directory,
"Creating repo directory {}",
2026-02-14 22:15:09 -05:00
repo_directory.to_string_lossy()
2026-02-14 16:00:37 -05:00
);
2026-02-14 19:20:52 -05:00
if is_git_repo(&repo_directory).await? {
2026-02-14 16:00:37 -05:00
// Clean up the existing clone
git_force_into_state(
2026-02-14 19:20:52 -05:00
&repo_directory,
2026-02-14 16:00:37 -05:00
target_config.get_branch()?,
"origin",
target_config.get_repo()?,
target_config.get_revision()?,
)
.await?;
} else {
git_init_at_rev(
2026-02-14 19:20:52 -05:00
&repo_directory,
2026-02-14 16:00:37 -05:00
target_config.get_branch()?,
target_config.get_repo()?,
target_config.get_revision()?,
)
.await?;
}
Ok(())
}
2026-02-14 19:20:52 -05:00
2026-06-25 18:25:02 -04:00
async fn run_nix_update(config_root: &Config, target_config: &TargetConfig) -> Result<()> {
let flake_directory = target_config.get_flake_directory(config_root)?;
nix_flake_update(flake_directory).await?;
Ok(())
}
async fn build_target(
db_handle: &DbHandle,
config_root: &Config,
target_config: &TargetConfig,
) -> Result<()> {
2026-02-14 19:20:52 -05:00
let flake_directory = target_config.get_flake_directory(config_root)?;
let build_directory = target_config.get_build_directory(config_root)?;
assert_directory!(
&build_directory,
"Creating build directory {}",
2026-02-14 22:15:09 -05:00
build_directory.to_string_lossy()
2026-02-14 19:20:52 -05:00
);
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?;
panic!();
nixos_build_target(
db_handle,
build_directory,
flake_directory,
target_config.get_attr()?,
target_name,
build_id,
)
.await?;
2026-02-14 19:20:52 -05:00
Ok(())
}
async fn write_input_revs_to_db(
db_handle: &DbHandle,
flake_lock: &FlakeLock,
build_id: i64,
) -> Result<()> {
let root_node = flake_lock.get_root_node()?;
let direct_inputs = flake_lock.get_inputs(root_node)?;
let mut tx = db_handle.conn.begin().await?;
for (input, node) in direct_inputs.iter() {
let locked = match &node.locked {
Some(locked) => locked,
None => {
info!(
"Not recording rev for input {} because it lacks a locked section.",
input
);
continue;
}
};
let rev = &locked.rev;
info!("input {} {}", input, rev);
sqlx::query(r#"INSERT INTO flake_inputs (build_id, input_name, rev) VALUES (?, ?, ?);"#)
.bind(build_id)
.bind(input)
.bind(rev)
.execute(&mut *tx)
.await?;
}
tx.commit().await?;
Ok(())
}