diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index c9019640072c9b08c7eb08bb5e0b6fcf58c54011..f0249d72a74df0b4a5ac2fd133682b38f1a2fd88 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,7 +1,6 @@
 ---
-image: registry.gitlab.inria.fr/solverstack/docker/vite
-
 stages:
+  - docker
   - pre
   - build
   - analyze
@@ -15,8 +14,9 @@ before_script:
   - git submodule update --init --recursive
 
 include:
-  - .gitlab/preliminary.yml
   - .gitlab/common.yml
+  - .gitlab/preliminary.yml
+  - .gitlab/docker.yml
   - .gitlab/build.yml
   - .gitlab/coverity.yml
   - .gitlab/sonarqube.yml
diff --git a/.gitlab/Dockerfile b/.gitlab/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..eff4b58f415b67ff80066f2b41c144731e15e5a1
--- /dev/null
+++ b/.gitlab/Dockerfile
@@ -0,0 +1,53 @@
+#
+#  @file Dockerfile
+#
+#  @copyright 2024-2024 Bordeaux INP, CNRS (LaBRI UMR 5800), Inria,
+#                       Univ. Bordeaux. All rights reserved.
+#
+#  @version 1.4.0
+#  @author Florent Pruvost
+#  @date 2024-12-03
+#
+# This docker image is used to test the package during gitlab-ci pipelines.
+# It should be stored in the gitlab's project container registry:
+# https://gitlab.inria.fr/solverstack/vite/container_registry
+#
+FROM registry.gitlab.inria.fr/solverstack/docker/analysis
+
+USER root
+
+# Vite dependencies
+RUN wget -qO- https://packages.lunarg.com/lunarg-signing-key-pub.asc | sudo tee /etc/apt/trusted.gpg.d/lunarg.asc
+RUN wget -qO /etc/apt/sources.list.d/lunarg-vulkan-noble.list http://packages.lunarg.com/vulkan/lunarg-vulkan-noble.list
+RUN apt-get -y update
+RUN apt-get -y upgrade --no-install-recommends \
+    libboost-dev \
+    libboost-graph-dev \
+    libglm-dev \
+    libglew-dev \
+    libotf2-trace-dev \
+    libqt5charts5-dev \
+    libqt5opengl5-dev \
+    libqt5svg5-dev \
+    otf2-tools \
+    qt5-qmake \
+    qtbase5-dev\
+    qttools5-dev \
+    vulkan-sdk
+
+ENV TAU_DIR=/home/gitlab/install/tau
+RUN wget http://tau.uoregon.edu/tau.tgz && \
+    tar -xzf tau.tgz && \
+    pushd tau-2.34 && \
+    ./configure && \
+    pushd src/TraceInput && \
+    make && \
+    mkdir -p $TAU_DIR/lib && \
+    cp libTAU_traceinput.a $TAU_DIR/lib && \
+    popd && \
+    cp -r include $TAU_DIR && \
+    cd $HOME
+ENV LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$TAU_DIR/lib
+ENV INCLUDE_PATH=$INCLUDE_PATH:$TAU_DIR/include
+
+USER gitlab
diff --git a/.gitlab/build.sh b/.gitlab/build.sh
index 50f559d620427273883038e01186f0244ae6041e..2d34ed0feab813adfdf05b5a978902a1e69da24a 100755
--- a/.gitlab/build.sh
+++ b/.gitlab/build.sh
@@ -5,7 +5,7 @@
 #  @copyright 2023-2024 Bordeaux INP, CNRS (LaBRI UMR 5800), Inria,
 #                       Univ. Bordeaux. All rights reserved.
 #
-#  @version 1.2.0
+#  @version 1.4.0
 #  @author Mathieu Faverge
 #  @author Florent Pruvost
 #  @date 2023-12-07
@@ -13,48 +13,7 @@
 ###
 set -ex
 
