Pipeline-Beispiel: Komplexes Projekt-Setup
Dieses Beispiel zeigt eine vollständige GitLab CI/CD Pipeline für ein Yii2-Projekt mit mehreren Kunden-Deployments, Docker-Image-Builds, automatisierten Tests, Security-Scanning und MR-Staging. Es dient als Referenz für die Einrichtung vergleichbarer Projekte.
Übersicht
┌─────────────────────────────────────────────────────────────┐
│ .pre vault-secrets (Credentials aus Vault laden) │
├─────────────────────────────────────────────────────────────┤
│ build build-php · build-docs │
├─────────────────────────────────────────────────────────────┤
│ test unit · functional · sast · code quality│
├─────────────────────────────────────────────────────────────┤
│ build-docker Docker Images (dev + release + staging) │
├─────────────────────────────────────────────────────────────┤
│ deploy dev · kunde-a · kunde-b · kunde-c │
│ docs-dev · docs-a · docs-b · docs-c │
└─────────────────────────────────────────────────────────────┘Trigger-Logik:
- Merge Requests → Build, Tests, SAST, MR-Staging (mit Label
deploy-review) - Branch-Pushes → Build, Tests, SAST, Docker-Images (dev)
- Tags → Build, Tests, Docker-Images (release), Produktions-Deployments
Vollständige Pipeline
stages:
- build
- test
- build-docker-image
- deploy
include:
- template: Security/SAST.gitlab-ci.yml
- component: git.styrion.net/iteas/gitlab-components/vault-secrets@~latest
inputs:
secrets: |
GITLAB_USER=secret/gitlab/common/gitlab_deploy_auth@username
GITLAB_PASS=secret/gitlab/common/gitlab_deploy_auth@password
GITHUB_TOKEN=secret/gitlab/common/github_deploy_auth@token
EDBS_DB_PASSWORD=secret/gitlab/common/edbs_on@db_edbs_password
APP_UPDATE_KEY=secret/gitlab/common/iscan@APP_UPDATE_KEY
MAIL_DSN=secret/gitlab/common/mail@global_dsn
- component: git.styrion.net/iteas/gitlab-components/mr-staging@~latest
inputs:
stage_build: "build-docker-image"
domain_suffix: "iscan.staging.iteas.cloud"
docker_builds: |
staging-iscan-webapp=./docker/deploy/Dockerfile
staging-iscan-docs=./docker/deploy/Dockerfile-Docs
build_extra_args: "--secret id=composer_auth,env=COMPOSER_AUTH"
compose_file: "./docker/staging/docker-compose.yml"
# ──────────────────────────────────────────────
# Component-Erweiterungen
# ──────────────────────────────────────────────
mr-staging:build:
before_script:
- 'export COMPOSER_AUTH="{\"http-basic\": { \"git.styrion.net\": {
\"username\": \"$GITLAB_USER\", \"password\": \"$GITLAB_PASS\" } },
\"github-token\":{\"github.com\": \"$GITHUB_TOKEN\"}}"'
mr-staging:deploy:
before_script:
- export EDBS_DB_HOST="kroepflfw01.iteas.at"
- export EDBS_DB_NAME="EDBS_Kroepfl"
# ──────────────────────────────────────────────
# Security / SAST
# ──────────────────────────────────────────────
sast:
tags:
- 'build-docker01'
variables:
SAST_EXCLUDED_PATHS: "tests, vendor, storage"
semgrep-sast:
tags:
- 'build-docker01'
rules:
- if: '$CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS'
when: never
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH
- if: $CI_COMMIT_TAG
sast-html-report:
stage: test
rules:
- if: '$CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS'
when: never
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH
- if: $CI_COMMIT_TAG
needs: ["semgrep-sast"]
image:
name: git.styrion.net:4567/iteas/docker-build-images/php-codecept-test:latest
entrypoint: [""]
tags:
- build-docker01
script:
- php /usr/local/bin/sast-converter
artifacts:
when: always
paths:
- sast-report.html
expose_as: 'Security Report'
# ──────────────────────────────────────────────
# Build-Stage
# ──────────────────────────────────────────────
build-php:
stage: build
rules:
- if: '$CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS'
when: never
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH
- if: $CI_COMMIT_TAG
tags:
- 'build-ubuntu-2204-64'
script:
- jq --arg version "${CI_COMMIT_TAG:-dev-$CI_COMMIT_BRANCH}"
--arg commit "$CI_COMMIT_SHA"
--arg deployed_at "$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
'.extra.version = $version | .extra.commit = $commit
| .extra.deployed_at = $deployed_at | .version = $version'
src/composer.json > src/composer.json.tmp
&& mv src/composer.json.tmp src/composer.json
artifacts:
paths:
- ./src/composer.json
build-docs:
stage: build
rules:
- if: '$CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS'
when: never
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH
- if: $CI_COMMIT_TAG
tags:
- 'build-docker01'
image: node:latest
script:
- cd docs
- |
if [ -n "$CI_COMMIT_TAG" ]; then
echo "VITE_APP_VERSION=$CI_COMMIT_TAG" > .env
echo "VITE_APP_ISRELEASE=true" >> .env
else
echo "VITE_APP_VERSION=dev-$CI_COMMIT_BRANCH" > .env
echo "VITE_APP_ISRELEASE=false" >> .env
fi
- echo "VITE_APP_BUILD_DATE=$(date -u +\"%Y-%m-%dT%H:%M:%SZ\")" >> .env
- echo "VITE_APP_COMMIT_HASH=$CI_COMMIT_SHORT_SHA" >> .env
- npm install
- npm run docs:build
artifacts:
paths:
- ./docs/.vitepress/dist
# ──────────────────────────────────────────────
# Docker-Image-Builds
# ──────────────────────────────────────────────
build-docker-image-dev:
stage: build-docker-image
rules:
- if: '$CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS'
when: never
- if: $CI_COMMIT_BRANCH
tags:
- 'build-ubuntu-2404-64'
script:
- echo "$CI_REGISTRY_PASSWORD" | docker login $CI_REGISTRY
-u $CI_REGISTRY_USER --password-stdin
- 'export COMPOSER_AUTH="{\"http-basic\": { \"git.styrion.net\": {
\"username\": \"$GITLAB_USER\", \"password\": \"$GITLAB_PASS\" } },
\"github-token\":{\"github.com\": \"$GITHUB_TOKEN\"}}"'
- 'docker build -f docker/deploy/Dockerfile
--secret id=composer_auth,env=COMPOSER_AUTH
-t $CI_REGISTRY/iteas/iscan/iscan-webapp:dev-${CI_PIPELINE_ID}
-t $CI_REGISTRY/iteas/iscan/iscan-webapp:latest .'
- docker push $CI_REGISTRY/iteas/iscan/iscan-webapp --all-tags
build-docker-image-release:
stage: build-docker-image
only:
- tags
tags:
- 'build-ubuntu-2404-64'
script:
- echo "$CI_REGISTRY_PASSWORD" | docker login $CI_REGISTRY
-u $CI_REGISTRY_USER --password-stdin
- 'export COMPOSER_AUTH="{\"http-basic\": { \"git.styrion.net\": {
\"username\": \"$GITLAB_USER\", \"password\": \"$GITLAB_PASS\" } },
\"github-token\":{\"github.com\": \"$GITHUB_TOKEN\"}}"'
- export APP_VERSION=$(jq -r '.version' src/composer.json)
- 'docker build -f docker/deploy/Dockerfile
--secret id=composer_auth,env=COMPOSER_AUTH
-t $CI_REGISTRY/iteas/iscan/iscan-webapp:${APP_VERSION} .'
- docker push $CI_REGISTRY/iteas/iscan/iscan-webapp --all-tags
# (analoge Jobs für Docs-Images: build-docker-docs-image-dev,
# build-docker-docs-image-release)
# ──────────────────────────────────────────────
# Tests
# ──────────────────────────────────────────────
test:unit:
stage: test
rules:
- if: '$CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS'
when: never
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH
- if: $CI_COMMIT_TAG
image:
name: git.styrion.net:4567/iteas/docker-build-images/php-codecept-test:latest
entrypoint: [""]
tags:
- 'build-docker01'
services:
- mariadb:lts-noble
variables:
MYSQL_ROOT_PASSWORD: test_password
MYSQL_DATABASE: iscan_test
TEST_DB_DSN: "mysql:host=mariadb;dbname=iscan_test"
TEST_DB_USERNAME: root
TEST_DB_PASSWORD: test_password
DB_HOSTNAME: mariadb
DB_NAME: iscan_test
DB_USER: root
DB_PASSWORD: test_password
before_script:
- cd src
- 'export COMPOSER_AUTH="..."'
- composer install --no-interaction --prefer-dist --optimize-autoloader
- php yii migrate --interactive=0 || true
script:
- cd tests
- php ../vendor/bin/codecept build
- php -d pcov.enabled=1 ../vendor/bin/codecept run unit
--xml --html --coverage --coverage-xml
--coverage-html --coverage-cobertura --no-colors
coverage: '/^\s*Lines:\s*(\d+[\.,]\d+)\%/'
artifacts:
when: always
expire_in: 30 days
paths:
- src/tests/codeception/_output/
reports:
junit: src/tests/codeception/_output/report.xml
coverage_report:
coverage_format: cobertura
path: src/tests/codeception/_output/cobertura.xml
# (test:functional analog, ohne Coverage)
# ──────────────────────────────────────────────
# Deployments
# ──────────────────────────────────────────────
deploy-dev:
stage: deploy
tags:
- 'build-ubuntu-2204-64'
only:
- develop
script:
- rsync -az --delete
--exclude '/config/secrets.php'
--exclude '/web/img/data/*'
--exclude '/data/*'
src/* user@dev-server:/var/www/app/htdocs
- ssh user@dev-server "cd /var/www/app/htdocs
&& php composer.phar install --no-interaction --optimize-autoloader --no-dev
&& php yii migrate --interactive=0
&& php yii cache/flush-all"
deploy-prod-kunde:
stage: deploy
tags:
- 'build-ubuntu-2204-64'
only:
- tags
script:
- rsync -az --delete
--exclude '/config/secrets.php'
--exclude '/data/*'
src/* user@prod-server:/var/www/app/htdocs
- ssh user@prod-server "cd /var/www/app/htdocs
&& php composer.phar install
&& php yii migrate --interactive=0
&& php yii cache/flush-all
&& php yii migrate-edbs --interactive=0"
# (weitere Kunden-Deployments + Docs-Deployments analog)Erklärung im Detail
1. Stages
stages:
- build
- test
- build-docker-image
- deployDie Pipeline definiert vier Stages. Zusätzlich läuft die Vault Secrets-Komponente automatisch in der impliziten .pre-Stage – also vor allen anderen Jobs. Das stellt sicher, dass Credentials in allen nachfolgenden Stages verfügbar sind.
| Stage | Zweck |
|---|---|
.pre (implizit) | Vault Secrets laden |
build | PHP-Metadaten setzen, VitePress-Docs bauen |
test | Unit-/Functional-Tests, SAST, Code Quality |
build-docker-image | Docker-Images für Dev, Release und Staging |
deploy | Rsync-Deployment auf Dev- und Produktions-Server |
2. Includes – Komponenten und Templates
include:
- template: Security/SAST.gitlab-ci.yml
- component: git.styrion.net/iteas/gitlab-components/vault-secrets@~latest
inputs: ...
- component: git.styrion.net/iteas/gitlab-components/mr-staging@~latest
inputs: ...Drei Includes werden eingebunden:
GitLab SAST Template
- template: Security/SAST.gitlab-ci.ymlDas offizielle GitLab SAST Template fügt automatisch Security-Scanner-Jobs hinzu. Hier wird semgrep-sast als Analyzer verwendet. Die Jobs werden anschließend mit eigenen tags und rules überschrieben, um sie auf den build-docker01 Runner zu lenken.
Vault Secrets
- component: git.styrion.net/iteas/gitlab-components/vault-secrets@~latest
inputs:
secrets: |
GITLAB_USER=secret/gitlab/common/gitlab_deploy_auth@username
GITLAB_PASS=secret/gitlab/common/gitlab_deploy_auth@password
GITHUB_TOKEN=secret/gitlab/common/github_deploy_auth@token
EDBS_DB_PASSWORD=secret/gitlab/common/edbs_on@db_edbs_password
APP_UPDATE_KEY=secret/gitlab/common/iscan@APP_UPDATE_KEY
MAIL_DSN=secret/gitlab/common/mail@global_dsnDie Vault Secrets-Komponente lädt sechs Secrets aus Vault und stellt sie als Umgebungsvariablen bereit:
| Variable | Verwendung |
|---|---|
GITLAB_USER / GITLAB_PASS | Composer-Authentifizierung gegen git.styrion.net |
GITHUB_TOKEN | Composer-Authentifizierung gegen github.com |
EDBS_DB_PASSWORD | Datenbankpasswort für EDBS-Verbindung |
APP_UPDATE_KEY | Anwendungs-Update-Schlüssel |
MAIL_DSN | E-Mail-Versand-Konfiguration |
Versionierung mit @~latest
@~latest verwendet immer die neueste Version der Komponente. Für produktionskritische Pipelines kann alternativ ein fixer Tag wie @1.0.0 verwendet werden.
MR Staging
- component: git.styrion.net/iteas/gitlab-components/mr-staging@~latest
inputs:
stage_build: "build-docker-image"
domain_suffix: "iscan.staging.iteas.cloud"
docker_builds: |
staging-iscan-webapp=./docker/deploy/Dockerfile
staging-iscan-docs=./docker/deploy/Dockerfile-Docs
build_extra_args: "--secret id=composer_auth,env=COMPOSER_AUTH"
compose_file: "./docker/staging/docker-compose.yml"Die MR Staging-Komponente wird konfiguriert mit:
stage_build: "build-docker-image"– Der Build-Job wird in die eigenebuild-docker-image-Stage einsortiert statt in die Standard-build-Stage- Zwei Docker-Images – Webapp und Docs werden separat gebaut
- Docker Build Secrets – Composer-Credentials werden per
--secretübergeben (nicht als Build-Arg, da das im Layer-Cache landen würde) - Eigene Compose-Datei –
docker/staging/docker-compose.ymlstatt der Standard-docker-compose.yml
Wichtig
Das Label deploy-review muss im Merge Request gesetzt sein, damit ein Staging-Build ausgelöst wird. Ohne dieses Label wird kein Staging-Deployment durchgeführt.
3. Component-Erweiterungen per before_script
mr-staging:build:
before_script:
- 'export COMPOSER_AUTH="{\"http-basic\": { \"git.styrion.net\": {
\"username\": \"$GITLAB_USER\", \"password\": \"$GITLAB_PASS\" } },
\"github-token\":{\"github.com\": \"$GITHUB_TOKEN\"}}"'
mr-staging:deploy:
before_script:
- export EDBS_DB_HOST="kroepflfw01.iteas.at"
- export EDBS_DB_NAME="EDBS_Kroepfl"Die Component-Jobs werden per before_script erweitert, ohne die Hauptlogik zu überschreiben:
mr-staging:build– Setzt dieCOMPOSER_AUTH-Variable, die dann per--secretan den Docker-Build übergeben wird. Die Werte$GITLAB_USER,$GITLAB_PASSund$GITHUB_TOKENstammen aus der vault-secrets-Komponente.mr-staging:deploy– Exportiert zusätzliche Umgebungsvariablen für die Datenbank-Verbindung. Diese stehen dann in derdocker-compose.ymlals${EDBS_DB_HOST}und${EDBS_DB_NAME}zur Verfügung.
4. Pipeline-Regeln (Duale Pipeline-Vermeidung)
Ein wiederkehrendes Muster in fast allen Jobs:
rules:
# Branch-Pipeline unterdrücken wenn ein MR offen ist
- if: '$CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS'
when: never
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH
- if: $CI_COMMIT_TAGWarum? Ohne die erste Regel würde bei einem offenen Merge Request sowohl eine Branch-Pipeline als auch eine MR-Pipeline laufen – die Jobs würden doppelt ausgeführt. Die Regel $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS → never stellt sicher, dass bei offenen MRs nur die MR-Pipeline läuft.
| Situation | Pipeline-Typ |
|---|---|
| Push auf Branch (kein MR offen) | Branch-Pipeline |
| Push auf Branch (MR offen) | MR-Pipeline |
| Tag erstellt | Tag-Pipeline |
5. Security / SAST
sast:
tags:
- 'build-docker01'
variables:
SAST_EXCLUDED_PATHS: "tests, vendor, storage"Der sast-Job kommt vom GitLab SAST Template und wird hier angepasst:
- Läuft auf dem Docker-Runner (
build-docker01) tests/,vendor/undstorage/werden vom Scan ausgeschlossen
Der sast-html-report-Job konvertiert die SAST-Ergebnisse in einen lesbaren HTML-Report, der als Artifact direkt im MR angezeigt wird (expose_as: 'Security Report').
6. Build-Stage
build-php – Versionsinformationen einbetten
build-php:
script:
- jq --arg version "${CI_COMMIT_TAG:-dev-$CI_COMMIT_BRANCH}"
--arg commit "$CI_COMMIT_SHA"
--arg deployed_at "$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
'.extra.version = $version | .extra.commit = $commit
| .extra.deployed_at = $deployed_at | .version = $version'
src/composer.json > src/composer.json.tmp
&& mv src/composer.json.tmp src/composer.jsonDieser Job schreibt Build-Metadaten in die composer.json:
- Version: Tag-Name (z.B.
v2.1.0) oderdev-branch-name - Commit-Hash: Für Nachvollziehbarkeit
- Deployment-Zeitstempel: Wann der Build erstellt wurde
Das modifizierte composer.json wird als Artifact an nachfolgende Jobs weitergegeben.
build-docs – VitePress-Dokumentation
build-docs:
image: node:latest
script:
- cd docs
- |
if [ -n "$CI_COMMIT_TAG" ]; then
echo "VITE_APP_VERSION=$CI_COMMIT_TAG" > .env
echo "VITE_APP_ISRELEASE=true" >> .env
else
echo "VITE_APP_VERSION=dev-$CI_COMMIT_BRANCH" > .env
echo "VITE_APP_ISRELEASE=false" >> .env
fi
- npm install
- npm run docs:buildDie VitePress-Dokumentation wird mit Versionsinformationen gebaut. Bei Tags wird die Version als Release markiert, bei Branches als Dev-Version. Das Build-Ergebnis wird als Artifact für die Deploy-Jobs bereitgestellt.
7. Docker-Image-Builds
Es gibt zwei Varianten pro Image – dev und release:
| Job | Trigger | Tag-Format | Beispiel |
|---|---|---|---|
build-docker-image-dev | Branch-Push | dev-<pipeline-id> + latest | iscan-webapp:dev-12345, iscan-webapp:latest |
build-docker-image-release | Git-Tag | <app-version> | iscan-webapp:2.1.0 |
Docker Build Secrets:
- 'docker build -f docker/deploy/Dockerfile
--secret id=composer_auth,env=COMPOSER_AUTH
-t $CI_REGISTRY/iteas/iscan/iscan-webapp:dev-${CI_PIPELINE_ID} .'Composer-Credentials werden per --secret übergeben statt per --build-arg. Das verhindert, dass Credentials in Docker-Image-Layern gespeichert werden.
8. Tests
Unit-Tests mit Coverage
test:unit:
services:
- mariadb:lts-noble
variables:
MYSQL_ROOT_PASSWORD: test_password
MYSQL_DATABASE: iscan_test
script:
- php -d pcov.enabled=1 ../vendor/bin/codecept run unit
--xml --html --coverage --coverage-xml
--coverage-html --coverage-cobertura --no-colors
coverage: '/^\s*Lines:\s*(\d+[\.,]\d+)\%/'- MariaDB Service-Container: Automatisch gestartet, erreichbar unter
mariadb - PCOV: PHP Code Coverage (schneller als Xdebug)
- Coverage-Regex: GitLab extrahiert den Coverage-Prozentsatz aus der Ausgabe
- Artifacts: JUnit-XML für MR-Integration, Cobertura für Coverage-Visualisierung
Functional-Tests
Gleiche Konfiguration wie Unit-Tests, aber ohne Coverage-Messung. Beide Test-Jobs laufen parallel in der test-Stage.
9. Deployments
Deployment-Muster: Dev
deploy-dev:
only:
- develop
script:
- rsync -az --delete --exclude '/config/secrets.php' ...
src/* user@dev-server:/var/www/app/htdocs
- ssh user@dev-server "cd /var/www/app/htdocs
&& php composer.phar install --no-interaction --optimize-autoloader --no-dev
&& php yii migrate --interactive=0
&& php yii cache/flush-all"Dev-Deployment läuft bei Push auf develop:
- Rsync synchronisiert den Code (mit Ausnahmen für Secrets und Daten)
- SSH führt Post-Deployment-Befehle aus: Composer, Migrations, Cache
Deployment-Muster: Produktion (pro Kunde)
deploy-prod-kunde:
only:
- tags
script:
- rsync -az --delete ... src/* user@prod-server:/var/www/app/htdocs
- ssh user@prod-server "... && php yii migrate-edbs --interactive=0"Produktions-Deployments laufen nur bei Tags. Einige Kunden haben zusätzliche Migrations-Schritte (z.B. migrate-edbs für EDBS-Datenbanken).
Ausschlüsse beim Rsync:
| Pfad | Grund |
|---|---|
/config/secrets.php | Server-spezifische Konfiguration |
/data/* | Benutzerdaten |
/web/apk | App-Binaries |
/web/user | Benutzer-Uploads |
Deaktivierte Deployments
.deploy-prod-stelzer: # Punkt-Prefix = deaktiviertJobs mit Punkt-Prefix (.) sind in GitLab deaktiviert und werden nicht ausgeführt. Das dient als Pattern um Kunden-Deployments temporär zu pausieren, ohne die Konfiguration zu löschen.
Zusammenspiel der Komponenten
vault-secrets (.pre)
│
├── GITLAB_USER, GITLAB_PASS, GITHUB_TOKEN
│ │
│ ├──► build-php (composer.json Metadaten)
│ ├──► test:unit, test:functional (Composer install)
│ ├──► build-docker-image-* (Docker --secret)
│ └──► mr-staging:build (Docker --secret via before_script)
│
├── EDBS_DB_PASSWORD
│ └──► mr-staging:deploy (via before_script)
│
└── APP_UPDATE_KEY, MAIL_DSN
└──► mr-staging:deploy (via docker-compose.yml)Die Vault Secrets-Komponente lädt alle Credentials einmalig in .pre. Diese werden dann von verschiedenen Jobs genutzt – teils direkt als Umgebungsvariable, teils über den COMPOSER_AUTH-JSON-String für die Composer-Authentifizierung.
Die MR Staging-Komponente nutzt die Vault-Secrets über before_script-Erweiterungen, um sowohl Build-Credentials als auch Deploy-Konfiguration zu setzen.
Häufige Anpassungen
Neuen Kunden hinzufügen
Einen bestehenden Deploy-Job kopieren und Host/Pfad anpassen:
deploy-prod-neukunde:
stage: deploy
tags:
- 'build-ubuntu-2204-64'
only:
- tags
script:
- rsync -az --delete
--exclude '/config/secrets.php'
--exclude '/data/*'
src/* f01_iscan@neukunde.iscan.iteas.at:/var/www/neukunde.iscan.iteas.at/htdocs
- ssh f01_iscan@neukunde.iscan.iteas.at "cd /var/www/neukunde.iscan.iteas.at/htdocs
&& php composer.phar install
&& php yii migrate --interactive=0
&& php yii cache/flush-all"Neues Vault-Secret hinzufügen
In der vault-secrets-Konfiguration eine neue Zeile ergänzen:
secrets: |
...bestehende Secrets...
NEUES_SECRET=secret/gitlab/common/pfad@feldnameStaging für MR aktivieren
- Merge Request erstellen
- Label
deploy-reviewsetzen - Pipeline startet automatisch → Review-App unter
https://<branch-slug>.iscan.staging.iteas.cloud
