Skip to content

Feedback - Lab 2

Tag your final code submission

When evaluating your code, we use the Lab2 tag to checkout your code, as in git checkout Lab2. If you did not tag your final code submission, we have to search for the last commit before the deadline.

Some groups however tagged code correctly, but made changes after the tag, before the deadline. This makes it hard for us to evaluate your code, since we don't know which commit to use. Please use other tags to test or mark progress and reserve the requested LabX tags for the final submission.

Tip: it is possible to remove a tag and re-add it to a different commit if you mistagged your code.

Maven lifecycle phases

Running both compile and package in one job

In maven-build many added the ./mvnw package instruction instead of replacing the ./mvnw compile instruction. This is not necessary, since ./mvnw package will also compile the code. Luckily maven will skip the compile phase if the code is already compiled, but it does cost you a bit of processing overhead since you start the command twice.

maven-build:
  script:
    # - mvn compile ## No longer necessary since package will also compile
    - mvn package -DskipTests

Keep your Unit Tests small

Many groups write a Unit Test which tests e.g. all functionality of a Cleric or Miner. Maybe this is because of confusion between the term Unit Test and the DevOps game Units. A Unit Test should test a single unit of code, e.g. a single method. If you want to test all functionality of a Cleric or Miner, you should write multiple Unit Tests, each testing a single method. This makes it easier to find the cause of a failing test and makes it easier to write the test. If you want to avoid code duplication in your Unit Tests, you can use the @Before annotation to create a setup method which is run before each test or extract functionality to a separate method. You can go even further and make additional test suites, one for each Game Unit for instance, to group common functionality together.

Using the wrong image version in the integration test

We noticed a fair amount of integration tests still using the latest version of the image instead of the commit hash. This essentially means that you are not testing the code of the commit that triggered the pipeline, but a quasi random version since as the pipeline is set up now, multiple branches can push that latest tag.

Excessive use of YAML anchors and extends

The idea of reducing duplication is to A) make the code more readable and B) make it easier to change. If you use anchors and extends too much you will achieve the opposite. Some groups went really hard into this subject but ended up with a very complex .gitlab-ci.yml. Their pipelines worked, and they (often arguably) reduced duplication, but at the cost of readability, maintainability and also collaboration.

Below an example of how you can achieve a clean and readable integration test setup with only extends:

.integration-tmpl:
  cache: []
  dependencies: []
  stage: tests
  image:
    name: ${UTIL_REGISTRY}/devops-runner:latest
    entrypoint:
      - ""
  script:
    - java -cp /app/resources:/app/classes:/app/libs/* be.ugent.devops.gamehost.services.runner.LauncherKt
  services:
    - name: ${CI_REGISTRY_IMAGE}/logic-service:${CI_COMMIT_SHORT_SHA}
      alias: logic-service
  variables:
    PLAYER_NAME: "CI/CD Player"
    LOGIC_URL: http://logic-service:8080
    ENABLE_FETCH_LOGS: "true"
    ABORT_ON_LOGIC_ERROR: "true"

test-integration-default:
  extends: .integration-tmpl
  variables:
    TURN_INTERVAL_MS: 25
    TURN_LIMIT: 100
    CPU_PLAYERS: 5
    MAP_WIDTH: 50
    MAP_HEIGHT: 50

test-integration-tiny-duel:
  extends: .integration-tmpl
  variables:
    TURN_INTERVAL_MS: 25
    TURN_LIMIT: 1000
    CPU_PLAYERS: 1
    MAP_WIDTH: 5
    MAP_HEIGHT: 5

Another tip is to use the GitLab pipeline editor and its Full Configuration view which will render the .gitlab-ci.yml file in its entirety, processing all anchors and extends. This way you can see what the final pipeline will look like and you can check if it does what you expect it to do.

GitLab Pipeline editor, full configuration

Mixing Quarkus configuration options

It is possible to configure Quarkus and your Logic Service using multiple methods. You can use environment variables, system properties, application.properties, application.yaml, profiles, etc. However, it is important to be intentional and consistent in how you configure your service.

In some jobs we see mixing of environment variables and system properties for the same configuration option. Setting both the variable QUARKUS_CONTAINER_IMAGE_PUSH=true and the system property -Dquarkus.container-image.push=true will lead to the system property taking precedence. Now when you decide to change the configuration, you might change the environment variable, but the system property will still be set and take precedence. This can lead to unexpected behavior and confusion.

Clean-up policy: case sensitivity

Be mindful that the regex for the clean up policy is case sensitive! Many groups had a policy such as lab.* but then pushedLab 2. This will not match and thus the tag will be removed.

An example regex which sets case insensitivity and matches both none and some whitespace is (?i)lab ?\d+, see this example on regex101.com for full explanation.