Skip to content

Commit 3878dd4

Browse files
authored
Merge pull request #176 from Ma27/activate-boot
Add new activation strategy `boot` as equivalent to `nixos-rebuild boot`
2 parents 2a3c5f7 + 068372a commit 3878dd4

File tree

4 files changed

+51
-15
lines changed

4 files changed

+51
-15
lines changed

flake.nix

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@
6363
if [[ "''${DRY_ACTIVATE:-}" == "1" ]]
6464
then
6565
${customSelf.dryActivate or "echo ${final.writeScript "activate" activate}"}
66+
elif [[ "''${BOOT:-}" == "1" ]]
67+
then
68+
${customSelf.boot or "echo ${final.writeScript "activate" activate}"}
6669
else
6770
${activate}
6871
fi
@@ -83,17 +86,23 @@
8386
};
8487
};
8588

86-
nixos = base: (custom // { dryActivate = "$PROFILE/bin/switch-to-configuration dry-activate"; }) base.config.system.build.toplevel ''
87-
# work around https://github.com/NixOS/nixpkgs/issues/73404
88-
cd /tmp
89-
90-
$PROFILE/bin/switch-to-configuration switch
91-
92-
# https://github.com/serokell/deploy-rs/issues/31
93-
${with base.config.boot.loader;
94-
final.lib.optionalString systemd-boot.enable
95-
"sed -i '/^default /d' ${efi.efiSysMountPoint}/loader/loader.conf"}
96-
'';
89+
nixos = base:
90+
(custom // {
91+
dryActivate = "$PROFILE/bin/switch-to-configuration dry-activate";
92+
boot = "$PROFILE/bin/switch-to-configuration boot";
93+
})
94+
base.config.system.build.toplevel
95+
''
96+
# work around https://github.com/NixOS/nixpkgs/issues/73404
97+
cd /tmp
98+
99+
$PROFILE/bin/switch-to-configuration switch
100+
101+
# https://github.com/serokell/deploy-rs/issues/31
102+
${with base.config.boot.loader;
103+
final.lib.optionalString systemd-boot.enable
104+
"sed -i '/^default /d' ${efi.efiSysMountPoint}/loader/loader.conf"}
105+
'';
97106

98107
home-manager = base: custom base.activationPackage "$PROFILE/activate";
99108

