mirror of
https://gitlab.opencode.de/bmi/opendesk/deployment/opendesk.git
synced 2025-12-06 07:21:36 +01:00
538 lines
16 KiB
YAML
538 lines
16 KiB
YAML
# SPDX-FileCopyrightText: 2023 Bundesministerium des Innern und für Heimat, PG ZenDiS "Projektgruppe für Aufbau ZenDiS"
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
---
|
|
.environments:
|
|
before_script:
|
|
- "echo 'The proper environment configuration will be checked-out here'"
|
|
|
|
include:
|
|
- project: "${PROJECT_PATH_GITLAB_CONFIG_TOOLING}"
|
|
ref: "main"
|
|
file:
|
|
- "ci/common/lint.yml"
|
|
- "ci/release-automation/semantic-release.yml"
|
|
- project: "souvap/devops/sovereign-workplace-env"
|
|
file: "gitlab/environments.yaml"
|
|
rules:
|
|
- if: "$INCLUDE_ENVIRONMENTS_ENABLED != 'false'"
|
|
|
|
stages:
|
|
- ".pre"
|
|
- "lint"
|
|
- "env-cleanup"
|
|
- "env"
|
|
- "basic-services-deploy"
|
|
- "component-deploy-stage-1"
|
|
- "component-deploy-stage-2"
|
|
- "tests"
|
|
- "env-stop"
|
|
- "generate-release-artefacts"
|
|
- ".post"
|
|
|
|
variables:
|
|
NAMESPACE:
|
|
description: "The name of namespaces to deploy to."
|
|
value: ""
|
|
CLUSTER:
|
|
description: "Define which cluster to use. Cluster must be defined in gitlab/environments.yaml of
|
|
sovereign-workplace-env included above."
|
|
value: "dev"
|
|
BASE_DOMAIN:
|
|
description: "Define the Cluster Base Domain."
|
|
value: "souvap.cloud"
|
|
MASTER_PASSWORD_WEB_VAR:
|
|
description: "Optional: Provide a passphrase to be used for password generation."
|
|
value: ""
|
|
ENV_STOP_BEFORE:
|
|
description: "Stop environment/delete namespace for the deployment"
|
|
value: "no"
|
|
options:
|
|
- "yes"
|
|
- "no"
|
|
DEPLOY_ALL_COMPONENTS:
|
|
description: "Enable all component deployment (overwrites 'no' setting on component level)."
|
|
value: "no"
|
|
options:
|
|
- "yes"
|
|
- "no"
|
|
DEPLOY_SERVICES:
|
|
description: "Enable Service deployment."
|
|
value: "no"
|
|
options:
|
|
- "yes"
|
|
- "no"
|
|
DEPLOY_UCS:
|
|
description: "Enable Univention Corporate Server deployment."
|
|
value: "no"
|
|
options:
|
|
- "yes"
|
|
- "no"
|
|
DEPLOY_PROVISIONING:
|
|
description: "Enable Provisioning Components."
|
|
value: "no"
|
|
options:
|
|
- "yes"
|
|
- "no"
|
|
DEPLOY_COLLABORA:
|
|
description: "Enable Collabora deployment."
|
|
value: "no"
|
|
options:
|
|
- "yes"
|
|
- "no"
|
|
DEPLOY_ELEMENT:
|
|
description: "Enable Element deployment."
|
|
value: "no"
|
|
options:
|
|
- "yes"
|
|
- "no"
|
|
DEPLOY_KEYCLOAK:
|
|
description: "Enable Keycloak deployment."
|
|
value: "no"
|
|
options:
|
|
- "yes"
|
|
- "no"
|
|
DEPLOY_OX:
|
|
description: "Enable OX AppSuite8 deployment."
|
|
value: "no"
|
|
options:
|
|
- "yes"
|
|
- "no"
|
|
DEPLOY_ICS:
|
|
description: "Enable ICS deployment."
|
|
value: "no"
|
|
options:
|
|
- "yes"
|
|
- "no"
|
|
DEPLOY_XWIKI:
|
|
description: "Enable XWiki deployment."
|
|
value: "no"
|
|
options:
|
|
- "yes"
|
|
- "no"
|
|
DEPLOY_NEXTCLOUD:
|
|
description: "Enable Nextcloud deployment."
|
|
value: "no"
|
|
options:
|
|
- "yes"
|
|
- "no"
|
|
DEPLOY_OPENPROJECT:
|
|
description: "Enable OpenProject deployment."
|
|
value: "no"
|
|
options:
|
|
- "yes"
|
|
- "no"
|
|
DEPLOY_JITSI:
|
|
description: "Enable Jitsi deployment."
|
|
value: "no"
|
|
options:
|
|
- "yes"
|
|
- "no"
|
|
RUN_TESTS:
|
|
description: "Triggers execution of E2E-tests."
|
|
value: "yes"
|
|
options:
|
|
- "yes"
|
|
- "no"
|
|
TESTS_PROJECT_URL:
|
|
description: "URL of the E2E-test Gitlab project API with project ID."
|
|
# please use the following set of variables with normalized names:
|
|
DOMAIN: "${NAMESPACE}.${CLUSTER}.${BASE_DOMAIN}"
|
|
ISTIO_DOMAIN: "${NAMESPACE}.istio.${CLUSTER}.${BASE_DOMAIN}"
|
|
|
|
.deploy-common:
|
|
cache: {}
|
|
dependencies: []
|
|
extends: ".environments"
|
|
image: "registry.souvap-univention.de/souvap/tooling/images/helm:latest"
|
|
secrets:
|
|
SMTP_PASSWORD:
|
|
vault:
|
|
engine:
|
|
name: "kv-v2"
|
|
path: "swp"
|
|
path: "accounts/brained/mail/relay@souvap-univention.de"
|
|
field: "password"
|
|
file: false
|
|
TURN_CREDENTIALS:
|
|
vault:
|
|
engine:
|
|
name: "kv-v2"
|
|
path: "swp"
|
|
path: "accounts/souvap-univention.de/develop/turn/secret"
|
|
field: "credentials"
|
|
file: false
|
|
script:
|
|
- "cd ${CI_PROJECT_DIR}/helmfile/apps/${COMPONENT}"
|
|
# MASTER_PASSWORD_WEB_VAR as precedence for MASTER_PASSWORD
|
|
- |
|
|
if ! [ -z "${MASTER_PASSWORD_WEB_VAR}" ]; then
|
|
export MASTER_PASSWORD="${MASTER_PASSWORD_WEB_VAR}"
|
|
fi;
|
|
- >
|
|
echo "Installing ${COMPONENT} into ${NAMESPACE} namespace as ${HELMFILE_ENVIRONMENT} environment on ${CLUSTER}"
|
|
- "helmfile --namespace ${NAMESPACE} apply --suppress-diff"
|
|
tags:
|
|
- "docker"
|
|
- "kubernetes"
|
|
- "${CLUSTER}"
|
|
variables:
|
|
HELMFILE_ENVIRONMENT: "dev"
|
|
|
|
env-cleanup:
|
|
extends: ".deploy-common"
|
|
environment:
|
|
name: "${NAMESPACE}"
|
|
action: "stop"
|
|
needs: []
|
|
rules:
|
|
- if: >
|
|
$CI_PIPELINE_SOURCE =~ "web|schedules|triggers" &&
|
|
$NAMESPACE =~ /.+/ &&
|
|
$ENV_STOP_BEFORE != "no"
|
|
when: "always"
|
|
script:
|
|
- "helmfile destroy --namespace ${NAMESPACE}"
|
|
- "kubectl delete pvc --all --namespace ${NAMESPACE}"
|
|
stage: "env-cleanup"
|
|
|
|
env-start:
|
|
environment:
|
|
name: "${NAMESPACE}"
|
|
url: "https://portal.${DOMAIN}"
|
|
on_stop: "env-stop"
|
|
extends: ".deploy-common"
|
|
image: "${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/alpine/k8s:1.25.6"
|
|
rules:
|
|
- if: >
|
|
$CI_PIPELINE_SOURCE =~ "web|schedules|triggers" &&
|
|
$NAMESPACE =~ /.+/
|
|
when: "always"
|
|
script:
|
|
- "echo \"Deploying to Environment ${NAMESPACE} in ${CLUSTER} Cluster\""
|
|
- "kubectl create namespace ${NAMESPACE} --dry-run=client -o yaml | kubectl apply -f -"
|
|
- >
|
|
kubectl create secret
|
|
--namespace "${NAMESPACE}"
|
|
docker-registry external-registry
|
|
--docker-server "external-registry.souvap-univention.de"
|
|
--docker-username sovereign-workplace
|
|
--docker-password "${EXTERNAL_REGISTRY_PASSWORD}"
|
|
--dry-run=client -o yaml | kubectl apply -f -
|
|
stage: "env"
|
|
|
|
services-deploy:
|
|
stage: "basic-services-deploy"
|
|
extends: ".deploy-common"
|
|
rules:
|
|
- if: >
|
|
$CI_PIPELINE_SOURCE =~ "web|schedules|triggers" &&
|
|
$NAMESPACE =~ /.+/ &&
|
|
($DEPLOY_ALL_COMPONENTS != "no" || $DEPLOY_SERVICES != "no")
|
|
when: "always"
|
|
variables:
|
|
COMPONENT: "services"
|
|
|
|
ucs-deploy:
|
|
stage: "component-deploy-stage-1"
|
|
extends: ".deploy-common"
|
|
rules:
|
|
- if: >
|
|
$CI_PIPELINE_SOURCE =~ "web|schedules|triggers" &&
|
|
$NAMESPACE =~ /.+/ &&
|
|
($DEPLOY_ALL_COMPONENTS != "no" || $DEPLOY_UCS != "no")
|
|
when: "always"
|
|
variables:
|
|
COMPONENT: "univention-corporate-container"
|
|
|
|
provisioning-deploy:
|
|
stage: "component-deploy-stage-2"
|
|
extends: ".deploy-common"
|
|
rules:
|
|
- if: >
|
|
$CI_PIPELINE_SOURCE =~ "web|schedules|triggers" &&
|
|
$NAMESPACE =~ /.+/ &&
|
|
($DEPLOY_ALL_COMPONENTS != "no" || $DEPLOY_UCS != "no" || $DEPLOY_PROVISIONING != "no")
|
|
when: "always"
|
|
variables:
|
|
COMPONENT: "provisioning"
|
|
|
|
keycloak-deploy:
|
|
stage: "component-deploy-stage-1"
|
|
extends: ".deploy-common"
|
|
rules:
|
|
- if: >
|
|
$CI_PIPELINE_SOURCE =~ "web|schedules|triggers" &&
|
|
$NAMESPACE =~ /.+/ &&
|
|
($DEPLOY_ALL_COMPONENTS != "no" || $DEPLOY_KEYCLOAK != "no")
|
|
when: "always"
|
|
variables:
|
|
COMPONENT: "keycloak"
|
|
|
|
keycloak-bootstrap-deploy:
|
|
stage: "component-deploy-stage-1"
|
|
extends: ".deploy-common"
|
|
timeout: "30m"
|
|
rules:
|
|
- if: >
|
|
$CI_PIPELINE_SOURCE =~ "web|schedules|triggers" &&
|
|
$NAMESPACE =~ /.+/ &&
|
|
($DEPLOY_ALL_COMPONENTS != "no" || $DEPLOY_KEYCLOAK != "no")
|
|
when: "always"
|
|
variables:
|
|
COMPONENT: "keycloak-bootstrap"
|
|
|
|
ox-deploy:
|
|
stage: "component-deploy-stage-1"
|
|
extends: ".deploy-common"
|
|
timeout: "30m"
|
|
rules:
|
|
- if: >
|
|
$CI_PIPELINE_SOURCE =~ "web|schedules|triggers" &&
|
|
$NAMESPACE =~ /.+/ &&
|
|
($DEPLOY_ALL_COMPONENTS != "no" || $DEPLOY_OX != "no")
|
|
when: "always"
|
|
variables:
|
|
COMPONENT: "open-xchange"
|
|
|
|
ics-deploy:
|
|
stage: "component-deploy-stage-1"
|
|
extends: ".deploy-common"
|
|
rules:
|
|
- if: >
|
|
$CI_PIPELINE_SOURCE =~ "web|schedules|triggers" &&
|
|
$NAMESPACE =~ /.+/ &&
|
|
($DEPLOY_ALL_COMPONENTS != "no" || $DEPLOY_ICS != "no")
|
|
when: "always"
|
|
variables:
|
|
COMPONENT: "intercom-service"
|
|
|
|
xwiki-deploy:
|
|
stage: "component-deploy-stage-1"
|
|
extends: ".deploy-common"
|
|
rules:
|
|
- if: >
|
|
$CI_PIPELINE_SOURCE =~ "web|schedules|triggers" &&
|
|
$NAMESPACE =~ /.+/ &&
|
|
($DEPLOY_ALL_COMPONENTS != "no" || $DEPLOY_XWIKI != "no")
|
|
when: "always"
|
|
variables:
|
|
COMPONENT: "xwiki"
|
|
|
|
collabora-deploy:
|
|
stage: "component-deploy-stage-1"
|
|
extends: ".deploy-common"
|
|
rules:
|
|
- if: >
|
|
$CI_PIPELINE_SOURCE =~ "web|schedules|triggers" &&
|
|
$NAMESPACE =~ /.+/ &&
|
|
($DEPLOY_ALL_COMPONENTS != "no" || $DEPLOY_NEXTCLOUD != "no" || $DEPLOY_COLLABORA != "no")
|
|
when: "always"
|
|
variables:
|
|
COMPONENT: "collabora"
|
|
|
|
nextcloud-deploy:
|
|
stage: "component-deploy-stage-1"
|
|
extends: ".deploy-common"
|
|
rules:
|
|
- if: >
|
|
$CI_PIPELINE_SOURCE =~ "web|schedules|triggers" &&
|
|
$NAMESPACE =~ /.+/ &&
|
|
($DEPLOY_ALL_COMPONENTS != "no" || $DEPLOY_NEXTCLOUD != "no")
|
|
when: "always"
|
|
variables:
|
|
COMPONENT: "nextcloud"
|
|
|
|
openproject-deploy:
|
|
stage: "component-deploy-stage-1"
|
|
extends: ".deploy-common"
|
|
rules:
|
|
- if: >
|
|
$CI_PIPELINE_SOURCE =~ "web|schedules|triggers" &&
|
|
$NAMESPACE =~ /.+/ &&
|
|
($DEPLOY_ALL_COMPONENTS != "no" || $DEPLOY_OPENPROJECT != "no")
|
|
when: "always"
|
|
variables:
|
|
COMPONENT: "openproject"
|
|
|
|
jitsi-deploy:
|
|
stage: "component-deploy-stage-1"
|
|
extends: ".deploy-common"
|
|
rules:
|
|
- if: >
|
|
$CI_PIPELINE_SOURCE =~ "web|schedules|triggers" &&
|
|
$NAMESPACE =~ /.+/ &&
|
|
($DEPLOY_ALL_COMPONENTS != "no" || $DEPLOY_JITSI != "no")
|
|
when: "always"
|
|
variables:
|
|
COMPONENT: "jitsi"
|
|
|
|
element-deploy:
|
|
stage: "component-deploy-stage-1"
|
|
extends: ".deploy-common"
|
|
rules:
|
|
- if: >
|
|
$CI_PIPELINE_SOURCE =~ "web|schedules|triggers" &&
|
|
$NAMESPACE =~ /.+/ &&
|
|
($DEPLOY_ALL_COMPONENTS != "no" || $DEPLOY_ELEMENT != "no")
|
|
when: "always"
|
|
variables:
|
|
COMPONENT: "element"
|
|
|
|
env-stop:
|
|
extends: ".deploy-common"
|
|
environment:
|
|
name: "${NAMESPACE}"
|
|
action: "stop"
|
|
image: "${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/alpine/k8s:1.25.6"
|
|
needs: []
|
|
rules:
|
|
- if: >
|
|
$CI_PIPELINE_SOURCE =~ "web|schedules|triggers" && $NAMESPACE =~ /.+/
|
|
when: "manual"
|
|
script:
|
|
- "echo 'We do not stop the env (delete the namespace) at the moment in this stage, as deleting a branches also
|
|
triggers this env-stop stage and we do not want this to happen.'"
|
|
# - kubectl delete namespace "${NAMESPACE}"
|
|
stage: "env-stop"
|
|
variables:
|
|
GIT_STRATEGY: "none"
|
|
|
|
run-tests:
|
|
extends: ".deploy-common"
|
|
environment:
|
|
name: "${NAMESPACE}"
|
|
tags:
|
|
- "docker"
|
|
- "kubernetes"
|
|
- "${CLUSTER}"
|
|
stage: "tests"
|
|
rules:
|
|
- if: >
|
|
$CI_PIPELINE_SOURCE =~ "web|schedules|triggers" && $NAMESPACE =~ /.+/ && $RUN_TESTS == "yes"
|
|
when: "always"
|
|
script:
|
|
- |
|
|
COMPONENTS="login or portal or profile or navigation"
|
|
if [ "${DEPLOY_ALL_COMPONENTS}" != "no" ]; then
|
|
COMPONENTS="${COMPONENTS} or collabora or ics or jitsi or keycloak or nextcloud or openproject or ox or ucs \
|
|
or xwiki"
|
|
else
|
|
[ "${DEPLOY_COLLABORA}" != "no" ] && COMPONENTS="${COMPONENTS} or collabora"
|
|
[ "${DEPLOY_ICS}" != "no" ] && COMPONENTS="${COMPONENTS} or ics"
|
|
[ "${DEPLOY_JITSI}" != "no" ] && COMPONENTS="${COMPONENTS} or jitsi"
|
|
[ "${DEPLOY_KEYCLOAK}" != "no" ] && COMPONENTS="${COMPONENTS} or keycloak"
|
|
[ "${DEPLOY_NEXTCLOUD}" != "no" ] && COMPONENTS="${COMPONENTS} or nextcloud"
|
|
[ "${DEPLOY_OPENPROJECT}" != "no" ] && COMPONENTS="${COMPONENTS} or openproject"
|
|
[ "${DEPLOY_OX}" != "no" ] && COMPONENTS="${COMPONENTS} or ox"
|
|
[ "${DEPLOY_UCS}" != "no" ] && COMPONENTS="${COMPONENTS} or ucs"
|
|
[ "${DEPLOY_XWIKI}" != "no" ] && COMPONENTS="${COMPONENTS} or xwiki"
|
|
fi
|
|
|
|
echo "Gathering passwords from UCS container ..."
|
|
UCS_CONTAINER_NAME=$( \
|
|
kubectl -n ${NAMESPACE} get pods --no-headers \
|
|
--selector 'app.kubernetes.io/instance=univention-corporate-container' \
|
|
| awk '{print $1}' \
|
|
)
|
|
echo "UCS_CONTAINER_NAME: ${UCS_CONTAINER_NAME}"
|
|
DEFAULT_USER_PASSWORD=$( \
|
|
kubectl -n ${NAMESPACE} describe pod ${UCS_CONTAINER_NAME} \
|
|
| grep DEFAULT_ACCOUNT_USER_PASSWORD \
|
|
| awk '{print $2}' \
|
|
)
|
|
DEFAULT_ADMIN_PASSWORD=$( \
|
|
kubectl -n ${NAMESPACE} describe pod ${UCS_CONTAINER_NAME} \
|
|
| grep DEFAULT_ACCOUNT_ADMIN_PASSWORD \
|
|
| awk '{print $2}' \
|
|
)
|
|
|
|
echo "triggering test pipeline ..."
|
|
curl -X POST \
|
|
-F "ref=main" \
|
|
-F "token=${CI_JOB_TOKEN}" \
|
|
-F "variables[url]=https://portal.${DOMAIN}" \
|
|
-F "variables[user_name]=${DEFAULT_USER_NAME}" \
|
|
-F "variables[user_password]=${DEFAULT_USER_PASSWORD}" \
|
|
-F "variables[admin_name]=${DEFAULT_ADMIN_NAME}" \
|
|
-F "variables[admin_password]=${DEFAULT_ADMIN_PASSWORD}" \
|
|
-F "variables[components]=\"${COMPONENTS}\"" \
|
|
https://${TESTS_PROJECT_URL}/trigger/pipeline
|
|
|
|
generate-release-artefacts:
|
|
stage: "generate-release-artefacts"
|
|
image: "registry.souvap-univention.de/souvap/tooling/images/ansible:4.10.0"
|
|
rules:
|
|
- if: "$JOB_RELEASE_ENABLED != 'false' && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH"
|
|
when: "always"
|
|
- when: "never"
|
|
script:
|
|
- |
|
|
git clone https://gitlab-ci-token:${CI_JOB_TOKEN}@${CI_SERVER_HOST}/souvap/devops/generate-deployment-artefacts
|
|
cd generate-deployment-artefacts
|
|
export OPENDESK_DEPLOYMENT_AUTOMATION_PATH=${CI_PROJECT_DIR}
|
|
./artefact_generator.py
|
|
mv ./build_artefacts ${CI_PROJECT_DIR}
|
|
cd ..
|
|
rm -rf generate-deployment-artefacts
|
|
ls -l ./build_artefacts
|
|
artifacts:
|
|
paths:
|
|
- "./build_artefacts/chart-index.json"
|
|
- "./build_artefacts/image-index.json"
|
|
tags:
|
|
- "docker"
|
|
|
|
# Overwrite shared settings
|
|
.common-semantic-release:
|
|
image: "registry.souvap-univention.de/souvap/tooling/images/semantic-release-patched:latest"
|
|
rules:
|
|
- if: "$CI_PIPELINE_SOURCE =~ 'tags|triggers|web|merge_request_event'"
|
|
when: "never"
|
|
- when: "always"
|
|
|
|
common-yaml-linter:
|
|
rules:
|
|
- if: "$CI_PIPELINE_SOURCE =~ 'tags|triggers|web|merge_request_event'"
|
|
when: "never"
|
|
- when: "always"
|
|
|
|
reuse-linter:
|
|
allow_failure: false
|
|
rules:
|
|
- if: "$CI_PIPELINE_SOURCE =~ 'tags|triggers|web|merge_request_event'"
|
|
when: "never"
|
|
- when: "always"
|
|
|
|
release:
|
|
rules:
|
|
- if: "$JOB_RELEASE_ENABLED != 'false' && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH"
|
|
when: "always"
|
|
- when: "never"
|
|
script:
|
|
- |
|
|
cat << 'EOF' > ${CI_PROJECT_DIR}/.releaserc
|
|
{
|
|
"branches": ["main"],
|
|
"plugins": [
|
|
["@semantic-release/gitlab",
|
|
{
|
|
"assets": [
|
|
{ "path": "./build_artefacts/chart-index.json",
|
|
"label": "Chart Index JSON" },
|
|
{ "path": "./build_artefacts/image-index.json",
|
|
"label": "Image Index JSON" },
|
|
]
|
|
}
|
|
],
|
|
"@semantic-release/release-notes-generator",
|
|
"@semantic-release/changelog",
|
|
["@semantic-release/git", {
|
|
"assets": ["charts/**/Chart.yaml", "CHANGELOG.md", "charts/**/README.md"],
|
|
"message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
|
|
}]
|
|
]
|
|
}
|
|
EOF
|
|
- "semantic-release"
|
|
...
|