Lab 1 Report
Successful run of a CI/CD run executing game
https://gitlab.stud.atlantis.ugent.be/SeppeMeeus/devops-project/-/pipelines/77846
My .gitlab-ci.yml file
variables:
MAVEN_CLI_OPTS: "--batch-mode -Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository"
I've changed this part in order to fix the caching. When setting the lab provided MAVEN_OPTS: "-Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository" CI variable the .m2/repository directory cannot be found. Because of this the caching simply will not work. This can be seen in some of my earlier runs (example, relevant output below).
Saving cache for successful job
00:01
Creating cache main-protected...
WARNING: .m2/repository: no matching files. Ensure that the artifact path is relative to the working directory (/builds/SeppeMeeus/devops-project)
Archive is up to date!
Created cache
...
The cause for this is the Maven wrapper script overriding it. The command in the script for the compile job is calling the Maven wrapper ./mvnw. This script on one of its first lines contains an export MAVEN_OPTS="..." itself which apperantly overrode the corresponding variable from CI/CD.
For the caching I added a key $CI_COMMIT_REF_SLUG to have jobs in each branch use the same cache.
In the maven-build job I've set the expiration time for the artifacts to a week in case i need to download an artifact later on. This uses up a bit of repo space but nothing crazy. I also wanted to mention I find the job's name to be a bit misleading as I was expecting it to produce a .jar file which the artifact would then pass onto the next job. This isn't the case though since Maven is just compiling the source here. It did cause me to look more into Maven's Build Lifecycle so I learned something new anyhow, which is great. Imo maven-compile would be a better job name here or just let the build step produce a .jar file with package.
Don't really have much to add for the maven-container-image-generation job. All is pretty self-explanatory. I have seen other repos use $CI_PROJECT_PATH for the QUARKUS_CONTAINER_IMAGE_GROUP environment variable which might be cleaner.
Not really anything to say about the run-game job either since it worked first try (was mostly copy paste from the lab). I've decided to not let it depend on any artifact since it doesn't have to as it's only using docker images.
I didn't encounter any issues apart from noticing the caching didn't work and being confused about the maven-build job or build stage not producing a .jar file in target/ as aforementioned.
Questions
What is ./mvnw and what is the advantage of using it above mvn?
./mvnw is a wrapper script for the Java maven build tool. It allows users to have a fully self-contained build setup provided by the project. The advantage of this is it being reproducible for everyone using the project. Everyone who works on the project will have the same maven version and thus no (maven) compatibility issues can arise. Users do not download Maven themselves. The wrapper will download it to .m2/wrapper if it's missing.
Explain the key differences between GitLab's cache and artifacts mechanisms. For each of Maven dependencies and build files, explain which mechanism you chose and why. What are the trade-offs of your choices?
A cache is one or more files a job downloads and saves. Subsequent jobs that use the same cache don’t have to download the files again, so they execute more quickly. This is particularly useful for external dependencies like those specified in pom.xml. An artifact is an archive of files and directories that a job can output. This archive can then be used in subsequent jobs, effectively passing intermediate build results between jobs. Doing it this way a subsequent job doesn't have to recompile the whole application, saving on compute and build minutes.
How i used each:
| Maven | used technique |
|---|---|
| dependencies | cache |
| build files | artifact |
As far as tradeoffs go for choosing caching for dependencies over artifacting i can't really think of any. It is obviously the correct (and only) choice here since I want my cache to persist over different pipeline runs and do not need to download this cache.
For the compiled build files of the application I don't need to persist them over different pipeline runs, but maybe do want to download them to debug locally. On top of that any code change (new commit) triggers a pipeline run. This would cause the cache to be invalid since the build files it contains are out of date. Such frequent updating isn't really a use case for GitLab caching. A disadvantage of artifacting is that it can take up quite a bit of repository space if the files need to be kept for a while.
In this lab, we use a 25-jre image as the base for our runtime container and a 25-jdk image for the CI/CD build jobs. Explain the reasoning behind this choice. What would be the impact (positive or negative) of using 25-jdk for both? What about using 25-jre for both?
A jre image contains only the Java Runtime Environment which is needed to actually run a compiled Java application. This is perfect for the runtime container as it's already compiled. Using a jdk here would be pure bloat.
A jdk image contains the full Java Development Kit which includes the compiler and the jre. This is needed for the CI/CD build jobs since the Java project still needs to be compiled there. Without the Java compiler this would obviously not be possible.
Using the jre for both would not work since the Java project still needs to be compiled. This is impossible without the Java compiler which the runtime environment does not provide. Using the jdk for both would work perfectly, but introduces unnesecary bloat for the runtime container as the compiler is not needed there.