diff --git a/ci-templates/gitlab/README.md b/ci-templates/gitlab/README.md index 22f9c15a..fa5bd446 100644 --- a/ci-templates/gitlab/README.md +++ b/ci-templates/gitlab/README.md @@ -9,6 +9,7 @@ Currently, we provide the following Gitlab CI/CD templates: - [Export to T4C](#export-to-t4c): Export model in repository to T4C using the merge strategy - [Diagram cache](#diagram-cache): Export diagrams of a Capella model and store them in Gitlab artifacts +- [Image builder](#image-builder): Build and push all Docker images to any Docker registry. ## Export to T4C @@ -61,3 +62,74 @@ Make sure to enable the "Expand variable reference" flag. This is the minimal configuration. For more advanced configuration options, please refer to the [Gitlab CI template](./diagram-cache.yml). + +## Image builder + +The image builder template builds all images supported by this repository and pushes them to any Docker registry. +We use it in our automated deployment environment for our [Collaboration project](https://github.com/DSD-DBS/capella-collab-manager). +We have restricted internet access in our build environment, so the Gitlab CI is optimized for restricted network access. + +Please add the following section to your `.gitlab-ci.yml`: + +```yml +include: + - remote: https://raw.githubusercontent.com/DSD-DBS/capella-dockerimages/${CAPELLA_DOCKER_IMAGES_REVISION}/ci-templates/gitlab/image-builder.yml +``` + +The resulting images will be tagged in the following format: +`$CAPELLA_VERSION-$CAPELLA_DOCKER_IMAGES_REVISION-$GITLAB_IMAGE_BUILDER_REVISION`, e.g., `6.0.0-v1.7.0-v1.0.0`. + +where: + +- `$CAPELLA_VERSION` is the semantic Capella version, e.g., `6.0.0` or `5.2.0` +- `$CAPELLA_DOCKER_IMAGES_REVISION` is the revision of this Github repository. + + - Any branch or tag name is supported as revision + - All characters matching the regex `[^a-zA-Z0-9.]` will be replaces with `-` + +- `$GITLAB_IMAGE_BUILDER_REVISION` is the revision of the Gitlab repository, where the Gitlab CI template is included. + + - We use the [predefined Gitlab CI variable](https://docs.gitlab.com/ee/ci/variables/predefined_variables.html) `$CI_COMMIT_REF_NAME` to determine the name of the branch or tag. + - This part can be used for your own versioning, e.g., when you have to patch the Capella archives, but the semantic version is still the same. + +In addition, you have to add the following environment variables on repository level. +Make sure to enable the "Expand variable reference" flag. + +- `CAPELLA_DOCKER_IMAGES_REVISION`: Revision of this Github repository. +- `UID_ENV`: The user ID which will be used for the technical user. +- Variables related to the Docker registry (all parameters are passed to `docker login`): + - `DOCKER_REGISTRY`: The URL to the Docker registry + - `DOCKER_REGISTRY_USER`: Username of a techuser with push permission to the Docker registry + - `DOCKER_REGISTRY_PASSWORD`: Corresponding password of the techuser + +The tree inside of your Gitlab repository should look like: + +```zsh +├── 5.0.0 +│   ├── capella.tar.gz +│   ├── dropins +│   ├── ease +│   └── updateSite +├── 5.2.0 +│   ├── capella.tar.gz +│   ├── dropins +│   ├── ease +│   └── updateSite +├── 6.0.0 +│   ├── capella.tar.gz +│   ├── dropins +│   ├── ease +│   └── updateSite +├── libs +│   ├── libicu66_66.1-2ubuntu2_amd64.deb +│   ├── libjavascriptcoregtk-4.0-18_2.28.1-1_amd64.deb +│   ├── libjpeg-turbo8_2.0.3-0ubuntu1.20.04.1_amd64.deb +│   ├── libjpeg8_8c-2ubuntu8_amd64.deb +│   └── libwebkit2gtk-4.0-37_2.28.1-1_amd64.deb +└── pure-variants + ├── dependencies + └── updateSite +``` + +This is the minimal configuration. For more advanced configuration options, +please refer to the [Gitlab CI template](./image-builder.yml). diff --git a/ci-templates/gitlab/image-builder.yml b/ci-templates/gitlab/image-builder.yml new file mode 100644 index 00000000..995f20c9 --- /dev/null +++ b/ci-templates/gitlab/image-builder.yml @@ -0,0 +1,422 @@ +# SPDX-FileCopyrightText: Copyright DB Netz AG and the capella-collab-manager contributors +# SPDX-License-Identifier: Apache-2.0 + +variables: + BASE: + value: "1" + description: "Build the base image?" + CAPELLA_BASE: + value: "1" + description: "Build the capella/base image?" + CAPELLA_CLI: + value: "1" + description: "Build the capella/cli image?" + CAPELLA_REMOTE: + value: "0" + description: "Build the capella/remote image?" + T4C_CLIENT_BASE: + value: "1" + description: "Build the t4c/client/base image?" + T4C_CLIENT_BACKUP: + value: "1" + description: "Build the t4c/client/backup image?" + T4C_CLIENT_EXPORTER: + value: "1" + description: "Build the t4c/client/exporter image?" + T4C_CLIENT_REMOTE: + value: "1" + description: "Build the t4c/client/remote image?" + T4C_CLIENT_REMOTE_PURE_VARIANTS: + value: "1" + description: "Build the t4c/client/remote/pure-variants image?" + CAPELLA_EASE: + value: "1" + description: "Build the capella/ease image?" + CAPELLA_EASE_REMOTE: + value: "1" + description: "Build the capella/ease/remote image?" + CAPELLA_READONLY: + value: "1" + description: "Build the capella/readonly image?" + T4C_CLIENT_EASE: + value: "0" + description: "Build the t4c/client/ease image?" + T4C_CLIENT_EASE_REMOTE: + value: "0" + description: "Build the t4c/client/ease/remote image?" + T4C_CLIENT_EASE_REMOTE_DEBUG: + value: "0" + description: "Build the t4c/client/ease/remote/debug image?" + CAPELLA_DOCKER_IMAGES_REVISION: + value: "main" + description: "Revision of the Capella Docker images Github repository (https://github.com/DSD-DBS/capella-dockerimages)" + CAPELLA_VERSION: + value: "6.0.0" + description: "Capella version. Please make sure that a subdirectory with the name of the value exists. The value must be valid ASCII and may contain lowercase and uppercase letters, digits, underscores, periods and dashes." + DOCKER_BUILD_ARGS: "--no-cache" + BUILD_ARCHITECTURE: amd64 + +default: + image: $DOCKER_REGISTRY/base + tags: + - docker + before_script: + - &normalizeTag export DOCKER_TAG=$CAPELLA_VERSION-$(echo $CAPELLA_DOCKER_IMAGES_REVISION | sed 's/[^a-zA-Z0-9.]/-/g')-$CI_COMMIT_REF_NAME + - export BASE_IMAGE=$BASE_IMAGE:$DOCKER_TAG + +.github: &github + - git clone --recurse-submodules https://github.com/DSD-DBS/capella-dockerimages.git + - cd capella-dockerimages + - git checkout $CAPELLA_DOCKER_IMAGES_REVISION + +.docker: &docker + - docker info + - docker login -u $DOCKER_REGISTRY_USER -p $DOCKER_REGISTRY_PASSWORD $DOCKER_REGISTRY + - docker pull $BASE_IMAGE + +.push: &push + - docker push $IMAGE:$DOCKER_TAG + +.ease: &ease + - cp -R ../ease/extensions/* ease/extensions/ + +.prepare: &prepare + - cd $CAPELLA_VERSION + - *github + +base: + stage: build + needs: [] + rules: + - if: '$BASE == "1"' + when: always + before_script: + - *normalizeTag + variables: + BASE_IMAGE: debian:bullseye + IMAGE: $DOCKER_REGISTRY/base2 + script: + - *prepare + - *docker + - | + docker build $DOCKER_BUILD_ARGS \ + -t $DOCKER_REGISTRY/base2:$DOCKER_TAG \ + --build-arg UID=$UID_ENV \ + --build-arg BASE_IMAGE=$BASE_IMAGE \ + base + - *push + +capella/base: + stage: build + needs: + - job: base + optional: true + rules: + - if: '$CAPELLA_BASE == "1"' + when: always + variables: + BASE_IMAGE: $DOCKER_REGISTRY/base2 + IMAGE: $DOCKER_REGISTRY/capella/base + script: + - *prepare + - *docker + - mv ../capella.tar.gz ./capella/versions/$CAPELLA_VERSION/$BUILD_ARCHITECTURE/capella.tar.gz + - mv ../dropins/* ./capella/versions/$CAPELLA_VERSION/dropins/ + - mv ../../libs/* ./capella/libs/ + - | + docker build $DOCKER_BUILD_ARGS \ + -t $DOCKER_REGISTRY/capella/base:$DOCKER_TAG \ + --build-arg BUILD_TYPE=offline \ + --build-arg CAPELLA_VERSION=$CAPELLA_VERSION \ + --build-arg INJECT_PACKAGES=true \ + --build-arg BUILD_ARCHITECTURE="$BUILD_ARCHITECTURE" \ + --build-arg BASE_IMAGE=$BASE_IMAGE \ + capella + - *push + +capella/cli: + stage: build + needs: + - job: capella/base + optional: true + rules: + - if: '$CAPELLA_CLI == "1"' + when: always + variables: + BASE_IMAGE: $DOCKER_REGISTRY/capella/base + IMAGE: $DOCKER_REGISTRY/capella/cli + script: + - *prepare + - *docker + - | + docker build $DOCKER_BUILD_ARGS \ + -t $DOCKER_REGISTRY/capella/cli:$DOCKER_TAG \ + --build-arg BASE_IMAGE=$BASE_IMAGE \ + cli + - *push + +capella/remote: + stage: build + needs: + - job: capella/base + optional: true + rules: + - if: '$CAPELLA_REMOTE == "1"' + when: always + variables: + BASE_IMAGE: $DOCKER_REGISTRY/capella/base + IMAGE: $DOCKER_REGISTRY/capella/remote + script: + - *prepare + - *docker + - | + docker build $DOCKER_BUILD_ARGS \ + -t $DOCKER_REGISTRY/capella/remote:$DOCKER_TAG \ + --build-arg BASE_IMAGE=$BASE_IMAGE \ + remote + - *push + +t4c/client/base: + stage: build + needs: + - job: capella/base + optional: true + rules: + - if: '$T4C_CLIENT_BASE == "1"' + when: always + variables: + BASE_IMAGE: $DOCKER_REGISTRY/capella/base + IMAGE: $DOCKER_REGISTRY/t4c/client/base + script: + - *prepare + - *docker + - mv ../updateSite/* t4c/updateSite/$CAPELLA_VERSION/ + - | + docker build $DOCKER_BUILD_ARGS \ + -t $DOCKER_REGISTRY/t4c/client/base:$DOCKER_TAG \ + --build-arg CAPELLA_VERSION=$CAPELLA_VERSION \ + --build-arg BASE_IMAGE=$BASE_IMAGE \ + t4c + - *push + +t4c/client/backup: + stage: build + needs: + - job: t4c/client/base + optional: true + rules: + - if: '$T4C_CLIENT_BACKUP == "1"' + when: always + variables: + BASE_IMAGE: $DOCKER_REGISTRY/t4c/client/base + IMAGE: $DOCKER_REGISTRY/t4c/client/backup + script: + - *prepare + - *docker + - | + docker build $DOCKER_BUILD_ARGS \ + -t $DOCKER_REGISTRY/t4c/client/backup:$DOCKER_TAG \ + --build-arg BASE_IMAGE=$BASE_IMAGE \ + backups + - *push + +t4c/client/exporter: + stage: build + needs: + - job: t4c/client/base + optional: true + rules: + - if: $CAPELLA_VERSION =~ /^5\.\d+\.\d+$/ + when: never + - if: '$T4C_CLIENT_EXPORTER == "1"' + when: always + variables: + BASE_IMAGE: $DOCKER_REGISTRY/t4c/client/base + IMAGE: $DOCKER_REGISTRY/t4c/client/exporter + script: + - *prepare + - *docker + - | + docker build $DOCKER_BUILD_ARGS \ + -t $DOCKER_REGISTRY/t4c/client/exporter:$DOCKER_TAG \ + --build-arg BASE_IMAGE=$BASE_IMAGE \ + exporter + - *push + +t4c/client/remote: + stage: build + needs: + - job: t4c/client/base + optional: true + rules: + - if: '$T4C_CLIENT_REMOTE == "1"' + when: always + variables: + BASE_IMAGE: $DOCKER_REGISTRY/t4c/client/base + IMAGE: $DOCKER_REGISTRY/t4c/client/remote + script: + - *prepare + - *docker + - | + docker build $DOCKER_BUILD_ARGS \ + -t $DOCKER_REGISTRY/t4c/client/remote:$DOCKER_TAG \ + --build-arg BASE_IMAGE=$BASE_IMAGE \ + remote + - *push + +t4c/client/remote/pure-variants: + stage: build + needs: + - job: t4c/client/remote + optional: true + rules: + - if: '$T4C_CLIENT_REMOTE_PURE_VARIANTS == "1"' + when: always + variables: + BASE_IMAGE: $DOCKER_REGISTRY/t4c/client/remote + IMAGE: $DOCKER_REGISTRY/t4c/client/remote/pure-variants + script: + - *prepare + - *docker + - mv ../../pure-variants/dependencies/* pure-variants/dependencies/ + - mv ../../pure-variants/updateSite/* pure-variants/updateSite/ + - | + docker build $DOCKER_BUILD_ARGS \ + -t $DOCKER_REGISTRY/t4c/client/remote/pure-variants:$DOCKER_TAG \ + --build-arg BUILD_TYPE=offline \ + --build-arg BASE_IMAGE=$BASE_IMAGE \ + pure-variants + - *push + +capella/ease: + stage: build + needs: + - job: capella/base + optional: true + rules: + - if: '$CAPELLA_EASE == "1"' + when: always + variables: + BASE_IMAGE: $DOCKER_REGISTRY/capella/base + IMAGE: $DOCKER_REGISTRY/capella/ease + script: + - *prepare + - *docker + - *ease + - | + docker build $DOCKER_BUILD_ARGS \ + -t $DOCKER_REGISTRY/capella/ease:$DOCKER_TAG \ + --build-arg BUILD_TYPE=offline \ + --build-arg BASE_IMAGE=$BASE_IMAGE \ + ease + - *push + +capella/ease/remote: + stage: build + needs: + - job: capella/ease + optional: true + rules: + - if: '$CAPELLA_EASE_REMOTE == "1"' + when: always + variables: + BASE_IMAGE: $DOCKER_REGISTRY/capella/ease + IMAGE: $DOCKER_REGISTRY/capella/ease/remote + script: + - *prepare + - *docker + - | + docker build $DOCKER_BUILD_ARGS \ + -t $DOCKER_REGISTRY/capella/ease/remote:$DOCKER_TAG \ + --build-arg BASE_IMAGE=$BASE_IMAGE \ + remote + - *push + +capella/readonly: + stage: build + needs: + - job: capella/ease/remote + optional: true + rules: + - if: '$CAPELLA_READONLY == "1"' + when: always + variables: + BASE_IMAGE: $DOCKER_REGISTRY/capella/ease/remote + IMAGE: $DOCKER_REGISTRY/capella/readonly + script: + - *prepare + - *docker + - | + docker build $DOCKER_BUILD_ARGS \ + -t $DOCKER_REGISTRY/capella/readonly:$DOCKER_TAG \ + --build-arg BASE_IMAGE=$BASE_IMAGE \ + readonly + - *push + +t4c/client/ease: + stage: build + needs: + - job: t4c/client/base + optional: true + rules: + - if: '$T4C_CLIENT_EASE == "1"' + when: always + variables: + BASE_IMAGE: $DOCKER_REGISTRY/t4c/client/base + IMAGE: $DOCKER_REGISTRY/t4c/client/ease + script: + - *prepare + - *docker + - *ease + - | + docker build $DOCKER_BUILD_ARGS \ + -t $DOCKER_REGISTRY/t4c/client/ease:$DOCKER_TAG \ + --build-arg BUILD_TYPE=offline \ + --build-arg BASE_IMAGE=$BASE_IMAGE \ + ease + - *push + +t4c/client/ease/remote: + stage: build + needs: + - job: t4c/client/ease + optional: true + rules: + - if: '$T4C_CLIENT_EASE_REMOTE == "1"' + when: always + variables: + BASE_IMAGE: $DOCKER_REGISTRY/t4c/client/ease + IMAGE: $DOCKER_REGISTRY/t4c/client/ease/remote + script: + - *prepare + - *docker + - | + docker build $DOCKER_BUILD_ARGS \ + -t $IMAGE:$DOCKER_TAG \ + --build-arg BASE_IMAGE=$BASE_IMAGE \ + remote + - *push + +t4c/client/ease/remote/debug: + stage: build + needs: + - job: t4c/client/ease/remote + optional: true + rules: + - if: '$T4C_CLIENT_EASE_REMOTE_DEBUG == "1"' + when: always + variables: + BASE_IMAGE: $DOCKER_REGISTRY/t4c/client/ease/remote + IMAGE: $DOCKER_REGISTRY/t4c/client/ease/remote/debug + script: + - *prepare + - *docker + - mkdir -p ease/debug/libs + - mv ../ease/debug/code.deb ease/debug/libs/code.deb + - | + docker build $DOCKER_BUILD_ARGS \ + -t $IMAGE:$DOCKER_TAG \ + --build-arg NETWORK_ACCESS=restricted \ + --build-arg BASE_IMAGE=$BASE_IMAGE \ + ease/debug + - *push