-# To be removed when OTF2 will be "correctly" installed in the Docker image
-PATH=$PATH:$OTF2_DIR/bin
-
-#
-# Build the project
-#
-if [[ "$SYSTEM" != "windows" ]]; then
-    if [[ "$SYSTEM" == "macosx" ]]; then
-        echo "macos unsupported"
-        return
-        # if brew ls --versions scotch > /dev/null; then
-        #   echo "Scotch is already installed with brew";
-        # else
-        #   echo "Start installing Scotch with brew";
-        #   brew install scotch;
-        # fi
-        # if brew ls --versions starpu > /dev/null; then
-        #   echo "Starpu is already installed with brew";
-        # else
-        #   echo "Start installing Starpu with brew";
-        #   brew install --build-from-source ~/brew-repo/starpu.rb;
-        # fi
-        # # clang is used on macosx and it is not compatible with MORSE_ENABLE_COVERAGE=ON
-        # # to avoid the Accelerate framework and get Openblas we use BLA_PREFER_PKGCONFIG
-        # # we do not have parsec installed on the macosx machine
-        # cmake -B build -S . -DVITE_CI_VERSION=${VERSION} -DVITE_CI_BRANCH=${BRANCH} \
-            #       -C .gitlab/ci-test-initial-cache.cmake \
-            #       -DMORSE_ENABLE_COVERAGE=OFF -DBLA_PREFER_PKGCONFIG=ON
-    else
-        cmake -B build -S . -DVITE_CI_VERSION=${VERSION} -DVITE_CI_BRANCH=${BRANCH} \
-              -C .gitlab/ci-test-initial-cache.cmake
-    fi
-else
-    echo "windows unsupported"
-    return
-    # on windows the mpi_f08 interface is missing, see https://www.scivision.dev/windows-mpi-msys2/
-    # default scotch in windows msys2 is int32
-    # do not use static libraries because executables are too large and the build
-    # directory can reach more than 10Go
-    # cmake -GNinja -B build -S . -DCMAKE_INSTALL_PREFIX=$PWD/install-${VERSION} \
-        #       -DBUILD_SHARED_LIBS=ON
-fi
-cmake --build build -j 4
+cmake -B build -S . -DVITE_CI_VERSION=${VERSION} -DVITE_CI_BRANCH=${BRANCH} -C .gitlab/ci-test-initial-cache.cmake
+cp build/compile_commands.json build/compile_commands-${VERSION}.json
+cmake --build build -j 4  > /dev/null
 cmake --install build
-
diff --git a/.gitlab/build.yml b/.gitlab/build.yml
index 5900cf6eaf93af85b2ebbd0fe525799da0a78a4c..06b452f45f7d81d192e78eb710881ce2909f1b64 100644
--- a/.gitlab/build.yml
+++ b/.gitlab/build.yml
@@ -1,13 +1,12 @@
 ---
 build:
   stage: build
-  tags: ["docker"]
   extends: .only-master-mr
   script:
     - bash .gitlab/build.sh | tee vite-build-${VERSION}.log
   artifacts:
     name: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
-    expire_in: 180 minutes
+    expire_in: 1 week
     untracked: true
   parallel:
     matrix:
diff --git a/.gitlab/common.yml b/.gitlab/common.yml
index b355735f652cf492c47bcee0a54262adc366550a..f248ea0c352038062c6f8ac58e2cda8cfbd7942f 100644
--- a/.gitlab/common.yml
+++ b/.gitlab/common.yml
@@ -2,6 +2,14 @@
 # This file describes the common rules for the stages
 #
 ---
+default:
+  image: $CI_REGISTRY_IMAGE
+  tags: ['ci.inria.fr', 'linux', 'small'] # gitlab instance runner (i.e. docker on linux)
+  interruptible: true
+
+variables:
+  GIT_SUBMODULE_STRATEGY: recursive
+
 # push event: executed only if the source branch is the default one on
 #   the root repository (solverstack), or on on the repository of the
 #   same name
@@ -9,7 +17,6 @@
 #   test on the main branch
 # schedule event: not executed
 .only-master:
-  interruptible: true
   rules:
     - if: ($CI_PIPELINE_SOURCE == "schedule" )
       when: never
