git.delta.rocks / jrsonnet / refs/commits / cc4299b11a7b

difftreelog

refactor nix-eval is now fully sync, parallelism should be explicit at the callsite

zorryxklYaroslav Bolyukin2025-09-18parent: #cf89cc0.patch.diff
in: trunk

6 files changed

modifiedCargo.lockdiffbeforeafterboth
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2070,8 +2070,6 @@
  "serde_json",
  "test-log",
  "thiserror 2.0.16",
- "tokio",
- "tokio-util",
  "tracing",
  "tracing-indicatif",
  "vte 0.15.0",
modifiedcmds/fleet/src/cmds/build_systems.rsdiffbeforeafterboth
before · cmds/fleet/src/cmds/build_systems.rs
1use std::{env::current_dir, os::unix::fs::symlink, path::PathBuf};23use anyhow::Result;4use clap::Parser;5use fleet_base::{6	deploy::{DeployAction, deploy_task, upload_task},7	host::{Config, DeployKind, GenerationStorage},8	opts::FleetOpts,9};10use nix_eval::nix_go;11use tokio::task::LocalSet;12use tracing::{Instrument, error, field, info, info_span, warn};1314#[derive(Parser)]15pub struct Deploy {16	/// Disable automatic rollback17	#[clap(long)]18	disable_rollback: bool,19	/// Action to execute after system is built20	action: DeployAction,21}2223#[derive(Parser, Clone)]24pub struct BuildSystems {25	/// Attribute to build. Systems are deployed from "toplevel" attr, well-known used attributes26	/// are "sdImage"/"isoImage", and your configuration may include any other build attributes.27	#[clap(long, default_value = "toplevel")]28	build_attr: String,29}3031async fn build_task(config: Config, hostname: String, build_attr: &str) -> Result<PathBuf> {32	info!("building");33	let host = config.host(&hostname).await?;34	// let action = Action::from(self.subcommand.clone());35	let nixos = host.nixos_config().await?;36	let drv = nix_go!(nixos.system.build[{ build_attr }]);37	let out_output = drv.build("out").await?;3839	// We already have system profiles for backups.40	if !host.local {41		info!("adding gc root");42		let mut cmd = config.local_host().cmd("nix").await?;43		cmd.arg("build")44			.comparg(45				"--profile",46				format!(47					"/nix/var/nix/profiles/{}-{hostname}",48					config.data().gc_root_prefix49				),50			)51			.arg(&out_output);52		cmd.sudo().run_nix().await?;53	}5455	Ok(out_output)56}5758impl BuildSystems {59	pub async fn run(self, config: &Config, opts: &FleetOpts) -> Result<()> {60		let hosts = opts.filter_skipped(config.list_hosts().await?).await?;61		let set = LocalSet::new();62		let build_attr = self.build_attr.clone();63		for host in hosts {64			let config = config.clone();65			let span = info_span!("build", host = field::display(&host.name));66			let hostname = host.name;67			let build_attr = build_attr.clone();68			set.spawn_local(69				(async move {70					let built = match build_task(config, hostname.clone(), &build_attr).await {71						Ok(path) => path,72						Err(e) => {73							error!("failed to deploy host: {}", e);74							return;75						}76					};77					// TODO: Handle error78					let mut out = current_dir().expect("cwd exists");79					out.push(format!("built-{hostname}"));8081					info!("linking iso image to {:?}", out);82					if let Err(e) = symlink(built, out) {83						error!("failed to symlink: {e}")84					}85				})86				.instrument(span),87			);88		}89		set.await;90		Ok(())91	}92}9394impl Deploy {95	pub async fn run(self, config: &Config, opts: &FleetOpts) -> Result<()> {96		let hosts = opts.filter_skipped(config.list_hosts().await?).await?;97		let set = LocalSet::new();98		for host in hosts.into_iter() {99			let config = config.clone();100			let span = info_span!("deploy", host = field::display(&host.name));101			let hostname = host.name.clone();102			let opts = opts.clone();103			if let Some(deploy_kind) = opts.action_attr::<DeployKind>(&host, "deploy_kind").await? {104				host.set_deploy_kind(deploy_kind);105			};106			if let Some(destination) = opts.action_attr::<String>(&host, "dest").await? {107				host.set_session_destination(destination);108			};109			if let Some(legacy) = opts.action_attr::<bool>(&host, "legacy_ssh_store").await? {110				host.set_legacy_ssh_store(legacy);111			};112113			set.spawn_local(114				(async move {115					let built = match build_task(config.clone(), hostname.clone(), "toplevel").await116					{117						Ok(path) => path,118						Err(e) => {119							error!("failed to build host system closure: {:#}", e);120							return;121						}122					};123124					let deploy_kind = match host.deploy_kind().await {125						Ok(v) => v,126						Err(e) => {127							error!("failed to query target deploy kind: {e}");128							return;129						}130					};131132					// TODO: Make disable_rollback a host attribute instead133					let mut disable_rollback = self.disable_rollback;134					if !disable_rollback && deploy_kind != DeployKind::Fleet {135						warn!("disabling rollback, as not supported by non-fleet deployment kinds");136						disable_rollback = true;137					}138139					let remote_path =140						match upload_task(&config, &host, GenerationStorage::Deployer, built).await141						{142							Ok(v) => v,143							Err(e) => {144								error!("upload failed: {e}");145								return;146							}147						};148149					if let Err(e) = deploy_task(150						self.action,151						&host,152						remote_path,153						match opts.action_attr(&host, "specialisation").await {154							Ok(v) => v,155							_ => {156								error!("unreachable? failed to get specialization");157								return;158							}159						},160						disable_rollback,161					)162					.await163					{164						error!("activation failed: {e}");165					}166				})167				.instrument(span),168			);169		}170		set.await;171		Ok(())172	}173}
modifiedcmds/fleet/src/cmds/secrets/mod.rsdiffbeforeafterboth
--- a/cmds/fleet/src/cmds/secrets/mod.rs
+++ b/cmds/fleet/src/cmds/secrets/mod.rs
@@ -19,7 +19,7 @@
 use owo_colors::OwoColorize;
 use serde::Deserialize;
 use tabled::{Table, Tabled};
