Skip to content

Commit

Permalink
Merge pull request #53 from jenkinsci/ant-pattern
Browse files Browse the repository at this point in the history
add `pattern` to add multiple reports with apache ant-pattern
  • Loading branch information
simonsymhoven authored Sep 9, 2022
2 parents bac3972 + e66874d commit fb463ab
Show file tree
Hide file tree
Showing 18 changed files with 290 additions and 91 deletions.
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -224,13 +224,16 @@ available in the json model. On the lowest level only the pie chart and the hist
### Pipeline Step

```
publishReport reportFile: "etc/result.json", displayType: "absolute"
publishReport pattern: "**/result-*.json", displayType: "absolute"
```

### Parameter:

##### reportFile:
The path to the report file. At the moment yaml/yml or json files are supported.
##### pattern:

This is an ant include pattern for the files should be parsed and scanned (see Patterns in the Apache Ant Manual).
Multiple includes can be specified by separating each pattern with a comma.
At the moment only yaml/yml or json files are supported.

##### displayType (optional, default = `absolute`):
This can be used to determine the representation of the values within the table.
Expand Down
3 changes: 1 addition & 2 deletions etc/Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ pipeline {
stage('Publish Data') {
steps {
checkout scm
publishReport reportFile: "etc/result.json", displayType: "dual"
publishReport reportFile: "etc/result-oc.json", displayType: "dual"
publishReport pattern: "etc/*.json", displayType: "dual"
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>9</source>
<target>9</target>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
</plugins>
Expand Down
10 changes: 8 additions & 2 deletions src/main/java/io/jenkins/plugins/reporter/ItemViewModel.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package io.jenkins.plugins.reporter;

import edu.hm.hafner.echarts.*;
import edu.hm.hafner.echarts.Build;
import edu.hm.hafner.echarts.BuildResult;
import edu.hm.hafner.echarts.ChartModelConfiguration;
import edu.hm.hafner.echarts.JacksonFacade;
import hudson.model.Job;
import hudson.model.ModelObject;
import hudson.model.Run;
Expand All @@ -16,7 +19,10 @@
import org.kohsuke.stapler.bind.JavaScriptMethod;

import java.io.IOException;
import java.util.*;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
Expand Down
93 changes: 33 additions & 60 deletions src/main/java/io/jenkins/plugins/reporter/PublishReportStep.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
package io.jenkins.plugins.reporter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import edu.hm.hafner.echarts.JacksonFacade;
import edu.umd.cs.findbugs.annotations.NonNull;
import hudson.EnvVars;
import hudson.Extension;
Expand All @@ -13,26 +10,19 @@
import hudson.model.TaskListener;
import hudson.tasks.BuildStepDescriptor;
import hudson.tasks.Builder;
import io.jenkins.cli.shaded.org.apache.commons.io.FilenameUtils;
import io.jenkins.plugins.reporter.model.DisplayType;
import io.jenkins.plugins.reporter.model.FilesScanner;
import io.jenkins.plugins.reporter.model.Report;
import io.jenkins.plugins.reporter.model.Result;
import jenkins.tasks.SimpleBuildStep;
import org.everit.json.schema.Schema;
import org.everit.json.schema.ValidationException;
import org.everit.json.schema.loader.SchemaClient;
import org.everit.json.schema.loader.SchemaLoader;
import org.jenkinsci.Symbol;
import org.json.JSONObject;
import org.json.JSONTokener;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.DataBoundSetter;

import java.io.IOException;
import java.io.InputStream;
import java.io.InvalidObjectException;
import java.io.Serializable;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;

/**
Expand All @@ -51,8 +41,11 @@ public class PublishReportStep extends Builder implements SimpleBuildStep, Seria
private String jsonFile;

private String displayType;


@Deprecated
private String reportFile;

private String pattern;

@DataBoundConstructor
public PublishReportStep() {
Expand Down Expand Up @@ -86,12 +79,17 @@ public String getJsonFile() {
public void setJsonFile(final String jsonFile) {
this.jsonFile = jsonFile;
}


@Deprecated
public String getReportFile() {
return reportFile;
}

/**
* use {@link #setPattern(String)} instead.
*/
@DataBoundSetter
@Deprecated
public void setReportFile(final String reportFile) {
this.reportFile = reportFile;
}
Expand All @@ -105,6 +103,15 @@ public void setDisplayType(final String displayType) {
this.displayType = displayType;
}

public String getPattern() {
return pattern;
}

@DataBoundSetter
public void setPattern(String pattern) {
this.pattern = pattern;
}

@Override
public DescriptorImpl getDescriptor() {
return (DescriptorImpl) super.getDescriptor();
Expand All @@ -115,54 +122,20 @@ public void perform(@NonNull Run<?, ?> run, @NonNull FilePath workspace, @NonNul
@NonNull Launcher launcher, @NonNull TaskListener listener) throws InterruptedException,
IOException {
listener.getLogger().println("[PublishReportStep] Report data... ");

FilePath filePath = workspace.child(getReportFile());
String extension = FilenameUtils.getExtension(filePath.getName()).toLowerCase(Locale.ROOT);

String json;

switch (extension) {
case "yaml":
case "yml": {
ObjectMapper yamlReader = new ObjectMapper(new YAMLFactory());
Object obj = yamlReader.readValue(filePath.readToString(), Object.class);
ObjectMapper jsonWriter = new ObjectMapper();
json = jsonWriter.writeValueAsString(obj);
break;
}
case "json":
json = filePath.readToString();
break;
default:
throw new InvalidObjectException("File extension is not supported!");
}
List<Result> results = workspace.act(new FilesScanner(getPattern()));

try (InputStream inputStream = getClass().getResourceAsStream("/report.json")) {
JSONObject rawSchema = new JSONObject(new JSONTokener(inputStream));
SchemaLoader schemaLoader = SchemaLoader.builder()
.schemaClient(SchemaClient.classPathAwareClient())
.schemaJson(rawSchema)
.resolutionScope("classpath:/")
.build();
Schema schema = schemaLoader.load().build();
schema.validate(new JSONObject(json));

JacksonFacade jackson = new JacksonFacade();
Result result = jackson.fromJson(json, Result.class);

DisplayType dt = Arrays.stream(DisplayType.values())
.filter(e -> e.name().toLowerCase(Locale.ROOT).equals(getDisplayType()))
.findFirst().orElse(DisplayType.ABSOLUTE);

Report report = new Report(result, dt);
run.addAction(new ReportAction(run, report));

listener.getLogger().println(String.format("[PublishReportStep] Add report with id %s to current build.",
report.getResult().getId()));

} catch (ValidationException e) {
listener.getLogger().printf("[PublishReportStep] error: %s", e.getMessage());
}
DisplayType dt = Arrays.stream(DisplayType.values())
.filter(e -> e.name().toLowerCase(Locale.ROOT).equals(getDisplayType()))
.findFirst().orElse(DisplayType.ABSOLUTE);

results.stream()
.map(result -> new Report(result, dt))
.forEach(report -> {
run.addAction(new ReportAction(run, report));
listener.getLogger().println(String.format("[PublishReportStep] Add report with id %s to current build.",
report.getResult().getId()));
});
}

@Extension
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
import io.jenkins.plugins.reporter.charts.TrendChart;
import io.jenkins.plugins.reporter.model.Report;

import java.util.*;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
import edu.hm.hafner.echarts.SeriesBuilder;
import io.jenkins.plugins.reporter.ReportAction;
import io.jenkins.plugins.reporter.model.Item;
import org.apache.commons.collections.ListUtils;

import java.util.*;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import edu.hm.hafner.echarts.SeriesBuilder;
import io.jenkins.plugins.reporter.ReportAction;
import io.jenkins.plugins.reporter.model.Item;
import io.jenkins.plugins.reporter.model.Report;

import java.util.Map;
import java.util.stream.Collectors;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import io.jenkins.plugins.reporter.ReportAction;
import io.jenkins.plugins.reporter.model.Item;
import io.jenkins.plugins.reporter.model.Report;

import java.util.List;
import java.util.Optional;

Expand Down
74 changes: 74 additions & 0 deletions src/main/java/io/jenkins/plugins/reporter/model/FileFinder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package io.jenkins.plugins.reporter.model;

import hudson.remoting.VirtualChannel;
import jenkins.MasterToSlaveFileCallable;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.selectors.TypeSelector;

import java.io.File;
import java.io.IOException;

public class FileFinder extends MasterToSlaveFileCallable<String[]> {

private final String includesPattern;


/**
* Creates a new instance of {@link FileFinder}.
*
* @param includesPattern
* the ant file includes pattern to scan for
*/
public FileFinder(final String includesPattern) {
super();

this.includesPattern = includesPattern;
}

/**
* Returns an array with the file names of the specified file pattern that have been found in the workspace.
*
* @param workspace
* root directory of the workspace
* @param channel
* not used
*
* @return the file names of all found files
* @throws IOException
* if the workspace could not be read
*/
@Override
public String[] invoke(final File workspace, final VirtualChannel channel) throws IOException, InterruptedException {
return find(workspace);
}

/**
* Returns an array with the file names of the specified file pattern that have been found in the workspace.
*
* @param workspace
* root directory of the workspace
*
* @return the file names of all found files
*/
public String[] find(final File workspace) {
try {
FileSet fileSet = new FileSet();
Project antProject = new Project();
fileSet.setProject(antProject);
fileSet.setDir(workspace);
fileSet.setIncludes(includesPattern);
TypeSelector selector = new TypeSelector();
TypeSelector.FileType fileType = new TypeSelector.FileType();
fileType.setValue(TypeSelector.FileType.FILE);
selector.setType(fileType);
fileSet.addType(selector);

return fileSet.getDirectoryScanner(antProject).getIncludedFiles();
}
catch (BuildException ignored) {
return new String[0]; // as fallback do not return any file
}
}
}
Loading

0 comments on commit fb463ab

Please sign in to comment.