@@ -26,7 +33,6 @@
 #   start with notest-
 # schedule event: not executed
 .only-master-mr:
-  interruptible: true
   rules:
     - if: ($CI_PIPELINE_SOURCE == "schedule" )
       when: never
@@ -42,7 +48,6 @@
 # merge request event: executed if the source branch name does not
 #   start with notest-
 .only-mr:
-  interruptible: true
   rules:
     - if: (($CI_PIPELINE_SOURCE == "merge_request_event") &&
            ($CI_MERGE_REQUEST_SOURCE_BRANCH_NAME !~ /^notest-.*$/))
diff --git a/.gitlab/coverity.yml b/.gitlab/coverity.yml
index a2d8f26f2c35d040bd5913da7b38858651947d91..514cebd868bab346695c61e3dde05e99696d299d 100644
--- a/.gitlab/coverity.yml
+++ b/.gitlab/coverity.yml
@@ -1,8 +1,6 @@
 ---
 coverity:
   stage: analyze
-  tags: ["docker"]
-  interruptible: true
   rules:
     - if: ($CI_PIPELINE_SOURCE == "schedule" )
       when: never
@@ -17,20 +15,17 @@ coverity:
   dependencies: []
   artifacts:
     name: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
-    expire_in: 180 minutes
+    expire_in: 1 week
     paths:
       - ${CI_PROJECT_NAME}.tgz
   variables:
     VERSION: plugins
   script:
-    - mkdir -p build-coverity
-    - cd build-coverity
-    - cmake -DVITE_CI_BRANCH=master -DVITE_CI_VERSION=${VERSION}
+    - cmake -B build-coverity -DVITE_CI_BRANCH=master -DVITE_CI_VERSION=${VERSION}
             -C ${CI_PROJECT_DIR}/.gitlab/ci-test-initial-cache.cmake
             ${CI_PROJECT_DIR}
-    - cov-build --dir ../cov-int make -j 4
-    - cd ..
-    - tar czvf ${CI_PROJECT_NAME}.tgz cov-int
+    - cov-build --dir cov-int/ cmake --build build-coverity -j 4
+    - tar czvf ${CI_PROJECT_NAME}.tgz cov-int/
     - curl --form token=$COVERITY_TOKEN
            --form email=mathieu.faverge@inria.fr
            --form file=@${CI_PROJECT_NAME}.tgz
diff --git a/.gitlab/docker.yml b/.gitlab/docker.yml
new file mode 100644
index 0000000000000000000000000000000000000000..c47d8fc25713261922209b573a09daba1649a316
--- /dev/null
+++ b/.gitlab/docker.yml
@@ -0,0 +1,10 @@
+---
+docker:
+  stage: docker
+  image: docker
+  when: manual
+  before_script:
+    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
+  script:
+    - docker build -f .gitlab/Dockerfile -t $CI_REGISTRY_IMAGE $PWD
+    - docker push $CI_REGISTRY_IMAGE
diff --git a/.gitlab/pages.yml b/.gitlab/pages.yml
index d0aea9f97c9a96427fafdb1e71380b389f6e222d..1552b8f39612dfa55467f15b1777f40ea3543aee 100644
--- a/.gitlab/pages.yml
+++ b/.gitlab/pages.yml
@@ -1,7 +1,6 @@
 ---
 pages:
   stage: deploy
-  tags: ["docker"]
   extends: .only-master
   dependencies: []
   artifacts:
diff --git a/.gitlab/preliminary.yml b/.gitlab/preliminary.yml
index 5c624afb11c56c2b9301896d5c182145097e39c2..8f11b3ad0294ae34d8278e655a3c6c80f74bca5e 100644
--- a/.gitlab/preliminary.yml
+++ b/.gitlab/preliminary.yml
@@ -4,7 +4,6 @@
 ---
 preliminary_checks:
   stage: pre
-  interruptible: true
   rules:
     - if: ($CI_PIPELINE_SOURCE == "merge_request_event")
   parallel:
