From 71c4864dcee36e20696f0682ccb7bda476bdf5b1 Mon Sep 17 00:00:00 2001 From: Nikita Tkachenko <121111529+nikita-tkachenko-datadog@users.noreply.github.com> Date: Wed, 8 Nov 2023 17:59:14 +0100 Subject: [PATCH] Add fallback logic for job name and build tag in build data (#368) --- .../plugins/datadog/model/BuildData.java | 75 ++++++++++---- .../plugins/datadog/model/BuildDataTest.java | 99 +++++++++++++++++++ 2 files changed, 157 insertions(+), 17 deletions(-) create mode 100644 src/test/java/org/datadog/jenkins/plugins/datadog/model/BuildDataTest.java diff --git a/src/main/java/org/datadog/jenkins/plugins/datadog/model/BuildData.java b/src/main/java/org/datadog/jenkins/plugins/datadog/model/BuildData.java index 9acdc0388..1f016a157 100644 --- a/src/main/java/org/datadog/jenkins/plugins/datadog/model/BuildData.java +++ b/src/main/java/org/datadog/jenkins/plugins/datadog/model/BuildData.java @@ -44,6 +44,8 @@ of this software and associated documentation files (the "Software"), to deal import hudson.model.BooleanParameterValue; import hudson.model.Cause; import hudson.model.CauseAction; +import hudson.model.ItemGroup; +import hudson.model.Job; import hudson.model.ParameterValue; import hudson.model.ParametersAction; import hudson.model.Run; @@ -193,23 +195,10 @@ public BuildData(Run run, TaskListener listener) throws IOException, Interrupted // Save charset canonical name setCharset(run.getCharset()); - // Set Job Name - String baseJobName = null; - try { - baseJobName = run.getParent().getParent().getFullName(); - if (baseJobName.length() == 0) { - baseJobName = run.getParent().getName(); - } - } catch(NullPointerException e){ - //noop - } + String baseJobName = getBaseJobName(run, envVars); setBaseJobName(normalizeJobName(baseJobName)); - String jobNameWithConfiguration = null; - try { - jobNameWithConfiguration = run.getParent().getFullName(); - } catch(NullPointerException e){ - //noop - } + + String jobNameWithConfiguration = getJobName(run, envVars); setJobName(normalizeJobName(jobNameWithConfiguration)); // Set Jenkins Url @@ -236,6 +225,51 @@ public BuildData(Run run, TaskListener listener) throws IOException, Interrupted } } + private static String getBaseJobName(Run run, EnvVars envVars) { + Job job = run.getParent(); + if (job != null) { + ItemGroup jobParent = job.getParent(); + if (jobParent != null) { + try { + String jobParentFullName = jobParent.getFullName(); + if (StringUtils.isNotBlank(jobParentFullName)) { + return jobParentFullName; + } + } catch (NullPointerException e) { + // this is possible if data is not mocked properly in unit tests + } + } + } + if (envVars != null) { + String envJobBaseName = envVars.get("JOB_BASE_NAME"); + if (StringUtils.isNotBlank(envJobBaseName)) { + return envJobBaseName; + } + } + return getJobName(run, envVars); + } + + private static String getJobName(Run run, EnvVars envVars) { + Job job = run.getParent(); + if (job != null) { + try { + String jobFullName = job.getFullName(); + if (StringUtils.isNotBlank(jobFullName)) { + return jobFullName; + } + } catch (NullPointerException e) { + // this is possible if data is not mocked properly in unit tests + } + } + if (envVars != null) { + String envJobName = envVars.get("JOB_NAME"); + if (StringUtils.isNotBlank(envJobName)) { + return envJobName; + } + } + return "unknown"; + } + private void getMissingGitValuesFrom(BuildData previousData) { if (branch == null) { branch = previousData.branch; @@ -311,7 +345,14 @@ private void populateEnvVariables(EnvVars envVars){ setBuildId(envVars.get("BUILD_ID")); setBuildUrl(envVars.get("BUILD_URL")); setNodeName(envVars.get("NODE_NAME")); - setBuildTag(envVars.get("BUILD_TAG")); + + String envBuildTag = envVars.get("BUILD_TAG"); + if (StringUtils.isNotBlank(envBuildTag)) { + setBuildTag(envBuildTag); + } else { + setBuildTag("jenkins-" + envVars.get("JOB_NAME") + "-" + envVars.get("BUILD_NUMBER")); + } + setExecutorNumber(envVars.get("EXECUTOR_NUMBER")); setJavaHome(envVars.get("JAVA_HOME")); setWorkspace(envVars.get("WORKSPACE")); diff --git a/src/test/java/org/datadog/jenkins/plugins/datadog/model/BuildDataTest.java b/src/test/java/org/datadog/jenkins/plugins/datadog/model/BuildDataTest.java new file mode 100644 index 000000000..8cb9a5edc --- /dev/null +++ b/src/test/java/org/datadog/jenkins/plugins/datadog/model/BuildDataTest.java @@ -0,0 +1,99 @@ +package org.datadog.jenkins.plugins.datadog.model; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import hudson.EnvVars; +import hudson.model.Hudson; +import hudson.model.Run; +import hudson.model.TaskListener; +import java.io.IOException; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import jenkins.model.Jenkins; +import org.datadog.jenkins.plugins.datadog.stubs.BuildStub; +import org.datadog.jenkins.plugins.datadog.stubs.ProjectStub; +import org.junit.Test; + +public class BuildDataTest { + + @Test + public void testBaseJobNameIsTakenFromParentName() throws IOException, InterruptedException { + Run run = givenJobRun("jobName", "jobParentName", Collections.singletonMap("JOB_BASE_NAME", "jobBaseNameFromEnvironment")); + BuildData buildData = whenCreatingBuildData(run); + assertEquals("jobParentName", buildData.getBaseJobName("")); + } + + @Test + public void testBaseJobNameFallsBackToEnvVar() throws IOException, InterruptedException { + Run run = givenJobRun("jobName", "", Collections.singletonMap("JOB_BASE_NAME", "jobBaseNameFromEnvironment")); + BuildData buildData = whenCreatingBuildData(run); + assertEquals("jobBaseNameFromEnvironment", buildData.getBaseJobName("")); + } + + @Test + public void testBaseJobNameFallsBackToJobName() throws IOException, InterruptedException { + Run run = givenJobRun("jobName", "", Collections.singletonMap("JOB_NAME", "jobNameFromEnvironment")); + BuildData buildData = whenCreatingBuildData(run); + assertEquals("jobName", buildData.getBaseJobName("")); + } + + @Test + public void testBaseJobNameFallsBackToJobNameFromEnvVar() throws IOException, InterruptedException { + Run run = givenJobRun("", "", Collections.singletonMap("JOB_NAME", "jobNameFromEnvironment")); + BuildData buildData = whenCreatingBuildData(run); + assertEquals("jobNameFromEnvironment", buildData.getBaseJobName("")); + } + + @Test + public void testJobNameIsTakenFromFullJobName() throws IOException, InterruptedException { + Run run = givenJobRun("jobName", "jobParentName", Collections.singletonMap("JOB_BASE_NAME", "jobBaseNameFromEnvironment")); + BuildData buildData = whenCreatingBuildData(run); + assertEquals("jobParentName/jobName", buildData.getJobName("")); + } + + @Test + public void testJobNameFallsBackToEnvVar() throws IOException, InterruptedException { + Run run = givenJobRun("", "", Collections.singletonMap("JOB_NAME", "jobNameFromEnvironment")); + BuildData buildData = whenCreatingBuildData(run); + assertEquals("jobNameFromEnvironment", buildData.getJobName("")); + } + + @Test + public void testBuildTagIsTakenFromEnvVar() throws IOException, InterruptedException { + Run run = givenJobRun("jobName", "jobParentName", Collections.singletonMap("BUILD_TAG", "buildTag")); + BuildData buildData = whenCreatingBuildData(run); + assertEquals("buildTag", buildData.getBuildTag("")); + } + + @Test + public void testBuildTagFallsBackToAlternativeEnvVars() throws IOException, InterruptedException { + Map envVars = new HashMap<>(); + envVars.put("JOB_NAME", "jobName"); + envVars.put("BUILD_NUMBER", "buildNumber"); + Run run = givenJobRun("jobName", "jobParentName", envVars); + BuildData buildData = whenCreatingBuildData(run); + assertEquals("jenkins-jobName-buildNumber", buildData.getBuildTag("")); + } + + private Run givenJobRun(String jobName, String jobParentName, Map environment) throws IOException { + Jenkins jenkins = mock(Hudson.class); + when(jenkins.getFullName()).thenReturn(jobParentName); + ProjectStub job = new ProjectStub(jenkins, jobName); + + EnvVars envVars = new EnvVars(); + envVars.putAll(environment); + + return new BuildStub(job, null, envVars, null, 10L, 2, null, 0L, null); + } + + private BuildData whenCreatingBuildData(Run run) throws IOException, InterruptedException { + TaskListener listener = mock(TaskListener.class); + BuildData bd = new BuildData(run, listener); + return bd; + } + + +}