3

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.

Pasha
  • 1,768
  • 6
  • 22
  • 43

1 Answers1

14

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:


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).

jeffrey.d.m
  • 616
  • 8
  • 23
Justin Albano
  • 3,809
  • 2
  • 24
  • 51
  • but I have a Gradle project, the question is about Gradle – Pasha Jan 06 '19 at 15:07
  • @Pavel That is my fault: I misread the original question. I have updated the answer to reflect a Gradle build (while leaving the Maven portion for reference). – Justin Albano Jan 06 '19 at 15:52
  • Thank you, do we still use image: maven:3-jdk-11 ? – Pasha Jan 06 '19 at 16:36
  • @Pavel Yes, the `maven:3-jdk-11` is required as of now to run a JDK 11 build. Otherwise, you may see errors such as `Fatal error compiling: invalid flag: --release`. – Justin Albano Jan 06 '19 at 16:40
  • I mean, don't we use something like gradle:5-jdk-11? As I use Gradle 5 – Pasha Jan 06 '19 at 17:17
  • @Pavel You are correct: You could use that one as well. As long as the Docker image selected supports JDK 11. My statement was made in the context of `maven` images, but `gradle:5-jdk-11` would work as well. I have updated the answer to reflect your comment. – Justin Albano Jan 06 '19 at 17:25
  • I don't know if gradle:5-jdk-11 exist, it was just for example, should I use maven image in case I have a gradle project? – Pasha Jan 06 '19 at 17:38
  • @Pavel There actually are Gradle Docker images similar to the name you provided (i.e. `gradle:5-jdk-11`) so I thought that that was a valid image name. There is, however, a `gradle:jdk11` image that can be used. I would prefer using the Gradle images over the Maven ones because those are guaranteed to have Gradle installed (the Maven images may or may not have Gradle installed). If you want to see the list of Gradle images available, see https://hub.docker.com/_/gradle/. – Justin Albano Jan 06 '19 at 18:02
  • Hi @Justin, I have the following exception in GitLab: /bin/bash: line 77: ./gradlew: No such file or directory ERROR: Job failed: exit code 1 because I simply don't have this folder in my project – Pasha Jan 06 '19 at 22:55
  • Be sure you have a gradlew script in the root of your project. Otherwise, you can adjust the specifics of the build step to reflect the specifics of your project. – Justin Albano Jan 06 '19 at 22:59
  • Works. Pipeline passed. Also need to >git update-index --chmod=+x gradlew – Pasha Jan 06 '19 at 23:12
  • Why do we need the Gradle wrapper if we are using the Gradle image and vice verca? Isn´t the wrapper meant to be used for environments where Gradle is not installed? – Marian Klühspies Nov 26 '20 at 13:52
  • @MarianKlühspies You don't have to run with the wrapper, but you can safely, even if Gradle is already installed on the machine. I tend to use the wrapper even on machines with Gradle installed because it is consistent (i.e., use the wrapper all f the time and it works regardless of whether Gradle is already installed or not). For more info: https://docs.gradle.org/current/userguide/gradle_wrapper.html – Justin Albano Dec 07 '20 at 12:36
  • 1
    @JustinAlbano Sure, you can do that, but you could also just use an Openjdk Docker Image as well as the wrapper will download the Gradle executable anyway. So I don´t really see a point in using the Gradle image if you are using the wrapper:) Makes your Docker image a bit slimmer as well – Marian Klühspies Dec 07 '20 at 13:10
  • @MarianKlühspies According to the documentation, the Gradle wrapper will "[download] it beforehand if necessary". From my understanding, it will not cause any unnecessary installations. It will amount to a no-op on the download. You are right, though, that for this particular case, foregoing the wrapper would be more direct. – Justin Albano Dec 09 '20 at 16:24
  • Use the first Android example that this dude shared in his comment https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Android.gitlab-ci.yml, be sure to change the image to use java11 and change the line where PATH is defined to "export PATH=$PATH:${ANDROID_HOME}/cmdline-tools/cmdline-tools/bin/" – Erick Jan 19 '22 at 00:41