diff --git a/.gitlab/sonarqube.yml b/.gitlab/sonarqube.yml
index 32c9a059cb7f99d68a092eb69190e6ea629eaf8f..b506272aced5e60d92377b0d7fd25571ba6194ed 100644
--- a/.gitlab/sonarqube.yml
+++ b/.gitlab/sonarqube.yml
@@ -1,8 +1,6 @@
 ---
 sonarqube:
   stage: analyze
-  tags: ["docker"]
-  interruptible: true
   rules:
     - if: ($CI_PIPELINE_SOURCE == "schedule" )
       when: never
@@ -21,7 +19,7 @@ sonarqube:
     GIT_DEPTH: "0"
   artifacts:
     name: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
-    expire_in: 180 minutes
+    expire_in: 1 week
     paths:
       - filelist.txt
       - ${CI_PROJECT_NAME}-cppcheck.xml
diff --git a/tools/analysis.sh b/tools/analysis.sh
index 6e5ed1eb5ec4f0442f0938df71e775af13ec1c1d..c5fe7b9027b427adeb029ccbdb406306cf2ff460 100755
--- a/tools/analysis.sh
+++ b/tools/analysis.sh
@@ -5,7 +5,7 @@
 #  @copyright 2008-2024 Bordeaux INP, CNRS (LaBRI UMR 5800), Inria,
 #                       Univ. Bordeaux. All rights reserved.
 #
-#  @version 1.2.0
+#  @version 1.4.0
 #  @author Mathieu Faverge
 #  @date 2024-05-22
 #
@@ -34,7 +34,12 @@ $TOOLSDIR/find_sources.sh $BUILDDIR
 #export UNDEFINITIONS="-UWIN32 -UWIN64 -U_MSC_EXTENSIONS -U_MSC_VER -U__SUNPRO_C -U__SUNPRO_CC -U__sun -Usun -U__cplusplus"
 
 # run cppcheck analysis
-cppcheck -v -f --language=c++ --platform=unix64 --enable=all --xml --xml-version=2 --suppress=missingInclude ${UNDEFINITIONS} --file-list=./filelist-c.txt 2> ${PROJECT}-cppcheck.xml
+cppcheck -v -f --language=c++ --platform=unix64 --enable=all --xml --xml-version=2 --suppress=missingIncludeSystem ${UNDEFINITIONS} --file-list=./filelist-c.txt 2> ${PROJECT}-cppcheck.xml
+
+# merge all different compile_commands.json files into one single file for sonarqube
+ls $BUILDDIR/compile_commands-*.json
+jq -s 'map(.[])' $BUILDDIR/compile_commands-*.json > ${PROJECT}-compile_commands.json
+ls ${PROJECT}-compile_commands.json
 
 # create the sonarqube config file
 cat > sonar-project.properties << EOF
@@ -63,7 +68,7 @@ sonar.cxx.gcc.encoding=UTF-8
 sonar.cxx.gcc.regex=(?<file>.*):(?<line>[0-9]+):[0-9]+:\\\x20warning:\\\x20(?<message>.*)\\\x20\\\[(?<id>.*)\\\]
 sonar.cxx.gcc.reportPaths=${PROJECT}-build*.log
 sonar.cxx.cppcheck.reportPaths=${PROJECT}-cppcheck.xml
-sonar.cxx.jsonCompilationDatabase=$BUILDDIR/compile_commands.json
+sonar.cxx.jsonCompilationDatabase=${PROJECT}-compile_commands.json
 EOF
 echo "====== sonar-project.properties ============"
 cat sonar-project.properties
diff --git a/tools/find_sources.sh b/tools/find_sources.sh
index 7e904319a0ba30ef27d39b0d6b55c8d9719dfba1..ba29fea16ed926ab9f9709d5a14d2edea06668ff 100755
--- a/tools/find_sources.sh
+++ b/tools/find_sources.sh
@@ -7,7 +7,7 @@
 #
 #  @brief Generate the filelist for the static analysis
 #
-#  @version 1.2.0
+#  @version 1.4.0
 #  @author Mathieu Faverge
 #  @date 2023-11-22
 #