-use tokio::fs::read;
+use tokio::{fs::read, task::spawn_blocking};
 use tracing::{Instrument, error, info, info_span, warn};
 
 #[derive(Parser)]
@@ -288,7 +288,9 @@
 
 	let generator = nix_go!(call_package(generator)(Obj {}));
 
-	let generator = generator.build("out").await?;
+	let generator = spawn_blocking(move || generator.build("out"))
+		.await
+		.expect("nix build shouldn't fail")?;
 	let generator = host.remote_derivation(&generator).await?;
 
 	let out_parent = host.mktemp_dir().await?;
modifiedcmds/fleet/src/cmds/tf.rsdiffbeforeafterboth
--- a/cmds/fleet/src/cmds/tf.rs
+++ b/cmds/fleet/src/cmds/tf.rs
@@ -10,6 +10,7 @@
 use tokio::{
 	fs::{self, create_dir_all},
 	process::Command,
+	task::spawn_blocking,
 };
 use tracing::debug;
 
@@ -38,7 +39,10 @@
 			debug!("generating terraform configs");
 			let system = &config.local_system;
 			let config = &config.config_field;
-			let data: PathBuf = nix_go!(config.tf({ system })).build("out").await?;
+			let data = nix_go!(config.tf({ system }));
+			let data: PathBuf = spawn_blocking(move || data.build("out"))
+				.await
+				.expect("tf.json derivation should not fail")?;
 			let data = fs::read(&data).await?;
 
 			create_dir_all(&dir).await?;
modifiedcrates/nix-eval/Cargo.tomldiffbeforeafterboth
--- a/crates/nix-eval/Cargo.toml
+++ b/crates/nix-eval/Cargo.toml
@@ -11,8 +11,6 @@
 serde = { workspace = true, features = ["derive"] }
 serde_json.workspace = true
 thiserror.workspace = true
-tokio = { workspace = true }
-tokio-util.workspace = true
 tracing.workspace = true
 
 cxx = "1.0.168"
modifiedcrates/nix-eval/src/lib.rsdiffbeforeafterboth
--- a/crates/nix-eval/src/lib.rs
+++ b/crates/nix-eval/src/lib.rs
@@ -750,7 +750,7 @@
 		})?;
 		Ok(out)
 	}
-	pub async fn build(&self, output: &str) -> Result<PathBuf> {
+	pub fn build(&self, output: &str) -> Result<PathBuf> {
 		if !self.is_derivation() {
 			bail!("expected derivation to build")
 		}