pipeline { agent any parameters { choice(name: 'ENV', choices: ['prod', 'uat'], description: 'Choose Environment') string(name: 'CI_JOB_BUILD_NUMBER', defaultValue: '', description: 'Build number of CI Job') } environment { PROJECT_NAME = 'portal' CI_JOB_NAME_UAT = 'CI-UAT-FE_PORTAL' // tên của job build code môi trường uat CI_JOB_NAME_PROD = 'CI-PROD-FE-PORTAL' // tên của job build code môi trường prod CI_JOB_METADATA_FILENAME = "${params.ENV}_${PROJECT_NAME}_metadata.json" // tên file metadata đã được lưu từ job build code GIT_PAT_CREDENTIALS_ID = 'b03f36c4-bba3-4764-94ca-b620651b2a68' // Id của Personal Access Token lưu trên jenkins GIT_ANSIBLE_URL = 'work.gct.com.vn/thienvv/nsg_ansible.git' GIT_ANSIBLE_BRANCH = 'v2' NEXUS_CREDENTIALS = credentials('Nexus_credential') ANSIBLE_SSH_CONNECTION = 'root@103.166.183.172 -p 24700' ANSIBLE_FOLDER_PATH = '/srv/ansible_v2' ANSIBLE_INVENTORY_PATH = "inventory/${params.ENV}.ini" ANSIBLE_PLAYBOOK_PATH = 'playbooks/deploy_fe.yml' TELEGRAM_CHAT_ID = -4678013464 TELEGRAM_BOT_TOKEN = credentials('TELEGRAM_BOT_TOKEN') } stages { stage('Retrieve Artifact Metadata From CI Job') { steps { script { switch (params.ENV) { case 'uat': env.CI_JOB_NAME = env.CI_JOB_NAME_UAT break case 'prod': env.CI_JOB_NAME = env.CI_JOB_NAME_PROD break default: error "Unsupported environment: ${params.ENV}" } def ciJobBuildNumber = params.CI_JOB_BUILD_NUMBER echo "Retrieving artifact from CI_JOB_BUILD_NUMBER: ${ciJobBuildNumber}" def metadata = retrieveArtifactMetadataFromCIJOB( env.CI_JOB_NAME, ciJobBuildNumber, env.CI_JOB_METADATA_FILENAME) env.NEXUS_URL = metadata.nexusUrl echo "env.NEXUS_URL : ${env.NEXUS_URL}" env.NEXUS_ARTIFACT_NAME = metadata.nexusArtifactName echo "env.NEXUS_ARTIFACT_NAME : ${env.NEXUS_ARTIFACT_NAME}" } } } stage('Checkout Ansible Code Git ') { steps { script { checkoutFromGit( env.ANSIBLE_SSH_CONNECTION, env.GIT_ANSIBLE_URL, env.GIT_PAT_CREDENTIALS_ID, env.GIT_ANSIBLE_BRANCH, env.ANSIBLE_FOLDER_PATH ) } } } stage('Deploy with Ansible') { steps { triggerAnsible( env.ANSIBLE_SSH_CONNECTION, env.ANSIBLE_FOLDER_PATH, env.ANSIBLE_INVENTORY_PATH, env.ANSIBLE_PLAYBOOK_PATH, params.ENV, env.PROJECT_NAME, env.NEXUS_URL, env.NEXUS_ARTIFACT_NAME, env.NEXUS_CREDENTIALS_USR, env.NEXUS_CREDENTIALS_PSW) } } } post { always { echo 'Pipeline execution finished.' } success { script { def message = "Deploy thành công : FRONTEND - Môi trường ${params.ENV} - Dự án ${env.PROJECT_NAME}, ${currentBuild.fullDisplayName}\n${env.BUILD_URL}" sh "curl -s -X POST https://api.telegram.org/bot${env.TELEGRAM_BOT_TOKEN}/sendMessage -d chat_id=${env.TELEGRAM_CHAT_ID} -d text=\"${message}\"" } } failure { script { def message = "Deploy thất bại: FRONTEND - Môi trường ${params.ENV} - Dự án ${env.PROJECT_NAME}, ${currentBuild.fullDisplayName}\n${env.BUILD_URL}" sh "curl -s -X POST https://api.telegram.org/bot${env.TELEGRAM_BOT_TOKEN}/sendMessage -d chat_id=${env.TELEGRAM_CHAT_ID} -d text=\"${message}\"" } } } } //Thienvv- hàm checkout git code ansible về máy ansible def checkoutFromGit( String ansibleSSHConnection, String gitUrl, String gitAnsibleCredentialsId, String branch, String ansibleFolderPath) { try { // kiểm tra đã tồn tại code ansible trên thư mục của máy ansible Boolean repoExists = sh( script: """ ssh -v ${ansibleSSHConnection} \\ ' [ -d ${ansibleFolderPath}/.git ] && echo '1' || echo '0' ' """, returnStdout: true ).trim() == '1' withCredentials([usernamePassword( credentialsId: gitAnsibleCredentialsId, usernameVariable: 'GIT_USERNAME', passwordVariable: 'GIT_PAT')]) { if (repoExists) { // nếu tồn tại source code ansible rồi thì pull về echo "Repository already exists on ${ansibleFolderPath}. Pulling latest changes..." Integer result = sh(script: """ ssh -v ${ansibleSSHConnection} \\ 'cd ${ansibleFolderPath} && \\ git reset --hard && \\ git clean -fd && \\ git fetch origin && \\ git checkout ${branch} && \\ git pull origin ${branch} -vvvv ' """, returnStatus: true) if (result == 0) { echo 'Pull ansible code successfully' } else { error "Pull ansible code failed, status: ${result}" } } else { //nếu chưa tồn tại code ansible Integer result = sh(script: """ ssh -v ${ansibleSSHConnection} \\ 'git clone --branch ${branch} http://${GIT_USERNAME}@${gitUrl} ${ansibleFolderPath} -vvvv ' """, returnStatus: true) if (result == 0) { echo 'Clone ansible code successfully' } else { error "Clone ansible code failed, status: ${result}" } } } } catch (Exception e) { echo "[ERROR] Unexpected error: ${e.message}" throw e } } //Hàm lấy artifact metadata file từ CI job def retrieveArtifactMetadataFromCIJOB(String ciJobName, String ciJobBuildNumber, String metadataFilename) { try { def selector = null if (ciJobBuildNumber != '') { // nếu ciJobBuildNumber khác rỗng thì selector = [$class: 'SpecificBuildSelector', buildNumber: ciJobBuildNumber] // selector = ciJobBuildNumber } else { //còn nếu ciJobBuildNumber = rỗng thì selector = lastSuccessful() //selector = build thành công gần nhất } // Sao chép artifact từ dự án khác copyArtifacts projectName: ciJobName, selector: selector, filter: metadataFilename, target: '.' // Kiểm tra sự tồn tại của file metadata if (!fileExists(metadataFilename)) { error "File ${metadataFilename} not found after copyArtifacts!" } else { echo "File ${metadataFilename} successfully copied." } // Đọc dữ liệu từ file JSON def metadata = readJSON file: metadataFilename return metadata } catch (Exception e) { echo "[ERROR] Unexpected error: ${e.message}" throw e } } def triggerAnsible( String sshAnsibleConnection, String ansibleansibleFolderPath, String inventoryPath, String playbookPath, String deployENV, String projectName, String nexusUrl, String nexusArtifactName, String nexusUsername, String nexusPassword) { try { Integer result = sh( script: """ ssh ${sshAnsibleConnection} " cd ${ansibleansibleFolderPath} && ansible-playbook -i ${inventoryPath} ${playbookPath} \\ -e 'deploy_env=${deployENV} \\ project_name=${projectName} \\ nexus_url=${nexusUrl} \\ artifact_name=${nexusArtifactName} \\ nexus_username=${nexusUsername} \\ nexus_password=${nexusPassword}' -vvvv " """, returnStatus: true ) if (result == 0) { echo 'triggerAnsible successfully' } else { error "triggerAnsible failed, status: ${result}" } } catch (Exception e) { echo "[ERROR] Unexpected error: ${e.message}" throw e } }