From 0b33b9453e3344483642432eefb830f1891073a6 Mon Sep 17 00:00:00 2001 From: Julien Delange Date: Mon, 6 May 2024 18:51:33 -0400 Subject: [PATCH] handle gitlab pipeline --- .../bins/src/bin/datadog-static-analyzer.rs | 2 +- crates/cli/src/constants.rs | 3 ++ crates/cli/src/git_utils.rs | 47 +++++++++++++++++++ crates/cli/src/lib.rs | 1 + crates/cli/src/model/cli_configuration.rs | 30 +++++------- 5 files changed, 65 insertions(+), 18 deletions(-) create mode 100644 crates/cli/src/git_utils.rs diff --git a/crates/bins/src/bin/datadog-static-analyzer.rs b/crates/bins/src/bin/datadog-static-analyzer.rs index dd4f74ef..6d2f2633 100644 --- a/crates/bins/src/bin/datadog-static-analyzer.rs +++ b/crates/bins/src/bin/datadog-static-analyzer.rs @@ -485,7 +485,7 @@ fn main() -> Result<()> { // check if we do a diff-aware scan let diff_aware_parameters: Option = if diff_aware_requested { - match configuration.generate_diff_aware_request_data() { + match configuration.generate_diff_aware_request_data(configuration.use_debug) { Ok(params) => { if configuration.use_debug { println!("Diff-aware request with repository url {}, sha {}, branch {}, config hash {}", params.repository_url, params.sha, params.branch, params.config_hash); diff --git a/crates/cli/src/constants.rs b/crates/cli/src/constants.rs index 4e069c2d..d4684d6d 100644 --- a/crates/cli/src/constants.rs +++ b/crates/cli/src/constants.rs @@ -8,3 +8,6 @@ pub static SARIF_PROPERTY_DATADOG_FINGERPRINT: &str = "DATADOG_FINGERPRINT"; pub static SARIF_PROPERTY_SHA: &str = "SHA"; pub static DEFAULT_MAX_FILE_SIZE_KB: u64 = 200; +// See https://docs.gitlab.com/ee/ci/variables/predefined_variables.html +pub static GITLAB_ENVIRONMENT_VARIABLE_COMMIT_BRANCH: &str = "CI_COMMIT_BRANCH"; +pub static GIT_HEAD: &str = "HEAD"; diff --git a/crates/cli/src/git_utils.rs b/crates/cli/src/git_utils.rs new file mode 100644 index 00000000..3792a6aa --- /dev/null +++ b/crates/cli/src/git_utils.rs @@ -0,0 +1,47 @@ +use crate::constants::{GITLAB_ENVIRONMENT_VARIABLE_COMMIT_BRANCH, GIT_HEAD}; +use git2::Repository; +use std::env; + +/// Try to get the branch running. We first try to get the branch from the repository. When +/// it fails, we attempt to get the branch from the CI provider when the analyzer +/// runs in a CI provider. +/// +/// Some CI providers (like Gitlab) runs their CI on a detached HEAD (see +/// [this thread for example](https://forum.gitlab.com/t/why-i-cant-get-the-branch-name/72462). +/// +/// When we do not find the branch, we attempt to find it from the CI provider using variables. +pub fn get_branch(repository: &Repository, use_debug: bool) -> Option { + // First, let's try to get it from the repository. + let head_try = repository.head(); + if let Ok(head) = head_try { + let branch_from_shorthand = head.shorthand(); + + if let Some(branch) = branch_from_shorthand { + if branch == GIT_HEAD && use_debug { + eprintln!("branch is HEAD, not using it for diff-aware"); + } + + if branch != GIT_HEAD { + if use_debug { + eprintln!("Getting branch {} from Git repo", branch) + } + + return Some(branch.to_string()); + } + } + } + + // Let's try to get it from Gitlab. + let branch_from_gitlab_pipeline_try = env::var(GITLAB_ENVIRONMENT_VARIABLE_COMMIT_BRANCH); + if let Ok(branch_from_gitlab_pipeline) = branch_from_gitlab_pipeline_try { + if use_debug { + eprintln!( + "getting branch {} from Gitlab pipelines", + branch_from_gitlab_pipeline + ); + } + return Some(branch_from_gitlab_pipeline); + } + + None +} diff --git a/crates/cli/src/lib.rs b/crates/cli/src/lib.rs index e70ccdee..af2cbc56 100644 --- a/crates/cli/src/lib.rs +++ b/crates/cli/src/lib.rs @@ -3,6 +3,7 @@ pub mod constants; pub mod csv; pub mod datadog_utils; pub mod file_utils; +mod git_utils; pub mod model; pub mod rule_utils; pub mod sarif; diff --git a/crates/cli/src/model/cli_configuration.rs b/crates/cli/src/model/cli_configuration.rs index 78707b5a..ccd99886 100644 --- a/crates/cli/src/model/cli_configuration.rs +++ b/crates/cli/src/model/cli_configuration.rs @@ -2,6 +2,7 @@ use anyhow::anyhow; use git2::Repository; use sha2::{Digest, Sha256}; +use crate::git_utils::get_branch; use kernel::config_file::ArgumentProvider; use kernel::model::common::OutputFormat; use kernel::model::config_file::PathConfig; @@ -71,7 +72,10 @@ impl CliConfiguration { /// the repository from the directory, get the repository information to get /// diff-aware data. If we are not in a repository or cannot get the data /// we need, we return an error. - pub fn generate_diff_aware_request_data(&self) -> anyhow::Result { + pub fn generate_diff_aware_request_data( + &self, + use_debug: bool, + ) -> anyhow::Result { let config_hash = self.generate_diff_aware_digest(); let repository_opt = Repository::init(&self.source_directory); @@ -93,22 +97,14 @@ impl CliConfiguration { // let's get the latest commit let head = repository.head()?; let oid = head.target(); - let head_name = head.shorthand(); - match (oid, head_name) { - (Some(o), Some(h)) => { - if h == "HEAD" { - return Err(anyhow!( - "branch is HEAD, cannot generate diff-aware scanning" - )); - } - - Ok(DiffAwareRequestArguments { - repository_url, - config_hash, - sha: o.to_string(), - branch: h.to_string(), - }) - } + let branch_option = get_branch(&repository, use_debug); + match (oid, branch_option) { + (Some(o), Some(b)) => Ok(DiffAwareRequestArguments { + repository_url, + config_hash, + sha: o.to_string(), + branch: b, + }), _ => { if self.use_debug { println!(