Skip to content

Commit

Permalink
Add support for checking policy status in build conditions
Browse files Browse the repository at this point in the history
  • Loading branch information
tylercamp committed Jan 12, 2023
1 parent fd2a5e1 commit fc87748
Show file tree
Hide file tree
Showing 7 changed files with 133 additions and 72 deletions.
10 changes: 10 additions & 0 deletions src/main/java/com/codedx/api/client/CodeDxClient.java
Expand Up @@ -302,6 +302,16 @@ public List<Branch> getProjectBranches(ProjectContext project) throws IOExceptio
);
}

public boolean projectPolicyShouldBreakTheBuild(ProjectContext project) throws IOException, CodeDxClientException {
return doHttpRequest(
new HttpGet(),
"projects/" + project.toString() + "/policies/any/build-broken",
true,
new TypeToken<Boolean>(){}.getType(),
null
);
}

/**
* Perform an HttpRequest to the given api path, with an optional request body, and parse the response
* @param request Generally a new `HttpGet`, `HttpPost`, or `HttpPut`
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/com/codedx/util/CodeDxVersion.java
Expand Up @@ -48,6 +48,8 @@ public final class CodeDxVersion implements Comparable<CodeDxVersion> {
// until 2022.4.3
public final static CodeDxVersion MIN_FOR_BRANCHING = fromString("2022.4.3");

public final static CodeDxVersion MIN_FOR_POLICIES = fromString("2023.1.0");

public static CodeDxVersion fromString(String version){
// format is expected to be "x(.y)*-abc", and we want the x.y.z part
Pattern versionRegex = Pattern.compile("^(\\d+(?:\\.\\d+)*).*");
Expand Down
Expand Up @@ -45,12 +45,13 @@ public class AnalysisResultChecker {
private Date newThreshold;
private boolean failureOnlyNew;
private boolean unstableOnlyNew;
private boolean breakForPolicy;
private PrintStream logger;
private ProjectContext project;

public AnalysisResultChecker(CodeDxClient client, CodeDxVersion cdxVersion, String failureSeverity,
String unstableSeverity, Date newThreshold, boolean failureOnlyNew,
boolean unstableOnlyNew, ProjectContext project, PrintStream logger) {
boolean unstableOnlyNew, boolean breakForPolicy, ProjectContext project, PrintStream logger) {

this.client = client;
this.cdxVersion = cdxVersion;
Expand All @@ -59,11 +60,28 @@ public AnalysisResultChecker(CodeDxClient client, CodeDxVersion cdxVersion, Stri
this.newThreshold = newThreshold;
this.failureOnlyNew = failureOnlyNew;
this.unstableOnlyNew = unstableOnlyNew;
this.breakForPolicy = breakForPolicy;
this.project = project;
this.logger = logger;

if (breakForPolicy && cdxVersion.compareTo(CodeDxVersion.MIN_FOR_POLICIES) < 0) {
logger.println(
"The discovered Code Dx version " + cdxVersion.toString() + " is older than the minimum required " +
"version for Policies (" + CodeDxVersion.MIN_FOR_POLICIES + "), policy-related options will be ignored."
);
this.breakForPolicy = false;
}
}

public Result checkResult() throws ClientProtocolException, CodeDxClientException, IOException{
public Result checkResult() throws ClientProtocolException, CodeDxClientException, IOException {

if (breakForPolicy) {
logger.println("Checking for build-breaking policy violations...");
if (client.projectPolicyShouldBreakTheBuild(project)) {
logger.println("Failure: At least one Policy is violated and requires build failure");
return Result.FAILURE;
}
}

logger.println("Checking for findings that indicate build failure...");
if(!"None".equalsIgnoreCase(failureSeverity) && client.getFindingsCount(project, createFilter(failureSeverity, failureOnlyNew)) > 0){
Expand Down
Expand Up @@ -30,19 +30,21 @@ public class AnalysisResultConfiguration {
private boolean unstableOnlyNew;
private int numBuildsInGraph;
private boolean breakIfFailed;
private boolean breakForPolicy;

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

this.failureSeverity = failureSeverity;
this.unstableSeverity = unstableSeverity;
this.failureOnlyNew = failureOnlyNew;
this.unstableOnlyNew = unstableOnlyNew;
this.numBuildsInGraph = numBuildsInGraph;
this.breakIfFailed = breakIfFailed;
this.breakForPolicy = breakForPolicy;
}
public String getFailureSeverity() {
return failureSeverity;
Expand Down Expand Up @@ -80,4 +82,10 @@ public boolean getBreakIfFailed() {
public void setBreakIfFailed(boolean breakIfFailed) {
this.breakIfFailed = breakIfFailed;
}
public boolean getBreakForPolicy() {
return breakForPolicy;
}
public void setBreakForPolicy(boolean breakForPolicy) {
this.breakForPolicy = breakForPolicy;
}
}
Expand Up @@ -441,6 +441,7 @@ public void perform(
startingDate, // the time this process started is the "new" threshold for filtering
analysisResultConfiguration.isFailureOnlyNew(),
analysisResultConfiguration.isUnstableOnlyNew(),
analysisResultConfiguration.getBreakForPolicy(),
project,
buildOutput);
Result buildResult = checker.checkResult();
Expand Down
@@ -1,98 +1,111 @@
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" escapeText="false">
<!--
This jelly script is used for per-project configuration.
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout"
xmlns:t="/lib/hudson" xmlns:f="/lib/form" escapeText="false">
<!--
This jelly script is used for per-project configuration.
See global.jelly for a general discussion about jelly script.
-->
See global.jelly for a general discussion about jelly script.
-->

<f:entry title="Server URL" field="url" help="/plugin/codedx/help-url.html">
<f:textbox clazz="codedx-url" />
</f:entry>
<f:textbox clazz="codedx-url"/>
</f:entry>
<f:advanced>
<f:entry field="selfSignedCertificateFingerprint" title="Self-Signed Certificate Fingerprint" help="/plugin/codedx/help-fingerprint.html">
<f:entry field="selfSignedCertificateFingerprint" title="Self-Signed Certificate Fingerprint"
help="/plugin/codedx/help-fingerprint.html">
<f:textbox/>
</f:entry>

</f:advanced>

<f:entry title="Server API Key" field="key" help="/plugin/codedx/help-key.html">
<f:textbox />
</f:entry>
<f:entry title="Server API Key" field="key" help="/plugin/codedx/help-key.html">
<f:textbox/>
</f:entry>

<f:entry title="Code Dx Project" field="projectId">
<f:select />
<f:select/>
</f:entry>

<f:entry title="Source and Binary Files" field="sourceAndBinaryFiles" help="/plugin/codedx/help-sourceAndBinaryFiles.html">
<f:textbox default="**" />
</f:entry>
<f:entry title="Source and Binary Files" field="sourceAndBinaryFiles"
help="/plugin/codedx/help-sourceAndBinaryFiles.html">
<f:textbox default="**"/>
</f:entry>

<f:entry title="Tool Output Files" field="toolOutputFiles" help="/plugin/codedx/help-toolOutputFiles.html">
<f:textbox />
</f:entry>
<f:entry title="Tool Output Files" field="toolOutputFiles" help="/plugin/codedx/help-toolOutputFiles.html">
<f:textbox/>
</f:entry>

<f:entry title="Analysis Name" field="analysisName" help="/plugin/codedx/help-analysisName.html">
<f:textbox default="Build #$${BUILD_NUMBER}" />
<f:entry title="Analysis Name" field="analysisName" help="/plugin/codedx/help-analysisName.html">
<f:textbox default="Build #$${BUILD_NUMBER}"/>
</f:entry>

<f:entry title="Target Branch" field="targetBranchName" help="/plugin/codedx/help-targetBranch.html">
<f:textbox />
<f:textbox/>
</f:entry>

<f:entry title="Base Branch" field="baseBranchName" help="/plugin/codedx/help-baseBranch.html">
<f:textbox />
<f:textbox/>
</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="Build Failure Conditions">
<f:entry title="Analysis Error" field="breakIfFailed" help="/plugin/codedx/help-breakIfFailed.html">
<f:checkbox checked="${analysisResultConfiguration.breakIfFailed}" default="true" />
</f:entry>

<f:entry title="Severity" field="failureSeverity" help="/plugin/codedx/help-failureSeverity.html">
<f:select value="${analysisResultConfiguration.failureSeverity}"/>
</f:entry>

<f:entry title="Only consider new findings." field="failureOnlyNew" help="/plugin/codedx/help-failureOnlyNew.html">
<f:checkbox checked="${analysisResultConfiguration.failureOnlyNew}"/>
</f:entry>
</f:section>

<f:section title="Build Unstable Conditions">
<f:entry title="Severity" field="unstableSeverity" help="/plugin/codedx/help-unstableSeverity.html">
<f:select value="${analysisResultConfiguration.unstableSeverity}"/>
<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="Build Failure Conditions">
<f:entry title="Analysis Error" field="breakIfFailed" help="/plugin/codedx/help-breakIfFailed.html">
<f:checkbox checked="${analysisResultConfiguration.breakIfFailed}" default="true"/>
</f:entry>

<f:entry title="'Break the build' Policy Action" field="breakForPolicy" help="/plugin/codedx/help-breakForPolicy.html">
<f:checkbox checked="${analysisResultConfiguration.breakForPolicy}" default="true"/>
</f:entry>

<f:entry title="Severity" field="failureSeverity" help="/plugin/codedx/help-failureSeverity.html">
<f:select value="${analysisResultConfiguration.failureSeverity}"/>
</f:entry>

<f:entry title="Only consider new findings." field="failureOnlyNew"
help="/plugin/codedx/help-failureOnlyNew.html">
<f:checkbox checked="${analysisResultConfiguration.failureOnlyNew}"/>
</f:entry>
</f:section>

<f:section title="Build Unstable Conditions">
<f:entry title="Severity" field="unstableSeverity" help="/plugin/codedx/help-unstableSeverity.html">
<f:select value="${analysisResultConfiguration.unstableSeverity}"/>
</f:entry>

<f:entry title="Only consider new findings." field="unstableOnlyNew"
help="/plugin/codedx/help-unstableOnlyNew.html">
<f:checkbox checked="${analysisResultConfiguration.unstableOnlyNew}"/>
</f:entry>
</f:section>


<f:section title="Graph Options">
<f:entry title="Number of Builds in Graph" field="numBuildsInGraph"
description="Any value less than 2 means unlimited.">
<f:number value="${analysisResultConfiguration.numBuildsInGraph}" default="0" clazz="number"/>
</f:entry>

</f:section>


</f:optionalBlock>
</table>
</f:block>

<f:section title="Advanced Options">
<f:advanced>
<f:entry title="Excluded Source and Binary Files" field="excludedSourceAndBinaryFiles"
help="/plugin/codedx/help-excludedSourceAndBinaryFiles.html">
<f:textbox/>
</f:entry>

<f:entry title="Only consider new findings." field="unstableOnlyNew" help="/plugin/codedx/help-unstableOnlyNew.html">
<f:checkbox checked="${analysisResultConfiguration.unstableOnlyNew}"/>
</f:entry>
</f:section>


<f:section title="Graph Options">
<f:entry title="Number of Builds in Graph" field="numBuildsInGraph" description="Any value less than 2 means unlimited.">
<f:number value="${analysisResultConfiguration.numBuildsInGraph}" default="0" clazz="number"/>
</f:entry>

</f:section>


</f:optionalBlock>
</table>
</f:block>

<f:section title="Advanced Options">
<f:advanced>
<f:entry title="Excluded Source and Binary Files" field="excludedSourceAndBinaryFiles" help="/plugin/codedx/help-excludedSourceAndBinaryFiles.html">
<f:textbox />
</f:entry>

</f:advanced>
</f:advanced>
</f:section>

</j:jelly>
9 changes: 9 additions & 0 deletions src/main/webapp/help-breakForPolicy.html
@@ -0,0 +1,9 @@
<div>
<p>
If enabled, will consider the build a failure if at least one of the Code Dx project's violated policies has
its action set to "Break the build".
</p>
<p>
(Note: policies are supported in Code Dx 2023.1.0 and up. This option will be ignored if using an older Code Dx version.)
</p>
</div>

0 comments on commit fc87748

Please sign in to comment.