diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 859594b5a7fc1155b7ebd38d6140dfb69e2e7588..38364947a0699f5039985c48ead904d0d9004cb8 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -8,8 +8,20 @@ default:
   # Try to use only one job per stage. 
   # Stupid GitLab fails to load the cache for second jobs.
   cache: # Global `cache`.
+    key: 'python-env'
     paths:
-      - g2p-env-$CI_PIPELINE_ID
+      - g2p-env-$CI_PIPELINE_ID/
+
+  before_script:
+    - apt-get -qq update && apt-get -qq install -y gcc gfortran libblas-dev liblapack-dev
+    - source g2p-env-$CI_PIPELINE_ID/bin/activate
+    - pip list
+    - ENV_PATH=$(python3 -c "import sysconfig; print(sysconfig.get_path('platlib'))")
+    #- ENV_PATH=$(python3 -m site --user-site)
+    - LIBDIR=$(python3 -c "import sysconfig; print(sysconfig.get_config_var('LIBDIR'))")
+    - echo $ENV_PATH
+    - echo $LIBDIR
+    - ls
 
   artifacts:
     reports:
@@ -18,7 +30,7 @@ default:
         path: coverage.xml
     paths:
       - logs/execution.log
-      - dist/*
+      - dist/
 
   after_script: # Global `after_script`.
     - ls g2p-env-$CI_PIPELINE_ID
@@ -28,31 +40,56 @@ variables:
   PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
 
 stages:
+  - startup
+  - build
   - install_and_test
   - release 
 
-# Changes (e.g. apt install, pip install) do not persist across different GitLab CI jobs.
-# => Consolidate everything in GitLab CI into a single job, because the design is dumb.
-# => Since we only have one job, and GitLab Pages requires the job to be called `pages` for it to work, we now call this job `pages`.
-install_and_test:
-  stage: install_and_test
+# python virtual environment into cache
+default_venv:
+  stage: startup
   rules:
     - if: $CI_COMMIT_TAG
       when: never
-    - if: $CI_COMMIT_REF_PROTECTED == "false" && $CI_PIPELINE_SOURCE == "push"
-  before_script: # Overrides global `before_script`.
-    - echo "Hello, $GITLAB_USER_LOGIN!"
-    - python -V  # Print out python version for debugging.
+    - if: $CI_PIPELINE_SOURCE == "push"
+  before_script:
+    - uname -s # get system info
+    - uname -v
+    - uname -m
+    - uname -o
+    - echo "Hello ${GITLAB_USER_NAME} !"
+    - echo "This is job ${CI_JOB_ID}"
+  script:
+    - echo "Creating virtual environment..."
+    - pip install -U virtualenv
+    - python3 -m venv g2p-env-$CI_PIPELINE_ID
+    - ls
     - pwd
-    # Install everything.
-    - apt-get -qq update && apt-get -qq install -y gcc gfortran libblas-dev liblapack-dev libopenmpi-dev openmpi-bin
-    - python -m venv g2p-env-$CI_PIPELINE_ID
     - source g2p-env-$CI_PIPELINE_ID/bin/activate
+    - python3 -m pip install --upgrade pip
     - pip install -U pip build pytest pytest-cov coverage twine 
+    - pip list
+
+# build on mpcdf server
+default_build:
+  stage: build
+  rules:
+    - if: $CI_COMMIT_TAG
+      when: never
+    - if: $CI_PIPELINE_SOURCE == "push"
+  needs: ['default_venv']
+  script:
+    - python3 -m build # build gvec_to_python (.whl) 
+
+install_and_test:
+  stage: install_and_test
+  rules:
+    - if: $CI_COMMIT_TAG
+      when: never
+    - if: $CI_COMMIT_REF_PROTECTED == "false" && $CI_PIPELINE_SOURCE == "push"
+  needs: ['default_build']
   script:
-    # Build: build python package, install package.
-    - echo "Run python build:"
-    - python -m build
+    # install package
     - ls -lah dist
     - echo "Install dist:"
     - pip install -U dist/gvec_to_python-*.whl --force-reinstall
@@ -77,7 +114,7 @@ deploy:
     - if: $CI_COMMIT_TAG
       when: never
     - if: $CI_COMMIT_REF_NAME == "master" 
-  needs: ["install_and_test"]
+  needs: ["default_build"]
   script:
     - twine upload dist/*
 
@@ -119,18 +156,4 @@ release_job:
           url: 'https://pypi.org/project/gvec_to_python/'
 
 
-# OLD, TO BE DELETED
-# deploy:
-#   stage: release
-#   rules:
-#     - if: $CI_COMMIT_TAG
-#       when: never
-#     - if: $CI_COMMIT_REF_NAME == "master" 
-#   before_script:
-#     - apt-get -qq update && apt-get -qq install -y gcc gfortran libblas-dev liblapack-dev libopenmpi-dev openmpi-bin
-#     - pip install -U pip build twine 
-#   script:
-#     - python -m build
-#     - ls -lah dist
-#     - twine upload dist/*