deploy script

This commit is contained in:
Patrick 2024-12-04 18:56:44 +01:00
parent ac55ccd2f5
commit 0cd8406ba5
Signed by: patrick
GPG key ID: 451F95EFB8BECD0F
4 changed files with 167 additions and 1309 deletions

1294
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -4,11 +4,13 @@ version = "0.1.0"
edition = "2021"
[dependencies]
async-trait = "0.1.83"
clap = { version = "4.5.20", features = ["derive"] }
color-eyre = "0.6.3"
futures = "0.3.31"
openssh = "0.11.4"
regex = "1.11.1"
reqwest = "0.12.9"
russh = "0.46.0"
serde = { version = "1.0.214", features = ["derive"] }
serde_json = "1.0.132"
tokio = { version = "1.41.1", features = ["full"] }

119
src/deploy.rs Normal file
View file

@ -0,0 +1,119 @@
use color_eyre::{eyre::Result, owo_colors::OwoColorize};
use futures::future::join_all;
use openssh::{KnownHosts, Session};
use std::{
env,
path::PathBuf,
process::{Command, Stdio},
};
fn gen_systems_path(system: &str) -> String {
format!(
".#nixosConfigurations.{}.config.system.build.toplevel",
system
)
}
pub fn build(systems: &[String], show_trace: bool) -> Result<()> {
if systems.is_empty() {
return Ok(());
}
let dir = env::var("PRJ_ROOT")
.map(PathBuf::from)
.or_else(|_| env::current_dir())?;
let mut configs = Vec::new();
for s in systems.iter().map(|x| gen_systems_path(x)) {
configs.push(format!(
".#nixosConfigurations.{}.config.system.build.toplevel",
s
));
}
let mut cmd = Command::new("nom");
let mut cmd = if cmd
.arg("--version")
.current_dir(dir)
.stdin(Stdio::null())
.stdout(Stdio::null())
.stderr(Stdio::null())
.spawn()
.is_err()
{
Command::new("nix")
} else {
Command::new("nom")
};
if show_trace {
cmd.arg("--show-trace");
};
let cmd = cmd
.arg("build")
.arg("--print-out-paths")
.arg("--no-link")
.args(configs);
cmd.spawn()?.wait()?;
Ok(())
}
pub async fn deploy(systems: &[String], show_trace: bool, mode: &str) -> Result<()> {
let (systems, hosts): (Vec<_>, Vec<_>) = systems
.iter()
.map(|x| x.split_once('@').unwrap_or((x, x)))
.unzip();
println!("Opening ssh connection for {} hosts.", hosts.len().blue());
let connections = hosts
.iter()
.map(|x| Session::connect(x, KnownHosts::Strict));
let connections = join_all(connections)
.await
.into_iter()
.collect::<std::result::Result<Vec<_>, openssh::Error>>()?;
build(
&systems.iter().map(|x| x.to_string()).collect::<Vec<_>>(),
show_trace,
)?;
for (system, (con, host)) in systems.into_iter().zip(connections.into_iter().zip(hosts)) {
let path = gen_systems_path(system);
let mut cmd = Command::new("nix");
let cmd = cmd.arg("eval").arg("--read-only").arg("--raw").arg(path);
let toplevel = String::from_utf8(cmd.output()?.stdout)?;
println!("Copyings toplevel for {}", system.blue());
let mut cmd = Command::new("nix");
let cmd = cmd
.arg("copy")
.arg("--to")
.arg(format!("ssh://{}", host))
.arg(&toplevel);
cmd.spawn()?.wait()?;
let prev_system = con
.command("readlink")
.arg("-e")
.arg("/nix/var/nix/profiles/system")
.output()
.await?
.stdout;
// register toplevel
con.command("nix-env")
.arg("--profile")
.arg("/nix/var/nix/profiles/system")
.arg("--set")
.arg(&toplevel)
.spawn()
.await?;
con.command(format!("{}/bin/switch-to-configuration", toplevel))
.arg(mode)
.spawn()
.await?;
if !prev_system.is_empty() {
con.command("nvd")
.arg("--color")
.arg("--always")
.arg("diff")
.arg(String::from_utf8(prev_system)?)
.arg(toplevel)
.spawn()
.await?;
}
}
Ok(())
}

