git.delta.rocks / jrsonnet / refs/commits / 4e7930a0a457

difftreelog

feat build specializations

Yaroslav Bolyukin2022-12-09parent: #38d1791.patch.diff
in: trunk

2 files changed

modifiedcmds/fleet/src/cmds/build_systems.rsdiffbeforeafterboth
before · cmds/fleet/src/cmds/build_systems.rs
1use std::{env::current_dir, process::Stdio, time::Duration};23use crate::{command::CommandExt, host::Config};4use anyhow::Result;5use clap::Parser;6use tokio::{process::Command, task::LocalSet, time::sleep};7use tracing::{error, field, info, info_span, warn, Instrument};89#[derive(Parser, Clone)]10pub struct BuildSystems {11	/// Jobs to run locally12	#[clap(long)]13	jobs: Option<usize>,14	/// Do not continue on error15	#[clap(long)]16	fail_fast: bool,17	/// Run builds as sudo18	#[clap(long)]19	privileged_build: bool,20	#[clap(subcommand)]21	subcommand: Subcommand,2223	/// --builders arg for nix24	#[clap(long)]25	builders: Option<String>,26	/// --show-trace arg for nix27	#[structopt(long)]28	show_trace: bool,29}3031enum UploadAction {32	Test,33	Boot,34	Switch,35}36impl UploadAction {37	fn name(&self) -> &'static str {38		match self {39			UploadAction::Test => "test",40			UploadAction::Boot => "boot",41			UploadAction::Switch => "switch",42		}43	}4445	pub(crate) fn should_switch_profile(&self) -> bool {46		matches!(self, Self::Switch | Self::Test)47	}48}4950enum PackageAction {51	SdImage,52}5354enum Action {55	Upload(Option<UploadAction>),56	Package(PackageAction),57}5859impl From<Subcommand> for Action {60	fn from(s: Subcommand) -> Self {61		match s {62			Subcommand::Upload => Self::Upload(None),63			Subcommand::Test => Self::Upload(Some(UploadAction::Test)),64			Subcommand::Boot => Self::Upload(Some(UploadAction::Boot)),65			Subcommand::Switch => Self::Upload(Some(UploadAction::Switch)),66			Subcommand::SdImage => Self::Package(PackageAction::SdImage),67		}68	}69}7071#[derive(Parser, Clone)]72enum Subcommand {73	/// Upload, but do not switch74	Upload,75	/// Upload + switch to built system until reboot76	Test,77	/// Upload + switch to built system after reboot78	Boot,79	/// Upload + test + boot80	Switch,8182	/// Build sd image83	SdImage,84}8586impl BuildSystems {87	async fn build_task(self, config: Config, host: String) -> Result<()> {88		info!("building");89		let built = {90			let dir = tempfile::tempdir()?;91			dir.path().to_owned()92		};9394		let mut nix_build = if self.privileged_build {95			let mut out = Command::new("sudo");96			out.arg("nix");97			out98		} else {99			Command::new("nix")100		};101		nix_build102			.args(&[103				"build",104				"--impure",105				"--json",106				// "--show-trace",107				"--no-link",108				"--out-link",109			])110			.arg(&built)111			.arg(config.configuration_attr_name(&format!(112				"configuredSystems.{}.config.system.build.toplevel",113				host114			)));115116		if self.show_trace {117			nix_build.arg("--show-trace");118		}119		if let Some(builders) = &self.builders {120			nix_build.arg("--builders").arg(builders);121		}122		if let Some(jobs) = &self.jobs {123			nix_build.arg("--max-jobs");124			nix_build.arg(format!("{}", jobs));125		}126		if !self.fail_fast {127			nix_build.arg("--keep-going");128		}129130		nix_build.run_nix().await?;131		let built = std::fs::canonicalize(built)?;132133		let action = Action::from(self.subcommand.clone());134135		match action {136			Action::Upload(action) => {137				if !config.is_local(&host) {138					info!("uploading system closure");139					let mut tries = 0;140					loop {141						match Command::new("nix")142							.args(&["copy", "--to"])143							.arg(format!("ssh://root@{}", host))144							.arg(&built)145							.inherit_stdio()146							.run_nix()147							.await148						{149							Ok(()) => break,150							Err(e) if tries < 3 => {151								tries += 1;152								warn!("Copy failure ({}/3): {}", tries, e);153								sleep(Duration::from_millis(5000)).await;154							}155							Err(e) => return Err(e),156						}157					}158				}159				if let Some(action) = action {160					if action.should_switch_profile() {161						info!("switching generation");162						config163							.command_on(&host, "nix-env", true)164							.args(&["-p", "/nix/var/nix/profiles/system", "--set"])165							.arg(&built)166							.inherit_stdio()167							.run()168							.await?;169					}170					info!("executing activation script");171					let mut switch_script = built.clone();172					switch_script.push("bin");173					switch_script.push("switch-to-configuration");174					config175						.command_on(&host, switch_script, true)176						.arg(action.name())177						.stdout(Stdio::inherit())178						.run()179						.await?;180				}181			}182			Action::Package(PackageAction::SdImage) => {183				let mut out = current_dir()?;184				out.push(format!("sd-image-{}", host));185186				info!("building sd image to {:?}", out);187				let mut nix_build = if self.privileged_build {188					let mut out = Command::new("sudo");189					out.arg("nix");190					out191				} else {192					Command::new("nix")193				};194				nix_build195					.args(&["build", "--impure", "--no-link", "--out-link"])196					.arg(&out)197					.arg(config.configuration_attr_name(&format!(198						"configuredSystems.{}.config.system.build.sdImage",199						host,200					)));201				if let Some(builders) = &self.builders {202					nix_build.arg("--builders").arg(builders);203				}204				if let Some(jobs) = &self.jobs {205					nix_build.arg("--max-jobs");206					nix_build.arg(format!("{}", jobs));207				}208				if !self.fail_fast {209					nix_build.arg("--keep-going");210				}211212				nix_build.inherit_stdio().run_nix().await?;213			}214		};215		Ok(())216	}217218	pub async fn run(self, config: &Config) -> Result<()> {219		let hosts = config.list_hosts().await?;220		let set = LocalSet::new();221		let this = &self;222		for host in hosts.iter() {223			if config.should_skip(host) {224				continue;225			}226			let config = config.clone();227			let host = host.clone();228			let this = this.clone();229			let span = info_span!("deployment", host = field::display(&host));230			set.spawn_local(231				(async move {232					match this.build_task(config, host).await {233						Ok(_) => {}234						Err(e) => {235							error!("failed to deploy host: {}", e)236						}237					}238				})239				.instrument(span),240			);241		}242		set.await;243		Ok(())244	}245}
modifiedlib/default.nixdiffbeforeafterboth
--- a/lib/default.nix
+++ b/lib/default.nix
@@ -20,21 +20,17 @@
           if failedAssertions != [ ]
           then throw "Failed assertions:\n${nixpkgs.lib.concatStringsSep "\n" (map (x: "- ${x}") failedAssertions)}"
           else nixpkgs.lib.showWarnings root.config.warnings root;
