From 9b1450be28cb9eda671b022ae27f0b04703c3920 Mon Sep 17 00:00:00 2001
From: Sotiris Tsepelakis <sotirios.tsepelakis@tuwien.ac.at>
Date: Fri, 17 Jan 2025 13:54:46 +0100
Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=80=20CI/CD:=20create=20pipeline?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* deployment to staging and production environments
* set pull policy to always for services, as major versions are pinned
---
 .gitlab-ci.yml          | 26 +++++++++++++++++++
 .gitlab-ci/deploy.sh    | 57 +++++++++++++++++++++++++++++++++++++++++
 docker-compose.base.yml |  1 +
 docker-compose.yml      |  1 +
 scripts/dump-vars.sh    | 28 ++++++++++++++++++++
 5 files changed, 113 insertions(+)
 create mode 100644 .gitlab-ci.yml
 create mode 100755 .gitlab-ci/deploy.sh
 create mode 100755 scripts/dump-vars.sh

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000..b656386
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,26 @@
+# GitLab CI/CD configuration
+
+stages:
+  - staging
+  - production
+
+deploy-staging:
+  stage: staging
+  environment:
+    name: staging
+    url: ${DEPLOYMENT_HOST}
+  script:
+    - ./.gitlab-ci/deploy.sh
+  rules:
+    - if: '$CI_COMMIT_BRANCH == "main"'
+
+deploy-production:
+  stage: production
+  environment:
+    name: production
+    url: ${DEPLOYMENT_HOST}
+  script:
+    - ./.gitlab-ci/deploy.sh
+  rules:
+    - if: '$CI_COMMIT_BRANCH == "main"'
+      when: manual
diff --git a/.gitlab-ci/deploy.sh b/.gitlab-ci/deploy.sh
new file mode 100755
index 0000000..e18ef3c
--- /dev/null
+++ b/.gitlab-ci/deploy.sh
@@ -0,0 +1,57 @@
+#!/bin/bash
+#
+# Deployment script for CRDM Logs.
+# Intended for execution by the GitLab Runner.
+
+set -euo pipefail
+
+# Ensure required environment variables are set.
+# DEPLOYMENT_HOST denotes the SSH TARGET. Can be only ONE IP or DNS name.
+if [ -z "$DEPLOYMENT_HOST" ]; then
+    echo "[ERROR] Make sure DEPLOYMENT_HOST is set." >&2
+    exit 1
+fi
+
+# ----------------------- #
+#    Repository checks    #
+# ----------------------- #
+DEPLOYMENT_PATH="${DEPLOYMENT_PATH:-crdm-logging-setup}"
+SSH_TARGET="${DEPLOYMENT_USER:-logs}@${DEPLOYMENT_HOST}"
+
+# SSH to target, initialize repo if it doesn't exist.
+# Otherwise, tear down old deployment and pull changes.
+ssh "${SSH_TARGET}" "bash" <<- EOF
+set -eu pipefail
+mkdir -p "${DEPLOYMENT_PATH}" && cd "${DEPLOYMENT_PATH}"
+
+if git status > /dev/null 2>&1; then
+    echo "[INFO] Pulling origin."
+    git pull "${CI_REPOSITORY_URL}"
+else
+    echo "[INFO] Git repository doesn't exist, cloning and setting up."
+    git clone "${CI_REPOSITORY_URL}" . > /dev/null 2>&1
+fi
+
+echo -n "[INFO] " && git checkout "${CI_COMMIT_BRANCH}"
+EOF
+
+# ----------------------- #
+#    .env file checks     #
+# ----------------------- #
+# Dump variables and transfer the file.
+echo "[INFO] Dumping variables to .env file."
+./scripts/dump-vars.sh ".env"
+scp ".env" "${SSH_TARGET}:${DEPLOYMENT_PATH}/.env"
+
+# SSH again, check if ssl directory is empty: setup or rerun.
+ssh "${SSH_TARGET}" "bash" <<- EOF
+set -eu pipefail
+cd "${DEPLOYMENT_PATH}"
+if [ $(find "./ssl" -type f ! -name '.gitkeep' | wc -l) -eq 0 ]; then
+    echo "[INFO] SSL directory only contains .gitkeep. Running setup.sh to create certificates."
+    ./scripts/setup.sh
+else
+    echo "[INFO] SSL directory is not empty. Skipping certificate setup."
+    docker compose up -d
+fi
+EOF
diff --git a/docker-compose.base.yml b/docker-compose.base.yml
index d8cee61..9bf5d4e 100644
--- a/docker-compose.base.yml
+++ b/docker-compose.base.yml
@@ -1,6 +1,7 @@
 services:
   os-node:
     image: opensearchproject/opensearch:2
+    pull_policy: "always"
     restart: "unless-stopped"
     environment:
       - DISABLE_INSTALL_DEMO_CONFIG=true
diff --git a/docker-compose.yml b/docker-compose.yml
index 1b0d09e..b5fbcbc 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -21,6 +21,7 @@ services:
 
   os-dashboards:
     image: opensearchproject/opensearch-dashboards:2
+    pull_policy: "always"
     restart: "unless-stopped"
     environment:
       # note: the dashboards entrypoint performs translations of naming for the env vars
diff --git a/scripts/dump-vars.sh b/scripts/dump-vars.sh
new file mode 100755
index 0000000..fb3aaba
--- /dev/null
+++ b/scripts/dump-vars.sh
@@ -0,0 +1,28 @@
+#!/bin/sh
+#
+# Dump environment variables to a file.
+#
+# This script is intended to be run by the Gitlab Runner, to dump all Gitlab
+# variables to the secrets file.
+#
+
+# The user can optionally specify the output file
+OUTPUT_FILE="${1:-.env}"
+
+# Delete the old file if it exists, and create one with secure permissions
+rm -f "${OUTPUT_FILE}"
+
+# Set 'rwx' only for user
+umask 077
+touch "${OUTPUT_FILE}"
+
+# Dump each exported variable
+# According to the current setup:
+# DASHBOARDS_ prefix for variables relevant to OpenSearch Dashboards.
+# METRICBEAT_ prefix for variables relevant to Metricbeat.
+# OPENSEARCH_ prefix for variables relevant to OpenSearch nodes.
+while read -r var; do
+    echo $var >> "${OUTPUT_FILE}"
+done <<- EOF
+    $(env | grep -E "^DASHBOARDS_.*|^METRICBEAT_.*|^OPENSEARCH_.*")
+EOF
-- 
GitLab