aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--flake.nix31
-rw-r--r--src/bin/activate.rs9
-rw-r--r--src/cli.rs11
-rw-r--r--src/deploy.rs15
4 files changed, 51 insertions, 15 deletions
diff --git a/flake.nix b/flake.nix
index 66ba60b..2d520b6 100644
--- a/flake.nix
+++ b/flake.nix
@@ -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>),
diff --git a/src/cli.rs b/src/cli.rs
index cc5a3ac..eb9094d 100644
--- a/src/cli.rs
+++ b/src/cli.rs
@@ -86,6 +86,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>,
@@ -409,6 +412,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> {
@@ -560,7 +564,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 {
@@ -617,6 +621,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
@@ -666,6 +674,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!");
}