diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 589511d6102cb7ce1afb56e5c875ad4a634c7d85..cc617b2a303c3a009d27e5af2a8b3cdb6bd030fc 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -43,4 +43,60 @@ test_python310:
 
 test_python311:
   extends: .test
+  image: python:3.11
+
+
+.build_python:
+  only:
+    - tags
+  except:
+    - branches
+  stage: build
+  before_script:
+    - pip install --break-system-packages --upgrade Cython setuptools pip repairwheel doctor-wheel
+    - pip install --break-system-packages -r requirements.txt
+  script:
+    - python setup.py bdist_wheel
+    - repairwheel dist/*.whl -o .
+    - doctor-wheel *.whl
+  after_script:
+    - pip install twine
+    - TWINE_PASSWORD=${CI_JOB_TOKEN} TWINE_USERNAME=gitlab-ci-token python3 -m twine upload --repository-url ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/pypi *.whl
+
+
+build_python35:
+  extends: .build_python
+  image: python:3.5
+  before_script:
+    - pip install --upgrade Cython setuptools pip repairwheel doctor-wheel
+    - pip install -r requirements.txt
+
+
+build_python36:
+  extends: .build_python
+  image: python:3.6
+  before_script:
+    - pip install --upgrade Cython setuptools pip repairwheel doctor-wheel
+    - pip install -r requirements.txt
+
+build_python37:
+  extends: .build_python
+  image: python:3.7
+
+
+build_python38:
+  extends: .build_python
+  image: python:3.8
+
+
+build_python39:
+  extends: .build_python
+  image: python:3.9
+
+build_python310:
+  extends: .build_python
+  image: python:3.10
+
+build_python311:
+  extends: .build_python
   image: python:3.11
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
index 4700652c0eaa5ed4a31a3439b24aaf55b9e1aeff..5c8faf96594f4483362e5f1530b576fadc15abdd 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,4 +1,3 @@
 Cython
-mako==1.1.0
-satella==2.20.0
-MarkupSafe==1.1.1
+satella>=2.20.0
+MarkupSafe>=1.1.1