|
|
@@ -0,0 +1,173 @@
|
|
|
+// ==============================
|
|
|
+// Pipeline config constants
|
|
|
+// ==============================
|
|
|
+def GIT_URL = 'http://8.134.139.102:10880/m1ro/gami-web'
|
|
|
+def GIT_BRANCH = 'main'
|
|
|
+
|
|
|
+// Deployment nodes list.
|
|
|
+def NODES = ['10.0.0.12']
|
|
|
+
|
|
|
+def REMOTE_USER = 'ubuntu'
|
|
|
+def REMOTE_DIR = '/home/ubuntu/gami-web-runtime'
|
|
|
+def PM2_APP = 'gami'
|
|
|
+
|
|
|
+// Required when NODES is not empty.
|
|
|
+def SSH_CREDENTIALS_ID = 'prod-web-server'
|
|
|
+
|
|
|
+// Jenkins credentials id of dotenv file (.env). Recommended type: "Secret file"
|
|
|
+def DOTENV_CREDENTIALS_ID = 'prod-web-env'
|
|
|
+
|
|
|
+// Skip coscli upload step inside yarn build:prod
|
|
|
+def SKIP_COS_UPLOAD = false
|
|
|
+
|
|
|
+pipeline {
|
|
|
+ agent {
|
|
|
+ docker {
|
|
|
+ image 'node:22'
|
|
|
+ args '-u root:root -v /usr/local/bin/coscli:/usr/local/bin/coscli:ro'
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ options {
|
|
|
+ timestamps()
|
|
|
+ skipDefaultCheckout(true)
|
|
|
+ }
|
|
|
+
|
|
|
+ environment {
|
|
|
+ CI = 'true'
|
|
|
+ }
|
|
|
+
|
|
|
+ stages {
|
|
|
+ stage('Checkout') {
|
|
|
+ steps {
|
|
|
+ checkout([
|
|
|
+ $class: 'GitSCM',
|
|
|
+ branches: [[name: "*/${GIT_BRANCH}"]],
|
|
|
+ userRemoteConfigs: [[url: GIT_URL]]
|
|
|
+ ])
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ stage('Install') {
|
|
|
+ steps {
|
|
|
+ sh '''
|
|
|
+ set -eu
|
|
|
+ node --version
|
|
|
+ if [ ! -x /usr/local/bin/coscli ]; then
|
|
|
+ echo "[WARN] /usr/local/bin/coscli not found or not executable on docker host mount. coscli-related steps may fail."
|
|
|
+ else
|
|
|
+ /usr/local/bin/coscli --version || true
|
|
|
+ fi
|
|
|
+ if ! command -v yarn >/dev/null 2>&1; then
|
|
|
+ if command -v corepack >/dev/null 2>&1; then
|
|
|
+ corepack enable
|
|
|
+ fi
|
|
|
+ fi
|
|
|
+ yarn --version
|
|
|
+ yarn install --frozen-lockfile
|
|
|
+ '''
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ stage('Prepare Env') {
|
|
|
+ when {
|
|
|
+ expression { return (DOTENV_CREDENTIALS_ID ?: '').trim() }
|
|
|
+ }
|
|
|
+ steps {
|
|
|
+ withCredentials([file(credentialsId: DOTENV_CREDENTIALS_ID, variable: 'DOTENV_FILE')]) {
|
|
|
+ sh '''
|
|
|
+ set -eu
|
|
|
+ cp "$DOTENV_FILE" .env
|
|
|
+ chmod 600 .env || true
|
|
|
+ '''
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ stage('Build') {
|
|
|
+ steps {
|
|
|
+ sh """
|
|
|
+ set -eu
|
|
|
+ SKIP_COS_UPLOAD="${SKIP_COS_UPLOAD}" yarn build:prod
|
|
|
+ test -d .output
|
|
|
+ """
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ stage('Archive') {
|
|
|
+ steps {
|
|
|
+ sh '''
|
|
|
+ set -eu
|
|
|
+ rm -f gami-web-runtime.tgz
|
|
|
+ tar -czf gami-web-runtime.tgz .output ecosystem.config.cjs
|
|
|
+ '''
|
|
|
+ archiveArtifacts artifacts: 'gami-web-runtime.tgz, ecosystem.config.cjs, .output/**', fingerprint: true
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ stage('Deploy') {
|
|
|
+ when {
|
|
|
+ expression { return (NODES ?: []).size() > 0 }
|
|
|
+ }
|
|
|
+ steps {
|
|
|
+ script {
|
|
|
+ def nodes = (NODES ?: [])
|
|
|
+ .collect { "${it}".trim() }
|
|
|
+ .findAll { it }
|
|
|
+ .unique()
|
|
|
+
|
|
|
+ if (nodes.isEmpty()) {
|
|
|
+ echo 'No nodes provided, skipping deploy.'
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!(SSH_CREDENTIALS_ID ?: '').trim()) {
|
|
|
+ error('SSH_CREDENTIALS_ID is required for deploy stage.')
|
|
|
+ }
|
|
|
+
|
|
|
+ sshagent(credentials: [SSH_CREDENTIALS_ID]) {
|
|
|
+ nodes.each { node ->
|
|
|
+ def deployThisNode = input(
|
|
|
+ message: "Deploy to node: ${node} ?",
|
|
|
+ ok: 'Deploy',
|
|
|
+ parameters: [
|
|
|
+ booleanParam(
|
|
|
+ name: 'CONFIRM_DEPLOY',
|
|
|
+ defaultValue: false,
|
|
|
+ description: "Check to confirm deploying to ${node}"
|
|
|
+ )
|
|
|
+ ]
|
|
|
+ ) as boolean
|
|
|
+
|
|
|
+ if (!deployThisNode) {
|
|
|
+ echo "Skipped node: ${node}"
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ sh """
|
|
|
+ set -eu
|
|
|
+ ssh -o StrictHostKeyChecking=no ${REMOTE_USER}@${node} 'mkdir -p ${REMOTE_DIR}'
|
|
|
+ scp -o StrictHostKeyChecking=no gami-web-runtime.tgz ${REMOTE_USER}@${node}:${REMOTE_DIR}/
|
|
|
+ if [ -f .env ]; then
|
|
|
+ scp -o StrictHostKeyChecking=no .env ${REMOTE_USER}@${node}:${REMOTE_DIR}/
|
|
|
+ fi
|
|
|
+ ssh -o StrictHostKeyChecking=no ${REMOTE_USER}@${node} '
|
|
|
+ set -eu
|
|
|
+ cd ${REMOTE_DIR}
|
|
|
+ rm -rf .output
|
|
|
+ tar -xzf gami-web-runtime.tgz
|
|
|
+ if [ -f .env ]; then
|
|
|
+ set -a
|
|
|
+ . ./.env
|
|
|
+ set +a
|
|
|
+ fi
|
|
|
+ pm2 restart ${PM2_APP} --update-env
|
|
|
+ '
|
|
|
+ """
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|