diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 6eb365268cc6c07f72705cbc2403c9e51a188944..99fe5d5fbd449e8da58edc5e1884cc9003419aad 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -33,3 +33,11 @@ tests (arch):
 tests:
   script:
     - tox -p
+
+publish:
+  rules:
+    - if: $CI_COMMIT_TAG
+  variables:
+    TWINE_REPOSITORY: testpypi
+  script:
+    - tox -e publish
diff --git a/tox.ini b/tox.ini
index 4b4dc318e767dbcbc03b39c01419abab33cc6b33..6cfbcbc56d60e8deca2df06910f58949b0b5690e 100644
--- a/tox.ini
+++ b/tox.ini
@@ -41,6 +41,20 @@ deps = pre-commit
 skip_install = True
 commands = pre-commit run --all-files
 
+[testenv:publish]
+deps =
+    build
+    twine
+skip_install = True
+passenv =
+    TWINE_REPOSITORY
+    TWINE_USERNAME
+    TWINE_PASSWORD
+commands =
+    pyproject-build
+    twine upload dist/*
+
+# Tool settings
 [pytest]
 testpaths = ogstools
 xfail_strict = true