Skip to content

Commit

Permalink
[JENKINS-39203] Mark failed publishIssues and recordIssues steps with…
Browse files Browse the repository at this point in the history
… WarningAction

This commit introduces a new Step called RecordIssuesStep that is nearly
identical to IssuesRecorder, but is able to retrieve the current FlowNode via
Pipeline-specific APIs.
  • Loading branch information
dwnusbaum committed May 8, 2019
1 parent f665d55 commit ceb5e58
Show file tree
Hide file tree
Showing 9 changed files with 787 additions and 28 deletions.
18 changes: 9 additions & 9 deletions pom.xml
Expand Up @@ -4,8 +4,8 @@
<parent>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>plugin</artifactId>
<version>3.42</version>
<relativePath />
<version>3.43</version>
<relativePath/>
</parent>

<groupId>io.jenkins.plugins</groupId>
Expand All @@ -25,7 +25,7 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

<!-- Override properties defined in parent POM -->
<jenkins.version>2.121.1</jenkins.version>
<jenkins.version>2.138.4</jenkins.version>
<java.level>8</java.level>
<jenkins-test-harness.version>2.49</jenkins-test-harness.version>

Expand Down Expand Up @@ -61,6 +61,7 @@
<matrix-project.version>1.13</matrix-project.version>
<junit-plugin.version>1.24</junit-plugin.version>
<git-plugin.version>3.9.1</git-plugin.version>
<workflow-api.version>2.34-rc901.34c79c66fab6</workflow-api.version> <!-- TODO: https://github.com/jenkinsci/workflow-api-plugin/pull/91 -->
<workflow-step.version>2.19</workflow-step.version>
<workflow-job.version>2.32</workflow-job.version>
<structs.version>1.17</structs.version>
Expand Down Expand Up @@ -248,6 +249,11 @@
<artifactId>script-security</artifactId>
<version>${script-security.version}</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-api</artifactId>
<version>${workflow-api.version}</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-step-api</artifactId>
Expand Down Expand Up @@ -440,12 +446,6 @@
</dependency>

<!-- Declarative Pipeline -->
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-api</artifactId>
<version>2.33</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-support</artifactId>
Expand Down
Expand Up @@ -17,6 +17,7 @@

import io.jenkins.plugins.analysis.core.model.AnalysisResult;
import io.jenkins.plugins.analysis.core.model.ResultAction;
import io.jenkins.plugins.analysis.core.util.QualityGateStatusHandler;

