fix(maestro): install maestro without the registry feature
ci / rust (push) Successful in 8m13s

The installer's cargo install of the umbrella maestro crate built the
default feature set (cli+daemon+registry+tui), forcing every host to
compile the registry — which a host neither needs nor runs (the registry
is a separate, centrally-deployed service). Install with
--no-default-features --features cli,daemon,tui instead.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-29 06:42:43 +00:00
co-authored by Claude Opus 4.8
parent 212ebbf120
commit 1cafa2c2af
2 changed files with 56 additions and 10 deletions
+41 -4
View File
@@ -41,7 +41,18 @@ impl SystemctlAction {
/// Build the args for `cargo install <args...>` (excluding the `cargo` and
/// `install` words themselves). `locked` adds `--locked` so the install uses
/// the committed `Cargo.lock`.
pub fn cargo_install_args(source: &CargoSource, crate_name: &str, locked: bool) -> Vec<String> {
/// Build the `cargo install` argument vector.
///
/// `features`, when `Some`, restricts the build to an explicit feature set via
/// `--no-default-features --features <list>`. The installer uses this to skip
/// the `registry` feature of the umbrella `maestro` crate: a host runs the CLI
/// + daemon (+ TUI); the registry is a separate, centrally-deployed service.
pub fn cargo_install_args(
source: &CargoSource,
crate_name: &str,
locked: bool,
features: Option<&str>,
) -> Vec<String> {
let mut args: Vec<String> = Vec::new();
match source {
CargoSource::Git { url, branch } => {
@@ -60,6 +71,11 @@ pub fn cargo_install_args(source: &CargoSource, crate_name: &str, locked: bool)
args.push(crate_name.to_string());
}
}
if let Some(list) = features {
args.push("--no-default-features".into());
args.push("--features".into());
args.push(list.to_string());
}
if locked {
args.push("--locked".into());
}
@@ -101,20 +117,41 @@ mod tests {
url: "https://git.naps.pt/naps62/maestro".into(),
branch: None,
};
let args = cargo_install_args(&src, "maestro", false);
let args = cargo_install_args(&src, "maestro", false, None);
assert_eq!(
args,
vec!["--git", "https://git.naps.pt/naps62/maestro", "maestro",]
);
}
#[test]
fn git_args_with_features_omit_defaults() {
let src = CargoSource::Git {
url: "https://git.naps.pt/naps62/maestro".into(),
branch: None,
};
let args = cargo_install_args(&src, "maestro", true, Some("cli,daemon,tui"));
assert_eq!(
args,
vec![
"--git",
"https://git.naps.pt/naps62/maestro",
"maestro",
"--no-default-features",
"--features",
"cli,daemon,tui",
"--locked",
]
);
}
#[test]
fn git_args_with_branch_and_locked() {
let src = CargoSource::Git {
url: "https://git.example/x".into(),
branch: Some("main".into()),
};
let args = cargo_install_args(&src, "maestro", true);
let args = cargo_install_args(&src, "maestro", true, None);
assert_eq!(
args,
vec![
@@ -131,7 +168,7 @@ mod tests {
#[test]
fn path_args_use_p_flag() {
let src = CargoSource::Path(PathBuf::from("/repos/maestro"));
let args = cargo_install_args(&src, "maestro", true);
let args = cargo_install_args(&src, "maestro", true, None);
assert_eq!(
args,
vec!["--path", "/repos/maestro", "-p", "maestro", "--locked",]
+15 -6
View File
@@ -22,8 +22,14 @@ use maestro_installer::{
};
const DEFAULT_GIT_URL: &str = "https://git.naps.pt/naps62/maestro";
/// Unified `maestro` crate — single `cargo install` covers CLI + daemon + registry.
/// Unified `maestro` crate. The installer builds it with the host feature set
/// (CLI + daemon + TUI); the `registry` feature is left out (see
/// `MAESTRO_HOST_FEATURES`).
const MAESTRO_CRATE: &str = "maestro";
/// Features installed for a host: CLI + per-host daemon + TUI. The `registry`
/// feature is deliberately omitted — the registry is a separate, centrally-
/// deployed service, not something a host install should compile or run.
const MAESTRO_HOST_FEATURES: &str = "cli,daemon,tui";
const WEB_CRATE: &str = "maestro-web";
const SYSTEMD_PROBE: &str = "/run/systemd/system";
@@ -101,9 +107,9 @@ fn run(args: Args) -> Result<(), Box<dyn std::error::Error>> {
return Ok(());
}
// 1. Install the unified binary (NAP-245).
// 1. Install the unified binary (NAP-245), minus the registry feature.
let locked = !args.no_locked;
install_crate(&source, MAESTRO_CRATE, locked)?;
install_crate(&source, MAESTRO_CRATE, locked, Some(MAESTRO_HOST_FEATURES))?;
// 2. Offer to run `maestro daemon configure` now (must happen before systemd
// start, since the daemon refuses to run without registry_url / token).
@@ -164,7 +170,9 @@ fn print_banner(source: &CargoSource) {
eprintln!("maestro installer");
eprintln!();
eprintln!("This wizard will:");
eprintln!(" 1. cargo install `{MAESTRO_CRATE}` (unified CLI + daemon + registry)");
eprintln!(
" 1. cargo install `{MAESTRO_CRATE}` (CLI + daemon + TUI; registry runs separately)"
);
eprintln!(" 2. (optional) run `maestro daemon configure` to bootstrap the config file");
eprintln!(" 3. (optional) install a systemd user unit and enable it");
eprintln!(" 4. (optional) install `{WEB_CRATE}` + its systemd unit (browser UI)");
@@ -185,9 +193,10 @@ fn install_crate(
source: &CargoSource,
crate_name: &str,
locked: bool,
features: Option<&str>,
) -> Result<(), Box<dyn std::error::Error>> {
let cargo = cargo_bin();
let args = cargo_install_args(source, crate_name, locked);
let args = cargo_install_args(source, crate_name, locked, features);
eprintln!("\n==> cargo install {}", args.join(" "));
let status = Command::new(&cargo).arg("install").args(&args).status()?;
if !status.success() {
@@ -449,7 +458,7 @@ fn handle_web(
// doesn't need to be undone.
let source = build_source(args);
let locked = !args.no_locked;
if let Err(e) = install_crate(&source, WEB_CRATE, locked) {
if let Err(e) = install_crate(&source, WEB_CRATE, locked, None) {
eprintln!("maestro-web install failed: {e}");
eprintln!("(skipping systemd unit; re-run after fixing the build.)");
return Ok(false);