I intend for this to be the first post of a series with various tips and tricks related to effective use of Maven repositories for dependency management, artifact storage, etc, for Java and other JDK languages such as Kotlin. My preferred Maven repository is of course the Maven Central Repository for a variety of reasons, and I will likely include some posts on Maven Central later in the series.
For now, however, I am beginning with a tip related to JitPack, specifically how to configure JitPack builds if your project requires recent JDK versions (e.g., JDK version > 8), or if you want to build with a specific JDK distribution. I am not affiliated with JitPack, and this post is based on my recent experience configuring JitPack builds in a couple of my projects where the JitPack documentation didn't entirely cover my requirements.
Table of Contents: The rest of this post is organized as follows:
- About JitPack: I need to start with an explanation of how JitPack works because it is a bit different than other Maven repositories.
- Why JitPack?: Brief explanation of why I've begun making my libraries available via JitPack in addition to other repositories.
- How to Specify a JitPack Dependency: Although not the purpose of this post, it will be useful to explain how to specify a dependency on an artifact served from JitPack.
- How to Configure JitPack Builds: Explanation with examples of configuring JitPack builds, including an example in a live project on GitHub.
- Where you can find me
About JitPack
JitPack works a bit differently than most other Maven artifact repositories. For most Maven repositories, such as Maven Central or GitHub Packages, you first build the artifacts either locally on your own system, or perhaps as part of a CI/CD workflow (e.g., via GitHub Actions); and then after building your artifacts (e.g., various jar files of compiled class files, source code, documentation, etc) you deploy them to your chosen Maven artifact repository.
JitPack doesn't work like this. Instead, JitPack is designed to build artifacts on-demand direct from a source code repository hosted on GitHub or any other git host, such as GitLab, Bitbucket, etc. The on-demand build occurs the first time a version of an artifact is requested, and then simply served thereafter.
One unique aspect of JitPack that directly derives from its approach is that developers can include dependencies on any public git repository on GitHub, Bitbucket, and other git hosts, even if the maintainers of those repositories don't explicitly publish artifacts to any Maven repository.
Why JitPack?
I am already publishing artifacts of all of the Java libraries I maintain to Maven Central, arguably the definitive Maven repository, so why do I also publish to JitPack? JitPack enables specifying any git tag, branch, pull request, or commit hash as the version for a dependency. You wouldn't want to rely on one of these in production. However, during development at times it might be useful to build against a very specific unreleased version of a dependency. With JitPack, you can do this by specifying the hash of the commit as the version, or even specifying a branch. Isn't this just like using a SNAPSHOT build? Yes, but in this case there is no reason to create SNAPSHOT builds that you may or may not need. Or perhaps your SNAPSHOTs are built nightly, but you find a need to build against a specific point in the git history that occurred between the nightly builds. Or perhaps your nightly SNAPSHOTs are built from the default branch, and you want to build a dependent against a feature branch that is a work-in-progress in the dependency that you are also working on.
This is essentially why I've started publishing artifacts to JitPack in addition to Maven Central. Essentially, as a source of SNAPSHOT builds for any and all commits, and for any and all branches including short-lived pull-request branches, without any intervention on my part.
But wait, did you just say "started publishing artifacts to JitPack"? I thought you said JitPack handles all of this regardless of whether the maintainer of a repository publishes artifacts anywhere? I did say that, and it is true, provided that JitPack can find a build file (such as a Maven pom.xml or the Gradle equivalent), and provided that your project can build with the JitPack defaults. We'll get to this in a bit....
How to Specify a JitPack Dependency
The details of how to specify dependencies depends upon your build tool. I use Maven, so my examples will use Maven. By default, Maven searches for artifacts of dependencies in the Maven Central Repository. If you want to import dependencies from anywhere else, you need to add the details to the <repositories></repositories>
section of your pom.xml. To import from JitPack, insert the following into that section of your pom.xml (you might need to create such a section if you are currently importing only from Maven Central):
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
To import a dependency from a Maven repository, you need to specify its coordinates, which consists in its groupId
, its artifactId
, and its version
. The groupId
is generally a reverse domain, or subdomain, controlled by the one publishing the artifacts. For example, on Maven Central and GitHub Packages, I use org.cicirello
as the groupId
for all of my Java libraries. However, although JitPack does support such custom groupIds, the groupId
for JitPack is usually formed from the domain of the git host along with the username or organization name who owns the repository that you want to import. The artifactId
is the name of the artifact, which is sometimes the name of a package or module within it, but it is not required to be. For JitPack, artifactId
is the name of the repository. And version
is, well, the version that you want.
My examples here will assume you are specifying a GitHub repository as a dependency, but you'll need something very similar for other hosts like Bitbucket.
To import using a tag, such as a release tag like v1.2.3
insert the following into the <dependencies></dependencies>
section of your pom.xml:
<dependency>
<groupId>com.github.USERNAME</groupId>
<artifactId>REPOSITORY_NAME</artifactId>
<version>v1.2.3</version>
</dependency>
JitPack also automatically supports dropping the v
, so if you want to be consistent with other Maven repositories, you can also use:
<dependency>
<groupId>com.github.USERNAME</groupId>
<artifactId>REPOSITORY_NAME</artifactId>
<version>1.2.3</version>
</dependency>
Or if you want to build against the current state of a specific branch, perhaps "main", you can use:
<dependency>
<groupId>com.github.USERNAME</groupId>
<artifactId>REPOSITORY_NAME</artifactId>
<version>main-SNAPSHOT</version>
</dependency>
Or even a specific commit hash with:
<dependency>
<groupId>com.github.USERNAME</groupId>
<artifactId>REPOSITORY_NAME</artifactId>
<version>COMMIT_HASH_GOES_HERE</version>
</dependency>
Whichever of the above you use, be aware that if the version you are importing has not previously been built, there will be a delay in your build while Maven (or Gradle or whatever build tool you are using) waits for a response from JitPack since JitPack must first build the dependency before delivering artifacts. Any subsequent imports, whether by you or someone else, will be without such delay.
Here are the equivalent examples as above, but using one of my repositories, for a Java library I maintain of stochastic local search and evolutionary algorithms, Chips-n-Salsa.
With tag:
<dependency>
<groupId>com.github.cicirello</groupId>
<artifactId>chips-n-salsa</artifactId>
<version>v5.2.0</version>
</dependency>
Dropping the v from the tag:
<dependency>
<groupId>com.github.cicirello</groupId>
<artifactId>chips-n-salsa</artifactId>
<version>5.2.0</version>
</dependency>
Latest commit in default branch:
<dependency>
<groupId>com.github.cicirello</groupId>
<artifactId>chips-n-salsa</artifactId>
<version>master-SNAPSHOT</version>
</dependency>
From a commit hash:
<dependency>
<groupId>com.github.cicirello</groupId>
<artifactId>chips-n-salsa</artifactId>
<version>278803985ceb0e3d1515eefb2a69d0601e0176cf</version>
</dependency>
From a pull-request:
<dependency>
<groupId>com.github.cicirello</groupId>
<artifactId>chips-n-salsa</artifactId>
<version>PR451-SNAPSHOT</version>
</dependency>
JitPack also supports configuring reverse domain:
I have also configured my reverse domain on JitPack, so all of the above will likewise work with <groupId>org.cicirello</groupId>
in addition to <groupId>com.github.cicirello</groupId>
, which is nice for consistency with Maven Central. But only the released versions are available via Maven Central, such as through a dependency like:
<dependency>
<groupId>org.cicirello</groupId>
<artifactId>chips-n-salsa</artifactId>
<version>5.2.0</version>
</dependency>
How to Configure JitPack Builds
You may or may not need to configure JitPack at all. If you have a Maven pom.xml in the root of your repository (or whatever the equivalent of this is for Gradle), AND if your project can be built with Java 8, then you likely won't need any configuration. You, or anyone else for that matter, can already utilize JitPack to import your repository as a Maven dependency. Upon finding a pom.xml at the root of your repository, JitPack will attempt to build using Java 8 with the following:
mvn install -DskipTests
I imagine that it skips running your tests to decrease the length of the delay the first time an artifact is requested. This seems reasonable.
In my case, most of my libraries require Java 17, so without configuration JitPack builds fail. To configure for a more recent JDK, here are the steps.
Step 1: Create a file named jitpack.yml
at the root of your repository. This is where all configuration takes place. Feel free to consult the jitpack.yml for the project this post is based upon, Chips-n-Salsa, for full details.
Step 2: Specify the JDK version within jitpack.yml
such as with:
jdk:
- openjdk17
Note that if you were to guess (like I did) that the above is sufficient, you'd be incorrect. You now need to install the JDK distribution that you want to use, as well as explicitly specify that you want to use it. I'm using the Temurin distribution of OpenJDK in the project that this post is based upon. You need both of the statements I've added below. Without the sdk use
, JitPack will continue to use Java 8. You can find the full list of available JDKs on the sdkman site.
jdk:
- openjdk17
before_install:
- sdk install java 17.0.3-tem
- sdk use java 17.0.3-tem
Step 3: Update Maven. The above might be sufficient in some cases. For me, it was not. JitPack currently (as of the time of the writing of this post) has Maven 3.6.1 installed. Maven 3.6.1 was released over 3 years ago in April 2019. The <release>
property for configuring Java version didn't exist then. If you are using that (as I am), your JitPack build will fail unless you update Maven. You can do that by revising the above to what follows (which as of the writing of this post will update Maven to 3.8.6):
jdk:
- openjdk17
before_install:
- sdk install java 17.0.3-tem
- sdk use java 17.0.3-tem
- sdk install maven
- mvn -v
You don't really need the mvn -v
above. I included that to show the version in the build logs.
Step 4: Customize the install step. You might be done at this point, provided that JitPack's default build command of mvn install -DskipTests
is relevant to your project. In my case, I wanted to also disable one of JitPack's features. One of JitPack's features, which many probably like, is that if the build produces a jar of the javadocs, JitPack will automatically extract the javadocs and serve them, including maintaining the javadocs for each release. I would prefer it if they simply served the jar of the javadocs, as Maven Central does, rather than automatically hosting them. For the libraries that I maintain, I also host the javadocs on the project's site, and would prefer if the definitive version of the javadocs is unambiguously the version hosted on my domain, cicirello.org
. Thus, for JitPack builds, I simply disable javadoc generation, leading to the complete jitpack.yml
below:
jdk:
- openjdk17
before_install:
- sdk install java 17.0.3-tem
- sdk use java 17.0.3-tem
- sdk install maven
- mvn -v
install:
- mvn install -Dmaven.javadoc.skip=true -DskipTests
Important Note: Because of the way JitPack essentially builds a snapshot of your repository, even for release builds, the jitpack.yml
must be present within the specific snapshot of your repository in order to apply. For example, for the library that this post is based upon, Chips-n-Salsa, the first release where the repository contains the configuration file is 5.0.1, so JitPack will fail to build any prior version, although earlier versions are available via Maven Central and GitHub Packages. Likewise, if you specify any commit hash prior to that of the commit where that configuration file was introduced, the JitPack build will also fail.
Live Configuration Example: See this jitpack.yml for a complete and live example, which is found within the following repository:
cicirello / Chips-n-Salsa
A Java library of Customizable, Hybridizable, Iterative, Parallel, Stochastic, and Self-Adaptive Local Search Algorithms
Copyright (C) 2002-2024 Vincent A. Cicirello.
Website: https://chips-n-salsa.cicirello.org/
API documentation: https://chips-n-salsa.cicirello.org/api/
How to Cite
If you use this library in your research, please cite the following paper:
Cicirello, V. A., (2020). Chips-n-Salsa: A Java Library of Customizable, Hybridizable, Iterative, Parallel, Stochastic, and Self-Adaptive Local Search Algorithms. Journal of Open Source Software, 5(52), 2448, https://doi.org/10.21105/joss.02448 .
Overview
Chips-n-Salsa is a Java library of customizable, hybridizable, iterative, parallel, stochastic, and self-adaptive local search algorithms. The library includes implementations of several stochastic local search algorithms, including simulated annealing, hill climbers, as well as constructive search algorithms such as stochastic sampling. Chips-n-Salsa now also includes genetic algorithms as well as evolutionary algorithms more generally. The library very extensively supports simulated annealing. It includes several classes for representing solutions to a variety of optimization problems…
Where you can find me
On the Web:
Follow me here on DEV:
Follow me on GitHub:
Vincent A Cicirello
View My Detailed GitHub Activity
If you want to generate the equivalent to the above for your own GitHub profile, check out the cicirello/user-statistician GitHub Action.
Top comments (0)