Skip to content

Commit

Permalink
[JENKINS-21456] Add option to let user decide to fail if build should…
Browse files Browse the repository at this point in the history
… be skipped
  • Loading branch information
kinow committed Aug 26, 2016
1 parent 1c2cc09 commit 1f148f4
Showing 1 changed file with 148 additions and 96 deletions.
244 changes: 148 additions & 96 deletions src/main/java/org/tap4j/plugin/TapPublisher.java
Expand Up @@ -67,7 +67,7 @@
* @since 1.0
*/
public class TapPublisher extends Recorder implements MatrixAggregatable, SimpleBuildStep {

private final String testResults;
private final Boolean failIfNoResults;
private final Boolean failedTestsMarkBuildAsFailure;
Expand All @@ -82,6 +82,7 @@ public class TapPublisher extends Recorder implements MatrixAggregatable, Simple
private final Boolean showOnlyFailures;
private final Boolean stripSingleParents;
private final Boolean flattenTapResult;
private final Boolean skipIfBuildNotOk;

@Deprecated
public TapPublisher(String testResults,
Expand Down Expand Up @@ -140,7 +141,7 @@ public TapPublisher(String testResults,
Boolean.FALSE, Boolean.FALSE, Boolean.FALSE);
}

@DataBoundConstructor
@Deprecated
public TapPublisher(String testResults,
Boolean failIfNoResults,
Boolean failedTestsMarkBuildAsFailure,
Expand All @@ -155,6 +156,28 @@ public TapPublisher(String testResults,
Boolean showOnlyFailures,
Boolean stripSingleParents,
Boolean flattenTapResult) {
this(testResults, failIfNoResults, failedTestsMarkBuildAsFailure,
outputTapToConsole, enableSubtests, discardOldReports, todoIsFailure,
includeCommentDiagnostics, validateNumberOfTests, planRequired, verbose,
showOnlyFailures, stripSingleParents, flattenTapResult, Boolean.FALSE);
}

@DataBoundConstructor
public TapPublisher(String testResults,
Boolean failIfNoResults,
Boolean failedTestsMarkBuildAsFailure,
Boolean outputTapToConsole,
Boolean enableSubtests,
Boolean discardOldReports,
Boolean todoIsFailure,
Boolean includeCommentDiagnostics,
Boolean validateNumberOfTests,
Boolean planRequired,
Boolean verbose,
Boolean showOnlyFailures,
Boolean stripSingleParents,
Boolean flattenTapResult,
Boolean skipIfBuildNotOk) {

this.testResults = testResults;
this.failIfNoResults = BooleanUtils.toBooleanDefaultIfNull(failIfNoResults, false);
Expand All @@ -170,6 +193,7 @@ public TapPublisher(String testResults,
this.showOnlyFailures = BooleanUtils.toBooleanDefaultIfNull(showOnlyFailures, false);
this.stripSingleParents = BooleanUtils.toBooleanDefaultIfNull(stripSingleParents, false);
this.flattenTapResult = BooleanUtils.toBooleanDefaultIfNull(flattenTapResult, false);
this.skipIfBuildNotOk = BooleanUtils.toBooleanDefaultIfNull(skipIfBuildNotOk, false);
}

public Object readResolve() {
Expand Down Expand Up @@ -282,6 +306,10 @@ public Boolean getFlattenTapResult() {
return flattenTapResult;
}

public Boolean getSkipIfBuildNotOk() {
return skipIfBuildNotOk;
}

/**
* Gets the directory where the plug-in saves its TAP streams before processing them and
* displaying in the UI.
Expand Down Expand Up @@ -316,7 +344,7 @@ public Action getProjectAction(AbstractProject<?, ?> project) {
*/
@Override
public void perform(
@Nonnull Run run,
@Nonnull Run<?, ?> run,
@Nonnull FilePath workspace,
@Nonnull Launcher launcher,
@Nonnull TaskListener listener)
Expand All @@ -325,114 +353,138 @@ public void perform(
performImpl(run, workspace, listener);
}

private boolean performImpl(Run build, FilePath workspace, TaskListener listener) throws IOException, InterruptedException {
PrintStream logger = listener.getLogger();
logger.println("TAP Reports Processing: START");

EnvVars envVars = build.getEnvironment(listener);
String antPattern = Util.replaceMacro(this.testResults, envVars);
logger.println("Looking for TAP results report in workspace using pattern: " + antPattern);

FilePath[] reports = locateReports(workspace, antPattern);

/*
* filter out the reports based on timestamps. See JENKINS-12187
*/
if (this.getDiscardOldReports()) {
reports = checkReports(build, reports, logger);
}

if (reports.length == 0) {
if(this.getFailIfNoResults()) {
logger.println("Did not find any matching files. Setting build result to FAILURE.");
build.setResult(Result.FAILURE);
return Boolean.FALSE;
} else {
logger.println("Did not find any matching files.");
// build can still continue
return Boolean.TRUE;
}
}

boolean filesSaved = saveReports(workspace, TapPublisher.getReportsDirectory(build), reports, logger);
if (!filesSaved) {
logger.println("Failed to save TAP reports");
return Boolean.TRUE;
}

TapResult testResult = null;
try {
testResult = loadResults(antPattern, build, logger);
testResult.setShowOnlyFailures(this.getShowOnlyFailures());
testResult.tally();
} catch (Throwable t) {
private boolean performImpl(Run<?, ?> build, FilePath workspace, TaskListener listener) throws IOException, InterruptedException {
final PrintStream logger = listener.getLogger();
if (isPerformPublisher(build)) {
logger.println("TAP Reports Processing: START");

EnvVars envVars = build.getEnvironment(listener);
String antPattern = Util.replaceMacro(this.testResults, envVars);
logger.println("Looking for TAP results report in workspace using pattern: " + antPattern);

FilePath[] reports = locateReports(workspace, antPattern);

/*
* don't fail build if TAP parser barfs. only print out the
* exception to console.
* filter out the reports based on timestamps. See JENKINS-12187
*/
t.printStackTrace(logger);
}

TapTestResultAction trAction = build.getAction(TapTestResultAction.class);
boolean appending;

if (trAction == null) {
appending = false;
trAction = new TapTestResultAction(build, testResult);
} else {
appending = true;
trAction.mergeResult(testResult);
}

if (!appending) {
build.addAction(trAction);
}

if (testResult.getTestSets().size() > 0 || testResult.getParseErrorTestSets().size() > 0) {
// create an individual report for all of the results and add it to
// the build

TapBuildAction action = build.getAction(TapBuildAction.class);
if (action == null) {
action = new TapBuildAction(build, testResult);
build.addAction(action);
if (this.getDiscardOldReports()) {
reports = checkReports(build, reports, logger);
}

if (reports.length == 0) {
if(this.getFailIfNoResults()) {
logger.println("Did not find any matching files. Setting build result to FAILURE.");
build.setResult(Result.FAILURE);
return Boolean.FALSE;
} else {
logger.println("Did not find any matching files.");
// build can still continue
return Boolean.TRUE;
}
}

boolean filesSaved = saveReports(workspace, TapPublisher.getReportsDirectory(build), reports, logger);
if (!filesSaved) {
logger.println("Failed to save TAP reports");
return Boolean.TRUE;
}

TapResult testResult = null;
try {
testResult = loadResults(antPattern, build, logger);
testResult.setShowOnlyFailures(this.getShowOnlyFailures());
testResult.tally();
} catch (Throwable t) {
/*
* don't fail build if TAP parser barfs. only print out the
* exception to console.
*/
t.printStackTrace(logger);
}

TapTestResultAction trAction = build.getAction(TapTestResultAction.class);
boolean appending;

if (trAction == null) {
appending = false;
trAction = new TapTestResultAction(build, testResult);
} else {
appending = true;
action.mergeResult(testResult);
}

if (testResult.hasParseErrors()) {
listener.getLogger().println("TAP parse errors found in the build. Marking build as UNSTABLE");
build.setResult(Result.UNSTABLE);
trAction.mergeResult(testResult);
}
if (this.getValidateNumberOfTests()) {
if (!this.validateNumberOfTests(testResult.getTestSets())) {
listener.getLogger().println("Not all test cases were executed according to the test set plan. Marking build as UNSTABLE");
build.setResult(Result.UNSTABLE);
}

if (!appending) {
build.addAction(trAction);
}
if (testResult.getFailed() > 0) {
if(this.getFailedTestsMarkBuildAsFailure()) {
listener.getLogger().println("There are failed test cases and the job is configured to mark the build as failure. Marking build as FAILURE");
build.setResult(Result.FAILURE);

if (testResult.getTestSets().size() > 0 || testResult.getParseErrorTestSets().size() > 0) {
// create an individual report for all of the results and add it to
// the build

TapBuildAction action = build.getAction(TapBuildAction.class);
if (action == null) {
action = new TapBuildAction(build, testResult);
build.addAction(action);
} else {
listener.getLogger().println("There are failed test cases. Marking build as UNSTABLE");
appending = true;
action.mergeResult(testResult);
}

if (testResult.hasParseErrors()) {
listener.getLogger().println("TAP parse errors found in the build. Marking build as UNSTABLE");
build.setResult(Result.UNSTABLE);
}
if (this.getValidateNumberOfTests()) {
if (!this.validateNumberOfTests(testResult.getTestSets())) {
listener.getLogger().println("Not all test cases were executed according to the test set plan. Marking build as UNSTABLE");
build.setResult(Result.UNSTABLE);
}
}
if (testResult.getFailed() > 0) {
if(this.getFailedTestsMarkBuildAsFailure()) {
listener.getLogger().println("There are failed test cases and the job is configured to mark the build as failure. Marking build as FAILURE");
build.setResult(Result.FAILURE);
} else {
listener.getLogger().println("There are failed test cases. Marking build as UNSTABLE");
build.setResult(Result.UNSTABLE);
}
}

if (appending) {
build.save();
}

} else {
logger.println("Found matching files but did not find any TAP results.");
return Boolean.TRUE;
}

if (appending) {
build.save();
}

logger.println("TAP Reports Processing: FINISH");
} else {
logger.println("Found matching files but did not find any TAP results.");
return Boolean.TRUE;
logger.println("Build result is not better or equal unstable. Skipping TAP publisher.");
}
logger.println("TAP Reports Processing: FINISH");
return Boolean.TRUE;
}

/**
* Return {@code true} if the build is ongoing, if the user did not ask to fail when
* failed, or otherwise if the build result is not better or equal to unstable.
* @param build Run
* @return whether to perform the publisher or not, based on user provided configuration
*/
private boolean isPerformPublisher(Run<?, ?> build) {
Result result = build.getResult();
// may be null if build is ongoing
if (result == null) {
return true;
}

if (!getSkipIfBuildNotOk()) {
return true;
}

return result.isBetterOrEqualTo(Result.UNSTABLE);
}

/**
* Iterates through the list of test sets and validates its plans and
* test results.
Expand Down

0 comments on commit 1f148f4

Please sign in to comment.