diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..fac523bb8686683e9d4fb0182da30c6f3cc13c15
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,2 @@
+include:
+  - ci/gitlab-ci/yml/gitlab-ci.yml
diff --git a/Documentation/ci/gitlab-ci/gitlab-ci.rst b/Documentation/ci/gitlab-ci/gitlab-ci.rst
new file mode 100644
index 0000000000000000000000000000000000000000..a65c6375a6d2399637382a74aa5b04e34b940d8f
--- /dev/null
+++ b/Documentation/ci/gitlab-ci/gitlab-ci.rst
@@ -0,0 +1,404 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+=========================================
+Automated Testing with GitLab CI/CD
+=========================================
+
+This documentation outlines the GitLab CI/CD workflow for the Linux Kernel. The
+workflow is designed to simplify testing for developers, allowing tests to be
+run on any branch at any time, without the need for specific infrastructure.
+Tests are automatically triggered on each `git push`, with results displayed in
+the GitLab UI.
+
+.. image:: images/the-pipeline.png
+   :alt: GitLab-CI pipeline for kernel testing
+   :align: center
+
+Customizations and extensions of the pipeline are possible through the
+scenarios. Scenarios can override existing jobs, change configurations, or
+define new jobs and stages. See :ref:`extending-the-ci` section.
+
+.. note:: If you are unfamiliar with GitLab CI/CD basic concepts, please check
+   the `official documentation <https://docs.gitlab.com/ee/ci/>`_.
+
+.. only:: subproject and html
+
+   Indices
+   =======
+
+   * :ref:`genindex`
+
+Setup
+-----
+
+The GitLab CI pipeline is configured for **"out-of-the-box"** use. Pushing code to a
+GitLab repository automatically triggers the pipeline.
+
+    .. code-block:: bash
+
+      # Download the Linux kernel source code
+      git clone https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
+      # Create a repository on GitLab and add it as a remote
+      git remote add gitlab https://gitlab.yourinstance.com/your-username/your-repo.git
+      # Push the code to GitLab
+      git push gitlab
+
+.. image:: images/pipelines-on-push.png
+   :alt: Pipeline triggered on push
+   :align: center
+
+Troubleshooting
+---------------
+
+If the pipeline doesn't trigger automatically, check the following:
+
+1. **Enable CI/CD in Project Settings:**
+
+   - Go to `Settings > General > Visibility, project features, permissions`.
+   - Under `Repository`, ensure the `CI/CD` toggle is enabled.
+
+2. **Enable Container Registry:**
+
+   - Still in `Settings`, find the `Container Registry` section.
+   - Enable the `Container Registry` toggle.
+
+3. **CI Minutes and Resources:**
+
+   - If you've exhausted CI minutes or other resources on the Free Tier,
+     consider setting up a local GitLab runner (see below).
+
+Setting Up a Local GitLab Runner
+--------------------------------
+
+You can use your own machine as a runner, instead of the shared runners provided
+by your GitLab instance.
+
+1. **Generate a GitLab Runner Token:**
+
+   - Navigate to `Settings > CI/CD > Runners`.
+   - Expand the `Runners` section and click on "New project runner".
+   - Choose "Run untagged jobs" and click "Create runner".
+   - Copy the provided token.
+
+.. image:: images/new-project-runner.png
+   :alt: New project runner button
+   :align: center
+
+2. **Launch the Runner:**
+
+   - Ensure Docker is installed and your user is added to the Docker group:
+
+    .. code-block:: bash
+
+        sudo usermod -aG docker <your-user>
+
+   - Log in again to apply the changes.
+   - Set up the runner:
+
+    .. code-block:: bash
+
+     export GITLAB_RUNNER_TOKEN=<your_token>
+     export GITLAB_URL=https://gitlab.yourinstance.com  # Use this for instances other than gitlab.com
+     cd ci/gitlab-ci
+     ./bootstrap-gitlab-runner.sh
+
+
+Current Pipeline Jobs
+---------------------
+
+stage: container
+^^^^^^^^^^^^^^^^
+
+**job: debian/x86_64_build**
+
+This job prepares the container used by subsequent jobs. It starts from a base
+Debian image, installing necessary tools for building the kernel and running
+tests. The resulting image is pushed to the project registry and cached. If the
+image already exists in the registry, it won't be rebuilt.
+
+To force a rebuild, update the `FDO_DISTRIBUTION_TAG` variable in the
+`container.yml` file.
+
+stage: static-checks
+^^^^^^^^^^^^^^^^^^^^
+
+**job: checkpatch**
+
+Runs the `checkpatch.pl` script on the last `$ICI_PATCH_SERIES_SIZE` commits.
+This variable is determined by:
+
+- `ICI_PATCH_SERIES_SIZE=` The number of differing patches between target and
+  source branches for merge requests; Or
+- `ICI_PATCH_SERIES_SIZE=$KCI_PATCH_SERIES_SIZE` if `KCI_PATCH_SERIES_SIZE` is
+  set (see :ref:`how-to-set-variables` below).
+
+Defaults to 1 and raises a GitLab warning if unable to identify the number of
+commits.
+
+**job: smatch**
+
+Checks `.c` files in the last `$ICI_PATCH_SERIES_SIZE` commits. Spawns a
+"sub-job" for each architecture and configuration in `kernel-combinations.yml`.
+If a smatch database exists (see `job: smatch-db-generate` below), it reuses it.
+
+stage: build
+^^^^^^^^^^^^
+
+**job: build-kernel**
+
+Compiles the kernel. Spawns a "sub-job" for each architecture and configuration
+in `kernel-combinations.yml`. Uses `ccache` to speed up builds, with its
+database shared inside the runner or across runners if configured with S3.
+
+Raises a GitLab warning if "warning" is found in the build log.
+
+.. image:: images/job-matrix.png
+   :alt: Matrix of jobs under build-kernel
+   :align: center
+
+**job: build-docs**
+
+Builds documentation. Spawns a "sub-job" for each documentation type. Not run
+automatically; requires manual triggering.
+
+stage: cache
+^^^^^^^^^^^^
+
+**job: smatch-db-generate**
+
+Generates a smatch database for use by the `smatch` job. Not run automatically;
+requires manual triggering.
+
+.. _extending-the-ci:
+
+Extending the CI - Test Scenarios (KCI_SCENARIO)
+------------------------------------------------
+
+The pipeline offers flexibility and adaptability through the use of scenarios,
+enhancing the CI/CD process with broad customization options. Key capabilities
+include:
+
+- **Overriding Existing Jobs:** Tailor existing jobs to meet specific needs or
+  conditions.
+
+- **Changing Configurations:** Dynamically adapt job settings to suit various
+  environments or subsystem requirements.
+
+- **Defining New Jobs and Stages:** Introduce new jobs and stages for additional
+  tests, build processes, or deployment strategies.
+
+These features are particularly useful when a subsystem has distinct
+requirements. For instance, to enable testing different configurations for a
+specific architecture, running static checks with varied arguments, or
+installing specialized tools to conduct targeted tests.
+
+Writing a test scenario
+^^^^^^^^^^^^^^^^^^^^^^^
+
+The GitLab CI pipeline configuration allows for the inclusion of additional
+`.yml` files based on the `KCI_SCENARIO` variable. For example, setting
+`KCI_SCENARIO` to `media` includes `media.yml` from the `scenarios/` folder.
+
+To illustrate, building a specific architecture with a custom config can be
+achieved by overriding the `.kernel-combinations` hidden job in the
+`scenarios/my-scenario.yml` file:
+
+.. code-block:: yaml
+
+    .kernel-combinations:
+        parallel:
+            matrix:
+            - KCI_KERNEL_ARCH: "arm64"
+              KCI_DEFCONFIG: "my/custom/config1"
+              KCI_KCONFIGS_ENABLE: "CONFIG1 CONFIG2 CONFIG3"
+
+            - KCI_KERNEL_ARCH: "arm64"
+              KCI_DEFCONFIG: "my/custom/config2"
+              KCI_KCONFIGS_ENABLE: "CONFIG4 CONFIG5"
+
+This modifies builds and static checks for `arm64` with different
+configurations.
+
+To select this scenario, trigger the pipeline with KCI_SCENARIO=my-scenario. See
+:ref:`how-to-set-variables` below.
+
+Variables
+---------
+
+GitLab CI/CD supports various variables to modify pipeline behavior or for use
+in jobs.
+
+- **CI_ Prefix:** Standard GitLab CI/CD variables (see GitLab documentation).
+- **KCI_ Prefix:** Custom variables defined for kernel CI.
+- **ICI_ Prefix:** Internal variables used between scripts (not for external
+  use).
+
+.. _how-to-set-variables:
+
+How to Set Variables
+--------------------
+
+Variables can be set in several ways:
+
+- **Project Settings:** Under `CI/CD > Variables`.
+- **Pipeline UI:** When triggering a pipeline manually.
+- **Command Line:** When triggering a pipeline manually (see
+  :ref:`triggering-pipelines-from-command-line` below).
+- **YML Files:** Using the `variables` keyword.
+- **Commit Message:** For runtime variables only (see
+  :ref:`setting-variables-in-the-commit-message` below).
+
+.. image:: images/variables.png
+   :alt: Manual creation of pipeline
+   :align: center
+
+Variables Precedence
+--------------------
+
+- **Commit Message Variables:** Highest precedence if evaluated at runtime.
+- **Pipeline Variables:** Next in precedence.
+- **Project Variables:** Follow pipeline variables.
+- **YML File Variables:** Considered after the above levels.
+
+.. _setting-variables-in-the-commit-message:
+
+Setting Variables in the Commit Message
+---------------------------------------
+
+Runtime variables can be set in the commit message. Patterns like
+`KCI_VARIABLE=value` are extracted and exported to the job. To avoid including
+variables in the git history, add them after three dashes (`---`) in the commit
+message, as `git am` ignores text after this line.
+
+Example:
+
+.. code-block::
+
+    Title of my awesome commit
+
+    This is the commit message description of my awesome patch
+    ---
+    KCI_PATCH_SERIES_SIZE=4
+
+Description of Each Variable
+----------------------------
+
+**KCI_KERNEL_ARCH**
+    Defines the architecture to be used in the build-kernel and static checks
+    jobs. Usually set in the `.kernel-combinations` hidden job.
+
+**KCI_DEFCONFIG**
+    Defines the config file to be used in the build-kernel and static checks
+    jobs. Usually set in the `.kernel-combinations` hidden job.
+
+**KCI_KCONFIGS_{ENABLE,DISABLE,MODULE}**
+    Defines the extra configs to be enabled, disabled or set as a module, used
+    in the build-kernel and static checks jobs. Usually set in the
+    `.kernel-combinations` hidden job.
+
+**KCI_SCENARIO**
+    Used to select which extra scenario file to include in the pipeline. See
+    :ref:`extending-the-ci` section above. Usually set by the user at project or
+    pipeline level.
+
+**KCI_CHECKPATCH_TYPES**
+    Used in `checkpatch.pl --types "$KCI_CHECKPATCH_TYPES"` (see checkpatch
+    documentation). Its default value is defined in static-checks.yml file, and
+    can be overwritten, even in the commit message, since it is evaluated in run
+    time.
+
+**KCI_PATCH_SERIES_SIZE**
+    Used to define the size of the patch series, see `job: checkpatch` section
+    above. It is evaluated in run time, and can be set in the commit message.
+
+.. _triggering-pipelines-from-command-line:
+
+Triggering Pipelines from Command Line
+--------------------------------------
+
+Pipelines can be triggered from the command line with custom variables using the
+`GitLab CLI tool <https://docs.gitlab.com/ee/editor_extensions/gitlab_cli>`_.
+
+Example:
+
+.. code-block:: bash
+
+    glab auth login
+    glab ci run -b gitlab-draft -R https://gitlab.collabora.com/koike/linux/ --variables-env KCI_PATCH_SERIES_SIZE:4
+
+
+Debugging and Replicating Jobs Locally
+--------------------------------------
+
+When a job fails in GitLab CI/CD, it's handy to replicate the issue in the
+same environment used by the GitLab CI/CD runner. This allows for interactive
+execution of each step and the use of debugging tools to pinpoint the failure's
+root cause.
+
+Rather than repeatedly modifying scripts and running the entire pipeline for
+debugging, you can download the specific Docker image used by the job and run it
+locally.
+
+To do this, first inspect the failed job in GitLab CI/CD. Look for a message
+indicating the Docker image used, typically in this format:
+
+   Pulling docker image registry.gitlab.collabora.com/koike/linux/debian/bookworm-slim:2024-02-6-ci-test-1
+
+You can then use this image to run the job locally. For example:
+
+.. code-block:: bash
+
+   IMAGE=registry.gitlab.collabora.com/koike/linux/debian/bookworm-slim:2024-02-6-ci-test-1
+   docker pull $IMAGE
+   docker run --rm -v `pwd`:/linux -w /linux $IMAGE bash
+
+
+Suggestions
+-----------
+
+Send Pipeline Links with Your Patch
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+When submitting patches or merge requests, it's highly beneficial to include
+links to the related GitLab CI pipelines. This practice enhances the review
+process in several ways:
+
+1. **Immediate Visibility:** Reviewers can immediately see the results of
+   automated tests, making it easier to assess the patch's impact.
+
+2. **Increased Confidence:** Successful pipeline runs increase confidence in the
+   changes, demonstrating that they pass existing tests.
+
+3. **Efficient Troubleshooting:** If there are issues, pipeline links allow both
+   authors and reviewers to quickly access logs and test results, facilitating
+   faster troubleshooting and iteration.
+
+4. **Transparency:** Providing pipeline links promotes transparency in the
+   development process, making it clear how changes have been verified.
+
+To include a pipeline link in your patch or merge request, simply copy the URL
+of the pipeline from your GitLab project's CI/CD pipeline page and paste it into
+your commit description after three dashes (`---`) or as a reply to your email
+patch.
+
+Always Green Pipeline
+^^^^^^^^^^^^^^^^^^^^^
+
+Maintaining an "always green" pipeline refers to the practice of ensuring that
+the main branch's pipeline is always in a passing state. This approach has
+several advantages:
+
+1. **Reliable Main Branch:** A green pipeline indicates a stable and reliable
+   main branch, which is crucial for continuous integration practices.
+
+2. **Immediate Feedback:** Developers receive immediate feedback on their
+   changes. If a merge causes the pipeline to fail, it's a clear signal that the
+   change introduced an issue.
+
+3. **Faster Iteration:** An always green pipeline facilitates faster development
+   and iteration, as developers can confidently build on top of the latest main
+   branch without worrying about hidden failures.
+
+4. **Culture of Responsibility:** It fosters a culture of responsibility, where
+   developers are encouraged to fix broken builds promptly and avoid merging
+   changes that could disrupt the pipeline.
\ No newline at end of file
diff --git a/Documentation/ci/gitlab-ci/images/job-matrix.png b/Documentation/ci/gitlab-ci/images/job-matrix.png
new file mode 100644
index 0000000000000000000000000000000000000000..b298749cf6f4951fa840f1f25903fb51e929e88c
Binary files /dev/null and b/Documentation/ci/gitlab-ci/images/job-matrix.png differ
diff --git a/Documentation/ci/gitlab-ci/images/new-project-runner.png b/Documentation/ci/gitlab-ci/images/new-project-runner.png
new file mode 100644
index 0000000000000000000000000000000000000000..d59de9f7eeab8982a61e872824c1a69c1027c532
Binary files /dev/null and b/Documentation/ci/gitlab-ci/images/new-project-runner.png differ
diff --git a/Documentation/ci/gitlab-ci/images/pipelines-on-push.png b/Documentation/ci/gitlab-ci/images/pipelines-on-push.png
new file mode 100644
index 0000000000000000000000000000000000000000..569c1d63503cf1a21b4a8fd9d01942b4dab86e97
Binary files /dev/null and b/Documentation/ci/gitlab-ci/images/pipelines-on-push.png differ
diff --git a/Documentation/ci/gitlab-ci/images/the-pipeline.png b/Documentation/ci/gitlab-ci/images/the-pipeline.png
new file mode 100644
index 0000000000000000000000000000000000000000..169ec2d7bc1a575e2ac927f72497c2170ce6a3f3
Binary files /dev/null and b/Documentation/ci/gitlab-ci/images/the-pipeline.png differ
diff --git a/Documentation/ci/gitlab-ci/images/variables.png b/Documentation/ci/gitlab-ci/images/variables.png
new file mode 100644
index 0000000000000000000000000000000000000000..02cfe146614a8cd60498ed132d80cc65896cf0bf
Binary files /dev/null and b/Documentation/ci/gitlab-ci/images/variables.png differ
diff --git a/MAINTAINERS b/MAINTAINERS
index 9d959a6881f7090a46bc3f3c7b606e7f3234255b..5ba62c7727f0a418e163cc4ee750a143f3d976bd 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4965,6 +4965,14 @@ T:	git git://linuxtv.org/media_tree.git
 F:	Documentation/devicetree/bindings/media/i2c/chrontel,ch7322.yaml
 F:	drivers/media/cec/i2c/ch7322.c
 
