Commit 5e43e602 authored by Ruben ten Hove's avatar Ruben ten Hove
Browse files

fix: monorepo image name race condition

parent f912a641
Loading
Loading
Loading
Loading
+1 −5
Original line number Diff line number Diff line
@@ -19,11 +19,7 @@ variables:
    - echo "{\"auths\":{\"$CI_REGISTRY\":{\"auth\":\"$(echo -n
      ${CI_REGISTRY_USER}:${CI_REGISTRY_PASSWORD} | base64)\"}}}" >
      /tmp/auth.json
    - |
      if [ "${IMAGE_CONTAINERFILE}" != "" ]; then
        CONTAINERFILE_ARG="-f ${IMAGE_CONTAINERFILE}"
      fi
    - buildah build --authfile /tmp/auth.json ${CONTAINERFILE_ARG}
    - buildah build --authfile /tmp/auth.json -f ${IMAGE_CONTAINERFILE}
      --tag=${IMAGE_NAME}:${IMAGE_DEV_TAG} --tag=${IMAGE_NAME}:${IMAGE_TAG}
      --layers=${IMAGE_CACHE} ${BUILDAH_EXTRA_ARGS} ${IMAGE_CONTEXT}
    - |
+23 −7
Original line number Diff line number Diff line
---
variables:
  IMAGE_NAME: automatic
  IMAGE_CONTAINERFILE: automatic
  IMAGE_DEV_TAG: dev-${CI_COMMIT_SHORT_SHA} # to always be used for follow-up jobs
  IMAGE_CONTEXT: ${CI_PROJECT_DIR}
  IMAGE_CACHE: "true"
@@ -23,12 +25,17 @@ variables:

.image:name:
  script:
    - IMAGE_CONTEXT=${IMAGE_CONTEXT/${CI_PROJECT_DIR}\/} # Remove CI_PROJECT_DIR prefix path
    - |
      if [ "${IMAGE_NAME}" = "" ]; then
      if [ "${IMAGE_CONTEXT}" = "${CI_PROJECT_DIR}" ]; then
        IMAGE_CONTEXT="."
      else
        IMAGE_CONTEXT=${IMAGE_CONTEXT/${CI_PROJECT_DIR}\/} # Remove prefixed path CI_PROJECT_DIR
      fi
    - |
      if [ "${IMAGE_NAME}" = "automatic" ]; then
        if [ "$(realpath ${IMAGE_CONTEXT})" != "$(realpath ${CI_PROJECT_DIR})" ]; then
          if [ "$(echo ${IMAGE_CONTEXT} | tr -cd '/' | wc -c)" -gt 2 ]; then
            echo "[!] Your image path is too deep. The limit is 2. Please set IMAGE_NAME to '\${CI_REGISTRY_IMAGE}/your_name/up_to_here'."
            echo "[!] Your context path is too deep. The limit is 2. Please set IMAGE_NAME to '\${CI_REGISTRY_IMAGE}/your_name/up_to_here'."
            exit 1
          fi
          IMAGE_NAME=$(echo ${CI_REGISTRY_IMAGE}/${IMAGE_CONTEXT} | tr [:upper:] [:lower:])  # Ensure lowercase
@@ -36,20 +43,29 @@ variables:
          IMAGE_NAME=${CI_REGISTRY_IMAGE}
        fi
      fi
    - |
      if [ "${CI_JOB_NAME}" = "image:build" ]; then
        echo "[+] Setting IMAGE_NAME for subsequent jobs to ${IMAGE_NAME}."
        echo "IMAGE_NAME=${IMAGE_NAME}" > ${CI_PROJECT_DIR}/image.env
      fi
    - |
      if [ "${IMAGE_CONTAINERFILE}" = "automatic" ]; then
        IMAGE_CONTAINERFILE=${IMAGE_CONTEXT}/Dockerfile
      fi
    - |
      echo "[*] Build info:"
      echo "Containerfile: ${IMAGE_CONTAINERFILE:-(default builder value - usually Dockerfile)}"
      echo "Context: ${IMAGE_CONTEXT}"
      echo "Image name: ${IMAGE_NAME}"
      echo "Containerfile: ${IMAGE_CONTAINERFILE#./}"
      echo "Name: ${IMAGE_NAME}"
      echo "Tags: ${IMAGE_TAG} ${IMAGE_DEV_TAG}"
  artifacts:
    reports:
      dotenv: image.env

# Allows for less problems with a monorepo setup. See pipelines/container.md.
# Extend this one for a default image build in a monorepo
.image:build:
  extends: .kaniko # Default to kaniko.

# Don't extend this one, unless you intend to re-use your first image settings in a monorepo
image:build:
  extends: .image:build
+2 −5
Original line number Diff line number Diff line
@@ -21,13 +21,10 @@ variables:
      if [ "${KANIKO_EXTRA_ARGS}" != "" ]; then
        echo "[*] Applying the extra arguments '${KANIKO_EXTRA_ARGS}'."
      fi
    - |
      if [ "${IMAGE_CONTAINERFILE}" != "" ]; then
        CONTAINERFILE_ARG="--dockerfile=${IMAGE_CONTAINERFILE}"
      fi
    - echo "{\"auths\":{\"$CI_REGISTRY\":{\"auth\":\"$(echo -n
      ${CI_REGISTRY_USER}:${CI_REGISTRY_PASSWORD} | base64)\"}}}" >
      /kaniko/.docker/config.json
    - /kaniko/executor --cache=${IMAGE_CACHE} --context=${IMAGE_CONTEXT}
      ${CONTAINERFILE_ARG} --destination=${IMAGE_NAME}:${IMAGE_DEV_TAG}
      --dockerfile=${IMAGE_CONTAINERFILE}
      --destination=${IMAGE_NAME}:${IMAGE_DEV_TAG}
      --destination=${IMAGE_NAME}:${IMAGE_TAG} ${KANIKO_EXTRA_ARGS}
+14 −3
Original line number Diff line number Diff line
## Monorepo (multiple Dockerfiles)

You can build multiple `Dockerfile`s in your repository, by using the following
steps.
steps. We differentiate between a primary image and secondary and further
images. The primary image will be used by any subsequent jobs that rely on a
built container to perform further actions. For example, the job `python:pytest`
will be using this primary container.

This container is built by the job `image:build`, which is the default job for
building any image when importing our templates.

We provide two examples with a directory tree and a `.gitlab-ci.yml`.

@@ -31,7 +37,7 @@ image:build:subdir_b:
grype:subdir_b:
  extends: .grype
  variables:
    IMAGE_NAME: subdir_b
    IMAGE_NAME: ${CI_REGISTRY_IMAGE}/subdir_b
```

### Two Dockerfiles in two subdirectories
@@ -69,12 +75,17 @@ image:build:subdir_b:
grype:subdir_b:
  extends: .grype
  variables:
    IMAGE_CONTEXT: subdir_b
    IMAGE_NAME: ${CI_REGISTRY_IMAGE}/subdir_b
```

You can have as many subdirectories and Dockerfiles as you want. They can even
share contexts. That's all up to you.

The setting above would create the images `${CI_REGISTRY_IMAGE}/subdir_a` and
`${CI_REGISTRY_IMAGE}/subdir_b`. No image will be created at
`${CI_REGISTRY_IMAGE}`. You can override that by adding a global variable called
`IMAGE_NAME: ${CI_REGISTRY_IMAGE}`.

## Different builder

You can change the builder by extending the base image template from a different