Skip to content

Commit

Permalink
feat(step): nix-helper
Browse files Browse the repository at this point in the history
  • Loading branch information
dtomvan committed Feb 17, 2025
1 parent fa3e472 commit 3227a96
Show file tree
Hide file tree
Showing 6 changed files with 127 additions and 3 deletions.
31 changes: 29 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ notify-rust = "~4.11"
wildmatch = "2.3.0"
rust-i18n = "3.0.1"
sys-locale = "0.3.1"
whoami = "1.5.2"

[package.metadata.generate-rpm]
assets = [{ source = "target/release/topgrade", dest = "/usr/bin/topgrade" }]
Expand Down
18 changes: 18 additions & 0 deletions locales/app.yml
Original file line number Diff line number Diff line change
Expand Up @@ -793,3 +793,21 @@ _version: 2
es: "No se pueden actualizar las aplicaciones de Microsoft Store, se requiere intervención manual"
fr: "Impossible de mettre à jour les applications du Microsoft Store, une intervention manuelle est nécessaire"
zh_TW: "無法更新 Microsoft Store 應用,需手動幹預"

"No flake configurations found for nh":
en: "No flake configurations found for nh"
es: "No se encontraron configuraciones de flake para nh."
fr: "Aucune configuration de flake trouvée pour nh."
zh_TW: "没有为 nh 找到 flake 配置"

"No username found":
en: "No username found"
es: "No se encontró ningún nombre de usuario."
fr: "Aucun nom d'utilisateur trouvé."
zh_TW: "未找到用户名"

"No hostname found":
en: "No hostname found"
es: "No se encontró ningún nombre de host."
fr: "Aucun nom d'hôte trouvé."
zh_TW: "未找到主机名"
1 change: 1 addition & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ pub enum Step {
Mise,
Myrepos,
Nix,
NixHelper,
Node,
Opam,
Pacdef,
Expand Down
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,7 @@ fn run() -> Result<()> {
runner.execute(Step::Yadm, "yadm", || unix::run_yadm(&ctx))?;
runner.execute(Step::Nix, "nix", || unix::run_nix(&ctx))?;
runner.execute(Step::Nix, "nix upgrade-nix", || unix::run_nix_self_upgrade(&ctx))?;
runner.execute(Step::NixHelper, "nh", || unix::run_nix_helper(&ctx))?;
runner.execute(Step::Guix, "guix", || unix::run_guix(&ctx))?;
runner.execute(Step::HomeManager, "home-manager", || unix::run_home_manager(&ctx))?;
runner.execute(Step::Asdf, "asdf", || unix::run_asdf(&ctx))?;
Expand Down
78 changes: 77 additions & 1 deletion src/steps/os/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ use regex::Regex;
use rust_i18n::t;
use semver::Version;
use tracing::debug;
use whoami::fallible::hostname;
use whoami::fallible::username;

#[cfg(target_os = "linux")]
use super::linux::Distribution;
Expand Down Expand Up @@ -620,8 +622,82 @@ fn nix_profile_dir(nix: &Path) -> Result<Option<PathBuf>> {
)
}

/// Update NixOS and home-manager through a flake using `nh`
///
/// See: https://github.com/viperML/nh
pub fn run_nix_helper(ctx: &ExecutionContext) -> Result<()> {
let nix = require("nix")?;
let nix_helper = require("nh")?;
let flake_path: PathBuf = std::env::var_os("FLAKE")
.ok_or_else(|| SkipStep("$FLAKE not set".into()))?
.require()?
.into();

flake_path.join("flake.nix").require()?;

let run_type = ctx.run_type();

// we never dry run this because it doesn't perform any changes and because it ensures that the
// behaviour between dry and wet runs is the same i.e. the checks performed are the same
// between dry and wet runs
let run_nix_eval = |attr| -> Result<String> {
Ok(String::from_utf8(
std::process::Command::new(&nix)
.args(nix_args())
.arg("eval")
.arg(format!("{}#{attr}", flake_path.display()))
.arg("--apply")
.arg("builtins.attrNames")
.output_checked()?
.stdout,
)?)
};

let nixos_cfg = run_nix_eval("nixosConfigurations");
let home_cfg = run_nix_eval("homeConfigurations");

if nixos_cfg.as_ref().or(home_cfg.as_ref()).is_err() && !run_type.dry() {
return Err(SkipStep(t!("No flake configurations found for nh").to_string()).into());
}

print_separator("nh flake");
run_type
.execute(&nix)
.args(nix_args())
.arg("flake")
.arg("update")
.arg("--flake")
.arg(&flake_path)
.status_checked()?;

let username = username().wrap_err_with(|| t!("No username found").to_string())?;
let hostname = hostname().wrap_err_with(|| t!("No hostname found").to_string())?;

// Let's not do any JSON parsing and just Keep It Simple
if nixos_cfg.is_ok_and(|x| x.contains(&format!(r#""{hostname}""#))) {
print_separator("nh os");

run_type.execute(&nix_helper).arg("os").arg("switch").status_checked()?;
}

if let Ok(home_cfg) = home_cfg {
let username_at_hostname = format!(r#""{username}@{hostname}""#);
if home_cfg.contains(&format!(r#""{username}""#)) || home_cfg.contains(&username_at_hostname) {
print_separator("nh home");

run_type
.execute(&nix_helper)
.arg("home")
.arg("switch")
.status_checked()?;
}
}

Ok(())
}

fn nix_args() -> [&'static str; 2] {
["--extra-experimental-features", "nix-command"]
["--extra-experimental-features", "nix-command flakes"]
}

pub fn run_yadm(ctx: &ExecutionContext) -> Result<()> {
Expand Down

0 comments on commit 3227a96

Please sign in to comment.