From 4c9ed7b8c93043f2ed22dcff5c8838f73fd4f333 Mon Sep 17 00:00:00 2001 From: Guillaume Lagrange Date: Fri, 31 Oct 2025 16:55:39 +0100 Subject: [PATCH] feat: add --config-name argument to allow multiple configs --- src/app.rs | 11 +++++++++-- src/auth.rs | 14 +++++++++----- src/config.rs | 36 +++++++++++++++++++++--------------- 3 files changed, 39 insertions(+), 22 deletions(-) diff --git a/src/app.rs b/src/app.rs index f72d9d91..fa289ab1 100644 --- a/src/app.rs +++ b/src/app.rs @@ -40,6 +40,12 @@ pub struct Cli { #[arg(long, env = "CODSPEED_OAUTH_TOKEN", global = true, hide = true)] pub oauth_token: Option, + /// The configuration name to use + /// If provided, the configuration will be loaded from ~/.config/codspeed/{config-name}.yaml + /// Otherwise, loads from ~/.config/codspeed/config.yaml + #[arg(long, env = "CODSPEED_CONFIG_NAME", global = true)] + pub config_name: Option, + /// The directory to use for caching installed tools /// The runner will restore cached tools from this directory before installing them. /// After successful installation, the runner will cache the installed tools to this directory. @@ -63,7 +69,8 @@ enum Commands { pub async fn run() -> Result<()> { let cli = Cli::parse(); - let codspeed_config = CodSpeedConfig::load_with_override(cli.oauth_token.as_deref())?; + let codspeed_config = + CodSpeedConfig::load_with_override(cli.config_name.as_deref(), cli.oauth_token.as_deref())?; let api_client = CodSpeedAPIClient::try_from((&cli, &codspeed_config))?; // In the context of the CI, it is likely that a ~ made its way here without being expanded by the shell let setup_cache_dir = cli @@ -83,7 +90,7 @@ pub async fn run() -> Result<()> { Commands::Run(args) => { run::run(args, &api_client, &codspeed_config, setup_cache_dir).await? } - Commands::Auth(args) => auth::run(args, &api_client).await?, + Commands::Auth(args) => auth::run(args, &api_client, cli.config_name.as_deref()).await?, Commands::Setup => setup::setup(setup_cache_dir).await?, } Ok(()) diff --git a/src/auth.rs b/src/auth.rs index deee6223..6998a906 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -17,16 +17,20 @@ enum AuthCommands { Login, } -pub async fn run(args: AuthArgs, api_client: &CodSpeedAPIClient) -> Result<()> { +pub async fn run( + args: AuthArgs, + api_client: &CodSpeedAPIClient, + config_name: Option<&str>, +) -> Result<()> { match args.command { - AuthCommands::Login => login(api_client).await?, + AuthCommands::Login => login(api_client, config_name).await?, } Ok(()) } const LOGIN_SESSION_MAX_DURATION: Duration = Duration::from_secs(60 * 5); // 5 minutes -async fn login(api_client: &CodSpeedAPIClient) -> Result<()> { +async fn login(api_client: &CodSpeedAPIClient, config_name: Option<&str>) -> Result<()> { debug!("Login to CodSpeed"); start_group!("Creating login session"); let login_session_payload = api_client.create_login_session().await?; @@ -67,9 +71,9 @@ async fn login(api_client: &CodSpeedAPIClient) -> Result<()> { } end_group!(); - let mut config = CodSpeedConfig::load()?; + let mut config = CodSpeedConfig::load_with_override(config_name, None)?; config.auth.token = Some(token); - config.persist()?; + config.persist(config_name)?; debug!("Token saved to configuration file"); info!("Login successful, your are now authenticated on CodSpeed"); diff --git a/src/config.rs b/src/config.rs index 729c5915..c8481b09 100644 --- a/src/config.rs +++ b/src/config.rs @@ -16,7 +16,10 @@ nest! { /// Get the path to the configuration file, following the XDG Base Directory Specification /// at https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html -fn get_configuration_file_path() -> PathBuf { +/// +/// If config_name is None, returns ~/.config/codspeed/config.yaml (default) +/// If config_name is Some, returns ~/.config/codspeed/{config_name}.yaml +fn get_configuration_file_path(config_name: Option<&str>) -> PathBuf { let config_dir = env::var("XDG_CONFIG_HOME") .map(PathBuf::from) .unwrap_or_else(|_| { @@ -24,7 +27,11 @@ fn get_configuration_file_path() -> PathBuf { PathBuf::from(home).join(".config") }); let config_dir = config_dir.join("codspeed"); - config_dir.join("config.yaml") + + match config_name { + Some(name) => config_dir.join(format!("{name}.yaml")), + None => config_dir.join("config.yaml"), + } } impl Default for CodSpeedConfig { @@ -40,15 +47,19 @@ impl CodSpeedConfig { /// /// If oauth_token_override is provided, the token from the loaded configuration will be /// ignored, and the override will be used instead - pub fn load_with_override(oauth_token_override: Option<&str>) -> Result { - let config_path = get_configuration_file_path(); + pub fn load_with_override( + config_name: Option<&str>, + oauth_token_override: Option<&str>, + ) -> Result { + let config_path = get_configuration_file_path(config_name); let mut config = match fs::read(&config_path) { Ok(config_str) => { - let config = serde_yaml::from_slice(&config_str).context(format!( - "Failed to parse CodSpeed config at {}", - config_path.display() - ))?; + let config: CodSpeedConfig = + serde_yaml::from_slice(&config_str).context(format!( + "Failed to parse CodSpeed config at {}", + config_path.display() + ))?; debug!("Config loaded from {}", config_path.display()); config } @@ -66,14 +77,9 @@ impl CodSpeedConfig { Ok(config) } - /// Load the configuration. If it does not exist, return a default configuration. - pub fn load() -> Result { - Self::load_with_override(None) - } - /// Persist changes to the configuration - pub fn persist(&self) -> Result<()> { - let config_path = get_configuration_file_path(); + pub fn persist(&self, config_name: Option<&str>) -> Result<()> { + let config_path = get_configuration_file_path(config_name); fs::create_dir_all(config_path.parent().unwrap())?; let config_str = serde_yaml::to_string(self)?;