/**
* Aggregates the {@link AnalysisResult}s of all {@link ResultAction}s of several {@link MatrixRun}s into {@link
Expand Down Expand Up @@ -91,7 +92,8 @@ private void updateMap(final List<ResultAction> actions) {
public boolean endBuild() {
for (Entry<String, List<AnnotatedReport>> reportsPerId : results.entrySet()) {
AnnotatedReport aggregatedReport = new AnnotatedReport(reportsPerId.getKey(), reportsPerId.getValue());
recorder.publishResult(build, listener, Messages.Tool_Default_Name(), aggregatedReport, StringUtils.EMPTY);
recorder.publishResult(build, listener, Messages.Tool_Default_Name(), aggregatedReport, StringUtils.EMPTY,
new QualityGateStatusHandler.SetBuildResultStatusHandler(build));
}
return true;
}
Expand Down
Expand Up @@ -27,6 +27,9 @@
import io.jenkins.plugins.analysis.core.util.LogHandler;
import io.jenkins.plugins.analysis.core.util.QualityGateEvaluator;
import io.jenkins.plugins.analysis.core.util.QualityGateStatus;
import io.jenkins.plugins.analysis.core.util.QualityGateStatusHandler;

import org.jenkinsci.plugins.workflow.graph.FlowNode;

import static io.jenkins.plugins.analysis.core.model.AnalysisHistory.JobResultEvaluationMode.*;
import static io.jenkins.plugins.analysis.core.model.AnalysisHistory.QualityGateEvaluationMode.*;
Expand All @@ -48,12 +51,14 @@ class IssuesPublisher {
private final QualityGateEvaluationMode qualityGateEvaluationMode;
private final JobResultEvaluationMode jobResultEvaluationMode;
private final LogHandler logger;
private final QualityGateStatusHandler qualityGateStatusHandler;

@SuppressWarnings("ParameterNumber")
IssuesPublisher(final Run<?, ?> run, final AnnotatedReport report,
final HealthDescriptor healthDescriptor, final QualityGateEvaluator qualityGate,
final String name, final String referenceJobName, final boolean ignoreQualityGate,
final boolean ignoreFailedBuilds, final Charset sourceCodeEncoding, final LogHandler logger) {
final boolean ignoreFailedBuilds, final Charset sourceCodeEncoding, final LogHandler logger,
final QualityGateStatusHandler qualityGateStatusHandler) {
this.report = report;
this.run = run;
this.healthDescriptor = healthDescriptor;
Expand All @@ -64,6 +69,7 @@ class IssuesPublisher {
qualityGateEvaluationMode = ignoreQualityGate ? IGNORE_QUALITY_GATE : SUCCESSFUL_QUALITY_GATE;
jobResultEvaluationMode = ignoreFailedBuilds ? NO_JOB_FAILURE : IGNORE_JOB_RESULT;
this.logger = logger;
this.qualityGateStatusHandler = qualityGateStatusHandler;
}

private String getId() {
Expand Down Expand Up @@ -142,7 +148,7 @@ private QualityGateStatus evaluateQualityGate(final Report filtered, final Delta
else {
filtered.logInfo("-> Some quality gates have been missed: overall result is %s", qualityGateStatus);
}
qualityGateStatus.setResult(run);
qualityGateStatusHandler.handleStatus(qualityGateStatus);
}
else {
filtered.logInfo("No quality gates have been set - skipping");
Expand Down
Expand Up @@ -16,7 +16,7 @@
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.DataBoundSetter;
import org.kohsuke.stapler.QueryParameter;
import org.jenkinsci.Symbol;
import org.jenkinsci.plugins.workflow.graph.FlowNode;
import hudson.Extension;
import hudson.FilePath;
import hudson.Launcher;
Expand Down Expand Up @@ -52,6 +52,7 @@
import io.jenkins.plugins.analysis.core.util.QualityGate.QualityGateResult;
import io.jenkins.plugins.analysis.core.util.QualityGate.QualityGateType;
import io.jenkins.plugins.analysis.core.util.QualityGateEvaluator;
import io.jenkins.plugins.analysis.core.util.QualityGateStatusHandler;

/**
* Freestyle or Maven job {@link Recorder} that scans report files or the console log for issues. Stores the created
Expand All @@ -73,7 +74,7 @@
*/
@SuppressWarnings({"PMD.ExcessivePublicCount", "PMD.ExcessiveClassLength", "PMD.ExcessiveImports", "PMD.TooManyFields", "PMD.DataClass", "ClassDataAbstractionCoupling", "ClassFanOutComplexity"})
public class IssuesRecorder extends Recorder implements SimpleBuildStep {
private static final String NO_REFERENCE_JOB = "-";
static final String NO_REFERENCE_JOB = "-";

private List<Tool> analysisTools = new ArrayList<>();

Expand Down Expand Up @@ -284,7 +285,7 @@ public void setTool(final Tool tool) {
analysisTools = Collections.singletonList(tool);
}

private void ensureThatToolIsValid(final Tool tool) {
static void ensureThatToolIsValid(final Tool tool) {
if (tool == null) {
throw new IllegalArgumentException("No valid tool defined! You probably used a symbol in the tools "
+ "definition that is also a symbol in another plugin. "
Expand Down Expand Up @@ -504,9 +505,19 @@ public Descriptor getDescriptor() {
public void perform(@NonNull final Run<?, ?> run, @NonNull final FilePath workspace,
@NonNull final Launcher launcher, @NonNull final TaskListener listener)
throws InterruptedException, IOException {
perform(run, workspace, listener, new QualityGateStatusHandler.SetBuildResultStatusHandler(run));
}

/**
* Executes the build step. Used from {@link RecordIssuesStep} to provide a {@link QualityGateStatusHandler}
* that has Pipeline-specific behavior.
*/
void perform(@NonNull final Run<?, ?> run, @NonNull final FilePath workspace,
@NonNull final TaskListener listener, @NonNull final QualityGateStatusHandler statusHandler)
throws InterruptedException, IOException {
Result overallResult = run.getResult();
if (isEnabledForFailure || overallResult == null || overallResult.isBetterOrEqualTo(Result.UNSTABLE)) {
record(run, workspace, listener);
record(run, workspace, listener, statusHandler);
}
else {
LogHandler logHandler = new LogHandler(listener, createLoggerPrefix());
Expand All @@ -518,7 +529,8 @@ private String createLoggerPrefix() {
return analysisTools.stream().map(Tool::getActualName).collect(Collectors.joining());
}

private void record(final Run<?, ?> run, final FilePath workspace, final TaskListener listener)
private void record(final Run<?, ?> run, final FilePath workspace, final TaskListener listener,
final QualityGateStatusHandler statusHandler)
throws IOException, InterruptedException {
for (Tool tool : getTools()) {
ensureThatToolIsValid(tool);
Expand All @@ -529,7 +541,7 @@ private void record(final Run<?, ?> run, final FilePath workspace, final TaskLis
totalIssues.add(scanWithTool(run, workspace, listener, tool), tool.getActualId());
}
String toolName = StringUtils.defaultIfEmpty(getName(), Messages.Tool_Default_Name());
publishResult(run, listener, toolName, totalIssues, toolName);
publishResult(run, listener, toolName, totalIssues, toolName, statusHandler);
}
else {
for (Tool tool : analysisTools) {
Expand All @@ -543,7 +555,7 @@ private void record(final Run<?, ?> run, final FilePath workspace, final TaskLis
report.logInfo("Ignoring name='%s' and id='%s' when publishing non-aggregating reports",
name, id);
}
publishResult(run, listener, tool.getActualName(), report, getReportName(tool));
publishResult(run, listener, tool.getActualName(), report, getReportName(tool), statusHandler);
}
}
}
Expand Down Expand Up @@ -605,7 +617,7 @@ private Charset getCharset(final String encoding) {
*/
@SuppressWarnings("deprecation")
void publishResult(final Run<?, ?> run, final TaskListener listener, final String loggerName,
final AnnotatedReport report, final String reportName) {
final AnnotatedReport report, final String reportName, QualityGateStatusHandler statusHandler) {
QualityGateEvaluator qualityGate = new QualityGateEvaluator();
if (qualityGates.isEmpty()) {
qualityGates.addAll(QualityGate.map(thresholds));
Expand All @@ -614,7 +626,7 @@ void publishResult(final Run<?, ?> run, final TaskListener listener, final Strin
IssuesPublisher publisher = new IssuesPublisher(run, report,
new HealthDescriptor(healthy, unhealthy, minimumSeverity), qualityGate,
reportName, referenceJobName, ignoreQualityGate, ignoreFailedBuilds, getSourceCodeCharset(),
new LogHandler(listener, loggerName, report.getReport()));
new LogHandler(listener, loggerName, report.getReport()), statusHandler);
publisher.attachAction();
}

Expand Down Expand Up @@ -1030,7 +1042,6 @@ public int getFailedNewLow() {
* Descriptor for this step: defines the context and the UI elements.
*/
@Extension
@Symbol("recordIssues")
@SuppressWarnings("unused") // most methods are used by the corresponding jelly view
public static class Descriptor extends BuildStepDescriptor<Publisher> {
/** Retain backward compatibility. */
Expand Down
Expand Up @@ -15,13 +15,16 @@
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.DataBoundSetter;
import org.kohsuke.stapler.QueryParameter;
import org.jenkinsci.plugins.workflow.actions.WarningAction;
import org.jenkinsci.plugins.workflow.graph.FlowNode;
import org.jenkinsci.plugins.workflow.steps.Step;
import org.jenkinsci.plugins.workflow.steps.StepContext;
import org.jenkinsci.plugins.workflow.steps.StepDescriptor;
import org.jenkinsci.plugins.workflow.steps.StepExecution;
import hudson.Extension;
import hudson.model.Action;
import hudson.model.Job;
import hudson.model.Result;
import hudson.model.Run;
import hudson.model.TaskListener;
import hudson.util.ComboBoxModel;
Expand All @@ -38,6 +41,8 @@
import io.jenkins.plugins.analysis.core.util.QualityGate.QualityGateResult;
import io.jenkins.plugins.analysis.core.util.QualityGate.QualityGateType;
import io.jenkins.plugins.analysis.core.util.QualityGateEvaluator;
import io.jenkins.plugins.analysis.core.util.QualityGateStatus;
import io.jenkins.plugins.analysis.core.util.QualityGateStatusHandler;

/**
* Publish issues created by a static analysis build. The recorded issues are stored as a {@link ResultAction} in the
Expand Down Expand Up @@ -569,10 +574,13 @@ protected ResultAction run() throws IOException, InterruptedException, IllegalSt
}
report.addAll(reports);

QualityGateStatusHandler statusHandler = new QualityGateStatusHandler.PipelineStatusHandler(getRun(),
getContext().get(FlowNode.class));
IssuesPublisher publisher = new IssuesPublisher(getRun(), report, healthDescriptor, qualityGate,
name, referenceJobName, ignoreQualityGate, ignoreFailedBuilds,
getCharset(sourceCodeEncoding), getLogger(report));
return publisher.attachAction();
getCharset(sourceCodeEncoding), getLogger(report), statusHandler);
ResultAction resultAction = publisher.attachAction();
return resultAction;
}

private LogHandler getLogger(final AnnotatedReport report) throws InterruptedException {
Expand All @@ -590,7 +598,7 @@ public static class Descriptor extends StepDescriptor {

@Override
public Set<Class<?>> getRequiredContext() {
return Sets.immutable.of(Run.class, TaskListener.class).castToSet();
return Sets.immutable.of(FlowNode.class, Run.class, TaskListener.class).castToSet();
}

@Override
Expand Down

0 comments on commit ceb5e58

Please sign in to comment.