Skip to content

Commit

Permalink
Switch all sub-commands to use the new OmConfig
Browse files Browse the repository at this point in the history
  • Loading branch information
shivaraj-bh committed Nov 11, 2024
1 parent f0e792f commit 8fb2156
Show file tree
Hide file tree
Showing 11 changed files with 66 additions and 149 deletions.
4 changes: 2 additions & 2 deletions crates/omnix-ci/src/command/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use nix_rs::command::NixCmd;
use omnix_common::config::OmConfig;
use tracing::instrument;

use crate::{config::subflakes::SubflakesConfig, flake_ref::FlakeRef};
use crate::flake_ref::FlakeRef;

use super::{gh_matrix::GHMatrixCommand, run::RunCommand};

Expand Down Expand Up @@ -46,7 +46,7 @@ impl Command {
}

/// Get the omnix-ci [config::Config] associated with this subcommand
async fn get_config(&self, cmd: &NixCmd) -> anyhow::Result<OmConfig<SubflakesConfig>> {
async fn get_config(&self, cmd: &NixCmd) -> anyhow::Result<OmConfig> {
let url = self.get_flake_ref().to_flake_url().await?;
let cfg = crate::config::core::ci_config_from_flake_url(cmd, &url).await?;
tracing::debug!("Config: {cfg:?}");
Expand Down
4 changes: 2 additions & 2 deletions crates/omnix-ci/src/command/gh_matrix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ pub struct GHMatrixCommand {

impl GHMatrixCommand {
/// Run the command
pub async fn run(&self, cfg: OmConfig<SubflakesConfig>) -> anyhow::Result<()> {
let (config, _rest) = cfg.get_referenced()?;
pub async fn run(&self, cfg: OmConfig) -> anyhow::Result<()> {
let (config, _rest) = cfg.get_referenced_for::<SubflakesConfig>("ci")?;
let matrix = github::matrix::GitHubMatrix::from(self.systems.clone(), &config);
println!("{}", serde_json::to_string(&matrix)?);
Ok(())
Expand Down
29 changes: 11 additions & 18 deletions crates/omnix-ci/src/command/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,25 +65,15 @@ impl RunCommand {
}

/// Run the build command which decides whether to do ci run on current machine or a remote machine
pub async fn run(
&self,
nixcmd: &NixCmd,
verbose: bool,
cfg: OmConfig<SubflakesConfig>,
) -> anyhow::Result<()> {
pub async fn run(&self, nixcmd: &NixCmd, verbose: bool, cfg: OmConfig) -> anyhow::Result<()> {
match &self.on {
Some(store_uri) => run_remote::run_on_remote_store(nixcmd, self, &cfg, store_uri).await,
None => self.run_local(nixcmd, verbose, cfg).await,
}
}

/// Run [RunCommand] on local Nix store.
async fn run_local(
&self,
nixcmd: &NixCmd,
verbose: bool,
cfg: OmConfig<SubflakesConfig>,
) -> anyhow::Result<()> {
async fn run_local(&self, nixcmd: &NixCmd, verbose: bool, cfg: OmConfig) -> anyhow::Result<()> {
// TODO: We'll refactor this function to use steps
// https://github.com/juspay/omnix/issues/216

Expand All @@ -95,7 +85,7 @@ impl RunCommand {

// First, run the necessary health checks
tracing::info!("{}", "\n🫀 Performing health check".bold());
check_nix_version(&cfg.flake_url, nix_info).await?;
check_nix_version(&cfg, nix_info).await?;

// Then, do the CI steps
tracing::info!(
Expand Down Expand Up @@ -153,9 +143,11 @@ impl RunCommand {
}

/// Check that Nix version is not too old.
pub async fn check_nix_version(flake_url: &FlakeUrl, nix_info: &NixInfo) -> anyhow::Result<()> {
let omnix_health = NixHealth::from_flake(flake_url).await?;
let checks = omnix_health.nix_version.check(nix_info, Some(flake_url));
pub async fn check_nix_version(cfg: &OmConfig, nix_info: &NixInfo) -> anyhow::Result<()> {
let omnix_health = NixHealth::from_om_config(cfg)?;
let checks = omnix_health
.nix_version
.check(nix_info, Some(&cfg.flake_url));
let exit_code = NixHealth::print_report_returning_exit_code(&checks).await?;

if exit_code != 0 {
Expand All @@ -169,13 +161,14 @@ pub async fn ci_run(
cmd: &NixCmd,
verbose: bool,
run_cmd: &RunCommand,
cfg: &OmConfig<SubflakesConfig>,
cfg: &OmConfig,
nix_config: &NixConfig,
) -> anyhow::Result<RunResult> {
let mut res = HashMap::new();
let systems = run_cmd.get_systems(cmd, nix_config).await?;

let (config, attrs) = cfg.get_referenced()?;
let (config, attrs) = cfg.get_referenced_for::<SubflakesConfig>("ci")?;

// User's filter by subflake name
let only_subflake = attrs.first();

Expand Down
9 changes: 2 additions & 7 deletions crates/omnix-ci/src/command/run_remote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ use omnix_common::config::OmConfig;
use std::path::PathBuf;
use tokio::process::Command;

use crate::config::subflakes::SubflakesConfig;

use super::run::RunCommand;

/// Path to Rust source corresponding to this (running) instance of Omnix
Expand All @@ -21,7 +19,7 @@ const OMNIX_SOURCE: &str = env!("OMNIX_SOURCE");
pub async fn run_on_remote_store(
nixcmd: &NixCmd,
run_cmd: &RunCommand,
cfg: &OmConfig<SubflakesConfig>,
cfg: &OmConfig,
store_uri: &StoreURI,
) -> anyhow::Result<()> {
tracing::info!(
Expand All @@ -48,10 +46,7 @@ pub async fn run_on_remote_store(
}

/// Return the locally cached [FlakeUrl] for the given flake url that points to same selected [ConfigRef].
async fn cache_flake(
nixcmd: &NixCmd,
cfg: &OmConfig<SubflakesConfig>,
) -> anyhow::Result<(PathBuf, FlakeUrl)> {
async fn cache_flake(nixcmd: &NixCmd, cfg: &OmConfig) -> anyhow::Result<(PathBuf, FlakeUrl)> {
let metadata = FlakeMetadata::from_nix(nixcmd, &cfg.flake_url).await?;
let path = metadata.path.to_string_lossy().into_owned();
let attr = cfg.reference.join(".");
Expand Down
18 changes: 5 additions & 13 deletions crates/omnix-ci/src/config/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ use anyhow::Result;
use nix_rs::{command::NixCmd, flake::url::FlakeUrl};
use omnix_common::config::OmConfig;

use super::subflakes::SubflakesConfig;

/// Create a `Config` pointed to by this [FlakeUrl]
///
/// Example:
Expand All @@ -13,21 +11,15 @@ use super::subflakes::SubflakesConfig;
/// let cfg = Config::from_flake_url(&url).await?;
/// ```
/// along with the config.
pub async fn ci_config_from_flake_url(
cmd: &NixCmd,
url: &FlakeUrl,
) -> Result<OmConfig<SubflakesConfig>> {
let v = omnix_common::config::OmConfig::<SubflakesConfig>::from_flake_url(
cmd,
url,
&["om.ci", "nixci"],
)
.await?;
pub async fn ci_config_from_flake_url(cmd: &NixCmd, url: &FlakeUrl) -> Result<OmConfig> {
let v = omnix_common::config::OmConfig::from_flake_url(cmd, url).await?;
Ok(v)
}

#[cfg(test)]
mod tests {
use crate::config::subflakes::SubflakesConfig;

use super::*;

#[tokio::test]
Expand All @@ -41,7 +33,7 @@ mod tests {
let cfg = ci_config_from_flake_url(&NixCmd::default(), url)
.await
.unwrap();
let (config, attrs) = cfg.get_referenced().unwrap();
let (config, attrs) = cfg.get_referenced_for::<SubflakesConfig>("ci").unwrap();
assert_eq!(attrs, &["dev"]);
// assert_eq!(cfg.selected_subconfig, Some("dev".to_string()));
assert_eq!(config.0.len(), 7);
Expand Down
4 changes: 2 additions & 2 deletions crates/omnix-cli/src/command/develop.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use clap::Parser;
use nix_rs::{command::NixCmd, flake::url::FlakeUrl};
use omnix_common::config::OmnixConfig;
use omnix_common::config::OmConfig;

/// Prepare to develop on a flake project
#[derive(Parser, Debug)]
Expand Down Expand Up @@ -28,7 +28,7 @@ impl DevelopCommand {
pub async fn run(&self) -> anyhow::Result<()> {
let flake = self.flake_shell.without_attr();

let om_config = OmnixConfig::from_flake_url(NixCmd::get().await, &self.flake_shell).await?;
let om_config = OmConfig::from_flake_url(NixCmd::get().await, &self.flake_shell).await?;

tracing::info!("⌨️ Preparing to develop project: {:}", &flake);
let prj = omnix_develop::core::Project::new(flake, om_config).await?;
Expand Down
102 changes: 25 additions & 77 deletions crates/omnix-common/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,13 @@ use std::collections::BTreeMap;

use nix_rs::{
command::NixCmd,
flake::{
eval::nix_eval_attr,
url::{
qualified_attr::{nix_eval_qualified_attr, QualifiedAttrError},
FlakeUrl,
},
},
flake::{eval::nix_eval_attr, url::FlakeUrl},
};
use serde::de::DeserializeOwned;

/// Reference to the whole `om` configuration in a flake
pub struct OmnixConfig {
#[derive(Debug)]
pub struct OmConfig {
/// The flake URL used to load this configuration
pub flake_url: FlakeUrl,

Expand All @@ -26,20 +21,40 @@ pub struct OmnixConfig {
pub config: BTreeMap<String, BTreeMap<String, serde_json::Value>>,
}

impl OmnixConfig {
impl OmConfig {
/// Read the om configuration from the flake url
pub async fn from_flake_url(cmd: &NixCmd, flake_url: &FlakeUrl) -> Result<Self, OmConfigError> {
let qualified_url = flake_url.with_attr("om");
let config = nix_eval_attr(cmd, &qualified_url)
.await?
.unwrap_or_default();

Ok(OmnixConfig {
Ok(OmConfig {
flake_url: flake_url.clone(),
reference: flake_url.get_attr().as_list(),
config,
})
}

/// Get all the configs of type `T` for a given sub-config
pub fn get_sub_config<T>(&self, sub_config: &str) -> Result<BTreeMap<String, T>, OmConfigError>
where
T: DeserializeOwned,
{
let config = self
.config
.get(sub_config)
.ok_or_else(|| OmConfigError::MissingConfigAttribute(sub_config.to_string()))?;
config
.iter()
.map(|(k, v)| {
serde_json::from_value(v.clone())
.map_err(OmConfigError::from)
.map(|converted| (k.clone(), converted))
})
.collect()
}

/// Get the user-referenced config value `T` for a given sub-config
pub fn get_referenced_for<T>(&self, sub_config: &str) -> Result<(T, &[String]), OmConfigError>
where
Expand Down Expand Up @@ -75,76 +90,9 @@ impl OmnixConfig {
}
}

/// Reference to some Omnix configuration of type `BTeeMap<String, T>` in a flake
///
/// For example, CI configuration at `om.ci.default` is captured by the `T` type.
#[derive(Debug)]
pub struct OmConfig<T> {
/// The flake URL used to load this configuration
pub flake_url: FlakeUrl,

/// The (nested) key reference into the flake config.
pub reference: Vec<String>,

/// The whole `om.??` configuration parsed as `T`
pub config: BTreeMap<String, T>,
}

impl<T> OmConfig<T> {
/// Read the Om configuration from the flake URL
pub async fn from_flake_url<S>(
cmd: &NixCmd,
url: &FlakeUrl,
k: &[S],
) -> Result<OmConfig<T>, OmConfigError>
where
S: AsRef<str>,
T: DeserializeOwned,
{
let (config, reference) =
nix_eval_qualified_attr::<BTreeMap<String, T>, _>(cmd, url, k).await?;
Ok(OmConfig {
flake_url: url.without_attr(),
reference,
config,
})
}

/// Get the user-referenced config value `T`
///
/// If the user passes `.#foo.bar` this selects "foo" from the config tree, along with returning ["bar"].
///
/// If nothing is specifically passed, a default value is returned, either from config tree (key "default") or `T::default()`.
///
/// TODO: This needs to be adjusted to support `om.templates` style configuration as well, where this default behaviour makes no sense.
pub fn get_referenced(&self) -> Result<(T, &[String]), OmConfigError>
where
T: Default + Clone,
{
if let Some((k, rest)) = self.reference.split_first() {
if let Some(v) = self.config.get(k) {
Ok((v.clone(), rest))
} else {
Err(OmConfigError::MissingConfigAttribute(k.to_string()))
}
} else {
// Use default
if let Some(v) = self.config.get("default") {
Ok((v.clone(), &[]))
} else {
Ok((T::default(), &[]))
}
}
}
}

/// Error type for OmConfig
#[derive(thiserror::Error, Debug)]
pub enum OmConfigError {
/// Qualified attribute error
#[error("Qualified attribute error: {0}")]
QualifiedAttrError(#[from] QualifiedAttrError),

/// Missing configuration attribute
#[error("Missing configuration attribute: {0}")]
MissingConfigAttribute(String),
Expand Down
12 changes: 2 additions & 10 deletions crates/omnix-develop/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use serde::Deserialize;

use nix_rs::{command::NixCmd, flake::url::FlakeUrl};
use omnix_common::config::{OmConfig, OmnixConfig};
use omnix_common::config::OmConfig;

use crate::readme::Readme;

Expand All @@ -17,7 +16,7 @@ pub struct CacheConfig {
}

impl DevelopConfig {
pub fn from_om_config(om_config: &OmnixConfig) -> anyhow::Result<Self> {
pub fn from_om_config(om_config: &OmConfig) -> anyhow::Result<Self> {
if let Some(v) = om_config.config.get("develop") {
let config = v.get("default").cloned().unwrap_or_default();
let v1 = serde_json::from_value(config)?;
Expand All @@ -26,11 +25,4 @@ impl DevelopConfig {
Ok(Default::default())
}
}
pub async fn from_flake(url: &FlakeUrl) -> anyhow::Result<Self> {
let v = OmConfig::<Self>::from_flake_url(NixCmd::get().await, url, &["om.develop"])
.await?
.config;
let config = v.get("default").cloned().unwrap_or_default();
Ok(config)
}
}
6 changes: 3 additions & 3 deletions crates/omnix-develop/src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use anyhow::Context;
use std::{env::current_dir, path::PathBuf};

use nix_rs::{flake::url::FlakeUrl, info::NixInfo};
use omnix_common::{config::OmnixConfig, markdown::print_markdown};
use omnix_common::{config::OmConfig, markdown::print_markdown};
use omnix_health::{check::caches::CachixCache, traits::Checkable, NixHealth};

use crate::config::DevelopConfig;
Expand All @@ -14,11 +14,11 @@ pub struct Project {
/// [FlakeUrl] corresponding to the project.
pub flake: FlakeUrl,
/// The `om` configuration
pub om_config: OmnixConfig,
pub om_config: OmConfig,
}

impl Project {
pub async fn new(flake: FlakeUrl, om_config: OmnixConfig) -> anyhow::Result<Self> {
pub async fn new(flake: FlakeUrl, om_config: OmConfig) -> anyhow::Result<Self> {
let dir = match flake.as_local_path() {
Some(path) => Some(path.canonicalize()?),
None => None,
Expand Down
Loading

0 comments on commit 8fb2156

Please sign in to comment.