This document describes generic approach to remote cache setup. The process implies good knowledge of both Maven and the project. Due to Maven model limitation the process is semi-manual, but allows you to achieve sufficient control and transparency over caching logic.
Before you start, please keep in mind basic principles:
skipTests
and similar) in config. The same applies for all over plugins.Fork stable code branch for cache setup purposes as you will need source code which doesn't change over time of setup. Also, you likely will need to do code changes as long as you go.
In order to share build results cache needs a shared storage. The simplest option is to set up a http server which supports http PUT/GET/HEAD operations will suffice (Nginx, Apache or similar). Add the url to config and change remote@enabled
to true:
<remote enabled="true"> <url>http://your-buildcache-url</url> </remote>
If proxy or authentication is required to access remote cache, add server record to settings.xml as described in Servers. The server should be referenced from cache config:
TBD
Beside the http server, remote cache could be configured using any storage which is supported by Maven Wagon. That includes a wide set of options, including SSH, FTP and many others. See Wagon documentation for a full list of options and other details.
Build stored in cache ideally should be a build assembled in the most correct, comprehensive and complete way. Pull requests builds are good candidates to populate cache usually because this is there quality safeguards are applied normally.
Allow writes in remote cache add jvm property to designated CI builds.
-Dremote.cache.save.enabled=true
Run the build, review log and ensure that artifacts are uploaded to remote cache. Now, rerun build and ensure that it completes almost instantly because it is fully cached.
As practice shows, developers often don't realize that builds they run in local and CI environments are different. So straightforward attempt to reuse remote cache in local build usually results in cache misses because of difference in plugins, parameters, profiles, environment, etc. In order to reuse results you might need to change poms, cache config, CI jobs and the project itself. This part is usually most challenging and time-consuming. Follow steps below to iteratively achieve working configuration.
build-cache-report.xml
[INFO] [CACHE] Saved to remote cache https://your-cache-url/<...>/915296a3-4596-4eb5-bf37-f6e13ebe087e/build-cache-report.xml
Copy the link to a cbuild-ache-report.xml
and provide it to your local build as a baseline for comparison.
mvn verify -Dremote.cache.failFast=true -Dremote.cache.baselineUrl=https://your-cache-url/<...>/915296a3-4596-4eb5-bf37-f6e13ebe087e/build-cache-report.xml
Once discrepancy between remote and local builds detected cache will fail with diagnostic info in project's target/incremental-maven
directory:
* buildinfo-baseline-3c64673e23259e6f.xml - build specification from baseline build * buildinfo-db43936e0666ce7.xml - build specification of local build * buildsdiff.xml - comparison report with list of discrepancies
Review buildsdiff.xml
file and eliminate detected discrepancies. You can also diff build-info files directly to get low level insights. See techniques to configure cache in How-To and troubleshooting of typical issues in the section below.
Solution: normalise line endings. Current implementation doesn't have built-in line endings normalization, it has to be done externally. In git it is recommended to use .gitattributes
file to establish consistent line endings across all envs for file types specific to this project
Different profiles between remote and local builds likely result in different text of effective poms. As effective pom contributes hash value to the key that could lead to cache misses. Solution: instead of adding/removing specific plugins by profiles, set default value of the plugin's skip
or disabled
flag in a profile properties instead. Instead of:
<profiles> <profile> <id>run-plugin-in-ci-only</id> <build> <plugins> <plugin> <artifactId>surefire-report-maven-plugin</artifactId> <configuration> <!-- my configuration --> </configuration> </plugin> </plugins> </build> </profile> </profiles>
Use:
<properties> <!-- default value --> <skip.plugin.property>true</skip.plugin.property> </properties> <build> <plugins> <plugin> <artifactId>maven-surefire-plugin</artifactId> <configuration> <!-- plugin behavior is controlled by property --> <skip>${skip.plugin.property}</skip> </configuration> </plugin> </plugins> </build> <profiles> <profile> <id>run-plugin-in-ci-only</id> <properties> <!-- override to run plugin in reference ci build --> <skip.plugin.property>false</skip.plugin.property> </properties> </profile> </profiles>
Hint: effective poms could be found in buildinfo
files under /build/projectsInputInfo/item[@type='pom']
xpath (item type="pom"
).
Potential reason: Sometimes it is not possible to avoid discrepancies in different environments - for example if plugin takes command line as parameter, it will be likely different on Win and linux. Such commands will appear in effective pom as a different literal values and will result in a different effective pom hash and cache key mismatch. Solution: filter out such properties from effective pom:
<input> <global> ... </global> <plugin artifactId="maven-surefire-plugin"> <effectivePom> <excludeProperty>argLine</excludeProperty> </effectivePom> </plugin> </input>
Potential reasons: plugins or tests emit temporary files (logs and similar) in non-standard locations. Solution: adjust global exclusions list to filter out the unexpected files:
<global> <exclude>tempfile.out</exclude> </global>
see sample config for exact syntax
Tracked property in config means it is critical for determining is build up to date or not. Discrepancies could happen for any plugin for a number of reasons. Example: local build is using java target 1.6, remote: 1.8. buildsdiff.xml
will produce something like
<mismatch item="target" current="1.8" baseline="1.6" reason="Plugin: default-compile:compile:compile:maven-compiler-plugin:org.apache.maven.plugins:3.8.1 has mismatch in tracked property and cannot be reused" resolution="Align properties between remote and local build or remove property from tracked list if mismatch could be tolerated. In some cases it is possible to add skip value to ignore lax mismatch"/>
Solution is at your discretion. If the property is tracked, out-of-date status is fair and expected. If you want to relax consistency rules in favor of compatibility, remove property from the reconciliations list