How to make GitLab CI Release a Spring Boot JAR using gradle? - java

I have a Spring Boot project that builds using a bootJar task in gradle. It produces a runnable ____-1.0-SNAPSHOT.jar file. Now, I want to leverage GitLab CI to build the JAR and make releases.
There didn't seem to be an obvious way to do the builds. I started looking at the researchgate gradle plugin. It seems promising but has a lot of assumptions.
What is the best way to get the release JARs out of GitLab CI?

There is couple of ways of getting released artifacts from gitlab ci pipeline.
Publish it to maven repository (private repository if it is propitiatory)
use gitlab job artifact functionality within pipeline so you can download it via gitlab web interface
build docker image from your pipeline and upload it to docker registry from pipeline
Here is the sample .gitlab-ci.yml which uses gitlab job artifacts functionality (assume gradle wrapper is used)
image: java:8-jdk
cache:
paths:
- .gradle/wrapper
- .gradle/caches
build:
stage: build
script:
- ./gradlew assemble
# define path to collect artifacts
artifacts:
paths:
- build/libs/*.jar
expire_in: 1 week
only:
- master

Ruwanka provided a great answer, however I believe it is now a bit outdated. GitLab.com (and self-hosted) now supports hosted maven repositories as a native feature of their Premium tiers.
More information regarding how to deploy a java application (JAR, etc.) for private or public consumption can be found here:
https://docs.gitlab.com/ee/user/project/packages/maven_repository.html#gitlab-maven-repository-premium

Related

What should be the .gitlab-ci.yml file that activates Gitlab to build a project and run tests?

I have a Gradle Java 11 project that resides into Gitlab.
I wanted to introduce gitlab-ci.yml to force Gitlab to build a project and run tests on each push to a remote branch.
What should it look like?
I'm pretty sure that a similar question already has been asked but I couldn't find it, so I appreciate your help.
Gitlab provides an official description of the .gitlab-ci.yml file, but that could be a bit lengthy to get started out of the gate. For a basic project, you can use the following as a basis:
image: gradle:jdk11
before_script:
- export GRADLE_USER_HOME=`pwd`/.gradle
cache:
paths:
- .gradle/wrapper
- .gradle/caches
package:
stage: build
script:
- ./gradlew assemble
test:
stage: test
script:
- ./gradlew check
Note that the image tag is set to maven:latest in many examples, but in order for Gitlab to compile the project using JDK 11, the image tag must be set to maven:3-jdk-11. The GRADLE_USER_HOME is set to the .gradle of the current directory that the script is read from to ensure that the Gradle environment is properly configured before starting the build.
The cache section defines the paths that Gitlab CI should look for cached artifacts and dependencies (which, for a Gradle build, is .gradle/wrapper and .gradle/cache). Builds may take a long time to execute, as each build requires downloading all dependencies each time the build is executed; to speed this up, caching can be included to remove the need to repeatedly download dependencies. The specifics for caching may vary for your project. See the official cache documentation for more information.
The assemble and check steps simply run gradle assemble and gradle check, respectively. While gradle test would be sufficient in many cases (as opposed to gradle check, the check step includes test while also including other verification steps. For more information on the difference between check and test, see Gradle difference between test and check.
For more information, see the following:
How to enable maven artifact caching for gitlab ci runner?
Cache dependencies in GitLab CI/CD
GitLab CI/CD Examples
Gitlab CI gradle dependency cache
A sample of .gitlab-ci.yml for a gradle project
gitlab 8.2.1, How to use cache in .gitlab-ci.yml
List of supported gradle images
Equivalent Maven example:
image: maven:3-jdk-11
variables:
MAVEN_CLI_OPTS: "--batch-mode"
MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository"
cache:
paths:
- .m2/repository/
- target/
package:
stage: build
script:
- mvn $MAVEN_CLI_OPTS package
test:
stage: test
script:
- mvn $MAVEN_CLI_OPTS test
The --batch-mode flag runs Maven with default values and does not prompt the user to select any defaults. The -Dmaven.repo.local=.m2/repository sets the local repository to the location on the build server (Gitlab). which plays into the caching ability of Gitlab. Builds may take a long time to execute, as each build requires downloading all dependencies each time the build is executed; to speed this up, caching can be included to remove the need to repeatedly download dependencies. The specifics for caching may vary for your project. See the official cache documentation for more information.
The package and test steps simply run mvn package and mvn test, respectively (with the Maven options described above).

GitLab CI Maven dependency resolution fails

I want to setup a CI pipeline in GitLab for my Java project managed with Maven.
This is my gitlab-ci.yml
image: maven:3-jdk-9
variables:
MAVEN_CLI_OPTS: "--batch-mode"
stages:
- build
compile:
stage: build
script:
- mvn $MAVEN_CLI_OPTS compile
I always get the following exception:
I tried many things like changing versions of the plugins, various docker images, including a settings.xml and local repository in the project itself, but nothing works.
Thanks in advance for any help!
UPDATE:
Using the latest docker image everything works.
It seems like the CI server has no connection to the internet. Check this using the curl command in your .gitlab-ci.ymlfile.
But I'm pretty sure you guys at daimler have a local mirror, something like Artifactory.
In that case you have to use a settings.xml file.
Here is the official tutorial of Gitlab

How to add java library without no repository to pom file?

I'd like to add one project A as my dependency, but unfortunately, there's no repository host this library. I know that I can install it to local repository manually, then refer this in pom file. But I have a travis build job where there's no such artifact, is there any way that I can install this library to local repo automatically ? Thanks
I would recommend to use the clean approach and uploading this library into your own repository. If you don't have one: time to get one running.
If you're really not up to this task the maven install plugin: http://maven.apache.org/plugins/maven-install-plugin/install-file-mojo.html can install a jar in the local repository. This will work both locally and on a CI server.
To upload a jar in a remote repository there is the deploy plugin: http://maven.apache.org/plugins/maven-deploy-plugin/deploy-file-mojo.html
If you bind the execution of this plugin to a very early phase in the maven life-cycle (validate) you might be able to avoid a build step required prior of your own build.

Travis CI not using extra Maven repository provided in pom.xml

I have a Java-based GitHub project, fitnessjiffy-spring (I'm currently focused on the "bootstrap" branch). It depends on a library built from another GitHib project, fitnessjiff-etl. I am trying to configure both of these to be built by Travis CI.
Unfortunately, Travis is not as sophisticated as Jenkins or Hudson in dealing with Maven-based Java projects. Jenkins can easily handle dependencies between projects, but the same concept doesn't seem to exist with Travis. If one project depends on another, then that other project must already be built previously... and its artifact uploaded to some Maven repo where the first project can download it later.
My "fitnessjiffy-etl" library is building and deploying just fine. I'm using Bintray for Maven repository hosting, and you can clearly see my artifacts over plain HTTP at:
http://dl.bintray.com/steve-perkins/maven/
In my "fitnessjiffy-spring" project, I am adding this Maven repo location directly in the pom.xml, so that Travis will be able to find that artifact dependency. Here is the state of my POM at the time of this writing. Note the <repositories> element at the bottom of the file.
When I build this project locally, it works just fine. I can see it downloading the Maven artifact from "http://dl.bintray.com/...". However, when I try to build on Travis CI it fails every time. I can see in the console log that Travis is still trying to download the artifact from Maven Central rather than my specified repo.
Does this make sense to anyone else? Why does Maven utilize a custom repository location in a POM file when building locally, but ignores this configuration when running on a Travis CI build?
From digging into this further, I discovered that Travis uses its own proxy for Maven Central, and has configured Maven to force ALL dependency requests through their proxy. In other words, it does not seem possible at this time to use additional Maven repos specified in the POM file of a project built on Travis.
In my case, I ended up refactoring such that project would not need the outside JAR dependency. I also switched to Drone.io, so I could manage my settings on the build server rather than having to carry a YAML file in my repository (which always struck me as a bit daft).
However, even on Drone it's still a major hassle to manage dependencies between multiple projects (extremely common with Java development). For Java, I just don't think there's currently an adequate substitute for Jenkins or Hudson, maybe running on a cheap Digital Ocean droplet or some other VPS provider instance.
In your install phase add a $HOME/.m2/settings.xml define your custom repository.
cache:
directories:
- "$HOME/.m2"
install:
- curl -o $HOME/.m2/settings.xml
https://raw.githubusercontent.com/trajano/trajano/master/src/site/resources/settings.xml
- mvn dependency:go-offline
script:
- mvn clean install site

Heroku: Java/Maven build requires NodeJS

I've got a Java web application that builds with Maven. My project uses RequireJS. I use a maven plugin at build time to compress the JS artifacts (https://github.com/bringking/requirejs-maven-plugin). The plugin calls out to NodeJS (with the r.js compressor) to do the actual work.
Local builds work wonderfully.
On Heroku, however, NodeJS is not available using the Heroku Java buildpack (the default for Java/Maven applications).
For now, I run the requireJS maven plugin locally using an active Maven profile that isn't present on the Heroku server. This prevents the RequireJS plugin from running on the Heroku server. This is less than ideal because it requires me to run the plugin locally, then check in the resulting build artifact. It's far better to generate the compressed JS file at build time in the Heroku system.
I'm looking for a good solution. Thanks in advance.
The best solution is to use Heroku Multi Buildpack with the Node.js and Java buildpacks. This is described in an article using Grunt with Java and Maven but the same principles apply for Require.js.

Categories

Resources