diff --git a/plugin/pom.xml b/plugin/pom.xml
index ecc47ed21b..0f0e77611b 100644
--- a/plugin/pom.xml
+++ b/plugin/pom.xml
@@ -4,7 +4,7 @@
org.jvnet.hudson.plugins
analysis-pom
- 6.17.0
+ 7.1.0
@@ -41,8 +41,8 @@
1.19.3
- 2.4.0-rc1560.b_4b_993ec6a_9f
- 2.1.0-20240205.180020-1
+ 2.4.0-rc1561.1f746b_248f63
+ 2.1.0-20240207.074913-2
3.22
1.84
diff --git a/plugin/src/main/java/io/jenkins/plugins/analysis/core/model/AnalysisHistory.java b/plugin/src/main/java/io/jenkins/plugins/analysis/core/model/AnalysisHistory.java
index 8e536222bd..0dcf507200 100644
--- a/plugin/src/main/java/io/jenkins/plugins/analysis/core/model/AnalysisHistory.java
+++ b/plugin/src/main/java/io/jenkins/plugins/analysis/core/model/AnalysisHistory.java
@@ -9,22 +9,17 @@
import edu.umd.cs.findbugs.annotations.CheckForNull;
import edu.umd.cs.findbugs.annotations.NonNull;
-import hudson.model.Result;
import hudson.model.Run;
import io.jenkins.plugins.analysis.core.charts.JenkinsBuild;
import io.jenkins.plugins.analysis.core.util.AnalysisBuildResult;
-import static io.jenkins.plugins.analysis.core.model.AnalysisHistory.JobResultEvaluationMode.*;
-import static io.jenkins.plugins.analysis.core.model.AnalysisHistory.QualityGateEvaluationMode.*;
-
/**
* Provides a history of static analysis results. The history starts from a baseline build and provides access to a
* historical build result of the same type (or to all historical results using the provided {@link
* AnalysisResultIterator interator} implementation). The results are filtered by a {@link ResultSelector}, so a history
- * returns only results of the same type. This history can be configured to ignore the overall result of the associated
- * Jenkins builds (see {@link JobResultEvaluationMode JobResultEvaluationMode}). Additionally, this history can be
- * configured to ignore the builds that did not pass the quality gate (see {@link QualityGateEvaluationMode
+ * returns only results of the same type. This history can be configured to ignore the builds that did not pass the quality
+ * gate (see {@link QualityGateEvaluationMode
* QualityGateEvaluationMode}). Note that the baseline run might still be in progress and thus has not yet a result
* attached: i.e., the result of the {@code getPrevious*} methods may return different results on subsequent calls.
*
@@ -38,46 +33,8 @@ public class AnalysisHistory implements History {
/** Selects a result of the same type. */
private final ResultSelector selector;
- private final QualityGateEvaluationMode qualityGateEvaluationMode;
- private final JobResultEvaluationMode jobResultEvaluationMode;
-
- /**
- * Determines how the evaluation of the quality gates is taken into account when the previous result is
- * searched for.
- */
- public enum QualityGateEvaluationMode {
- /**
- * The quality gate result is ignored. The previous build with results of the same type is selected.
- */
- IGNORE_QUALITY_GATE,
- /**
- * The quality gate result must be successful. I.e., the history is searched for a
- * build that either passed the quality gate or has deactivated the quality gate.
- */
- SUCCESSFUL_QUALITY_GATE
- }
-
/**
- * Determines how the overall build {@link Result} of the {@link Run} is taken into account when the previous result
- * is searched for.
- */
- public enum JobResultEvaluationMode {
- /**
- * Only those jobs are considered that did not fail. I.e., jobs with result {@link Result#UNSTABLE} or {@link
- * Result#SUCCESS}.
- */
- NO_JOB_FAILURE,
-
- /**
- * All jobs are considered regardless of the result. If the job has an overall result of {@link Result#FAILURE}
- * then it will be considered as well.
- */
- IGNORE_JOB_RESULT
- }
-
- /**
- * Creates a new instance of {@link AnalysisHistory}. This history ignores the results of the
- * quality gate and the {@link Result} of the associated {@link Run}.
+ * Creates a new instance of {@link AnalysisHistory}.
*
* @param baseline
* the build to start the history from
@@ -85,34 +42,8 @@ public enum JobResultEvaluationMode {
* selects the associated action from a build
*/
public AnalysisHistory(final Run, ?> baseline, final ResultSelector selector) {
- this(baseline, selector, IGNORE_QUALITY_GATE, IGNORE_JOB_RESULT);
- }
-
- /**
- * Creates a new instance of {@link AnalysisHistory}.
- *
- * @param baseline
- * the run to start the history from
- * @param selector
- * selects the type of the result (to get a result for the same type of static analysis)
- * @param qualityGateEvaluationMode
- * If set to {@link QualityGateEvaluationMode#IGNORE_QUALITY_GATE}, then the result of the quality gate is
- * ignored when selecting a reference build. If set to {@link QualityGateEvaluationMode#SUCCESSFUL_QUALITY_GATE}
- * a failing quality gate will be passed from build to build until the original reason for the failure has
- * been resolved.
- * @param jobResultEvaluationMode
- * If set to {@link JobResultEvaluationMode#NO_JOB_FAILURE}, then only successful or unstable reference
- * builds will be considered (since analysis results might be inaccurate if the build failed). If set to
- * {@link JobResultEvaluationMode#IGNORE_JOB_RESULT}, then every build that contains a static analysis
- * result is considered, even if the build failed.
- */
- public AnalysisHistory(final Run, ?> baseline, final ResultSelector selector,
- final QualityGateEvaluationMode qualityGateEvaluationMode,
- final JobResultEvaluationMode jobResultEvaluationMode) {
this.baseline = baseline;
this.selector = selector;
- this.qualityGateEvaluationMode = qualityGateEvaluationMode;
- this.jobResultEvaluationMode = jobResultEvaluationMode;
}
@Override
@@ -141,46 +72,24 @@ public Report getIssues() {
}
private Optional getPreviousAction() {
- Optional> run = getRunWithResult(baseline, selector, qualityGateEvaluationMode,
- jobResultEvaluationMode);
+ Optional> run = getRunWithResult(baseline, selector);
if (run.isPresent()) {
return selector.get(run.get());
}
return Optional.empty();
}
- private static Optional> getRunWithResult(final @CheckForNull Run, ?> start,
- final ResultSelector selector,
- final QualityGateEvaluationMode qualityGateEvaluationMode,
- final JobResultEvaluationMode jobResultEvaluationMode) {
+ private static Optional> getRunWithResult(
+ final @CheckForNull Run, ?> start, final ResultSelector selector) {
for (Run, ?> run = start; run != null; run = run.getPreviousBuild()) {
Optional action = selector.get(run);
if (action.isPresent()) {
- ResultAction resultAction = action.get();
- if (hasCorrectJobResult(run, jobResultEvaluationMode)
- && hasCorrectQualityGateStatus(resultAction, qualityGateEvaluationMode)) {
- return Optional.of(run);
- }
+ return Optional.of(run);
}
}
return Optional.empty();
}
- private static boolean hasCorrectQualityGateStatus(final ResultAction action,
- final QualityGateEvaluationMode qualityGateEvaluationMode) {
- return action.isSuccessful() || qualityGateEvaluationMode == IGNORE_QUALITY_GATE;
- }
-
- private static boolean hasCorrectJobResult(final Run, ?> run,
- final JobResultEvaluationMode jobResultEvaluationMode) {
- if (jobResultEvaluationMode == NO_JOB_FAILURE) {
- Result result = run.getResult();
-
- return result != null && result.isBetterThan(Result.FAILURE);
- }
- return true;
- }
-
@Override
public boolean hasMultipleResults() {
Iterator> iterator = iterator();
@@ -195,7 +104,7 @@ public boolean hasMultipleResults() {
@Override
public String toString() {
- return String.format("%s - %s", jobResultEvaluationMode, qualityGateEvaluationMode);
+ return String.format("%s - %s", baseline.getFullDisplayName(), selector);
}
@Override
@@ -221,7 +130,7 @@ private static class AnalysisResultIterator implements Iterator baseline, final ResultSelector selector) {
- cursor = getRunWithResult(baseline, selector, IGNORE_QUALITY_GATE, IGNORE_JOB_RESULT);
+ cursor = getRunWithResult(baseline, selector);
this.selector = selector;
}
@@ -236,7 +145,7 @@ public BuildResult next() {
Run, ?> run = cursor.get();
Optional resultAction = selector.get(run);
- cursor = getRunWithResult(run.getPreviousBuild(), selector, IGNORE_QUALITY_GATE, IGNORE_JOB_RESULT);
+ cursor = getRunWithResult(run.getPreviousBuild(), selector);
if (resultAction.isPresent()) {
return new BuildResult<>(new JenkinsBuild(run), resultAction.get().getResult());
diff --git a/plugin/src/main/java/io/jenkins/plugins/analysis/core/model/QualityGateEvaluationMode.java b/plugin/src/main/java/io/jenkins/plugins/analysis/core/model/QualityGateEvaluationMode.java
new file mode 100644
index 0000000000..5590484eef
--- /dev/null
+++ b/plugin/src/main/java/io/jenkins/plugins/analysis/core/model/QualityGateEvaluationMode.java
@@ -0,0 +1,16 @@
+package io.jenkins.plugins.analysis.core.model;
+
+/**
+ * Determines how the evaluation of the quality gates is taken into account when the previous result is searched for.
+ */
+public enum QualityGateEvaluationMode {
+ /**
+ * The quality gate result is ignored. The previous build with results of the same type is selected.
+ */
+ IGNORE_QUALITY_GATE,
+ /**
+ * The quality gate result must be successful. I.e., the history is searched for a build that either passed the
+ * quality gate or has deactivated the quality gate.
+ */
+ SUCCESSFUL_QUALITY_GATE
+}
diff --git a/plugin/src/main/java/io/jenkins/plugins/analysis/core/steps/IssuesPublisher.java b/plugin/src/main/java/io/jenkins/plugins/analysis/core/steps/IssuesPublisher.java
index 4b1cf57379..8c5d2e5b74 100644
--- a/plugin/src/main/java/io/jenkins/plugins/analysis/core/steps/IssuesPublisher.java
+++ b/plugin/src/main/java/io/jenkins/plugins/analysis/core/steps/IssuesPublisher.java
@@ -12,13 +12,10 @@
import io.jenkins.plugins.analysis.core.model.AggregationAction;
import io.jenkins.plugins.analysis.core.model.AnalysisHistory;
-import io.jenkins.plugins.analysis.core.model.AnalysisHistory.JobResultEvaluationMode;
-import io.jenkins.plugins.analysis.core.model.AnalysisHistory.QualityGateEvaluationMode;
import io.jenkins.plugins.analysis.core.model.AnalysisResult;
import io.jenkins.plugins.analysis.core.model.ByIdResultSelector;
import io.jenkins.plugins.analysis.core.model.DeltaReport;
-import io.jenkins.plugins.analysis.core.model.History;
-import io.jenkins.plugins.analysis.core.model.NullAnalysisHistory;
+import io.jenkins.plugins.analysis.core.model.QualityGateEvaluationMode;
import io.jenkins.plugins.analysis.core.model.ResetReferenceAction;
import io.jenkins.plugins.analysis.core.model.ResultAction;
import io.jenkins.plugins.analysis.core.model.ResultSelector;
@@ -26,13 +23,13 @@
import io.jenkins.plugins.analysis.core.util.TrendChartType;
import io.jenkins.plugins.analysis.core.util.WarningsQualityGate;
import io.jenkins.plugins.analysis.core.util.WarningsQualityGateEvaluator;
+import io.jenkins.plugins.forensics.reference.ReferenceBuild;
import io.jenkins.plugins.forensics.reference.ReferenceFinder;
import io.jenkins.plugins.util.LogHandler;
import io.jenkins.plugins.util.QualityGateResult;
import io.jenkins.plugins.util.ResultHandler;
-import static io.jenkins.plugins.analysis.core.model.AnalysisHistory.JobResultEvaluationMode.*;
-import static io.jenkins.plugins.analysis.core.model.AnalysisHistory.QualityGateEvaluationMode.*;
+import static io.jenkins.plugins.analysis.core.model.QualityGateEvaluationMode.*;
/**
* Publishes issues: Stores the created issues in an {@link AnalysisResult}. The result is attached to the {@link Run}
@@ -49,7 +46,6 @@ class IssuesPublisher {
private final Charset sourceCodeEncoding;
private final List qualityGates;
private final QualityGateEvaluationMode qualityGateEvaluationMode;
- private final JobResultEvaluationMode jobResultEvaluationMode;
private final LogHandler logger;
private final ResultHandler notifier;
private final boolean failOnErrors;
@@ -57,9 +53,8 @@ class IssuesPublisher {
@SuppressWarnings("ParameterNumber")
IssuesPublisher(final Run, ?> run, final AnnotatedReport report,
final HealthDescriptor healthDescriptor, final List qualityGates,
- final String name, final boolean ignoreQualityGate, final boolean ignoreFailedBuilds,
- final Charset sourceCodeEncoding, final LogHandler logger,
- final ResultHandler notifier, final boolean failOnErrors) {
+ final String name, final boolean ignoreQualityGate, final Charset sourceCodeEncoding,
+ final LogHandler logger, final ResultHandler notifier, final boolean failOnErrors) {
this.report = report;
this.run = run;
this.healthDescriptor = healthDescriptor;
@@ -67,7 +62,6 @@ class IssuesPublisher {
this.sourceCodeEncoding = sourceCodeEncoding;
this.qualityGates = qualityGates;
qualityGateEvaluationMode = ignoreQualityGate ? IGNORE_QUALITY_GATE : SUCCESSFUL_QUALITY_GATE;
- jobResultEvaluationMode = ignoreFailedBuilds ? NO_JOB_FAILURE : IGNORE_JOB_RESULT;
this.logger = logger;
this.notifier = notifier;
this.failOnErrors = failOnErrors;
@@ -87,17 +81,8 @@ private String getId() {
* @return the created result action
*/
ResultAction attachAction(final TrendChartType trendChartType) {
- ResultSelector selector = ensureThatIdIsUnique();
-
Report issues = report.getReport();
- var history = createAnalysisHistory(selector, issues);
- DeltaReport deltaReport;
- if (history.getBuild().isPresent()) {
- deltaReport = new DeltaReport(issues, history.getBuild().get(), run.getNumber(), history.getIssues());
- }
- else {
- deltaReport = new DeltaReport(issues, run.getNumber());
- }
+ var deltaReport = computeDelta(issues);
QualityGateResult qualityGateResult = evaluateQualityGate(issues, deltaReport);
reportHealth(issues);
@@ -121,7 +106,7 @@ ResultAction attachAction(final TrendChartType trendChartType) {
logger.logInfoMessages(issues.getInfoMessages());
logger.logErrorMessages(issues.getErrorMessages());
- AnalysisResult result = new AnalysisHistory(run, selector).getResult()
+ AnalysisResult result = new AnalysisHistory(run, ensureThatIdIsUnique()).getResult()
.map(previous -> new AnalysisResult(run, getId(), deltaReport, report.getBlames(),
report.getStatistics(), qualityGateResult, report.getSizeOfOrigin(),
previous))
@@ -138,6 +123,20 @@ ResultAction attachAction(final TrendChartType trendChartType) {
return action;
}
+ private DeltaReport computeDelta(final Report issues) {
+ ResultSelector selector = ensureThatIdIsUnique();
+ var possibleReferenceBuild = findReferenceBuild(selector, issues);
+ if (possibleReferenceBuild.isPresent()) {
+ Run, ?> build = possibleReferenceBuild.get();
+ var resultAction = selector.get(build)
+ .orElseThrow(() -> new IllegalStateException("Reference build does not contain a result action"));
+ return new DeltaReport(issues, build, run.getNumber(), resultAction.getResult().getIssues());
+ }
+ else {
+ return new DeltaReport(issues, run.getNumber());
+ }
+ }
+
private ResultSelector ensureThatIdIsUnique() {
ResultSelector selector = new ByIdResultSelector(getId());
Optional other = selector.get(run);
@@ -170,22 +169,67 @@ private QualityGateResult evaluateQualityGate(final Report issues, final DeltaRe
return qualityGateStatus;
}
- private History createAnalysisHistory(final ResultSelector selector, final Report issues) {
- var reference = findReference(issues);
+ private Optional> findReferenceBuild(final ResultSelector selector, final Report logger) {
+ FilteredLog log = new FilteredLog("Errors while resolving the reference build:");
+ var reference = new ReferenceFinder().findReference(run, log);
+ logger.mergeLogMessages(log);
+
if (reference.isPresent()) {
- return new AnalysisHistory(reference.get(), selector,
- determineQualityGateEvaluationMode(issues), jobResultEvaluationMode);
+ return refineReferenceBasedOnQualityGate(selector, logger, reference.get());
}
- else {
- return new NullAnalysisHistory();
+ return Optional.empty();
+ }
+
+ private Optional> refineReferenceBasedOnQualityGate(final ResultSelector selector, final Report issues,
+ final Run, ?> reference) {
+ boolean isSkipped = false;
+ var gateEvaluationMode = determineQualityGateEvaluationMode(issues);
+ for (Run, ?> r = reference; r != null; r = r.getPreviousBuild()) {
+ var result = r.getResult();
+ if (result != null && result.isBetterOrEqualTo(getRequiredResult())) {
+ var displayName = r.getFullDisplayName();
+ Optional action = selector.get(r);
+ if (action.isPresent()) {
+ ResultAction resultAction = action.get();
+ if (resultAction.isSuccessful()) {
+ issues.logInfo(
+ "Quality gate successful for reference build '%s', using this build as reference",
+ displayName);
+ return Optional.of(r);
+ }
+ if (gateEvaluationMode == IGNORE_QUALITY_GATE) {
+ issues.logInfo(
+ "Quality gate has been missed for reference build '%s', but is configured to be ignored",
+ displayName);
+ return Optional.of(r);
+ }
+ if (!isSkipped) {
+ issues.logInfo("Quality gate failed for reference build '%s', analyzing previous builds",
+ displayName);
+ isSkipped = true;
+ }
+ }
+ else {
+ if (!isSkipped) {
+ issues.logInfo(
+ "Reference build '%s' does not contain a result action, analyzing previous builds",
+ displayName);
+ isSkipped = true;
+ }
+ }
+ }
}
+ issues.logInfo("No reference build with successful quality gate found, skipping delta computation");
+
+ return Optional.empty();
}
- private Optional> findReference(final Report issues) {
- FilteredLog log = new FilteredLog("Errors while resolving the reference build:");
- Optional> reference = new ReferenceFinder().findReference(run, log);
- issues.mergeLogMessages(log);
- return reference;
+ private Result getRequiredResult() {
+ ReferenceBuild action = run.getAction(ReferenceBuild.class);
+ if (action == null) {
+ return Result.UNSTABLE;
+ }
+ return action.getRequiredResult();
}
private QualityGateEvaluationMode determineQualityGateEvaluationMode(final Report filtered) {
diff --git a/plugin/src/main/java/io/jenkins/plugins/analysis/core/steps/IssuesRecorder.java b/plugin/src/main/java/io/jenkins/plugins/analysis/core/steps/IssuesRecorder.java
index a4c454f258..914670ff27 100644
--- a/plugin/src/main/java/io/jenkins/plugins/analysis/core/steps/IssuesRecorder.java
+++ b/plugin/src/main/java/io/jenkins/plugins/analysis/core/steps/IssuesRecorder.java
@@ -97,7 +97,6 @@ public class IssuesRecorder extends Recorder {
private SourceCodeRetention sourceCodeRetention = SourceCodeRetention.EVERY_BUILD;
private boolean ignoreQualityGate = false; // by default, a successful quality gate is mandatory;
- private boolean ignoreFailedBuilds = true; // by default, failed builds are ignored;
private boolean failOnError = false;
@@ -511,24 +510,6 @@ public boolean getIgnoreQualityGate() {
return ignoreQualityGate;
}
- /**
- * If {@code true}, then only successful or unstable reference builds will be considered. This option is enabled by
- * default, since analysis results might be inaccurate if the build failed. If {@code false}, every build that
- * contains a static analysis result is considered, even if the build failed.
- *
- * @param ignoreFailedBuilds
- * if {@code true} then a stable build is used as reference
- */
- @DataBoundSetter
- public void setIgnoreFailedBuilds(final boolean ignoreFailedBuilds) {
- this.ignoreFailedBuilds = ignoreFailedBuilds;
- }
-
- @SuppressWarnings("PMD.BooleanGetMethodName")
- public boolean getIgnoreFailedBuilds() {
- return ignoreFailedBuilds;
- }
-
public int getHealthy() {
return healthy;
}
@@ -747,8 +728,7 @@ AnalysisResult publishResult(final Run, ?> run, final TaskListener listener, f
IssuesPublisher publisher = new IssuesPublisher(run, annotatedReport,
new HealthDescriptor(healthy, unhealthy, minimumSeverity), qualityGates,
- reportName, ignoreQualityGate, ignoreFailedBuilds,
- getSourceCodeCharset(), logHandler, resultHandler, failOnError);
+ reportName, ignoreQualityGate, getSourceCodeCharset(), logHandler, resultHandler, failOnError);
ResultAction action = publisher.attachAction(trendChartType);
if (!skipPublishingChecks) {
diff --git a/plugin/src/main/java/io/jenkins/plugins/analysis/core/steps/PublishIssuesStep.java b/plugin/src/main/java/io/jenkins/plugins/analysis/core/steps/PublishIssuesStep.java
index 2f41e08ceb..c49e45d372 100644
--- a/plugin/src/main/java/io/jenkins/plugins/analysis/core/steps/PublishIssuesStep.java
+++ b/plugin/src/main/java/io/jenkins/plugins/analysis/core/steps/PublishIssuesStep.java
@@ -55,9 +55,6 @@ public class PublishIssuesStep extends Step implements Serializable {
private String sourceCodeEncoding = StringUtils.EMPTY;
private boolean ignoreQualityGate = false; // by default, a successful quality gate is mandatory
- private boolean ignoreFailedBuilds = true; // by default, failed builds are ignored
- private String referenceJobName = StringUtils.EMPTY;
- private final String referenceBuildId = StringUtils.EMPTY;
private boolean failOnError = false; // by default, it should not fail on error
private boolean skipPublishingChecks; // by default, warnings should be published to SCM platforms
@@ -203,25 +200,6 @@ public boolean getIgnoreQualityGate() {
return ignoreQualityGate;
}
- /**
- * If {@code true}, then only successful or unstable reference builds will be considered. This option is enabled by
- * default, since analysis results might be inaccurate if the build failed. If {@code false}, every build that
- * contains a static analysis result is considered, even if the build failed.
- *
- * @param ignoreFailedBuilds
- * if {@code true} then a stable build is used as reference
- */
- @DataBoundSetter
- @SuppressWarnings("unused") // Used by Stapler
- public void setIgnoreFailedBuilds(final boolean ignoreFailedBuilds) {
- this.ignoreFailedBuilds = ignoreFailedBuilds;
- }
-
- @SuppressWarnings({"PMD.BooleanGetMethodName", "WeakerAccess"})
- public boolean getIgnoreFailedBuilds() {
- return ignoreFailedBuilds;
- }
-
/**
* If {@code true}, then logger content is muted
* If {@code false}, then logger content goes to loghandler output.
@@ -239,20 +217,6 @@ public boolean isQuiet() {
return quiet;
}
- /**
- * Sets the reference job to get the results for the issue difference computation.
- *
- * @param referenceJobName
- * the name of reference job
- */
- @DataBoundSetter
- public void setReferenceJobName(final String referenceJobName) {
- if (IssuesRecorder.NO_REFERENCE_DEFINED.equals(referenceJobName)) {
- this.referenceJobName = StringUtils.EMPTY;
- }
- this.referenceJobName = referenceJobName;
- }
-
@CheckForNull
public String getSourceCodeEncoding() {
return sourceCodeEncoding;
@@ -411,8 +375,7 @@ protected ResultAction run() throws IOException, InterruptedException, IllegalSt
IssuesPublisher publisher = new IssuesPublisher(getRun(), report,
new HealthDescriptor(step.getHealthy(), step.getUnhealthy(),
step.getMinimumSeverityAsSeverity()), step.getQualityGates(),
- StringUtils.defaultString(step.getName()),
- step.getIgnoreQualityGate(), step.getIgnoreFailedBuilds(),
+ StringUtils.defaultString(step.getName()), step.getIgnoreQualityGate(),
getCharset(step.getSourceCodeEncoding()), getLogger(report), notifier, step.getFailOnError());
ResultAction action = publisher.attachAction(step.getTrendChartType());
diff --git a/plugin/src/main/java/io/jenkins/plugins/analysis/core/steps/RecordIssuesStep.java b/plugin/src/main/java/io/jenkins/plugins/analysis/core/steps/RecordIssuesStep.java
index cdc98e808a..9782affe61 100644
--- a/plugin/src/main/java/io/jenkins/plugins/analysis/core/steps/RecordIssuesStep.java
+++ b/plugin/src/main/java/io/jenkins/plugins/analysis/core/steps/RecordIssuesStep.java
@@ -74,8 +74,6 @@ public class RecordIssuesStep extends Step implements Serializable {
private SourceCodeRetention sourceCodeRetention = SourceCodeRetention.EVERY_BUILD;
private boolean ignoreQualityGate = false; // by default, a successful quality gate is mandatory;
- private boolean ignoreFailedBuilds = true; // by default, failed builds are ignored;
- private final String referenceBuildId = StringUtils.EMPTY;
private int healthy;
private int unhealthy;
@@ -470,24 +468,6 @@ public boolean getIgnoreQualityGate() {
return ignoreQualityGate;
}
- /**
- * If {@code true}, then only successful or unstable reference builds will be considered. This option is enabled by
- * default, since analysis results might be inaccurate if the build failed. If {@code false}, every build that
- * contains a static analysis result is considered, even if the build failed.
- *
- * @param ignoreFailedBuilds
- * if {@code true} then a stable build is used as reference
- */
- @DataBoundSetter
- public void setIgnoreFailedBuilds(final boolean ignoreFailedBuilds) {
- this.ignoreFailedBuilds = ignoreFailedBuilds;
- }
-
- @SuppressWarnings("PMD.BooleanGetMethodName")
- public boolean getIgnoreFailedBuilds() {
- return ignoreFailedBuilds;
- }
-
/**
* Determines whether to fail the step on errors during the step of recording issues.
*
@@ -602,7 +582,6 @@ protected List run() throws IOException, InterruptedException {
recorder.setTools(step.getTools());
recorder.setSourceCodeEncoding(step.getSourceCodeEncoding());
recorder.setIgnoreQualityGate(step.getIgnoreQualityGate());
- recorder.setIgnoreFailedBuilds(step.getIgnoreFailedBuilds());
recorder.setHealthy(step.getHealthy());
recorder.setUnhealthy(step.getUnhealthy());
recorder.setMinimumSeverity(step.getMinimumSeverity());
diff --git a/plugin/src/test/java/io/jenkins/plugins/analysis/core/model/AnalysisHistoryTest.java b/plugin/src/test/java/io/jenkins/plugins/analysis/core/model/AnalysisHistoryTest.java
index 07036d88d0..2c0dd1143a 100644
--- a/plugin/src/test/java/io/jenkins/plugins/analysis/core/model/AnalysisHistoryTest.java
+++ b/plugin/src/test/java/io/jenkins/plugins/analysis/core/model/AnalysisHistoryTest.java
@@ -15,16 +15,12 @@
import hudson.model.Result;
import hudson.model.Run;
-import io.jenkins.plugins.analysis.core.model.AnalysisHistory.JobResultEvaluationMode;
-import io.jenkins.plugins.analysis.core.model.AnalysisHistory.QualityGateEvaluationMode;
import io.jenkins.plugins.analysis.core.util.WarningsQualityGate;
import io.jenkins.plugins.analysis.core.util.WarningsQualityGate.QualityGateType;
import io.jenkins.plugins.util.QualityGate.QualityGateCriticality;
import io.jenkins.plugins.util.QualityGateResult;
import io.jenkins.plugins.util.QualityGateStatus;
-import static io.jenkins.plugins.analysis.core.model.AnalysisHistory.JobResultEvaluationMode.*;
-import static io.jenkins.plugins.analysis.core.model.AnalysisHistory.QualityGateEvaluationMode.*;
import static io.jenkins.plugins.analysis.core.model.AnalysisHistoryTest.ExpectedResult.*;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;
@@ -122,41 +118,14 @@ void baselineResultIsPreviousResultIfAlreadySet() {
@DisplayName("Ignore job result + ignore quality gate -> history with one previous build")
void shouldTestFirstIterationOfLoopIgnoreStatusAndResult(final String name,
final ExpectedResult expectedResult, final QualityGateResult qualityGateStatus, final Result jobStatus) {
- runTest(IGNORE_QUALITY_GATE, IGNORE_JOB_RESULT, qualityGateStatus, jobStatus, expectedResult);
+ runTest(qualityGateStatus, jobStatus, expectedResult);
}
- @ParameterizedTest(name = "{0}")
- @MethodSource("createTestDataForIgnoredQualityGateAndNoFailedBuild")
- @DisplayName("No job failure + ignore quality gate -> history with one previous build")
- void shouldTestFirstIterationOfLoopIgnoreStatus(final String name,
- final ExpectedResult expectedResult, final QualityGateResult qualityGateStatus, final Result jobStatus) {
- runTest(IGNORE_QUALITY_GATE, NO_JOB_FAILURE, qualityGateStatus, jobStatus, expectedResult);
- }
-
- @ParameterizedTest(name = "{0}")
- @MethodSource("createTestDataForSuccessfulQualityGateAndIgnoredBuildResult")
- @DisplayName("Ignore job result + successful quality gate -> history with one previous build")
- void shouldTestFirstIterationOfLoopIgnoreResult(final String name,
- final ExpectedResult expectedResult, final QualityGateResult qualityGateStatus, final Result jobStatus) {
- runTest(SUCCESSFUL_QUALITY_GATE, IGNORE_JOB_RESULT, qualityGateStatus, jobStatus, expectedResult);
- }
-
- @ParameterizedTest(name = "{0}")
- @MethodSource("createTestDataForSuccessfulQualityGateAndNoFailedBuild")
- @DisplayName("No job failure + successful quality gate -> history with one previous build")
- void shouldTestFirstIterationOfLoop(final String name,
- final ExpectedResult expectedResult, final QualityGateResult qualityGateStatus, final Result jobStatus) {
- runTest(SUCCESSFUL_QUALITY_GATE, NO_JOB_FAILURE, qualityGateStatus, jobStatus, expectedResult);
- }
-
- private void runTest(final QualityGateEvaluationMode qualityGateEvaluationMode,
- final JobResultEvaluationMode jobResultEvaluationMode,
- final QualityGateResult qualityGateStatus, final Result jobStatus, final ExpectedResult expectedResult) {
+ private void runTest(final QualityGateResult qualityGateStatus, final Result jobStatus, final ExpectedResult expectedResult) {
ResultSelector resultSelector = mock(ResultSelector.class);
Run, ?> baseline = createBuild(qualityGateStatus, jobStatus, resultSelector);
- AnalysisHistory history = new AnalysisHistory(baseline, resultSelector, qualityGateEvaluationMode,
- jobResultEvaluationMode);
+ AnalysisHistory history = new AnalysisHistory(baseline, resultSelector);
if (expectedResult == NONE) {
assertThat(history.getResult()).isEmpty();
diff --git a/plugin/src/test/java/io/jenkins/plugins/analysis/warnings/integrations/JobDslITest.java b/plugin/src/test/java/io/jenkins/plugins/analysis/warnings/integrations/JobDslITest.java
index b06aa1c561..88d864ca8f 100644
--- a/plugin/src/test/java/io/jenkins/plugins/analysis/warnings/integrations/JobDslITest.java
+++ b/plugin/src/test/java/io/jenkins/plugins/analysis/warnings/integrations/JobDslITest.java
@@ -59,7 +59,6 @@ void shouldCreateFreestyleJobUsingJobDslAndVerifyIssueRecorderWithDefaultConfigu
assertThat(recorder.getEnabledForFailure()).isFalse();
assertThat(recorder.getHealthy()).isEqualTo(0);
assertThat(recorder.getId()).isNull();
- assertThat(recorder.getIgnoreFailedBuilds()).isTrue();
assertThat(recorder.getIgnoreQualityGate()).isFalse();
assertThat(recorder.getMinimumSeverity()).isEqualTo("LOW");
assertThat(recorder.getName()).isNull();
@@ -101,7 +100,6 @@ void shouldCreateFreestyleJobUsingJobDslAndVerifyIssueRecorderWithValuesSet() {
assertThat(recorder.getEnabledForFailure()).isTrue();
assertThat(recorder.getHealthy()).isEqualTo(10);
assertThat(recorder.getId()).isEqualTo("test-id");
- assertThat(recorder.getIgnoreFailedBuilds()).isFalse();
assertThat(recorder.getIgnoreQualityGate()).isTrue();
assertThat(recorder.isSkipPublishingChecks()).isTrue();
assertThat(recorder.getMinimumSeverity()).isEqualTo("ERROR");
diff --git a/plugin/src/test/java/io/jenkins/plugins/analysis/warnings/steps/ReferenceFinderITest.java b/plugin/src/test/java/io/jenkins/plugins/analysis/warnings/steps/ReferenceFinderITest.java
index b2beaeb0c1..cafceae608 100644
--- a/plugin/src/test/java/io/jenkins/plugins/analysis/warnings/steps/ReferenceFinderITest.java
+++ b/plugin/src/test/java/io/jenkins/plugins/analysis/warnings/steps/ReferenceFinderITest.java
@@ -4,6 +4,7 @@
import java.util.Optional;
import java.util.function.Consumer;
+import org.apache.commons.lang3.StringUtils;
import org.junit.jupiter.api.Test;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
@@ -68,7 +69,8 @@ void shouldUseOtherJobAsReference() {
assertThat(getConsoleLog(result)).contains(
"[ReferenceFinder] Configured reference job: 'reference'",
- "[ReferenceFinder] Found reference build '#1' of reference job 'reference'",
+ "[ReferenceFinder] Found last completed build '#1' of reference job 'reference'",
+ "[ReferenceFinder] -> Build '#1' has a result SUCCESS",
"Obtaining reference build from reference recorder",
"-> Found 'reference #1'");
}
@@ -101,12 +103,12 @@ void shouldHandleMissingJobBuildAsReference() {
}
/**
- * Checks if the reference will be reset just for one build.
+ * Checks if the reference is reset just for one build.
*/
@Test
void shouldResetReference() {
// #1 SUCCESS
- FreeStyleProject project = createReferenceJob();
+ FreeStyleProject project = createEmptyReferenceJob();
enableWarnings(project, recorder -> recorder.setQualityGates(List.of(
new WarningsQualityGate(3, QualityGateType.NEW, QualityGateCriticality.UNSTABLE))));
scheduleBuildAndAssertStatus(project, Result.SUCCESS,
@@ -171,7 +173,7 @@ void shouldResetReference() {
@Test
void shouldCreateSuccessResultWithIgnoredUnstableInBetween() {
// #1 SUCCESS
- FreeStyleProject project = createReferenceJob();
+ FreeStyleProject project = createEmptyReferenceJob();
enableWarnings(project, recorder -> recorder.setQualityGates(List.of(
new WarningsQualityGate(3, QualityGateType.NEW, QualityGateCriticality.UNSTABLE))));
Run, ?> expectedReference = scheduleBuildAndAssertStatus(project, Result.SUCCESS,
@@ -199,22 +201,18 @@ void shouldCreateSuccessResultWithIgnoredUnstableInBetween() {
.hasReferenceBuild(Optional.of(expectedReference)));
}
- private FreeStyleProject createReferenceJob() {
- return createJob(JOB_NAME, "eclipse2Warnings.txt");
- }
-
private void createResetAction(final Run, ?> unstable, final String id) {
ResetQualityGateCommand resetCommand = new ResetQualityGateCommand();
resetCommand.resetReferenceBuild(unstable, id);
}
/**
- * Checks if the reference is taken from the last successful build and therefore returns an unstable in the end.
+ * Checks if the reference is taken from the last successful build and therefore returns an unstable build in the end.
*/
@Test
void shouldCreateUnstableResultWithIgnoredUnstableInBetween() {
// #1 SUCCESS
- FreeStyleProject project = createReferenceJob();
+ FreeStyleProject project = createEmptyReferenceJob();
enableWarnings(project, recorder -> recorder.setQualityGates(List.of(
new WarningsQualityGate(3, QualityGateType.NEW, QualityGateCriticality.UNSTABLE))));
Run, ?> expectedReference = scheduleBuildAndAssertStatus(project, Result.SUCCESS,
@@ -244,7 +242,7 @@ void shouldCreateUnstableResultWithIgnoredUnstableInBetween() {
@Test
void shouldCreateSuccessResultWithNotIgnoredUnstableInBetween() {
// #1 SUCCESS
- FreeStyleProject project = createReferenceJob();
+ FreeStyleProject project = createEmptyReferenceJob();
enableWarnings(project, recorder -> {
recorder.setIgnoreQualityGate(true);
recorder.setQualityGates(List.of(
@@ -272,12 +270,12 @@ void shouldCreateSuccessResultWithNotIgnoredUnstableInBetween() {
}
/**
- * Checks if the reference ignores the quality gate status and therefore returns an unstable in the end.
+ * Checks if the reference ignores the quality gate status and therefore returns an unstable build in the end.
*/
@Test
void shouldCreateUnstableResultWithNotIgnoredUnstableInBetween() {
// #1 INACTIVE
- FreeStyleProject project = createJob(JOB_NAME, "eclipse6Warnings.txt");
+ FreeStyleProject project = createEmptyReferenceJob(JOB_NAME, "eclipse6Warnings.txt");
IssuesRecorder issuesRecorder = enableWarnings(project, recorder -> recorder.setIgnoreQualityGate(true));
scheduleBuildAndAssertStatus(project, Result.SUCCESS,
analysisResult -> assertThat(analysisResult).hasTotalSize(6)
@@ -312,9 +310,8 @@ void shouldCreateUnstableResultWithNotIgnoredUnstableInBetween() {
@Test
void shouldCreateUnstableResultWithOverAllMustBeSuccess() {
// #1 SUCCESS
- FreeStyleProject project = createReferenceJob();
+ FreeStyleProject project = createEmptyReferenceJob();
enableWarnings(project, recorder -> {
- recorder.setIgnoreFailedBuilds(true);
recorder.setEnabledForFailure(true);
recorder.setQualityGates(List.of(
new WarningsQualityGate(3, QualityGateType.NEW, QualityGateCriticality.UNSTABLE)));
@@ -344,14 +341,13 @@ void shouldCreateUnstableResultWithOverAllMustBeSuccess() {
/**
* Checks if the reference only looks at complete success builds instead of just looking at the eclipse result.
- * Should return an success result.
+ * Should return a success result.
*/
@Test
void shouldCreateSuccessResultWithOverAllMustBeSuccess() {
// #1 SUCCESS
- FreeStyleProject project = createJob(JOB_NAME, "eclipse4Warnings.txt");
+ FreeStyleProject project = createEmptyReferenceJob(JOB_NAME, "eclipse4Warnings.txt");
IssuesRecorder issuesRecorder = enableWarnings(project, recorder -> {
- recorder.setIgnoreFailedBuilds(true);
recorder.setEnabledForFailure(true);
});
Run, ?> expectedReference = scheduleBuildAndAssertStatus(project, Result.SUCCESS,
@@ -386,9 +382,8 @@ void shouldCreateSuccessResultWithOverAllMustBeSuccess() {
@Test
void shouldCreateUnstableResultWithOverAllMustNotBeSuccess() {
// #1 SUCCESS
- FreeStyleProject project = createJob(JOB_NAME, "eclipse4Warnings.txt");
+ FreeStyleProject project = createJob(JOB_NAME, "eclipse4Warnings.txt", Result.FAILURE, StringUtils.EMPTY);
IssuesRecorder issuesRecorder = enableWarnings(project, recorder -> {
- recorder.setIgnoreFailedBuilds(false);
recorder.setEnabledForFailure(true);
});
scheduleBuildAndAssertStatus(project, Result.SUCCESS,
@@ -418,15 +413,14 @@ void shouldCreateUnstableResultWithOverAllMustNotBeSuccess() {
}
/**
- * Checks if the reference only looks at the eclipse result of a build and not the overall success. Should return an
+ * Checks if the reference only looks at the eclipse result of a build and not the overall success. Should return a
* success result.
*/
@Test
void shouldCreateSuccessResultWithOverAllMustNotBeSuccess() {
// #1 SUCCESS
- FreeStyleProject project = createReferenceJob();
+ FreeStyleProject project = createEmptyReferenceJob(Result.FAILURE);
enableWarnings(project, recorder -> {
- recorder.setIgnoreFailedBuilds(false);
recorder.setEnabledForFailure(true);
recorder.setQualityGates(List.of(
new WarningsQualityGate(3, QualityGateType.NEW, QualityGateCriticality.UNSTABLE)));
@@ -461,7 +455,7 @@ void shouldCreateSuccessResultWithOverAllMustNotBeSuccess() {
@Test
void shouldCreateSuccessResultWithIgnoredUnstableInBetweenWithReferenceBuild() {
// #1 SUCCESS
- FreeStyleProject reference = createJob(REFERENCE_JOB_NAME, "eclipse2Warnings.txt");
+ FreeStyleProject reference = createEmptyReferenceJob(REFERENCE_JOB_NAME, "eclipse2Warnings.txt");
enableWarnings(reference,
recorder -> recorder.setQualityGates(List.of(
new WarningsQualityGate(3, QualityGateType.NEW, QualityGateCriticality.UNSTABLE))));
@@ -478,7 +472,7 @@ void shouldCreateSuccessResultWithIgnoredUnstableInBetweenWithReferenceBuild() {
.hasQualityGateStatus(QualityGateStatus.WARNING));
// #1 SUCCESS (Reference #1)
- FreeStyleProject project = createJob(JOB_NAME, "eclipse4Warnings.txt");
+ FreeStyleProject project = createJob(JOB_NAME, "eclipse4Warnings.txt", Result.SUCCESS, REFERENCE_JOB_NAME);
enableWarnings(project, recorder -> {
recorder.setQualityGates(List.of(
@@ -494,13 +488,13 @@ void shouldCreateSuccessResultWithIgnoredUnstableInBetweenWithReferenceBuild() {
}
/**
- * Checks if the reference is taken from the last successful build and therefore returns an unstable in the end.
+ * Checks if the reference is taken from the last successful build and therefore returns an unstable build in the end.
* Uses a different freestyle project for the reference.
*/
@Test
void shouldCreateUnstableResultWithIgnoredUnstableInBetweenWithReferenceBuild() {
// #1 SUCCESS
- FreeStyleProject reference = createJob(REFERENCE_JOB_NAME, "eclipse2Warnings.txt");
+ FreeStyleProject reference = createEmptyReferenceJob(REFERENCE_JOB_NAME, "eclipse2Warnings.txt");
enableWarnings(reference, recorder -> {
recorder.setQualityGates(List.of(
new WarningsQualityGate(3, QualityGateType.NEW, QualityGateCriticality.UNSTABLE)));
@@ -519,7 +513,7 @@ void shouldCreateUnstableResultWithIgnoredUnstableInBetweenWithReferenceBuild()
.hasQualityGateStatus(QualityGateStatus.WARNING));
// #1 SUCCESS (Reference #1)
- FreeStyleProject project = createJob(JOB_NAME, "eclipse8Warnings.txt");
+ FreeStyleProject project = createEmptyReferenceJob(JOB_NAME, "eclipse8Warnings.txt");
enableWarnings(project, recorder -> {
recorder.setQualityGates(List.of(
@@ -541,7 +535,7 @@ void shouldCreateUnstableResultWithIgnoredUnstableInBetweenWithReferenceBuild()
@Test
void shouldCreateSuccessResultWithNotIgnoredUnstableInBetweenWithReferenceBuild() {
// #1 SUCCESS
- FreeStyleProject reference = createJob(REFERENCE_JOB_NAME, "eclipse2Warnings.txt");
+ FreeStyleProject reference = createEmptyReferenceJob(REFERENCE_JOB_NAME, "eclipse2Warnings.txt");
enableWarnings(reference, recorder -> {
recorder.setIgnoreQualityGate(true);
recorder.setQualityGates(List.of(
@@ -560,7 +554,7 @@ void shouldCreateSuccessResultWithNotIgnoredUnstableInBetweenWithReferenceBuild(
.hasQualityGateStatus(QualityGateStatus.WARNING)).getOwner();
// #1 SUCCESS (Reference #2)
- FreeStyleProject project = createJob(JOB_NAME, "eclipse8Warnings.txt");
+ FreeStyleProject project = createEmptyReferenceJob(JOB_NAME, "eclipse8Warnings.txt");
enableWarnings(project, recorder -> {
recorder.setQualityGates(List.of(
@@ -575,13 +569,13 @@ void shouldCreateSuccessResultWithNotIgnoredUnstableInBetweenWithReferenceBuild(
}
/**
- * Checks if the reference ignores the result of the last build and therefore returns an unstable in the end. Uses a
+ * Checks if the reference ignores the result of the last build and therefore returns an unstable build in the end. Uses a
* different freestyle project for the reference.
*/
@Test
void shouldCreateUnstableResultWithNotIgnoredUnstableInBetweenWithReferenceBuild() {
// #1 SUCCESS
- FreeStyleProject reference = createJob(REFERENCE_JOB_NAME, "eclipse6Warnings.txt");
+ FreeStyleProject reference = createEmptyReferenceJob(REFERENCE_JOB_NAME, "eclipse6Warnings.txt");
IssuesRecorder issuesRecorder = enableWarnings(reference, recorder -> recorder.setIgnoreQualityGate(true));
scheduleBuildAndAssertStatus(reference, Result.SUCCESS,
analysisResult -> assertThat(analysisResult).hasTotalSize(6)
@@ -599,7 +593,7 @@ void shouldCreateUnstableResultWithNotIgnoredUnstableInBetweenWithReferenceBuild
.hasQualityGateStatus(QualityGateStatus.WARNING)).getOwner();
// #1 SUCCESS (Reference #2)
- FreeStyleProject project = createJob(JOB_NAME, "eclipse8Warnings.txt");
+ FreeStyleProject project = createEmptyReferenceJob(JOB_NAME, "eclipse8Warnings.txt");
enableWarnings(project, recorder -> {
recorder.setQualityGates(List.of(
@@ -621,9 +615,8 @@ void shouldCreateUnstableResultWithNotIgnoredUnstableInBetweenWithReferenceBuild
@Test
void shouldCreateUnstableResultWithOverAllMustBeSuccessWithReferenceBuild() {
// #1 SUCCESS
- FreeStyleProject reference = createJob(REFERENCE_JOB_NAME, "eclipse2Warnings.txt");
+ FreeStyleProject reference = createEmptyReferenceJob(REFERENCE_JOB_NAME, "eclipse2Warnings.txt");
enableWarnings(reference, recorder -> {
- recorder.setIgnoreFailedBuilds(true);
recorder.setEnabledForFailure(true);
recorder.setQualityGates(List.of(
new WarningsQualityGate(3, QualityGateType.NEW, QualityGateCriticality.UNSTABLE)));
@@ -643,12 +636,11 @@ void shouldCreateUnstableResultWithOverAllMustBeSuccessWithReferenceBuild() {
removeBuilder(reference, failureStep);
// #1 SUCCESS (Reference #1)
- FreeStyleProject project = createJob(JOB_NAME, "eclipse6Warnings.txt");
+ FreeStyleProject project = createEmptyReferenceJob(JOB_NAME, "eclipse6Warnings.txt");
enableWarnings(project, recorder -> {
recorder.setQualityGates(List.of(
new WarningsQualityGate(3, QualityGateType.NEW, QualityGateCriticality.UNSTABLE)));
- recorder.setIgnoreFailedBuilds(true);
recorder.setEnabledForFailure(true);
});
scheduleBuildAndAssertStatus(project, Result.UNSTABLE, analysisResult -> assertThat(analysisResult)
@@ -658,6 +650,49 @@ void shouldCreateUnstableResultWithOverAllMustBeSuccessWithReferenceBuild() {
.hasReferenceBuild(Optional.of(expectedReference)));
}
+ /**
+ * Checks if the plugin ignores failed builds if the reference finder is configured accordingly.
+ *
+ * @see #shouldCreateUnstableResultWithOverAllMustBeSuccessWithReferenceBuild
+ */
+ @Test
+ void shouldUseFailedBuildsIfConfigured() {
+ // #1 SUCCESS
+ FreeStyleProject reference = createEmptyReferenceJob(REFERENCE_JOB_NAME, "eclipse2Warnings.txt");
+ enableWarnings(reference, recorder -> {
+ recorder.setEnabledForFailure(true);
+ recorder.setQualityGates(List.of(
+ new WarningsQualityGate(3, QualityGateType.NEW, QualityGateCriticality.UNSTABLE)));
+ });
+ scheduleBuildAndAssertStatus(reference, Result.SUCCESS,
+ analysisResult -> assertThat(analysisResult).hasTotalSize(2)
+ .hasNewSize(0)
+ .hasQualityGateStatus(QualityGateStatus.PASSED));
+
+ // #2 FAILURE
+ cleanAndCopy(reference, "eclipse4Warnings.txt");
+ Builder failureStep = addFailureStep(reference);
+ Run, ?> expectedReference = scheduleBuildAndAssertStatus(reference, Result.FAILURE,
+ analysisResult -> assertThat(analysisResult).hasTotalSize(4)
+ .hasNewSize(2)
+ .hasQualityGateStatus(QualityGateStatus.PASSED)).getOwner();
+ removeBuilder(reference, failureStep);
+
+ // #1 SUCCESS (Reference #1)
+ FreeStyleProject project = createJob(JOB_NAME, "eclipse6Warnings.txt", Result.FAILURE, REFERENCE_JOB_NAME);
+
+ enableWarnings(project, recorder -> {
+ recorder.setQualityGates(List.of(
+ new WarningsQualityGate(2, QualityGateType.NEW, QualityGateCriticality.UNSTABLE)));
+ recorder.setEnabledForFailure(true);
+ });
+ scheduleBuildAndAssertStatus(project, Result.UNSTABLE, analysisResult -> assertThat(analysisResult)
+ .hasTotalSize(6)
+ .hasNewSize(2)
+ .hasQualityGateStatus(QualityGateStatus.WARNING)
+ .hasReferenceBuild(Optional.of(expectedReference)));
+ }
+
/**
* Checks if the reference only looks at complete success builds instead of just looking at the eclipse result.
* Should return a success result. Uses a different freestyle project for the reference.
@@ -665,9 +700,8 @@ void shouldCreateUnstableResultWithOverAllMustBeSuccessWithReferenceBuild() {
@Test
void shouldCreateSuccessResultWithOverAllMustBeSuccessWithReferenceBuild() {
// #1 SUCCESS
- FreeStyleProject reference = createJob(REFERENCE_JOB_NAME, "eclipse4Warnings.txt");
+ FreeStyleProject reference = createEmptyReferenceJob(REFERENCE_JOB_NAME, "eclipse4Warnings.txt");
IssuesRecorder issuesRecorder = enableWarnings(reference, recorder -> {
- recorder.setIgnoreFailedBuilds(true);
recorder.setEnabledForFailure(true);
});
Run, ?> expectedReference = scheduleBuildAndAssertStatus(reference, Result.SUCCESS,
@@ -686,12 +720,11 @@ void shouldCreateSuccessResultWithOverAllMustBeSuccessWithReferenceBuild() {
.hasQualityGateStatus(QualityGateStatus.PASSED));
// #1 SUCCESS (Reference #1)
- FreeStyleProject project = createJob(JOB_NAME, "eclipse6Warnings.txt");
+ FreeStyleProject project = createEmptyReferenceJob(JOB_NAME, "eclipse6Warnings.txt");
enableWarnings(project, recorder -> {
recorder.setQualityGates(List.of(
new WarningsQualityGate(3, QualityGateType.NEW, QualityGateCriticality.UNSTABLE)));
- recorder.setIgnoreFailedBuilds(true);
recorder.setEnabledForFailure(true);
});
scheduleBuildAndAssertStatus(project, Result.SUCCESS,
@@ -708,9 +741,8 @@ void shouldCreateSuccessResultWithOverAllMustBeSuccessWithReferenceBuild() {
@Test
void shouldCreateUnstableResultWithOverAllMustNotBeSuccessWithReferenceBuild() {
// #1 SUCCESS
- FreeStyleProject reference = createJob(REFERENCE_JOB_NAME, "eclipse4Warnings.txt");
+ FreeStyleProject reference = createEmptyReferenceJob(REFERENCE_JOB_NAME, "eclipse4Warnings.txt");
IssuesRecorder issuesRecorder = enableWarnings(reference, recorder -> {
- recorder.setIgnoreFailedBuilds(false);
recorder.setEnabledForFailure(true);
});
scheduleBuildAndAssertStatus(reference, Result.SUCCESS,
@@ -730,12 +762,11 @@ void shouldCreateUnstableResultWithOverAllMustNotBeSuccessWithReferenceBuild() {
removeBuilder(reference, failureStep);
// #1 UNSTABLE (Reference #2)
- FreeStyleProject project = createJob(JOB_NAME, "eclipse6Warnings.txt");
+ FreeStyleProject project = createJob(JOB_NAME, "eclipse6Warnings.txt", Result.FAILURE, REFERENCE_JOB_NAME);
enableWarnings(project, recorder -> {
recorder.setQualityGates(List.of(
new WarningsQualityGate(3, QualityGateType.NEW, QualityGateCriticality.UNSTABLE)));
- recorder.setIgnoreFailedBuilds(false);
recorder.setEnabledForFailure(true);
});
scheduleBuildAndAssertStatus(project, Result.UNSTABLE,
@@ -752,9 +783,8 @@ void shouldCreateUnstableResultWithOverAllMustNotBeSuccessWithReferenceBuild() {
@Test
void shouldCreateSuccessResultWithOverAllMustNotBeSuccessWithReferenceBuild() {
// #1 SUCCESS
- FreeStyleProject reference = createJob(REFERENCE_JOB_NAME, "eclipse2Warnings.txt");
+ FreeStyleProject reference = createJob(REFERENCE_JOB_NAME, "eclipse2Warnings.txt", Result.FAILURE, StringUtils.EMPTY);
enableWarnings(reference, recorder -> {
- recorder.setIgnoreFailedBuilds(false);
recorder.setEnabledForFailure(true);
recorder.setQualityGates(List.of(
new WarningsQualityGate(3, QualityGateType.NEW, QualityGateCriticality.UNSTABLE)));
@@ -775,12 +805,11 @@ void shouldCreateSuccessResultWithOverAllMustNotBeSuccessWithReferenceBuild() {
removeBuilder(reference, failureStep);
// #1 UNSTABLE (Reference #2)
- FreeStyleProject project = createJob(JOB_NAME, "eclipse6Warnings.txt");
+ FreeStyleProject project = createJob(JOB_NAME, "eclipse6Warnings.txt", Result.FAILURE, REFERENCE_JOB_NAME);
enableWarnings(project, recorder -> {
recorder.setQualityGates(List.of(
new WarningsQualityGate(3, QualityGateType.NEW, QualityGateCriticality.UNSTABLE)));
- recorder.setIgnoreFailedBuilds(false);
recorder.setEnabledForFailure(true);
});
scheduleBuildAndAssertStatus(project, Result.SUCCESS,
@@ -813,13 +842,25 @@ private void cleanAndCopy(final FreeStyleProject project, final String fileName)
copyMultipleFilesToWorkspaceWithSuffix(project, fileName);
}
- private FreeStyleProject createJob(final String jobName, final String fileName) {
+ private FreeStyleProject createEmptyReferenceJob() {
+ return createEmptyReferenceJob(Result.UNSTABLE);
+ }
+
+ private FreeStyleProject createEmptyReferenceJob(final Result requiredResult) {
+ return createJob(JOB_NAME, "eclipse2Warnings.txt", requiredResult, StringUtils.EMPTY);
+ }
+
+ private FreeStyleProject createEmptyReferenceJob(final String jobName, final String fileName) {
+ return createJob(jobName, fileName, Result.UNSTABLE, StringUtils.EMPTY);
+ }
+
+ private FreeStyleProject createJob(final String jobName, final String fileName, final Result requiredResult,
+ final String referenceJobName) {
FreeStyleProject job = createProject(FreeStyleProject.class, jobName);
var referenceRecorder = new SimpleReferenceRecorder();
job.getPublishersList().add(referenceRecorder);
- if (!referenceRecorder.equals(REFERENCE_JOB_NAME)) {
- referenceRecorder.setReferenceJob(REFERENCE_JOB_NAME);
- }
+ referenceRecorder.setReferenceJob(referenceJobName);
+ referenceRecorder.setRequiredResult(requiredResult);
copyMultipleFilesToWorkspaceWithSuffix(job, fileName);
return job;
}
diff --git a/plugin/src/test/resources/io/jenkins/plugins/analysis/warnings/integrations/job-dsl-warnings-ng.yaml b/plugin/src/test/resources/io/jenkins/plugins/analysis/warnings/integrations/job-dsl-warnings-ng.yaml
index a51f35a417..1822cf8170 100644
--- a/plugin/src/test/resources/io/jenkins/plugins/analysis/warnings/integrations/job-dsl-warnings-ng.yaml
+++ b/plugin/src/test/resources/io/jenkins/plugins/analysis/warnings/integrations/job-dsl-warnings-ng.yaml
@@ -9,7 +9,6 @@ jobs:
enabledForFailure(true)
quiet(false)
healthy(10)
- ignoreFailedBuilds(false)
ignoreQualityGate(true)
skipPublishingChecks(true)
id('test-id')