From 32337925383cfa864540c9dbf056b3b9a7edd96c Mon Sep 17 00:00:00 2001 From: Daniel Beland Date: Thu, 13 Jan 2022 15:29:40 -0500 Subject: [PATCH] Add optional attribute to set the junit results parse interval (#32) Co-authored-by: Daniel Beland Co-authored-by: Tim Jacomb --- .../AbstractRealtimeTestResultAction.java | 11 ++++++--- .../PipelineRealtimeTestResultAction.java | 10 +++++++- .../RealtimeJUnitStep.java | 24 +++++++++++++++---- .../RealtimeJUnitStep/config.jelly | 9 ++++--- .../RealtimeJUnitStep/help-parseInterval.html | 7 ++++++ 5 files changed, 50 insertions(+), 11 deletions(-) create mode 100644 src/main/resources/org/jenkinsci/plugins/junitrealtimetestreporter/RealtimeJUnitStep/help-parseInterval.html diff --git a/src/main/java/org/jenkinsci/plugins/junitrealtimetestreporter/AbstractRealtimeTestResultAction.java b/src/main/java/org/jenkinsci/plugins/junitrealtimetestreporter/AbstractRealtimeTestResultAction.java index 784c78b..60debea 100644 --- a/src/main/java/org/jenkinsci/plugins/junitrealtimetestreporter/AbstractRealtimeTestResultAction.java +++ b/src/main/java/org/jenkinsci/plugins/junitrealtimetestreporter/AbstractRealtimeTestResultAction.java @@ -49,12 +49,10 @@ protected AbstractRealtimeTestResultAction() {} @Override public TestResult getResult() { - // Refresh every 1/100 of a job estimated duration but not more often than every 5 seconds - final long threshold = Math.max(5000, run.getEstimatedDuration() / 100); + final long threshold = getParseInterval(); // TODO possible improvements: // · always run parse in case result == null // · run parse regardless of cache if result.getTotalCount() == 0 - // · refresh no less often than every 1m even if job is estimated to take >100m if (updated > System.currentTimeMillis() - threshold && !Main.isUnitTest) { LOGGER.fine("Cache hit"); return result; @@ -82,6 +80,13 @@ public TestResult getResult() { return result; } + protected long getParseInterval() { + // Refresh every 1/100 of a job estimated duration but not more often than every 5 seconds + return Math.max(5000, run.getEstimatedDuration() / 100); + // TODO possible improvements: + // · refresh no less often than every 1m even if job is estimated to take >100m + } + @Override public int getFailCount() { if (getResult() == null) { diff --git a/src/main/java/org/jenkinsci/plugins/junitrealtimetestreporter/PipelineRealtimeTestResultAction.java b/src/main/java/org/jenkinsci/plugins/junitrealtimetestreporter/PipelineRealtimeTestResultAction.java index 276ebb0..718b12a 100644 --- a/src/main/java/org/jenkinsci/plugins/junitrealtimetestreporter/PipelineRealtimeTestResultAction.java +++ b/src/main/java/org/jenkinsci/plugins/junitrealtimetestreporter/PipelineRealtimeTestResultAction.java @@ -55,13 +55,15 @@ class PipelineRealtimeTestResultAction extends AbstractRealtimeTestResultAction private final String glob; @CheckForNull private transient final StepContext context; + private final Long parseInterval; PipelineRealtimeTestResultAction( String id, FilePath ws, boolean keepLongStdio, String glob, - StepContext context + StepContext context, + Long parseInterval ) { this.id = id; node = FilePathUtils.getNodeName(ws); @@ -69,6 +71,7 @@ class PipelineRealtimeTestResultAction extends AbstractRealtimeTestResultAction this.keepLongStdio = keepLongStdio; this.glob = glob; this.context = context; + this.parseInterval = parseInterval; } @Override @@ -86,6 +89,11 @@ public String getUrlName() { return "realtimeTestReport-" + id; } + @Override + protected long getParseInterval() { + return parseInterval != null ? parseInterval.longValue() : super.getParseInterval(); + } + @Override protected TestResult parse() throws IOException, InterruptedException { FilePath ws = FilePathUtils.find(node, workspace); diff --git a/src/main/java/org/jenkinsci/plugins/junitrealtimetestreporter/RealtimeJUnitStep.java b/src/main/java/org/jenkinsci/plugins/junitrealtimetestreporter/RealtimeJUnitStep.java index f87fc7e..35915f1 100644 --- a/src/main/java/org/jenkinsci/plugins/junitrealtimetestreporter/RealtimeJUnitStep.java +++ b/src/main/java/org/jenkinsci/plugins/junitrealtimetestreporter/RealtimeJUnitStep.java @@ -76,6 +76,7 @@ public class RealtimeJUnitStep extends Step { private Double healthScaleFactor; private boolean allowEmptyResults; private boolean skipMarkingBuildUnstable; + private Long parseInterval; @DataBoundConstructor public RealtimeJUnitStep(String testResults) { @@ -132,6 +133,15 @@ public void setSkipMarkingBuildUnstable(boolean skipMarkingBuildUnstable) { this.skipMarkingBuildUnstable = skipMarkingBuildUnstable; } + public Long getParseInterval() { + return parseInterval; + } + + @DataBoundSetter + public void setParseInterval(Long parseInterval) { + this.parseInterval = parseInterval; + } + @Override public StepExecution start(StepContext context) throws Exception { JUnitResultArchiver delegate = new JUnitResultArchiver(testResults); @@ -140,16 +150,20 @@ public StepExecution start(StepContext context) throws Exception { delegate.setKeepLongStdio(keepLongStdio); delegate.setTestDataPublishers(getTestDataPublishers()); delegate.setSkipMarkingBuildUnstable(isSkipMarkingBuildUnstable()); - return new Execution2(context, delegate); + // step takes value in milliseconds but users provide in seconds + Long parseInterval = this.parseInterval != null ? this.parseInterval * 1000 : null; + return new Execution2(context, delegate, parseInterval); } @SuppressFBWarnings("SE_BAD_FIELD") // FIXME static class Execution2 extends GeneralNonBlockingStepExecution { private final JUnitResultArchiver archiver; + private final Long parseInterval; - Execution2(StepContext context, JUnitResultArchiver archiver) { + Execution2(StepContext context, JUnitResultArchiver archiver, Long parseInterval) { super(context); this.archiver = archiver; + this.parseInterval = parseInterval; } @Override @@ -168,7 +182,8 @@ private void doStart() throws IOException, InterruptedException { context.get(FilePath.class), archiver.isKeepLongStdio(), archiver.getTestResults(), - context + context, + parseInterval ) ); AbstractRealtimeTestResultAction.saveBuild(r); @@ -249,7 +264,8 @@ void doStart() throws IOException, InterruptedException { context.get(FilePath.class), archiver.isKeepLongStdio(), archiver.getTestResults(), - context + context, + null ) ); AbstractRealtimeTestResultAction.saveBuild(r); diff --git a/src/main/resources/org/jenkinsci/plugins/junitrealtimetestreporter/RealtimeJUnitStep/config.jelly b/src/main/resources/org/jenkinsci/plugins/junitrealtimetestreporter/RealtimeJUnitStep/config.jelly index 0f556fa..a3fc6df 100644 --- a/src/main/resources/org/jenkinsci/plugins/junitrealtimetestreporter/RealtimeJUnitStep/config.jelly +++ b/src/main/resources/org/jenkinsci/plugins/junitrealtimetestreporter/RealtimeJUnitStep/config.jelly @@ -24,8 +24,11 @@ THE SOFTWARE. --> - + - - + + + + + diff --git a/src/main/resources/org/jenkinsci/plugins/junitrealtimetestreporter/RealtimeJUnitStep/help-parseInterval.html b/src/main/resources/org/jenkinsci/plugins/junitrealtimetestreporter/RealtimeJUnitStep/help-parseInterval.html new file mode 100644 index 0000000..3dbaa8c --- /dev/null +++ b/src/main/resources/org/jenkinsci/plugins/junitrealtimetestreporter/RealtimeJUnitStep/help-parseInterval.html @@ -0,0 +1,7 @@ +
+

+ The interval between two file system scans to parse test results (in seconds). + Must be a positive value greater than 0. + Default value is calculated as 1/100 of the estimated build duration, but never more often than every 5 seconds. +

+
\ No newline at end of file