From 6a363f2507d088fb4173619dd3cb5c4aab04ebd6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laurent=20P=C3=A9tr=C3=A9?= <laurent.petre@cern.ch>
Date: Wed, 20 Sep 2023 23:28:43 +0200
Subject: [PATCH] Add MR preview environments

Note the following:

* The '<root>/doc' URL has been renamed to '<root>/doc/latest' for the
  "production" environment.

* The MR pipeline might need to be triggered by a reviewer/maintainer
  due to permissions and safety concerns.
---
 .gitlab-ci.yml | 117 +++++++++++++++++++++++++++++++++++++------------
 1 file changed, 90 insertions(+), 27 deletions(-)

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 1c165c6..373accc 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,45 +1,108 @@
 stages:
-  - build
+  - test
   - deploy
 
-build:
-  stage: build
-  variables:
-    GIT_DEPTH: 1
-    PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
-  image: python:3
+variables:
+  GIT_STRATEGY: fetch
+  GIT_DEPTH: 1
+
+# Builds the static website with MkDocs. The whole sequence of command is
+# implemented into the before_script section for enhanced composability.
+.build site:
   before_script:
     - python3 -m venv pyvenv
-    - source pyvenv/bin/activate
-    - python3 -m pip install --upgrade pip
-    - python3 -m pip install -r requirements.txt
-    - deactivate
-  script:
+    - pyvenv/bin/pip install --upgrade pip
+    - pyvenv/bin/pip install -r requirements.txt
     - pyvenv/bin/mkdocs build
+  variables:
+    PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
   cache:
     paths:
-      - .cache/pip/
-      - pyvenv/
+      - .cache/pip
+      - pyvenv
   artifacts:
-    expire_in: 1w
+    expire_in: 12h
     paths:
-      - site/
+      - site
 
-deploy:
-  stage: deploy
-  rules:
-    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
-  needs:
-    - build
-  variables:
-    GIT_STRATEGY: none
-  before_script:
-    - echo ${SERVICE_ACCOUNT_PASSWORD} | base64 -d | kinit -A -f ${SERVICE_ACCOUNT_USERNAME}@CERN.CH
+# Publish the website to an EOS directory specified in EOS_FULL_PATH via the
+# SERVICE_ACCOUNT_USERNAME and SERVICE_ACCOUNT_PASSWORD credentials.
+.deploy eos:
   script:
     - dnf install -y rsync
+    - echo ${SERVICE_ACCOUNT_PASSWORD} | base64 -d | kinit -A -f ${SERVICE_ACCOUNT_USERNAME}@CERN.CH
     - >
       rsync -av --delete
       -e "ssh -o StrictHostKeyChecking=no -o GSSAPIAuthentication=yes -o GSSAPITrustDNS=yes -o GSSAPIDelegateCredentials=yes"
-      site/ ${SERVICE_ACCOUNT_USERNAME}@lxplus.cern.ch:${EOS_SITE_PATH}/
+      site/ ${SERVICE_ACCOUNT_USERNAME}@lxplus.cern.ch:${EOS_FULL_PATH}
   after_script:
     - kdestroy
+
+# Delete the website published to an EOS directory specified in EOS_FULL_PATH
+# via the SERVICE_ACCOUNT_USERNAME and SERVICE_ACCOUNT_PASSWORD credentials.
+.deploy eos:stop:
+  script:
+    - echo ${SERVICE_ACCOUNT_PASSWORD} | base64 -d | kinit -A -f ${SERVICE_ACCOUNT_USERNAME}@CERN.CH
+    - >
+      ssh -o StrictHostKeyChecking=no -o GSSAPIAuthentication=yes -o GSSAPITrustDNS=yes -o GSSAPIDelegateCredentials=yes
+      ${SERVICE_ACCOUNT_USERNAME}@lxplus.cern.ch "rm -r ${EOS_FULL_PATH}"
+  after_script:
+    - kdestroy
+
+# Run simple build check test job in a branch pipeline as long as a MR is not
+# open. Once opened, run the job only manually upon user's request.
+test:
+  extends: .build site
+  stage: test
+  rules:
+    - if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS
+      when: manual
+    - if: $CI_COMMIT_BRANCH
+  script:
+    - echo "Build done!"
+
+# Prepare and publish a preview environment for each MR. Note that it may have
+# to be triggered manually by the upstream maintainers.
+deploy preview:
+  extends:
+    - .build site
+    - .deploy eos
+  stage: deploy
+  rules:
+    - if: $CI_PIPELINE_SOURCE == 'merge_request_event'
+  environment:
+    name: preview-$CI_MERGE_REQUEST_IID
+    url: https://cmsgemonline.web.cern.ch/doc/preview-$CI_MERGE_REQUEST_IID
+    on_stop: deploy preview:stop
+  variables:
+    EOS_FULL_PATH: ${EOS_SITE_PATH}/$CI_ENVIRONMENT_NAME/
+
+# Stop the MR preview environment by making sure that the files are deleted
+# from EOS.
+deploy preview:stop:
+  extends: .deploy eos:stop
+  stage: deploy
+  rules:
+    - if: $CI_PIPELINE_SOURCE == 'merge_request_event'
+      when: manual
+      allow_failure: true
+  environment:
+    name: preview-$CI_MERGE_REQUEST_IID
+    action: stop
+  variables:
+    GIT_STRATEGY: none
+    EOS_FULL_PATH: ${EOS_SITE_PATH}/$CI_ENVIRONMENT_NAME/
+
+# Publish the latest and greatest version in a well-known URL and environment.
+deploy latest:
+  extends:
+    - .build site
+    - .deploy eos
+  stage: deploy
+  rules:
+    - if: $CI_PROJECT_NAMESPACE == 'cmsgemonline/gem-ops' && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
+  environment:
+    name: latest
+    url: https://cmsgemonline.web.cern.ch/doc/latest
+  variables:
+    EOS_FULL_PATH: ${EOS_SITE_PATH}/latest/
-- 
GitLab