src/bin/activate.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ struct ActivateOpts {
6969
#[clap(long)]
7070
dry_activate: bool,
7171

72+
/// Don't activate, but update the boot loader to boot into the new profile
73+
#[clap(long)]
74+
boot: bool,
75+
7276
/// Path for any temporary files that may be needed during activation
7377
#[clap(long)]
7478
temp_path: String,
@@ -363,6 +367,7 @@ pub async fn activate(
363367
confirm_timeout: u16,
364368
magic_rollback: bool,
365369
dry_activate: bool,
370+
boot: bool,
366371
) -> Result<(), ActivateError> {
367372
if !dry_activate {
368373
info!("Activating profile");
@@ -396,6 +401,7 @@ pub async fn activate(
396401
let activate_status = match Command::new(format!("{}/deploy-rs-activate", activation_location))
397402
.env("PROFILE", activation_location)
398403
.env("DRY_ACTIVATE", if dry_activate { "1" } else { "0" })
404+
.env("BOOT", if boot { "1" } else { "0" })
399405
.current_dir(activation_location)
400406
.status()
401407
.await
@@ -425,7 +431,7 @@ pub async fn activate(
425431
info!("Activation succeeded!");
426432
}
427433

428-
if magic_rollback {
434+
if magic_rollback && !boot {
429435
info!("Magic rollback is enabled, setting up confirmation hook...");
430436

431437
match activation_confirmation(profile_path.clone(), temp_path, confirm_timeout, closure)
@@ -479,6 +485,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
479485
activate_opts.confirm_timeout,
480486
activate_opts.magic_rollback,
481487
activate_opts.dry_activate,
488+
activate_opts.boot,
482489
)
483490
.await
484491
.map_err(|x| Box::new(x) as Box<dyn std::error::Error>),

src/cli.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ pub struct Opts {
9090
/// Show what will be activated on the machines
9191
#[clap(long)]
9292
dry_activate: bool,
93+
/// Don't activate, but update the boot loader to boot into the new profile
94+
#[clap(long)]
95+
boot: bool,
9396
/// Revoke all previously succeeded deploys when deploying multiple profiles
9497
#[clap(long)]
9598
rollback_succeeded: Option<bool>,
@@ -411,6 +414,7 @@ async fn run_deploy(
411414
extra_build_args: &[String],
412415
debug_logs: bool,
413416
dry_activate: bool,
417+
boot: bool,
414418
log_dir: &Option<String>,
415419
rollback_succeeded: bool,
416420
) -> Result<(), RunDeployError> {
@@ -562,7 +566,7 @@ async fn run_deploy(
562566
// Rollbacks adhere to the global seeting to auto_rollback and secondary
563567
// the profile's configuration
564568
for (_, deploy_data, deploy_defs) in &parts {
565-
if let Err(e) = deploy::deploy::deploy_profile(deploy_data, deploy_defs, dry_activate).await
569+
if let Err(e) = deploy::deploy::deploy_profile(deploy_data, deploy_defs, dry_activate, boot).await
566570
{
567571
error!("{}", e);
568572
if dry_activate {
@@ -619,6 +623,10 @@ pub async fn run(args: Option<&ArgMatches>) -> Result<(), RunError> {
619623
&deploy::LoggerType::Deploy,
620624
)?;
621625

626+
if opts.dry_activate && opts.boot {
627+
error!("Cannot use both --dry-activate & --boot!");
628+
}
629+
622630
let deploys = opts
623631
.clone()
624632
.targets
@@ -669,6 +677,7 @@ pub async fn run(args: Option<&ArgMatches>) -> Result<(), RunError> {
669677
&opts.extra_build_args,
670678
opts.debug_logs,
671679
opts.dry_activate,
680+
opts.boot,
672681
&opts.log_dir,
673682
opts.rollback_succeeded.unwrap_or(true),
674683
)

src/deploy.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ struct ActivateCommandData<'a> {
2222
debug_logs: bool,
2323
log_dir: Option<&'a str>,
2424
dry_activate: bool,
25+
boot: bool,
2526
}
2627

2728
fn build_activate_command(data: &ActivateCommandData) -> String {
@@ -57,6 +58,10 @@ fn build_activate_command(data: &ActivateCommandData) -> String {
5758
self_activate_command = format!("{} --dry-activate", self_activate_command);
5859
}
5960

61+
if data.boot {
62+
self_activate_command = format!("{} --boot", self_activate_command);
63+
}
64+
6065
if let Some(sudo_cmd) = &data.sudo {
6166
self_activate_command = format!("{} {}", sudo_cmd, self_activate_command);
6267
}
@@ -71,6 +76,7 @@ fn test_activation_command_builder() {
7176
let closure = "/nix/store/blah/etc";
7277
let auto_rollback = true;
7378
let dry_activate = false;
79+
let boot = false;
7480
let temp_path = "/tmp";
7581
let confirm_timeout = 30;
7682
let magic_rollback = true;
@@ -88,7 +94,8 @@ fn test_activation_command_builder() {
8894
magic_rollback,
8995
debug_logs,
9096
log_dir,
91-
dry_activate
97+
dry_activate,
98+
boot,
9299
}),
93100
"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"
94101
.to_string(),
@@ -270,6 +277,7 @@ pub async fn deploy_profile(
270277
deploy_data: &super::DeployData<'_>,
271278
deploy_defs: &super::DeployDefs,
272279
dry_activate: bool,
280+
boot: bool,
273281
) -> Result<(), DeployProfileError> {
274282
if !dry_activate {
275283
info!(
@@ -300,6 +308,7 @@ pub async fn deploy_profile(
300308
debug_logs: deploy_data.debug_logs,
301309
log_dir: deploy_data.log_dir,
302310
dry_activate,
311+
boot,
303312
});
304313

305314
debug!("Constructed activation command: {}", self_activate_command);
@@ -318,7 +327,7 @@ pub async fn deploy_profile(
318327
ssh_activate_command.arg(&ssh_opt);
319328
}
320329

321-
if !magic_rollback || dry_activate {
330+
if !magic_rollback || dry_activate || boot {
322331
let ssh_activate_exit_status = ssh_activate_command
323332
.arg(self_activate_command)
324333
.status()
@@ -332,6 +341,8 @@ pub async fn deploy_profile(
332341

333342
if dry_activate {
334343
info!("Completed dry-activate!");
344+
} else if boot {
345+
info!("Success activating for next boot, done!");
335346
} else {
336347
info!("Success activating, done!");
337348
}

0 commit comments

Comments
 (0)