From bd8f33edffddb90263d87c3d818f2aabef6feed2 Mon Sep 17 00:00:00 2001 From: fargito Date: Wed, 10 Jun 2026 11:58:37 +0200 Subject: [PATCH] feat(setup): add optional `mode` arg to target setup In some cases, we want to setup only one or several modes. We can now do so with the `mode` argument that only installs the requested mode. Usage: - `codspeed setup`: installs all modes - `codspeed setup --mode simulation`: only setup simulation mode - `codspeed setup --mode simulation,walltime`: setup both modes - `codspeed setup --mode simulation --mode walltime`: setup both modes - `codspeed setup status`: show status for all modes - `codspeed setup --mode simulation` status: show status for simulation mode - `codspeed setup --mode simulation,walltime` status: show status for both modes - `codspeed setup --mode simulation --mode walltime` status: show status for both modes --- src/cli/setup.rs | 102 ++++++++++++++++++++++++++++++++-------------- src/cli/status.rs | 2 +- 2 files changed, 72 insertions(+), 32 deletions(-) diff --git a/src/cli/setup.rs b/src/cli/setup.rs index db1d8a9d..76aca014 100644 --- a/src/cli/setup.rs +++ b/src/cli/setup.rs @@ -1,5 +1,8 @@ -use crate::executor::{ExecutorSupport, ToolInstallStatus, get_all_executors}; +use crate::executor::{ + Executor, ExecutorSupport, ToolInstallStatus, get_all_executors, get_executor_from_mode, +}; use crate::prelude::*; +use crate::runner_mode::RunnerMode; use crate::system::SystemInfo; use clap::{Args, Subcommand}; use console::style; @@ -9,6 +12,16 @@ use super::status::{check_mark, cross_mark, warn_mark}; #[derive(Debug, Default, Args)] pub struct SetupArgs { + /// The modes to set up. If omitted, the environment is set up for all supported executors. + #[arg( + short, + long, + value_enum, + env = "CODSPEED_RUNNER_MODE", + value_delimiter = ',' + )] + mode: Vec, + #[command(subcommand)] command: Option, } @@ -21,49 +34,76 @@ enum SetupCommands { pub async fn run(args: SetupArgs, setup_cache_dir: Option<&Path>) -> Result<()> { match args.command { - None => setup(setup_cache_dir).await, - Some(SetupCommands::Status) => status(), + Some(SetupCommands::Status) => status(&args.mode), + None => setup(&args.mode, setup_cache_dir).await, + } +} + +/// Resolve the executors to operate on from the requested modes. +/// +/// An empty list of modes means "every executor". +fn get_executors_from_modes(modes: &[RunnerMode]) -> Vec> { + if modes.is_empty() { + get_all_executors() + } else { + modes + .iter() + .map(|mode| get_executor_from_mode(mode, None)) + .collect() } } -async fn setup(setup_cache_dir: Option<&Path>) -> Result<()> { +async fn setup(modes: &[RunnerMode], setup_cache_dir: Option<&Path>) -> Result<()> { let system_info = SystemInfo::new()?; - let executors = get_all_executors(); - start_group!("Setting up the environment for all executors"); + let executors = get_executors_from_modes(modes); + start_group!("Setting up the environment"); for executor in executors { - match executor.support_level(&system_info) { - ExecutorSupport::Unsupported => { - info!( - "Skipping setup for the {} executor: not supported on {}", - executor.name(), - system_info.os - ); - } - ExecutorSupport::RequiresManualInstallation => { - info!( - "Skipping automatic setup for the {} executor on {}; install required tooling manually.", - executor.name(), - system_info.os - ); - } - ExecutorSupport::FullySupported => { - info!( - "Setting up the environment for the executor: {}", - executor.name() - ); - executor.setup(&system_info, setup_cache_dir).await?; - } - } + setup_executor(executor.as_ref(), &system_info, setup_cache_dir).await?; } info!("Environment setup completed"); end_group!(); Ok(()) } -pub fn status() -> Result<()> { +/// Set up a single executor based on its support level on the current system. +/// +/// Unsupported executors or executors that require manual installation are +/// skipped, not treated as fatal. +async fn setup_executor( + executor: &dyn Executor, + system_info: &SystemInfo, + setup_cache_dir: Option<&Path>, +) -> Result<()> { + match executor.support_level(system_info) { + ExecutorSupport::Unsupported => { + info!( + "Skipping setup for the {} executor: not supported on {}", + executor.name(), + system_info.os + ); + } + ExecutorSupport::RequiresManualInstallation => { + info!( + "Skipping automatic setup for the {} executor on {}; install required tooling manually.", + executor.name(), + system_info.os + ); + } + ExecutorSupport::FullySupported => { + info!( + "Setting up the environment for the executor: {}", + executor.name() + ); + executor.setup(system_info, setup_cache_dir).await?; + } + } + Ok(()) +} + +pub fn status(modes: &[RunnerMode]) -> Result<()> { let system_info = SystemInfo::new()?; info!("{}", style("Tools").bold()); - for executor in get_all_executors() { + for executor in get_executors_from_modes(modes) { // Don't probe for tooling that can't be used on this OS anyway. if executor.support_level(&system_info) == ExecutorSupport::Unsupported { continue; diff --git a/src/cli/status.rs b/src/cli/status.rs index c43505e4..fc9d055b 100644 --- a/src/cli/status.rs +++ b/src/cli/status.rs @@ -23,7 +23,7 @@ pub async fn run(api_client: &CodSpeedAPIClient, config: &CodSpeedConfig) -> Res info!(""); // Setup/tools status - super::setup::status()?; + super::setup::status(&[])?; info!(""); // System info