diff options
-rw-r--r-- | flake.nix | 31 | ||||
-rw-r--r-- | src/bin/activate.rs | 9 | ||||
-rw-r--r-- | src/cli.rs | 11 | ||||
-rw-r--r-- | src/deploy.rs | 15 |
4 files changed, 51 insertions, 15 deletions
@@ -63,6 +63,9 @@ if [[ "''${DRY_ACTIVATE:-}" == "1" ]] then ${customSelf.dryActivate or "echo ${final.writeScript "activate" activate}"} + elif [[ "''${BOOT:-}" == "1" ]] + then + ${customSelf.boot or "echo ${final.writeScript "activate" activate}"} else ${activate} fi @@ -83,17 +86,23 @@ }; }; - nixos = base: (custom // { dryActivate = "$PROFILE/bin/switch-to-configuration dry-activate"; }) base.config.system.build.toplevel '' - # work around https://github.com/NixOS/nixpkgs/issues/73404 - cd /tmp - - $PROFILE/bin/switch-to-configuration switch - - # https://github.com/serokell/deploy-rs/issues/31 - ${with base.config.boot.loader; - final.lib.optionalString systemd-boot.enable - "sed -i '/^default /d' ${efi.efiSysMountPoint}/loader/loader.conf"} - ''; + nixos = base: + (custom // { + dryActivate = "$PROFILE/bin/switch-to-configuration dry-activate"; + boot = "$PROFILE/bin/switch-to-configuration boot"; + }) + base.config.system.build.toplevel + '' + # work around https://github.com/NixOS/nixpkgs/issues/73404 + cd /tmp + + $PROFILE/bin/switch-to-configuration switch + + # https://github.com/serokell/deploy-rs/issues/31 + ${with base.config.boot.loader; + final.lib.optionalString systemd-boot.enable + "sed -i '/^default /d' ${efi.efiSysMountPoint}/loader/loader.conf"} + ''; home-manager = base: custom base.activationPackage "$PROFILE/activate"; diff --git a/src/bin/activate.rs b/src/bin/activate.rs index d0cfbe1..4c865f1 100644 --- a/src/bin/activate.rs +++ b/src/bin/activate.rs @@ -69,6 +69,10 @@ struct ActivateOpts { #[clap(long)] dry_activate: bool, + /// Don't activate, but update the boot loader to boot into the new profile + #[clap(long)] + boot: bool, + /// Path for any temporary files that may be needed during activation #[clap(long)] temp_path: String, @@ -363,6 +367,7 @@ pub async fn activate( confirm_timeout: u16, magic_rollback: bool, dry_activate: bool, + boot: bool, ) -> Result<(), ActivateError> { if !dry_activate { info!("Activating profile"); @@ -396,6 +401,7 @@ pub async fn activate( let activate_status = match Command::new(format!("{}/deploy-rs-activate", activation_location)) .env("PROFILE", activation_location) .env("DRY_ACTIVATE", if dry_activate { "1" } else { "0" }) + .env("BOOT", if boot { "1" } else { "0" }) .current_dir(activation_location) .status() .await @@ -425,7 +431,7 @@ pub async fn activate( info!("Activation succeeded!"); } - if magic_rollback { + if magic_rollback && !boot { info!("Magic rollback is enabled, setting up confirmation hook..."); match activation_confirmation(profile_path.clone(), temp_path, confirm_timeout, closure) @@ -479,6 +485,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> { activate_opts.confirm_timeout, activate_opts.magic_rollback, activate_opts.dry_activate, + activate_opts.boot, ) .await .map_err(|x| Box::new(x) as Box<dyn std::error::Error>), @@ -90,6 +90,9 @@ pub struct Opts { /// Show what will be activated on the machines #[clap(long)] dry_activate: bool, + /// Don't activate, but update the boot loader to boot into the new profile + #[clap(long)] + boot: bool, /// Revoke all previously succeeded deploys when deploying multiple profiles #[clap(long)] rollback_succeeded: Option<bool>, @@ -411,6 +414,7 @@ async fn run_deploy( extra_build_args: &[String], debug_logs: bool, dry_activate: bool, + boot: bool, log_dir: &Option<String>, rollback_succeeded: bool, ) -> Result<(), RunDeployError> { @@ -562,7 +566,7 @@ async fn run_deploy( // Rollbacks adhere to the global seeting to auto_rollback and secondary // the profile's configuration for (_, deploy_data, deploy_defs) in &parts { - if let Err(e) = deploy::deploy::deploy_profile(deploy_data, deploy_defs, dry_activate).await + if let Err(e) = deploy::deploy::deploy_profile(deploy_data, deploy_defs, dry_activate, boot).await { error!("{}", e); if dry_activate { @@ -619,6 +623,10 @@ pub async fn run(args: Option<&ArgMatches>) -> Result<(), RunError> { &deploy::LoggerType::Deploy, )?; + if opts.dry_activate && opts.boot { + error!("Cannot use both --dry-activate & --boot!"); + } + let deploys = opts .clone() .targets @@ -669,6 +677,7 @@ pub async fn run(args: Option<&ArgMatches>) -> Result<(), RunError> { &opts.extra_build_args, opts.debug_logs, opts.dry_activate, + opts.boot, &opts.log_dir, opts.rollback_succeeded.unwrap_or(true), ) diff --git a/src/deploy.rs b/src/deploy.rs index 5c4b656..cc5d862 100644 --- a/src/deploy.rs +++ b/src/deploy.rs @@ -22,6 +22,7 @@ struct ActivateCommandData<'a> { debug_logs: bool, log_dir: Option<&'a str>, dry_activate: bool, + boot: bool, } fn build_activate_command(data: &ActivateCommandData) -> String { @@ -57,6 +58,10 @@ fn build_activate_command(data: &ActivateCommandData) -> String { self_activate_command = format!("{} --dry-activate", self_activate_command); } + if data.boot { + self_activate_command = format!("{} --boot", self_activate_command); + } + if let Some(sudo_cmd) = &data.sudo { self_activate_command = format!("{} {}", sudo_cmd, self_activate_command); } @@ -71,6 +76,7 @@ fn test_activation_command_builder() { let closure = "/nix/store/blah/etc"; let auto_rollback = true; let dry_activate = false; + let boot = false; let temp_path = "/tmp"; let confirm_timeout = 30; let magic_rollback = true; @@ -88,7 +94,8 @@ fn test_activation_command_builder() { magic_rollback, debug_logs, log_dir, - dry_activate + dry_activate, + boot, }), "sudo -u test /nix/store/blah/etc/activate-rs --debug-logs --log-dir /tmp/something.txt activate '/nix/store/blah/etc' '/blah/profiles/test' --temp-path '/tmp' --confirm-timeout 30 --magic-rollback --auto-rollback" .to_string(), @@ -270,6 +277,7 @@ pub async fn deploy_profile( deploy_data: &super::DeployData<'_>, deploy_defs: &super::DeployDefs, dry_activate: bool, + boot: bool, ) -> Result<(), DeployProfileError> { if !dry_activate { info!( @@ -300,6 +308,7 @@ pub async fn deploy_profile( debug_logs: deploy_data.debug_logs, log_dir: deploy_data.log_dir, dry_activate, + boot, }); debug!("Constructed activation command: {}", self_activate_command); @@ -318,7 +327,7 @@ pub async fn deploy_profile( ssh_activate_command.arg(&ssh_opt); } - if !magic_rollback || dry_activate { + if !magic_rollback || dry_activate || boot { let ssh_activate_exit_status = ssh_activate_command .arg(self_activate_command) .status() @@ -332,6 +341,8 @@ pub async fn deploy_profile( if dry_activate { info!("Completed dry-activate!"); + } else if boot { + info!("Success activating for next boot, done!"); } else { info!("Success activating, done!"); } |