diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index ae695f2c2a0a21e74e18a6b96791865b76f67216..30b25fbe7ff168761d7dd7a5926d901be56c666f 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -3,6 +3,8 @@ stages: [ nix-cache, lint, build, tests ]
 variables:
   NIX_CI_CACHE_PUB_KEY: "ci_nix_store:PrLrhCBBIPW9ZQIyDJ4q+BEcT9JUDxa5pQawc5w8pKU="
   NIX_CI_CACHE_PRIV_KEY: "ci_nix_store:PNgPTN7SJq+jXFXNIkg/SZ9dwwvJxghxRn1wU7dpezg+suuEIEEg9b1lAjIMnir4ERxP0lQPFrmlBrBznDykpQ=="
+  NIX_STORE_ARTIFACTS_PATH: ".ci_nix_artifacts"
+  NIX_STORE_CACHE_PATH: ".ci_nix_cache"
 
 default:
   image: nixos/nix:2.20.1
@@ -11,44 +13,47 @@ default:
 
   before_script:
    - echo "experimental-features = nix-command flakes" >> /etc/nix/nix.conf
-   - echo "substituters = file://$(pwd)/.ci_nix_artifacts file://$(pwd)/.ci_nix_cache https://cache.nixos.org" >> /etc/nix/nix.conf
+   - echo "substituters = file://$(pwd)/${NIX_STORE_ARTIFACTS_PATH} file://$(pwd)/${NIX_STORE_CACHE_PATH} https://cache.nixos.org" >> /etc/nix/nix.conf
    - echo "trusted-public-keys = ${NIX_CI_CACHE_PUB_KEY} cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=" >> /etc/nix/nix.conf
 
    # Since the cache is not guaranteed to be available, it is preferable to build the dependencies for each job (which is no-op if the cache is available)
    - nix build --print-build-logs .#theories.inputDerivation
    - nix build --print-build-logs .#frontend.inputDerivation
 
-  artifacts:
-    paths: [ .ci_nix_artifacts ]
-
   cache:
     key:
       files: [ flake.lock, flake.nix ]
-    paths: [ .ci_nix_cache ]
+    paths: [ "${NIX_STORE_CACHE_PATH}" ]
+
+
+.build_to_cache:
+  script:
+   - nix build --print-build-logs ${NIX_DERIVATION}
+   - nix store sign --key-file <(echo "${NIX_CI_CACHE_PRIV_KEY}") --recursive ${NIX_DERIVATION}
+   - nix copy --to "file://$(pwd)/${NIX_STORE_CACHE_PATH}" ${NIX_DERIVATION}
 
+.build_to_artifacts:
+  artifacts:
+    paths: [ "${NIX_STORE_ARTIFACTS_PATH}" ]
 
-.build_and_push_to_nix_store: &build_and_push_to_nix_store
- - nix build --print-build-logs ${NIX_DERIVATION}
- - nix store sign --key-file <(echo ${NIX_CI_CACHE_PRIV_KEY}) --recursive ${NIX_DERIVATION}
- - nix copy ${NIX_DERIVATION} --to file://$(pwd)/.ci_nix_cache
+  script:
+   - !reference [.build_to_cache, script]
 
- # To avoid generating large 'artifacts' without cluttering the 'cache', an overlay on top of the nix store must be used.
- # So, one of the following solutions can be used:
- #  1. Using the `local-overlay` feature, but still in RFC (https://github.com/NixOS/rfcs/pull/152)
- #  2. Using OverlayFS, but SYS_ADMIN capability is required
- #  3. Moving files around, which is not the best way to do
- - mkdir -p ${NIX_STORE_PATH}/nar
- - nix path-info ${NIX_DERIVATION} | xargs -r basename -a | cut -d'-' -f1 | xargs -r printf -- '.ci_nix_cache/%s.narinfo\0' | xargs -r0 mv -v -t ${NIX_STORE_PATH} || true
- - find ${NIX_STORE_PATH} -name "*.narinfo" -type f -print0 | xargs -r0 grep -oPh "(?<=URL:\ ).*" | xargs -r printf -- '.ci_nix_cache/%s\0' | xargs -r0 mv -v -t ${NIX_STORE_PATH}/nar || true
+   # To avoid generating large `artifacts` without cluttering the `cache`, an overlay on top of the nix store must be used.
+   # So, one of the following solutions can be used:
+   #  1. Using the `local-overlay` feature, but still in RFC (https://github.com/NixOS/rfcs/pull/152)
+   #  2. Using OverlayFS, but SYS_ADMIN capability is required
+   #  3. Moving files around, which is not the best way to do
+   - mkdir -p "${NIX_STORE_ARTIFACTS_PATH}/nar"
+   - nix path-info ${NIX_DERIVATION} | xargs -r basename -a | cut -d'-' -f1 | xargs -r printf -- "${NIX_STORE_CACHE_PATH}/%s.narinfo\0" | xargs -r0 mv -v -t "${NIX_STORE_ARTIFACTS_PATH}" || true
+   - find "${NIX_STORE_ARTIFACTS_PATH}" -name "*.narinfo" -type f -print0 | xargs -r0 grep -oPh "(?<=URL:\ ).*" | xargs -r printf -- "${NIX_STORE_CACHE_PATH}/%s\0" | xargs -r0 mv -v -t ${NIX_STORE_ARTIFACTS_PATH}/nar || true
 
 
 nix-cache:
   stage: nix-cache
   variables:
     NIX_DERIVATION: .#theories.inputDerivation .#frontend.inputDerivation nixpkgs#gnumake
-    NIX_STORE_PATH: .ci_nix_cache
-  script:
-    - *build_and_push_to_nix_store
+  extends: .build_to_cache
 
 clippy:
   stage: lint
@@ -67,28 +72,28 @@ theories:
   stage: build
   variables:
     NIX_DERIVATION: .#theories
-    NIX_STORE_PATH: .ci_nix_artifacts
-  script:
-   - *build_and_push_to_nix_store
+  extends: .build_to_artifacts
 
 frontend:
   stage: build
   variables:
     NIX_DERIVATION: .#frontend
-    NIX_STORE_PATH: .ci_nix_artifacts
-  script:
-   - *build_and_push_to_nix_store
+  extends: .build_to_artifacts
 
 tests:
   stage: tests
   script:
+   - export DIR=$(nix run nixpkgs#gnumake -- -np | grep -oPh "(?<=RUST_SRC = ).*")
+   - mkdir .ci_tmp
+   - echo ${DIR} | xargs -r -n 1 | cut -d'/' -f1 | uniq | xargs -r mv -v -t .ci_tmp
+   - cd .ci_tmp
+   - echo "(lang dune 3.8)" >| dune-project
+   - echo "(using coq 0.8)" >> dune-project
    - |
-     echo "(lang dune 3.8)" >| case_studies/dune-project
-     echo "(using coq 0.8)" >> case_studies/dune-project
-     for folder in $(nix run nixpkgs#gnumake -- -np | grep RUST_SRC | cut -d' ' -f3-)
+     for folder in ${DIR}
      do
          cd $folder
          nix shell -c cargo refinedrust
          cd -
-         nix shell -c dune build --display=short --root=case_studies
+         nix shell -c dune build --display=short --root=.
      done