mirror of
https://github.com/theonedev/onedev.git
synced 2025-12-08 18:26:30 +00:00
CI/CD support for rust projects
feat: Able to analyze and publish rust clippy report (OD-2113) feat: Job template for rust projects (OD-2112)
This commit is contained in:
parent
4ef6a697d5
commit
f84faed69d
@ -350,6 +350,11 @@
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.8.9</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.moandjiezana.toml</groupId>
|
||||
<artifactId>toml4j</artifactId>
|
||||
<version>0.7.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.hazelcast</groupId>
|
||||
<artifactId>hazelcast-hibernate53</artifactId>
|
||||
|
||||
@ -3,8 +3,11 @@ package io.onedev.server.util;
|
||||
import org.dom4j.io.SAXReader;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class XmlUtils {
|
||||
|
||||
private static final Pattern DOC_TYPE = Pattern.compile("<!DOCTYPE\\s.*?>", Pattern.DOTALL);
|
||||
// Prevent XXE attack as the xml might be provided by malicious users
|
||||
public static void disallowDocTypeDecl(SAXReader reader) {
|
||||
try {
|
||||
@ -15,7 +18,7 @@ public class XmlUtils {
|
||||
}
|
||||
|
||||
public static String stripDoctype(String xml) {
|
||||
return xml.replaceFirst("<!DOCTYPE\\s.*?>", "");
|
||||
return DOC_TYPE.matcher(xml).replaceFirst("");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,5 +1,20 @@
|
||||
.problem-popover.popover {
|
||||
max-width: 370px;
|
||||
max-width: 360px;
|
||||
}
|
||||
@media(min-width: 600px) {
|
||||
.problem-popover.popover {
|
||||
max-width: 400px;
|
||||
}
|
||||
}
|
||||
@media(min-width: 900px) {
|
||||
.problem-popover.popover {
|
||||
max-width: 600px;
|
||||
}
|
||||
}
|
||||
@media(min-width: 1200px) {
|
||||
.problem-popover.popover {
|
||||
max-width: 900px;
|
||||
}
|
||||
}
|
||||
.problem-popover .problem-content+.problem-content {
|
||||
margin-top: 0.75rem;
|
||||
|
||||
@ -848,4 +848,4 @@ span.keycap {
|
||||
border-radius: 2px;
|
||||
background: #C9F7F5;
|
||||
color: #1BC5BD;
|
||||
}
|
||||
}
|
||||
|
||||
@ -27,6 +27,7 @@
|
||||
<module>server-plugin-buildspec-cmake</module>
|
||||
<module>server-plugin-buildspec-bazel</module>
|
||||
<module>server-plugin-buildspec-golang</module>
|
||||
<module>server-plugin-buildspec-rust</module>
|
||||
<module>server-plugin-authenticator-ldap</module>
|
||||
<module>server-plugin-mailservice-smtpimap</module>
|
||||
<module>server-plugin-mailservice-office365</module>
|
||||
@ -63,6 +64,7 @@
|
||||
<module>server-plugin-report-ruff</module>
|
||||
<module>server-plugin-report-mypy</module>
|
||||
<module>server-plugin-report-cppcheck</module>
|
||||
<module>server-plugin-report-clippy</module>
|
||||
<module>server-plugin-sso-discord</module>
|
||||
<module>server-plugin-notification-slack</module>
|
||||
<module>server-plugin-notification-discord</module>
|
||||
|
||||
@ -23,11 +23,6 @@
|
||||
<artifactId>server-plugin-report-ruff</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.moandjiezana.toml</groupId>
|
||||
<artifactId>toml4j</artifactId>
|
||||
<version>0.7.2</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<properties>
|
||||
<moduleClass>io.onedev.server.plugin.buildspec.python.PythonModule</moduleClass>
|
||||
|
||||
30
server-plugin/server-plugin-buildspec-rust/pom.xml
Normal file
30
server-plugin/server-plugin-buildspec-rust/pom.xml
Normal file
@ -0,0 +1,30 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>server-plugin-buildspec-rust</artifactId>
|
||||
<parent>
|
||||
<groupId>io.onedev</groupId>
|
||||
<artifactId>server-plugin</artifactId>
|
||||
<version>11.2.1</version>
|
||||
</parent>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.onedev</groupId>
|
||||
<artifactId>server-plugin-report-junit</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.onedev</groupId>
|
||||
<artifactId>server-plugin-report-cobertura</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.onedev</groupId>
|
||||
<artifactId>server-plugin-report-clippy</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<properties>
|
||||
<moduleClass>io.onedev.server.plugin.buildspec.rust.RustModule</moduleClass>
|
||||
</properties>
|
||||
</project>
|
||||
@ -0,0 +1,137 @@
|
||||
package io.onedev.server.plugin.buildspec.rust;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.moandjiezana.toml.Toml;
|
||||
import io.onedev.k8shelper.ExecuteCondition;
|
||||
import io.onedev.server.buildspec.job.Job;
|
||||
import io.onedev.server.buildspec.job.JobSuggestion;
|
||||
import io.onedev.server.buildspec.job.trigger.BranchUpdateTrigger;
|
||||
import io.onedev.server.buildspec.job.trigger.PullRequestUpdateTrigger;
|
||||
import io.onedev.server.buildspec.step.*;
|
||||
import io.onedev.server.git.Blob;
|
||||
import io.onedev.server.git.BlobIdent;
|
||||
import io.onedev.server.model.Project;
|
||||
import io.onedev.server.plugin.report.clippy.PublishClippyReportStep;
|
||||
import io.onedev.server.plugin.report.cobertura.PublishCoberturaReportStep;
|
||||
import io.onedev.server.plugin.report.junit.PublishJUnitReportStep;
|
||||
import org.eclipse.jgit.lib.FileMode;
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class RustJobSuggestion implements JobSuggestion {
|
||||
|
||||
|
||||
private GenerateChecksumStep newChecksumGenerateStep(String name, String files) {
|
||||
var generateChecksum = new GenerateChecksumStep();
|
||||
generateChecksum.setName(name);
|
||||
generateChecksum.setFiles(files);
|
||||
generateChecksum.setTargetFile("checksum");
|
||||
return generateChecksum;
|
||||
}
|
||||
|
||||
private Job newJob() {
|
||||
Job job = new Job();
|
||||
job.setName("rust ci");
|
||||
return job;
|
||||
}
|
||||
|
||||
private void addCommonJobsAndTriggers(Job job) {
|
||||
var checkout = new CheckoutStep();
|
||||
checkout.setName("checkout code");
|
||||
job.getSteps().add(0, checkout);
|
||||
job.getSteps().add(newUnitTestReportPublishStep());
|
||||
job.getSteps().add(newCoverageReportPublishStep());
|
||||
job.getSteps().add(newClippyReportPublishStep());
|
||||
job.getTriggers().add(new BranchUpdateTrigger());
|
||||
job.getTriggers().add(new PullRequestUpdateTrigger());
|
||||
}
|
||||
|
||||
private PublishJUnitReportStep newUnitTestReportPublishStep() {
|
||||
var publishUnitTestReport = new PublishJUnitReportStep();
|
||||
publishUnitTestReport.setName("publish unit test report");
|
||||
publishUnitTestReport.setReportName("Unit Test");
|
||||
publishUnitTestReport.setFilePatterns("target/nextest/default/test-result.xml");
|
||||
publishUnitTestReport.setCondition(ExecuteCondition.ALWAYS);
|
||||
return publishUnitTestReport;
|
||||
}
|
||||
|
||||
private PublishCoberturaReportStep newCoverageReportPublishStep() {
|
||||
var publishCoverageReportStep = new PublishCoberturaReportStep();
|
||||
publishCoverageReportStep.setName("publish coverage report");
|
||||
publishCoverageReportStep.setReportName("Coverage");
|
||||
publishCoverageReportStep.setFilePatterns("coverage.xml");
|
||||
publishCoverageReportStep.setCondition(ExecuteCondition.ALWAYS);
|
||||
return publishCoverageReportStep;
|
||||
}
|
||||
|
||||
private PublishClippyReportStep newClippyReportPublishStep() {
|
||||
var publishClippyReportStep = new PublishClippyReportStep();
|
||||
publishClippyReportStep.setName("publish clippy report");
|
||||
publishClippyReportStep.setReportName("Clippy");
|
||||
publishClippyReportStep.setFilePatterns("check-result.json");
|
||||
publishClippyReportStep.setCondition(ExecuteCondition.ALWAYS);
|
||||
return publishClippyReportStep;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Job> suggestJobs(Project project, ObjectId commitId) {
|
||||
List<Job> jobs = new ArrayList<>();
|
||||
Blob blob;
|
||||
if ((blob = project.getBlob(new BlobIdent(commitId.name(), "Cargo.toml", FileMode.TYPE_FILE), false)) != null) {
|
||||
Job job = newJob();
|
||||
var cargoToml = new Toml().read(blob.getText().getContent());
|
||||
if (cargoToml.getString("package.version") != null) {
|
||||
CommandStep detectBuildVersion = new CommandStep();
|
||||
detectBuildVersion.setName("detect build version");
|
||||
detectBuildVersion.setImage("1dev/yq:1.0.0");
|
||||
detectBuildVersion.getInterpreter().setCommands("yq '.package.version' Cargo.toml > buildVersion");
|
||||
job.getSteps().add(detectBuildVersion);
|
||||
|
||||
SetBuildVersionStep setBuildVersion = new SetBuildVersionStep();
|
||||
setBuildVersion.setName("set build version");
|
||||
setBuildVersion.setBuildVersion("@file:buildVersion@");
|
||||
job.getSteps().add(setBuildVersion);
|
||||
}
|
||||
|
||||
job.getSteps().add(newChecksumGenerateStep("generate dependency checksum", "**/Cargo.toml **/Cargo.lock"));
|
||||
var setupCache = new SetupCacheStep();
|
||||
setupCache.setName("set up dependency cache");
|
||||
setupCache.setKey("rust_cache_@file:checksum@");
|
||||
setupCache.setPaths(Lists.newArrayList("/root/.cache/cargo"));
|
||||
setupCache.getLoadKeys().add("rust_cache");
|
||||
job.getSteps().add(setupCache);
|
||||
|
||||
CommandStep buildAndTest = new CommandStep();
|
||||
buildAndTest.setName("build and test");
|
||||
|
||||
buildAndTest.setImage("1dev/rust:1.0.3");
|
||||
buildAndTest.getInterpreter().setCommands("" +
|
||||
"set -e\n" +
|
||||
"\n" +
|
||||
"# Set CARGO_HOME to cache folder so that downloaded artifacts can be populated there. Note that we cannot cache '/root/.cargo' directly as cache folder will be mounted from an empty folder initially\n" +
|
||||
"export CARGO_HOME=/root/.cache/cargo\n" +
|
||||
"mkdir -p .config\n" +
|
||||
"cat << EOF > .config/nextest.toml\n" +
|
||||
"[profile.default.junit]\n" +
|
||||
"path = \"test-result.xml\"\n" +
|
||||
"store-success-output = true\n" +
|
||||
"store-failure-output = true\n" +
|
||||
"EOF\n" +
|
||||
"cargo llvm-cov nextest --lcov --output-path lcov.info\n" +
|
||||
"lcov_cobertura lcov.info -o coverage.xml\n" +
|
||||
"# cargo clippy --message-format=json > check-result.json\n" +
|
||||
"\n" +
|
||||
"# Make sure all files inside $CARGO_HOME is accessible by OneDev outside of container for cache upload\n" +
|
||||
"chmod -R o+r $CARGO_HOME");
|
||||
job.getSteps().add(buildAndTest);
|
||||
|
||||
addCommonJobsAndTriggers(job);
|
||||
jobs.add(job);
|
||||
}
|
||||
return jobs;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
package io.onedev.server.plugin.buildspec.rust;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import io.onedev.commons.loader.AbstractPluginModule;
|
||||
import io.onedev.server.buildspec.job.JobSuggestion;
|
||||
import io.onedev.server.model.support.administration.GroovyScript;
|
||||
import io.onedev.server.util.ScriptContribution;
|
||||
|
||||
/**
|
||||
* NOTE: Do not forget to rename moduleClass property defined in the pom if you've renamed this class.
|
||||
*
|
||||
*/
|
||||
public class RustModule extends AbstractPluginModule {
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
super.configure();
|
||||
|
||||
// put your guice bindings here
|
||||
contribute(JobSuggestion.class, RustJobSuggestion.class);
|
||||
}
|
||||
|
||||
}
|
||||
@ -9,9 +9,9 @@ import io.onedev.server.annotation.Interpolative;
|
||||
import io.onedev.server.annotation.Patterns;
|
||||
import io.onedev.server.buildspec.BuildSpec;
|
||||
import io.onedev.server.buildspec.step.StepGroup;
|
||||
import io.onedev.server.codequality.BlobTarget;
|
||||
import io.onedev.server.codequality.CodeProblem;
|
||||
import io.onedev.server.codequality.CodeProblem.Severity;
|
||||
import io.onedev.server.codequality.BlobTarget;
|
||||
import io.onedev.server.model.Build;
|
||||
import io.onedev.server.plugin.report.problem.PublishProblemReportStep;
|
||||
import io.onedev.server.util.XmlUtils;
|
||||
@ -19,7 +19,6 @@ import org.dom4j.Document;
|
||||
import org.dom4j.DocumentException;
|
||||
import org.dom4j.Element;
|
||||
import org.dom4j.io.SAXReader;
|
||||
import org.unbescape.html.HtmlEscape;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import java.io.File;
|
||||
@ -29,6 +28,8 @@ import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.unbescape.html.HtmlEscape.escapeHtml5;
|
||||
|
||||
@Editable(order=10000, group=StepGroup.PUBLISH, name="Checkstyle Report")
|
||||
public class PublishCheckstyleReportStep extends PublishProblemReportStep {
|
||||
|
||||
@ -85,8 +86,7 @@ public class PublishCheckstyleReportStep extends PublishProblemReportStep {
|
||||
else
|
||||
severity = Severity.LOW;
|
||||
|
||||
String message = violationElement.attributeValue("source") + ": "
|
||||
+ HtmlEscape.escapeHtml5(violationElement.attributeValue("message"));
|
||||
String message = violationElement.attributeValue("source") + ": " + violationElement.attributeValue("message");
|
||||
int lineNo = Integer.parseInt(violationElement.attributeValue("line"))-1;
|
||||
String column = violationElement.attributeValue("column");
|
||||
|
||||
@ -98,7 +98,7 @@ public class PublishCheckstyleReportStep extends PublishProblemReportStep {
|
||||
location = new PlanarRange(lineNo, -1, lineNo, -1, tabWidth);
|
||||
}
|
||||
|
||||
problems.add(new CodeProblem(severity, new BlobTarget(blobPath, location), message));
|
||||
problems.add(new CodeProblem(severity, new BlobTarget(blobPath, location), escapeHtml5(message)));
|
||||
}
|
||||
} else {
|
||||
logger.warning("Unable to find blob path for file: " + filePath);
|
||||
|
||||
20
server-plugin/server-plugin-report-clippy/pom.xml
Normal file
20
server-plugin/server-plugin-report-clippy/pom.xml
Normal file
@ -0,0 +1,20 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>server-plugin-report-clippy</artifactId>
|
||||
<parent>
|
||||
<groupId>io.onedev</groupId>
|
||||
<artifactId>server-plugin</artifactId>
|
||||
<version>11.2.1</version>
|
||||
</parent>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.onedev</groupId>
|
||||
<artifactId>server-plugin-report-problem</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<properties>
|
||||
<moduleClass>io.onedev.server.plugin.report.clippy.ClippyModule</moduleClass>
|
||||
</properties>
|
||||
</project>
|
||||
@ -0,0 +1,39 @@
|
||||
package io.onedev.server.plugin.report.clippy;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
import io.onedev.commons.loader.AbstractPluginModule;
|
||||
import io.onedev.commons.loader.ImplementationProvider;
|
||||
import io.onedev.server.buildspec.step.PublishReportStep;
|
||||
|
||||
/**
|
||||
* NOTE: Do not forget to rename moduleClass property defined in the pom if you've renamed this class.
|
||||
*
|
||||
*/
|
||||
public class ClippyModule extends AbstractPluginModule {
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
super.configure();
|
||||
|
||||
// put your guice bindings here
|
||||
|
||||
contribute(ImplementationProvider.class, new ImplementationProvider() {
|
||||
|
||||
@Override
|
||||
public Class<?> getAbstractClass() {
|
||||
return PublishReportStep.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Class<?>> getImplementations() {
|
||||
return Sets.newHashSet(PublishClippyReportStep.class);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,69 @@
|
||||
package io.onedev.server.plugin.report.clippy;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import io.onedev.commons.utils.PlanarRange;
|
||||
import io.onedev.commons.utils.TaskLogger;
|
||||
import io.onedev.server.codequality.BlobTarget;
|
||||
import io.onedev.server.codequality.CodeProblem;
|
||||
import io.onedev.server.model.Build;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.*;
|
||||
|
||||
import static java.lang.Integer.parseInt;
|
||||
import static org.unbescape.html.HtmlEscape.escapeHtml5;
|
||||
|
||||
public class ClippyReportParser {
|
||||
|
||||
@Nullable
|
||||
private static String getBlobPath(Build build, Map<String, Optional<String>> blobPaths,
|
||||
String filePath, TaskLogger logger) {
|
||||
var blobPath = blobPaths.get(filePath);
|
||||
if (blobPath == null) {
|
||||
blobPath = Optional.ofNullable(build.getBlobPath(filePath));
|
||||
if (blobPath.isEmpty())
|
||||
logger.warning("Unable to find blob path for file: " + filePath);
|
||||
blobPaths.put(filePath, blobPath);
|
||||
}
|
||||
return blobPath.orElse(null);
|
||||
}
|
||||
|
||||
public static List<CodeProblem> parse(Build build, List<JsonNode> problemNodes, TaskLogger logger) {
|
||||
var problems = new ArrayList<CodeProblem>();
|
||||
Map<String, Optional<String>> blobPaths = new HashMap<>();
|
||||
for (var problemNode: problemNodes) {
|
||||
var messageNode = problemNode.get("message");
|
||||
if (messageNode != null && messageNode.hasNonNull("spans")
|
||||
&& !messageNode.get("spans").isEmpty() && messageNode.hasNonNull("rendered")) {
|
||||
CodeProblem.Severity severity = CodeProblem.Severity.LOW;
|
||||
var levelNode = messageNode.get("level");
|
||||
if (levelNode != null) {
|
||||
switch (levelNode.asText()) {
|
||||
case "error":
|
||||
severity = CodeProblem.Severity.HIGH;
|
||||
break;
|
||||
case "warning":
|
||||
severity = CodeProblem.Severity.MEDIUM;
|
||||
}
|
||||
}
|
||||
var message = new StringBuilder();
|
||||
message.append(messageNode.get("rendered").asText());
|
||||
var spanNode = messageNode.get("spans").iterator().next();
|
||||
var blobPath = getBlobPath(build, blobPaths, spanNode.get("file_name").asText(), logger);
|
||||
if (blobPath != null) {
|
||||
PlanarRange location;
|
||||
int lineStart = parseInt(spanNode.get("line_start").asText());
|
||||
int columnStart = parseInt(spanNode.get("column_start").asText());
|
||||
int lineEnd = parseInt(spanNode.get("line_end").asText());
|
||||
int columnEnd = parseInt(spanNode.get("column_end").asText());
|
||||
if (lineStart == lineEnd && columnStart == columnEnd)
|
||||
columnEnd++;
|
||||
location = new PlanarRange(lineStart - 1, columnStart - 1, lineEnd - 1, columnEnd - 1);
|
||||
problems.add(new CodeProblem(severity, new BlobTarget(blobPath, location), escapeHtml5(message.toString())));
|
||||
}
|
||||
}
|
||||
}
|
||||
return problems;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,70 @@
|
||||
package io.onedev.server.plugin.report.clippy;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.google.common.collect.Lists;
|
||||
import io.onedev.commons.codeassist.InputSuggestion;
|
||||
import io.onedev.commons.utils.FileUtils;
|
||||
import io.onedev.commons.utils.TaskLogger;
|
||||
import io.onedev.server.OneDev;
|
||||
import io.onedev.server.annotation.Editable;
|
||||
import io.onedev.server.annotation.Interpolative;
|
||||
import io.onedev.server.annotation.Patterns;
|
||||
import io.onedev.server.buildspec.BuildSpec;
|
||||
import io.onedev.server.buildspec.step.StepGroup;
|
||||
import io.onedev.server.codequality.CodeProblem;
|
||||
import io.onedev.server.model.Build;
|
||||
import io.onedev.server.plugin.report.problem.PublishProblemReportStep;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Editable(order=10000, group=StepGroup.PUBLISH, name="Clippy Report")
|
||||
public class PublishClippyReportStep extends PublishProblemReportStep {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Editable(order=100, description="Specify <a href='https://github.com/rust-lang/rust-clippy'>rust clippy</a> json output file relative to <a href='https://docs.onedev.io/concepts#job-workspace'>job workspace</a>. "
|
||||
+ "This file can be generated with clippy json output option, for instance <code>cargo clippy --message-format json>check-result.json</code>. Use * or ? for pattern match")
|
||||
@Interpolative(variableSuggester="suggestVariables")
|
||||
@Patterns(path=true)
|
||||
@NotEmpty
|
||||
@Override
|
||||
public String getFilePatterns() {
|
||||
return super.getFilePatterns();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFilePatterns(String filePatterns) {
|
||||
super.setFilePatterns(filePatterns);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static List<InputSuggestion> suggestVariables(String matchWith) {
|
||||
return BuildSpec.suggestVariables(matchWith, true, true, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<CodeProblem> process(Build build, File inputDir, File reportDir, TaskLogger logger) {
|
||||
try {
|
||||
var mapper = OneDev.getInstance(ObjectMapper.class);
|
||||
List<CodeProblem> problems = new ArrayList<>();
|
||||
int baseLen = inputDir.getAbsolutePath().length()+1;
|
||||
for (File file: FileUtils.listFiles(inputDir, Lists.newArrayList("**"), Lists.newArrayList())) {
|
||||
logger.log("Processing clippy report: " + file.getAbsolutePath().substring(baseLen));
|
||||
var problemNodes = new ArrayList<JsonNode>();
|
||||
for (var line: FileUtils.readLines(file, StandardCharsets.UTF_8))
|
||||
problemNodes.add(mapper.readTree(line));
|
||||
problems.addAll(ClippyReportParser.parse(build, problemNodes, logger));
|
||||
}
|
||||
return problems;
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,55 @@
|
||||
package io.onedev.server.plugin.report.clippy;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.google.common.io.Resources;
|
||||
import io.onedev.commons.utils.TaskLogger;
|
||||
import io.onedev.server.codequality.BlobTarget;
|
||||
import io.onedev.server.codequality.CodeProblem;
|
||||
import io.onedev.server.model.Build;
|
||||
import io.onedev.server.util.IOUtils;
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class ClippyReportParserTest {
|
||||
|
||||
@Test
|
||||
public void testParse() {
|
||||
try (InputStream is = Resources.getResource(ClippyReportParserTest.class, "check-result.json").openStream()) {
|
||||
Build build = new Build() {
|
||||
@Override
|
||||
public String getBlobPath(String filePath) {
|
||||
return filePath;
|
||||
}
|
||||
};
|
||||
|
||||
build.setCommitHash(ObjectId.zeroId().name());
|
||||
|
||||
var mapper = new ObjectMapper();
|
||||
var problemNodes = new ArrayList<JsonNode>();
|
||||
for (var line: IOUtils.readLines(is, StandardCharsets.UTF_8))
|
||||
problemNodes.add(mapper.readTree(line));
|
||||
var problems = ClippyReportParser.parse(build, problemNodes, new TaskLogger() {
|
||||
@Override
|
||||
public void log(String message, @Nullable String sessionId) {
|
||||
}
|
||||
});
|
||||
assertEquals(5, problems.size());
|
||||
assertEquals(CodeProblem.Severity.MEDIUM, problems.get(0).getSeverity());
|
||||
assertEquals("29.23-29.54-1", ((BlobTarget)problems.get(0).getTarget()).getLocation().toString());
|
||||
assertEquals(CodeProblem.Severity.MEDIUM, problems.get(3).getSeverity());
|
||||
assertEquals("78.5-78.6-1", ((BlobTarget)problems.get(3).getTarget()).getLocation().toString());
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#proc-macro2@1.0.85","manifest_path":"/Users/robin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/proc-macro2-1.0.85/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/Users/robin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/proc-macro2-1.0.85/build.rs","edition":"2021","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default","proc-macro"],"filenames":["/Users/robin/temp/zola/target/debug/build/proc-macro2-f4040980c7bda631/build-script-build"],"executable":null,"fresh":true}
|
||||
{"reason":"compiler-message","package_id":"path+file:///Users/robin/temp/zola/components/utils#0.1.0","manifest_path":"/Users/robin/temp/zola/components/utils/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"utils","src_path":"/Users/robin/temp/zola/components/utils/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"message":{"rendered":"warning: length comparison to zero\n --> components/utils/src/de.rs:29:23\n |\n29 | ... fraction = if fraction_intermediate.len() > 0 { fraction_intermediat...\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!fraction_intermediate.is_empty()`\n |\n = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#len_zero\n = note: `#[warn(clippy::len_zero)]` on by default\n\n","$message_type":"diagnostic","children":[{"children":[],"code":null,"level":"help","message":"for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#len_zero","rendered":null,"spans":[]},{"children":[],"code":null,"level":"note","message":"`#[warn(clippy::len_zero)]` on by default","rendered":null,"spans":[]},{"children":[],"code":null,"level":"help","message":"using `!is_empty` is clearer and more explicit","rendered":null,"spans":[{"byte_end":1646,"byte_start":1615,"column_end":54,"column_start":23,"expansion":null,"file_name":"components/utils/src/de.rs","is_primary":true,"label":null,"line_end":29,"line_start":29,"suggested_replacement":"!fraction_intermediate.is_empty()","suggestion_applicability":"MachineApplicable","text":[{"highlight_end":54,"highlight_start":23,"text":" let fraction = if fraction_intermediate.len() > 0 { fraction_intermediate } else { \"0\" };"}]}]}],"code":{"code":"clippy::len_zero","explanation":null},"level":"warning","message":"length comparison to zero","spans":[{"byte_end":1646,"byte_start":1615,"column_end":54,"column_start":23,"expansion":null,"file_name":"components/utils/src/de.rs","is_primary":true,"label":null,"line_end":29,"line_start":29,"suggested_replacement":null,"suggestion_applicability":null,"text":[{"highlight_end":54,"highlight_start":23,"text":" let fraction = if fraction_intermediate.len() > 0 { fraction_intermediate } else { \"0\" };"}]}]}}
|
||||
{"reason":"compiler-message","package_id":"path+file:///Users/robin/temp/zola/components/utils#0.1.0","manifest_path":"/Users/robin/temp/zola/components/utils/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"utils","src_path":"/Users/robin/temp/zola/components/utils/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"message":{"rendered":"warning: this expression creates a reference which is immediately dereferenced by the compiler\n --> components/utils/src/fs.rs:80:19\n |\n80 | create_parent(&dest)?;\n | ^^^^^ help: change this to: `dest`\n |\n = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow\n = note: `#[warn(clippy::needless_borrow)]` on by default\n\n","$message_type":"diagnostic","children":[{"children":[],"code":null,"level":"help","message":"for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow","rendered":null,"spans":[]},{"children":[],"code":null,"level":"note","message":"`#[warn(clippy::needless_borrow)]` on by default","rendered":null,"spans":[]},{"children":[],"code":null,"level":"help","message":"change this to","rendered":null,"spans":[{"byte_end":2812,"byte_start":2807,"column_end":24,"column_start":19,"expansion":null,"file_name":"components/utils/src/fs.rs","is_primary":true,"label":null,"line_end":80,"line_start":80,"suggested_replacement":"dest","suggestion_applicability":"MachineApplicable","text":[{"highlight_end":24,"highlight_start":19,"text":" create_parent(&dest)?;"}]}]}],"code":{"code":"clippy::needless_borrow","explanation":null},"level":"warning","message":"this expression creates a reference which is immediately dereferenced by the compiler","spans":[{"byte_end":2812,"byte_start":2807,"column_end":24,"column_start":19,"expansion":null,"file_name":"components/utils/src/fs.rs","is_primary":true,"label":null,"line_end":80,"line_start":80,"suggested_replacement":null,"suggestion_applicability":null,"text":[{"highlight_end":24,"highlight_start":19,"text":" create_parent(&dest)?;"}]}]}}
|
||||
{"reason":"compiler-message","package_id":"path+file:///Users/robin/temp/zola/components/utils#0.1.0","manifest_path":"/Users/robin/temp/zola/components/utils/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"utils","src_path":"/Users/robin/temp/zola/components/utils/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"message":{"rendered":"warning: this manual char comparison can be written more succinctly\n --> components/utils/src/slugs.rs:26:38\n |\n26 | let trimmed = s.trim_end_matches(|c| c == ' ' || c == '.');\n | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using an array of `char`: `[' ', '.']`\n |\n = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#manual_pattern_char_comparison\n = note: `#[warn(clippy::manual_pattern_char_comparison)]` on by default\n\n","$message_type":"diagnostic","children":[{"children":[],"code":null,"level":"help","message":"for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#manual_pattern_char_comparison","rendered":null,"spans":[]},{"children":[],"code":null,"level":"note","message":"`#[warn(clippy::manual_pattern_char_comparison)]` on by default","rendered":null,"spans":[]},{"children":[],"code":null,"level":"help","message":"consider using an array of `char`","rendered":null,"spans":[{"byte_end":873,"byte_start":849,"column_end":62,"column_start":38,"expansion":null,"file_name":"components/utils/src/slugs.rs","is_primary":true,"label":null,"line_end":26,"line_start":26,"suggested_replacement":"[' ', '.']","suggestion_applicability":"MachineApplicable","text":[{"highlight_end":62,"highlight_start":38,"text":" let trimmed = s.trim_end_matches(|c| c == ' ' || c == '.');"}]}]}],"code":{"code":"clippy::manual_pattern_char_comparison","explanation":null},"level":"warning","message":"this manual char comparison can be written more succinctly","spans":[{"byte_end":873,"byte_start":849,"column_end":62,"column_start":38,"expansion":null,"file_name":"components/utils/src/slugs.rs","is_primary":true,"label":null,"line_end":26,"line_start":26,"suggested_replacement":null,"suggestion_applicability":null,"text":[{"highlight_end":62,"highlight_start":38,"text":" let trimmed = s.trim_end_matches(|c| c == ' ' || c == '.');"}]}]}}
|
||||
{"reason":"compiler-message","package_id":"path+file:///Users/robin/temp/zola/components/utils#0.1.0","manifest_path":"/Users/robin/temp/zola/components/utils/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"utils","src_path":"/Users/robin/temp/zola/components/utils/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"message":{"rendered":"warning: 3 warnings emitted\n\n","$message_type":"diagnostic","children":[],"code":null,"level":"warning","message":"3 warnings emitted","spans":[]}}
|
||||
{"reason":"compiler-artifact","package_id":"path+file:///Users/robin/temp/zola/components/utils#0.1.0","manifest_path":"/Users/robin/temp/zola/components/utils/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"utils","src_path":"/Users/robin/temp/zola/components/utils/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/Users/robin/temp/zola/target/debug/deps/libutils-c09278f6e65bd41f.rmeta"],"executable":null,"fresh":true}
|
||||
{"reason":"compiler-artifact","package_id":"path+file:///Users/robin/temp/zola/components/console#0.1.0","manifest_path":"/Users/robin/temp/zola/components/console/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"console","src_path":"/Users/robin/temp/zola/components/console/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/Users/robin/temp/zola/target/debug/deps/libconsole-465709f8f3e18ca5.rmeta"],"executable":null,"fresh":true}
|
||||
{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#getrandom@0.1.16","manifest_path":"/Users/robin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/getrandom-0.1.16/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"getrandom","src_path":"/Users/robin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/getrandom-0.1.16/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["std"],"filenames":["/Users/robin/temp/zola/target/debug/deps/libgetrandom-7813f0a8d28687a3.rmeta"],"executable":null,"fresh":true}
|
||||
{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#anstyle@1.0.7","manifest_path":"/Users/robin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/anstyle-1.0.7/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"anstyle","src_path":"/Users/robin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/anstyle-1.0.7/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default","std"],"filenames":["/Users/robin/temp/zola/target/debug/deps/libanstyle-19c86a7d68421148.rmeta"],"executable":null,"fresh":true}
|
||||
{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#is_terminal_polyfill@1.70.0","manifest_path":"/Users/robin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/is_terminal_polyfill-1.70.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"is_terminal_polyfill","src_path":"/Users/robin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/is_terminal_polyfill-1.70.0/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default"],"filenames":["/Users/robin/temp/zola/target/debug/deps/libis_terminal_polyfill-1c35c4e83590019b.rmeta"],"executable":null,"fresh":true}
|
||||
{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#powerfmt@0.2.0","manifest_path":"/Users/robin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/powerfmt-0.2.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"powerfmt","src_path":"/Users/robin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/powerfmt-0.2.0/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/Users/robin/temp/zola/target/debug/deps/libpowerfmt-6998240b76618d9b.rlib","/Users/robin/temp/zola/target/debug/deps/libpowerfmt-6998240b76618d9b.rmeta"],"executable":null,"fresh":true}
|
||||
{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#cfg-if@0.1.10","manifest_path":"/Users/robin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/cfg-if-0.1.10/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"cfg_if","src_path":"/Users/robin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/cfg-if-0.1.10/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/Users/robin/temp/zola/target/debug/deps/libcfg_if-5f7cbaaf39cc4df9.rmeta"],"executable":null,"fresh":true}
|
||||
{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#nix@0.28.0","manifest_path":"/Users/robin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/nix-0.28.0/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/Users/robin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/nix-0.28.0/build.rs","edition":"2021","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["fs","process","signal"],"filenames":["/Users/robin/temp/zola/target/debug/build/nix-f8ac794f013e692c/build-script-build"],"executable":null,"fresh":true}
|
||||
{"reason":"compiler-artifact","package_id":"path+file:///Users/robin/temp/zola/components/config#0.1.0","manifest_path":"/Users/robin/temp/zola/components/config/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"config","src_path":"/Users/robin/temp/zola/components/config/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/Users/robin/temp/zola/target/debug/deps/libconfig-f8438e411985c0b9.rmeta"],"executable":null,"fresh":true}
|
||||
{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#rand_core@0.5.1","manifest_path":"/Users/robin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rand_core-0.5.1/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"rand_core","src_path":"/Users/robin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rand_core-0.5.1/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["alloc","getrandom","std"],"filenames":["/Users/robin/temp/zola/target/debug/deps/librand_core-213d5b82d2159aa0.rmeta"],"executable":null,"fresh":true}
|
||||
{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#anstream@0.6.14","manifest_path":"/Users/robin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/anstream-0.6.14/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"anstream","src_path":"/Users/robin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/anstream-0.6.14/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["auto","default","wincon"],"filenames":["/Users/robin/temp/zola/target/debug/deps/libanstream-d0b0ebe9353fae29.rmeta"],"executable":null,"fresh":true}
|
||||
{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#deranged@0.3.11","manifest_path":"/Users/robin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/deranged-0.3.11/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"deranged","src_path":"/Users/robin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/deranged-0.3.11/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["alloc","powerfmt","std"],"filenames":["/Users/robin/temp/zola/target/debug/deps/libderanged-14fa1f7dc06bb337.rlib","/Users/robin/temp/zola/target/debug/deps/libderanged-14fa1f7dc06bb337.rmeta"],"executable":null,"fresh":true}
|
||||
{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#net2@0.2.39","manifest_path":"/Users/robin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/net2-0.2.39/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"net2","src_path":"/Users/robin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/net2-0.2.39/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default","duration"],"filenames":["/Users/robin/temp/zola/target/debug/deps/libnet2-4a27462e4f22df38.rmeta"],"executable":null,"fresh":true}
|
||||
{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#block-padding@0.1.5","manifest_path":"/Users/robin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/block-padding-0.1.5/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"block_padding","src_path":"/Users/robin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/block-padding-0.1.5/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/Users/robin/temp/zola/target/debug/deps/libblock_padding-abdeba7f674c2ab5.rmeta"],"executable":null,"fresh":true}
|
||||
{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#kamadak-exif@0.5.5","manifest_path":"/Users/robin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/kamadak-exif-0.5.5/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"exif","src_path":"/Users/robin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/kamadak-exif-0.5.5/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/Users/robin/temp/zola/target/debug/deps/libexif-435c9b5453728dd5.rmeta"],"executable":null,"fresh":true}
|
||||
{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#unicase@2.7.0","manifest_path":"/Users/robin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/unicase-2.7.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"unicase","src_path":"/Users/robin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/unicase-2.7.0/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/Users/robin/temp/zola/target/debug/deps/libunicase-f28739690847d4bb.rlib","/Users/robin/temp/zola/target/debug/deps/libunicase-f28739690847d4bb.rmeta"],"executable":null,"fresh":true}
|
||||
{"reason":"compiler-artifact","package_id":"path+file:///Users/robin/temp/zola/components/markdown#0.1.0","manifest_path":"/Users/robin/temp/zola/components/markdown/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"markdown","src_path":"/Users/robin/temp/zola/components/markdown/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/Users/robin/temp/zola/target/debug/deps/libmarkdown-2af279526114c711.rmeta"],"executable":null,"fresh":true}
|
||||
{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#toml@0.5.11","manifest_path":"/Users/robin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/toml-0.5.11/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"toml","src_path":"/Users/robin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/toml-0.5.11/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default"],"filenames":["/Users/robin/temp/zola/target/debug/deps/libtoml-4a03a679e33f15d7.rlib","/Users/robin/temp/zola/target/debug/deps/libtoml-4a03a679e33f15d7.rmeta"],"executable":null,"fresh":true}
|
||||
{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#heck@0.5.0","manifest_path":"/Users/robin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/heck-0.5.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"heck","src_path":"/Users/robin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/heck-0.5.0/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/Users/robin/temp/zola/target/debug/deps/libheck-c7f34bf60343d28b.rlib","/Users/robin/temp/zola/target/debug/deps/libheck-c7f34bf60343d28b.rmeta"],"executable":null,"fresh":true}
|
||||
{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#clap_lex@0.7.1","manifest_path":"/Users/robin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/clap_lex-0.7.1/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"clap_lex","src_path":"/Users/robin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/clap_lex-0.7.1/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/Users/robin/temp/zola/target/debug/deps/libclap_lex-ba1a9257ad086ed8.rmeta"],"executable":null,"fresh":true}
|
||||
{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#strsim@0.11.1","manifest_path":"/Users/robin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/strsim-0.11.1/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"strsim","src_path":"/Users/robin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/strsim-0.11.1/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/Users/robin/temp/zola/target/debug/deps/libstrsim-450171a639ada5f5.rmeta"],"executable":null,"fresh":true}
|
||||
{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#mime_guess@2.0.4","manifest_path":"/Users/robin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/mime_guess-2.0.4/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/Users/robin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/mime_guess-2.0.4/build.rs","edition":"2015","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default","rev-mappings"],"filenames":["/Users/robin/temp/zola/target/debug/build/mime_guess-b5eed588b8a20482/build-script-build"],"executable":null,"fresh":true}
|
||||
{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#rand_chacha@0.2.2","manifest_path":"/Users/robin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rand_chacha-0.2.2/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"rand_chacha","src_path":"/Users/robin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rand_chacha-0.2.2/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["std"],"filenames":["/Users/robin/temp/zola/target/debug/deps/librand_chacha-2d378126a001264e.rmeta"],"executable":null,"fresh":true}
|
||||
{"reason":"compiler-artifact","package_id":"path+file:///Users/robin/temp/zola/components/imageproc#0.1.0","manifest_path":"/Users/robin/temp/zola/components/imageproc/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"imageproc","src_path":"/Users/robin/temp/zola/components/imageproc/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/Users/robin/temp/zola/target/debug/deps/libimageproc-3d67d1373cb34e71.rmeta"],"executable":null,"fresh":true}
|
||||
{"reason":"compiler-message","package_id":"path+file:///Users/robin/temp/zola/components/content#0.1.0","manifest_path":"/Users/robin/temp/zola/components/content/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"content","src_path":"/Users/robin/temp/zola/components/content/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"message":{"rendered":"warning: doc list item without indentation\n --> components/content/src/front_matter/page.rs:78:5\n |\n78 | /// This tries each in order.\n | ^\n |\n = help: if this is supposed to be its own paragraph, add a blank line\n = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#doc_lazy_continuation\n = note: `#[warn(clippy::doc_lazy_continuation)]` on by default\nhelp: indent this line\n |\n78 | /// This tries each in order.\n | +++\n\n","$message_type":"diagnostic","children":[{"children":[],"code":null,"level":"help","message":"if this is supposed to be its own paragraph, add a blank line","rendered":null,"spans":[]},{"children":[],"code":null,"level":"help","message":"for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#doc_lazy_continuation","rendered":null,"spans":[]},{"children":[],"code":null,"level":"note","message":"`#[warn(clippy::doc_lazy_continuation)]` on by default","rendered":null,"spans":[]},{"children":[],"code":null,"level":"help","message":"indent this line","rendered":null,"spans":[{"byte_end":3155,"byte_start":3155,"column_end":5,"column_start":5,"expansion":null,"file_name":"components/content/src/front_matter/page.rs","is_primary":true,"label":null,"line_end":78,"line_start":78,"suggested_replacement":" ","suggestion_applicability":"MaybeIncorrect","text":[{"highlight_end":5,"highlight_start":5,"text":"/// This tries each in order."}]}]}],"code":{"code":"clippy::doc_lazy_continuation","explanation":null},"level":"warning","message":"doc list item without indentation","spans":[{"byte_end":3155,"byte_start":3155,"column_end":5,"column_start":5,"expansion":null,"file_name":"components/content/src/front_matter/page.rs","is_primary":true,"label":null,"line_end":78,"line_start":78,"suggested_replacement":null,"suggestion_applicability":null,"text":[{"highlight_end":5,"highlight_start":5,"text":"/// This tries each in order."}]}]}}
|
||||
{"reason":"compiler-message","package_id":"path+file:///Users/robin/temp/zola/components/content#0.1.0","manifest_path":"/Users/robin/temp/zola/components/content/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"content","src_path":"/Users/robin/temp/zola/components/content/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"message":{"rendered":"warning: the borrowed expression implements the required traits\n --> components/content/src/page.rs:271:35\n |\n271 | .strip_prefix(&base_path.join(\"content\"))\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: change this to: `base_path.join(\"content\")`\n |\n = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrows_for_generic_args\n = note: `#[warn(clippy::needless_borrows_for_generic_args)]` on by default\n\n","$message_type":"diagnostic","children":[{"children":[],"code":null,"level":"help","message":"for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrows_for_generic_args","rendered":null,"spans":[]},{"children":[],"code":null,"level":"note","message":"`#[warn(clippy::needless_borrows_for_generic_args)]` on by default","rendered":null,"spans":[]},{"children":[],"code":null,"level":"help","message":"change this to","rendered":null,"spans":[{"byte_end":10380,"byte_start":10354,"column_end":61,"column_start":35,"expansion":null,"file_name":"components/content/src/page.rs","is_primary":true,"label":null,"line_end":271,"line_start":271,"suggested_replacement":"base_path.join(\"content\")","suggestion_applicability":"MachineApplicable","text":[{"highlight_end":61,"highlight_start":35,"text":" .strip_prefix(&base_path.join(\"content\"))"}]}]}],"code":{"code":"clippy::needless_borrows_for_generic_args","explanation":null},"level":"warning","message":"the borrowed expression implements the required traits","spans":[{"byte_end":10380,"byte_start":10354,"column_end":61,"column_start":35,"expansion":null,"file_name":"components/content/src/page.rs","is_primary":true,"label":null,"line_end":271,"line_start":271,"suggested_replacement":null,"suggestion_applicability":null,"text":[{"highlight_end":61,"highlight_start":35,"text":" .strip_prefix(&base_path.join(\"content\"))"}]}]}}
|
||||
{"reason":"compiler-message","package_id":"path+file:///Users/robin/temp/zola/components/content#0.1.0","manifest_path":"/Users/robin/temp/zola/components/content/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"content","src_path":"/Users/robin/temp/zola/components/content/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"message":{"rendered":"warning: 2 warnings emitted\n\n","$message_type":"diagnostic","children":[],"code":null,"level":"warning","message":"2 warnings emitted","spans":[]}}
|
||||
{"reason":"build-finished","success":true}
|
||||
@ -13,12 +13,6 @@
|
||||
<artifactId>server-plugin-report-coverage</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.onedev</groupId>
|
||||
<artifactId>commons-loader</artifactId>
|
||||
<type>test-jar</type>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<properties>
|
||||
<moduleClass>io.onedev.server.plugin.report.cobertura.CoberturaModule</moduleClass>
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
package io.onedev.server.plugin.report.cobertura;
|
||||
|
||||
import com.google.common.io.Resources;
|
||||
import io.onedev.commons.loader.AppLoaderMocker;
|
||||
import io.onedev.commons.utils.FileUtils;
|
||||
import io.onedev.commons.utils.TaskLogger;
|
||||
import io.onedev.server.codequality.CoverageStatus;
|
||||
@ -18,7 +17,7 @@ import java.util.HashMap;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class PublishCoberturaReportStepTest extends AppLoaderMocker {
|
||||
public class PublishCoberturaReportStepTest {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
@ -127,13 +126,4 @@ public class PublishCoberturaReportStepTest extends AppLoaderMocker {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setup() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void teardown() {
|
||||
|
||||
}
|
||||
}
|
||||
@ -11,6 +11,7 @@ import javax.annotation.Nullable;
|
||||
import java.util.*;
|
||||
|
||||
import static java.lang.Integer.parseInt;
|
||||
import static org.unbescape.html.HtmlEscape.escapeHtml5;
|
||||
|
||||
public class CppcheckReportParser {
|
||||
|
||||
@ -69,7 +70,7 @@ public class CppcheckReportParser {
|
||||
location = new PlanarRange(line-1, column-1, line-1, column);
|
||||
else
|
||||
location = new PlanarRange(line-1, -1, line-1, -1);
|
||||
problems.add(new CodeProblem(severity, new BlobTarget(blobPath, location), message.toString()));
|
||||
problems.add(new CodeProblem(severity, new BlobTarget(blobPath, location), escapeHtml5(message.toString())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,8 +5,8 @@ import com.google.common.base.Splitter;
|
||||
import io.onedev.commons.utils.ExplicitException;
|
||||
import io.onedev.commons.utils.PlanarRange;
|
||||
import io.onedev.commons.utils.TaskLogger;
|
||||
import io.onedev.server.codequality.CodeProblem;
|
||||
import io.onedev.server.codequality.BlobTarget;
|
||||
import io.onedev.server.codequality.CodeProblem;
|
||||
import io.onedev.server.model.Build;
|
||||
import org.apache.commons.lang3.math.NumberUtils;
|
||||
|
||||
@ -16,6 +16,7 @@ import java.util.*;
|
||||
import static io.onedev.server.codequality.CodeProblem.Severity.LOW;
|
||||
import static io.onedev.server.codequality.CodeProblem.Severity.MEDIUM;
|
||||
import static java.lang.Integer.parseInt;
|
||||
import static org.unbescape.html.HtmlEscape.escapeHtml5;
|
||||
|
||||
public class MypyReportParser {
|
||||
|
||||
@ -75,7 +76,7 @@ public class MypyReportParser {
|
||||
if (blobPath.isPresent()) {
|
||||
var location = new PlanarRange(parsedLine.fromRow-1, parsedLine.fromColumn-1, parsedLine.toRow-1, parsedLine.toColumn, 1);
|
||||
var severity = parsedLine.error?MEDIUM:LOW;
|
||||
problems.add(new CodeProblem(severity, new BlobTarget(blobPath.get(), location), parsedLine.message));
|
||||
problems.add(new CodeProblem(severity, new BlobTarget(blobPath.get(), location), escapeHtml5(parsedLine.message)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -9,9 +9,9 @@ import io.onedev.server.annotation.Interpolative;
|
||||
import io.onedev.server.annotation.Patterns;
|
||||
import io.onedev.server.buildspec.BuildSpec;
|
||||
import io.onedev.server.buildspec.step.StepGroup;
|
||||
import io.onedev.server.codequality.BlobTarget;
|
||||
import io.onedev.server.codequality.CodeProblem;
|
||||
import io.onedev.server.codequality.CodeProblem.Severity;
|
||||
import io.onedev.server.codequality.BlobTarget;
|
||||
import io.onedev.server.model.Build;
|
||||
import io.onedev.server.plugin.report.problem.PublishProblemReportStep;
|
||||
import io.onedev.server.util.XmlUtils;
|
||||
@ -19,7 +19,6 @@ import org.dom4j.Document;
|
||||
import org.dom4j.DocumentException;
|
||||
import org.dom4j.Element;
|
||||
import org.dom4j.io.SAXReader;
|
||||
import org.unbescape.html.HtmlEscape;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import java.io.File;
|
||||
@ -29,6 +28,8 @@ import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.unbescape.html.HtmlEscape.escapeHtml5;
|
||||
|
||||
@Editable(order=10000, group=StepGroup.PUBLISH, name="PMD Report")
|
||||
public class PublishPMDReportStep extends PublishProblemReportStep {
|
||||
|
||||
@ -92,7 +93,7 @@ public class PublishPMDReportStep extends PublishProblemReportStep {
|
||||
else
|
||||
severity = Severity.LOW;
|
||||
|
||||
String message = type + ": " + HtmlEscape.escapeHtml5(violationElement.getText());
|
||||
String message = escapeHtml5(type + ": " + violationElement.getText());
|
||||
problems.add(new CodeProblem(severity, new BlobTarget(blobPath, location), message));
|
||||
}
|
||||
} else {
|
||||
|
||||
@ -319,7 +319,7 @@ public class ProblemReportPage extends BuildReportPage {
|
||||
severityLabel.add(AttributeAppender.append("class", "badge-warning"));
|
||||
else
|
||||
severityLabel.add(AttributeAppender.append("class", "badge-secondary"));
|
||||
|
||||
|
||||
item.add(new Label("message", problem.getMessage()).setEscapeModelStrings(false));
|
||||
|
||||
if (problem.getTarget() instanceof BlobTarget
|
||||
|
||||
@ -3,13 +3,14 @@ package io.onedev.server.plugin.report.pylint;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import io.onedev.commons.utils.PlanarRange;
|
||||
import io.onedev.commons.utils.TaskLogger;
|
||||
import io.onedev.server.codequality.CodeProblem;
|
||||
import io.onedev.server.codequality.BlobTarget;
|
||||
import io.onedev.server.codequality.CodeProblem;
|
||||
import io.onedev.server.model.Build;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static java.lang.Integer.parseInt;
|
||||
import static org.unbescape.html.HtmlEscape.escapeHtml5;
|
||||
|
||||
public class PylintReportParser {
|
||||
|
||||
@ -48,7 +49,7 @@ public class PylintReportParser {
|
||||
if (problemNode.hasNonNull("endColumn"))
|
||||
endColumn = parseInt(problemNode.get("endColumn").asText());
|
||||
var location = new PlanarRange(line-1, column, endLine-1, endColumn);
|
||||
problems.add(new CodeProblem(severity, new BlobTarget(blobPath.get(), location), message));
|
||||
problems.add(new CodeProblem(severity, new BlobTarget(blobPath.get(), location), escapeHtml5(message)));
|
||||
}
|
||||
}
|
||||
return problems;
|
||||
|
||||
@ -10,9 +10,9 @@ import io.onedev.server.annotation.Interpolative;
|
||||
import io.onedev.server.annotation.Patterns;
|
||||
import io.onedev.server.buildspec.BuildSpec;
|
||||
import io.onedev.server.buildspec.step.StepGroup;
|
||||
import io.onedev.server.codequality.BlobTarget;
|
||||
import io.onedev.server.codequality.CodeProblem;
|
||||
import io.onedev.server.codequality.CodeProblem.Severity;
|
||||
import io.onedev.server.codequality.BlobTarget;
|
||||
import io.onedev.server.model.Build;
|
||||
import io.onedev.server.plugin.report.problem.PublishProblemReportStep;
|
||||
import io.onedev.server.util.XmlUtils;
|
||||
@ -75,10 +75,10 @@ public class PublishRoslynatorReportStep extends PublishProblemReportStep {
|
||||
Map<String, String> messages = new HashMap<>();
|
||||
for (var diagnosticElement: codeAnalysisElement.element("Summary").elements("Diagnostic")) {
|
||||
var id = diagnosticElement.attributeValue("Id");
|
||||
var message = escapeHtml5(diagnosticElement.attributeValue("Title"));
|
||||
var message = diagnosticElement.attributeValue("Title");
|
||||
var description = diagnosticElement.elementText("Description");
|
||||
if (description != null)
|
||||
message += "<br><br>" + escapeHtml5(description);
|
||||
message += "\n\n" + description;
|
||||
messages.put(id, message);
|
||||
}
|
||||
for (var projectElement: codeAnalysisElement.element("Projects").elements("Project")) {
|
||||
@ -112,7 +112,7 @@ public class PublishRoslynatorReportStep extends PublishProblemReportStep {
|
||||
int line = parseInt(locationElement.attributeValue("Line"));
|
||||
int character = parseInt(locationElement.attributeValue("Character"));
|
||||
var location = new PlanarRange(line-1, character-1, line-1, character);
|
||||
problems.add(new CodeProblem(severity, new BlobTarget(blobPath.get(), location), message));
|
||||
problems.add(new CodeProblem(severity, new BlobTarget(blobPath.get(), location), escapeHtml5(message)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,13 +3,14 @@ package io.onedev.server.plugin.report.ruff;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import io.onedev.commons.utils.PlanarRange;
|
||||
import io.onedev.commons.utils.TaskLogger;
|
||||
import io.onedev.server.codequality.CodeProblem;
|
||||
import io.onedev.server.codequality.BlobTarget;
|
||||
import io.onedev.server.codequality.CodeProblem;
|
||||
import io.onedev.server.model.Build;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static java.lang.Integer.parseInt;
|
||||
import static org.unbescape.html.HtmlEscape.escapeHtml5;
|
||||
|
||||
public class RuffReportParser {
|
||||
|
||||
@ -33,7 +34,7 @@ public class RuffReportParser {
|
||||
int endColumn = parseInt(problemNode.get("end_location").get("column").asText());
|
||||
|
||||
var location = new PlanarRange(row-1, column-1, endRow-1, endColumn-1);
|
||||
problems.add(new CodeProblem(CodeProblem.Severity.MEDIUM, new BlobTarget(blobPath.get(), location), message));
|
||||
problems.add(new CodeProblem(CodeProblem.Severity.MEDIUM, new BlobTarget(blobPath.get(), location), escapeHtml5(message)));
|
||||
}
|
||||
}
|
||||
return problems;
|
||||
|
||||
@ -9,9 +9,9 @@ import io.onedev.server.annotation.Interpolative;
|
||||
import io.onedev.server.annotation.Patterns;
|
||||
import io.onedev.server.buildspec.BuildSpec;
|
||||
import io.onedev.server.buildspec.step.StepGroup;
|
||||
import io.onedev.server.codequality.BlobTarget;
|
||||
import io.onedev.server.codequality.CodeProblem;
|
||||
import io.onedev.server.codequality.CodeProblem.Severity;
|
||||
import io.onedev.server.codequality.BlobTarget;
|
||||
import io.onedev.server.model.Build;
|
||||
import io.onedev.server.plugin.report.problem.PublishProblemReportStep;
|
||||
import io.onedev.server.util.XmlUtils;
|
||||
@ -20,7 +20,6 @@ import org.dom4j.Document;
|
||||
import org.dom4j.DocumentException;
|
||||
import org.dom4j.Element;
|
||||
import org.dom4j.io.SAXReader;
|
||||
import org.unbescape.html.HtmlEscape;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
@ -31,6 +30,8 @@ import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.unbescape.html.HtmlEscape.escapeHtml5;
|
||||
|
||||
@Editable(order=10000, group=StepGroup.PUBLISH, name="SpotBugs Report")
|
||||
public class PublishSpotBugsReportStep extends PublishProblemReportStep {
|
||||
|
||||
@ -92,7 +93,7 @@ public class PublishSpotBugsReportStep extends PublishProblemReportStep {
|
||||
if (StringUtils.isBlank(message))
|
||||
message = bugElement.elementText("ShortMessage");
|
||||
|
||||
message = type + ": " + HtmlEscape.escapeHtml5(message);
|
||||
message = type + ": " + message;
|
||||
|
||||
PlanarRange location = getLocation(bugElement, true);
|
||||
|
||||
@ -105,7 +106,7 @@ public class PublishSpotBugsReportStep extends PublishProblemReportStep {
|
||||
if (location == null)
|
||||
location = new PlanarRange(0, -1, 0, -1);
|
||||
|
||||
problems.add(new CodeProblem(severity, new BlobTarget(blobPath, location), message));
|
||||
problems.add(new CodeProblem(severity, new BlobTarget(blobPath, location), escapeHtml5(message)));
|
||||
} else {
|
||||
logger.warning("Unable to find blob path for file: " + filePath);
|
||||
}
|
||||
|
||||
@ -85,6 +85,11 @@
|
||||
<artifactId>server-plugin-buildspec-golang</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.onedev</groupId>
|
||||
<artifactId>server-plugin-buildspec-rust</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.onedev</groupId>
|
||||
<artifactId>server-plugin-buildspec-node</artifactId>
|
||||
@ -160,6 +165,11 @@
|
||||
<artifactId>server-plugin-report-cppcheck</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.onedev</groupId>
|
||||
<artifactId>server-plugin-report-clippy</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.onedev</groupId>
|
||||
<artifactId>server-plugin-report-pmd</artifactId>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user