Skip to content

Commit

Permalink
Change "analysis failed behavior" to have more of a global effect
Browse files Browse the repository at this point in the history
  • Loading branch information
tylercamp committed Jan 18, 2023
1 parent 45161f7 commit 3cd778c
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 37 deletions.
Expand Up @@ -32,21 +32,18 @@ public class AnalysisResultConfiguration {
private int numBuildsInGraph;
private boolean breakForPolicy;

private BuildEffectBehavior analysisFailedBehavior;

@DataBoundConstructor
public AnalysisResultConfiguration(String failureSeverity,
String unstableSeverity, boolean failureOnlyNew,
boolean unstableOnlyNew, int numBuildsInGraph,
boolean breakForPolicy, BuildEffectBehavior analysisFailedBehavior) {
boolean breakForPolicy) {

this.failureSeverity = failureSeverity;
this.unstableSeverity = unstableSeverity;
this.failureOnlyNew = failureOnlyNew;
this.unstableOnlyNew = unstableOnlyNew;
this.numBuildsInGraph = numBuildsInGraph;
this.breakForPolicy = breakForPolicy;
this.analysisFailedBehavior = analysisFailedBehavior;
}
public String getFailureSeverity() {
return failureSeverity;
Expand Down Expand Up @@ -78,12 +75,6 @@ public int getNumBuildsInGraph() {
public void setNumBuildsInGraph(int numBuildsInGraph) {
this.numBuildsInGraph = numBuildsInGraph;
}
public BuildEffectBehavior getAnalysisFailedBehavior() {
return analysisFailedBehavior;
}
public void setAnalysisFailedBehavior(BuildEffectBehavior behavior) {
this.analysisFailedBehavior = behavior;
}
public boolean getBreakForPolicy() {
return breakForPolicy;
}
Expand Down
@@ -1,9 +1,9 @@
package org.jenkinsci.plugins.codedx;

public enum BuildEffectBehavior {
MarkFailed("Mark Failed"),
MarkUnstable("Mark Unstable"),
None("Ignore");
MarkFailed("Mark Build as Failed"),
MarkUnstable("Mark Build as Unstable"),
None("Ignore Errors");

private String label;
BuildEffectBehavior(String label) {
Expand Down
56 changes: 42 additions & 14 deletions src/main/java/org/jenkinsci/plugins/codedx/CodeDxPublisher.java
Expand Up @@ -83,6 +83,8 @@ public class CodeDxPublisher extends Recorder implements SimpleBuildStep {

private String targetBranchName, baseBranchName;

private BuildEffectBehavior errorHandlingBehavior;

private final static Logger logger = Logger.getLogger(CodeDxPublisher.class.getName());

/**
Expand All @@ -109,6 +111,7 @@ public CodeDxPublisher(
this.selfSignedCertificateFingerprint = null;
this.targetBranchName = null;
this.baseBranchName = null;
this.errorHandlingBehavior = BuildEffectBehavior.MarkFailed;

setupClient();
}
Expand Down Expand Up @@ -218,20 +221,31 @@ public void setBaseBranchName(String baseBranchName) {
this.baseBranchName = null;
}

private void handleAnalysisFailure(Run<?, ?> build, PrintStream buildOutput, String cause) {
switch (analysisResultConfiguration.getAnalysisFailedBehavior()) {
public BuildEffectBehavior getErrorHandlingBehavior() {
return errorHandlingBehavior;
}

@DataBoundSetter
public void setErrorHandlingBehavior(BuildEffectBehavior behavior) {
errorHandlingBehavior = behavior;
}

// returns true if we ignore the error, false if we want to exit prematurely
private Boolean handleAnalysisFailure(Run<?, ?> build, PrintStream buildOutput, String cause) {
buildOutput.println(cause);
switch (errorHandlingBehavior) {
case MarkUnstable:
buildOutput.println(cause + ", marking build as Unstable");
buildOutput.println("Marking build as Unstable");
build.setResult(Result.UNSTABLE);
break;
return false;

case MarkFailed:
buildOutput.println(cause + ", marking build as Failure");
buildOutput.println("Marking build as Failure");
build.setResult(Result.FAILURE);
break;
return false;

case None:
break;
default:
return true;
}
}

Expand Down Expand Up @@ -271,7 +285,12 @@ public void perform(
cdxVersion = repeatingClient.getCodeDxVersion();
buildOutput.println("Got Code Dx version: " + cdxVersion);
} catch (CodeDxClientException e) {
throw new IOException("Failed to get Code Dx version; aborting build.", e);
if (!handleAnalysisFailure(build, buildOutput, "Failed to get Code Dx version")) {
return;
} else {
cdxVersion = CodeDxVersion.fromString("1.0.0");
buildOutput.println("Continuing with placeholder Code Dx version " + cdxVersion);
}
}

ValueResolver valueResolver = new ValueResolver(build, workspace, listener, buildOutput);
Expand Down Expand Up @@ -345,7 +364,9 @@ public void perform(
String.format("Response Content: %s", e.getResponseContent()) + '\n' +
Util.getStackTrace(e);

throw new AbortException(message);
buildOutput.println(message);
handleAnalysisFailure(build, buildOutput, "Failed to start analysis");
return; // nothing else to do if we can't start the analysis, everything else relies on it
} finally {
// close streams after we're done sending them
for(Map.Entry<String, InputStream> entry : toSend.entrySet()){
Expand Down Expand Up @@ -373,7 +394,11 @@ public void perform(
repeatingClient.setAnalysisName(project, response.getAnalysisId(), expandedAnalysisName);
buildOutput.println("Successfully updated analysis name.");
} catch (CodeDxClientException e) {
throw new IOException("Got error from Code Dx API Client while trying to set the analysis name", e);
e.printStackTrace(buildOutput);
// this doesn't affect anything else in the plugin, only exit early if we're meant to fail
if (!handleAnalysisFailure(build, buildOutput, "Got error from Code Dx API Client while trying to set the analysis name")) {
return;
}
}
}
}
Expand Down Expand Up @@ -402,7 +427,9 @@ public void perform(
}
} while (Job.QUEUED.equals(status) || Job.RUNNING.equals(status));
} catch (CodeDxClientException e) {
throw new IOException("Fatal Error! There was a problem querying for the analysis status.", e);
e.printStackTrace(buildOutput);
handleAnalysisFailure(build, buildOutput, "There was an error querying for the analysis status");
return; // nothing else to do if the analysis failed
}

if (Job.COMPLETED.equals(status)) {
Expand Down Expand Up @@ -467,7 +494,8 @@ public void perform(
throw new AbortException("Build result is non-success, terminating build");
}
} catch (CodeDxClientException e) {
throw new IOException("Fatal Error! There was a problem retrieving analysis results.", e);
e.printStackTrace(buildOutput);
handleAnalysisFailure(build, buildOutput, "There was an error retrieving analysis results");
}
} else {
buildOutput.println("Analysis status: " + status);
Expand Down Expand Up @@ -730,7 +758,7 @@ public ListBoxModel doFillProjectIdItems(@QueryParameter final String url, @Quer
return listBox;
}

public ListBoxModel doFillAnalysisFailedBehaviorItems() {
public ListBoxModel doFillErrorHandlingBehaviorItems() {
ListBoxModel listBox = new ListBoxModel();
listBox.add(BuildEffectBehavior.None.getLabel(), BuildEffectBehavior.None.name());
listBox.add(BuildEffectBehavior.MarkUnstable.getLabel(), BuildEffectBehavior.MarkUnstable.name());
Expand Down
Expand Up @@ -47,19 +47,18 @@
<f:textbox/>
</f:entry>

<f:entry title="Error Handling" field="errorHandlingBehavior" help="/plugin/codedx/help-errorHandlingBehavior.html">
<!-- note: we could use <enum> instead, but it looks like this is semi-broken and unreliable (depending on jenkins version) -->
<f:select default="MarkFailed" />
</f:entry>

<f:block>
<table id="analysisResultConfiguration">
<j:set var="analysisResultConfiguration" value="${instance.analysisResultConfiguration}"/>
<f:optionalBlock title="Wait for Analysis Results" name="analysisResultConfiguration"
checked="${analysisResultConfiguration != null}"
help="/plugin/codedx/help-analysisResultConfiguration.html">

<f:section title="Error Handling">
<f:entry title="Analysis Error Behavior" field="analysisFailedBehavior">
<f:select default="None" />
</f:entry>
</f:section>

<f:section title="Build Failure Conditions">
<f:entry title="'Break the build' Policy Action" field="breakForPolicy" help="/plugin/codedx/help-breakForPolicy.html">
<f:checkbox checked="${analysisResultConfiguration.breakForPolicy}" default="true"/>
Expand Down
4 changes: 0 additions & 4 deletions src/main/webapp/help-breakIfFailed.html

This file was deleted.

12 changes: 12 additions & 0 deletions src/main/webapp/help-errorHandlingBehavior.html
@@ -0,0 +1,12 @@
<div>
<p>
Determines the action when a connection error occurs, or when the analysis fails. If
set to "Ignore Errors", the build will always succeed when an error occurs, regardless
of any "Build Failure Conditions" or "Build Unstable Conditions" set in the
"Wait for Analysis Results" section.
</p>
<p>
(Does not affect behavior for internal plugin errors, eg configuration errors or unexpected exceptions - these
will still cause build errors.)
</p>
</div>

0 comments on commit 3cd778c

Please sign in to comment.