-      in
-      rec {
         configuredHosts = rootAssertWarn.config.hosts;
         configuredSecrets = rootAssertWarn.config.secrets;
-        configuredSystems = nixpkgs.lib.listToAttrs (
+        configuredSystems = configuredSystemsWithExtraModules [ ];
+        configuredSystemsWithExtraModules = extraModules: nixpkgs.lib.listToAttrs (
           map
             (
               name: {
                 inherit name;
                 value = nixpkgs.lib.nixosSystem {
                   system = configuredHosts.${name}.system;
-                  modules = configuredHosts.${name}.modules ++ (
-                    if configuredHosts.${name}.system == "aarch64-linux" then [ (nixpkgs + "/nixos/modules/installer/sd-card/sd-image-aarch64-installer.nix") ]
-                    else [ ]
-                  ) ++ [
+                  modules = configuredHosts.${name}.modules ++ extraModules ++ [
                     ({ ... }: {
                       nixpkgs.system = system;
                       nixpkgs.localSystem.system = system;
@@ -51,6 +47,22 @@
               }
             )
             (builtins.attrNames rootAssertWarn.config.hosts)
-        ); #nixpkgs.lib.nixosSystem {}
+        );
+      in
+      rec {
+        inherit configuredHosts configuredSecrets configuredSystems;
+        buildSystems = {
+          toplevel = builtins.mapAttrs (_name: value: value.config.system.build.toplevel) (configuredSystemsWithExtraModules [ ]);
+          sdImage = builtins.mapAttrs (_name: value: value.config.system.build.sdImage) (configuredSystemsWithExtraModules [
+            (nixpkgs + "/nixos/modules/installer/sd-card/sd-image-aarch64-installer.nix")
+          ]);
+          installationCd = builtins.mapAttrs (_name: value: value.config.system.build.isoImage) (configuredSystemsWithExtraModules [
+            (nixpkgs + "/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix")
+            ({ lib, ... }: {
+              # Needed for https://github.com/NixOS/nixpkgs/issues/58959
+              boot.supportedFilesystems = lib.mkForce [ "btrfs" "reiserfs" "vfat" "f2fs" "xfs" "ntfs" "cifs" ];
+            })
+          ]);
+        };
       });
 }