From 80aad3286f692cd31616d2bee93679be7be7a3fb Mon Sep 17 00:00:00 2001
From: Daniel Speicher <daniel.speicher@lakedrops.com>
Date: Wed, 31 Jul 2024 16:15:08 +0200
Subject: [PATCH] Document stages and jobs.

---
 .../screenshots/pipeline_check4updates.png    |   3 +
 docs/files/screenshots/pipeline_deploy.png    |   3 +
 .../screenshots/pipeline_executebuild.png     |   3 +
 .../screenshots/pipeline_lakedrops_build.png  |   3 +
 .../screenshots/pipeline_lakedrops_deploy.png |   3 +
 .../screenshots/pipeline_publish_release.png  |   3 +
 docs/gitlab/drupal/index.md                   | 784 +-----------------
 docs/gitlab/pipelines/index.md                | 775 +++++++++++++++++
 mkdocs.yml                                    |   1 +
 9 files changed, 803 insertions(+), 775 deletions(-)
 create mode 100644 docs/files/screenshots/pipeline_check4updates.png
 create mode 100644 docs/files/screenshots/pipeline_deploy.png
 create mode 100644 docs/files/screenshots/pipeline_executebuild.png
 create mode 100644 docs/files/screenshots/pipeline_lakedrops_build.png
 create mode 100644 docs/files/screenshots/pipeline_lakedrops_deploy.png
 create mode 100644 docs/files/screenshots/pipeline_publish_release.png
 create mode 100644 docs/gitlab/pipelines/index.md

diff --git a/docs/files/screenshots/pipeline_check4updates.png b/docs/files/screenshots/pipeline_check4updates.png
new file mode 100644
index 0000000..65942b3
--- /dev/null
+++ b/docs/files/screenshots/pipeline_check4updates.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:b8e37419bac006b304fe61e0cf554d686885407e3f53cfd958971604dc332bfd
+size 68316
diff --git a/docs/files/screenshots/pipeline_deploy.png b/docs/files/screenshots/pipeline_deploy.png
new file mode 100644
index 0000000..31e5347
--- /dev/null
+++ b/docs/files/screenshots/pipeline_deploy.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:34dd0dd3667d348bca2d3fb468a4013f1555aa935d0bf5730cb1bc62a1974796
+size 31753
diff --git a/docs/files/screenshots/pipeline_executebuild.png b/docs/files/screenshots/pipeline_executebuild.png
new file mode 100644
index 0000000..d3f782e
--- /dev/null
+++ b/docs/files/screenshots/pipeline_executebuild.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:6c172f171905fd1663ac2a0fc215271f398c23fb86be99a0887060a0b96a38b7
+size 47997
diff --git a/docs/files/screenshots/pipeline_lakedrops_build.png b/docs/files/screenshots/pipeline_lakedrops_build.png
new file mode 100644
index 0000000..a883676
--- /dev/null
+++ b/docs/files/screenshots/pipeline_lakedrops_build.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:ebea0c72b325180cabfd90896565a434e0bc0fb6351933694b18fb4684f4be1b
+size 63193
diff --git a/docs/files/screenshots/pipeline_lakedrops_deploy.png b/docs/files/screenshots/pipeline_lakedrops_deploy.png
new file mode 100644
index 0000000..9f0bcff
--- /dev/null
+++ b/docs/files/screenshots/pipeline_lakedrops_deploy.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:13d1d81ff8c03cb8d9adc2c17a46aea831b3e7142fa4ca2b0f9b910afe5e024b
+size 37884
diff --git a/docs/files/screenshots/pipeline_publish_release.png b/docs/files/screenshots/pipeline_publish_release.png
new file mode 100644
index 0000000..45606e5
--- /dev/null
+++ b/docs/files/screenshots/pipeline_publish_release.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:d08c881aa5513a2be423cc3045e950e04dbfb0321fc965fae88fe169735b0704
+size 42078
diff --git a/docs/gitlab/drupal/index.md b/docs/gitlab/drupal/index.md
index c1d1b96..77e25e3 100644
--- a/docs/gitlab/drupal/index.md
+++ b/docs/gitlab/drupal/index.md
@@ -7,776 +7,10 @@ tags:
 - ci/cd
 - drupal
 ---
-# GitLab CI for Drupal pipelines
 
-This project contains a number of pre-configured tasks for GitLab CI/CD that
-allow to run very powerful pipelines which contain the following stage order:
+# Configuration
 
