deploy script
This commit is contained in:
parent
ac55ccd2f5
commit
0cd8406ba5
1294
Cargo.lock
generated
1294
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -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
119
src/deploy.rs
Normal 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(())
|
||||
}
|
59
src/main.rs
59
src/main.rs
|
@ -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!("\t↪ PR 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(())
|
||||
|
|
Loading…
Reference in a new issue