View file

@ -1,16 +1,18 @@
use std::{
env,
fs::{self, read_dir},
io::Error,
path::PathBuf,
process::{Command, Stdio},
};
use clap::{error::ErrorKind, Args, CommandFactory, Parser, Subcommand};
use color_eyre::eyre::{bail, Result};
use color_eyre::{
eyre::{bail, Result},
owo_colors::OwoColorize,
};
use deploy::*;
use pr::*;
use regex::Regex;
use reqwest::{header, Client};
mod deploy;
mod pr;
#[derive(Parser)]
@ -51,6 +53,10 @@ struct AddPR {
#[derive(Args, Debug, Default)]
struct Deploy {
systems: Vec<String>,
#[arg(long, default_value_t = false)]
show_trace: bool,
#[arg(long, default_value_t = ("switch".to_string()))]
mode: String,
}
#[derive(Args, Debug, Default)]
@ -82,7 +88,12 @@ async fn main() -> Result<()> {
let nix_rev = get_local_nixp_rev()?;
println!("Local nixpkgs: {}", contains(&nix_rev, &pr, &client).await?);
for &i in BRANCHES {
println!("{}: {}", i, contains(i, &pr, &client).await?);
let t = contains(i, &pr, &client).await?;
if t {
println!("{:<25}: {}", i, "contained".green());
} else {
println!("{:<25}: {}", i, "not contained".red());
}
}
}
CliCommands::UpdatePrs(opts) => {
@ -107,10 +118,10 @@ async fn main() -> Result<()> {
bail!("This shouldn't happen")
};
let pr = get_pr(l, &client).await?;
println!("Fetching diff for PR #{}: {}", l, pr.title);
println!("Fetching diff for PR #{:<6}: {}", l, pr.title);
let branch = get_local_nixp_rev()?;
if contains(&branch, &pr, &client).await? {
println!("PR is contained in your local nixpkgs, removing diff");
println!("\tPR is contained in your local nixpkgs, removing diff");
fs::remove_file(format!("{}/{}.diff", opts.path, l))?;
} else {
get_diff(l, &opts.path, &client).await?;
@ -123,9 +134,6 @@ async fn main() -> Result<()> {
get_diff(pr, &opts.path, &client).await?;
}
CliCommands::Build(opts) => {
let dir = env::var("PRJ_ROOT")
.map(PathBuf::from)
.or_else(|_| env::current_dir())?;
if opts.systems.is_empty() {
let mut cmd = Cli::command();
cmd.error(
@ -134,35 +142,7 @@ async fn main() -> Result<()> {
)
.exit()
}
let mut configs = Vec::new();
for s in &opts.systems {
configs.push(format!(
".#nixosConfigurations.{}.config.system.build.toplevel",
s
));
}
println!("{:?}", configs);
let mut cmd = Command::new("nom");
let mut cmd = if cmd
.arg("--version")
.current_dir(dir)
.stdin(Stdio::null())
.stdout(Stdio::null())
.stderr(Stdio::null())
.spawn()
.is_err()
{
Command::new("nix")
} else {
Command::new("nom")
};
let cmd = cmd
.arg("build")
.arg("--print-out-paths")
.arg("--no-link")
.args(configs);
cmd.spawn()?.wait()?;
println!();
build(&opts.systems, opts.show_trace)?;
}
CliCommands::Deploy(opts) => {
@ -174,6 +154,7 @@ async fn main() -> Result<()> {
)
.exit()
}
deploy(&opts.systems, opts.show_trace, &opts.mode).await?;
}
};
Ok(())