diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index e3a7752f84d870b8cf583009b805b6d5ae20c420..6083b47df1f381496885bfe563dc3b83c1c56c74 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -3,7 +3,9 @@
 
 stages:
   - tests
+  - distrib
   - compatibility
+  - release
 
 ################################################################################
 ### DEFAULT JOB PARAMETERS
@@ -18,22 +20,6 @@ variables:
   DEFAULT: "master"
   OCAML: "4.14"
 
-################################################################################
-### ONLY/EXCEPT TEMPLATES
-
-.build_template: &manual_when_not_special_pipeline
-  except:
-    refs:
-      - schedules
-    variables:
-      - $RELEASE == "yes"
-  when: manual
-
-.build_template: &when_schedules
-  only:
-    refs:
-      - schedules
-
 ################################################################################
 ### TESTS
 
@@ -42,15 +28,18 @@ build-and-test:
   script:
     - ./nix/ci.sh
 
+################################################################################
+### Distrib
+
 check-headers:
-  stage: tests
+  stage: distrib
   variables:
     CI_MODE: "check-headers"
   script:
     - ./nix/ci.sh
 
 lint:
-  stage: tests
+  stage: distrib
   variables:
     CI_MODE: "lint"
   script:
@@ -59,63 +48,41 @@ lint:
 ################################################################################
 ### COMPATIBILITY
 
-.build_template: &opam_pin_template
+.build_template: &opam_template
+  tags: [docker]
+  image: "ocaml/opam:ubuntu-lts-ocaml-$OCAML"
   stage: compatibility
-  image: 'ocaml/opam:ubuntu-20.04-ocaml-$OCAML'
+  variables:
+    CI_MODE: "check-opam"
+    DEFAULT: "plugin-release-script"
   script:
-    - sudo apt update
-    - opam pin -n --dev frama-c
-    - opam pin . -n -k path
-    - opam depext frama-c-metacsl --with-test
-    - opam install --jobs 2 frama-c-metacsl --with-test --with-doc
-    - frama-c -meta-h
-  timeout: 2h
-  tags:
-    - docker
-
-opam-pin:
-  <<: *opam_pin_template
-  <<: *manual_when_not_special_pipeline
-
-opam-pin-nightly:
-  <<: *opam_pin_template
-  <<: *when_schedules
-
-.build_template: &opam_pin_minimal_template
-  stage: compatibility
-  image: 'ocaml/opam:ubuntu-20.04-ocaml-$OCAML'
+    - ./nix/ci.sh
+
+check-opam:
+  <<: *opam_template
+  except:
+    - schedules
+  when: manual
+
+check-opam-nightly:
+  <<: *opam_template
+  only:
+    - schedules
+
+################################################################################
+### RELEASE
+
+release:
+  stage: release
+  needs:
+    - check-opam
   variables:
-    OPAMDOWNLOADJOBS: "1"
-    OPAMERRLOGLEN: "0"
-    OPAMSOLVERTIMEOUT: "500"
-    OPAMPRECISETRACKING: "1"
+    CI_MODE: "release"
+    PLUGIN_FULL_NAME: "MetAcsl"
+    REPO: "meta"
+    RELEASE_OPT: "--assume-yes"
+    DEFAULT: "plugin-release-script"
   script:
