diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 5d9dbd502d854257f3baab7090d50d9a198b0b51..7a713df88c4221deaad0ef665d8d6d2a4d657881 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -92,7 +92,7 @@ executable:
         --manifest-branch=${MANIFEST_BRANCH} \
         --submodule=.gitlab-ci \
         --revision=${CI_COMMIT_SHA} \
-        --group=${PROJECT_INTEGRATION} \
+        --group="${PROJECT_INTEGRATION}" \
         --verbose \
         ${MERGE}
       done
diff --git a/layers-integration.yml b/layers-integration.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ca522a0a60e7fc145aaf915e0c9fd1d930a43bf1
--- /dev/null
+++ b/layers-integration.yml
@@ -0,0 +1,186 @@
+---
+# --------------------------------------------------------------------------------------
+# Global
+# --------------------------------------------------------------------------------------
+
+include:
+  - local: common.yml
+
+stages:
+  - infrastructure
+  - integrate-into-layer
+  - create-merge
+  - check
+  - accept-merge
+
+variables:
+  # The BB_RECIPE_NAME is used for projects referenced in the SRCREV file
+  # to match the repository and the bitbake recipe name.
+  # We set it here to none, as every project needing it
+  # has to specify it in its own gitlab-ci.yml file.
+  # The BB_RECIPE_NAME is passed to the python scripts below anyway, but not
+  # used for projects referenced in the manifest file.
+  # FIXME: This is only necessary due to the following GitLab limitation:
+  # https://gitlab.com/gitlab-org/gitlab/-/issues/209904
+  # As soon as this gets fixed upstream, the hard-coded branch name should be removed.
+  MANIFEST_PROJECT: yocto_ng/seco-manifest
+  MASTER_BRANCH_LAYER: kirkstone/develop
+  BB_RECIPE_NAME: none
+  SRCREV_FILE: conf/SRCREV.conf
+
+  DEPLOYPATH_TEST: "/artifacts/${CI_JOB_ID}/"
+  GITLAB_SERVER: "${CI_SERVER_HOST}:${CI_SERVER_SSH_PORT}"
+  GIT_BASE_URL: "ssh://git@${GITLAB_SERVER}/${CI_PROJECT_ROOT_NAMESPACE}"
+  TESTS_GIT_URL: "${GIT_BASE_URL}/yocto/tests.git"
+ 
+# --------------------------------------------------------------------------------------
+# Stage: infrastructure
+# --------------------------------------------------------------------------------------
+integrate-into-layer:
+  extends: .infrastructure
+  rules:
+    # Do not integration pipeline for merge requests for integrate/gitlab-ci/ branches
+    # The integration is done from the pipeline in gitlab-ci already
+    - if: $CI_COMMIT_REF_NAME =~ /^integrate\/gitlab-ci\/.*/
+      when: never
+    # We have to make sure that the pipeline runs for the current manifest
+    # master at the time a merge request is created. Otherwise we cannot
+    # guarantee a green master after merging.
+    - if: $CI_MERGE_REQUEST_IID
+    # Explicitly allow externally triggered pipelines in every case
+    - if: $CI_PIPELINE_SOURCE == "pipeline" || $CI_PIPELINE_SOURCE == "api"
+  cache:
+    policy: push
+  script:
+    - cd ${CI_PROJECT_DIR}
+    - if [ -n "${CI_MERGE_REQUEST_IID}" ];then
+        MERGE_REQUEST="${CI_MERGE_REQUEST_IID}";
+      else
+        MERGE_REQUEST="${CI_OPEN_MERGE_REQUESTS%%,*}";
+      fi
+    - .gitlab-ci/scripts/integrate_into_layer.py
+        --gitlab-url=${CI_SERVER_URL}
+        --token=${GITBOT_TOKEN}
+        --layer-project=${LAYER_PROJECT_PATH}
+        --layer-branch=${MASTER_BRANCH_LAYER}
+        --project=${CI_PROJECT_PATH}
+        --srcrev-file=${SRCREV_FILE}
+        --merge-request=${MERGE_REQUEST}
+        --save-revision-to=srcrev_revision
+        --recipe-name=${BB_RECIPE_NAME}
+        --verbose
+  artifacts:
+    paths:
+      - srcrev_revision
+      - integration_branch_file
+
+# --------------------------------------------------------------------------------------
+# Stage: create-merge-request
+# --------------------------------------------------------------------------------------
+create-merge-request:
+  stage: create-merge
+  extends: .infrastructure
+  rules:
+    # Do not integration pipeline for merge requests for integrate/gitlab-ci/ branches
+    # The integration is done from the pipeline in gitlab-ci already
+    - if: $CI_COMMIT_REF_NAME =~ /^integrate\/gitlab-ci\/.*/
+      when: never
+    # We have to make sure that the pipeline runs for the current manifest
+    # master at the time a merge request is created. Otherwise we cannot
+    # guarantee a green master after merging.
+    - if: $CI_MERGE_REQUEST_IID
+    - if: $CI_PIPELINE_SOURCE == "pipeline" || $CI_PIPELINE_SOURCE == "api"
+  cache:
+    policy: push
+  script:
+    - cd ${CI_PROJECT_DIR}
+    - INTEGRATION_BRANCH=$(cat integration_branch_file)
+    - .gitlab-ci/scripts/create_merge_request.py
+        --gitlab-url=${CI_SERVER_URL}
+        --token=${GITBOT_TOKEN}
+        --project=${LAYER_PROJECT_PATH}
+        --source-branch=${INTEGRATION_BRANCH}
+        --target-branch=${MASTER_BRANCH_LAYER}
+  needs: 
+   - job: integrate-into-layer
+     artifacts: true
+
+#yamllint:
+#  extends: .yamllint
+ 
+# --------------------------------------------------------------------------------------
+# Stage: check
+# --------------------------------------------------------------------------------------
+check:
+  extends: .infrastructure
+  stage: check
+  rules:
+    # Do not run check if the "skip build" label is set on the merge request
+    - if: $CI_MERGE_REQUEST_LABELS =~ /skip build/
+      when: never
+    # Do not integration pipeline for merge requests for integrate/gitlab-ci/ branches
+    # The integration is done from the pipeline in gitlab-ci already
+    - if: $CI_COMMIT_REF_NAME =~ /^integrate\/gitlab-ci\/.*/
+      when: never
+    - if: $CI_MERGE_REQUEST_IID
+    # Explicitly allow externally triggered pipelines in every case
+    - if: $CI_PIPELINE_SOURCE == "pipeline" || $CI_PIPELINE_SOURCE == "api"
+  needs: ["integrate-into-layer"]
+  allow_failure: true
+  script:
+    - cd ${CI_PROJECT_DIR}
+    # When running in a trigger pipeline the CII_MERGE_REQUEST_IID is not set
+    # but CI_OPEN_MERGE_REQUESTS. We use  the first of this comma separated list
+    # in this case
+    - if [ -n "${CI_MERGE_REQUEST_IID}" ];then
+        MERGE_REQUEST="${CI_MERGE_REQUEST_IID}";
+      else
+        MERGE_REQUEST="${CI_OPEN_MERGE_REQUESTS%%,*}";
+      fi
+    # The 'parent_merge_request' is passed from the trigger
+    # in case this check job is part of a gitlab-ci integration
+    # pipeline. It is only used to display the correct MR to run again
+    # in a failed check
+    - if [ -n "${parent_merge_request}" ];then
+        PARENT_MR="--parent-merge-request=${parent_merge_request}";
+      fi
+    - while read -r integration; do
+        SOURCE_BRANCH=$(echo $integration | cut -d':' -f1);
+        TARGET_PROJECT=${LAYER_PROJECT_PATH};
+        TARGET_BRANCH=$(echo $integration | cut -d':' -f3);
+        if [[ "$SOURCE_BRANCH" == "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" ]]; then
+          .gitlab-ci/scripts/check_if_layer_branch_is_up_to_date.py
+            --gitlab-url=${CI_SERVER_URL}
+            --token=${GITBOT_TOKEN}
+            --target-project=${TARGET_PROJECT}
+            --target-branch=${TARGET_BRANCH}
+            --source-project=${CI_PROJECT_PATH}
+            --recipe-name=${BB_RECIPE_NAME}
+            --merge-request=${CI_MERGE_REQUEST_IID}
+            ;
+        fi;
+      done <<< "$INTEGRATION"
+
+merge-into-layer:
+  extends: .infrastructure
+  stage: accept-merge
+  timeout: 4h
+  rules:
+     # Do not integration pipeline for merge requests for integrate/gitlab-ci/ branches
+     # The integration is done from the pipeline in gitlab-ci already
+     - if: $CI_COMMIT_REF_NAME =~ /^integrate\/gitlab-ci\/.*/
+       when: never
+     - if: $CI_COMMIT_BRANCH == $MASTER_BRANCH
+       when: always
+  script:
+    - cd ${CI_PROJECT_DIR}
+    - echo ${CI_COMMIT_REF_NAME}
+    - .gitlab-ci/scripts/accept_layer_merge_request.py
+        --gitlab-url=${CI_SERVER_URL}
+        --token=${GITBOT_TOKEN}
+        --project=${CI_PROJECT_PATH}
+        --layer-project=${LAYER_PROJECT_PATH}
+        --target-branch=${MASTER_BRANCH}
+        --layer-target-branch=${MASTER_BRANCH_LAYER}
+        --recipe-name=${BB_RECIPE_NAME}
+        --rebase
\ No newline at end of file