Skip to content

Commit ae2bddd

Browse files
olegmaiboroda-lab49Oleg.Maiboroda
andauthored
Option to handle test reports by Artifact Manager (#89)
* RobotPublisher.copyFilesToBuildDir() use Artifact Manager. * useArtifactManager parameter added * Remove 'Robot Test Summary' section if useArtifactManager * Links and UTs are tested. * Add UTs --------- Co-authored-by: Oleg.Maiboroda <[email protected]>
1 parent 80ceead commit ae2bddd

File tree

17 files changed

+169
-35
lines changed

17 files changed

+169
-35
lines changed

src/main/java/hudson/plugins/robot/RobotBuildAction.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ public class RobotBuildAction extends AbstractTestResultAction<RobotBuildAction>
6565
private String xAxisLabel;
6666

6767
private boolean countSkippedTests;
68+
private boolean useArtifactManager;
6869

6970
static {
7071
XSTREAM.alias("result",RobotResult.class);
@@ -85,7 +86,7 @@ public class RobotBuildAction extends AbstractTestResultAction<RobotBuildAction>
8586
*/
8687
public RobotBuildAction(Run<?, ?> build, RobotResult result,
8788
String outputPath, TaskListener listener, String logFileLink, String logHtmlLink, boolean enableCache, String xAxisLabel,
88-
boolean countSkippedTests) {
89+
boolean countSkippedTests, boolean useArtifactManager) {
8990
super();
9091
super.onAttached(build);
9192
this.build = build;
@@ -95,6 +96,7 @@ public RobotBuildAction(Run<?, ?> build, RobotResult result,
9596
this.enableCache = enableCache;
9697
this.xAxisLabel = xAxisLabel;
9798
this.countSkippedTests = countSkippedTests;
99+
this.useArtifactManager = useArtifactManager;
98100
setResult(result, listener);
99101
}
100102

@@ -332,6 +334,10 @@ public String getUrlName() {
332334
return "robot";
333335
}
334336

337+
public String getReportUrlName() {
338+
return getUseArtifactManager() ? "artifact/" : getUrlName() + "/report/";
339+
}
340+
335341
public List<RobotCaseResult> getAllTests() {
336342
return getResult().getAllCases();
337343
}
@@ -343,4 +349,8 @@ public boolean isCountSkippedTests() {
343349
public void setCountSkippedTests(boolean countSkippedTests) {
344350
this.countSkippedTests = countSkippedTests;
345351
}
352+
353+
public boolean getUseArtifactManager() {
354+
return useArtifactManager;
355+
}
346356
}

src/main/java/hudson/plugins/robot/RobotPublisher.java

Lines changed: 95 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,12 @@
3434
import java.io.PrintStream;
3535
import java.io.Serial;
3636
import java.io.Serializable;
37+
import java.nio.file.Path;
38+
import java.nio.file.Paths;
3739
import java.util.ArrayList;
3840
import java.util.Collection;
41+
import java.util.HashMap;
42+
import java.util.Map;
3943

4044
import jakarta.servlet.ServletException;
4145

@@ -47,6 +51,8 @@
4751
import edu.umd.cs.findbugs.annotations.NonNull;
4852
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
4953

54+
import jenkins.model.ArtifactManager;
55+
5056
public class RobotPublisher extends Recorder implements Serializable,
5157
MatrixAggregatable, SimpleBuildStep {
5258

@@ -71,6 +77,7 @@ public class RobotPublisher extends Recorder implements Serializable,
7177
private String[] otherFiles;
7278
final private String overwriteXAxisLabel;
7379
final private boolean enableCache;
80+
final private boolean useArtifactManager;
7481

7582
//Default to true
7683
private boolean countSkippedTests = false;
@@ -88,12 +95,13 @@ public class RobotPublisher extends Recorder implements Serializable,
8895
* @param unstableThreshold Threshold of test pass percentage for unstable builds
8996
* @param otherFiles Other files to be saved
9097
* @param enableCache True if caching is used
98+
* @param useArtifactManager True if Artifact Manager is used
9199
*/
92100
@DataBoundConstructor
93101
public RobotPublisher(String archiveDirName, String outputPath, String outputFileName,
94102
boolean disableArchiveOutput, String reportFileName, String logFileName,
95103
double passThreshold, double unstableThreshold,
96-
boolean countSkippedTests, String otherFiles, boolean enableCache, String overwriteXAxisLabel) {
104+
boolean countSkippedTests, String otherFiles, boolean enableCache, String overwriteXAxisLabel, boolean useArtifactManager) {
97105
this.archiveDirName = archiveDirName;
98106
this.outputPath = outputPath;
99107
this.outputFileName = outputFileName;
@@ -105,6 +113,7 @@ public RobotPublisher(String archiveDirName, String outputPath, String outputFil
105113
this.countSkippedTests = countSkippedTests;
106114
this.enableCache = enableCache;
107115
this.overwriteXAxisLabel = overwriteXAxisLabel;
116+
this.useArtifactManager = useArtifactManager;
108117

109118
if (otherFiles != null) {
110119
String[] filemasks = otherFiles.split(",");
@@ -235,6 +244,15 @@ public String getOverwriteXAxisLabel() {
235244
return overwriteXAxisLabel;
236245
}
237246

247+
/**
248+
* Gets value of useArtifactManager
249+
*
250+
* @return true if Artifact Manager is used
251+
*/
252+
public boolean getUseArtifactManager() {
253+
return useArtifactManager;
254+
}
255+
238256
/**
239257
* {@inheritDoc}
240258
*/
@@ -286,25 +304,26 @@ public void perform(Run<?, ?> build, @NonNull FilePath workspace, @NonNull EnvVa
286304

287305
if (!DEFAULT_JENKINS_ARCHIVE_DIR.equalsIgnoreCase(getArchiveDirName())) {
288306
logger.println(Messages.robot_publisher_copying());
289-
//Save configured Robot files (including split output) to build dir
290-
copyFilesToBuildDir(build, workspace, expandedOutputPath, StringUtils.join(modifyMasksforSplittedOutput(new String[]{expandedReportFileName, expandedLogFileName, logFileJavascripts}), ","));
307+
//Save configured Robot files (including split output) to destination dir
308+
copyFilesToDestination(build, workspace, expandedOutputPath, StringUtils.join(modifyMasksforSplittedOutput(new String[]{expandedReportFileName, expandedLogFileName, logFileJavascripts}), ","), launcher, listener);
291309

292310
if (!getDisableArchiveOutput()) {
293-
copyFilesToBuildDir(build, workspace, expandedOutputPath, StringUtils.join(modifyMasksforSplittedOutput(new String[]{expandedOutputFileName}), ","));
311+
copyFilesToDestination(build, workspace, expandedOutputPath, StringUtils.join(modifyMasksforSplittedOutput(new String[]{expandedOutputFileName}), ","), launcher, listener);
294312
}
295313

296-
//Save other configured files to build dir
314+
//Save other configured files to destination dir
297315
if (StringUtils.isNotBlank(getOtherFiles())) {
298316
String filemask = buildEnv.expand(getOtherFiles());
299-
copyFilesToBuildDir(build, workspace, expandedOutputPath, filemask);
317+
copyFilesToDestination(build, workspace, expandedOutputPath, filemask, launcher, listener);
300318
}
301319
logger.println(Messages.robot_publisher_done());
302320
}
303321

304322
logger.println(Messages.robot_publisher_assigning());
305323

306324
String label = buildEnv.expand(overwriteXAxisLabel);
307-
RobotBuildAction action = new RobotBuildAction(build, result, getArchiveDirName(), listener, expandedReportFileName, expandedLogFileName, enableCache, label, countSkippedTests);
325+
RobotBuildAction action = new RobotBuildAction(build, result, getArchiveDirName(), listener,
326+
expandedReportFileName, expandedLogFileName, enableCache, label, countSkippedTests, useArtifactManager);
308327
build.addAction(action);
309328

310329
// set RobotProjectAction as project action
@@ -339,7 +358,29 @@ public void perform(Run<?, ?> build, @NonNull FilePath workspace, @NonNull EnvVa
339358
}
340359

341360
/**
342-
* Copy files with given filemasks from input path relative to build into specific build file archive dir
361+
* Copy files with given filemasks from input path relative to build into
362+
* local build archive dir or artifact manager destination
363+
*
364+
* @param build The Jenkins run
365+
* @param workspace Build workspace
366+
* @param inputPath Base path for copy. Relative to build workspace.
367+
* @param filemaskToCopy List of Ant GLOB style filemasks to copy from dirs specified at inputPathMask
368+
* @param launcher A way to start processes
369+
* @param listener A place to send output
370+
* @throws IOException thrown exception
371+
* @throws InterruptedException thrown exception
372+
*/
373+
public void copyFilesToDestination(Run<?, ?> build, FilePath workspace, String inputPath, String filemaskToCopy,
374+
Launcher launcher, TaskListener listener) throws IOException, InterruptedException {
375+
if (getUseArtifactManager()) {
376+
archiveFilesToDestination(build, workspace, inputPath, filemaskToCopy, launcher, listener);
377+
} else {
378+
copyFilesToBuildDir(build, workspace, inputPath, filemaskToCopy);
379+
}
380+
}
381+
382+
/**
383+
* Copy files with given filemasks from input path relative to build into local build file archive dir
343384
*
344385
* @param build The Jenkins run
345386
* @param inputPath Base path for copy. Relative to build workspace.
@@ -351,11 +392,55 @@ public void perform(Run<?, ?> build, @NonNull FilePath workspace, @NonNull EnvVa
351392
public void copyFilesToBuildDir(Run<?, ?> build, FilePath workspace,
352393
String inputPath, String filemaskToCopy) throws IOException, InterruptedException {
353394
FilePath srcDir = new FilePath(workspace, inputPath);
354-
FilePath destDir = new FilePath(new FilePath(build.getRootDir()),
355-
getArchiveDirName());
395+
FilePath destDir = new FilePath(new FilePath(build.getRootDir()), getArchiveDirName());
356396
srcDir.copyRecursiveTo(filemaskToCopy, destDir);
357397
}
358398

399+
/**
400+
* Copy files with given filemasks from input path relative to Artifact Manager
401+
*
402+
* @param build The Jenkins run
403+
* @param workspace Build workspace
404+
* @param inputPath Base path for copy. Relative to build workspace.
405+
* @param artifactsFilemask List of Ant GLOB style filemasks to copy from dirs specified at inputPathMask
406+
* @param launcher A way to start processes
407+
* @param listener A place to send output
408+
* @throws IOException thrown exception
409+
* @throws InterruptedException thrown exception
410+
*/
411+
public void archiveFilesToDestination(Run<?, ?> build, FilePath workspace, String inputPath, String artifactsFilemask,
412+
Launcher launcher, TaskListener listener) throws IOException, InterruptedException {
413+
FilePath srcDir = new FilePath(workspace, inputPath);
414+
FilePath[] artifactFiles = srcDir.list(artifactsFilemask);
415+
416+
Map<String, String> artifacts = new HashMap<>();
417+
for (FilePath file : artifactFiles) {
418+
// Use relative path as artifact name
419+
String pathInArchiveArea = getRelativePath(srcDir, file);
420+
String pathInWorkspaceArea = getRelativePath(workspace, file);
421+
artifacts.put(pathInArchiveArea, pathInWorkspaceArea);
422+
}
423+
424+
// This will automatically use the configured artifact manager (S3, etc.)
425+
ArtifactManager artifactManager = build.pickArtifactManager();
426+
artifactManager.archive(srcDir, launcher, (BuildListener)listener, artifacts);
427+
if (artifacts.isEmpty()) {
428+
listener.getLogger().println("No artifacts to archive");
429+
} else {
430+
for (Map.Entry<String,String> artifact : artifacts.entrySet()) {
431+
listener.getLogger().println("The artifact to archive: " + artifact.getKey() + "->" + artifact.getValue());
432+
}
433+
}
434+
}
435+
436+
private String getRelativePath(FilePath path1, FilePath path2) {
437+
Path javaPath1 = Paths.get(path1.getRemote());
438+
Path javaPath2 = Paths.get(path2.getRemote());
439+
Path relativeJavaPath = javaPath1.relativize(javaPath2);
440+
441+
return relativeJavaPath.toString();
442+
}
443+
359444
/**
360445
* Return filename without file suffix.
361446
*

src/main/java/hudson/plugins/robot/RobotStep.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ public class RobotStep extends Step {
3939
private boolean enableCache = true;
4040
private boolean countSkippedTests = false;
4141
private @CheckForNull String overwriteXAxisLabel;
42+
private boolean useArtifactManager = false;
4243

4344

4445

@@ -96,7 +97,11 @@ public boolean getEnableCache() {
9697
public String getOverwriteXAxisLabel() {
9798
return this.overwriteXAxisLabel;
9899
}
99-
100+
101+
public boolean getUseArtifactManager() {
102+
return this.useArtifactManager;
103+
}
104+
100105
@DataBoundSetter
101106
public void setArchiveDirName(String archiveDirName) {
102107
this.archiveDirName = Util.fixEmpty(archiveDirName);
@@ -159,6 +164,11 @@ public void setOverwriteXAxisLabel(String overwriteXAxisLabel) {
159164
this.overwriteXAxisLabel = overwriteXAxisLabel;
160165
}
161166

167+
@DataBoundSetter
168+
public void setUseArtifactManager(boolean useArtifactManager) {
169+
this.useArtifactManager = useArtifactManager;
170+
}
171+
162172
@Override
163173
public StepExecution start(StepContext context) throws Exception {
164174
return new RobotStepExecution(this, context);

src/main/java/hudson/plugins/robot/RobotStepExecution.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public class RobotStepExecution extends SynchronousNonBlockingStepExecution<Void
2929
@Override protected Void run() throws Exception {
3030
FilePath workspace = getContext().get(FilePath.class);
3131
workspace.mkdirs();
32-
RobotPublisher rp = new RobotPublisher(step.getArchiveDirName(), step.getOutputPath(), step.getOutputFileName(), step.getDisableArchiveOutput(), step.getReportFileName(), step.getLogFileName(), step.getPassThreshold(), step.getUnstableThreshold(), step.getCountSkippedTests(), step.getOtherFiles(), step.getEnableCache(), step.getOverwriteXAxisLabel());
32+
RobotPublisher rp = new RobotPublisher(step.getArchiveDirName(), step.getOutputPath(), step.getOutputFileName(), step.getDisableArchiveOutput(), step.getReportFileName(), step.getLogFileName(), step.getPassThreshold(), step.getUnstableThreshold(), step.getCountSkippedTests(), step.getOtherFiles(), step.getEnableCache(), step.getOverwriteXAxisLabel(), step.getUseArtifactManager());
3333
rp.perform(getContext().get(Run.class), workspace, getContext().get(EnvVars.class), getContext().get(Launcher.class), getContext().get(TaskListener.class));
3434
return null;
3535
}

src/main/java/hudson/plugins/robot/tokens/RobotReportLinkTokenMacro.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ public String evaluate(Run<?, ?> context, FilePath workspace, TaskListener liste
3131
if (action!=null){
3232
String rootURL = (Jenkins.getInstanceOrNull() != null) ? Jenkins.get().getRootUrl() : "";
3333
if (action.getLogFileLink() == null)
34-
return rootURL + context.getUrl()+ action.getUrlName() + "/report/";
34+
return rootURL + context.getUrl()+ action.getReportUrlName();
3535
else
36-
return rootURL + context.getUrl()+ action.getUrlName() + "/report/" + action.getLogFileLink();
36+
return rootURL + context.getUrl()+ action.getReportUrlName() + action.getLogFileLink();
3737
}
3838
return "";
3939
}

src/main/resources/hudson/plugins/robot/RobotPublisher/config.jelly

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ limitations under the License.
4444
<f:entry title="${%advanced.overwriteXAxisLabel}" description="${%advanced.overwriteXAxisLabel.description}" field="overwriteXAxisLabel">
4545
<f:textbox />
4646
</f:entry>
47+
<f:entry title="${%advanced.useArtifactManager}" description="${%advanced.useArtifactManager.description}" field="useArtifactManager">
48+
<f:checkbox default="false"/>
49+
</f:entry>
4750
</f:advanced>
4851
<f:entry title="${%thresholds.label}" help="/plugin/robot/help-thresholds.html">
4952
<table width="100%">

src/main/resources/hudson/plugins/robot/RobotPublisher/config.properties

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ advanced.enableCache=Enable cache
1818
advanced.enableCache.description=Enable cache for test results
1919
advanced.overwriteXAxisLabel=X-axis label
2020
advanced.overwriteXAxisLabel.description=Overwrite default x-axis label for publish trend. You can use $display_name to change the label for the build display name.
21+
advanced.useArtifactManager=Use Artifact Manager
22+
advanced.useArtifactManager.description=Use Artifact Manager to copy tests results
2123
2224
2325
thresholds.label=Thresholds for build result

src/main/resources/hudson/plugins/robot/RobotStep/config.jelly

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ limitations under the License.
4444
<f:entry title="${%advanced.overwriteXAxisLabel}" description="${%advanced.overwriteXAxisLabel.description}" field="overwriteXAxisLabel">
4545
<f:textbox />
4646
</f:entry>
47+
<f:entry title="${%advanced.useArtifactManager}" description="${%advanced.useArtifactManager.description}" field="useArtifactManager">
48+
<f:checkbox default="false"/>
49+
</f:entry>
4750
</f:advanced>
4851
<f:entry title="${%thresholds.label}" help="/plugin/robot/help-thresholds.html">
4952
<table width="100%">

src/main/resources/hudson/plugins/robot/RobotStep/config.properties

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ advanced.enableCache=Enable cache
1818
advanced.enableCache.description=Enable cache for test results
1919
advanced.overwriteXAxisLabel=X-axis label
2020
advanced.overwriteXAxisLabel.description=Overwrite default x-axis label for publish trend
21+
advanced.useArtifactManager=Use Artifact Manager
22+
advanced.useArtifactManager.description=Use Artifact Manager to copy tests results
2123
2224
thresholds.label=Thresholds for build result
2325
thresholds.countSkippedTests=Include skipped tests in total count for thresholds

src/main/resources/hudson/plugins/robot/model/RobotCaseResult/index.jelly

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ limitations under the License.
4444
<tr><th>Message:</th><td class="error-message">${it.errorMsg}</td></tr>
4545
</j:if>
4646
<j:if test="${it.hasLog}">
47-
<tr><th>Log File:</th><td><a href="${rootURL}/${it.parentAction.owner.url}${it.parentAction.urlName}/report/${it.logFile}#${it.id}">${it.logFile}</a></td></tr>
47+
<tr><th>Log File:</th><td><a href="${rootURL}/${it.parentAction.owner.url}${it.parentAction.reportUrlName}${it.logFile}#${it.id}">${it.logFile}</a></td></tr>
4848
</j:if>
4949
</tbody>
5050
</table>

0 commit comments

Comments
 (0)