diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 34d1201..2b26ada 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,7 +3,6 @@ name: 'GitHub CI' on: push: branches: - - master - main pull_request: @@ -34,4 +33,4 @@ jobs: - name: Build with Maven env: BROWSER: chrome-container - run: mvn -V --color always -ntp clean verify --file pom.xml '-Djenkins.test.timeout=5000' '-Dgpg.skip' + run: mvn -V --color always -ntp clean verify '-Djenkins.test.timeout=5000' '-Dgpg.skip' '-Pci' diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index af74477..4004878 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -49,7 +49,7 @@ jobs: queries: +security-and-quality - name: Build with Maven - run: mvn -V --color always -ntp clean verify --file pom.xml -Pskip + run: mvn -V --color always -ntp clean verify -Pskip - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v3 diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 2804837..bada6d3 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -3,7 +3,6 @@ name: 'CodeCov' on: push: branches: - - master - main pull_request: @@ -27,7 +26,7 @@ jobs: with: maven-version: 3.9.6 - name: Generate coverage with JaCoCo - run: mvn -V --color always -ntp clean verify '-Dgpg.skip' + run: mvn -V --color always -ntp clean verify -Dgpg.skip -Pci - name: Upload coverage to Codecov uses: codecov/codecov-action@v4.3.1 with: diff --git a/.github/workflows/quality-monitor.yml b/.github/workflows/quality-monitor.yml index c1942da..a193c54 100644 --- a/.github/workflows/quality-monitor.yml +++ b/.github/workflows/quality-monitor.yml @@ -25,7 +25,7 @@ jobs: - name: Build with Maven env: BROWSER: chrome-container - run: mvn -V --color always -ntp clean verify -Ppit | tee maven.log + run: mvn -V --color always -ntp clean verify -Ppit -Pci | tee maven.log - name: Extract pull request number uses: jwalton/gh-find-current-pr@v1 id: pr @@ -34,3 +34,82 @@ jobs: with: github-token: ${{ secrets.GITHUB_TOKEN }} pr-number: ${{ steps.pr.outputs.number }} + config: > + { + "tests": { + "tools": [ + { + "id": "test", + "name": "Tests", + "pattern": "**/target/*-reports/TEST*.xml" + } + ], + "name": "Tests" + }, + "analysis": [ + { + "name": "Style", + "id": "style", + "tools": [ + { + "id": "checkstyle", + "pattern": "**/target/checkstyle-*/checkstyle-result.xml" + }, + { + "id": "pmd", + "pattern": "**/target/pmd-*/pmd.xml" + } + ] + }, + { + "name": "Bugs", + "id": "bugs", + "icon": "bug", + "tools": [ + { + "id": "spotbugs", + "sourcePath": "src/main/java", + "pattern": "**/target/spotbugsXml.xml" + }, + { + "id": "error-prone", + "icon": "bug", + "pattern": "**/maven.log" + } + ] + } + ], + "coverage": [ + { + "name": "Code Coverage", + "tools": [ + { + "id": "jacoco", + "name": "Line Coverage", + "metric": "line", + "sourcePath": "src/main/java", + "pattern": "**/target/site/jacoco/jacoco.xml" + }, + { + "id": "jacoco", + "name": "Branch Coverage", + "metric": "branch", + "sourcePath": "src/main/java", + "pattern": "**/target/site/jacoco/jacoco.xml" + } + ] + }, + { + "name": "Mutation Coverage", + "tools": [ + { + "id": "pit", + "name": "Mutation Coverage", + "metric": "mutation", + "sourcePath": "src/main/java", + "pattern": "**/target/pit-reports/mutations.xml" + } + ] + } + ] + } diff --git a/.github/workflows/update-badges.yml b/.github/workflows/update-badges.yml index 948d62a..54f3ed5 100644 --- a/.github/workflows/update-badges.yml +++ b/.github/workflows/update-badges.yml @@ -30,6 +30,84 @@ jobs: uses: uhafner/quality-monitor@v1 with: github-token: ${{ secrets.GITHUB_TOKEN }} + config: > + { + "tests": { + "tools": [ + { + "id": "test", + "name": "Tests", + "pattern": "**/target/*-reports/TEST*.xml" + } + ], + "name": "Tests" + }, + "analysis": [ + { + "name": "Style", + "id": "style", + "tools": [ + { + "id": "checkstyle", + "pattern": "**/target/checkstyle-*/checkstyle-result.xml" + }, + { + "id": "pmd", + "pattern": "**/target/pmd-*/pmd.xml" + } + ] + }, + { + "name": "Bugs", + "id": "bugs", + "icon": "bug", + "tools": [ + { + "id": "spotbugs", + "sourcePath": "src/main/java", + "pattern": "**/target/spotbugsXml.xml" + }, + { + "id": "error-prone", + "pattern": "**/maven.log" + } + ] + } + ], + "coverage": [ + { + "name": "Code Coverage", + "tools": [ + { + "id": "jacoco", + "name": "Line Coverage", + "metric": "line", + "sourcePath": "src/main/java", + "pattern": "**/target/site/jacoco/jacoco.xml" + }, + { + "id": "jacoco", + "name": "Branch Coverage", + "metric": "branch", + "sourcePath": "src/main/java", + "pattern": "**/target/site/jacoco/jacoco.xml" + } + ] + }, + { + "name": "Mutation Coverage", + "tools": [ + { + "id": "pit", + "name": "Mutation Coverage", + "metric": "mutation", + "sourcePath": "src/main/java", + "pattern": "**/target/pit-reports/mutations.xml" + } + ] + } + ] + } - name: Write metrics to GitHub output id: metrics run: | diff --git a/pom.xml b/pom.xml index 9afe02b..432583b 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ edu.hm.hafner codingstyle-pom - 4.5.0 + 4.9.0 diff --git a/src/main/java/edu/hm/hafner/grading/AnalysisMarkdown.java b/src/main/java/edu/hm/hafner/grading/AnalysisMarkdown.java index 651dd5c..b7caf63 100644 --- a/src/main/java/edu/hm/hafner/grading/AnalysisMarkdown.java +++ b/src/main/java/edu/hm/hafner/grading/AnalysisMarkdown.java @@ -87,10 +87,10 @@ private int sum(final AnalysisScore score, final Function" diff --git a/src/main/java/edu/hm/hafner/grading/AnalysisScore.java b/src/main/java/edu/hm/hafner/grading/AnalysisScore.java index 0508f4e..eef680c 100644 --- a/src/main/java/edu/hm/hafner/grading/AnalysisScore.java +++ b/src/main/java/edu/hm/hafner/grading/AnalysisScore.java @@ -119,10 +119,10 @@ public int getTotalSize() { @Override protected String createSummary() { if (getReport().isEmpty()) { - return "No warnings found"; + return "No warnings"; } else { - return String.format("%d warning%s found (%d error%s, %d high, %d normal, %d low)", + return String.format("%d warning%s (%d error%s, %d high, %d normal, %d low)", getTotalSize(), plural(getTotalSize()), getErrorSize(), plural(getErrorSize()), getHighSeveritySize(), getNormalSeveritySize(), getLowSeveritySize()); diff --git a/src/main/java/edu/hm/hafner/grading/FileSystemAnalysisReportFactory.java b/src/main/java/edu/hm/hafner/grading/FileSystemAnalysisReportFactory.java index 63a1a2c..21bef62 100644 --- a/src/main/java/edu/hm/hafner/grading/FileSystemAnalysisReportFactory.java +++ b/src/main/java/edu/hm/hafner/grading/FileSystemAnalysisReportFactory.java @@ -2,6 +2,8 @@ import java.nio.file.Path; +import org.apache.commons.lang3.StringUtils; + import edu.hm.hafner.analysis.FileReaderFactory; import edu.hm.hafner.analysis.Report; import edu.hm.hafner.analysis.registry.ParserDescriptor; @@ -23,17 +25,22 @@ public final class FileSystemAnalysisReportFactory implements AnalysisReportFact public Report create(final ToolConfiguration tool, final FilteredLog log) { ParserDescriptor parser = new ParserRegistry().get(tool.getId()); - var total = new Report(tool.getId(), tool.getDisplayName()); + var displayName = getDisplayName(tool, parser.getName()); + var total = new Report(tool.getId(), displayName); var analysisParser = parser.createParser(); - for (Path file : REPORT_FINDER.find(tool, log)) { + for (Path file : REPORT_FINDER.find(log, displayName, tool.getPattern())) { Report report = analysisParser.parseFile(new FileReaderFactory(file)); - report.setOrigin(tool.getId(), tool.getDisplayName()); + report.setOrigin(tool.getId(), displayName); log.logInfo("- %s: %d warnings", PATH_UTIL.getRelativePath(file), report.size()); total.addAll(report); } - log.logInfo("-> %s Total: %d warnings", tool.getDisplayName(), total.size()); + log.logInfo("-> %s Total: %d warnings", displayName, total.size()); return total; } + + private String getDisplayName(final ToolConfiguration tool, final String defaultName) { + return StringUtils.defaultIfBlank(tool.getName(), defaultName); + } } diff --git a/src/main/java/edu/hm/hafner/grading/ReportFinder.java b/src/main/java/edu/hm/hafner/grading/ReportFinder.java index 8044a1e..469cf90 100644 --- a/src/main/java/edu/hm/hafner/grading/ReportFinder.java +++ b/src/main/java/edu/hm/hafner/grading/ReportFinder.java @@ -32,14 +32,20 @@ class ReportFinder { * * @return the paths */ - public List find(final ToolConfiguration tool, final FilteredLog log) { - log.logInfo("Searching for %s results matching file name pattern %s", - tool.getDisplayName(), tool.getPattern()); - List files = find("glob:" + tool.getPattern(), ".", log); + List find(final ToolConfiguration tool, final FilteredLog log) { + var displayName = tool.getDisplayName(); + var pattern = tool.getPattern(); + + return find(log, displayName, pattern); + } + + List find(final FilteredLog log, final String displayName, final String pattern) { + log.logInfo("Searching for %s results matching file name pattern %s", displayName, pattern); + List files = find("glob:" + pattern, ".", log); if (files.isEmpty()) { log.logError("No matching report files found when using pattern '%s'! " - + "Configuration error for '%s'?", tool.getPattern(), tool.getDisplayName()); + + "Configuration error for '%s'?", pattern, displayName); } Collections.sort(files); diff --git a/src/main/java/edu/hm/hafner/grading/TestMarkdown.java b/src/main/java/edu/hm/hafner/grading/TestMarkdown.java index 2543911..b984d49 100644 --- a/src/main/java/edu/hm/hafner/grading/TestMarkdown.java +++ b/src/main/java/edu/hm/hafner/grading/TestMarkdown.java @@ -185,8 +185,8 @@ protected String createSummary(final TestScore score) { - :microscope:   Mutation Coverage: 93% mutations killed - ☑️ 99% Test strength --- -- :warning:   Style:: No warnings found -- :bug:   Bugs: No warnings found +- :warning:   Style:: No warnings +- :bug:   Bugs: No warnings
Created by [Quality Monitor](https://github.com/uhafner/quality-monitor/releases/tag/v1.6.0) v1.6.0 (#85eae94). More details are shown in the [GitHub Checks Result](https://github.com/jenkinsci/coverage-model/runs/23474192891). diff --git a/src/test/java/edu/hm/hafner/grading/AnalysisMarkdownTest.java b/src/test/java/edu/hm/hafner/grading/AnalysisMarkdownTest.java index 0e98090..231dd1b 100644 --- a/src/test/java/edu/hm/hafner/grading/AnalysisMarkdownTest.java +++ b/src/test/java/edu/hm/hafner/grading/AnalysisMarkdownTest.java @@ -58,7 +58,7 @@ void shouldShowMaximumScore() { .contains(IMPACT_CONFIGURATION); assertThat(analysisMarkdown.createSummary(score)) .contains("CheckStyle - 100 of 100") - .contains("No warnings found"); + .contains("No warnings"); } @Test @@ -87,7 +87,7 @@ void shouldShowScoreWithOneResult() { var analysisMarkdown = new AnalysisMarkdown(); assertThat(analysisMarkdown.createSummary(score)).contains( - "CS - 70 of 100: 10 warnings found (1 error, 2 high, 3 normal, 4 low)"); + "CS - 70 of 100: 10 warnings (1 error, 2 high, 3 normal, 4 low)"); assertThat(analysisMarkdown.createDetails(score)) .contains("TopLevel Warnings - 70 of 100") .contains("|CS|1|1|2|3|4|10|-30") @@ -126,8 +126,8 @@ void shouldShowScoreWithTwoSubResults() { assertThat(analysisMarkdown.createSummary(score)) .contains( - "CheckStyle - 70 of 100: 10 warnings found (1 error, 2 high, 3 normal, 4 low)", - "SpotBugs - 80 of 100: 10 warnings found (4 errors, 3 high, 2 normal, 1 low)"); + "CheckStyle - 70 of 100: 10 warnings (1 error, 2 high, 3 normal, 4 low)", + "SpotBugs - 80 of 100: 10 warnings (4 errors, 3 high, 2 normal, 1 low)"); assertThat(analysisMarkdown.createDetails(score)) .contains("CheckStyle - 50 of 100", "|CheckStyle|1|1|2|3|4|10|-30", @@ -162,8 +162,8 @@ void shouldShowNoImpactsWithTwoSubResults() { var analysisMarkdown = new AnalysisMarkdown(); assertThat(analysisMarkdown.createSummary(score)) - .contains("CheckStyle: 10 warnings found (1 error, 2 high, 3 normal, 4 low)", - "SpotBugs: 10 warnings found (4 errors, 3 high, 2 normal, 1 low)"); + .contains("CheckStyle: 10 warnings (1 error, 2 high, 3 normal, 4 low)", + "SpotBugs: 10 warnings (4 errors, 3 high, 2 normal, 1 low)"); assertThat(analysisMarkdown.createDetails(score)) .contains("CheckStyle", "|CheckStyle|1|1|2|3|4|10", @@ -217,10 +217,10 @@ void shouldShowScoreWithTwoResults() { ":moneybag:|:heavy_minus_sign:|*1*|*2*|*3*|*4*|:heavy_minus_sign:|:heavy_minus_sign:", ":moneybag:|:heavy_minus_sign:|*-11*|*-12*|*-13*|*-14*|:heavy_minus_sign:|:heavy_minus_sign:"); assertThat(analysisMarkdown.createSummary(score)) - .contains("CheckStyle 1 - 30 of 100: 10 warnings found (1 error, 2 high, 3 normal, 4 low)", - "CheckStyle 2 - 30 of 100: 10 warnings found (1 error, 2 high, 3 normal, 4 low)", - "SpotBugs 1 - 0 of 100: 10 warnings found (4 errors, 3 high, 2 normal, 1 low)", - "SpotBugs 2 - 0 of 100: 10 warnings found (4 errors, 3 high, 2 normal, 1 low)") + .contains("CheckStyle 1 - 30 of 100: 10 warnings (1 error, 2 high, 3 normal, 4 low)", + "CheckStyle 2 - 30 of 100: 10 warnings (1 error, 2 high, 3 normal, 4 low)", + "SpotBugs 1 - 0 of 100: 10 warnings (4 errors, 3 high, 2 normal, 1 low)", + "SpotBugs 2 - 0 of 100: 10 warnings (4 errors, 3 high, 2 normal, 1 low)") .doesNotContain("Total"); } diff --git a/src/test/java/edu/hm/hafner/grading/FileSystemAnalysisReportFactoryTest.java b/src/test/java/edu/hm/hafner/grading/FileSystemAnalysisReportFactoryTest.java index 5d2ab1b..39781f8 100644 --- a/src/test/java/edu/hm/hafner/grading/FileSystemAnalysisReportFactoryTest.java +++ b/src/test/java/edu/hm/hafner/grading/FileSystemAnalysisReportFactoryTest.java @@ -17,12 +17,10 @@ class FileSystemAnalysisReportFactoryTest { "tools": [ { "id": "checkstyle", - "name": "CheckStyle", "pattern": "**/src/**/checkstyle*.xml" }, { "id": "pmd", - "name": "PMD", "pattern": "**/src/**/pmd*.xml" } ], @@ -35,11 +33,15 @@ class FileSystemAnalysisReportFactoryTest { { "name": "Bugs", "id": "bugs", + "icon": "bug", "tools": [ { "id": "spotbugs", - "name": "SpotBugs", "pattern": "**/src/**/spotbugs*.xml" + }, + { + "id": "error-prone", + "pattern": "**/src/**/error-prone.log" } ], "errorImpact": -11, @@ -51,7 +53,7 @@ class FileSystemAnalysisReportFactoryTest { ] } """; - private static final int EXPECTED_ISSUES = 6 + 4 + 2; + private static final int EXPECTED_ISSUES = 6 + 4 + 2 + 1; @Test void shouldCreateAggregation() { @@ -66,7 +68,8 @@ void shouldCreateAggregation() { "CopyToClipboard.java", "ChangeSelectionAction.java", "SelectSourceDialog.java", - "IssuesTest.java"); + "IssuesTest.java", + "RobocopyParser.java"); assertThat(score.getIssues().stream() .filter(issue -> issue.getBaseName().equals("CsharpNamespaceDetector.java"))) .map(Issue::getOriginName) @@ -82,6 +85,21 @@ void shouldCreateAggregation() { "Searching for SpotBugs results matching file name pattern **/src/**/spotbugs*.xml", "- src/test/resources/edu/hm/hafner/grading/spotbugsXml.xml: 2 warnings", "-> SpotBugs Total: 2 warnings", - "=> Bugs Score: 72 of 100"); + "Searching for Error Prone results matching file name pattern **/src/**/error-prone.log", + "- src/test/resources/edu/hm/hafner/grading/error-prone.log: 1 warnings", + "-> Error Prone Total: 1 warnings", + "=> Bugs Score: 59 of 100"); + + var gradingReport = new GradingReport(); + assertThat(gradingReport.getMarkdownSummary(score)).contains( + "Autograding score - 77 of 200 (38%)", + " AnalysisMarkdownTest.createTwoReports(tool)); assertThat(logger.getInfoMessages()).contains( "Processing 2 static analysis configuration(s)", - "=> Style: 10 warnings found (1 error, 2 high, 3 normal, 4 low)", - "=> Bugs: 10 warnings found (4 errors, 3 high, 2 normal, 1 low)"); + "=> Style: 10 warnings (1 error, 2 high, 3 normal, 4 low)", + "=> Bugs: 10 warnings (4 errors, 3 high, 2 normal, 1 low)"); aggregation.gradeTests((tool, log) -> TestMarkdownTest.createTwoReports(tool)); assertThat(logger.getInfoMessages()).contains( @@ -229,8 +229,8 @@ void shouldSkipScores() { "Line Coverage: 80% (20 missed lines)", "Branch Coverage: 60% (40 missed branches)", "Mutation Coverage: 60% (40 survived mutations)", - "Checkstyle: 10 warnings found (1 error, 2 high, 3 normal, 4 low)", - "SpotBugs: 10 warnings found (4 errors, 3 high, 2 normal, 1 low)"); + "Checkstyle: 10 warnings (1 error, 2 high, 3 normal, 4 low)", + "SpotBugs: 10 warnings (4 errors, 3 high, 2 normal, 1 low)"); assertThat(results.getTextSummary(aggregation)).isEqualTo( "Autograding score"); assertThat(results.getTextSummary(aggregation, "Quality Summary")).isEqualTo( diff --git a/src/test/resources/edu/hm/hafner/grading/error-prone.log b/src/test/resources/edu/hm/hafner/grading/error-prone.log new file mode 100644 index 0000000..f82d4f5 --- /dev/null +++ b/src/test/resources/edu/hm/hafner/grading/error-prone.log @@ -0,0 +1,7 @@ +[INFO] Compiling 143 source files to /Users/hafner/Development/jenkins/workspace/Model - Freestyle - New/target/classes +[WARNING] /Users/hafner/Development/jenkins/workspace/Model - Freestyle - New/src/main/java/edu/hm/hafner/analysis/parser/RobocopyParser.java:[29,45] [StringSplitter] String.split(String) has surprising behavior + (see http://errorprone.info/bugpattern/StringSplitter) + Did you mean 'String file = matcher.group(4).split("\\s{11}", -1)[0];'? +[INFO] +[INFO] --- maven-resources-plugin:3.1.0:testResources (default-testResources) @ analysis-model --- +[INFO] Using 'UTF-8' encoding to copy filtered resources.