+CI AUTOMATED TESTING
+M:	Helen Koike <helen.koike@collabora.com>
+L:	linux-kernel@vger.kernel.org
+S:	Maintained
+T:	git https://gitlab.collabora.com/koike/linux.git
+F:	.gitlab-ci.yml
+F:	ci/
+
 CIRRUS LOGIC AUDIO CODEC DRIVERS
 M:	James Schulman <james.schulman@cirrus.com>
 M:	David Rhodes <david.rhodes@cirrus.com>
diff --git a/ci/gitlab-ci/bootstrap-gitlab-runner.sh b/ci/gitlab-ci/bootstrap-gitlab-runner.sh
new file mode 100755
index 0000000000000000000000000000000000000000..3aa28e6fd06239d44157b596545335ec3d2edc08
--- /dev/null
+++ b/ci/gitlab-ci/bootstrap-gitlab-runner.sh
@@ -0,0 +1,54 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Copyright (C) 2024 Collabora, Helen Koike <helen.koike@collabora.com>
+
+set -eo pipefail
+
+# Define variables
+CONFIG_VOLUME="/srv/gitlab-runner/config" # Path to your GitLab Runner config
+
+# Check if RUNNER_REGISTRATION_TOKEN is set
+if [ -z "${RUNNER_REGISTRATION_TOKEN}" ]; then
+    echo "Error: RUNNER_REGISTRATION_TOKEN is not set."
+    echo "Please set the RUNNER_REGISTRATION_TOKEN environment variable and try again."
+    exit 1
+fi
+
+# Check if GITLAB_URL is set
+if [ -z "${GITLAB_URL}" ]; then
+    GITLAB_URL="https://gitlab.com/"
+    echo "Info: GITLAB_URL is not set. Using the default $GITLAB_URL"
+    echo "Please set the RUNNER_REGISTRATION_TOKEN environment variable and try again."
+fi
+
+# Check if docker-compose is installed
+if ! command -v docker-compose &> /dev/null
+then
+    echo "docker-compose could not be found. Please install it first."
+    exit 1
+fi
+
+# Start the GitLab Runner using Docker Compose
+echo "Starting GitLab Runner..."
+docker-compose up -d
+
+# Wait for a few seconds to ensure the service is up
+sleep 5
+
+# Register the GitLab Runner
+echo "Registering GitLab Runner..."
+docker run --rm -v ${CONFIG_VOLUME}:/etc/gitlab-runner gitlab/gitlab-runner register \
+  --non-interactive \
+  --url ${GITLAB_URL} \
+  --token ${RUNNER_REGISTRATION_TOKEN} \
+  --executor docker \
+  --docker-image "alpine:latest" \
+  --description "Docker Runner" \
+  --docker-privileged
+
+echo ""
+echo "INFO: To configure the number of concurrent jobs, edit the value of concurrent in ${CONFIG_VOLUME}/config.toml"
+echo "INFO: than restart the GitLab Runner using docker-compose restart"
+echo ""
+echo "GitLab Runner setup complete."
diff --git a/ci/gitlab-ci/ci-scripts/build-docs.sh b/ci/gitlab-ci/ci-scripts/build-docs.sh
new file mode 100755
index 0000000000000000000000000000000000000000..8cfa67b6f135b039c62941e352e53485d10c7948
--- /dev/null
+++ b/ci/gitlab-ci/ci-scripts/build-docs.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Copyright (C) 2024 Collabora, Helen Koike <helen.koike@collabora.com>
+
+set -exo pipefail
+
+source ci/gitlab-ci/ci-scripts/ici-functions.sh
+
+ici_get_patch_series_size
+
+# Get the list of modified files in the last $ICI_PATCH_SERIES_SIZE commits
+MODIFIED_DOC_FILES=$(git diff HEAD~$ICI_PATCH_SERIES_SIZE --name-only -- Documentation/)
+
+make -j$(nproc) "$ICI_DOC_TYPE" 2>&1 | tee output.txt
+
+mkdir -p "${CI_PROJECT_DIR}/artifacts"
+mv Documentation/output "${CI_PROJECT_DIR}/artifacts/Documentation-output"
+
+# Check if any of the MODIFIED_DOC_FILES generated a warning
+# NOTE: the alternative solution was to touch the modified files and run make
+# again, but too much warnings still appears
+for file in $MODIFIED_DOC_FILES; do
+    if grep -qi "warning" output.txt && grep -q "$file" output.txt; then
+        echo "Warning found in $file"
+        exit 101
+    fi
+done
+
+if [ -n "$ICI_UNABLE_TO_DETECT_PATCH_SERIES_SIZE" ]; then
+    # If the patch series size was not detected, exit with a warning
+    echo "The patch series size was not detected, we probably didn't check the whole series. Exiting with a warning."
+    exit 101
+fi
\ No newline at end of file
diff --git a/ci/gitlab-ci/ci-scripts/build-kernel.sh b/ci/gitlab-ci/ci-scripts/build-kernel.sh
new file mode 100755
index 0000000000000000000000000000000000000000..df410c20912e908a2c935bd1e16f35dede747d26
--- /dev/null
+++ b/ci/gitlab-ci/ci-scripts/build-kernel.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Copyright (C) 2024 Collabora, Helen Koike <helen.koike@collabora.com>
+
+set -exo pipefail
+
+source ci/gitlab-ci/ci-scripts/ici-functions.sh
+
+ici_prepare_build
+
+pushd build
+
+# compile the entire kernel
+make CF=-D__CHECK_ENDIAN__ -C "$ICI_KERNEL_DIR" O=$(pwd) -j$(nproc) 2>&1 | tee output.txt
+
+export INSTALL_PATH="${CI_PROJECT_DIR}/artifacts/kernel-install-${KCI_KERNEL_ARCH}-${KCI_DEFCONFIG}_config"
+mkdir -p "$INSTALL_PATH"
+
+# install the kernel image to artifacts/kernel-install
+make -C "$ICI_KERNEL_DIR" O=$(pwd) install INSTALL_PATH="$INSTALL_PATH"
+
+# install kernel modules to artifacts/kernel-install
+make -C "$ICI_KERNEL_DIR" O=$(pwd) modules_install INSTALL_MOD_PATH="$INSTALL_PATH"
+
+# export config as artifact
+cp .config "${CI_PROJECT_DIR}/artifacts/${KCI_KERNEL_ARCH}-${KCI_DEFCONFIG}_config"
+
+# if the compilation has warnings, exit with the warning code
+if grep -iq "warning" output.txt; then
+    exit 101
+fi
+
+popd
diff --git a/ci/gitlab-ci/ci-scripts/ici-functions.sh b/ci/gitlab-ci/ci-scripts/ici-functions.sh
new file mode 100644
index 0000000000000000000000000000000000000000..e9aae235eaddabab31b522216be9c4bbf546d989
--- /dev/null
+++ b/ci/gitlab-ci/ci-scripts/ici-functions.sh
@@ -0,0 +1,100 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Copyright (C) 2024 Collabora, Helen Koike <helen.koike@collabora.com>
+
+set -exo pipefail
+
+# internal CI bash functions
+
+# convention:
+# KCI_<VARIABLE_NAME> for variables defined by the user (outside of this script)
+# ICI_<VARIABLE_NAME> for variables defined internally for usage between scripts
+# CI_<VARIABLE_NAME> for variables defined by GitLab CI
+
+
+ici_prepare_build() {
+    BUILD_DIR="${1:-build}"
+
+    echo ""
+    echo "Architecture: $KCI_KERNEL_ARCH"
+    echo "Defconfig: $KCI_DEFCONFIG"
+    echo ""
+
+    # Get the current directory if KCI_KERNEL_DIR is not set
+    ICI_KERNEL_DIR="${KCI_KERNEL_DIR:-$(pwd)}"
+
+    cd "$ICI_KERNEL_DIR" || { echo "Kernel directory not found"; exit 1; }
+
+    # Clean up stale rebases that GitLab might not have removed when reusing a checkout dir
+    rm -rf .git/rebase-apply
+
+    if [[ "$KCI_KERNEL_ARCH" = "arm64" ]]; then
+        GCC_ARCH="aarch64-linux-gnu"
+    elif [[ "$KCI_KERNEL_ARCH" = "arm" ]]; then
+        GCC_ARCH="arm-linux-gnueabihf"
+    else
+        GCC_ARCH="x86_64-linux-gnu"
+    fi
+
+    # do not set ARCH and CROSS_COMPILE if KCI_KERNEL_ARCH is not set, useful for local run
+    if [ -n "$KCI_KERNEL_ARCH" ]; then
+        export ARCH=${KCI_KERNEL_ARCH}
+        export CROSS_COMPILE="${GCC_ARCH}-"
+    fi
+
+    mkdir -p "$BUILD_DIR"
+
+    pushd "$BUILD_DIR" || { echo "Failed to create $BUILD_DIR directory"; exit 1; }
+
+    # generate defconfig
+    make -C "$ICI_KERNEL_DIR" O=$(pwd) $(basename ${KCI_DEFCONFIG-"defconfig"})
+
+    # add extra configs from variable KCI_KCONFIGS_{ENABLE,DISABLE,MODULE}
+    for opt in $KCI_KCONFIGS_ENABLE; do
+        ../scripts/config --file .config --enable CONFIG_$opt
+    done
+    for opt in $KCI_KCONFIGS_DISABLE; do
+        ../scripts/config --file .config --disable CONFIG_$opt
+    done
+    for opt in $KCI_KCONFIGS_MODULE; do
+        ../scripts/config --file .config --module CONFIG_$opt
+    done
+
+    if [ -n "$KCI_KCONFIGS_DISABLE" ] || [ -n "$KCI_KCONFIGS_ENABLE" ] ||
+       [ -n "$KCI_KCONFIGS_MODULE" ]; then
+        # execude olddefconfig only if we changed the default config, otherwise,
+        # let it raise warnings if any
+        make -C "$ICI_KERNEL_DIR" O=$(pwd) olddefconfig
+    fi
+
+    popd
+}
+
+ici_get_patch_series_size()
+{
+    local CLONE_DEPTH
+    CLONE_DEPTH=$(git rev-list --count HEAD)
+    echo "The depth of the clone is $CLONE_DEPTH"
+
+    # If this is in the context of a merge request, calculate the patch series size comparing to the target branch
+    if [ -n "$CI_MERGE_REQUEST_IID" ]; then
+        git fetch origin "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" --depth $CLONE_DEPTH
+        ICI_PATCH_SERIES_SIZE=$(git rev-list --count origin/"$CI_MERGE_REQUEST_TARGET_BRANCH_NAME".."$CI_COMMIT_SHA")
+    # if KCI_PATCH_SERIES_SIZE is set, use it
+    elif [ -n "$KCI_PATCH_SERIES_SIZE" ]; then
+        ICI_PATCH_SERIES_SIZE="$KCI_PATCH_SERIES_SIZE"
+    else
+        ICI_PATCH_SERIES_SIZE=1
+        echo "WARNING: unable to detect the patch series size, using the default value of 1."
+        # shellcheck disable=SC2034
+        ICI_UNABLE_TO_DETECT_PATCH_SERIES_SIZE=true
+    fi
+
+    # Check if the clone depth is smaller than or equal to KCI_PATCH_SERIES_SIZE, otherwise the checkpatch.pl hangs
+    if [ "$ICI_PATCH_SERIES_SIZE" -ge "$CLONE_DEPTH" ]; then
+        echo "ERROR: the depth of the clone is $CLONE_DEPTH, smaller than or equal to the patch series size."
+        echo "Update your GitLab configuration to increase the size of the clone."
+        return 1
+    fi
+}
\ No newline at end of file
diff --git a/ci/gitlab-ci/ci-scripts/install-smatch.sh b/ci/gitlab-ci/ci-scripts/install-smatch.sh
new file mode 100755
index 0000000000000000000000000000000000000000..839cebd16283d629aaa87a05a37ff7498c9a9a2d
--- /dev/null
+++ b/ci/gitlab-ci/ci-scripts/install-smatch.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Copyright (C) 2024 Collabora, Helen Koike <helen.koike@collabora.com>
+
+set -exo pipefail
+
+pushd /
+git clone --depth 1 https://repo.or.cz/smatch.git
+pushd smatch
+make
+popd
+popd
\ No newline at end of file
diff --git a/ci/gitlab-ci/ci-scripts/parse_commit_message.sh b/ci/gitlab-ci/ci-scripts/parse_commit_message.sh
new file mode 100755
index 0000000000000000000000000000000000000000..2b1929e010543c16c9fc83cba952e8d2424fed02
--- /dev/null
+++ b/ci/gitlab-ci/ci-scripts/parse_commit_message.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Copyright (C) 2024 Collabora, Helen Koike <helen.koike@collabora.com>
+
+set -exo pipefail
+
+# Get the last commit message
+commit_message=$(git log -1 --pretty=%B)
+
+# Define a regex pattern to match KCI_VARIABLE=value
+pattern="(KCI_[A-Za-z_]+)=([A-Za-z0-9_-]+)"
+
+# Check if the commit message contains the pattern
+if [[ $commit_message =~ $pattern ]]; then
+    variable_name="${BASH_REMATCH[1]}"
+    variable_value="${BASH_REMATCH[2]}"
+    
+    # Export the variable
+    export "$variable_name=$variable_value"
+    
+    echo "Exported $variable_name=$variable_value"
+else
+    echo "No matching pattern found in the commit message."
+fi
diff --git a/ci/gitlab-ci/ci-scripts/run-checkpatch.sh b/ci/gitlab-ci/ci-scripts/run-checkpatch.sh
new file mode 100755
index 0000000000000000000000000000000000000000..ba8ae9a0b458b3c5a7f1b468924b21978c468ab4
--- /dev/null
+++ b/ci/gitlab-ci/ci-scripts/run-checkpatch.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Copyright (C) 2024 Collabora, Helen Koike <helen.koike@collabora.com>
+
+set -exo pipefail
+
+source ci/gitlab-ci/ci-scripts/ici-functions.sh
+
+ici_get_patch_series_size
+
+# Run scripts/checkpatch.pl with specified options
+scripts/checkpatch.pl --terse --types "$KCI_CHECKPATCH_TYPES" --git HEAD-"$ICI_PATCH_SERIES_SIZE"
+
+if [ -n "$ICI_UNABLE_TO_DETECT_PATCH_SERIES_SIZE" ]; then
+    # If the patch series size was not detected, exit with a warning
+    echo "The patch series size was not detected, we probably didn't check the whole series. Exiting with a warning."
+    exit 101
+fi
diff --git a/ci/gitlab-ci/ci-scripts/run-smatch.sh b/ci/gitlab-ci/ci-scripts/run-smatch.sh
new file mode 100755
index 0000000000000000000000000000000000000000..1db3038d633dd2041f9b032a76c4ef7260da723d
--- /dev/null
+++ b/ci/gitlab-ci/ci-scripts/run-smatch.sh
@@ -0,0 +1,44 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Copyright (C) 2024 Collabora, Helen Koike <helen.koike@collabora.com>
+
+set -exo pipefail
+
+source ci/gitlab-ci/ci-scripts/ici-functions.sh
+
+ls -l
+pwd
+
+# generate config file
+ici_prepare_build
+
+ici_get_patch_series_size
+
+cp build/.config .
+
+# Get a list of modified .c files in the last ICI_PATCH_SERIES_SIZE commits
+MODIFIED_C_FILES=$(git diff --name-only HEAD~$ICI_PATCH_SERIES_SIZE HEAD | grep '\.c$' || true)
+
+# Check if any .c files were modified
+if [ -z "$MODIFIED_C_FILES" ]; then
+    echo "No .c files were modified in the last $ICI_PATCH_SERIES_SIZE commits."
+else
+    echo "Running kchecker on modified .c files..."
+    mkdir -p "$CI_PROJECT_DIR"/artifacts
+fi
+
+# Run kchecker on each modified .c file
+for file in $MODIFIED_C_FILES; do
+    if [ -f "$file" ]; then
+        /smatch/smatch_scripts/kchecker "$file" | tee "$CI_PROJECT_DIR"/artifacts/smatch_warns.txt
+    else
+        echo "File not found: $file"
+    fi
+done
+
+if [ -n "$ICI_UNABLE_TO_DETECT_PATCH_SERIES_SIZE" ]; then
+    # If the patch series size was not detected, exit with a warning
+    echo "The patch series size was not detected, we probably didn't check the whole series. Exiting with a warning."
+    exit 101
+fi
\ No newline at end of file
diff --git a/ci/gitlab-ci/docker-compose.yaml b/ci/gitlab-ci/docker-compose.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..7edf8055ca3752882042ff7b79778b4b8ade78e1
--- /dev/null
+++ b/ci/gitlab-ci/docker-compose.yaml
@@ -0,0 +1,18 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Copyright (C) 2024 Collabora, Helen Koike <helen.koike@collabora.com>
+
+version: '3.8'
+
+services:
+  gitlab-runner:
+    image: gitlab/gitlab-runner:latest
+    container_name: gitlab-runner
+    restart: always
+    privileged: true
+    volumes:
+      - /srv/gitlab-runner/config:/etc/gitlab-runner
+      - /var/run/docker.sock:/var/run/docker.sock
+
+# To register the GitLab Runner, run the following command:
+# docker run --rm -it -v /srv/gitlab-runner/config:/etc/gitlab-runner gitlab/gitlab-runner register --url https://gitlab.com --token YOUR_REGISTRATION_TOKEN
diff --git a/ci/gitlab-ci/yml/build.yml b/ci/gitlab-ci/yml/build.yml
new file mode 100644
index 0000000000000000000000000000000000000000..f81410c293f351e976904ba682ddbfa690705cab
--- /dev/null
+++ b/ci/gitlab-ci/yml/build.yml
@@ -0,0 +1,43 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Copyright (C) 2024 Collabora, Helen Koike <helen.koike@collabora.com>
+
+.build:
+  extends: .use-debian/x86_64_build
+  stage: build
+
+build-kernel:
+  extends:
+    - .build
+    - .kernel-combinations
+  variables:
+    # ccache in gitlab-runner to speed up builds
+    CCACHE_BASEDIR: $CI_PROJECT_DIR
+    CCACHE_DIR: $CI_PROJECT_DIR/ccache
+    CCACHE_COMPILERCHECK: content
+  cache:
+    - key: ccache-$CI_JOB_NAME
+      paths:
+        - $CCACHE_DIR
+  before_script:
+    - export PATH="/usr/lib/ccache:$PATH"
+    - ccache --zero-stats || true
+    - ccache --show-stats || true
+  after_script:
+    - ccache --show-stats
+  script:
+    - ./ci/gitlab-ci/ci-scripts/build-kernel.sh
+
+build-docs:
+  extends:
+    - .build
+  parallel:
+    matrix:
+      - ICI_DOC_TYPE: "htmldocs"
+      # TODO: re-add pdfdocs once build errors are fixed
+      # - ICI_DOC_TYPE: "pdfdocs"
+      - ICI_DOC_TYPE: "latexdocs"
+      - ICI_DOC_TYPE: "epubdocs"
+  script:
+    - ./ci/gitlab-ci/ci-scripts/build-docs.sh
+  when: manual
\ No newline at end of file
diff --git a/ci/gitlab-ci/yml/cache.yml b/ci/gitlab-ci/yml/cache.yml
new file mode 100644
index 0000000000000000000000000000000000000000..efe4fc69b11cad699b056d890774cb7777660130
--- /dev/null
+++ b/ci/gitlab-ci/yml/cache.yml
@@ -0,0 +1,26 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Copyright (C) 2024 Collabora, Helen Koike <helen.koike@collabora.com>
+
+# Smatch db is saved to a cached folder, so it can be used by other jobs and pipelines.
+# It is set to manual so it can be run when needed
+
+.use-cache-smatch-db:
+  cache:
+    # TODO: check if this cache shouldn't be per architecture
+    - key: smatch-db
+      paths:
+        - /smatch/smatch_data
+
+smatch-db-generate:
+  stage: cache
+  extends:
+    - .kernel-combinations
+    - .use-debian/x86_64_build
+    - .use-cache-smatch-db
+  script:
+    - source ci/gitlab-ci/ci-scripts/ici-functions.sh
+    - ici_prepare_build
+    - cp build/.config .
+    - /smatch/smatch_scripts/build_kernel_data.sh
+  when: manual
\ No newline at end of file
diff --git a/ci/gitlab-ci/yml/container.yml b/ci/gitlab-ci/yml/container.yml
new file mode 100644
index 0000000000000000000000000000000000000000..3c3ba294f71bc21d0ca636b64fbe4d201c3d8d6b
--- /dev/null
+++ b/ci/gitlab-ci/yml/container.yml
@@ -0,0 +1,36 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Copyright (C) 2024 Collabora, Helen Koike <helen.koike@collabora.com>
+
+.prep-debian/x86_64_build:
+  variables:
+    FDO_DISTRIBUTION_VERSION: bookworm-slim
+    FDO_DISTRIBUTION_TAG: "2024-02-27-ci-test-1"
+
+
+debian/x86_64_build:
+  extends:
+    - ".fdo.container-build@debian"
+    - ".prep-debian/x86_64_build"
+  variables:
+    FDO_DISTRIBUTION_PACKAGES: >
+      make bc flex bison pahole mount build-essential
+      libcairo-dev libdw-dev libjson-c-dev libkmod2
+      libkmod-dev libpciaccess-dev libproc2-dev libudev-dev
+      libunwind-dev python3-docutils bc python3-ply
+      libssl-dev ccache
+      gcc-aarch64-linux-gnu binutils-aarch64-linux-gnu
+      gcc-arm-linux-gnueabihf binutils-arm-linux-gnueabihf
+      perl git kmod python3-git
+      sqlite3 libsqlite3-dev libdbd-sqlite3-perl libssl-dev libtry-tiny-perl
+      python3-sphinx imagemagick graphviz dvipng python3-venv fonts-noto-cjk
+      latexmk librsvg2-bin texlive-lang-chinese texlive-xetex
+    FDO_DISTRIBUTION_EXEC: ./ci/gitlab-ci/ci-scripts/install-smatch.sh
+  stage: container
+
+
+.use-debian/x86_64_build:
+  extends:
+    - ".fdo.distribution-image@debian"
+    - ".prep-debian/x86_64_build"
+  needs: [debian/x86_64_build]
\ No newline at end of file
diff --git a/ci/gitlab-ci/yml/gitlab-ci.yml b/ci/gitlab-ci/yml/gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..c995a5a06360a98c70baf6c48fd254eca9cb04d3
--- /dev/null
+++ b/ci/gitlab-ci/yml/gitlab-ci.yml
@@ -0,0 +1,71 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Copyright (C) 2024 Collabora, Helen Koike <helen.koike@collabora.com>
+
+workflow:
+  name: $PIPELINE_NAME
+  rules:
+    # when triggered as a multi-project pipeline for an MR
+    - if: $CI_PIPELINE_SOURCE == 'pipeline' && $PARENT_MERGE_REQUEST_IID != null && $PARENT_MERGE_REQUEST_IID != ""
+      variables:
+        PIPELINE_NAME: 'Downstream pipeline for $PARENT_PROJECT_PATH!$PARENT_MERGE_REQUEST_IID'
+    # when triggered as a multi-project pipeline
+    - if: $CI_PIPELINE_SOURCE == 'pipeline'
+      variables:
+        PIPELINE_NAME: 'Downstream pipeline for $PARENT_PROJECT_PATH'
+    # when triggered via a schedule
+    - if: $CI_PIPELINE_SOURCE == 'schedule'
+      variables:
+        PIPELINE_NAME: 'Scheduled pipeline for $ONLY_JOB_NAME'
+    # for merge requests
+    - if: $CI_MERGE_REQUEST_ID
+    # when triggered via the REST api
+    - if: $CI_PIPELINE_SOURCE == 'api'
+    # for the tip of the default branch
+    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
+    # when triggered via a trigger token
+    - if: $CI_PIPELINE_SOURCE == 'trigger'
+    # when triggered from a button press in the web interface
+    - if: $CI_PIPELINE_SOURCE == 'web'
+    # for branch tips without open MRs, ignoring special branches
+    - if: $CI_PIPELINE_SOURCE == 'push' && $CI_OPEN_MERGE_REQUESTS == null
+    # when forced via '-o ci.variable="FORCE_CI=true"' during pushing
+    - if: $FORCE_CI == 'true'
+
+variables:
+  FDO_UPSTREAM_REPO: helen.fornazier/linux   # The repo where to look for cached images
+    # ccache builds in gitlab-runner to speed up builds
+  SMATCH_DB_DIR: /smatch/smatch_data
+  # exit code of bash script on `script` will be the exit code of the job
+  FF_USE_NEW_BASH_EVAL_STRATEGY: "true"
+
+default:
+  artifacts:
+    paths:
+      - artifacts/
+    when: always
+
+include:
+  - remote: 'https://gitlab.freedesktop.org/freedesktop/ci-templates/-/raw/16bc29078de5e0a067ff84a1a199a3760d3b3811/templates/ci-fairy.yml'
+  - remote: 'https://gitlab.freedesktop.org/freedesktop/ci-templates/-/raw/16bc29078de5e0a067ff84a1a199a3760d3b3811/templates/debian.yml'
+
+  - ci/gitlab-ci/yml/kernel-combinations.yml
+  - ci/gitlab-ci/yml/container.yml
+  - ci/gitlab-ci/yml/cache.yml
+  - ci/gitlab-ci/yml/build.yml
+  - ci/gitlab-ci/yml/static-checks.yml
+  - ci/gitlab-ci/yml/scenarios/scenarios.yml
+
+before_script:
+  - source ci/gitlab-ci/ci-scripts/parse_commit_message.sh
+
+.use-debian/x86_64_build:
+  allow_failure:
+    # Code to exit with a warning
+    exit_codes: 101
+
+stages:
+  - container
+  - static-checks
+  - build
+  - cache
\ No newline at end of file
diff --git a/ci/gitlab-ci/yml/kernel-combinations.yml b/ci/gitlab-ci/yml/kernel-combinations.yml
new file mode 100644
index 0000000000000000000000000000000000000000..87f08579ffd628b3aa578376feb9e577967ecacd
--- /dev/null
+++ b/ci/gitlab-ci/yml/kernel-combinations.yml
@@ -0,0 +1,18 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Copyright (C) 2024 Collabora, Helen Koike <helen.koike@collabora.com>
+
+.kernel-combinations:
+  parallel:
+    matrix:
+      - KCI_KERNEL_ARCH: "x86_64"
+        KCI_DEFCONFIG: "x86_64_defconfig"
+        KCI_KCONFIGS_ENABLE: "PROVE_LOCKING DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT CONFIG_DEBUG_SECTION_MISMATCH"
+
+      - KCI_KERNEL_ARCH: "arm64"
+        KCI_DEFCONFIG: "defconfig"
+        KCI_KCONFIGS_ENABLE: "PROVE_LOCKING DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT CONFIG_DEBUG_SECTION_MISMATCH"
+
+      - KCI_KERNEL_ARCH: "arm"
+        KCI_DEFCONFIG: "multi_v7_defconfig"
+        KCI_KCONFIGS_ENABLE: "PROVE_LOCKING DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT CONFIG_DEBUG_SECTION_MISMATCH"
\ No newline at end of file
diff --git a/ci/gitlab-ci/yml/scenarios/file-systems.yml b/ci/gitlab-ci/yml/scenarios/file-systems.yml
new file mode 100644
index 0000000000000000000000000000000000000000..66456600a9dd309cc924cb3066766f5d1c8f6bcc
--- /dev/null
+++ b/ci/gitlab-ci/yml/scenarios/file-systems.yml
@@ -0,0 +1,21 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Copyright (C) 2024 Collabora, Helen Koike <helen.koike@collabora.com>
+
+# Write here specific configurations and extensions for the given scenario
+
+# Example - overwrite kernel combinations in the pipeline
+# .kernel-combinations:
+#   parallel:
+#     matrix:
+#       - KCI_KERNEL_ARCH: "x86_64"
+#         KCI_DEFCONFIG: "path/to/my/config/file_config"
+#         KCI_ENABLE_KCONFIGS: "CONFIG1 CONFIG2 CONFIG3 ..."
+#
+#       - KCI_KERNEL_ARCH: "arm64"
+#         KCI_DEFCONFIG: "path/to/my/config/file_config"
+#         KCI_ENABLE_KCONFIGS: "CONFIG1 CONFIG2 CONFIG3 ..."
+#
+#       - KCI_KERNEL_ARCH: "arm"
+#         KCI_DEFCONFIG: "path/to/my/config/file_config"
+#         KCI_ENABLE_KCONFIGS: "CONFIG1 CONFIG2 CONFIG3 ..."
\ No newline at end of file
diff --git a/ci/gitlab-ci/yml/scenarios/media.yml b/ci/gitlab-ci/yml/scenarios/media.yml
new file mode 100644
index 0000000000000000000000000000000000000000..66456600a9dd309cc924cb3066766f5d1c8f6bcc
--- /dev/null
+++ b/ci/gitlab-ci/yml/scenarios/media.yml
@@ -0,0 +1,21 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Copyright (C) 2024 Collabora, Helen Koike <helen.koike@collabora.com>
+
+# Write here specific configurations and extensions for the given scenario
+
+# Example - overwrite kernel combinations in the pipeline
+# .kernel-combinations:
+#   parallel:
+#     matrix:
+#       - KCI_KERNEL_ARCH: "x86_64"
+#         KCI_DEFCONFIG: "path/to/my/config/file_config"
+#         KCI_ENABLE_KCONFIGS: "CONFIG1 CONFIG2 CONFIG3 ..."
+#
+#       - KCI_KERNEL_ARCH: "arm64"
+#         KCI_DEFCONFIG: "path/to/my/config/file_config"
+#         KCI_ENABLE_KCONFIGS: "CONFIG1 CONFIG2 CONFIG3 ..."
+#
+#       - KCI_KERNEL_ARCH: "arm"
+#         KCI_DEFCONFIG: "path/to/my/config/file_config"
+#         KCI_ENABLE_KCONFIGS: "CONFIG1 CONFIG2 CONFIG3 ..."
\ No newline at end of file
diff --git a/ci/gitlab-ci/yml/scenarios/network.yml b/ci/gitlab-ci/yml/scenarios/network.yml
new file mode 100644
index 0000000000000000000000000000000000000000..66456600a9dd309cc924cb3066766f5d1c8f6bcc
--- /dev/null
+++ b/ci/gitlab-ci/yml/scenarios/network.yml
@@ -0,0 +1,21 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Copyright (C) 2024 Collabora, Helen Koike <helen.koike@collabora.com>
+
+# Write here specific configurations and extensions for the given scenario
+
+# Example - overwrite kernel combinations in the pipeline
+# .kernel-combinations:
+#   parallel:
+#     matrix:
+#       - KCI_KERNEL_ARCH: "x86_64"
+#         KCI_DEFCONFIG: "path/to/my/config/file_config"
+#         KCI_ENABLE_KCONFIGS: "CONFIG1 CONFIG2 CONFIG3 ..."
+#
+#       - KCI_KERNEL_ARCH: "arm64"
+#         KCI_DEFCONFIG: "path/to/my/config/file_config"
+#         KCI_ENABLE_KCONFIGS: "CONFIG1 CONFIG2 CONFIG3 ..."
+#
+#       - KCI_KERNEL_ARCH: "arm"
+#         KCI_DEFCONFIG: "path/to/my/config/file_config"
+#         KCI_ENABLE_KCONFIGS: "CONFIG1 CONFIG2 CONFIG3 ..."
\ No newline at end of file
diff --git a/ci/gitlab-ci/yml/scenarios/scenarios.yml b/ci/gitlab-ci/yml/scenarios/scenarios.yml
new file mode 100644
index 0000000000000000000000000000000000000000..11598c3b6f2a9d5d8a69635e07a079c0c5064aab
--- /dev/null
+++ b/ci/gitlab-ci/yml/scenarios/scenarios.yml
@@ -0,0 +1,12 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Copyright (C) 2024 Collabora, Helen Koike <helen.koike@collabora.com>
+
+# Extend the CI by including a test scenario here. The scenario will be
+# activated if KCI_SCENARIO is set to the scenario name. KCI_SCENARIO can be
+# defined in the gitlab-ci.yml file, or through GitLab UI.
+
+include:
+  - local: 'ci/gitlab-ci/yml/scenarios/$KCI_SCENARIO.yml'
+    rules:
+      - if: '$KCI_SCENARIO'
\ No newline at end of file
diff --git a/ci/gitlab-ci/yml/static-checks.yml b/ci/gitlab-ci/yml/static-checks.yml
new file mode 100644
index 0000000000000000000000000000000000000000..55f9eafe2b9a779241cf4e76b9121e8fc087cf6b
--- /dev/null
+++ b/ci/gitlab-ci/yml/static-checks.yml
@@ -0,0 +1,23 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Copyright (C) 2024 Collabora, Helen Koike <helen.koike@collabora.com>
+
+.static-checks:
+  stage: static-checks
+  extends:
+    - .use-debian/x86_64_build
+
+checkpatch:
+  extends: .static-checks
+  script:
+    - ci/gitlab-ci/ci-scripts/run-checkpatch.sh
+  variables:
+    KCI_CHECKPATCH_TYPES: "BAD_SIGN_OFF,BAD_STABLE_ADDRESS_STYLE,COMMIT_COMMENT_SYMBOL,COMMIT_MESSAGE,EMAIL_SUBJECT,FROM_SIGN_OFF_MISMATCH,MISSING_SIGN_OFF,NO_AUTHOR_SIGN_OFF,DIFF_IN_COMMIT_MSG,GERRIT_CHANGE_ID,GIT_COMMIT_ID,UNKNOWN_COMMIT_ID,CODE_INDENT,BIT_MACRO,DOS_LINE_ENDINGS"
+
+smatch:
+  extends:
+    - .static-checks
+    - .kernel-combinations
+    - .use-cache-smatch-db
+  script:
+    - ci/gitlab-ci/ci-scripts/run-smatch.sh
\ No newline at end of file