Skip to content
This repository was archived by the owner on Nov 19, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 43 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
[![Codecov](https://codecov.io/gh/jenkinsci/code-coverage-api/branch/master/graph/badge.svg)](https://codecov.io/gh/jenkinsci/code-coverage-api-plugin/branch/master)
[![CodeQL](https://github.com/jenkinsci/code-coverage-api/workflows/CodeQL/badge.svg?branch=master)](https://github.com/jenkinsci/code-coverage-api/actions/workflows/codeql.yml)

The Jenkins code coverage plug-in collects reports of code coverage or mutation coverage tools. It has support for the following report formats:
The Jenkins Code Coverage Plug-in collects reports of code coverage or mutation coverage tools. It has support for the following report formats:

- [JaCoCo](https://www.jacoco.org/jacoco)
- [Cobertura](https://cobertura.github.io/cobertura/)
Expand All @@ -25,46 +25,66 @@ This project was part of [GSoC 2018](https://jenkins.io/projects/gsoc/2018/code-

## Features

The code coverage plug-in provides the following features when added as a post build action (or step)
to a job:
The code coverage plug-in provides the following features when added as a post build action (or step) to a job:

* **Coverage analysis of projects and pull requests:**
* all project code (Project Coverage)
* code changes (Modified Lines or Files Coverage)
* coverage changes created by changed test cases (Indirect Coverage Changes)
* **Modernized coverage report visualization:**
* Coverage overview and trend
* Coverage analysis of projects and pull requests: The plugin now computes and shows the absolute coverage of the project, the coverage of the modified files and the coverage of the modified lines, so you can see how the changes actually affect the code coverage. Additionally, the delta of these coverages with respect to the reference build are computed and the coverage changes created by changed test cases (indirect coverage changes).

![alt text](./images/reportOverview_screen.PNG "Coverage overview and trend")
![Coverage overview and trend](./images/summary.png)

* Coverage overview and trend:

![Coverage overview and trend](./images/reportOverview_screen.PNG)

* Colored project coverage tree map for line and branch coverage
* Colored project coverage tree map for line, branch, instruction and mutation coverage:

![alt text](./images/reportTree_screen.PNG "Colored project coverage tree map")
![Colored project coverage tree map](./images/reportTree_screen.PNG)

* Source code navigation
* Source code navigation with a configuration option to store the source code files for all builds, for current build only, or for changed files only:

![alt text](./images/reportFile_screen.PNG "Source code navigation")
![Source code navigation](./images/reportFile_screen.PNG)

* Specific source code view for specifically analyzing the coverage of code changes (Change Coverage):
* Specific source code view for analyzing the coverage of changed code lines:

![alt text](./images/reportCC_screen.PNG "Specific source code view for Change Coverage")
![Specific source code view for Change Coverage](./images/reportCC_screen.PNG)

* Specific source code view for specifically analyzing the coverage after test changes (Indirect Coverage Changes):
* Specific source code view for analyzing the coverage changes that are a result of test changes (indirect coverage changes):

![alt text](./images/reportICC_screen.PNG "Specific source code view for Indirect Coverage Changes")
![Specific source code view for Indirect Coverage Changes](./images/reportICC_screen.PNG)

* Customizable coverage overview for the Jenkins dashboard view and for build results:

* **Customizable coverage overview for the Jenkins dashboard view and for build results:**
![alt text](./images/dashboard_screen.PNG "Analysis overview for Jenkins dashboard")
![alt text](./images/buildview_screen.PNG "Analysis overview for Jenkins build result")

* Quality Gates: You can specify an arbitrary number of quality gates that allow to set the build to unstable or failed if the thresholds are not met. For each quality gate the metric (branch coverage, complexity, etc.) and the baseline (whole project, changed files, etc.) can be defined.

![Quality Gates](./images/quality-gates.png)

* Cyclomatic Complexity and LOC metrics: Several coverage parsers support the measurement of cyclomatic complexity and lines of code. These metrics are now computed and recorded as well:

![Cyclomatic Complexity and LOC metrics](./images/all-metrics.png)

* The recorder has been extended with a native step that is capable of setting the step status (unstable, failed, ok):

![Native step](./images/step.png)

* GitHub checks report to show the detailed line and branch coverage results for pull request:

![Code Coverage Checks Overview](./images/jacoco-coverage-checks.png)
![Code Coverage Checks Annotations](./images/jacoco-coverage-checks-annotations.png)

* GitHub checks report to show the detailed line and mutation coverage results for pull request:

![Mutation Coverage Checks Overview](./images/pit-coverage-checks.png)
![Mutation Coverage Checks Annotations](./images/pit-coverage-checks-annotations.png)


## Usage

:exclamation: The plugin does not run the code coverage, it just visualizes the results reported by such tools.
You still need to enable and configure the code coverage tool in your build file or Jenkinsfile.
:exclamation: The plugin does not run the code coverage, it just visualizes the results reported by such tools. You still need to enable and configure the code coverage tool in your build file or Jenkinsfile. :exclamation:

### Supported project types

The Warnings Next Generation plugin supports the following Jenkins project types:
The Code Coverage Plug-in supports the following Jenkins project types:

- Freestyle Project
- Maven Project
Expand Down
35 changes: 35 additions & 0 deletions etc/Jenkinsfile.analysis
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
node('java-agent') {
stage ('Checkout') {
checkout scm
}

stage ('Git mining') {
discoverGitReferenceBuild()
mineRepository()
gitDiffStat()
}

stage ('Build, Test, and Static Analysis') {
withMaven(mavenLocalRepo: '/var/data/m2repository', mavenOpts: '-Xmx768m -Xms512m') {
sh 'mvn -V -e clean verify -Dmaven.test.failure.ignore -Dgpg.skip'
}

recordIssues tools: [java(), javaDoc()], aggregatingResults: 'true', id: 'java', name: 'Java', filters:[excludeFile('.*Assert.java')]
recordIssues tool: errorProne(), healthy: 1, unhealthy: 20

junit testResults: '**/target/*-reports/TEST-*.xml'
recordCoverage tools: [[parser: 'JACOCO', pattern: '**/jacoco/jacoco.xml']], sourceCodeRetention: 'EVERY_BUILD',
qualityGates: [ [threshold: 90.0, metric: 'LINE', baseline: 'PROJECT', criticality: 'UNSTABLE']],
sourceDirectories: [[path: 'plugin/src/main/java']]
recordIssues tools: [checkStyle(pattern: 'target/checkstyle-result.xml'),
spotBugs(pattern: 'target/spotbugsXml.xml'),
pmdParser(pattern: 'target/pmd.xml'),
cpd(pattern: 'target/cpd.xml'),
revApi(pattern: 'target/revapi-result.json'),
taskScanner(highTags:'FIXME', normalTags:'TODO', includePattern: '**/*.java', excludePattern: 'target/**/*')]
}

stage ('Collect Maven Warnings') {
recordIssues tool: mavenConsole()
}
}
Binary file added images/all-metrics.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed images/buildview_screen.PNG
Binary file not shown.
Binary file removed images/config-add-adapter.png
Binary file not shown.
Binary file removed images/config.png
Binary file not shown.
Binary file added images/jacoco-coverage-checks-annotations.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/jacoco-coverage-checks.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/pit-coverage-checks-annotations.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/pit-coverage-checks.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/quality-gates.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/step.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/summary.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion plugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
<testcontainers.version>1.17.6</testcontainers.version>
<job-dsl.version>1.83</job-dsl.version>

<coverage-model.version>0.21.0</coverage-model.version>
<coverage-model.version>0.22.0</coverage-model.version>
<git-forensics.version>2.0.0</git-forensics.version>
<prism-api.version>1.29.0-4</prism-api.version>
<pull-request-monitoring.version>1.7.8</pull-request-monitoring.version>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,25 @@ public class TreeMapNodeConverter {
*/
public LabeledTreeMapNode toTreeChartModel(final Node node, final Metric metric, final ColorProvider colorProvider) {
var tree = mergePackages(node);
LabeledTreeMapNode root = toTreeMapNode(tree, metric, colorProvider).orElse(
new LabeledTreeMapNode(node.getPath(), node.getName()));
LabeledTreeMapNode root = toTreeMapNode(tree, metric, colorProvider)
.orElse(new LabeledTreeMapNode(getId(node), node.getName()));
for (LabeledTreeMapNode child : root.getChildren()) {
child.collapseEmptyPackages();
}

return root;
}

private String getId(final Node node) {
String id = node.getName();
if (node.isRoot()) {
return id;
}
else {
return getId(node.getParent()) + '/' + id;
}
}

private Node mergePackages(final Node node) {
if (node instanceof ModuleNode) {
ModuleNode copy = (ModuleNode) node.copyTree();
Expand Down Expand Up @@ -82,13 +92,14 @@ private LabeledTreeMapNode createCoverageTree(final Coverage coverage, final Col
Label label = new Label(true, lineColor);
Label upperLabel = new Label(true, lineColor);

var id = getId(node);
if (node instanceof FileNode) {
return new LabeledTreeMapNode(node.getPath(), node.getName(), new ItemStyle(fillColor), label, upperLabel,
return new LabeledTreeMapNode(id, node.getName(), new ItemStyle(fillColor), label, upperLabel,
String.valueOf(coverage.getTotal()), FORMATTER.getTooltip(coverage));
}

ItemStyle packageStyle = new ItemStyle(fillColor, fillColor, 4);
LabeledTreeMapNode treeNode = new LabeledTreeMapNode(node.getPath(), node.getName(), packageStyle, label, upperLabel,
LabeledTreeMapNode treeNode = new LabeledTreeMapNode(id, node.getName(), packageStyle, label, upperLabel,
String.valueOf(coverage.getTotal()), FORMATTER.getTooltip(coverage));

node.getChildren().stream()
Expand Down
Loading