Skip to content

Commit

Permalink
Display some of nix show-config (#19)
Browse files Browse the repository at this point in the history
Also add Rust tests, and run them as part of Nix build.
  • Loading branch information
srid authored Aug 8, 2023
1 parent 0176f91 commit a22606e
Show file tree
Hide file tree
Showing 7 changed files with 152 additions and 8 deletions.
6 changes: 3 additions & 3 deletions flake.lock

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

7 changes: 7 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@
};
};

leptos-fullstack.overrideCraneArgs = oa: {
nativeBuildInputs = (oa.nativeBuildInputs or [ ]) ++ [
pkgs.nix # cargo tests need nix
];
};

packages.default = self'.packages.nix-browser;

devShells.default = pkgs.mkShell {
Expand All @@ -47,6 +53,7 @@
];
nativeBuildInputs = with pkgs; [
just
cargo-watch
];
};
};
Expand Down
4 changes: 4 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,7 @@ fmt:
# Run the project locally
watch *ARGS:
cargo leptos watch

# Run tests (backend & frontend)
test:
cargo watch -- cargo leptos test
2 changes: 1 addition & 1 deletion src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ fn Home(cx: Scope) -> impl IntoView {
<h1 class="text-5xl font-bold">Welcome to nix-browser</h1>
<p class="py-6">
<h2 class="text-3xl font-bold text-gray-500">"Nix Info"</h2>
<div class="my-1">
<div class="my-1 text-left">
<Suspense fallback=move || view! {cx, <Spinner /> }>
<ErrorBoundary fallback=|cx, errors| view! { cx, <Errors errors=errors.get() /> } >
{nix_info.read(cx)}
Expand Down
118 changes: 118 additions & 0 deletions src/nix/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
use leptos::*;
use serde::{Deserialize, Serialize};

/// Nix configuration spit out by `nix show-config`
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
/// Information about the user's Nix installation
#[serde(rename_all = "kebab-case")]
pub struct NixConfig {
pub cores: ConfigVal<i32>,
pub experimental_features: ConfigVal<Vec<String>>,
pub extra_platforms: ConfigVal<Vec<String>>,
pub flake_registry: ConfigVal<String>,
pub max_jobs: ConfigVal<i32>,
pub substituters: ConfigVal<Vec<String>>,
pub system: ConfigVal<String>,
}

/// The value for each 'nix show-config --json' key.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ConfigVal<T> {
/// Current value in use.
pub value: T,
/// Default value by Nix.
pub default_value: T,
/// Description of this config item.
pub description: String,
}

impl IntoView for ConfigVal<Vec<String>> {
fn into_view(self, cx: Scope) -> View {
view! {cx,
// Render a list of T items in the list 'self'
<div class="flex flex-col space-y-4">
{self.value.into_iter().map(|item| view! {cx, <div>{item}</div>}).collect_view(cx)}
</div>
}
.into_view(cx)
}
}

impl IntoView for ConfigVal<i32> {
fn into_view(self, cx: Scope) -> View {
self.value.into_view(cx)
}
}

impl IntoView for ConfigVal<String> {
fn into_view(self, cx: Scope) -> View {
self.value.into_view(cx)
}
}

/// Get the output of `nix show-config`
#[cfg(feature = "ssr")]
pub async fn get_nix_config() -> Result<NixConfig, ServerFnError> {
run_nix_show_config().await
}

#[cfg(feature = "ssr")]
pub async fn run_nix_show_config() -> Result<NixConfig, ServerFnError> {
use tokio::process::Command;
let out = Command::new("nix")
.args(vec![
"--extra-experimental-features",
"nix-command",
"show-config",
"--json",
])
.output()
.await?;
if out.status.success() {
let v = serde_json::from_slice::<NixConfig>(&out.stdout)?;
Ok(v)
} else {
Err(ServerFnError::ServerError(
"'nix show-config' failed".into(),
))
}
}

impl IntoView for NixConfig {
fn into_view(self, cx: Scope) -> View {
fn mk_row<T: IntoView>(cx: Scope, key: impl IntoView, value: ConfigVal<T>) -> impl IntoView
where
ConfigVal<T>: IntoView,
{
view! {cx,
// TODO: Use a nice Tailwind tooltip here, instead of "title"
// attribute.
<tr title=&value.description>
<td class="px-4 py-2 font-bold">{key}</td>
<td class="px-4 py-2 text-left">{value}</td>
</tr>
}
}
view! {cx,
<div class="py-1 my-1 rounded bg-blue-50">
<table class="text-right">
<tbody>
{mk_row(cx, "System", self.system)}
{mk_row(cx, "Max Jobs", self.max_jobs)}
{mk_row(cx, "Cores per build", self.cores)}
{mk_row(cx, "Nix Caches", self.substituters)}
</tbody>
</table>
</div>
}
.into_view(cx)
}
}

#[cfg(feature = "ssr")]
#[tokio::test]
async fn test_run_nix_show_config() {
let nix_config = run_nix_show_config().await.unwrap();
println!("Max Jobs: {}", nix_config.max_jobs.value)
}
22 changes: 18 additions & 4 deletions src/nix/info.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,30 @@
use leptos::*;
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
use crate::nix::config::NixConfig;

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
/// Information about the user's Nix installation
pub struct NixInfo {
/// Nix version string
pub nix_version: String,
pub nix_config: NixConfig,
}

#[server(GetNixInfo, "/api")]
pub async fn get_nix_info() -> Result<NixInfo, ServerFnError> {
use super::config::get_nix_config;
use tokio::process::Command;
let out = Command::new("nix").arg("--version").output().await?;
if out.status.success() {
// TODO: Parse the version string
let nix_version = String::from_utf8(out.stdout)
.map_err(|e| <std::string::FromUtf8Error as Into<ServerFnError>>::into(e))?;
Ok(NixInfo { nix_version })
let nix_config = get_nix_config().await?;
Ok(NixInfo {
nix_version,
nix_config,
})
} else {
Err(ServerFnError::ServerError(
"Unable to determine nix version".into(),
Expand All @@ -27,9 +35,15 @@ pub async fn get_nix_info() -> Result<NixInfo, ServerFnError> {
impl IntoView for NixInfo {
fn into_view(self, cx: Scope) -> View {
view! {cx,
<div class="p-2 bg-blue-100 border-2 border-black rounded shadow-md">
<b>Nix Version:</b>
<div class="flex flex-col p-4 space-y-8 bg-blue-100 border-2 border-black rounded shadow-md">
<div>
<b>Nix Version</b>
<pre>{self.nix_version}</pre>
</div>
<div>
<b>Nix Config</b>
{self.nix_config}
</div>
</div>
}
.into_view(cx)
Expand Down
1 change: 1 addition & 0 deletions src/nix/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
pub mod config;
pub mod info;

0 comments on commit a22606e

Please sign in to comment.