Skip to content

Commit

Permalink
feature: Allow for the traceability option to be toggled globally (JE…
Browse files Browse the repository at this point in the history
…NKINS-70543) (#619)
  • Loading branch information
bguerin authored May 2, 2023
1 parent 9ee6981 commit 10f6e41
Show file tree
Hide file tree
Showing 17 changed files with 201 additions and 44 deletions.
20 changes: 17 additions & 3 deletions README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ For example, you might end up having builds incorrectly succeed, just because yo
By using this option, Jenkins will tell Maven to use a custom path for the build as the local Maven repository by using `-Dmaven.repo.local` +
If specified as a relative path then this value will be resolved against the workspace root and not the current working directory. +
ie. `$WORKSPACE/.repository` if `.repository` value is specified.
* *Maven Traceability* (`traceability`): adds additional output to the maven wrapper script. Maven is executed with parameter `--show-version` and the start of the wrapper script is indicated by `----- withMaven Wrapper script -----`. Defaults to `true`.
* *Maven Traceability* (`traceability`): adds additional output to the maven wrapper script. Maven is executed with parameter `--show-version` and the start of the wrapper script is indicated by `----- withMaven Wrapper script -----`. Defaults to `false`.

IMPORTANT: `mavenSettingsConfig` and `globalMavenSettingsConfig` use the *ID*, not the *name*, of the Maven settings file (resp Maven Global Settings file).

Expand Down Expand Up @@ -176,7 +176,9 @@ image:docs/images/default-maven-settings-defined-at-the-folder-level.png[]
[#feature-traceability]
=== Traceability of Maven builds

The `withMaven()` pipeline step will capture in the logs of the build all the details of the execution:
By setting the parameter `traceability` to `true` (either globally on the tools configuration page, or for one step in particular), the `withMaven()` pipeline step will capture in the logs of the build all the details of the execution:

image:docs/images/global-tools-configuration-traceability.png[]

* Version of the JVM
** `withMaven(){}` step initialization:
Expand Down Expand Up @@ -207,7 +209,19 @@ Apache Maven 3.3.9 (bb52d8502b132ec0a5a3f4c09453c07478323dc5; 2015-11-10T16:41:4
[withMaven] use Maven settings.xml 'maven-settings-for-supply-chain-build-job' with Maven servers credentials provided by Jenkins (replaceAll: true): [mavenServerId: 'nexus.beescloud.com', jenkinsCredentials: 'beescloud-nexus-deployment-credentials', username: 'deployment', ...]
----

.Sample
.Pipeline snippet
[source,groovy]
----
node {
stage ('Build') {
withMaven(traceability: true) {
...
}
}
}
----

.Logs sample
----
[withMaven] use JDK installation JDK8
[withMaven] use Maven installation 'M3'
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ public class GlobalPipelineMavenConfig extends GlobalConfiguration {

private transient PipelineTriggerService pipelineTriggerService;

private boolean globalTraceability = false;

private boolean triggerDownstreamUponResultSuccess = true;
private boolean triggerDownstreamUponResultUnstable;
private boolean triggerDownstreamUponResultFailure;
Expand Down Expand Up @@ -125,6 +127,15 @@ public void setPublisherOptions(List<MavenPublisher> publisherOptions) {
this.publisherOptions = publisherOptions;
}

public boolean isGlobalTraceability() {
return globalTraceability;
}

@DataBoundSetter
public void setGlobalTraceability(boolean globalTraceability) {
this.globalTraceability = globalTraceability;
}

public boolean isTriggerDownstreamUponResultSuccess() {
return triggerDownstreamUponResultSuccess;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,9 @@
/**
* Configures maven environment to use within a pipeline job by calling <code>sh mvn</code> or <code>bat mvn</code>.
* The selected maven installation will be configured and prepended to the path.
*
*/
public class WithMavenStep extends Step {


private String tempBinDir = "";
private String mavenSettingsConfig;
private String mavenSettingsFilePath = "";
Expand All @@ -78,7 +76,7 @@ public class WithMavenStep extends Step {
private String mavenLocalRepo = "";
private List<MavenPublisher> options = new ArrayList<>();
private MavenPublisherStrategy publisherStrategy = MavenPublisherStrategy.IMPLICIT;
private boolean traceability = true;
private Boolean traceability = null;

@DataBoundConstructor
public WithMavenStep() {
Expand Down Expand Up @@ -174,12 +172,12 @@ public void setPublisherStrategy(MavenPublisherStrategy publisherStrategy) {
this.publisherStrategy = publisherStrategy;
}

public boolean isTraceability() {
public Boolean isTraceability() {
return traceability;
}

@DataBoundSetter
public void setTraceability(final boolean traceability) {
public void setTraceability(final Boolean traceability) {
this.traceability = traceability;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ class WithMavenStepExecution2 extends GeneralNonBlockingStepExecution {

protected boolean doStart() throws Exception {
envOverride = new EnvVars();
console = new TaskListenerTraceWrapper(listener, step.isTraceability());
console = new TaskListenerTraceWrapper(listener, computeTraceability());

if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.FINE, "Maven: {0}", step.getMaven());
Expand Down Expand Up @@ -506,7 +506,7 @@ private String obtainMavenExec() throws IOException, InterruptedException {
// if at this point mvnExecPath is still null try to use which/where command to find a maven executable
if (mvnExecPath == null) {
if (LOGGER.isLoggable(Level.FINE)) {
console.println("[withMaven] No Maven Installation or MAVEN_HOME found, looking for mvn executable by using which/where command");
console.trace("[withMaven] No Maven Installation or MAVEN_HOME found, looking for mvn executable by using which/where command");
}
if (Boolean.TRUE.equals(getComputer().isUnix())) {
mvnExecPath = readFromProcess("/bin/sh", "-c", "which mvn");
Expand Down Expand Up @@ -748,7 +748,7 @@ private String setupSettingFile(@NonNull Collection<Credentials> credentials) th
envOverride.put("MVN_SETTINGS", settingsDest.getRemote());
if (LOGGER.isLoggable(Level.FINE)) {
mavenSettingsLog.append("Maven settings on the build agent'").append(settingsPath).append("'");
console.println(mavenSettingsLog);
console.trace(mavenSettingsLog);
}
return settingsDest.getRemote();
} else {
Expand All @@ -759,14 +759,14 @@ private String setupSettingFile(@NonNull Collection<Credentials> credentials) th
// do nothing
if (LOGGER.isLoggable(Level.FINE)) {
mavenSettingsLog.append("Maven settings defined by 'DefaultSettingsProvider', NOT overriding it.");
console.println(mavenSettingsLog);
console.trace(mavenSettingsLog);
}
} else if (settingsProvider == null) {
// should not happen according to the source code of jenkins.mvn.MavenConfig.getSettingsProvider() in jenkins-core 2.7
// do nothing
if (LOGGER.isLoggable(Level.FINE)) {
mavenSettingsLog.append("Maven settings are null. NO settings will be defined.");
console.println(mavenSettingsLog);
console.trace(mavenSettingsLog);
}
} else {
console.trace("[withMaven] Ignore unsupported Maven SettingsProvider " + settingsProvider);
Expand Down Expand Up @@ -876,7 +876,7 @@ private String setupGlobalSettingFile(@NonNull Collection<Credentials> credentia
settings.copyTo(settingsDest);
envOverride.put("GLOBAL_MVN_SETTINGS", settingsDest.getRemote());
if (LOGGER.isLoggable(Level.FINE)) {
console.println(mavenSettingsLog);
console.trace(mavenSettingsLog);
}
return settingsDest.getRemote();
} else {
Expand All @@ -886,14 +886,14 @@ private String setupGlobalSettingFile(@NonNull Collection<Credentials> credentia
// do nothing
if (LOGGER.isLoggable(Level.FINE)) {
mavenSettingsLog.append("Maven global settings defined by 'DefaultSettingsProvider', NOT overriding it.");
console.println(mavenSettingsLog);
console.trace(mavenSettingsLog);
}
} else if (globalSettingsProvider == null) {
// should not happen according to the source code of jenkins.mvn.GlobalMavenConfig.getGlobalSettingsProvider() in jenkins-core 2.7
// do nothing
if (LOGGER.isLoggable(Level.FINE)) {
mavenSettingsLog.append("Maven global settings are null. NO settings will be defined.");
console.println(mavenSettingsLog);
console.trace(mavenSettingsLog);
}
} else {
console.trace("[withMaven] Ignore unsupported Maven GlobalSettingsProvider " + globalSettingsProvider);
Expand Down Expand Up @@ -1050,11 +1050,16 @@ public Map<String, StandardUsernameCredentials> resolveCredentials(@Nullable fin
}

private void ifTraceabilityEnabled(Runnable runnable) {
if (step.isTraceability()) {
if (computeTraceability()) {
runnable.run();
}
}

private boolean computeTraceability() {
return GlobalPipelineMavenConfig.get().isGlobalTraceability() && step.isTraceability() == null
|| Boolean.TRUE.equals(step.isTraceability());
}

/**
* Takes care of overriding the environment with our defined overrides
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ THE SOFTWARE.

<f:validateButton title="${%Validate Database Configuration}" method="validateJdbcConnection" with="jdbcUrl,properties,jdbcCredentialsId"/>
</f:entry>
<f:entry title="${%Global traceability}" >
<f:checkbox title="${%Enable traceability globally : Java/Maven versions, settings, ...}" field="globalTraceability" />
</f:entry>
<f:entry title="${%Trigger downstream upon result}" field="triggerDownstreamUponResult" >
<f:checkbox title="${%Success}" field="triggerDownstreamUponResultSuccess" default="true" />
<f:checkbox title="${%Unstable}" field="triggerDownstreamUponResultUnstable" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public class ConfigurationAsCodeTest {
public void should_support_default_configuration() throws Exception {
GlobalPipelineMavenConfig config = r.jenkins.getExtensionList(GlobalPipelineMavenConfig.class).get(0);

assertThat(config.isGlobalTraceability(), is(false));
assertThat(config.getJdbcUrl(), nullValue());
assertThat(config.getJdbcCredentialsId(), nullValue());
assertThat(config.getProperties(), nullValue());
Expand All @@ -46,6 +47,21 @@ public void should_support_default_configuration() throws Exception {
assertThat(exported, is(expected));
}

@Test
@ConfiguredWithCode("configuration-as-code_traceability.yml")
public void should_support_global_traceability() throws Exception {
GlobalPipelineMavenConfig config = r.jenkins.getExtensionList(GlobalPipelineMavenConfig.class).get(0);

assertThat(config.isGlobalTraceability(), is(true));

ConfiguratorRegistry registry = ConfiguratorRegistry.get();
ConfigurationContext context = new ConfigurationContext(registry);
String exported = toYamlString(getToolRoot(context).get("pipelineMaven"));
String expected = toStringFromYamlFile(this, "expected_output_traceability.yml");

assertThat(exported, is(expected));
}

@Test
@ConfiguredWithCode("configuration-as-code_triggers.yml")
public void should_support_triggers_configuration() throws Exception {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ public void testMavenGlobalToolRecognizedInScriptedPipeline() throws Exception {
"node('" + AGENT_NAME + "') {\n" +
" def mavenHome = tool '" + MAVEN_GLOBAL_TOOL_NAME + "'\n" +
" withEnv([\"MAVEN_HOME=${mavenHome}\"]) {\n" +
" withMaven() {\n" +
" withMaven(traceability: true) {\n" +
" sh \"mvn --version\"\n" +
" }\n" +
" }\n" +
Expand All @@ -109,7 +109,7 @@ public void testMavenGlobalToolRecognizedInDeclarativePipeline() throws Exceptio
" stages {\n" +
" stage('Build') {\n" +
" steps {\n" +
" withMaven() {\n" +
" withMaven(traceability: true) {\n" +
" sh \"mvn --version\"\n" +
" }\n" +
" }\n" +
Expand All @@ -127,7 +127,7 @@ public void testPreInstalledMavenRecognizedWithoutMavenHome() throws Exception {

WorkflowRun run = runPipeline("" +
"node('" + AGENT_NAME + "') {\n" +
" withMaven() {\n" +
" withMaven(traceability: true) {\n" +
" sh \"mvn --version\"\n" +
" }\n" +
"}");
Expand All @@ -143,7 +143,7 @@ public void testPreInstalledMavenRecognizedWithMavenHome() throws Exception {
WorkflowRun run = runPipeline("" +
"node('" + AGENT_NAME + "') {\n" +
" sh 'echo $MAVEN_HOME'\n" +
" withMaven() {\n" +
" withMaven(traceability: true) {\n" +
" sh \"mvn --version\"\n" +
" }\n" +
"}");
Expand Down
Loading

0 comments on commit 10f6e41

Please sign in to comment.