Skip to content

Commit f156bbf

Browse files
circleci env parsing (#982)
* add tests * Update context/src/env/parser.rs Co-authored-by: Dylan Frankland <[email protected]> Signed-off-by: Matt Matheson <[email protected]> * fix the url encoding of the step uuid * support circleci env parsing * cleanup --------- Signed-off-by: Matt Matheson <[email protected]> Co-authored-by: Dylan Frankland <[email protected]>
1 parent a57e35e commit f156bbf

File tree

2 files changed

+199
-2
lines changed

2 files changed

+199
-2
lines changed

context/src/env/parser.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,9 +226,9 @@ impl<'a> CIInfoParser<'a> {
226226
CIPlatform::GitLabCI => self.parse_gitlab_ci(),
227227
CIPlatform::Drone => self.parse_drone(),
228228
CIPlatform::BitbucketPipelines => self.parse_bitbucket_pipelines(),
229+
CIPlatform::CircleCI => self.parse_circleci(),
229230
CIPlatform::Custom => self.parse_custom_info(),
230-
CIPlatform::CircleCI
231-
| CIPlatform::TravisCI
231+
CIPlatform::TravisCI
232232
| CIPlatform::Webappio
233233
| CIPlatform::AWSCodeBuild
234234
| CIPlatform::AzurePipelines
@@ -466,6 +466,16 @@ impl<'a> CIInfoParser<'a> {
466466
// via apply_repo_overrides(), or users can set them via CUSTOM env vars.
467467
}
468468

469+
fn parse_circleci(&mut self) {
470+
self.ci_info.job_url = self.get_env_var("CIRCLE_BUILD_URL");
471+
self.ci_info.branch = self.get_env_var("CIRCLE_BRANCH");
472+
self.ci_info.pr_number = Self::parse_pr_number(self.get_env_var("CIRCLE_PR_NUMBER"));
473+
self.ci_info.actor = self.get_env_var("CIRCLE_USERNAME");
474+
475+
self.ci_info.workflow = self.get_env_var("CIRCLE_WORKFLOW_ID");
476+
self.ci_info.job = self.get_env_var("CIRCLE_JOB");
477+
}
478+
469479
fn get_env_var<T: AsRef<str>>(&self, env_var: T) -> Option<String> {
470480
self.env_vars
471481
.get(env_var.as_ref())

context/tests/env.rs

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1260,6 +1260,193 @@ fn test_bitbucket_missing_job_url_vars() {
12601260
);
12611261
}
12621262

1263+
#[test]
1264+
fn test_simple_circleci() {
1265+
let branch = String::from("circleci-project-setup");
1266+
let build_url = String::from("https://circleci.com/gh/trunk-io/trunk2/6");
1267+
let workflow_id = String::from("5a984496-cf63-4f63-b315-5776a3186d4b");
1268+
let job_name = String::from("unit-tests");
1269+
let username = String::from("mmatheson");
1270+
1271+
let env_vars = EnvVars::from_iter(vec![
1272+
(String::from("CI"), String::from("true")),
1273+
(String::from("CIRCLECI"), String::from("true")),
1274+
(String::from("CIRCLE_JOB"), String::from(&job_name)),
1275+
(
1276+
String::from("CIRCLE_SHA1"),
1277+
String::from("fcddd4c25274e885fc6fd584b0d04290289b8e3e"),
1278+
),
1279+
(String::from("CIRCLE_BRANCH"), String::from(&branch)),
1280+
(String::from("CIRCLE_USERNAME"), String::from(&username)),
1281+
(String::from("CIRCLE_BUILD_NUM"), String::from("6")),
1282+
(String::from("CIRCLE_BUILD_URL"), String::from(&build_url)),
1283+
(
1284+
String::from("CIRCLE_WORKFLOW_ID"),
1285+
String::from(&workflow_id),
1286+
),
1287+
(
1288+
String::from("CIRCLE_REPOSITORY_URL"),
1289+
String::from("[email protected]:trunk-io/trunk2.git"),
1290+
),
1291+
(
1292+
String::from("CIRCLE_WORKFLOW_JOB_ID"),
1293+
String::from("8fa2fd0d-e60a-42ac-9be3-67255ba5badc"),
1294+
),
1295+
(
1296+
String::from("CIRCLE_PROJECT_REPONAME"),
1297+
String::from("trunk2"),
1298+
),
1299+
(
1300+
String::from("CIRCLE_PROJECT_USERNAME"),
1301+
String::from("trunk-io"),
1302+
),
1303+
]);
1304+
1305+
let mut env_parser = EnvParser::new();
1306+
env_parser.parse(&env_vars, &[], None);
1307+
1308+
let ci_info = env_parser.into_ci_info_parser().unwrap().info_ci_info();
1309+
1310+
pretty_assertions::assert_eq!(
1311+
ci_info,
1312+
CIInfo {
1313+
platform: CIPlatform::CircleCI,
1314+
job_url: Some(build_url),
1315+
branch: Some(branch),
1316+
branch_class: Some(BranchClass::None),
1317+
pr_number: None,
1318+
actor: Some(username),
1319+
committer_name: None,
1320+
committer_email: None,
1321+
author_name: None,
1322+
author_email: None,
1323+
commit_message: None,
1324+
title: None,
1325+
workflow: Some(workflow_id),
1326+
job: Some(job_name),
1327+
}
1328+
);
1329+
}
1330+
1331+
#[test]
1332+
fn test_circleci_pr() {
1333+
let branch = String::from("feature/add-feature");
1334+
let build_url = String::from("https://circleci.com/gh/my-org/my-repo/456");
1335+
let workflow_id = String::from("workflow-def-456");
1336+
let job_name = String::from("build-and-test");
1337+
let username = String::from("janedoe");
1338+
let pr_number = 42;
1339+
1340+
let env_vars = EnvVars::from_iter(vec![
1341+
(String::from("CIRCLECI"), String::from("true")),
1342+
(String::from("CIRCLE_BRANCH"), String::from(&branch)),
1343+
(String::from("CIRCLE_BUILD_URL"), String::from(&build_url)),
1344+
(
1345+
String::from("CIRCLE_WORKFLOW_ID"),
1346+
String::from(&workflow_id),
1347+
),
1348+
(String::from("CIRCLE_JOB"), String::from(&job_name)),
1349+
(String::from("CIRCLE_USERNAME"), String::from(&username)),
1350+
(String::from("CIRCLE_PR_NUMBER"), pr_number.to_string()),
1351+
]);
1352+
1353+
let mut env_parser = EnvParser::new();
1354+
env_parser.parse(&env_vars, &[], None);
1355+
1356+
let ci_info = env_parser.into_ci_info_parser().unwrap().info_ci_info();
1357+
1358+
pretty_assertions::assert_eq!(
1359+
ci_info,
1360+
CIInfo {
1361+
platform: CIPlatform::CircleCI,
1362+
job_url: Some(build_url),
1363+
branch: Some(branch),
1364+
branch_class: Some(BranchClass::PullRequest),
1365+
pr_number: Some(pr_number),
1366+
actor: Some(username),
1367+
committer_name: None,
1368+
committer_email: None,
1369+
author_name: None,
1370+
author_email: None,
1371+
commit_message: None,
1372+
title: None,
1373+
workflow: Some(workflow_id),
1374+
job: Some(job_name),
1375+
}
1376+
);
1377+
}
1378+
1379+
#[test]
1380+
fn test_circleci_stable_branch() {
1381+
let branch = String::from("main");
1382+
let build_url = String::from("https://circleci.com/gh/my-org/my-repo/789");
1383+
1384+
let env_vars = EnvVars::from_iter(vec![
1385+
(String::from("CIRCLECI"), String::from("true")),
1386+
(String::from("CIRCLE_BRANCH"), String::from(&branch)),
1387+
(String::from("CIRCLE_BUILD_URL"), String::from(&build_url)),
1388+
]);
1389+
1390+
let stable_branches: &[&str] = &["main", "master"];
1391+
1392+
let mut env_parser = EnvParser::new();
1393+
env_parser.parse(&env_vars, stable_branches, None);
1394+
1395+
let ci_info = env_parser.into_ci_info_parser().unwrap().info_ci_info();
1396+
1397+
pretty_assertions::assert_eq!(
1398+
ci_info,
1399+
CIInfo {
1400+
platform: CIPlatform::CircleCI,
1401+
job_url: Some(build_url),
1402+
branch: Some(branch),
1403+
branch_class: Some(BranchClass::ProtectedBranch),
1404+
pr_number: None,
1405+
actor: None,
1406+
committer_name: None,
1407+
committer_email: None,
1408+
author_name: None,
1409+
author_email: None,
1410+
commit_message: None,
1411+
title: None,
1412+
workflow: None,
1413+
job: None,
1414+
}
1415+
);
1416+
}
1417+
1418+
#[test]
1419+
fn test_circleci_minimal() {
1420+
// Test that CircleCI works with minimal env vars (just the platform identifier)
1421+
// When no branch is set, branch_class is None
1422+
let env_vars = EnvVars::from_iter(vec![(String::from("CIRCLECI"), String::from("true"))]);
1423+
1424+
let mut env_parser = EnvParser::new();
1425+
env_parser.parse(&env_vars, &[], None);
1426+
1427+
let ci_info = env_parser.into_ci_info_parser().unwrap().info_ci_info();
1428+
1429+
pretty_assertions::assert_eq!(
1430+
ci_info,
1431+
CIInfo {
1432+
platform: CIPlatform::CircleCI,
1433+
job_url: None,
1434+
branch: None,
1435+
branch_class: None, // No branch means no branch_class
1436+
pr_number: None,
1437+
actor: None,
1438+
committer_name: None,
1439+
committer_email: None,
1440+
author_name: None,
1441+
author_email: None,
1442+
commit_message: None,
1443+
title: None,
1444+
workflow: None,
1445+
job: None,
1446+
}
1447+
);
1448+
}
1449+
12631450
#[test]
12641451
fn does_not_cross_contaminate_prioritizes_custom() {
12651452
let pr_number = 123;

0 commit comments

Comments
 (0)