diff --git a/constants/src/lib.rs b/constants/src/lib.rs index ddd7c0a7..5d9f7661 100644 --- a/constants/src/lib.rs +++ b/constants/src/lib.rs @@ -126,6 +126,7 @@ pub const ENVS_TO_GET: &[&str] = &[ "CIRCLE_PR_NUMBER", "CIRCLE_PR_REPONAME", "CIRCLE_PULL_REQUEST", + "CIRCLE_PULL_REQUESTS", "CIRCLE_PR_USERNAME", "CIRCLE_REPOSITORY_URL", "CIRCLE_SHA1", diff --git a/context/src/env/parser.rs b/context/src/env/parser.rs index e85ff91b..82a720b4 100644 --- a/context/src/env/parser.rs +++ b/context/src/env/parser.rs @@ -512,7 +512,19 @@ impl<'a> CIInfoParser<'a> { _ => build_url, }; self.ci_info.branch = self.get_env_var("CIRCLE_BRANCH"); - self.ci_info.pr_number = self.parse_pr_number(self.get_env_var("CIRCLE_PR_NUMBER")); + // CIRCLE_PR_NUMBER is only set on forks + // https://circleci.com/docs/reference/variables/#built-in-environment-variables + self.ci_info.pr_number = self + .parse_pr_number(self.get_env_var("CIRCLE_PR_NUMBER")) + .or_else(|| { + self.get_env_var("CIRCLE_PULL_REQUEST") + .and_then(|pull_request_url| { + pull_request_url + .rsplit('/') + .next() + .and_then(|pr_number| pr_number.parse::().ok()) + }) + }); self.ci_info.actor = self.get_env_var("CIRCLE_USERNAME"); self.ci_info.workflow = self.get_env_var("CIRCLE_WORKFLOW_ID"); diff --git a/context/tests/env.rs b/context/tests/env.rs index f3e3bbf4..98c75872 100644 --- a/context/tests/env.rs +++ b/context/tests/env.rs @@ -1440,6 +1440,55 @@ fn test_circleci_pr() { ); } +#[test] +fn test_circleci_pull_request_url_fallback() { + let branch = String::from("feature/add-feature"); + let build_url = String::from("https://circleci.com/gh/my-org/my-repo/456"); + let workflow_id = String::from("workflow-def-456"); + let job_name = String::from("build-and-test"); + let username = String::from("janedoe"); + let pr_number = 26558; + let pull_request_url = format!("https://github.com/my-org/my-repo/pull/{pr_number}"); + + let env_vars = EnvVars::from_iter(vec![ + (String::from("CIRCLECI"), String::from("true")), + (String::from("CIRCLE_BRANCH"), String::from(&branch)), + (String::from("CIRCLE_BUILD_URL"), String::from(&build_url)), + ( + String::from("CIRCLE_WORKFLOW_ID"), + String::from(&workflow_id), + ), + (String::from("CIRCLE_JOB"), String::from(&job_name)), + (String::from("CIRCLE_USERNAME"), String::from(&username)), + (String::from("CIRCLE_PULL_REQUEST"), pull_request_url), + ]); + + let mut env_parser = EnvParser::new(); + env_parser.parse(&env_vars, &[], None); + + let ci_info = env_parser.into_ci_info_parser().unwrap().info_ci_info(); + + pretty_assertions::assert_eq!( + ci_info, + CIInfo { + platform: CIPlatform::CircleCI, + job_url: Some(build_url), + branch: Some(branch), + branch_class: Some(BranchClass::PullRequest), + pr_number: Some(pr_number), + actor: Some(username), + committer_name: None, + committer_email: None, + author_name: None, + author_email: None, + commit_message: None, + title: None, + workflow: Some(workflow_id), + job: Some(job_name), + } + ); +} + #[test] fn test_circleci_stable_branch() { let branch = String::from("main");