Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 13 additions & 54 deletions src/run/ci_provider/buildkite/provider.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
use std::env;

use lazy_static::lazy_static;
use regex::Regex;
use simplelog::SharedLogger;

use crate::prelude::*;
use crate::run::helpers::{parse_git_remote, GitRemote};
use crate::run::{
ci_provider::{
interfaces::{CIProviderMetadata, RepositoryProvider, RunEvent},
Expand All @@ -27,16 +26,6 @@ pub struct BuildkiteProvider {
repository_root_path: String,
}

lazy_static! {
static ref GITHUB_URL_REGEX: Regex = Regex::new(
r"(?x)
(?:https://github.com/|git@github.com:)
(?P<owner>[^/]+)/(?P<repository>[^/.]+)\.git
"
)
.expect("Failed to compile GitHub URL regex");
}

pub fn get_pr_number() -> Result<Option<u64>> {
Ok(get_env_variable("BUILDKITE_PULL_REQUEST")?.parse().ok())
}
Expand Down Expand Up @@ -64,24 +53,6 @@ pub fn get_ref() -> Result<String> {
}
}

pub fn get_owner_and_repository() -> Result<(String, String)> {
let repository_url = get_env_variable("BUILDKITE_REPO")?;
let captures = GITHUB_URL_REGEX
.captures(&repository_url)
.context("Failed to parse the GitHub repository URL")?;

let owner = captures
.name("owner")
.context("Failed to parse the GitHub repository URL")?
.as_str();
let repository = captures
.name("repository")
.context("Failed to parse the GitHub repository URL")?
.as_str();

Ok((owner.into(), repository.into()))
}

impl TryFrom<&Config> for BuildkiteProvider {
type Error = Error;
fn try_from(config: &Config) -> Result<Self> {
Expand All @@ -90,7 +61,18 @@ impl TryFrom<&Config> for BuildkiteProvider {
}

let is_pr = get_pr_number()?.is_some();
let (owner, repository) = get_owner_and_repository()?;
let repository_url = get_env_variable("BUILDKITE_REPO")?;
let GitRemote {
owner,
repository,
domain,
} = parse_git_remote(&repository_url)?;

if domain != "github.com" {
bail!(
"Only GitHub repositories are supported by CodSpeed BuildKite integration for now."
);
}

let repository_root_path = match find_repository_root(&std::env::current_dir()?) {
Some(mut path) => {
Expand Down Expand Up @@ -181,29 +163,6 @@ mod tests {
});
}

#[test]
fn test_get_owner_and_repository() {
with_var(
"BUILDKITE_REPO",
Some("https://github.com/my-org/adrien-python-test.git"),
|| {
let (owner, repository) = get_owner_and_repository().unwrap();
assert_eq!(owner, "my-org");
assert_eq!(repository, "adrien-python-test");
},
);

with_var(
"BUILDKITE_REPO",
Some("git@github.com:my-org/adrien-python-test.git"),
|| {
let (owner, repository) = get_owner_and_repository().unwrap();
assert_eq!(owner, "my-org");
assert_eq!(repository, "adrien-python-test");
},
);
}

#[test]
fn test_try_from_push_main() {
with_vars(
Expand Down
33 changes: 12 additions & 21 deletions src/run/ci_provider/local/provider.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use git2::Repository;
use lazy_static::lazy_static;
use simplelog::SharedLogger;

use crate::local_logger::get_local_logger;
use crate::prelude::*;
use crate::run::helpers::{parse_git_remote, GitRemote};
use crate::run::{
ci_provider::{
interfaces::{CIProviderMetadata, RepositoryProvider, RunEvent},
Expand All @@ -27,31 +27,22 @@ pub struct LocalProvider {

impl LocalProvider {}

lazy_static! {
static ref REMOTE_REGEX: regex::Regex = regex::Regex::new(
r"(?P<domain>[^/@\.]+)\.\w+[:/](?P<owner>[^/]+)/(?P<repository>[^/]+)\.git"
)
.unwrap();
}

fn extract_provider_owner_and_repository_from_remote_url(
remote_url: &str,
) -> Result<(RepositoryProvider, String, String)> {
let captures = REMOTE_REGEX.captures(remote_url).ok_or_else(|| {
anyhow!(
"Could not extract owner and repository from remote url: {}",
remote_url
)
})?;

let domain = captures.name("domain").unwrap().as_str();
let repository_provider = serde_json::from_str(&format!("\"{}\"", domain.to_uppercase()))
.context(format!(
let GitRemote {
domain,
owner,
repository,
} = parse_git_remote(remote_url)?;
let repository_provider = match domain.as_str() {
"github.com" => RepositoryProvider::GitHub,
"gitlab.com" => RepositoryProvider::GitLab,
domain => bail!(
"Repository provider {} is not supported by CodSpeed",
domain
))?;
let owner = captures.name("owner").unwrap().as_str();
let repository = captures.name("repository").unwrap().as_str();
),
};

Ok((
repository_provider,
Expand Down
2 changes: 2 additions & 0 deletions src/run/helpers/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
mod find_repository_root;
mod get_env_var;
mod parse_git_remote;

pub use find_repository_root::find_repository_root;
pub use get_env_var::get_env_variable;
pub use parse_git_remote::*;
93 changes: 93 additions & 0 deletions src/run/helpers/parse_git_remote.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
use anyhow::{anyhow, Result};
use lazy_static::lazy_static;

lazy_static! {
static ref REMOTE_REGEX: regex::Regex = regex::Regex::new(
r"(?P<domain>[^/@\.]+\.\w+)[:/](?P<owner>[^/]+)/(?P<repository>[^/]+?)(\.git)?$"
)
.unwrap();
}

#[derive(Debug)]
pub struct GitRemote {
pub domain: String,
pub owner: String,
pub repository: String,
}

pub fn parse_git_remote(remote: &str) -> Result<GitRemote> {
let captures = REMOTE_REGEX.captures(remote).ok_or_else(|| {
anyhow!(
"Could not extract owner and repository from remote url: {}",
remote
)
})?;

let domain = captures.name("domain").unwrap().as_str();
let owner = captures.name("owner").unwrap().as_str();
let repository = captures.name("repository").unwrap().as_str();

Ok(GitRemote {
domain: domain.to_string(),
owner: owner.to_string(),
repository: repository.to_string(),
})
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_parse_git_remote() {
let remote = "git@github.com:CodSpeedHQ/runner.git";
let git_remote = parse_git_remote(remote).unwrap();
insta::assert_debug_snapshot!(git_remote, @r###"
GitRemote {
domain: "github.com",
owner: "CodSpeedHQ",
repository: "runner",
}
"###);

let remote = "https://github.com/CodSpeedHQ/runner.git";
let git_remote = parse_git_remote(remote).unwrap();
insta::assert_debug_snapshot!(git_remote, @r###"
GitRemote {
domain: "github.com",
owner: "CodSpeedHQ",
repository: "runner",
}
"###);

let remote = "https://github.com/CodSpeedHQ/runner";
let git_remote = parse_git_remote(remote).unwrap();
insta::assert_debug_snapshot!(git_remote, @r###"
GitRemote {
domain: "github.com",
owner: "CodSpeedHQ",
repository: "runner",
}
"###);

let remote = "git@gitlab.com:codspeed/runner.git";
let git_remote = parse_git_remote(remote).unwrap();
insta::assert_debug_snapshot!(git_remote, @r###"
GitRemote {
domain: "gitlab.com",
owner: "codspeed",
repository: "runner",
}
"###);

let remote = "https://gitlab.com/codspeed/runner.git";
let git_remote = parse_git_remote(remote).unwrap();
insta::assert_debug_snapshot!(git_remote, @r###"
GitRemote {
domain: "gitlab.com",
owner: "codspeed",
repository: "runner",
}
"###);
}
}
Loading