Repository: trautonen/coveralls-maven-plugin
Branch: master
Commit: 773a396fa382
Files: 134
Total size: 410.1 KB
Directory structure:
gitextract_4r5n4qdh/
├── .gitignore
├── .gitmodules
├── .travis.yml
├── CHANGELOG.md
├── LICENSE.MIT
├── MIGRATION.md
├── README.md
├── README_2_x.md
├── pom.xml
├── sample/
│ ├── README.md
│ ├── module1/
│ │ ├── pom.xml
│ │ └── src/
│ │ ├── main/
│ │ │ ├── java/
│ │ │ │ └── org/
│ │ │ │ └── eluder/
│ │ │ │ └── coverage/
│ │ │ │ └── sample/
│ │ │ │ ├── InnerClassCoverage.java
│ │ │ │ └── SimpleCoverage.java
│ │ │ └── resources/
│ │ │ ├── Components.js
│ │ │ └── Localization.js
│ │ └── test/
│ │ ├── java/
│ │ │ └── org/
│ │ │ └── eluder/
│ │ │ └── coverage/
│ │ │ └── sample/
│ │ │ ├── InnerClassCoverageTest.java
│ │ │ └── SimpleCoverageTest.java
│ │ └── specs/
│ │ └── ComponentsSpec.coffee
│ ├── module2/
│ │ ├── pom.xml
│ │ └── src/
│ │ ├── main/
│ │ │ └── java/
│ │ │ └── org/
│ │ │ └── eluder/
│ │ │ └── coverage/
│ │ │ └── sample/
│ │ │ └── PartialCoverage.java
│ │ └── test/
│ │ └── java/
│ │ └── org/
│ │ └── eluder/
│ │ └── coverage/
│ │ └── sample/
│ │ ├── PartialCoverageIT.java
│ │ └── PartialCoverageTest.java
│ └── pom.xml
├── scripts/
│ ├── bump-version.sh
│ ├── functions.sh
│ └── release.sh
└── src/
├── main/
│ └── java/
│ └── org/
│ └── eluder/
│ └── coveralls/
│ └── maven/
│ └── plugin/
│ ├── CoverageParser.java
│ ├── CoverallsReportMojo.java
│ ├── Environment.java
│ ├── ProcessingException.java
│ ├── domain/
│ │ ├── Branch.java
│ │ ├── CoverallsResponse.java
│ │ ├── Git.java
│ │ ├── GitRepository.java
│ │ ├── Job.java
│ │ ├── JsonObject.java
│ │ └── Source.java
│ ├── httpclient/
│ │ ├── CoverallsClient.java
│ │ ├── CoverallsProxyClient.java
│ │ └── HttpClientFactory.java
│ ├── json/
│ │ └── JsonWriter.java
│ ├── logging/
│ │ ├── CoverageTracingLogger.java
│ │ ├── DryRunLogger.java
│ │ ├── JobLogger.java
│ │ └── Logger.java
│ ├── parser/
│ │ ├── AbstractXmlEventParser.java
│ │ ├── CoberturaParser.java
│ │ ├── JaCoCoParser.java
│ │ └── SagaParser.java
│ ├── service/
│ │ ├── AbstractServiceSetup.java
│ │ ├── Appveyor.java
│ │ ├── Bamboo.java
│ │ ├── Circle.java
│ │ ├── General.java
│ │ ├── Jenkins.java
│ │ ├── ServiceSetup.java
│ │ ├── Shippable.java
│ │ ├── Travis.java
│ │ └── Wercker.java
│ ├── source/
│ │ ├── AbstractSourceLoader.java
│ │ ├── ChainingSourceCallback.java
│ │ ├── DirectorySourceLoader.java
│ │ ├── MultiSourceLoader.java
│ │ ├── ScanSourceLoader.java
│ │ ├── SourceCallback.java
│ │ ├── SourceLoader.java
│ │ ├── UniqueSourceCallback.java
│ │ └── UrlSourceLoader.java
│ ├── util/
│ │ ├── CoverageParsersFactory.java
│ │ ├── ExistingFiles.java
│ │ ├── MavenProjectCollector.java
│ │ ├── Md5DigestInputStream.java
│ │ ├── SourceLoaderFactory.java
│ │ ├── TimestampParser.java
│ │ ├── UrlUtils.java
│ │ └── Wildcards.java
│ └── validation/
│ ├── JobValidator.java
│ ├── ValidationError.java
│ ├── ValidationErrors.java
│ └── ValidationException.java
└── test/
├── java/
│ └── org/
│ └── eluder/
│ └── coveralls/
│ └── maven/
│ └── plugin/
│ ├── CoverageFixture.java
│ ├── CoverallsReportMojoTest.java
│ ├── EnvironmentTest.java
│ ├── ProcessingExceptionTest.java
│ ├── domain/
│ │ ├── GitRepositoryTest.java
│ │ ├── JobTest.java
│ │ └── SourceTest.java
│ ├── httpclient/
│ │ ├── CoverallsClientTest.java
│ │ ├── CoverallsProxyClientTest.java
│ │ └── HttpClientFactoryTest.java
│ ├── json/
│ │ └── JsonWriterTest.java
│ ├── logging/
│ │ ├── CoverageTracingLoggerTest.java
│ │ ├── DryRunLoggerTest.java
│ │ └── JobLoggerTest.java
│ ├── parser/
│ │ ├── AbstractCoverageParserTest.java
│ │ ├── CoberturaParserTest.java
│ │ ├── JaCoCoParserTest.java
│ │ └── SagaParserTest.java
│ ├── service/
│ │ ├── AbstractServiceSetupTest.java
│ │ ├── AppveyorTest.java
│ │ ├── BambooTest.java
│ │ ├── CircleTest.java
│ │ ├── GeneralTest.java
│ │ ├── JenkinsTest.java
│ │ ├── ShippableTest.java
│ │ ├── TravisTest.java
│ │ └── WerckerTest.java
│ ├── source/
│ │ ├── DirectorySourceLoaderTest.java
│ │ ├── MultiSourceLoaderTest.java
│ │ ├── ScanSourceLoaderTest.java
│ │ ├── UniqueSourceCallbackTest.java
│ │ └── UrlSourceLoaderTest.java
│ ├── util/
│ │ ├── CoverageParsersFactoryTest.java
│ │ ├── ExistingFilesTest.java
│ │ ├── Md5DigestInputStreamTest.java
│ │ ├── SourceLoaderFactoryTest.java
│ │ ├── TestIoUtil.java
│ │ ├── TimestampParserTest.java
│ │ ├── UrlUtilsTest.java
│ │ └── WildcardsTest.java
│ └── validation/
│ ├── JobValidatorTest.java
│ ├── ValidationErrorTest.java
│ ├── ValidationErrorsTest.java
│ └── ValidationExceptionTest.java
└── resources/
├── Components.js
├── InnerClassCoverage.java
├── Localization.js
├── PartialCoverage.java
├── SimpleCoverage.java
├── cobertura.xml
├── jacoco1.xml
├── jacoco2-it.xml
├── jacoco2.xml
└── saga.xml
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
target
target/*
# Eclipse
.settings
.project
.classpath
# Idea
*.iml
.idea
# Atlassian
atlassian-ide-plugin.xml
================================================
FILE: .gitmodules
================================================
[submodule "etc"]
path = etc
url = git://github.com/trautonen/etc.git
================================================
FILE: .travis.yml
================================================
dist: xenial
language: java
sudo: false
jdk:
- openjdk8
- openjdk10
- openjdk11
env:
global:
- secure: "pmNBqCAW1rc4WKHEmnroZNwAMus18K1VWhRYwt+CN0acH8griJp612tjwWcI\n9XkZcSPR0CJx1TZqGDZZTFH44Pkm6ELU1kc54xtJR6WMXnubEVoEom0tcv/1\nNyzxv9UFJfaNgaTESww+OXSlO9wQre5ZS0/wn2xrz0+twtOPYDU="
- secure: "CZ9mejMLJdrh+a5TFXsNSiYyK9K/zNYOtubv2sPq1OEGhuohdUfLtdsk7bK9\nQcIlhZjrE5Q/wVgjZcFsnVpKhnUSRLC7sTOh6tu08EwpNtnNLl5AeUztOMCs\nxhG5H7jDu9uEH81WDZnIuK4Zq4qxXx523rnqQfk4DsTCKLVh9jI="
addons:
apt:
packages:
- python-yaml
before_install:
- git submodule update --init --recursive
before_script:
- python etc/travis-sonatype.py
script: python etc/travis-build.py --settings ~/.m2/sonatype.xml
after_success:
- mvn clean cobertura:cobertura org.eluder.coveralls:coveralls-maven-plugin:report
================================================
FILE: CHANGELOG.md
================================================
# Changelog
## 4.2.0
- #95, #96: Improved error message for misbehaving Coveralls API
- #92: Support for HTTP proxies in settings.xml
- #91: Support for epoch formatted timestamps
## 4.1.0
- #88: Support for AppVeyor CI
## 4.0.0
- #85: Merge coverages from multiple reports to single source file
- #84: Change source content to source digest per new Coveralls API
- #83: Require Java 7 to support new features and syntax
- #77: Support for custom build timestamp format
## 3.2.1
- #87: Downgraded jgit version to support Java 6
## 3.2.0
- #82: Improved error message for duplicate classes in different modules
- #76: Property to allow Coveralls service fail without build failure
- #74: Handle transitive logging dependencies better
## 3.1.0
- #67: Configurable project basedir
- #65, #66, #68: Support for Shippable CI
- #63: Directory scanning source loader
## 3.0.1
- #53: Improved error message for missing source encoding
- #52: Ignore duplicate source files on Cobertura aggregate mode
## 3.0.0
- #48: Removed support for URL based source loading due to Coveralls changes
- #42, #45, #46: Support Coveralls new GitHub based source view
- #40: Proper multi-module support and report aggregation
- #37, #41: Disclaimer for Java 8 usage
## 2.2.0
- #31: Improved error messages for Coveralls API failures
- #30: Improved error message for missing charset
- #28: More lenient XML parsing
- #26, #29: Support for Saga coverage tool and chain multiple coverage reports
## 2.1.0
- #24: Filter out remote names from git branches
- #19, #20: Skip configuration property to allow skipping of plugin execution
## 2.0.1
- #18: Update to HttpComponents HttpClient 4.3
- #15, #16, #17: Disable PKCS cryptography provider at runtime to work around OpenJDK SSL issue
## 2.0.0
- #13: Dry run property for test builds
- #12: Use ServiceSetup as secondary configuration source and Maven/VM properties as primary
- #11: Support multiple source directories
- #9: Support for other CI tools and platforms
- #8: Aggregated reports for multi-module projects
## 1.2.0
- #10: Validation of the Coveralls job
- #4: Report build timestamp to Coveralls
- #3: Log code lines from generated report to Maven console
## 1.1.0
- #1: Easier configuration for Travis CI
## 1.0.0
- Initial release
================================================
FILE: LICENSE.MIT
================================================
The MIT License (MIT)
Copyright (c) 2013 - 2016, Tapio Rautonen
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
================================================
FILE: MIGRATION.md
================================================
# Migration guide
Changes marked with bold affect the plugin usage. Other changes are only related to development
and codebase.
## 2.x to 3.x
-
## 1.x to 2.x
- **`sourceDirectory` parameter removed and replaced with a list parameter `sourceDirectories`**
- **service environment parameters do not override configuration parameters**
- `org.eluder.coveralls.maven.plugin.service.ServiceSetup` interface completely changed to reflect
the service specific configuration properly
- `org.eluder.coveralls.maven.plugin.service.Travis` changed to reflect the new service setup
interface
- `org.eluder.coveralls.maven.plugin.domain.JobValidator` and all validation related code is
now located in `org.eluder.coveralls.maven.plugin.validation` package
- `org.eluder.coveralls.maven.plugin.domain.GitRepository` does not take custom branch parameter
as constructor argument anymore, the same behavior is handled with the new service environment
setup
- `org.eluder.coveralls.maven.plugin.domain.Job` has only default constructor and initialization
is done with _with*_ methods, _validate()_ method returns list of validation errors instead of
throwing exception
- `org.eluder.coveralls.maven.plugin.domain.SourceLoader` constructor takes a list of source
directories instead of a single source directory
================================================
FILE: README.md
================================================
coveralls-maven-plugin
======================
[](http://unmaintained.tech/)
[](https://coveralls.io/r/trautonen/coveralls-maven-plugin?branch=master)
[](https://maven-badges.herokuapp.com/maven-central/org.eluder.coveralls/coveralls-maven-plugin/)
Maven plugin for submitting Java code coverage reports to [Coveralls](https://coveralls.io/) web
service.
## !!! Deprecated !!!
This project is deprecated due to lack of time and interest. Please use https://github.com/hazendaz/coveralls-maven-plugin from now on.
### Requirements
* Java 6 up to 3.x and Java 7 for 4.x onwards.
* Maven 3.0.0 or newer.
### Features
* Supports [Cobertura](http://mojo.codehaus.org/cobertura-maven-plugin/),
[JaCoCo](http://www.eclemma.org/jacoco/trunk/doc/maven.html) and
[Saga](http://timurstrekalov.github.io/saga/) coverage tools
* Multi-module report aggregation
* Built-in support for [Travis CI](https://travis-ci.org/), [Circle](https://circleci.com/),
[Codeship](https://www.codeship.io/), [Jenkins](http://jenkins-ci.org/),
[Bamboo](https://www.atlassian.com/software/bamboo/), [Shippable](https://www.shippable.com/)
and [Appveyor](http://www.appveyor.com/) continuous integration services
* Fully streaming implementation for fast report generation and small memory footprint
* Provides clean interfaces to allow easy extending to different coverage tools
* Convention over configuration for almost zero configuration usage
* Applies [semantic versioning](http://semver.org/)
### Usage
Set up the Coveralls maven plugin in the build section of the project pom.xml:
```xml
org.eluder.coverallscoveralls-maven-plugin4.3.0yourcoverallsprojectrepositorytoken
```
#### Configuration
If used as a standalone Maven build or with any continuous integration server other than Travis
CI, the Coveralls repository token must be provided. This can be achieved by setting the
configuration section in the plugin or setting the Maven property `repoToken` to your coveralls
project repository token, using `-DrepoToken=yourcoverallsprojectrepositorytoken` when running the
maven command. **Do not publish your repository token in public GitHub repositories.** If you do,
anyone can submit coverage data without permission.
If you are using Travis CI, CircleCI, Codeship, Jenkins or Bamboo continuous integration services,
no other configuration is required. The plugin's built-in service environment support take care of
the rest. The plugin tries to find report files for any of the supported coverage tools and
finally aggregates the coverage report. Java 8 is currently supported only by JaCoCo.
See [Complete plugin configuration](#complete-plugin-configuration) for all of the available
configuration parameters.
#### Cobertura
Set up the Cobertura Maven plugin with XML report format in the build section of the project
pom.xml:
```xml
org.codehaus.mojocobertura-maven-plugin2.7xml256mtrue
```
Execute Maven to create Cobertura report and submit Coveralls data:
```
mvn cobertura:cobertura coveralls:report
```
For example if you are using Travis CI this means you need to add to your `.travis.yml` the lines:
```
after_success:
- mvn clean cobertura:cobertura coveralls:report
```
#### JaCoCo
Set up the JaCoCo Maven plugin in the build section of the project pom.xml:
```xml
org.jacocojacoco-maven-plugin0.7.6.201602180812prepare-agentprepare-agent
```
Execute Maven to create JaCoCo report and submit Coveralls data:
```
mvn clean test jacoco:report coveralls:report
```
Again, if you are using Travis CI this means you need to add to your `.travis.yml` the lines:
```
after_success:
- mvn clean test jacoco:report coveralls:report
```
#### Saga
Set up the Saga Maven plugin in the build section of the project pom.xml:
```xml
com.github.timurstrekalovsaga-maven-plugin1.5.5coveragehttp://localhost:${jasmine.serverPort}${project.build.directory}/saga-coverage.*/spec/.*.*/classpath/.*.*/webjars/.*
```
Note that Saga does not have default report output directory, but the plugin assumes
`${project.build.directory}/saga-coverage`.
Execute Maven to create Saga report and submit Coveralls data:
```
mvn clean test saga:coverage coveralls:report
```
And if you are using Travis CI this means you need to add to your `.travis.yml` the lines:
```
after_success:
- mvn clean test saga:coverage coveralls:report
```
#### Aggregate multiple reports
Report aggregation is applied by default and the only thing the user must take care of is to run
all the desired coverage tools. You can use JaCoCo in a multi-module project so that all modules
run JaCoCo separately and let the plugin aggregate the report, or you can run Saga and Cobertura
in same project and get coverage report for JavaScript and Java files.
Execute Maven to create Saga and Cobertura report and submit Coveralls data:
```
mvn clean test saga:coverage cobertura:cobertura coveralls:report
```
And if you are using Travis CI this means you need to add to your `.travis.yml` the lines:
```
after_success:
- mvn clean test saga:coverage cobertura:cobertura coveralls:report
```
### Complete plugin configuration
Configuration can be changed by the configuration section of plugin's definition in POM or with
Java virtual machine system properties using the syntax `-Dparameter=value`. See
[Maven plugin guide](http://maven.apache.org/guides/plugin/guide-java-plugin-development.html#Configuring_Parameters_in_a_Project)
how different types are mapped in the configuration XML. Some of the optional parameters are set
by the built-in service environment setups. Note that if a parameter is explicitly defined, the
service environment will not override it.
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `jacocoReports` | `List` | List of additional JaCoCo report files. ${project.reporting.outputDirectory}/jacoco/jacoco.xml is used as default for every module. |
| `coberturaReports` | `List` | List of additional Cobertura report files. ${project.reporting.outputDirectory}/cobertura/coverage.xml is used as default for every module. |
| `sagaReports` | `List` | List of additional Saga report files. ${project.build.directory}/saga-coverage/total-coverage.xml is used as default for every module. |
| `relativeReportDirs` | `List` | List of additional relative report directories. Directories relative to ${project.reporting.outputDirectory} and ${project.build.directory} are scanned for reports. |
| `coverallsFile` | `File` | **Default: ${project.build.directory}/coveralls.json** File path to write and submit Coveralls data. |
| `coverallsUrl` | `String` | **Default: https://coveralls.io/api/v1/jobs** Url for the Coveralls API. |
| `sourceDirectories` | `List` | List of additional source directories. The plugin will scan the project's compiled source roots for defaults. |
| `sourceEncoding` | `String` | **Default: ${project.build.sourceEncoding}** Source file encoding. |
| `serviceName` | `String` | CI service name. If not provided the supported service environments are used. |
| `serviceJobId` | `String` | CI service job id. Currently supported only with Travis CI. If this property is set, `repoToken` is not required. If not provided the supported service environments are used. |
| `serviceBuildNumber` | `String` | CI service build number. If not provided the supported service environments are used. |
| `serviceBuildUrl` | `String` | CI service build url. If not provided the supported service environments are used. |
| `serviceEnvironment` | `Properties` | CI service specific environment properties. If not provided the supported service environments are used. |
| `repoToken` | `String` | Coveralls repository token. **Do not publish this parameter unencrypted in public GitHub repositories.** |
| `parallel` | `boolean` | **Default: false** Coveralls API flag: If this is set, the build will not be considered done until a webhook has been sent to https://coveralls.io/webhook?repo_token=… |
| `branch` | `String` | Git branch name. If not provided the supported service environments are used. |
| `pullRequest` | `String` | GitHub pull request identifier. If not provided the supported service environments are used. |
| `timestampFormat` | `String` | **Default: ${maven.build.timestamp}** Build timestamp format. Must be in format supported by SimpleDateFormat. |
| `timestamp` | `String` | **Default: ${timestamp}** Build timestamp. Must be in format defined by 'timestampFormat' if it's available or in default timestamp format yyyy-MM-dd'T'HH:mm:ss'Z'. |
| `dryRun` | `boolean` | **Default: false** Dry run Coveralls report without actually sending it. |
| `failOnServiceError` | `boolean` | **Default: true** Fail build if Coveralls service is not available or submission fails for internal errors. |
| `scanForSources` | `boolean` | **Default: false** Scan subdirectories for source files. |
| `coveralls.basedir` | `File` | **Default: ${project.basedir}** Base directory of the project. |
| `coveralls.skip` | `boolean` | **Default: false** Skip the plugin execution. |
### FAQ
> **Q:** How do I know that my coverage report was submitted successfully to Coveralls?
> **A:** The plugin will end with BUILD SUCCESS and the log contains the reported job id and
> direct URL to Coveralls.
> **Q:** I get BUILD SUCCESS but why Coveralls shows only question marks in the reports?
> **A:** The data is most likely reported correctly, but Coveralls might take hours, or even a
> day, to update the actual coverage numbers.
> **Q:** Can I use Java 8 with the plugin?
> **A:** Yes. The Coveralls plugin works fine with Java 8, but the problem is the coverage tools.
> Currently only tool supporting Java 8 is JaCoCo. You can use JaCoCo in a single module or
> a multi-module project and let the Coveralls plugin handle the report aggregation. This is not
> true aggregation though and does not address cross module coverage calculation (see
> https://github.com/jacoco/jacoco/pull/97)
> **Q:** Build fails with 'javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated'
> exception, what to do?
> **A:** If the build is run with OpenJDK, you probably hit an issue with the Cryptography Package
> Providers not supporting all Elliptic Curves. The [issue](https://bugs.launchpad.net/ubuntu/+source/openjdk-6/+bug/1006776)
> is described in the Ubuntu issue tracker. A workaround is to disable the PKCS provider from the
> `java.security` options file.
> ```
> sudo sed -i 's/security.provider.9/#security.provider.9/g' $JAVA_HOME/jre/lib/security/java.security
> ```
> In Travis CI the above command can be added to before_install phase. See complete example from
> this project's `.travis.yml`.
> **Q:** How can I use Scala or some other project which sources reside in other folder than
> `src/main/java`?
> **A:** The plugin uses all compiled source roots available for the project at runtime. If the
> source directories are available, everything is fine. Otherwise additional source directories
> can be applied with `sourceDirectories` configuration parameter that takes a Maven configuration
> style list of source directories.
> **Q:** How can I set the plugin to use multiple source directories?
> **A:** For multi-module projects, the plugin automatically scans the project hierarchy and adds
> all required source directories. You can also customize the used source directories with
> `sourceDirectories` configuration parameter that takes a Maven configuration style list of
> source directories.
> **Q:** Why source files are not found for generated sources?
> **A:** Generated source directories under target are not added to the sources list
> automatically. It is often not good practice to test generated code, because the code is not
> managed by the project under test, unless you are testing a source generator. Cobertura and
> JaCoCo both have `` configuration directive that provides ignoring of class files. If
> the generated sources still must be tested, all source directories can be explicitly defined
> with `sourceDirectories` configuration parameter.
> **Q:** JaCoCo or Cobertura, which one should i choose?
> **A:** For multi-module projects, only Cobertura supports report aggregation out of the box. The
> coverage metrics and performance of the two plugins are not much different for a small or medium
> sized project, but there are 2 notable differences with the tools:
> - JaCoCo does not track how many times a single line of code is hit by all the tests together,
> so Coveralls is always reported with 1 as the number of hits if the line is covered. Cobertura
> tracks the number of hits and the number is reported to Coveralls.
> - Cobertura tracks all inner classes separately, so a single source file will contain multiple
> records with same file name in Coveralls if there are any innner classes defined. The
> coveralls-maven-plugin adds classifier from the inner class to distinguish the files, but if
> there are lot of inner classes defined this creates some noise to the Coveralls reports. JaCoCo
> tracks inner classes within same source file so each source file is only reported once to
> Coveralls.
### Changelog
See [changelog](CHANGELOG.md) for more details.
### Migration
See [migration](MIGRATION.md) documentation for more information.
### Credits
- Jakub Bednář (@bednar) for Saga integration and the idea of chaining multiple reports provided
by different coverage tools.
- Marvin Froeder (@velo) for Shippable and Appveyor support, configurable basedir and directory
scanning source loader.
- Pasi Niemi (@psiniemi) for coverage merging from different reports to single source file.
### Continuous integration
Travis CI builds the plugin with Oracle JDK 7. All successfully built snapshots are deployed to
Sonatype OSS repository. Cobertura is used to gather coverage metrics and the report is submitted
to Coveralls with this plugin.
### Using test versions
Add the following repository configurations to your `pom.xml` to enable snapshot versions of this
plugin to be used.
```xml
sonatype-nexus-snapshotshttps://oss.sonatype.org/content/repositories/snapshotsfalsetruesonatype-nexus-snapshothttps://oss.sonatype.org/content/repositories/snapshotsfalsetrue
```
### License
The project coveralls-maven-plugin is licensed under the MIT license.
================================================
FILE: README_2_x.md
================================================
coveralls-maven-plugin
======================
[](https://travis-ci.org/trautonen/coveralls-maven-plugin)
[](https://coveralls.io/r/trautonen/coveralls-maven-plugin?branch=master)
Maven plugin for submitting Java code coverage reports to [Coveralls](https://coveralls.io/) web
service.
### Features
* Supports [Cobertura](http://mojo.codehaus.org/cobertura-maven-plugin/),
[JaCoCo](http://www.eclemma.org/jacoco/trunk/doc/maven.html) and
[Saga](http://timurstrekalov.github.io/saga/) coverage tools
* Multi-module report aggregation with Cobertura
* Built-in support for [Travis CI](https://travis-ci.org/), [Circle](https://circleci.com/),
[Codeship](https://www.codeship.io/), [Jenkins](http://jenkins-ci.org/) and
[Bamboo](https://www.atlassian.com/software/bamboo/) continuous integration services
* Fully streaming implementation for fast report generation and small memory footprint
* Provides clean interfaces to allow easy extending to different coverage tools
* Convention over configuration for almost zero configuration usage
* Applies [semantic versioning](http://semver.org/)
### Usage
Set up the Coveralls maven plugin in the build section of the project pom.xml:
```xml
org.eluder.coverallscoveralls-maven-plugin2.2.0yourcoverallsprojectrepositorytoken
```
#### Configuration
If used as a standalone Maven build or with any continuous integration server other than Travis
CI, the Coveralls repository token must be provided. This can be achieved by setting the
configuration section in the plugin or setting the Maven property `repoToken` to your coveralls project repository token, using
`-DrepoToken=yourcoverallsprojectrepositorytoken` when running the maven command. **Do not publish
your repository token in public GitHub repositories.** If you do, anyone can submit coverage data without permission.
If you are using Travis CI, Circle, Codeship, Jenkins or Bamboo continuous integration services, no
other configuration is required. The plugin's built-in service environment support take care of
the rest. Multi-module projects that require aggregated reports have to set up Cobertura Maven
plugin for the root project with `aggregate=true`. For other projects you are free to choose
either [Cobertura](#cobertura) or [JaCoCo](#jacoco) plugin. Finally add the corresponding Maven
command for the selected plugin to your continuous integration service build job.
See [Complete plugin configuration](#complete-plugin-configuration) for all of the available
configuration parameters.
#### Cobertura
Set up the Cobertura Maven plugin with XML report format in the build section of the project
pom.xml:
```xml
org.codehaus.mojocobertura-maven-plugin2.6xml256mtrue
```
Execute Maven to create Cobertura report and submit Coveralls data:
```
mvn cobertura:cobertura coveralls:cobertura
```
For example if you are using Travis CI this means you need to add to your `.travis.yml` the lines:
```
after_success:
- mvn clean cobertura:cobertura coveralls:cobertura
```
#### JaCoCo
Set up the JaCoCo Maven plugin in the build section of the project pom.xml:
```xml
org.jacocojacoco-maven-plugin0.7.2.201409121644prepare-agentprepare-agent
```
Execute Maven to create JaCoCo report and submit Coveralls data:
```
mvn clean test jacoco:report coveralls:jacoco
```
Again, if you are using Travis CI this means you need to add to your `.travis.yml` the lines:
```
after_success:
- mvn clean test jacoco:report coveralls:jacoco
```
#### Saga
Set up the Saga Maven plugin in the build section of the project pom.xml:
```xml
com.github.timurstrekalovsaga-maven-plugin1.5.2coveragehttp://localhost:${jasmine.serverPort}${project.build.directory}/saga-coverage.*/spec/.*
```
You should also set the `sourceUrls` parameter for the plugin to load the sources from Jaasmine
server. This allows creating coverage reports also for example CoffeeScript sources:
```xml
http://localhost:${jasmine.serverPort}
```
Execute Maven to create Saga report and submit Coveralls data:
```
mvn clean test saga:coverage coveralls:saga
```
And if you are using Travis CI this means you need to add to your `.travis.yml` the lines:
```
after_success:
- mvn clean test saga:coverage coveralls:saga
```
#### Chain
Create Coveralls data from multiple coverage tools.
*Note: The chaining approach will be the default approach for future versions of coveralls maven
plugin usage. Probably with the difference that the goal is changed from `chain` to `report`.*
Configure the coverage plugins as described earlier and instead of single coverage tool goal
use the `chain` goal to aggregate all coverage sources.
Execute Maven to create Cobertura and Saga report and submit Coveralls data:
```
mvn clean test saga:coverage cobertura:cobertura coveralls:chain
```
And if you are using Travis CI this means you need to add to your `.travis.yml` the lines:
```
after_success:
- mvn clean test saga:coverage cobertura:cobertura coveralls:chain
```
### Complete plugin configuration
Configuration can be changed by the configuration section of plugin's definition in POM or with
Java virtual machine system properties using the syntax `-Dparameter=value`. See
[Maven plugin guide](http://maven.apache.org/guides/plugin/guide-java-plugin-development.html#Configuring_Parameters_in_a_Project)
how different types are mapped in the configuration XML. Some of the optional parameters are set
by the built-in service environment setups. Note that if a parameter is explicitly defined, the
service environment will not override it.
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `coverallsFile` | `File` | **Default: ${project.build.directory}/coveralls.json** File path to write and submit Coveralls data. |
| `coverallsUrl` | `String` | **Default: https://coveralls.io/api/v1/jobs** Url for the Coveralls API. |
| `sourceDirectories` | `List` | List of source directories. If not provided, the plugin will scan the project's compiled source roots. |
| `sourceUrls` | `List` | List of source urls. Can be used to load sources from external service, e.g. Jasmine server. |
| `sourceEncoding` | `String` | **Default: ${project.build.sourceEncoding}** Source file encoding. |
| `serviceName` | `String` | CI service name. If not provided the supported service environments are used. |
| `serviceJobId` | `String` | CI service job id. Currently supported only with Travis CI. If this property is set, `repoToken` is not required. If not provided the supported service environments are used. |
| `serviceBuildNumber` | `String` | CI service build number. If not provided the supported service environments are used. |
| `serviceBuildUrl` | `String` | CI service build url. If not provided the supported service environments are used. |
| `serviceEnvironment` | `Properties` | CI service specific environment properties. If not provided the supported service environments are used. |
| `repoToken` | `String` | Coveralls repository token. **Do not publish this parameter unencrypted in public GitHub repositories.** |
| `branch` | `String` | Git branch name. If not provided the supported service environments are used. |
| `pullRequest` | `String` | GitHub pull request identifier. If not provided the supported service environments are used. |
| `timestamp` | `Date` | **Default: ${timestamp}** Build timestamp. Must be in Maven supported 'yyyy-MM-dd HH:mm:ssa' format. |
| `dryRun` | `boolean` | **Default: false** Dry run Coveralls report without actually sending it. |
| `coveralls.skip` | `boolean` | **Default: false** Skip the plugin execution. |
| `coberturaFile` | `File` | **Default: ${project.reporting.outputDirectory}/cobertura/coverage.xml** Only for `chain` goal. Cobertura report file. |
| `jacocoFile` | `File` | **Default: ${project.reporting.outputDirectory}/jacoco/jacoco.xml** Only for `chain` goal. JaCoCo report file. |
| `sagaFile` | `File` | **Default: ${project.build.directory}/saga-coverage/total-coverage.xml** Only for `chain` goal. Saga report file. |
### FAQ
> **Q:** How do I know that my coverage report was submitted successfully to Coveralls?
> **A:** The plugin will end with BUILD SUCCESS and the log contains the reported job id and
> direct URL to Coveralls.
> **Q:** I get BUILD SUCCESS but why Coveralls shows only question marks in the reports?
> **A:** The data is most likely reported correctly, but Coveralls might take hours, or even a
> day, to update the actual coverage numbers.
> **Q:** Build fails with 'javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated'
> exception, what to do?
> **A:** If the build is run with OpenJDK, you probably hit an issue with the Cryptography Package
> Providers not supporting all Elliptic Curves. The [issue](https://bugs.launchpad.net/ubuntu/+source/openjdk-6/+bug/1006776)
> is described in the Ubuntu issue tracker. A workaround is to disable the PKCS provider from the
> `java.security` options file.
> ```
> sudo sed -i 's/security.provider.9/#security.provider.9/g' $JAVA_HOME/jre/lib/security/java.security
> ```
> In Travis CI the above command can be added to before_install phase. See complete example from
> this project's `.travis.yml`.
> **Q:** How can I use Scala or some other project which sources reside in other folder than
> `src/main/java`?
> **A:** The plugin uses all compiled source roots available for the project at runtime. If the
> source directories are available, everything is fine. Otherwise the used source directories can
> be changed with `sourceDirectories` configuration parameter that takes a Maven configuration
> style list of source directories.
> **Q:** How can I set the plugin to use multiple source directories?
> **A:** For multi-module projects, the plugin automatically scans the project hierarchy and adds
> all required source directories. You can also customize the used source directories with
> `sourceDirectories` configuration parameter that takes a Maven configuration style list of
> source directories.
> **Q:** Why source files are not found for generated sources?
> **A:** Generated source directories under target are not added to the sources list
> automatically. It is often not good practice to test generated code, because the code is not
> managed by the project under test, unless you are testing a source generator. Cobertura and
> JaCoCo both have `` configuration directive that provides ignoring of class files. If
> the generated sources still must be tested, all source directories can be explicitly defined
> with `sourceDirectories` configuration parameter.
> **Q:** JaCoCo or Cobertura, which one should i choose?
> **A:** For multi-module projects, only Cobertura supports report aggregation out of the box. The
> coverage metrics and performance of the two plugins are not much different for a small or medium
> sized project, but there are 2 notable differences with the tools:
> - JaCoCo does not track how many times a single line of code is hit by all the tests together,
> so Coveralls is always reported with 1 as the number of hits if the line is covered. Cobertura
> tracks the number of hits and the number is reported to Coveralls.
> - Cobertura tracks all inner classes separately, so a single source file will contain multiple
> records with same file name in Coveralls if there are any innner classes defined. The
> coveralls-maven-plugin adds classifier from the inner class to distinguish the files, but if
> there are lot of inner classes defined this creates some noise to the Coveralls reports. JaCoCo
> tracks inner classes within same source file so each source file is only reported once to
> Coveralls.
### Changelog
#### 2.2.0
- #31: Improved error messages for Coveralls API failures
- #30: Improved error message for missing charset
- #28: More lenient XML parsing
- #26, #29: Support for Saga coverage tool and chain multiple coverage reports
#### 2.1.0
- #24: Filter out remote names from git branches
- #19, #20: Skip configuration property to allow skipping of plugin execution
#### 2.0.1
- #18: Update to HttpComponents HttpClient 4.3
- #15, #16, #17: Disable PKCS cryptography provider at runtime to work around OpenJDK SSL issue
#### 2.0.0
- #13: Dry run property for test builds
- #12: Use ServiceSetup as secondary configuration source and Maven/VM properties as primary
- #11: Support multiple source directories
- #9: Support for other CI tools and platforms
- #8: Aggregated reports for multi-module projects
#### 1.2.0
- #10: Validation of the Coveralls job
- #4: Report build timestamp to Coveralls
- #3: Log code lines from generated report to Maven console
#### 1.1.0
- #1: Easier configuration for Travis CI
#### 1.0.0
- Initial release
### Migration guide
Changes marked with bold affect the plugin usage. Other changes are only related to development
and codebase.
#### 1.x to 2.x
- **`sourceDirectory` parameter removed and replaced with a list parameter `sourceDirectories`**
- **service environment parameters do not override configuration parameters**
- `org.eluder.coveralls.maven.plugin.service.ServiceSetup` interface completely changed to reflect
the service specific configuration properly
- `org.eluder.coveralls.maven.plugin.service.Travis` changed to reflect the new service setup
interface
- `org.eluder.coveralls.maven.plugin.domain.JobValidator` and all validation related code is
now located in `org.eluder.coveralls.maven.plugin.validation` package
- `org.eluder.coveralls.maven.plugin.domain.GitRepository` does not take custom branch parameter
as constructor argument anymore, the same behavior is handled with the new service environment
setup
- `org.eluder.coveralls.maven.plugin.domain.Job` has only default constructor and initialization
is done with _with*_ methods, _validate()_ method returns list of validation errors instead of
throwing exception
- `org.eluder.coveralls.maven.plugin.domain.SourceLoader` constructor takes a list of source
directories instead of a single source directory
### Credits
- Jakub Bednář (@bednar) for Saga integration and the idea of chaining multiple reports provided
by different coverage tools.
### Continuous integration
Travis CI builds the plugin with Oracle JDK 7. All successfully built snapshots are deployed to
Sonatype OSS repository. Cobertura is used to gather coverage metrics and the report is submitted
to Coveralls with this plugin.
### License
The project coveralls-maven-plugin is licensed under the MIT license.
================================================
FILE: pom.xml
================================================
4.0.0org.eludereluder-parent9org.eluder.coverallscoveralls-maven-plugin4.4.0-SNAPSHOTmaven-plugincoveralls-maven-pluginMaven plugin for submitting Java code coverage reports to Coveralls web service.https://github.com/trautonen/coveralls-maven-plugin2013Tapio RautonenThe MIT License (MIT)http://opensource.org/licenses/MITreposcm:git:git://github.com/trautonen/coveralls-maven-plugin.gitscm:git:git://github.com/trautonen/coveralls-maven-plugin.githttps://github.com/trautonen/coveralls-maven-plugin1.84.5.102.10.04.5.0.201609210915-r3.5.4yyyy-MM-dd'T'HH:mm:ss'Z'${maven.build.timestamp}org.apache.httpcomponentshttpclientcommons-loggingcommons-loggingorg.apache.httpcomponentshttpmimecommons-codeccommons-codec1.13com.fasterxml.jackson.corejackson-corecom.fasterxml.jackson.corejackson-annotationscom.fasterxml.jackson.corejackson-databindorg.eclipse.jgitorg.eclipse.jgitorg.codehaus.plexusplexus-utilsorg.apache.mavenmaven-plugin-apiorg.apache.mavenmaven-coreorg.apache.maven.plugin-toolsmaven-plugin-annotations3.5.2providedorg.slf4jslf4j-apiorg.slf4jjcl-over-slf4jjunitjunittestorg.mockitomockito-coretestorg.hamcresthamcrest-all1.3testorg.apache.commonscommons-lang33.9testcom.github.tomakehurstwiremock2.25.1testorg.apache.httpcomponentshttpclient${httpclient.version}org.apache.httpcomponentshttpmime${httpclient.version}com.fasterxml.jackson.corejackson-core${jackson.version}com.fasterxml.jackson.corejackson-annotations${jackson.version}com.fasterxml.jackson.corejackson-databind${jackson.version}org.eclipse.jgitorg.eclipse.jgit${jgit.version}org.apache.mavenmaven-plugin-api${maven.version}org.apache.mavenmaven-model${maven.version}org.apache.mavenmaven-artifact${maven.version}org.apache.mavenmaven-core${maven.version}org.apache.mavenmaven-settings${maven.version}org.apache.mavenmaven-settings-builder${maven.version}org.apache.mavenmaven-repository-metadata${maven.version}org.apache.mavenmaven-model-builder${maven.version}org.sonatype.sisusisu-inject-plexus1.4.3.2org.codehaus.plexusplexus-utils2.0.7org.apache.maven.pluginsmaven-plugin-plugin3.5.2truemojo-descriptordescriptorhelp-goalhelpmojoorg.codehaus.mojocobertura-maven-pluginorg.eluder.coverallscoveralls-maven-plugin${project.version}org.apache.maven.pluginsmaven-checkstyle-pluginorg.apache.maven.pluginsmaven-jar-plugin2.6org.codehaus.mojocobertura-maven-plugin${maven.cobertura.version}**/HelpMojo.classorg.apache.maven.pluginsmaven-checkstyle-plugin2.17**/HelpMojo.javaorg.apache.maven.pluginsmaven-javadoc-plugin${maven.javadoc.version}${project.basedir}/src/main/javaorg.codehaus.mojolicense-maven-plugin${maven.license.version}**/cobertura.xml**/jacoco1.xml**/jacoco2.xml**/SimpleCoverage.java**/InnerClassCoverage.java**/PartialCoverage.java**/saga.xml**/Components.js**/Localization.js
================================================
FILE: sample/README.md
================================================
Coverage samples
================
### Cobertura
```
mvn -Pcobertura clean cobertura:cobertura
```
### JaCoCo
```
mvn -Pjacoco clean verify jacoco:report
```
### Saga
```
mvn -Psaga clean test saga:coverage
```
================================================
FILE: sample/module1/pom.xml
================================================
4.0.0sampleorg.eluder.coverage1.0-SNAPSHOTmodule11.0-SNAPSHOTjar
================================================
FILE: sample/module1/src/main/java/org/eluder/coverage/sample/InnerClassCoverage.java
================================================
package org.eluder.coverage.sample;
public class InnerClassCoverage {
public void anonymous() {
InnerClass i = new InnerClass() {
@Override
public void run() {
System.out.println("overridden");
}
};
i.run();
}
public boolean delegate() {
return new InnerClass().isInner();
}
public static class InnerClass {
public boolean isInner() {
return true;
}
public void run() {
System.out.println("run");
}
}
}
================================================
FILE: sample/module1/src/main/java/org/eluder/coverage/sample/SimpleCoverage.java
================================================
package org.eluder.coverage.sample;
public class SimpleCoverage {
public boolean isTested() {
return false;
}
public void neverRun() {
System.out.println("oops");
}
}
================================================
FILE: sample/module1/src/main/resources/Components.js
================================================
(function() {
this.Components = {};
}).call(this);
================================================
FILE: sample/module1/src/main/resources/Localization.js
================================================
(function() {
var Localization;
Localization = (function() {
function Localization(values) {
this.values = values;
}
Localization.prototype.byKey = function(key) {
return this.values[key];
};
return Localization;
})();
}).call(this);
================================================
FILE: sample/module1/src/test/java/org/eluder/coverage/sample/InnerClassCoverageTest.java
================================================
package org.eluder.coverage.sample;
import org.junit.Test;
public class InnerClassCoverageTest {
@Test
public void testAnonymous() {
new InnerClassCoverage().anonymous();
}
@Test
public void testDelegate() {
new InnerClassCoverage().delegate();
}
}
================================================
FILE: sample/module1/src/test/java/org/eluder/coverage/sample/SimpleCoverageTest.java
================================================
package org.eluder.coverage.sample;
import org.junit.Test;
public class SimpleCoverageTest {
@Test
public void test() {
new SimpleCoverage().isTested();
}
}
================================================
FILE: sample/module1/src/test/specs/ComponentsSpec.coffee
================================================
describe 'Components testing', ->
it 'Components object on window not null', ->
expect(window.Components).not.toBe(null)
================================================
FILE: sample/module2/pom.xml
================================================
4.0.0sampleorg.eluder.coverage1.0-SNAPSHOTmodule21.0-SNAPSHOTjar
================================================
FILE: sample/module2/src/main/java/org/eluder/coverage/sample/PartialCoverage.java
================================================
package org.eluder.coverage.sample;
public class PartialCoverage {
public void partial(boolean test) {
if (test) {
System.out.println("test");
} else {
System.out.println("not test");
}
}
}
================================================
FILE: sample/module2/src/test/java/org/eluder/coverage/sample/PartialCoverageIT.java
================================================
package org.eluder.coverage.sample;
import org.junit.Test;
public class PartialCoverageIT {
@Test
public void testSum() {
new PartialCoverage().partial(false);
}
}
================================================
FILE: sample/module2/src/test/java/org/eluder/coverage/sample/PartialCoverageTest.java
================================================
package org.eluder.coverage.sample;
import org.junit.Test;
public class PartialCoverageTest {
@Test
public void testPartial() {
new PartialCoverage().partial(true);
}
}
================================================
FILE: sample/pom.xml
================================================
4.0.0org.eludereluder-parent9org.eluder.coveragesample1.0-SNAPSHOTpom3.1.00.8.12.72.21.5.5module1module2junitjunittestorg.eluder.coverallscoveralls-maven-plugin4.3.0module1/src/main/resourcesmaven-surefire-pluginmaven-failsafe-pluginorg.apache.maven.pluginsmaven-jar-plugin2.6coberturaorg.codehaus.mojocobertura-maven-plugin${maven.cobertura.version}coberturatruejacocoorg.jacocojacoco-maven-plugin${maven.jacoco.version}default-prepare-agentprepare-agentdefault-prepare-agent-integrationprepare-agent-integrationdefault-reportreportdefault-report-integrationreport-integrationsagacom.github.searlsjasmine-maven-plugin${maven.jasmine.version}test${project.basedir}/src/main/resources/${project.basedir}/src/test/specstrueorg.openqa.selenium.htmlunit.HtmlUnitDrivercom.github.timurstrekalovsaga-maven-plugin${maven.saga.version}coveragehttp://localhost:${jasmine.serverPort}${project.build.directory}/saga-coverage.*/spec/.*.*/classpath/.*.*/webjars/.*
================================================
FILE: scripts/bump-version.sh
================================================
#!/bin/bash
if [ $# -ne 1 ]
then
echo "Invalid number of arguments"
echo "USAGE: $0 "
exit 1
fi
version=$1
script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
working_dir="$( pwd )"
files=( "pom.xml" "README.md" )
source $script_dir/functions.sh
if ! ( contains_files ${files[@]} )
then
working_dir=$working_dir/..
cd $working_dir
fi
if ! ( contains_files ${files[@]} )
then
echo "Some of the required files (${files[@]}) not found, aborting version bump"
exit 1
fi
echo "Updating version to $version in all poms"
mvn versions:set -DnewVersion=$version > /dev/null
mvn versions:commit > /dev/null
if [[ "$version" != *-SNAPSHOT ]]; then
echo "Replacing version numbers in readme"
sed -n -i '1h;1!H;${;g;s,coveralls-maven-plugin\n [^<]*,coveralls-maven-plugin\n '"$version"',g;p;}' README.md
fi
echo "Committing version changes"
git add ${files[@]}
git commit -m "Updated to version $version."
================================================
FILE: scripts/functions.sh
================================================
#!/bin/bash
contains_files()
{
for file in "$@"
do
if ! [ -f $file ]
then
return 1
fi
done
return 0
}
================================================
FILE: scripts/release.sh
================================================
#!/bin/bash
script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
working_dir="$( pwd )"
files=( "pom.xml" "README.md" )
source $script_dir/functions.sh
if ! ( contains_files ${files[@]} )
then
working_dir=$working_dir/..
cd $working_dir
fi
if ! ( contains_files ${files[@]} )
then
echo "Some of the required files (${files[@]}) not found, aborting release"
exit 1
fi
echo -n "Enter release version: "
read release_version
echo -n "Enter new development version: "
read develop_version
echo -n "Enter GPG passphrase: "
stty_orig=$(stty -g)
stty -echo
read passphrase
stty $stty_orig
echo "$passphrase" | gpg --passphrase-fd 0 --armor --output pom.xml.asc --detach-sig pom.xml > /dev/null
gpg --verify pom.xml.asc > /dev/null
if [ $? -ne 0 ]; then
echo "Seems that the GPG passphrase was invalid"
exit $?
fi
rm pom.xml.asc
echo ""
echo "Starting release process for $release_version"
echo "Working in $( pwd )"
echo "Press return to continue or CTRL-C to abort"
read
echo "Cleaning project"
mvn clean > /dev/null
echo "Updating license information"
mvn license:update-project-license license:update-file-header > /dev/null
git add -A
git commit -m "Updated license information."
$script_dir/bump-version.sh $release_version
echo "Creating tag for v$release_version"
git tag -a v$release_version -m "coveralls-maven-plugin version $release_version"
git checkout v$release_version
echo ""
echo "If everything went fine artifacts can be deployed to staging repository"
echo "After artifacts are deployed, login to https://oss.sonatype.org/ and complete the release"
echo "Press return to continue deploying or CTRL-C to abort"
read
mvn -Pprepare-deploy,prepare-release -Dgpg.passphrase=$passphrase clean deploy
echo ""
echo "Preparing for next development version $develop_version"
git checkout master
$script_dir/bump-version.sh $develop_version
echo ""
echo "Pushing everything to origin"
git push origin
git push origin --tags
echo ""
echo "Release completed for $release_version, current development version is $develop_version!"
================================================
FILE: src/main/java/org/eluder/coveralls/maven/plugin/CoverageParser.java
================================================
package org.eluder.coveralls.maven.plugin;
/*
* #[license]
* coveralls-maven-plugin
* %%
* Copyright (C) 2013 - 2016 Tapio Rautonen
* %%
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
* %[license]
*/
import java.io.File;
import java.io.IOException;
import org.eluder.coveralls.maven.plugin.source.SourceCallback;
/**
* Handles parsing of a coverage report. The implemenation can be statefull, and the same instance
* should be used only one time to parse a coverage report. Completed source files are passed to
* the {@link org.eluder.coveralls.maven.plugin.source.SourceCallback} handler. To maximize performance, the parser should use streaming.
*/
public interface CoverageParser {
/**
* Parses a coverage report. Parsed source files are passed to the callback handler. This
* method should be called only once per instance.
*
* @param callback the source callback handler
* @throws ProcessingException if processing of the coverage report fails
* @throws IOException if an I/O error occurs
*/
void parse(SourceCallback callback) throws ProcessingException, IOException;
/**
* @return the coverage report file under processing
*/
File getCoverageFile();
}
================================================
FILE: src/main/java/org/eluder/coveralls/maven/plugin/CoverallsReportMojo.java
================================================
package org.eluder.coveralls.maven.plugin;
/*
* #[license]
* coveralls-maven-plugin
* %%
* Copyright (C) 2013 - 2016 Tapio Rautonen
* %%
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
* %[license]
*/
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import org.apache.maven.settings.Settings;
import org.eluder.coveralls.maven.plugin.domain.CoverallsResponse;
import org.eluder.coveralls.maven.plugin.domain.Git;
import org.eluder.coveralls.maven.plugin.domain.GitRepository;
import org.eluder.coveralls.maven.plugin.domain.Job;
import org.eluder.coveralls.maven.plugin.httpclient.CoverallsClient;
import org.eluder.coveralls.maven.plugin.httpclient.CoverallsProxyClient;
import org.eluder.coveralls.maven.plugin.json.JsonWriter;
import org.eluder.coveralls.maven.plugin.logging.CoverageTracingLogger;
import org.eluder.coveralls.maven.plugin.logging.DryRunLogger;
import org.eluder.coveralls.maven.plugin.logging.JobLogger;
import org.eluder.coveralls.maven.plugin.logging.Logger;
import org.eluder.coveralls.maven.plugin.logging.Logger.Position;
import org.eluder.coveralls.maven.plugin.service.Appveyor;
import org.eluder.coveralls.maven.plugin.service.Bamboo;
import org.eluder.coveralls.maven.plugin.service.Circle;
import org.eluder.coveralls.maven.plugin.service.General;
import org.eluder.coveralls.maven.plugin.service.Jenkins;
import org.eluder.coveralls.maven.plugin.service.ServiceSetup;
import org.eluder.coveralls.maven.plugin.service.Shippable;
import org.eluder.coveralls.maven.plugin.service.Travis;
import org.eluder.coveralls.maven.plugin.service.Wercker;
import org.eluder.coveralls.maven.plugin.source.SourceCallback;
import org.eluder.coveralls.maven.plugin.source.SourceLoader;
import org.eluder.coveralls.maven.plugin.source.UniqueSourceCallback;
import org.eluder.coveralls.maven.plugin.util.CoverageParsersFactory;
import org.eluder.coveralls.maven.plugin.util.SourceLoaderFactory;
import org.eluder.coveralls.maven.plugin.util.TimestampParser;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Properties;
@Mojo(name = "report", threadSafe = false, aggregator = true)
public class CoverallsReportMojo extends AbstractMojo {
/**
* File paths to additional JaCoCo coverage report files.
*/
@Parameter(property = "jacocoReports")
protected List jacocoReports;
/**
* File paths to additional Cobertura coverage report files.
*/
@Parameter(property = "coberturaReports")
protected List coberturaReports;
/**
* File paths to additional Saga coverage report files.
*/
@Parameter(property = "sagaReports")
protected List sagaReports;
/**
* Directories for relative per module specific report files.
*/
@Parameter(property = "relativeReportDirs")
protected List relativeReportDirs;
/**
* File path to write and submit Coveralls data.
*/
@Parameter(property = "coverallsFile", defaultValue = "${project.build.directory}/coveralls.json")
protected File coverallsFile;
/**
* Url for the Coveralls API.
*/
@Parameter(property = "coverallsUrl", defaultValue = "https://coveralls.io/api/v1/jobs")
protected String coverallsUrl;
/**
* Source directories.
*/
@Parameter(property = "sourceDirectories")
protected List sourceDirectories;
/**
* Source file encoding.
*/
@Parameter(property = "sourceEncoding", defaultValue = "${project.build.sourceEncoding}")
protected String sourceEncoding;
/**
* CI service name.
*/
@Parameter(property = "serviceName")
protected String serviceName;
/**
* CI service job id.
*/
@Parameter(property = "serviceJobId")
protected String serviceJobId;
/**
* CI service build number.
*/
@Parameter(property = "serviceBuildNumber")
protected String serviceBuildNumber;
/**
* CI service build url.
*/
@Parameter(property = "serviceBuildUrl")
protected String serviceBuildUrl;
/**
* CI service specific environment properties.
*/
@Parameter(property = "serviceEnvironment")
protected Properties serviceEnvironment;
/**
* Coveralls repository token.
*/
@Parameter(property = "repoToken")
protected String repoToken;
/**
* Git branch name.
*/
@Parameter(property = "branch")
protected String branch;
/**
* GitHub pull request identifier.
*/
@Parameter(property = "pullRequest")
protected String pullRequest;
/**
* Coveralls parallel flag.
*/
@Parameter(property = "parallel")
protected boolean parallel;
/**
* Build timestamp format. Must be in format supported by SimpleDateFormat.
*/
@Parameter(property = "timestampFormat", defaultValue = "${maven.build.timestamp.format}")
protected String timestampFormat;
/**
* Build timestamp. Must be in format defined by 'timestampFormat' if it's available or in
* default timestamp format yyyy-MM-dd'T'HH:mm:ss'Z'.
*/
@Parameter(property = "timestamp", defaultValue = "${maven.build.timestamp}")
protected String timestamp;
/**
* Dry run Coveralls report without actually sending it.
*/
@Parameter(property = "dryRun", defaultValue = "false")
protected boolean dryRun;
/**
* Fail build if Coveralls service is not available or submission fails for internal errors.
*/
@Parameter(property = "failOnServiceError", defaultValue = "true")
protected boolean failOnServiceError;
/**
* Scan subdirectories for source files.
*/
@Parameter(property = "scanForSources", defaultValue = "false")
protected boolean scanForSources;
/**
* Base directory of the project.
*/
@Parameter(property = "coveralls.basedir", defaultValue = "${project.basedir}")
protected File basedir;
/**
* Skip the plugin execution.
*/
@Parameter(property = "coveralls.skip", defaultValue = "false")
protected boolean skip;
/**
* Maven settings.
*/
@Parameter(defaultValue = "${settings}", readonly = true, required = true)
protected Settings settings;
/**
* Maven project for runtime value resolution.
*/
@Component
protected MavenProject project;
@Override
public final void execute() throws MojoExecutionException, MojoFailureException {
if (skip) {
getLog().info("Skip property set, skipping plugin execution");
return;
}
try {
createEnvironment().setup();
Job job = createJob();
job.validate().throwOrInform(getLog());
SourceLoader sourceLoader = createSourceLoader(job);
List parsers = createCoverageParsers(sourceLoader);
JsonWriter writer = createJsonWriter(job);
CoverallsClient client = createCoverallsClient();
List reporters = new ArrayList<>();
reporters.add(new JobLogger(job));
SourceCallback sourceCallback = createSourceCallbackChain(writer, reporters);
reporters.add(new DryRunLogger(job.isDryRun(), writer.getCoverallsFile()));
report(reporters, Position.BEFORE);
writeCoveralls(writer, sourceCallback, parsers);
report(reporters, Position.AFTER);
if (!job.isDryRun()) {
submitData(client, writer.getCoverallsFile());
}
} catch (ProcessingException ex) {
throw new MojoFailureException("Processing of input or output data failed", ex);
} catch (IOException ex) {
throw new MojoFailureException("I/O operation failed", ex);
} catch (Exception ex) {
throw new MojoExecutionException("Build error", ex);
}
}
/**
*
* @param sourceLoader source loader that extracts source files
* @return coverage parsers for all maven modules and additional reports
* @throws IOException if parsers cannot be created
*/
protected List createCoverageParsers(final SourceLoader sourceLoader) throws IOException {
return new CoverageParsersFactory(project, sourceLoader)
.withJaCoCoReports(jacocoReports)
.withCoberturaReports(coberturaReports)
.withSagaReports(sagaReports)
.withRelativeReportDirs(relativeReportDirs)
.createParsers();
}
/**
* @return source loader that extracts source files
*
* @param job the job describing the coveralls report
*/
protected SourceLoader createSourceLoader(final Job job) {
return new SourceLoaderFactory(job.getGit().getBaseDir(), project, sourceEncoding)
.withSourceDirectories(sourceDirectories)
.withScanForSources(scanForSources)
.createSourceLoader();
}
/**
* @return environment to setup mojo and service specific properties
*/
protected Environment createEnvironment() {
return new Environment(this, getServices());
}
/**
* @return list of available continuous integration services
*/
protected List getServices() {
Map env = System.getenv();
List services = new ArrayList<>();
services.add(new Shippable(env));
services.add(new Travis(env));
services.add(new Circle(env));
services.add(new Jenkins(env));
services.add(new Bamboo(env));
services.add(new Appveyor(env));
services.add(new Wercker(env));
services.add(new General(env));
return services;
}
/**
* @return job that describes the coveralls report
* @throws ProcessingException if processing of timestamp fails
* @throws IOException if an I/O error occurs
*/
protected Job createJob() throws ProcessingException, IOException {
Git git = new GitRepository(basedir).load();
Date time = new TimestampParser(timestampFormat).parse(timestamp);
return new Job()
.withRepoToken(repoToken)
.withServiceName(serviceName)
.withServiceJobId(serviceJobId)
.withServiceBuildNumber(serviceBuildNumber)
.withServiceBuildUrl(serviceBuildUrl)
.withParallel(parallel)
.withServiceEnvironment(serviceEnvironment)
.withDryRun(dryRun)
.withBranch(branch)
.withPullRequest(pullRequest)
.withTimestamp(time)
.withGit(git);
}
/**
* @param job the job describing the coveralls report
* @return JSON writer that writes the coveralls data
* @throws IOException if an I/O error occurs
*/
protected JsonWriter createJsonWriter(final Job job) throws IOException {
return new JsonWriter(job, coverallsFile);
}
/**
* @return http client that submits the coveralls data
*/
protected CoverallsClient createCoverallsClient() {
return new CoverallsProxyClient(coverallsUrl, settings.getActiveProxy());
}
/**
* @param writer the JSON writer
* @param reporters the logging reporters
* @return source callback chain for different source handlers
*/
protected SourceCallback createSourceCallbackChain(final JsonWriter writer, final List reporters) {
SourceCallback chain = writer;
if (getLog().isInfoEnabled()) {
CoverageTracingLogger coverageTracingReporter = new CoverageTracingLogger(chain);
chain = coverageTracingReporter;
reporters.add(coverageTracingReporter);
}
chain = new UniqueSourceCallback(chain);
return chain;
}
/**
* Writes coverage data to JSON file.
*
* @param writer JSON writer that writes the coveralls data
* @param sourceCallback the source callback handler
* @param parsers list of coverage parsers
* @throws ProcessingException if process to to create JSON file fails
* @throws IOException if an I/O error occurs
*/
protected void writeCoveralls(final JsonWriter writer, final SourceCallback sourceCallback, final List parsers) throws ProcessingException, IOException {
try {
getLog().info("Writing Coveralls data to " + writer.getCoverallsFile().getAbsolutePath() + "...");
long now = System.currentTimeMillis();
sourceCallback.onBegin();
for (CoverageParser parser : parsers) {
getLog().info("Processing coverage report from " + parser.getCoverageFile().getAbsolutePath());
parser.parse(sourceCallback);
}
sourceCallback.onComplete();
long duration = System.currentTimeMillis() - now;
getLog().info("Successfully wrote Coveralls data in " + duration + "ms");
} finally {
writer.close();
}
}
private void submitData(final CoverallsClient client, final File coverallsFile) throws ProcessingException, IOException {
getLog().info("Submitting Coveralls data to API");
long now = System.currentTimeMillis();
try {
CoverallsResponse response = client.submit(coverallsFile);
long duration = System.currentTimeMillis() - now;
getLog().info("Successfully submitted Coveralls data in " + duration + "ms for " + response.getMessage());
getLog().info(response.getUrl());
getLog().info("*** It might take hours for Coveralls to update the actual coverage numbers for a job");
getLog().info(" If you see question marks in the report, please be patient");
} catch (ProcessingException ex) {
long duration = System.currentTimeMillis() - now;
String message = "Submission failed in " + duration + "ms while processing data";
handleSubmissionError(ex, message, true);
} catch (IOException ex) {
long duration = System.currentTimeMillis() - now;
String message = "Submission failed in " + duration + "ms while handling I/O operations";
handleSubmissionError(ex, message, failOnServiceError);
}
}
private void handleSubmissionError(final T ex, final String message, final boolean failOnException) throws T {
if (failOnException) {
getLog().error(message);
throw ex;
} else {
getLog().warn(message);
}
}
private void report(final List reporters, final Position position) {
for (Logger reporter : reporters) {
if (position.equals(reporter.getPosition())) {
reporter.log(getLog());
}
}
}
}
================================================
FILE: src/main/java/org/eluder/coveralls/maven/plugin/Environment.java
================================================
package org.eluder.coveralls.maven.plugin;
/*
* #[license]
* coveralls-maven-plugin
* %%
* Copyright (C) 2013 - 2016 Tapio Rautonen
* %%
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
* %[license]
*/
import java.util.Properties;
import org.codehaus.plexus.util.StringUtils;
import org.eluder.coveralls.maven.plugin.service.ServiceSetup;
/**
* Constructs and setups the project environment and continuous integration service.
*/
public final class Environment {
private final CoverallsReportMojo mojo;
private final Iterable services;
public Environment(final CoverallsReportMojo mojo, final Iterable services) {
if (mojo == null) {
throw new IllegalArgumentException("mojo must be defined");
}
if (services == null) {
throw new IllegalArgumentException("services must be defined");
}
this.mojo = mojo;
this.services = services;
}
public void setup() {
setupService();
verify();
}
private void verify() {
if (mojo.sourceEncoding == null) {
throw new IllegalArgumentException("Source encoding not set, use configuration option or set project wide property ");
}
}
private void setupService() {
for (ServiceSetup service : services) {
if (service.isSelected()) {
setupEnvironment(service);
break;
}
}
}
private void setupEnvironment(final ServiceSetup service) {
String name = service.getName();
if (StringUtils.isBlank(mojo.serviceName) && StringUtils.isNotBlank(name)) {
mojo.serviceName = name;
}
String jobId = service.getJobId();
if (StringUtils.isBlank(mojo.serviceJobId) && StringUtils.isNotBlank(jobId)) {
mojo.serviceJobId = jobId;
}
String buildNumber = service.getBuildNumber();
if (StringUtils.isBlank(mojo.serviceBuildNumber) && StringUtils.isNotBlank(buildNumber)) {
mojo.serviceBuildNumber = buildNumber;
}
String buildUrl = service.getBuildUrl();
if (StringUtils.isBlank(mojo.serviceBuildUrl) && StringUtils.isNotBlank(buildUrl)) {
mojo.serviceBuildUrl = buildUrl;
}
String branch = service.getBranch();
if (StringUtils.isBlank(mojo.branch) && StringUtils.isNotBlank(branch)) {
mojo.branch = branch;
}
String pullRequest = service.getPullRequest();
if (StringUtils.isBlank(mojo.pullRequest) && StringUtils.isNotBlank(pullRequest)) {
mojo.pullRequest = pullRequest;
}
Properties environment = service.getEnvironment();
if ((mojo.serviceEnvironment == null || mojo.serviceEnvironment.isEmpty()) &&
(environment != null && !environment.isEmpty())) {
mojo.serviceEnvironment = environment;
}
}
}
================================================
FILE: src/main/java/org/eluder/coveralls/maven/plugin/ProcessingException.java
================================================
package org.eluder.coveralls.maven.plugin;
/*
* #[license]
* coveralls-maven-plugin
* %%
* Copyright (C) 2013 - 2016 Tapio Rautonen
* %%
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
* %[license]
*/
/**
* Exception to indicate if processing of input or output data fails.
*/
public class ProcessingException extends Exception {
public ProcessingException() {
super();
}
public ProcessingException(final String message) {
super(message);
}
public ProcessingException(final Throwable cause) {
super(cause);
}
public ProcessingException(final String message, final Throwable cause) {
super(message, cause);
}
}
================================================
FILE: src/main/java/org/eluder/coveralls/maven/plugin/domain/Branch.java
================================================
package org.eluder.coveralls.maven.plugin.domain;
/*
* #[license]
* coveralls-maven-plugin
* %%
* Copyright (C) 2013 - 2016 Tapio Rautonen
* %%
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
* %[license]
*/
public class Branch {
private final int lineNumber;
private final int blockNumber;
private final int branchNumber;
private final int hits;
public Branch(final int lineNumber,
final int blockNumber,
final int branchNumber,
final int hits) {
this.lineNumber = lineNumber;
this.blockNumber = blockNumber;
this.branchNumber = branchNumber;
this.hits = hits;
}
public int getLineNumber() {
return lineNumber;
}
public int getBlockNumber() {
return blockNumber;
}
public int getBranchNumber() {
return branchNumber;
}
public int getHits() {
return hits;
}
}
================================================
FILE: src/main/java/org/eluder/coveralls/maven/plugin/domain/CoverallsResponse.java
================================================
package org.eluder.coveralls.maven.plugin.domain;
/*
* #[license]
* coveralls-maven-plugin
* %%
* Copyright (C) 2013 - 2016 Tapio Rautonen
* %%
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
* %[license]
*/
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
public final class CoverallsResponse implements JsonObject {
private final String message;
private final boolean error;
private final String url;
@JsonCreator
public CoverallsResponse(
@JsonProperty("message") final String message,
@JsonProperty("error") final boolean error,
@JsonProperty("url") final String url) {
this.message = message;
this.error = error;
this.url = url;
}
public String getMessage() {
return message;
}
public boolean isError() {
return error;
}
public String getUrl() {
return url;
}
}
================================================
FILE: src/main/java/org/eluder/coveralls/maven/plugin/domain/Git.java
================================================
package org.eluder.coveralls.maven.plugin.domain;
/*
* #[license]
* coveralls-maven-plugin
* %%
* Copyright (C) 2013 - 2016 Tapio Rautonen
* %%
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
* %[license]
*/
import java.io.File;
import java.io.Serializable;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
public class Git implements JsonObject {
@JsonIgnore
private final File baseDir;
@JsonProperty("head")
private final Head head;
@JsonProperty("branch")
private final String branch;
@JsonProperty("remotes")
private final List remotes;
public Git(final File baseDir, final Head head, final String branch, final List remotes) {
this.baseDir = baseDir;
this.head = head;
this.branch = branch;
this.remotes = remotes;
}
public File getBaseDir() {
return baseDir;
}
public Head getHead() {
return head;
}
public String getBranch() {
return branch;
}
public List getRemotes() {
return remotes;
}
public static class Head implements Serializable {
@JsonProperty("id")
private final String id;
@JsonProperty("author_name")
private final String authorName;
@JsonProperty("author_email")
private final String authorEmail;
@JsonProperty("committer_name")
private final String committerName;
@JsonProperty("committer_email")
private final String committerEmail;
@JsonProperty("message")
private final String message;
public Head(final String id, final String authorName, final String authorEmail, final String committerName, final String committerEmail, final String message) {
this.id = id;
this.authorName = authorName;
this.authorEmail = authorEmail;
this.committerName = committerName;
this.committerEmail = committerEmail;
this.message = message;
}
public String getId() {
return id;
}
public String getAuthorName() {
return authorName;
}
public String getAuthorEmail() {
return authorEmail;
}
public String getCommitterName() {
return committerName;
}
public String getCommitterEmail() {
return committerEmail;
}
public String getMessage() {
return message;
}
}
public static class Remote implements Serializable {
@JsonProperty("name")
private final String name;
@JsonProperty("url")
private final String url;
public Remote(final String name, final String url) {
this.name = name;
this.url = url;
}
public String getName() {
return name;
}
public String getUrl() {
return url;
}
}
}
================================================
FILE: src/main/java/org/eluder/coveralls/maven/plugin/domain/GitRepository.java
================================================
package org.eluder.coveralls.maven.plugin.domain;
/*
* #[license]
* coveralls-maven-plugin
* %%
* Copyright (C) 2013 - 2016 Tapio Rautonen
* %%
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
* %[license]
*/
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.RepositoryBuilder;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class GitRepository {
private final File sourceDirectory;
public GitRepository(final File sourceDirectory) {
this.sourceDirectory = sourceDirectory;
}
public Git load() throws IOException {
try (Repository repository = new RepositoryBuilder().findGitDir(this.sourceDirectory).build()) {
Git.Head head = getHead(repository);
String branch = getBranch(repository);
List remotes = getRemotes(repository);
return new Git(repository.getWorkTree(), head, branch, remotes);
}
}
private Git.Head getHead(final Repository repository) throws IOException {
ObjectId revision = repository.resolve(Constants.HEAD);
RevCommit commit = new RevWalk(repository).parseCommit(revision);
Git.Head head = new Git.Head(
revision.getName(),
commit.getAuthorIdent().getName(),
commit.getAuthorIdent().getEmailAddress(),
commit.getCommitterIdent().getName(),
commit.getCommitterIdent().getEmailAddress(),
commit.getFullMessage()
);
return head;
}
private String getBranch(final Repository repository) throws IOException {
return repository.getBranch();
}
private List getRemotes(final Repository repository) {
Config config = repository.getConfig();
List remotes = new ArrayList<>();
for (String remote : config.getSubsections("remote")) {
String url = config.getString("remote", remote, "url");
remotes.add(new Git.Remote(remote, url));
}
return remotes;
}
}
================================================
FILE: src/main/java/org/eluder/coveralls/maven/plugin/domain/Job.java
================================================
package org.eluder.coveralls.maven.plugin.domain;
import java.util.Date;
import java.util.Properties;
import org.eluder.coveralls.maven.plugin.domain.Git.Remote;
import org.eluder.coveralls.maven.plugin.validation.JobValidator;
import org.eluder.coveralls.maven.plugin.validation.ValidationErrors;
/*
* #[license]
* coveralls-maven-plugin
* %%
* Copyright (C) 2013 - 2016 Tapio Rautonen
* %%
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
* %[license]
*/
public class Job {
private String repoToken;
private String serviceName;
private String serviceJobId;
private String serviceBuildNumber;
private String serviceBuildUrl;
private boolean parallel;
private Properties serviceEnvironment;
private Date timestamp;
private boolean dryRun;
private String branch;
private String pullRequest;
private Git git;
public Job() {
// noop
}
public Job withRepoToken(final String repoToken) {
this.repoToken = repoToken;
return this;
}
public Job withServiceName(final String serviceName) {
this.serviceName = serviceName;
return this;
}
public Job withServiceJobId(final String serviceJobId) {
this.serviceJobId = serviceJobId;
return this;
}
public Job withServiceBuildNumber(final String serviceBuildNumber) {
this.serviceBuildNumber = serviceBuildNumber;
return this;
}
public Job withServiceBuildUrl(final String serviceBuildUrl) {
this.serviceBuildUrl = serviceBuildUrl;
return this;
}
public Job withParallel(final boolean parallel) {
this.parallel = parallel;
return this;
}
public Job withServiceEnvironment(final Properties serviceEnvironment) {
this.serviceEnvironment = serviceEnvironment;
return this;
}
public Job withTimestamp(final Date timestamp) {
this.timestamp = timestamp;
return this;
}
public Job withDryRun(final boolean dryRun) {
this.dryRun = dryRun;
return this;
}
public Job withBranch(final String branch) {
this.branch = branch;
return this;
}
public Job withPullRequest(final String pullRequest) {
this.pullRequest = pullRequest;
return this;
}
public Job withGit(final Git git) {
this.git = git;
return this;
}
public String getRepoToken() {
return repoToken;
}
public String getServiceName() {
return serviceName;
}
public String getServiceJobId() {
return serviceJobId;
}
public String getServiceBuildNumber() {
return serviceBuildNumber;
}
public String getServiceBuildUrl() {
return serviceBuildUrl;
}
public Properties getServiceEnvironment() {
return serviceEnvironment;
}
public Date getTimestamp() {
return timestamp;
}
public boolean isParallel() {
return parallel;
}
public boolean isDryRun() {
return dryRun;
}
public String getBranch() {
if (branch != null && getGit() != null && getGit().getRemotes() != null) {
for (Remote remote : getGit().getRemotes()) {
if (branch.startsWith(remote.getName() + "/")) {
return branch.substring(remote.getName().length() + 1);
}
}
}
return branch;
}
public String getPullRequest() {
return pullRequest;
}
public Git getGit() {
return git;
}
public ValidationErrors validate() {
JobValidator validator = new JobValidator(this);
return validator.validate();
}
}
================================================
FILE: src/main/java/org/eluder/coveralls/maven/plugin/domain/JsonObject.java
================================================
package org.eluder.coveralls.maven.plugin.domain;
/*
* #[license]
* coveralls-maven-plugin
* %%
* Copyright (C) 2013 - 2016 Tapio Rautonen
* %%
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
* %[license]
*/
import java.io.Serializable;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(Include.NON_NULL)
public interface JsonObject extends Serializable {
}
================================================
FILE: src/main/java/org/eluder/coveralls/maven/plugin/domain/Source.java
================================================
package org.eluder.coveralls.maven.plugin.domain;
/*
* #[license]
* coveralls-maven-plugin
* %%
* Copyright (C) 2013 - 2016 Tapio Rautonen
* %%
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
* %[license]
*/
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.ListIterator;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public final class Source implements JsonObject {
private static final Pattern NEWLINE = Pattern.compile("\r\n|\r|\n");
//private static final String CLASSIFIER_SEPARATOR = "#";
private final String name;
private final String digest;
private final Integer[] coverage;
private final List branches;
private String classifier;
public Source(final String name, final String source, final String digest) {
this(name, getLines(source), digest, null);
}
protected Source(final String name, final int lines, final String digest, final String classifier) {
this.name = name;
this.digest = digest;
this.coverage = new Integer[lines];
this.classifier = classifier;
this.branches = new ArrayList<>();
}
@JsonIgnore
public String getName() {
return name;
}
@JsonProperty("name")
public String getFullName() {
return name;
// #45: cannot use identifier due to unfetchable source files
//return (classifier == null ? name : name + CLASSIFIER_SEPARATOR + classifier);
}
@JsonProperty("source_digest")
public String getDigest() {
return digest;
}
@JsonProperty("coverage")
public Integer[] getCoverage() {
return coverage;
}
@JsonProperty("branches")
public Integer[] getBranches() {
final List branchesRaw = new ArrayList<>(branches.size() * 4);
for (final Branch b : branches) {
branchesRaw.add(b.getLineNumber());
branchesRaw.add(b.getBlockNumber());
branchesRaw.add(b.getBranchNumber());
branchesRaw.add(b.getHits());
}
return branchesRaw.toArray(new Integer[branchesRaw.size()]);
}
public List getBranchesList() {
return Collections.unmodifiableList(branches);
}
@JsonIgnore
public String getClassifier() {
return classifier;
}
public void setClassifier(final String classifier) {
this.classifier = classifier;
}
private void checkLineRange(final int lineNumber) {
int index = lineNumber - 1;
if (index >= this.coverage.length) {
throw new IllegalArgumentException("Line number " + lineNumber + " is greater than the source file " + name + " size");
}
}
public void addCoverage(final int lineNumber, final Integer coverage) {
checkLineRange(lineNumber);
this.coverage[lineNumber - 1] = coverage;
}
public void addBranchCoverage(final int lineNumber,
final int blockNumber,
final int branchNumber,
final int hits) {
addBranchCoverage(false, lineNumber, blockNumber, branchNumber, hits);
}
private void addBranchCoverage(final boolean merge,
final int lineNumber,
final int blockNumber,
final int branchNumber,
final int hits) {
checkLineRange(lineNumber);
int hitSum = hits;
final ListIterator it = this.branches.listIterator();
while (it.hasNext()) {
final Branch b = it.next();
if (b.getLineNumber() == lineNumber &&
b.getBlockNumber() == blockNumber &&
b.getBranchNumber() == branchNumber) {
it.remove();
if (merge) {
hitSum += b.getHits();
}
}
}
this.branches.add(new Branch(lineNumber, blockNumber, branchNumber, hitSum));
}
public Source merge(final Source source) {
Source copy = new Source(this.name, this.coverage.length, this.digest, this.classifier);
System.arraycopy(this.coverage, 0, copy.coverage, 0, this.coverage.length);
copy.branches.addAll(this.branches);
if (copy.equals(source)) {
for (int i = 0; i < copy.coverage.length; i++) {
if (source.coverage[i] != null) {
int base = copy.coverage[i] != null ? copy.coverage[i] : 0;
copy.coverage[i] = base + source.coverage[i];
}
}
for (final Branch b : source.branches) {
copy.addBranchCoverage(true,
b.getLineNumber(),
b.getBlockNumber(),
b.getBranchNumber(),
b.getHits());
}
}
return copy;
}
@Override
public boolean equals(final Object obj) {
if (!(obj instanceof Source)) {
return false;
}
Source other = (Source) obj;
return (Objects.equals(this.name, other.name) &&
Objects.equals(this.digest, other.digest) &&
Objects.equals(this.coverage.length, other.coverage.length));
}
@Override
public int hashCode() {
return Objects.hash(this.name, this.digest, this.coverage.length);
}
private static int getLines(final String source) {
int lines = 1;
Matcher matcher = NEWLINE.matcher(source);
while (matcher.find()) {
lines++;
}
return lines;
}
}
================================================
FILE: src/main/java/org/eluder/coveralls/maven/plugin/httpclient/CoverallsClient.java
================================================
package org.eluder.coveralls.maven.plugin.httpclient;
/*
* #[license]
* coveralls-maven-plugin
* %%
* Copyright (C) 2013 - 2016 Tapio Rautonen
* %%
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
* %[license]
*/
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.codehaus.plexus.util.IOUtil;
import org.codehaus.plexus.util.StringUtils;
import org.eluder.coveralls.maven.plugin.ProcessingException;
import org.eluder.coveralls.maven.plugin.domain.CoverallsResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.security.Provider;
import java.security.Security;
public class CoverallsClient {
static {
for (Provider provider : Security.getProviders()) {
if (provider.getName().startsWith("SunPKCS11")) {
Security.removeProvider(provider.getName());
}
}
}
private static final String FILE_NAME = "coveralls.json";
private static final ContentType MIME_TYPE = ContentType.create("application/octet-stream", "utf-8");
private final String coverallsUrl;
private final HttpClient httpClient;
private final ObjectMapper objectMapper;
public CoverallsClient(final String coverallsUrl) {
this(coverallsUrl, new HttpClientFactory(coverallsUrl).create(), new ObjectMapper());
}
public CoverallsClient(final String coverallsUrl, final HttpClient httpClient, final ObjectMapper objectMapper) {
this.coverallsUrl = coverallsUrl;
this.httpClient = httpClient;
this.objectMapper = objectMapper;
}
public CoverallsResponse submit(final File file) throws ProcessingException, IOException {
HttpEntity entity = MultipartEntityBuilder.create()
.setMode(HttpMultipartMode.BROWSER_COMPATIBLE)
.addBinaryBody("json_file", file, MIME_TYPE, FILE_NAME)
.build();
HttpPost post = new HttpPost(coverallsUrl);
post.setEntity(entity);
HttpResponse response = httpClient.execute(post);
return parseResponse(response);
}
private CoverallsResponse parseResponse(final HttpResponse response) throws ProcessingException, IOException {
HttpEntity entity = response.getEntity();
ContentType contentType = ContentType.getOrDefault(entity);
if (contentType.getCharset() == null) {
throw new ProcessingException(getResponseErrorMessage(response, "Response doesn't contain Content-Type header"));
}
InputStreamReader reader = null;
try {
if (response.getStatusLine().getStatusCode() >= HttpStatus.SC_INTERNAL_SERVER_ERROR) {
throw new IOException("Coveralls API internal error");
}
reader = new InputStreamReader(entity.getContent(), contentType.getCharset());
CoverallsResponse cr = objectMapper.readValue(reader, CoverallsResponse.class);
if (cr.isError()) {
throw new ProcessingException(getResponseErrorMessage(response, cr.getMessage()));
}
return cr;
} catch (JsonProcessingException ex) {
throw new ProcessingException(getResponseErrorMessage(response, ex.getMessage()), ex);
} catch (IOException ex) {
throw new IOException(getResponseErrorMessage(response, ex.getMessage()), ex);
} finally {
IOUtil.close(reader);
}
}
private String getResponseErrorMessage(final HttpResponse response, final String message) {
int status = response.getStatusLine().getStatusCode();
String reason = response.getStatusLine().getReasonPhrase();
String errorMessage = "Report submission to Coveralls API failed with HTTP status " + status + ":";
if (StringUtils.isNotBlank(reason)) {
errorMessage += " " + reason;
}
if (StringUtils.isNotBlank(message)) {
errorMessage += " (" + message + ")";
}
return errorMessage;
}
}
================================================
FILE: src/main/java/org/eluder/coveralls/maven/plugin/httpclient/CoverallsProxyClient.java
================================================
package org.eluder.coveralls.maven.plugin.httpclient;
/*
* #[license]
* coveralls-maven-plugin
* %%
* Copyright (C) 2013 - 2016 Tapio Rautonen
* %%
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
* %[license]
*/
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.maven.settings.Proxy;
public class CoverallsProxyClient extends CoverallsClient {
public CoverallsProxyClient(final String coverallsUrl, final Proxy proxy) {
super(coverallsUrl, new HttpClientFactory(coverallsUrl).proxy(proxy).create(), new ObjectMapper());
}
}
================================================
FILE: src/main/java/org/eluder/coveralls/maven/plugin/httpclient/HttpClientFactory.java
================================================
package org.eluder.coveralls.maven.plugin.httpclient;
/*
* #[license]
* coveralls-maven-plugin
* %%
* Copyright (C) 2013 - 2016 Tapio Rautonen
* %%
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
* %[license]
*/
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.maven.settings.Proxy;
import org.codehaus.plexus.util.StringUtils;
import org.eluder.coveralls.maven.plugin.util.UrlUtils;
import org.eluder.coveralls.maven.plugin.util.Wildcards;
class HttpClientFactory {
private static final int DEFAULT_CONNECTION_TIMEOUT = 10000;
private static final int DEFAULT_SOCKET_TIMEOUT = 60000;
private final String targetUrl;
private final HttpClientBuilder hcb = HttpClientBuilder.create();
private final RequestConfig.Builder rcb = RequestConfig.custom()
.setConnectTimeout(DEFAULT_CONNECTION_TIMEOUT)
.setSocketTimeout(DEFAULT_SOCKET_TIMEOUT);
HttpClientFactory(final String targetUrl) {
this.targetUrl = targetUrl;
}
public HttpClientFactory proxy(final Proxy proxy) {
if (proxy != null && isProxied(targetUrl, proxy)) {
rcb.setProxy(new HttpHost(proxy.getHost(), proxy.getPort(), proxy.getProtocol()));
if (StringUtils.isNotBlank(proxy.getUsername())) {
CredentialsProvider cp = new BasicCredentialsProvider();
cp.setCredentials(
new AuthScope(proxy.getHost(), proxy.getPort()),
new UsernamePasswordCredentials(proxy.getUsername(), proxy.getPassword())
);
hcb.setDefaultCredentialsProvider(cp);
}
}
return this;
}
public HttpClient create() {
return hcb.setDefaultRequestConfig(rcb.build()).build();
}
private boolean isProxied(final String url, final Proxy proxy) {
if (StringUtils.isNotBlank(proxy.getNonProxyHosts())) {
String host = UrlUtils.create(url).getHost();
String[] excludes = proxy.getNonProxyHosts().split("\\|");
for (String exclude : excludes) {
if (StringUtils.isNotBlank(exclude) && Wildcards.matches(host, exclude.trim())) {
return false;
}
}
}
return true;
}
}
================================================
FILE: src/main/java/org/eluder/coveralls/maven/plugin/json/JsonWriter.java
================================================
package org.eluder.coveralls.maven.plugin.json;
/*
* #[license]
* coveralls-maven-plugin
* %%
* Copyright (C) 2013 - 2016 Tapio Rautonen
* %%
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
* %[license]
*/
import com.fasterxml.jackson.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.MappingJsonFactory;
import org.codehaus.plexus.util.StringUtils;
import org.eluder.coveralls.maven.plugin.ProcessingException;
import org.eluder.coveralls.maven.plugin.domain.Job;
import org.eluder.coveralls.maven.plugin.domain.Source;
import org.eluder.coveralls.maven.plugin.source.SourceCallback;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map.Entry;
import java.util.Properties;
public class JsonWriter implements SourceCallback, Closeable {
protected static final String TIMESTAMP_FORMAT = "yyyy-MM-dd HH:mm:ss Z";
private final Job job;
private final File coverallsFile;
private final JsonGenerator generator;
public JsonWriter(final Job job, final File coverallsFile) throws IOException {
File directory = coverallsFile.getParentFile();
if (!directory.exists()) {
directory.mkdirs();
}
this.job = job;
this.coverallsFile = coverallsFile;
this.generator = new MappingJsonFactory().createGenerator(coverallsFile, JsonEncoding.UTF8);
}
public final Job getJob() {
return job;
}
public final File getCoverallsFile() {
return coverallsFile;
}
@Override
public void onBegin() throws ProcessingException, IOException {
try {
generator.writeStartObject();
writeOptionalString("repo_token", job.getRepoToken());
writeOptionalString("service_name", job.getServiceName());
writeOptionalString("service_job_id", job.getServiceJobId());
writeOptionalString("service_number", job.getServiceBuildNumber());
writeOptionalString("service_build_url", job.getServiceBuildUrl());
writeOptionalString("service_branch", job.getBranch());
writeOptionalString("service_pull_request", job.getPullRequest());
writeOptionalBoolean("parallel", job.isParallel());
writeOptionalTimestamp("run_at", job.getTimestamp());
writeOptionalEnvironment("environment", job.getServiceEnvironment());
writeOptionalObject("git", job.getGit());
generator.writeArrayFieldStart("source_files");
} catch (JsonProcessingException ex) {
throw new ProcessingException(ex);
}
}
@Override
public void onSource(final Source source) throws ProcessingException, IOException {
try {
generator.writeObject(source);
} catch (JsonProcessingException ex) {
throw new ProcessingException(ex);
}
}
@Override
public void onComplete() throws ProcessingException, IOException {
try {
generator.writeEndArray();
generator.writeEndObject();
} catch (JsonProcessingException ex) {
throw new ProcessingException(ex);
}
}
@Override
public void close() throws IOException {
generator.close();
}
private void writeOptionalString(final String field, final String value) throws ProcessingException, IOException {
if (StringUtils.isNotBlank(value)) {
generator.writeStringField(field, value);
}
}
private void writeOptionalBoolean(final String field, final boolean value) throws ProcessingException, IOException {
if (value) {
generator.writeBooleanField(field, value);
}
}
private void writeOptionalObject(final String field, final Object value) throws ProcessingException, IOException {
if (value != null) {
generator.writeObjectField(field, value);
}
}
private void writeOptionalTimestamp(final String field, final Date value) throws ProcessingException, IOException {
if (value != null) {
SimpleDateFormat format = new SimpleDateFormat(TIMESTAMP_FORMAT);
writeOptionalString(field, format.format(value));
}
}
private void writeOptionalEnvironment(final String field, final Properties properties) throws ProcessingException, IOException {
if (properties != null) {
generator.writeObjectFieldStart(field);
for (Entry