Skip to content

WIP: Try to support local builds #428

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 42 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ pub(crate) use os::{NixOperatingSystem, Verb};

use anyhow::{anyhow, bail, Context};
use os::Nixos;
use std::borrow::Cow;
use std::collections::HashMap;
use std::{
fmt,
path::{Path, PathBuf},
Expand Down Expand Up @@ -220,9 +222,32 @@ impl fmt::Display for Flavor {
}

impl Flavor {
pub fn on_connection(&self, host: &str, connection: openssh::Session) -> Arc<Nixos> {
pub fn on_connection(&self, dest: &Destination, connection: openssh::Session) -> Arc<Nixos> {
match self {
Flavor::Nixos => Arc::new(Nixos::new(host.to_owned(), connection)),
Flavor::Nixos => Arc::new(Nixos::new(dest.clone(), connection)),
}
}
}

/// Where and how to perform the build
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub enum BuildKind{
/// Build on the deploy destination host
#[default]
OnDestination,

/// Build on the system running deploy-flake
Local,
}

impl FromStr for BuildKind {
type Err = anyhow::Error;

fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"local" => Ok(BuildKind::Local),
"on_destination" => Ok(BuildKind::OnDestination),
_ => Err(anyhow::anyhow!("Could not parse build kind {:?}", s))
}
}
}
Expand All @@ -232,13 +257,20 @@ pub struct Destination {
pub os_flavor: Flavor,
pub hostname: String,
pub config_name: Option<String>,
pub build_kind: BuildKind,
}

impl FromStr for Destination {
type Err = anyhow::Error;

fn from_str(s: &str) -> Result<Self, Self::Err> {
if let Ok(url) = Url::parse(s) {
let query: HashMap<Cow<'_, str>, Cow<'_, str>>= url.query_pairs().collect();
let build_kind = if let Some(build_kind) = query.get("build_kind") {
build_kind.parse::<BuildKind>().with_context(|| format!("Parsing {:?}", s))?
} else {
Default::default()
};
// we have a URL, let's see if it matches something we can deal with:
match (url.scheme(), url.host_str(), url.path(), url.username()) {
("nixos", Some(host), path, username) => {
Expand All @@ -254,6 +286,7 @@ impl FromStr for Destination {
.strip_prefix('/')
.filter(|path| !path.is_empty())
.map(String::from),
build_kind,
})
}
_ => anyhow::bail!("Unable to parse {s}"),
Expand All @@ -263,11 +296,18 @@ impl FromStr for Destination {
os_flavor: Flavor::Nixos,
hostname: s.to_string(),
config_name: None,
build_kind: Default::default()
})
}
}
}

impl fmt::Display for Destination {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}://{}/{}", self.os_flavor, self.hostname, self.config_name.as_deref().unwrap_or(""))
}
}

#[cfg(test)]
mod test {
use super::Destination;
Expand Down
2 changes: 1 addition & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ async fn deploy(

log::debug!("Connecting");
let flavor = destination.os_flavor.on_connection(
&destination.hostname,
&destination,
Session::connect(&destination.hostname, KnownHosts::Strict)
.await
.with_context(|| format!("Connecting to {:?}", &destination.hostname))?,
Expand Down
12 changes: 6 additions & 6 deletions src/os/nixos.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::read_and_log_messages;
use crate::{read_and_log_messages, Destination};
use anyhow::Context;
use openssh::{Command, Stdio};
use tokio::io::AsyncReadExt;
Expand All @@ -18,7 +18,7 @@ use crate::{NixOperatingSystem, Verb};

/// A nixos operating system instance.
pub struct Nixos {
host: String,
host: Destination,
session: openssh::Session,
}

Expand All @@ -36,7 +36,7 @@ fn strip_shell_output(output: Output) -> String {

impl Nixos {
/// Setup a new Nixos connection
pub(crate) fn new(host: String, session: openssh::Session) -> Self {
pub(crate) fn new(host: Destination, session: openssh::Session) -> Self {
Self { host, session }
}

Expand Down Expand Up @@ -169,15 +169,15 @@ impl NixOperatingSystem for Nixos {
let script_path = if script.is_none() {
// Try to use the default pre-activation script name emitted by preflight-safety:
let script_path = derivation.join(DEFAULT_PREFLIGHT_SCRIPT_NAME);
log::event!(log::Level::DEBUG, dest=?self.host, script=?script_path.file_name(), "Checking for existence of inferred pre-activation script");
log::event!(log::Level::DEBUG, dest=%self.host, script=?script_path.file_name(), "Checking for existence of inferred pre-activation script");
if !self.test_file_existence(&script_path).await? {
return Ok(());
}
script_path
} else {
derivation.join(script.unwrap())
};
log::event!(log::Level::INFO, dest=?self.host, script=?script_path.file_name(), "Running pre-activation script");
log::event!(log::Level::INFO, dest=%self.host, script=?script_path.file_name(), "Running pre-activation script");
let mut cmd = self.session.command("sudo");
cmd.raw_arg(script_path);
self.run_command(cmd)
Expand Down Expand Up @@ -260,7 +260,7 @@ impl NixOperatingSystem for Nixos {
Ok(())
}

#[instrument(level = "DEBUG", skip(self), fields(host=self.host), err)]
#[instrument(level = "DEBUG", skip(self), fields(host=%self.host), err)]
async fn test_config(&self, derivation: &Path) -> Result<(), anyhow::Error> {
let mut cmd = self.session.command("sudo");
let flake_base_name = derivation
Expand Down
Loading