Skip to content

Commit d6149ba

Browse files
feat: add flags to specify repository from CLI
1 parent 7b3a19c commit d6149ba

7 files changed

Lines changed: 200 additions & 72 deletions

File tree

src/run/config.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use crate::prelude::*;
22
use crate::run::instruments::Instruments;
33
use url::Url;
44

5+
use crate::run::run_environment::RepositoryProvider;
56
use crate::run::RunArgs;
67

78
use super::RunnerMode;
@@ -10,6 +11,7 @@ use super::RunnerMode;
1011
pub struct Config {
1112
pub upload_url: Url,
1213
pub token: Option<String>,
14+
pub repository_override: Option<RepositoryOverride>,
1315
pub working_directory: Option<String>,
1416
pub command: String,
1517

@@ -20,6 +22,13 @@ pub struct Config {
2022
pub skip_setup: bool,
2123
}
2224

25+
#[derive(Debug, PartialEq, Clone)]
26+
pub struct RepositoryOverride {
27+
pub owner: String,
28+
pub repository: String,
29+
pub repository_provider: RepositoryProvider,
30+
}
31+
2332
impl Config {
2433
pub fn set_token(&mut self, token: Option<String>) {
2534
self.token = token;
@@ -33,6 +42,7 @@ impl Config {
3342
Self {
3443
upload_url: Url::parse(DEFAULT_UPLOAD_URL).unwrap(),
3544
token: None,
45+
repository_override: None,
3646
working_directory: None,
3747
command: "".into(),
3848
mode: RunnerMode::Instrumentation,
@@ -52,9 +62,22 @@ impl TryFrom<RunArgs> for Config {
5262
let raw_upload_url = args.upload_url.unwrap_or_else(|| DEFAULT_UPLOAD_URL.into());
5363
let upload_url = Url::parse(&raw_upload_url)
5464
.map_err(|e| anyhow!("Invalid upload URL: {}, {}", raw_upload_url, e))?;
65+
5566
Ok(Self {
5667
upload_url,
5768
token: args.token,
69+
repository_override: args
70+
.repository
71+
.map(|respository_and_owner| -> Result<RepositoryOverride> {
72+
let (owner, repository) =
73+
extract_owner_and_repository_from_arg(&respository_and_owner)?;
74+
Ok(RepositoryOverride {
75+
owner,
76+
repository,
77+
repository_provider: args.provider.unwrap_or_default(),
78+
})
79+
})
80+
.transpose()?,
5881
working_directory: args.working_directory,
5982
mode: args.mode,
6083
instruments,
@@ -65,6 +88,13 @@ impl TryFrom<RunArgs> for Config {
6588
}
6689
}
6790

91+
fn extract_owner_and_repository_from_arg(owner_and_repository: &str) -> Result<(String, String)> {
92+
let (owner, repository) = owner_and_repository
93+
.split_once('/')
94+
.context("Invalid owner/repository format")?;
95+
Ok((owner.to_string(), repository.to_string()))
96+
}
97+
6898
#[cfg(test)]
6999
mod tests {
70100
use crate::run::instruments::MongoDBConfig;
@@ -76,6 +106,8 @@ mod tests {
76106
let config = Config::try_from(RunArgs {
77107
upload_url: None,
78108
token: None,
109+
repository: None,
110+
provider: None,
79111
working_directory: None,
80112
mode: RunnerMode::Instrumentation,
81113
instruments: vec![],
@@ -87,6 +119,7 @@ mod tests {
87119
.unwrap();
88120
assert_eq!(config.upload_url, Url::parse(DEFAULT_UPLOAD_URL).unwrap());
89121
assert_eq!(config.token, None);
122+
assert_eq!(config.repository_override, None);
90123
assert_eq!(config.working_directory, None);
91124
assert_eq!(config.instruments, Instruments { mongodb: None });
92125
assert!(!config.skip_upload);
@@ -99,6 +132,8 @@ mod tests {
99132
let config = Config::try_from(RunArgs {
100133
upload_url: Some("https://example.com/upload".into()),
101134
token: Some("token".into()),
135+
repository: Some("owner/repo".into()),
136+
provider: Some(RepositoryProvider::GitLab),
102137
working_directory: Some("/tmp".into()),
103138
mode: RunnerMode::Instrumentation,
104139
instruments: vec!["mongodb".into()],
@@ -114,6 +149,14 @@ mod tests {
114149
Url::parse("https://example.com/upload").unwrap()
115150
);
116151
assert_eq!(config.token, Some("token".into()));
152+
assert_eq!(
153+
config.repository_override,
154+
Some(RepositoryOverride {
155+
owner: "owner".into(),
156+
repository: "repo".into(),
157+
repository_provider: RepositoryProvider::GitLab,
158+
})
159+
);
117160
assert_eq!(config.working_directory, Some("/tmp".into()));
118161
assert_eq!(
119162
config.instruments,
@@ -127,4 +170,18 @@ mod tests {
127170
assert!(config.skip_setup);
128171
assert_eq!(config.command, "cargo codspeed bench");
129172
}
173+
174+
#[test]
175+
fn test_extract_owner_and_repository_from_arg() {
176+
let owner_and_repository = "CodSpeedHQ/runner";
177+
let (owner, repository) =
178+
extract_owner_and_repository_from_arg(owner_and_repository).unwrap();
179+
assert_eq!(owner, "CodSpeedHQ");
180+
assert_eq!(repository, "runner");
181+
182+
let owner_and_repository = "CodSpeedHQ_runner";
183+
184+
let result = extract_owner_and_repository_from_arg(owner_and_repository);
185+
assert!(result.is_err());
186+
}
130187
}

src/run/mod.rs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::VERSION;
66
use check_system::SystemInfo;
77
use clap::{Args, ValueEnum};
88
use instruments::mongo_tracer::{install_mongodb_tracer, MongoTracer};
9-
use run_environment::interfaces::RunEnvironment;
9+
use run_environment::interfaces::{RepositoryProvider, RunEnvironment};
1010
use runner::get_run_data;
1111
use serde::Serialize;
1212

@@ -55,6 +55,19 @@ pub struct RunArgs {
5555
#[arg(long, env = "CODSPEED_TOKEN")]
5656
pub token: Option<String>,
5757

58+
/// The repository the benchmark is associated with, under the format `owner/repo`.
59+
#[arg(short, long, env = "CODSPEED_REPOSITORY")]
60+
pub repository: Option<String>,
61+
62+
/// The repository provider to use in case --repository is used. Defaults to github
63+
#[arg(
64+
long,
65+
env = "CODSPEED_PROVIDER",
66+
requires = "repository",
67+
ignore_case = true
68+
)]
69+
pub provider: Option<RepositoryProvider>,
70+
5871
/// The directory where the command will be executed.
5972
#[arg(long)]
6073
pub working_directory: Option<String>,
@@ -98,6 +111,8 @@ impl RunArgs {
98111
Self {
99112
upload_url: None,
100113
token: None,
114+
repository: None,
115+
provider: None,
101116
working_directory: None,
102117
mode: RunnerMode::Instrumentation,
103118
instruments: vec![],
@@ -186,3 +201,17 @@ pub async fn run(args: RunArgs, api_client: &CodSpeedAPIClient) -> Result<()> {
186201

187202
Ok(())
188203
}
204+
205+
// We have to implement this manually, because deriving the trait makes the CLI values `git-hub`
206+
// and `git-lab`
207+
impl clap::ValueEnum for RepositoryProvider {
208+
fn value_variants<'a>() -> &'a [Self] {
209+
&[Self::GitLab, Self::GitHub]
210+
}
211+
fn to_possible_value<'a>(&self) -> ::std::option::Option<clap::builder::PossibleValue> {
212+
match self {
213+
Self::GitLab => Some(clap::builder::PossibleValue::new("gitlab").aliases(["gl"])),
214+
Self::GitHub => Some(clap::builder::PossibleValue::new("github").aliases(["gh"])),
215+
}
216+
}
217+
}

src/run/run_environment/buildkite/provider.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ impl TryFrom<&Config> for BuildkiteProvider {
6161
bail!("Token authentication is required for Buildkite");
6262
}
6363

64+
if config.repository_override.is_some() {
65+
bail!("Specifying owner and repository from CLI is not supported for Buildkite");
66+
}
67+
6468
let is_pr = get_pr_number()?.is_some();
6569
let repository_url = get_env_variable("BUILDKITE_REPO")?;
6670
let GitRemote {

src/run/run_environment/github_actions/provider.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,10 @@ lazy_static! {
4747

4848
impl TryFrom<&Config> for GitHubActionsProvider {
4949
type Error = Error;
50-
fn try_from(_config: &Config) -> Result<Self> {
50+
fn try_from(config: &Config) -> Result<Self> {
51+
if config.repository_override.is_some() {
52+
bail!("Specifying owner and repository from CLI is not supported for Github Actions");
53+
}
5154
let (owner, repository) = Self::get_owner_and_repository()?;
5255
let ref_ = get_env_variable("GITHUB_REF")?;
5356
let is_pr = PR_REF_REGEX.is_match(&ref_);

src/run/run_environment/gitlab_ci/provider.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@ pub struct GitLabCIProvider {
2828

2929
impl TryFrom<&Config> for GitLabCIProvider {
3030
type Error = Error;
31-
fn try_from(_config: &Config) -> Result<Self> {
31+
fn try_from(config: &Config) -> Result<Self> {
32+
if config.repository_override.is_some() {
33+
bail!("Specifying owner and repository from CLI is not supported for GitLab CI");
34+
}
3235
let owner = get_env_variable("CI_PROJECT_NAMESPACE")?;
3336
let repository = get_env_variable("CI_PROJECT_NAME")?;
3437

src/run/run_environment/interfaces.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@ use serde::{Deserialize, Serialize};
22
use serde_json::Value;
33
use std::collections::BTreeMap;
44

5-
#[derive(Deserialize, Serialize, Debug, Clone, PartialEq)]
5+
#[derive(Deserialize, Serialize, Debug, Clone, PartialEq, Default)]
66
#[serde(rename_all = "UPPERCASE")]
77
pub enum RepositoryProvider {
8-
GitLab,
8+
#[default]
99
GitHub,
10+
GitLab,
1011
}
1112

1213
#[derive(Deserialize, Serialize, Debug, Clone, PartialEq)]

0 commit comments

Comments
 (0)