-    - sudo ln -f /usr/bin/opam-2.1 /usr/bin/opam
-    - opam --version
-    - opam init --reinit -ni
-    - sudo apt update
-    - export OPAMCRITERIA="-removed,-count[avoid-version,changed],-count[version-lag,request],-count[version-lag,changed],-count[missing-depexts,changed],-changed"
-    - export OPAMFIXUPCRITERIA="-removed,-count[avoid-version,changed],-count[version-lag,request],-count[version-lag,changed],-count[missing-depexts,changed],-changed"
-    - export OPAMUPGRADECRITERIA="-removed,-count[avoid-version,changed],-count[version-lag,request],-count[version-lag,changed],-count[missing-depexts,changed],-changed"
-    - opam pin -n --dev frama-c
-    - opam pin . -n -k path
-    - opam update --depexts
-    - opam depext --jobs 2 frama-c-metacsl
-    - export OPAMCRITERIA="+removed,+count[version-lag,solution]"
-    - export OPAMFIXUPCRITERIA="+removed,+count[version-lag,solution]"
-    - export OPAMUPGRADECRITERIA="+removed,+count[version-lag,solution]"
-    - export OPAMEXTERNALSOLVER="builtin-0install"
-    - opam update --depexts
-    - opam reinstall --jobs 2 frama-c-metacsl
-    - frama-c -meta-h
-  timeout: 2h
-  tags:
-    - docker
-
-opam-pin-minimal:
-  <<: *opam_pin_minimal_template
-  <<: *manual_when_not_special_pipeline
-
-opam-pin-minimal-nightly:
-  <<: *opam_pin_minimal_template
-  <<: *when_schedules
+    - ls -la
+    - ./nix/ci.sh
+  when: manual
diff --git a/frama-c-metacsl.opam b/frama-c-metacsl.opam
index 259f42726246cc6b44d9c9670dfd8e480c3e43da..905cb7e0902243f277f7c05b17331170e7288152 100644
--- a/frama-c-metacsl.opam
+++ b/frama-c-metacsl.opam
@@ -36,7 +36,7 @@ build: [
 ]
 name: "frama-c-metacsl"
 synopsis: "MetAcsl plugin of Frama-C for writing pervasives properties"
-version: "0.6+dev"
+version: "0.7"
 description:"""
 MetAcsl let users write properties that need to be checked at particular
 contexts (e.g. each time a location is written to inside a given set
diff --git a/frama-c-metacsl.opam.template b/frama-c-metacsl.opam.template
index bebd53461f4ece93b6fbd34e2f731c07f277d684..19f34626dee931ded33eefe59b35dc24a2afa856 100644
--- a/frama-c-metacsl.opam.template
+++ b/frama-c-metacsl.opam.template
@@ -1,6 +1,6 @@
 name: "frama-c-metacsl"
 synopsis: "MetAcsl plugin of Frama-C for writing pervasives properties"
-version: "0.6+dev"
+version: "0.7"
 description:"""
 MetAcsl let users write properties that need to be checked at particular
 contexts (e.g. each time a location is written to inside a given set
diff --git a/nix/ci.sh b/nix/ci.sh
index 5bad402390811398889ffe9e1ee00b447fe57d75..f30479adc32b31dea506998922830e1d0b2f4600 100755
--- a/nix/ci.sh
+++ b/nix/ci.sh
@@ -34,7 +34,7 @@ trap cleanup EXIT
 
 mkdir -p $TMP_DIR/frama-ci
 frama_ci_repo="$(readlink -f $TMP_DIR/frama-ci)"
-frama_ci_url="git@git.frama-c.com:frama-c/Frama-CI.git"
+frama_ci_url=${FRAMA_CI_LOCAL:-"https://git-token:${TOKEN_FOR_API}@git.frama-c.com/frama-c/Frama-CI.git"}
 frama_ci_branch="$(get_matching_branch "$frama_ci_url")"
 echo "using branch $frama_ci_branch of Frama-CI repo at $frama_ci_repo"
 git clone --depth=1 --branch="$frama_ci_branch" "$frama_ci_url" "$frama_ci_repo"
diff --git a/nix/pkgs.nix b/nix/pkgs.nix
index ea13271156aab0801ead2937021d5da1270eb557..6120386b14cf910ee771f060e0283e702c78962e 100644
--- a/nix/pkgs.nix
+++ b/nix/pkgs.nix
@@ -10,6 +10,13 @@ let
         then value.overrideScope ocamlOverlay
         else value
     ) super.ocaml-ng;
+    release = self.callPackage ./release.nix {
+      git = pkgs.git;
+      jq = pkgs.jq;
+      curl = pkgs.curl;
+      git-lfs = pkgs.git-lfs;
+      opam = pkgs.opam;
+    };
   };
   pkgs = (import (frama-c-repo + "/nix/pkgs.nix")).appendOverlays [ overlay ];
 in
diff --git a/nix/release.nix b/nix/release.nix
new file mode 100644
index 0000000000000000000000000000000000000000..c2c0bbd74e54a4b4994e00e5e2a1f3123c599eef
--- /dev/null
+++ b/nix/release.nix
@@ -0,0 +1,18 @@
+{
+  stdenv,
+  curl,
+  git,
+  git-lfs,
+  jq,
+  opam
+}:
+stdenv.mkDerivation rec {
+  name = "release";
+  buildInputs = [
+    curl
+    git
+    git-lfs
+    jq
+    opam
+  ];
+}