Maven is a great build tool. Although it's based on XML, it's still manageable XML. Easy to understand, easy to write.
It also is a quite simple build tool, the only thing we need, in terms of Java/Kotlin/any other JVM based language is a
pom.xml ("Project Object Model"... makes sense in hindsight, but I could have never guessed it)
Maven and Gitlabs Docker Runners
Today we would like to promote the usage of Maven as a build tool with Gitlabs Docker Runner. And there is not much we can do wrong by using Maven and Gitlab Docker Runners, except two things.
Since Maven in contrast to other build dependency management solutions stores its general settings not in the before mentioned
pom.xml but rather uses a dedicated
settings.xml and a dedicated cache folder in the
.m2 folder of the user directory, its performance in combination with Docker is open for improvements.
Mind you, nothing impossible there, but also not as straight forward as with other solutions like
So lets address these two pain points, shall we?
Caching Maven Dependencies with Gitlabs Docker Runner
Actually, it's quite simple, but takes a bit of digging through the World Wide Web to find the solution, which is as simple as an environment variable. In our case we found it best to utilize the
MAVEN_OPTS environment variable setting its value to
build_maven: variables: MAVEN_OPTS: "-Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository" cache: paths: - ./.m2/repository/ image: maven:3-jdk-12-alpine stage: build script: - mvn clean verify only: - master - develop
What we can see from the example above is that we set the Maven local repository to the current build directory, which in turn now, as Gitlab is only able to cache stuff within the current project directory, enables Gitlab to cache our dependencies.
Of course, depending on the size of our project this could be a huge performance impact of our builds, or a really marginal one. Nevertheless, as our project grows, we definitely want to have those cody bits in there to save some time.
Using a settings.xml in our Build Project
Maybe, just maybe, we are one of the majorities that don't have their artifacts shipped to mvnrepository.com. That's fine, since most of the work a normal developer does is proprietary software, we probably have our own JFrog Artifactoy or Sonatype Nexus Repository setup within our company.
But that also means standard
mvnwouldn't know about it, that's why we generate a fancy
settings.xml out of those tools, put it into our
.m2 folder on our development machine and be happy about it.
But as soon as CI/CD hits, we are faced with the question:
How can my Docker Runner use such a configuration?
And the answer is also, quite simple again.
mvn --settings $MAVEN_SETTINGS_XML clean deploy
Cheesy right? Gitlab offers the possibility to provide environment variables during build jobs, and we should utilize that possibility, create an CI/CD user for our repository, and copy the generated settings XML into such an environment variable.
Mind the type of that variable though: File.
Gitlab here is putting the content we put in there into a file on the file system referencing the path to it via the environment variable, which we are passing to
So effectively we are passing a path to it, not an inline version of the
This way and with the
--settings we can pass those settings to Maven in order to be utilized by the build it's about to be doing for us.
To be honest, it's not rocket science, and we can probably get away without optimizing our CI/CD pipeline in such a manner, but putting the time into making our CI/CD as efficient as possible will definitely help us in the long run!
Feel free to copy the combined example of both our above explained techniques.
build_maven: variables: MAVEN_OPTS: "-Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository" cache: paths: - ./.m2/repository/ image: maven:3-jdk-12-alpine stage: artifactory script: - mvn --settings $MAVEN_SETTINGS_XML clean deploy only: - master - develop