-- [.pre (predefined)](#pre)
-- [execute](#execute)
-- [buildprod](#build-prod)
-- [build (predefined)](#build)
-- [prepare](#prepare)
-- [postprocess](#postprocess)
-- [validate](#validate)
-- [test (predefined)](#test)
-- [deploy (predefined)](#deploy)
-- [finalize](#finalize)
-- [release](#release-stage)
-
-We have a predefined `execute` job called `LakeDrops`, which looks like this:
-
-- [execute](#execute)
-    - LakeDrops
-        - [buildprod](#build-prod)
-            - [Build Prod Site](#build-prod-site)
-            - [Build Prod Site NG](#build-prod-site-ng)
-        - [build (predefined)](#build)
-            - [Build Site](#build-site)
-            - [Build Theme](#build-theme)
-            - [Check 4 Outdated Packages](#check-4-outdated-packages)
-            - [Check 4 Security Vulnerability Advisories](#check-4-security-vulnerability-advisories)
-            - [Download DB](#download-db)
-            - [Download DB NG](#download-db-ng)
-        - [prepare](#prepare)
-            - [Import DB](#import-db)
-            - [Import DB NG](#import-db-ng)
-            - [Import Local DB](#import-local-db)
-            - [Update DB](#update-db) 
-        - [test](#test)
-            - [Test Code Style](#test-code-style)
-            - [Test PHPUnit](#test-phpunit)
-            - [Test Backstop](#test-backstop)
-            - [Test Cypress E2E](#test-cypress-e2e)
-        - [finalize](#finalize)
-            - [Shut Down Docker Project](#shut-down-docker-project)
-
-These pre-configured tasks can easily be included into your Drupal project.
-A GitLab runner on any host can then be configured to run those pipelines. The 
-following chapters describe the necessary steps and also all the options
-available for configuration.
-
-## Stages
-The following chapters describes all stages and their jobs. The files:
-
--  [lakedrops.yml](https://gitlab.lakedrops.com/gitlab-ci-cd/drupal/-/blob/main/lakedrops.yml?ref_type=heads).
--  [tests/lakedrops.yml](https://gitlab.lakedrops.com/gitlab-ci-cd/drupal/-/blob/main/tests/lakedrops.yml?ref_type=heads).
--  [test_deploy.yml](https://gitlab.lakedrops.com/gitlab-ci-cd/drupal/-/blob/main/test-and-deploy.yml?ref_type=heads).
--  [check4updates.yml](https://gitlab.lakedrops.com/gitlab-ci-cd/drupal/-/blob/main/check4updates.yml?ref_type=heads).
-
-### .pre
-
-To prepare and check, if the environment is good to go, we have a `.pre` stage, which contains the
-following jobs:
-
-#### Sanity Checks
-
-The sanity check gets important when you are using [Crowdsec](https://www.crowdsec.net/).
-It contains two little scripts, that check:
-
--    if the `crowdsec.settings.yml` is in the config split and
--    if it is not enabled in the `core.extensions.yml`.
-
-Otherwise, it is conflicting with you local settings, since `CrowdSec`
-is a tool for production sites.
-
-Except:
-
-- Commit message contains "Merge tag"
-- Commit message contains "Merge branch"
-- When the job is triggered by config auto export (CAE)
-
-#### Validate Environment
-
-This job extends the `.prerequisites` in 
-[test_deploy.yml](https://gitlab.lakedrops.com/gitlab-ci-cd/drupal/-/blob/main/test-and-deploy.yml?ref_type=heads).
-
-This job executes a script, where several [variables](#variables) are checked and set accordingly.
-
-Except:
-
-- Commit message contains "Merge tag"
-- Commit message contains "Merge branch"
-- When the job is triggered by config auto export (CAE)
-
-### Validate
-
-This stage is currently not officially used.
-
-### Execute
-
-This stage executes the build itself.
-
-### Build Prod
-
-This stage is responsible for building the production website, which we want to finally deploy.
-
-#### Build Prod Site
-
-First we have to do some preparation. This is done in the `before_script` section.
-
-- [.prepareaccess](#prepareaccess)
-- [.preparecomposerplugins](#preparecomposerplugins)
-
-We start a docker image for php with the specifies versions:
-
-- `PHP_MAJOR_VERSION`
-- `PHP_MINOR_VERSION`
-
-In the script section we first update the environment by executing `/usr/local/bin/update-env`.
-
-After that we install the production site with `composer install` **without** the tools for development. That is pretty 
-it. We also add `drupal/core-vendor-hardening`.
-
-The entire installation is saved as a build artefact called `build-prod` where all `git` files are excluded.
-
-#### Build Prod Site NG
-
-First we have to do some preparation. This is done in the `before_script` section.
-
-- [.prepareaccess](#prepareaccess)
-- [.preparecomposerplugins](#preparecomposerplugins)
-
-We start a docker image for php with the specifies versions:
-
-- `PHP_MAJOR_VERSION`
-- `PHP_MINOR_VERSION`
-
-In the script part we install two of our LakeDrops modules:
-
-- [lakedrops/drupal-environment](../../composer/plugin/drupal-environment)
-- [lakedrops/docker4drupal](../../composer/plugin/d4d)
-
-After that we execute:
-
-- `composer lakedrops:config`
-- `composer lakedrops:docker4drupal`
-
-The entire installation is saved as a build artefact called `build-prod-ng` where all `git` files are excluded.
-
-Rules, when the job should run:
-
-- `$DISABLE_DEPLOYMENT_LOCAL` != "1"
-
-### Build
-
-Here, we define jobs, which build the Drupal website and does some additional checks. This stage is
-responsible for the database downloads as well.
-
-#### Build Site
-
-We start a docker image for `php` with the specifies versions:
-
-- `PHP_MAJOR_VERSION`
-- `PHP_MINOR_VERSION`
-
-After that, we start to build the Drupal site with [Composer](https://getcomposer.org/):
-
-Now we execute a `composer install` twice to ensure that all patches get applied correctly. After
-that we setup our own `LakeDrops` tools by `composer lakedrops:scaffold` and
-`composer lakedrops:docker4drupal`.
-
-The next step is to pull all required [Docker](https://www.docker.com/) images 
-with [Docker Compose](https://docs.docker.com/compose/) and start the services.
-
-After everything has started, we create some directories, e.g. for styles, logs and JavaScript.
-
-The entire installation is saved as a build artefact called `build` where all `git` files are excluded.
-
-Rules, when the job should run:
-
-- the tests are enabled by `$TESTSDISABLED` == "no"
-
-#### Build Theme
-
-This job creates the required files for the styling of the website. 
-
-The following jobs must run before successfully:
-
-- [Build Prod Site](#build-prod-site)
-
-#### Check 4 Updates
-
-e start a docker image for `php` with the specifies versions:
-
-- `PHP_MAJOR_VERSION`
-- `PHP_MINOR_VERSION`
-
-First we have to do some preparation. This is done in the `before_script` section.
-
-- [.prepareaccess](#prepareaccess)
-- [.preparecomposerplugins](#preparecomposerplugins)
-
-The job stores the artefacts in `check4updates`.
-
-
-
-Rules, when the job should run:
-
-- `$CHECKUPDATES` is set
-- we are on the `develop` branch
-
-
-#### Check 4 Outdated Packages
-
-We start a docker image for `php` with the specifies versions:
-
-- `PHP_MAJOR_VERSION`
-- `PHP_MINOR_VERSION`
-
-The following jobs must run before successfully. Some are optional, which means, if they exist, this job waits for them
-to complete:
-
-- [Check 4 Updates](#check-4-updates)
-    - uses its artefacts
-    - optional
-- [Build Prod Site](#build-prod-site)
-    - uses its artefacts
-    - optional
-- [Build Prod Site NG](#build-prod-site-ng)
-    - uses its artefacts
-    - optional
-- [Build Site](#build-site)
-    - uses its artefacts
-    - optional
-
-First we have to do some preparation. This is done in the `before_script` section.
-
-- [.prepareaccess](#prepareaccess)
-- [.preparecomposerplugins](#preparecomposerplugins)
-
-First we perform a `composer update` which all dependencies without the development part.
-
-Then we check for outdated packages:
-
-```yml
-composer outdated --minor-only --strict --no-interaction $OUTDATED_EXTRAS
-composer outdated --patch-only --strict --no-interaction $OUTDATED_EXTRAS
-```
-
-The variable `$OUTDATED_EXTRAS` contains the ignored package like:
-`--ignore=drupal/somemodule --ignore=drupal/another`
-
-Rules, when the job must not run:
-
-- the commit message contains `SKIP_check4outdated` and `$CHECKUPDATES` != "yes"
-- the commit message contains "Merge branch 'develop' into 'main'"
-- the commit message contains "Merge branch 'release' into 'main'"
-
-Rules, when the job should run:
-
-- `$IGNORE_COMPOSER_EXTENDED_AUDIT` == "0"
-
-#### Check 4 Security Vulnerability Advisories
-
-We start a docker image for `php` with the specifies versions:
-
-- `PHP_MAJOR_VERSION`
-- `PHP_MINOR_VERSION`
-
-The following jobs must run before successfully. Some are optional, which means, if they exist, this job waits for them
-to complete:
-
-- [Check 4 Updates](#check-4-updates)
-    - uses its artefacts
-    - optional
-- [Build Prod Site](#build-prod-site)
-    - uses its artefacts
-    - optional
-- [Build Prod Site NG](#build-prod-site-ng)
-    - uses its artefacts
-    - optional
-- [Build Site](#build-site)
-    - uses its artefacts
-    - optional
-
-First we have to do some preparation. This is done in the `before_script` section.
-
-- [.prepareaccess](#prepareaccess)
-- [.preparecomposerplugins](#preparecomposerplugins)
-
-First we perform a `composer update` which all dependencies without the development part.
-
-Then we check for outdated packages:
-
-```yml
-composer diagnose --no-interaction || true
-composer audit --no-dev --locked --format=table
-```
-
-Rules, when the job must not run:
-
-- the commit message contains `SKIP_check4security` and `$CHECKUPDATES` != "yes"
-- the commit message contains "Merge branch 'develop' into 'main'"
-- the commit message contains "Merge branch 'release' into 'main'"
-
-Rules, when the job should run:
-
-- `$IGNORE_COMPOSER_AUDIT` == "0"
-
-#### Download DB
-
-This job executes a script, that removes the SQL file `$]PROJECT_NAME}.sql`, if it exists already.
-After that an Ansible script is executed, which dumbs the current Drupal database of the live stage.
-
-The file is saved as a build artefact, which contains `$]PROJECT_NAME}.sql`.
-
-Rules, when the job must not run:
-
-- `$DISABLE_DEPLOYMENT` != "0"
-- `$DISABLE_DEPLOYMENT_LOCAL` != "1"
-- `$DBREQUIRED` == "no"
-- `$INITIALINSTALL` == "yes"
-- `$TESTSDISABLED` == "yes"
-- `$LOCALDBFILE` != "none"
-
-Rules, when the job should run:
-
-- the tests are enabled by `$DISABLE_CI_TESTS` != "1"
-
-#### Download DB NG
-
-This is very similar to [Download DB](#download-db), but does not use Ansible. 
-It uses Docker Compose instead to execute the `drush sql:dump` command
-to dumb the current live database to the file `$]PROJECT_NAME}.sql`.
-
-The file is saved as a build artefact, which contains `$]PROJECT_NAME}.sql`.
-
-Rules, when the job must not run:
-
-- `$DISABLE_DEPLOYMENT` != "0"
-- `$DISABLE_DEPLOYMENT_LOCAL` != "0"
-- `$DBREQUIRED` == "no"
-- `$INITIALINSTALL` == "yes"
-- `$TESTSDISABLED` == "yes"
-- `$LOCALDBFILE` != "none"
-
-Rules, when the job should run:
-
-- the tests are enabled by `$DISABLE_CI_TESTS` != "1"
-
-### Prepare
-
-This stage is used to prepare the system for testing. This stage is also used for internal purpose
-and for proprietary tools.
-
-#### Import DB
-
-This job extends `.importdb`, which itself defines the 
-anchor [import_db_default](#import-db-default-anchor).
-
-The following jobs must run before successfully:
-
-- [Build Site](#build-site)
-- [Download DB](#download-db)
-
-Rules, when the job must not run:
-
- - `$DISABLE_DEPLOYMENT` != "0"
- - `$DISABLE_DEPLOYMENT_LOCAL` != "1"
- - `$DBREQUIRED` == "no"
- - `$INITIALINSTALL` == "yes"
- - `$TESTSDISABLED` == "yes"
- - `$LOCALDBFILE` != "none"
-
-Rules, when the job should run:
-
-- the tests are enabled by `$DISABLE_CI_TESTS` != "1"
-
-##### Import DB Default Anchor
-
-We start a docker image for `php` with the specifies versions:
-
-- `PHP_MAJOR_VERSION`
-- `PHP_MINOR_VERSION`
-
-A script copies the available SQL file into the PHP container, drops the current DB and imports the file.
-If the variable `SKIPCONFIGIMPORT` is `no`, a `drush config-import` gets executed as well. After that the
-`UPDATE_DB_COMMAND` gets called as well as a cache reset.
-
-#### Import DB NG
-
-This job extends `.importdbNG`, which itself defines the
-anchor [import_db_default](#import-db-default-anchor).
-
-The following jobs must run before successfully:
-
-- [Build Site](#build-site)
-- [Download DB NG](#download-db-ng)
-
-Rules, when the job must not run:
-
-- `$DISABLE_DEPLOYMENT` != "0"
-- `$DISABLE_DEPLOYMENT_LOCAL` != "0"
-- `$DBREQUIRED` == "no"
-- `$INITIALINSTALL` == "yes"
-- `$TESTSDISABLED` == "yes"
-- `$LOCALDBFILE` != "none"
-
-Rules, when the job should run:
-
-- the tests are enabled by `$DISABLE_CI_TESTS` != "1"
-
-#### Import Local DB
-
-This job extends `.importdbLocal`, which itself defines the
-anchor [import_db_default](#import-db-default-anchor).
-
-The following jobs must run before successfully:
-
-- [Build Site](#build-site)
-
-A before script is executed, which copies the `${LOCALDBFILE}` to `${PROJECT_NAME}.sql.gz` and
-unzips that file.
-
-Rules, when the job must not run:
-
-- `$DBREQUIRED` == "no"
-- `$TESTSDISABLED` == "yes"
-- `$LOCALDBFILE` != "none"
-
-Rules, when the job should run:
-
-- the tests are enabled by `$DISABLE_CI_TESTS` != "1"
-
-#### Update DB
-
-We start a docker image for php with the specifies versions:
-
-- `PHP_MAJOR_VERSION`
-- `PHP_MINOR_VERSION`
-
-If the variable `SKIPCONFIGIMPORT` is `no`, a `drush config-import` gets executed as well. 
-After that the `UPDATE_DB_COMMAND` gets called as well as a cache reset.
-
-The following jobs must run before successfully:
-
-- [Build Site](#build-site)
-
-Rules, when the job must not run:
-
-- `$DBREQUIRED` == "yes"
-- `$DBUPDREQUIRED` == "no"
-- `$INITIALINSTALL` == "yes"
-- `$TESTSDISABLED` == "yes"
-
-Rules, when the job should run:
-
-- the tests are enabled by `$DISABLE_CI_TESTS` != "1"
-
-### Postprocess
-
-#### Check 4 Updates Commit
-
-We start a docker image for php with the specifies versions:
-
-- `PHP_MAJOR_VERSION`
-- `PHP_MINOR_VERSION`
-
-The following jobs must run before successfully. Some are optional, which means, if they exist, this job waits for them
-to complete:
-
-- [Check 4 Updates](#check-4-updates)
-    - uses its artefacts
-- [Check 4 Security Vulnerability Advisories](#check-4-security-vulnerability-advisories)
-    - optional
-- [Check 4 Outdated Packages](#check-4-outdated-packages)
-    - optional
-
-First we have to do some preparation. This is done in the `before_script` section.
-
-- [.prepareaccess](#prepareaccess)
-- [.preparecomposerplugins](#preparecomposerplugins)
-
-
-
-Rules, when the job should run:
-
-- `$CHECKUPDATES` is set
-- we are on the `develop` branch
-
-### Test
-
-After the preparation and the setup of a Drupal database, we can execute tests. This happens in this stage.
-
-All tests use the two [Internal Test Stages](#internal-test-stages).
-
-#### Test Code Style
-
-This job uses [PHP Code Sniffer](../../dev_tools/test.md#php-code-sniffer) and stores the artefacts in `phpcs`.
-
-Rules, when the job should run:
-
-- the code style tests are enabled by `$DISABLE_CI_TEST_CODESTYLE` != "1"
-
-#### Test PHPUnit
-
-This job uses [PHP Unit](../../dev_tools/test.md#unitkernelfunctional-testing) and stores the artefacts in `phpunit`.
-
-Rules, when the job should run:
-
-- the code style tests are enabled by `$DISABLE_CI_TEST_PHPUNIT` != "1"
-
-
-#### Test Backstop
-
-This job uses [Backstop](../../dev_tools/test.md#unitkernelfunctional-testing) and stores the artefacts in `backstop`.
-
-The following jobs must run before successfully. Some are optional, which means, if they exist, this job waits for them
-to complete:
-
-- [Build Site](#build-site)
-- [Build Theme](#build-theme)
-    - uses its artefacts
-    - optional
-- [Import DB](#import-db)
-    - optional 
-- [Import DB NG](#import-db-ng)
-    - optional
-- [Import Local DB](#import-local-db)
-    - optional
-- [Update DB](#update-db)
-    - optional
-
-Rules, when the job should run:
-
-- the backstop tests are enabled by `$DISABLE_CI_TEST_BACKSTOP` != "1"
-
-
-#### Test Cypress E2E
-
-This job uses [Cypress](../../dev_tools/test.md#cypress) and stores the artefacts in `cypresse2e`. The tests
-are executed in headless mode.
-
-The following jobs must run before successfully. Some are optional, which means, if they exist, this job waits for them
-to complete:
-
-- [Build Site](#build-site)
-- [Build Theme](#build-theme)
-    - uses its artefacts
-    - optional
-- [Import DB](#import-db)
-    - optional
-- [Import DB NG](#import-db-ng)
-    - optional
-- [Import Local DB](#import-local-db)
-    - optional
-- [Update DB](#update-db)
-    - optional
-- [Test Backstop](#test-backstop)
-    - optional
-
-Rules, when the job should run:
-
-- the cypress tests are enabled by `$DISABLE_CI_TEST_CYPRESSE2E` != "1"
-
-#### Internal Test Stages
-
-Every test stage needs internal reoccurring definitions.
-
-**.test_lakedrops_default**
-
-We start a docker image for `php` with the specifies versions:
-
-- `PHP_MAJOR_VERSION`
-- `PHP_MINOR_VERSION`
-
-The following jobs must run before successfully:
-
-- [Build Site](#build-site)
-
-But this job can start running when the [Build Site](#build-site) has finished, so other
-test jobs can run in parallel.
-
-After running, we copy the logs from the `php` container to the current directory.
-
-
-**.test_lakedrops_theme**
-
-The following jobs must run before successfully:
-
-- [Build Site](#build-site)
-- [Build Theme](#build-theme)
-
-In the `before_script` part, we copy the `$THEME_CSS_PATH` into the `php` container, if the
-`$THEME_BUILD` variable ist set to "yes".
-
-In `after_script` we remove `$THEME_CSS_PATH` again.
-
-####
-
-### Deploy
-
-This stage handles the deployment of the produced build artefact.
-
-#### Deploy
-
-The following jobs must run before successfully:
-
-- [Build Prod Site](#build-prod-site)
-- [Build Theme](#build-theme)
-
-This job executes an [Ansible](https://www.ansible.com/) script, which does the deployment.
-
-Rules, when the job must not run:
-
-- `$DISABLE_DEPLOYMENT` != "0"
-- `$DISABLE_DEPLOYMENT_LOCAL` != "1"
-
-#### Deploy NG
-
-The following jobs must run before successfully:
-
-- [Build Prod Site](#build-prod-site)
-- [Build Prod Site NG](#build-prod-site-ng)
-- [Build Theme](#build-theme)
-
-First we have to do some preparation. This is done in the `before_script` section.
-
-- [.prepareaccess](#prepareaccess)
-
-This job does not use [Ansible](https://www.ansible.com/). A lot of commands are executed in the script section.
-Here is a summary:
-
-- create the directories, where the site gets deployed to:
-    - app
-    - db
-    - files
-    - redis
-    - backup
-- sets the ownership and permissions of these files
-- start all the docker service with [Docker Compose](https://docs.docker.com/compose/)
-- execute several `drush` commands
-- create config auto export directory
-- restart cron jobs
-
-To see all the commands, visit
-[test_deploy.yml](https://gitlab.lakedrops.com/gitlab-ci-cd/drupal/-/blob/main/test-and-deploy.yml?ref_type=heads).
-
-Rules, when the job must not run:
-
-- `$DISABLE_DEPLOYMENT` != "0"
-- `$CI_COMMIT_BRANCH` != "main" && `$ENFORCE_DEPLOYMENT` != "1"
-
-### Finalize
-
-Here we can do cleanups and remove some garbage the build process produces.
-
-#### Shut Down Docker Project
-
-We start a docker image for php with the specifies versions:
-
-- `PHP_MAJOR_VERSION`
-- `PHP_MINOR_VERSION`
-
-The following jobs must run before successfully:
-
-- [Build Site](#build-site)
-
-This job simply stops and removes the docker container, which are started for the build by:
-
-`docker compose down`
-
-### Release Stage
-
-This stage is responsible for creating a new release.
-
-#### Release Job
-
-This job extends the internal job [.merge](#merge).
-
-Rules, when the job should run:
-
-- `$CI_COMMIT_MESSAGE` contains `CREATE_RELEASE`
-- we are on the `develop` branch
-
-Rules, when the job must not run:
-
-- if the reference is a `tag`
-- `$CI_COMMIT_MESSAGE` contains `Merge tag`
-- if it is triggered by config auto export (CAE)
-- `$CHECKUPDATES` is set
-- `$TRIGGERTASK` is set
-
-
-### Internal Stages
-
-Here we have some internal stages, which cannot be executed alone. The purpose is to
-collect repeating execution.
-
-#### .prepareaccess
-
-This internal job, you find in [mixins.yml](https://gitlab.lakedrops.com/gitlab-ci-cd/general/-/blob/main/mixins.yml?ref_type=heads).
-
-Mainly, we care about getting access to:
-
-- the host `$CI_SERVER_HOST` with `ssh` via `$SSH_PRIVATE_KEY`
-- GitLab Login via `$GITLAB_ACCESS_TOKEN` and `$GITLAB_PRIVATE_TOKEN`
-- Docker configuration via `$DOCKER_AUTH_CONFIG`
-
-
-#### .preparecomposerplugins
-
-This internal job, you find in [mixins.yml](https://gitlab.lakedrops.com/gitlab-ci-cd/general/-/blob/main/mixins.yml?ref_type=heads).
-
-The following points will be prepared for [Composer](https://getcomposer.org/):
-
-- the version >2, if `$DOWNGRADE_COMPOSER` is not set
-- the configuration `allow-plugins`
-- the configuration `audit.abandoned`, depend on `$IGNORE_COMPOSER_ABANDONED_AUDIT`
-- unsupported module versions, which are allowed to use
-
-#### .merge
-
-First we have to do some preparation. This is done in the `before_script` section.
-
-- [.prepareaccess](#prepareaccess)
-
-We start a docker image for php with the specifies versions:
-
-- `PHP_MAJOR_VERSION`
-- `PHP_MINOR_VERSION`
-
-We create a clean directory and clone the git project `$CI_PROJECT_PATH`
-for branch `$SOURCE_BRANCH` from `$CI_SERVER_HOST` right into it.
-
-After that we execute the [merge](https://gitlab.lakedrops.com/docker/gitlab-drupal-ci/-/blob/main/bin/merge?ref_type=heads) 
-script, which does a few checks and use the `gitlab` tool to merge.
-
-Finally, we remove the directory we created above.
-
-#### .retry-for-system-issues
-
-This little job ste the amount of retries to "2", when:
-
-- runner_system_failure
-- stuck_or_timeout_failure
-
-#### .cache_paths
-
-All internal jobs concerning cache will use this job here. It defines the paths:
-
-- .docker-init/
-- assets/
-- drush/
-- files/
-- keys/
-- settings/
-- vendor/
-- web/core/
-- web/libraries/
-- web/modules/contrib/
-- web/profiles/contrib/
-- web/sites/
-- web/themes/contrib/
-- .ahoy.yml
-- .env
-- docker-compose.yml
-
-
-## Configuration
-
-### GitLab Runner
+## GitLab Runner
 
 To setup a GitLab runner, they need to be
 [installed first](https://docs.gitlab.com/runner/install) - see also our
@@ -813,7 +47,7 @@ different PHP versions a different GitLab runner should be configured or the
 image being overwritten for each task in the `.gitlab-ci.yml` of the respective
 project.
 
-### GitLab Variables
+## GitLab Variables
 
 Some variables are required for proper access control, and you have to provide
 them in the project configuration by going to **Settings / CI/CD / Variables**
@@ -825,7 +59,7 @@ and adding these variables:
   repository, you have to create an access tokeb for the user who runs the
   pipeline and provide it in this variable.
 
-### GitLab CI instructions in Drupal project
+## GitLab CI instructions in Drupal project
 
 The Drupal project should be setup with the
 [Drupal Development Environment](/composer/plugin/drupal-dev-environment)
@@ -930,7 +164,7 @@ using our Ansible environment too, then please refer to
 [Using Ansible for Deployment](#Using Ansible for Deployment) below. Otherwise,
 you have to write the scripts for those two tasks yourselves.
 
-#### Variables
+### Variables
 
 - `COMPOSE_PROJECT_NAME`: a string only unique project name which will be used
   to identify caches and Docker containers.
@@ -969,11 +203,11 @@ you have to write the scripts for those two tasks yourselves.
   completely and built from scratch.  Can also be used as
   `[RESET_LOCALE]` in the Git commit message. 
 
-## Usage
+# Usage
 
 This chapter is incomplete so far and needs more attention.
 
-### Initial installation of a Drupal site
+## Initial installation of a Drupal site
 
 This pipeline covers both, the initial installation and later updates of a
 Drupal site. The latter is the default, because it happens regularely whereas
@@ -987,7 +221,7 @@ pipeline from the GitLab UI.
 When either of these conditions apply, no database will be downloaded, imported
 or updated and all tests will be skipped.
 
-### Handling of the database
+## Handling of the database
 
 To build and test your Drupal site prior to deployment, a database with content
 for this project is required and this is handled by the pipeline pretty smart.
@@ -1012,7 +246,7 @@ task `Import DB` will then import that dump in the `prepare` stage.
 Otherwise, those two tasks will be skipped and the task `Update DB` will be
 executed in the `prepare` stage instead.
 
-## Example
+# Example
 
 We provide a [Demo Drupal 10 project](https://gitlab.lakedrops.com/gitlab-ci-cd/demos/drupal-10)
 which uses this GitLab CI framework. If you want to give it a try, login to 
diff --git a/docs/gitlab/pipelines/index.md b/docs/gitlab/pipelines/index.md
new file mode 100644
index 0000000..9e92ad6
--- /dev/null
+++ b/docs/gitlab/pipelines/index.md
@@ -0,0 +1,775 @@
+---
+title: GitLab Drupal
+repo: https://gitlab.lakedrops.com/gitlab-ci-cd/pipelines
+issues: https://gitlab.lakedrops.com/gitlab-ci-cd/pipelines/-/issues
+tags:
+- gitlab
+- ci/cd
+- pipeline
+- job
+---
+# GitLab CI for Drupal pipelines
+
+This project contains a number of pre-configured tasks for GitLab CI/CD that
+allow to run very powerful pipelines which contain the following stage order:
+
+- [.pre (predefined)](#pre)
+- [execute](#execute)
+- [buildprod](#build-prod)
+- [build (predefined)](#build)
+- [prepare](#prepare)
+- [postprocess](#postprocess)
+- [validate](#validate)
+- [test (predefined)](#test)
+- [deploy (predefined)](#deploy)
+- [finalize](#finalize)
+- [release](#release-stage)
+
+We have a predefined `execute` job called `LakeDrops`, which looks like this:
+
+- [execute](#execute)
+    - LakeDrops
+        - [buildprod](#build-prod)
+            - [Build Prod Site](#build-prod-site)
+            - [Build Prod Site NG](#build-prod-site-ng)
+        - [build (predefined)](#build)
+            - [Build Site](#build-site)
+            - [Build Theme](#build-theme)
+            - [Check 4 Outdated Packages](#check-4-outdated-packages)
+            - [Check 4 Security Vulnerability Advisories](#check-4-security-vulnerability-advisories)
+            - [Download DB](#download-db)
+            - [Download DB NG](#download-db-ng)
+        - [prepare](#prepare)
+            - [Import DB](#import-db)
+            - [Import DB NG](#import-db-ng)
+            - [Import Local DB](#import-local-db)
+            - [Update DB](#update-db) 
+        - [test](#test)
+            - [Test Code Style](#test-code-style)
+            - [Test PHPUnit](#test-phpunit)
+            - [Test Backstop](#test-backstop)
+            - [Test Cypress E2E](#test-cypress-e2e)
+        - [finalize](#finalize)
+            - [Shut Down Docker Project](#shut-down-docker-project)
+
+These pre-configured tasks can easily be included into your Drupal project.
+A GitLab runner on any host can then be configured to run those pipelines. The 
+following chapters describe the necessary steps and also all the options
+available for configuration.
+
+## Stages
+The following chapters describes all stages and their jobs. The files:
+
+-  [lakedrops.yml](https://gitlab.lakedrops.com/gitlab-ci-cd/drupal/-/blob/main/lakedrops.yml?ref_type=heads).
+-  [tests/lakedrops.yml](https://gitlab.lakedrops.com/gitlab-ci-cd/drupal/-/blob/main/tests/lakedrops.yml?ref_type=heads).
+-  [test_deploy.yml](https://gitlab.lakedrops.com/gitlab-ci-cd/drupal/-/blob/main/test-and-deploy.yml?ref_type=heads).
+-  [check4updates.yml](https://gitlab.lakedrops.com/gitlab-ci-cd/drupal/-/blob/main/check4updates.yml?ref_type=heads).
+
+### .pre
+
+To prepare and check, if the environment is good to go, we have a `.pre` stage, which contains the
+following jobs:
+
+#### Sanity Checks
+
+The sanity check gets important when you are using [Crowdsec](https://www.crowdsec.net/).
+It contains two little scripts, that check:
+
+-    if the `crowdsec.settings.yml` is in the config split and
+-    if it is not enabled in the `core.extensions.yml`.
+
+Otherwise, it is conflicting with you local settings, since `CrowdSec`
+is a tool for production sites.
+
+Except:
+
+- Commit message contains "Merge tag"
+- Commit message contains "Merge branch"
+- When the job is triggered by config auto export (CAE)
+
+#### Validate Environment
+
+This job extends the `.prerequisites` in 
+[test_deploy.yml](https://gitlab.lakedrops.com/gitlab-ci-cd/drupal/-/blob/main/test-and-deploy.yml?ref_type=heads).
+
+This job executes a script, where several [variables](#variables) are checked and set accordingly.
+
+Except:
+
+- Commit message contains "Merge tag"
+- Commit message contains "Merge branch"
+- When the job is triggered by config auto export (CAE)
+
+### Validate
+
+This stage is currently not officially used.
+
+### Execute
+
+This stage executes the build itself.
+
+### Build Prod
+
+This stage is responsible for building the production website, which we want to finally deploy.
+
+#### Build Prod Site
+
+First we have to do some preparation. This is done in the `before_script` section.
+
+- [.prepareaccess](#prepareaccess)
+- [.preparecomposerplugins](#preparecomposerplugins)
+
+We start a docker image for php with the specifies versions:
+
+- `PHP_MAJOR_VERSION`
+- `PHP_MINOR_VERSION`
+
+In the script section we first update the environment by executing `/usr/local/bin/update-env`.
+
+After that we install the production site with `composer install` **without** the tools for development. That is pretty 
+it. We also add `drupal/core-vendor-hardening`.
+
+The entire installation is saved as a build artefact called `build-prod` where all `git` files are excluded.
+
+#### Build Prod Site NG
+
+First we have to do some preparation. This is done in the `before_script` section.
+
+- [.prepareaccess](#prepareaccess)
+- [.preparecomposerplugins](#preparecomposerplugins)
+
+We start a docker image for php with the specifies versions:
+
+- `PHP_MAJOR_VERSION`
+- `PHP_MINOR_VERSION`
+
+In the script part we install two of our LakeDrops modules:
+
+- [lakedrops/drupal-environment](../../composer/plugin/drupal-environment)
+- [lakedrops/docker4drupal](../../composer/plugin/d4d)
+
+After that we execute:
+
+- `composer lakedrops:config`
+- `composer lakedrops:docker4drupal`
+
+The entire installation is saved as a build artefact called `build-prod-ng` where all `git` files are excluded.
+
+Rules, when the job should run:
+
+- `$DISABLE_DEPLOYMENT_LOCAL` != "1"
+
+### Build
+
+Here, we define jobs, which build the Drupal website and does some additional checks. This stage is
+responsible for the database downloads as well.
+
+#### Build Site
+
+We start a docker image for `php` with the specifies versions:
+
+- `PHP_MAJOR_VERSION`
+- `PHP_MINOR_VERSION`
+
+After that, we start to build the Drupal site with [Composer](https://getcomposer.org/):
+
+Now we execute a `composer install` twice to ensure that all patches get applied correctly. After
+that we setup our own `LakeDrops` tools by `composer lakedrops:scaffold` and
+`composer lakedrops:docker4drupal`.
+
+The next step is to pull all required [Docker](https://www.docker.com/) images 
+with [Docker Compose](https://docs.docker.com/compose/) and start the services.
+
+After everything has started, we create some directories, e.g. for styles, logs and JavaScript.
+
+The entire installation is saved as a build artefact called `build` where all `git` files are excluded.
+
+Rules, when the job should run:
+
+- the tests are enabled by `$TESTSDISABLED` == "no"
+
+#### Build Theme
+
+This job creates the required files for the styling of the website. 
+
+The following jobs must run before successfully:
+
+- [Build Prod Site](#build-prod-site)
+
+#### Check 4 Updates
+
+e start a docker image for `php` with the specifies versions:
+
+- `PHP_MAJOR_VERSION`
+- `PHP_MINOR_VERSION`
+
+First we have to do some preparation. This is done in the `before_script` section.
+
+- [.prepareaccess](#prepareaccess)
+- [.preparecomposerplugins](#preparecomposerplugins)
+
+The job stores the artefacts in `check4updates`.
+
+
+
+Rules, when the job should run:
+
+- `$CHECKUPDATES` is set
+- we are on the `develop` branch
+
+
+#### Check 4 Outdated Packages
+
+We start a docker image for `php` with the specifies versions:
+
+- `PHP_MAJOR_VERSION`
+- `PHP_MINOR_VERSION`
+
+The following jobs must run before successfully. Some are optional, which means, if they exist, this job waits for them
+to complete:
+
+- [Check 4 Updates](#check-4-updates)
+    - uses its artefacts
+    - optional
+- [Build Prod Site](#build-prod-site)
+    - uses its artefacts
+    - optional
+- [Build Prod Site NG](#build-prod-site-ng)
+    - uses its artefacts
+    - optional
+- [Build Site](#build-site)
+    - uses its artefacts
+    - optional
+
+First we have to do some preparation. This is done in the `before_script` section.
+
+- [.prepareaccess](#prepareaccess)
+- [.preparecomposerplugins](#preparecomposerplugins)
+
+First we perform a `composer update` which all dependencies without the development part.
+
+Then we check for outdated packages:
+
+```yml
+composer outdated --minor-only --strict --no-interaction $OUTDATED_EXTRAS
+composer outdated --patch-only --strict --no-interaction $OUTDATED_EXTRAS
+```
+
+The variable `$OUTDATED_EXTRAS` contains the ignored package like:
+`--ignore=drupal/somemodule --ignore=drupal/another`
+
+Rules, when the job must not run:
+
+- the commit message contains `SKIP_check4outdated` and `$CHECKUPDATES` != "yes"
+- the commit message contains "Merge branch 'develop' into 'main'"
+- the commit message contains "Merge branch 'release' into 'main'"
+
+Rules, when the job should run:
+
+- `$IGNORE_COMPOSER_EXTENDED_AUDIT` == "0"
+
+#### Check 4 Security Vulnerability Advisories
+
+We start a docker image for `php` with the specifies versions:
+
+- `PHP_MAJOR_VERSION`
+- `PHP_MINOR_VERSION`
+
+The following jobs must run before successfully. Some are optional, which means, if they exist, this job waits for them
+to complete:
+
+- [Check 4 Updates](#check-4-updates)
+    - uses its artefacts
+    - optional
+- [Build Prod Site](#build-prod-site)
+    - uses its artefacts
+    - optional
+- [Build Prod Site NG](#build-prod-site-ng)
+    - uses its artefacts
+    - optional
+- [Build Site](#build-site)
+    - uses its artefacts
+    - optional
+
+First we have to do some preparation. This is done in the `before_script` section.
+
+- [.prepareaccess](#prepareaccess)
+- [.preparecomposerplugins](#preparecomposerplugins)
+
+First we perform a `composer update` which all dependencies without the development part.
+
+Then we check for outdated packages:
+
+```yml
+composer diagnose --no-interaction || true
+composer audit --no-dev --locked --format=table
+```
+
+Rules, when the job must not run:
+
+- the commit message contains `SKIP_check4security` and `$CHECKUPDATES` != "yes"
+- the commit message contains "Merge branch 'develop' into 'main'"
+- the commit message contains "Merge branch 'release' into 'main'"
+
+Rules, when the job should run:
+
+- `$IGNORE_COMPOSER_AUDIT` == "0"
+
+#### Download DB
+
+This job executes a script, that removes the SQL file `$]PROJECT_NAME}.sql`, if it exists already.
+After that an Ansible script is executed, which dumbs the current Drupal database of the live stage.
+
+The file is saved as a build artefact, which contains `$]PROJECT_NAME}.sql`.
+
+Rules, when the job must not run:
+
+- `$DISABLE_DEPLOYMENT` != "0"
+- `$DISABLE_DEPLOYMENT_LOCAL` != "1"
+- `$DBREQUIRED` == "no"
+- `$INITIALINSTALL` == "yes"
+- `$TESTSDISABLED` == "yes"
+- `$LOCALDBFILE` != "none"
+
+Rules, when the job should run:
+
+- the tests are enabled by `$DISABLE_CI_TESTS` != "1"
+
+#### Download DB NG
+
+This is very similar to [Download DB](#download-db), but does not use Ansible. 
+It uses Docker Compose instead to execute the `drush sql:dump` command
+to dumb the current live database to the file `$]PROJECT_NAME}.sql`.
+
+The file is saved as a build artefact, which contains `$]PROJECT_NAME}.sql`.
+
+Rules, when the job must not run:
+
+- `$DISABLE_DEPLOYMENT` != "0"
+- `$DISABLE_DEPLOYMENT_LOCAL` != "0"
+- `$DBREQUIRED` == "no"
+- `$INITIALINSTALL` == "yes"
+- `$TESTSDISABLED` == "yes"
+- `$LOCALDBFILE` != "none"
+
+Rules, when the job should run:
+
+- the tests are enabled by `$DISABLE_CI_TESTS` != "1"
+
+### Prepare
+
+This stage is used to prepare the system for testing. This stage is also used for internal purpose
+and for proprietary tools.
+
+#### Import DB
+
+This job extends `.importdb`, which itself defines the 
+anchor [import_db_default](#import-db-default-anchor).
+
+The following jobs must run before successfully:
+
+- [Build Site](#build-site)
+- [Download DB](#download-db)
+
+Rules, when the job must not run:
+
+ - `$DISABLE_DEPLOYMENT` != "0"
+ - `$DISABLE_DEPLOYMENT_LOCAL` != "1"
+ - `$DBREQUIRED` == "no"
+ - `$INITIALINSTALL` == "yes"
+ - `$TESTSDISABLED` == "yes"
+ - `$LOCALDBFILE` != "none"
+
+Rules, when the job should run:
+
+- the tests are enabled by `$DISABLE_CI_TESTS` != "1"
+
+##### Import DB Default Anchor
+
+We start a docker image for `php` with the specifies versions:
+
+- `PHP_MAJOR_VERSION`
+- `PHP_MINOR_VERSION`
+
+A script copies the available SQL file into the PHP container, drops the current DB and imports the file.
+If the variable `SKIPCONFIGIMPORT` is `no`, a `drush config-import` gets executed as well. After that the
+`UPDATE_DB_COMMAND` gets called as well as a cache reset.
+
+#### Import DB NG
+
+This job extends `.importdbNG`, which itself defines the
+anchor [import_db_default](#import-db-default-anchor).
+
+The following jobs must run before successfully:
+
+- [Build Site](#build-site)
+- [Download DB NG](#download-db-ng)
+
+Rules, when the job must not run:
+
+- `$DISABLE_DEPLOYMENT` != "0"
+- `$DISABLE_DEPLOYMENT_LOCAL` != "0"
+- `$DBREQUIRED` == "no"
+- `$INITIALINSTALL` == "yes"
+- `$TESTSDISABLED` == "yes"
+- `$LOCALDBFILE` != "none"
+
+Rules, when the job should run:
+
+- the tests are enabled by `$DISABLE_CI_TESTS` != "1"
+
+#### Import Local DB
+
+This job extends `.importdbLocal`, which itself defines the
+anchor [import_db_default](#import-db-default-anchor).
+
+The following jobs must run before successfully:
+
+- [Build Site](#build-site)
+
+A before script is executed, which copies the `${LOCALDBFILE}` to `${PROJECT_NAME}.sql.gz` and
+unzips that file.
+
+Rules, when the job must not run:
+
+- `$DBREQUIRED` == "no"
+- `$TESTSDISABLED` == "yes"
+- `$LOCALDBFILE` != "none"
+
+Rules, when the job should run:
+
+- the tests are enabled by `$DISABLE_CI_TESTS` != "1"
+
+#### Update DB
+
+We start a docker image for php with the specifies versions:
+
+- `PHP_MAJOR_VERSION`
+- `PHP_MINOR_VERSION`
+
+If the variable `SKIPCONFIGIMPORT` is `no`, a `drush config-import` gets executed as well. 
+After that the `UPDATE_DB_COMMAND` gets called as well as a cache reset.
+
+The following jobs must run before successfully:
+
+- [Build Site](#build-site)
+
+Rules, when the job must not run:
+
+- `$DBREQUIRED` == "yes"
+- `$DBUPDREQUIRED` == "no"
+- `$INITIALINSTALL` == "yes"
+- `$TESTSDISABLED` == "yes"
+
+Rules, when the job should run:
+
+- the tests are enabled by `$DISABLE_CI_TESTS` != "1"
+
+### Postprocess
+
+#### Check 4 Updates Commit
+
+We start a docker image for php with the specifies versions:
+
+- `PHP_MAJOR_VERSION`
+- `PHP_MINOR_VERSION`
+
+The following jobs must run before successfully. Some are optional, which means, if they exist, this job waits for them
+to complete:
+
+- [Check 4 Updates](#check-4-updates)
+    - uses its artefacts
+- [Check 4 Security Vulnerability Advisories](#check-4-security-vulnerability-advisories)
+    - optional
+- [Check 4 Outdated Packages](#check-4-outdated-packages)
+    - optional
+
+First we have to do some preparation. This is done in the `before_script` section.
+
+- [.prepareaccess](#prepareaccess)
+- [.preparecomposerplugins](#preparecomposerplugins)
+
+
+
+Rules, when the job should run:
+
+- `$CHECKUPDATES` is set
+- we are on the `develop` branch
+
+### Test
+
+After the preparation and the setup of a Drupal database, we can execute tests. This happens in this stage.
+
+All tests use the two [Internal Test Stages](#internal-test-stages).
+
+#### Test Code Style
+
+This job uses [PHP Code Sniffer](../../dev_tools/test.md#php-code-sniffer) and stores the artefacts in `phpcs`.
+
+Rules, when the job should run:
+
+- the code style tests are enabled by `$DISABLE_CI_TEST_CODESTYLE` != "1"
+
+#### Test PHPUnit
+
+This job uses [PHP Unit](../../dev_tools/test.md#unitkernelfunctional-testing) and stores the artefacts in `phpunit`.
+
+Rules, when the job should run:
+
+- the code style tests are enabled by `$DISABLE_CI_TEST_PHPUNIT` != "1"
+
+
+#### Test Backstop
+
+This job uses [Backstop](../../dev_tools/test.md#unitkernelfunctional-testing) and stores the artefacts in `backstop`.
+
+The following jobs must run before successfully. Some are optional, which means, if they exist, this job waits for them
+to complete:
+
+- [Build Site](#build-site)
+- [Build Theme](#build-theme)
+    - uses its artefacts
+    - optional
+- [Import DB](#import-db)
+    - optional 
+- [Import DB NG](#import-db-ng)
+    - optional
+- [Import Local DB](#import-local-db)
+    - optional
+- [Update DB](#update-db)
+    - optional
+
+Rules, when the job should run:
+
+- the backstop tests are enabled by `$DISABLE_CI_TEST_BACKSTOP` != "1"
+
+
+#### Test Cypress E2E
+
+This job uses [Cypress](../../dev_tools/test.md#cypress) and stores the artefacts in `cypresse2e`. The tests
+are executed in headless mode.
+
+The following jobs must run before successfully. Some are optional, which means, if they exist, this job waits for them
+to complete:
+
+- [Build Site](#build-site)
+- [Build Theme](#build-theme)
+    - uses its artefacts
+    - optional
+- [Import DB](#import-db)
+    - optional
+- [Import DB NG](#import-db-ng)
+    - optional
+- [Import Local DB](#import-local-db)
+    - optional
+- [Update DB](#update-db)
+    - optional
+- [Test Backstop](#test-backstop)
+    - optional
+
+Rules, when the job should run:
+
+- the cypress tests are enabled by `$DISABLE_CI_TEST_CYPRESSE2E` != "1"
+
+#### Internal Test Stages
+
+Every test stage needs internal reoccurring definitions.
+
+**.test_lakedrops_default**
+
+We start a docker image for `php` with the specifies versions:
+
+- `PHP_MAJOR_VERSION`
+- `PHP_MINOR_VERSION`
+
+The following jobs must run before successfully:
+
+- [Build Site](#build-site)
+
+But this job can start running when the [Build Site](#build-site) has finished, so other
+test jobs can run in parallel.
+
+After running, we copy the logs from the `php` container to the current directory.
+
+
+**.test_lakedrops_theme**
+
+The following jobs must run before successfully:
+
+- [Build Site](#build-site)
+- [Build Theme](#build-theme)
+
+In the `before_script` part, we copy the `$THEME_CSS_PATH` into the `php` container, if the
+`$THEME_BUILD` variable ist set to "yes".
+
+In `after_script` we remove `$THEME_CSS_PATH` again.
+
+####
+
+### Deploy
+
+This stage handles the deployment of the produced build artefact.
+
+#### Deploy
+
+The following jobs must run before successfully:
+
+- [Build Prod Site](#build-prod-site)
+- [Build Theme](#build-theme)
+
+This job executes an [Ansible](https://www.ansible.com/) script, which does the deployment.
+
+Rules, when the job must not run:
+
+- `$DISABLE_DEPLOYMENT` != "0"
+- `$DISABLE_DEPLOYMENT_LOCAL` != "1"
+
+#### Deploy NG
+
+The following jobs must run before successfully:
+
+- [Build Prod Site](#build-prod-site)
+- [Build Prod Site NG](#build-prod-site-ng)
+- [Build Theme](#build-theme)
+
+First we have to do some preparation. This is done in the `before_script` section.
+
+- [.prepareaccess](#prepareaccess)
+
+This job does not use [Ansible](https://www.ansible.com/). A lot of commands are executed in the script section.
+Here is a summary:
+
+- create the directories, where the site gets deployed to:
+    - app
+    - db
+    - files
+    - redis
+    - backup
+- sets the ownership and permissions of these files
+- start all the docker service with [Docker Compose](https://docs.docker.com/compose/)
+- execute several `drush` commands
+- create config auto export directory
+- restart cron jobs
+
+To see all the commands, visit
+[test_deploy.yml](https://gitlab.lakedrops.com/gitlab-ci-cd/drupal/-/blob/main/test-and-deploy.yml?ref_type=heads).
+
+Rules, when the job must not run:
+
+- `$DISABLE_DEPLOYMENT` != "0"
+- `$CI_COMMIT_BRANCH` != "main" && `$ENFORCE_DEPLOYMENT` != "1"
+
+### Finalize
+
+Here we can do cleanups and remove some garbage the build process produces.
+
+#### Shut Down Docker Project
+
+We start a docker image for php with the specifies versions:
+
+- `PHP_MAJOR_VERSION`
+- `PHP_MINOR_VERSION`
+
+The following jobs must run before successfully:
+
+- [Build Site](#build-site)
+
+This job simply stops and removes the docker container, which are started for the build by:
+
+`docker compose down`
+
+### Release Stage
+
+This stage is responsible for creating a new release.
+
+#### Release Job
+
+This job extends the internal job [.merge](#merge).
+
+Rules, when the job should run:
+
+- `$CI_COMMIT_MESSAGE` contains `CREATE_RELEASE`
+- we are on the `develop` branch
+
+Rules, when the job must not run:
+
+- if the reference is a `tag`
+- `$CI_COMMIT_MESSAGE` contains `Merge tag`
+- if it is triggered by config auto export (CAE)
+- `$CHECKUPDATES` is set
+- `$TRIGGERTASK` is set
+
+
+### Internal Stages
+
+Here we have some internal stages, which cannot be executed alone. The purpose is to
+collect repeating execution.
+
+#### .prepareaccess
+
+This internal job, you find in [mixins.yml](https://gitlab.lakedrops.com/gitlab-ci-cd/general/-/blob/main/mixins.yml?ref_type=heads).
+
+Mainly, we care about getting access to:
+
+- the host `$CI_SERVER_HOST` with `ssh` via `$SSH_PRIVATE_KEY`
+- GitLab Login via `$GITLAB_ACCESS_TOKEN` and `$GITLAB_PRIVATE_TOKEN`
+- Docker configuration via `$DOCKER_AUTH_CONFIG`
+
+
+#### .preparecomposerplugins
+
+This internal job, you find in [mixins.yml](https://gitlab.lakedrops.com/gitlab-ci-cd/general/-/blob/main/mixins.yml?ref_type=heads).
+
+The following points will be prepared for [Composer](https://getcomposer.org/):
+
+- the version >2, if `$DOWNGRADE_COMPOSER` is not set
+- the configuration `allow-plugins`
+- the configuration `audit.abandoned`, depend on `$IGNORE_COMPOSER_ABANDONED_AUDIT`
+- unsupported module versions, which are allowed to use
+
+#### .merge
+
+First we have to do some preparation. This is done in the `before_script` section.
+
+- [.prepareaccess](#prepareaccess)
+
+We start a docker image for php with the specifies versions:
+
+- `PHP_MAJOR_VERSION`
+- `PHP_MINOR_VERSION`
+
+We create a clean directory and clone the git project `$CI_PROJECT_PATH`
+for branch `$SOURCE_BRANCH` from `$CI_SERVER_HOST` right into it.
+
+After that we execute the [merge](https://gitlab.lakedrops.com/docker/gitlab-drupal-ci/-/blob/main/bin/merge?ref_type=heads) 
+script, which does a few checks and use the `gitlab` tool to merge.
+
+Finally, we remove the directory we created above.
+
+#### .retry-for-system-issues
+
+This little job ste the amount of retries to "2", when:
+
+- runner_system_failure
+- stuck_or_timeout_failure
+
+#### .cache_paths
+
+All internal jobs concerning cache will use this job here. It defines the paths:
+
+- .docker-init/
+- assets/
+- drush/
+- files/
+- keys/
+- settings/
+- vendor/
+- web/core/
+- web/libraries/
+- web/modules/contrib/
+- web/profiles/contrib/
+- web/sites/
+- web/themes/contrib/
+- .ahoy.yml
+- .env
+- docker-compose.yml
diff --git a/mkdocs.yml b/mkdocs.yml
index 75aab87..2a3414b 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -266,6 +266,7 @@ nav:
   - GitLab:
       - gitlab/index.md
       - Drupal: gitlab/drupal/index.md
+      - Pipelines: gitlab/pipelines/index.md
       - Ansible: gitlab/ansible/index.md
   - DevOps:
       - ALM:
-- 
GitLab