|
@@ -0,0 +1,173 @@
|
|
|
|
|
+/**
|
|
|
|
|
+ * alien_py_cloud production deploy (canonical Jenkinsfile at repo root)
|
|
|
|
|
+ *
|
|
|
|
|
+ * Jenkins: 39.106.135.88 | Target: 39.105.153.68
|
|
|
|
|
+ * Job Script Path: Jenkinsfile
|
|
|
|
|
+ *
|
|
|
|
|
+ */
|
|
|
|
|
+
|
|
|
|
|
+def DEFAULT_PROD_SSH_TARGET = 'alien_store@39.105.153.68'
|
|
|
|
|
+def DEFAULT_PROD_SSH_CREDENTIALS_ID = 'e611a045-2fdc-4613-babd-a72d69bf9814'
|
|
|
|
|
+
|
|
|
|
|
+pipeline {
|
|
|
|
|
+ agent any
|
|
|
|
|
+
|
|
|
|
|
+ options {
|
|
|
|
|
+ buildDiscarder(logRotator(numToKeepStr: '10'))
|
|
|
|
|
+ timestamps()
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ parameters {
|
|
|
|
|
+ string(name: 'PROD_SSH_TARGET', defaultValue: DEFAULT_PROD_SSH_TARGET,
|
|
|
|
|
+ description: 'Production host SSH target')
|
|
|
|
|
+ string(name: 'PROD_SSH_CREDENTIALS_ID', defaultValue: DEFAULT_PROD_SSH_CREDENTIALS_ID,
|
|
|
|
|
+ description: 'Jenkins SSH Username with private key credential ID')
|
|
|
|
|
+ string(name: 'GIT_BRANCH', defaultValue: 'produ',
|
|
|
|
|
+ description: 'alien_py_cloud branch to deploy')
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ environment {
|
|
|
|
|
+ CODE_DIR_REMOTE = '/alien_produ/python/alien_py_cloud'
|
|
|
|
|
+ ENV_FILE_REMOTE = '/alien_produ/python/alien_py_cloud/.env.produ'
|
|
|
|
|
+ LOG_ROOT_REMOTE = '/alien_produ/python/alien_py_cloud/logs'
|
|
|
|
|
+
|
|
|
|
|
+ IMAGE_STORE = 'alien_store:local'
|
|
|
|
|
+ IMAGE_GATEWAY = 'alien_gateway:local'
|
|
|
|
|
+ IMAGE_CONTRACT = 'alien_contract:local'
|
|
|
|
|
+
|
|
|
|
|
+ CONTAINER_NAME_STORE = 'alien_store_produ'
|
|
|
|
|
+ CONTAINER_NAME_GATEWAY = 'alien_gateway_produ'
|
|
|
|
|
+ CONTAINER_NAME_CONTRACT = 'alien_contract_produ'
|
|
|
|
|
+
|
|
|
|
|
+ PORT_STORE_INTERNAL = '48001'
|
|
|
|
|
+ PORT_GATEWAY_INTERNAL = '43333'
|
|
|
|
|
+ PORT_CONTRACT_INTERNAL = '8002'
|
|
|
|
|
+ PORT_GATEWAY_HOST = '33333'
|
|
|
|
|
+ PORT_CONTRACT_HOST = '8002'
|
|
|
|
|
+
|
|
|
|
|
+ DOCKER_NET = 'alien_net_produ'
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ stages {
|
|
|
|
|
+ stage('Verify SSH') {
|
|
|
|
|
+ steps {
|
|
|
|
|
+ script {
|
|
|
|
|
+ def sshTarget = (params.PROD_SSH_TARGET ?: DEFAULT_PROD_SSH_TARGET).trim()
|
|
|
|
|
+ def credId = (params.PROD_SSH_CREDENTIALS_ID ?: DEFAULT_PROD_SSH_CREDENTIALS_ID).trim()
|
|
|
|
|
+ env.SSH_TARGET = sshTarget
|
|
|
|
|
+ env.SSH_CRED_ID = credId
|
|
|
|
|
+ sshagent(credentials: [credId]) {
|
|
|
|
|
+ sh """
|
|
|
|
|
+ set -e
|
|
|
|
|
+ ssh -o BatchMode=yes -o StrictHostKeyChecking=accept-new '${sshTarget}' \\
|
|
|
|
|
+ 'test -f ${ENV_FILE_REMOTE} && sudo docker info >/dev/null'
|
|
|
|
|
+ echo ">>> SSH OK: ${sshTarget}"
|
|
|
|
|
+ """
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ stage('Git Pull on Production') {
|
|
|
|
|
+ steps {
|
|
|
|
|
+ sshagent(credentials: [env.SSH_CRED_ID]) {
|
|
|
|
|
+ sh """
|
|
|
|
|
+ set -e
|
|
|
|
|
+ ssh -o BatchMode=yes -o StrictHostKeyChecking=accept-new '${env.SSH_TARGET}' bash -s <<'REMOTE_EOF'
|
|
|
|
|
+set -e
|
|
|
|
|
+cd '${CODE_DIR_REMOTE}'
|
|
|
|
|
+if [ ! -d .git ]; then
|
|
|
|
|
+ echo "ERROR: ${CODE_DIR_REMOTE} is not a git repo. Clone manually first."
|
|
|
|
|
+ exit 1
|
|
|
|
|
+fi
|
|
|
|
|
+git fetch origin
|
|
|
|
|
+git checkout '${params.GIT_BRANCH}'
|
|
|
|
|
+git pull origin '${params.GIT_BRANCH}'
|
|
|
|
|
+echo ">>> git at \$(git rev-parse --short HEAD) on \$(hostname)"
|
|
|
|
|
+REMOTE_EOF
|
|
|
|
|
+ """
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ stage('Build Images on Production') {
|
|
|
|
|
+ steps {
|
|
|
|
|
+ sshagent(credentials: [env.SSH_CRED_ID]) {
|
|
|
|
|
+ sh """
|
|
|
|
|
+ set -e
|
|
|
|
|
+ ssh -o BatchMode=yes -o StrictHostKeyChecking=accept-new '${env.SSH_TARGET}' bash -s <<'REMOTE_EOF'
|
|
|
|
|
+set -e
|
|
|
|
|
+cd '${CODE_DIR_REMOTE}'
|
|
|
|
|
+sudo docker build -f alien_store/Dockerfile -t ${IMAGE_STORE} .
|
|
|
|
|
+sudo docker build -f alien_gateway/Dockerfile -t ${IMAGE_GATEWAY} .
|
|
|
|
|
+sudo docker build -f alien_contract/Dockerfile -t ${IMAGE_CONTRACT} .
|
|
|
|
|
+echo ">>> images built on \$(hostname)"
|
|
|
|
|
+sudo docker images | grep -E 'alien_store|alien_gateway|alien_contract' | head -10
|
|
|
|
|
+REMOTE_EOF
|
|
|
|
|
+ """
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ stage('Deploy on Production') {
|
|
|
|
|
+ steps {
|
|
|
|
|
+ sshagent(credentials: [env.SSH_CRED_ID]) {
|
|
|
|
|
+ sh """
|
|
|
|
|
+ set -e
|
|
|
|
|
+ ssh -o BatchMode=yes -o StrictHostKeyChecking=accept-new '${env.SSH_TARGET}' bash -s <<'REMOTE_EOF'
|
|
|
|
|
+set -e
|
|
|
|
|
+sudo docker network create ${DOCKER_NET} 2>/dev/null || true
|
|
|
|
|
+mkdir -p ${LOG_ROOT_REMOTE}/store ${LOG_ROOT_REMOTE}/gateway ${LOG_ROOT_REMOTE}/contract
|
|
|
|
|
+
|
|
|
|
|
+sudo docker rm -f ${CONTAINER_NAME_STORE} ${CONTAINER_NAME_GATEWAY} ${CONTAINER_NAME_CONTRACT} 2>/dev/null || true
|
|
|
|
|
+
|
|
|
|
|
+sudo docker run -d --name ${CONTAINER_NAME_STORE} \\
|
|
|
|
|
+ --network ${DOCKER_NET} \\
|
|
|
|
|
+ --env-file ${ENV_FILE_REMOTE} \\
|
|
|
|
|
+ -v ${ENV_FILE_REMOTE}:/app/.env.produ:ro \\
|
|
|
|
|
+ -v ${LOG_ROOT_REMOTE}/store:/app/common/logs/alien_store \\
|
|
|
|
|
+ --restart unless-stopped \\
|
|
|
|
|
+ ${IMAGE_STORE}
|
|
|
|
|
+
|
|
|
|
|
+sudo docker run -d --name ${CONTAINER_NAME_CONTRACT} \\
|
|
|
|
|
+ --network ${DOCKER_NET} \\
|
|
|
|
|
+ -p ${PORT_CONTRACT_HOST}:${PORT_CONTRACT_INTERNAL} \\
|
|
|
|
|
+ --env-file ${ENV_FILE_REMOTE} \\
|
|
|
|
|
+ -v ${ENV_FILE_REMOTE}:/app/.env.produ:ro \\
|
|
|
|
|
+ -v ${LOG_ROOT_REMOTE}/contract:/app/common/logs/alien_contract \\
|
|
|
|
|
+ --restart unless-stopped \\
|
|
|
|
|
+ ${IMAGE_CONTRACT}
|
|
|
|
|
+
|
|
|
|
|
+sudo docker run -d --name ${CONTAINER_NAME_GATEWAY} \\
|
|
|
|
|
+ --network ${DOCKER_NET} \\
|
|
|
|
|
+ -p ${PORT_GATEWAY_HOST}:${PORT_GATEWAY_INTERNAL} \\
|
|
|
|
|
+ --env-file ${ENV_FILE_REMOTE} \\
|
|
|
|
|
+ -v ${ENV_FILE_REMOTE}:/app/.env.produ:ro \\
|
|
|
|
|
+ -v ${LOG_ROOT_REMOTE}/gateway:/app/common/logs/alien_gateway \\
|
|
|
|
|
+ -e STORE_BASE_URL=http://${CONTAINER_NAME_STORE}:${PORT_STORE_INTERNAL} \\
|
|
|
|
|
+ --restart unless-stopped \\
|
|
|
|
|
+ ${IMAGE_GATEWAY}
|
|
|
|
|
+
|
|
|
|
|
+sleep 3
|
|
|
|
|
+curl -sf http://127.0.0.1:${PORT_GATEWAY_HOST}/health || (echo 'gateway /health failed' && exit 1)
|
|
|
|
|
+curl -sf http://127.0.0.1:${PORT_CONTRACT_HOST}/health || (echo 'contract /health failed' && exit 1)
|
|
|
|
|
+sudo docker ps --filter name=${CONTAINER_NAME_STORE} --filter name=${CONTAINER_NAME_GATEWAY} --filter name=${CONTAINER_NAME_CONTRACT}
|
|
|
|
|
+REMOTE_EOF
|
|
|
|
|
+ """
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ post {
|
|
|
|
|
+ success {
|
|
|
|
|
+ echo ">>> alien_py_cloud deployed on ${env.SSH_TARGET}"
|
|
|
|
|
+ }
|
|
|
|
|
+ failure {
|
|
|
|
|
+ echo '>>> failed: check SSH, .env.produ, sudo docker, and remote git path'
|
|
|
|
|
+ }
|
|
|
|
|
+ always {
|
|
|
|
|
+ cleanWs()
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|