pipeline { agent any environment { GIT_CREDENTIALSID = 'd3de261f-8f1e-470b-b6d1-2fb4965e0129' GIT_URL = 'http://work.gct.com.vn/anhln/ACP_2025.git' GIT_BRANCH = 'main' PROJECT_NAME = 'portal' TRIGGER_JOB_NAME = 'CD_BE_PORTAL' METADATA_FILENAME = "${PROJECT_NAME}_metadata.json" NUGET_CONFIG_PATH = 'NuGet.config' APPLICATIONCORE_PATH = 'Packages' JENKINS_BUILD_FOLDER_PATH = 'Portal.WebApi' JENKINS_PUBLISH_FOLDER_PATH = 'publish' COMPRESSED_FILE_NAME = "${PROJECT_NAME}_publish.zip" // tên file nén COMPRESSED_FILE_PATH = "${env.WORKSPACE }/${COMPRESSED_FILE_NAME}" NEXUS_CREDENTIALS = credentials('Nexus_credential') NEXUS_REPO_URL = "https://nexus.gct.com.vn/repository/${PROJECT_NAME}-backend" GROUP_ID = 'vn.kinhtedothi' ARTIFACT_ID = "${PROJECT_NAME}-backend-api" PACKAGING = 'zip' VERSION = '1.0.0' // Phiên bản cơ bản TIMESTAMP = new Date().format('yyyyMMdd.HH', TimeZone.getTimeZone('UTC')) FULL_VERSION = "${env.VERSION}-${env.TIMESTAMP}-${env.BUILD_NUMBER}" // Tạo phiên bản hoàn chỉnh TELEGRAM_CHAT_ID = -4678013464 TELEGRAM_BOT_TOKEN = credentials('TELEGRAM_BOT_TOKEN') } stages { stage('Checkout') { steps { // Checkout mã nguồn từ Gitea checkoutFromGit(env.GIT_URL as String, env.GIT_CREDENTIALSID as String, env.GIT_BRANCH as String) } } stage('Clear Nuget caches') { steps { // Xóa cache của NuGet clearNuGetCaches() } } stage('Setup Nuget.Config') { steps { // Thiết lập tệp NuGet.config setupNuGetConfig(env.APPLICATIONCORE_PATH as String) } } stage('Restore') { steps { // Gọi hàm để thực hiện restore restoreNuGetPackages(env.JENKINS_BUILD_FOLDER_PATH as String , env.NUGET_CONFIG_PATH as String) } } stage('Clean & Build') { steps { script { cleanProject(env.JENKINS_BUILD_FOLDER_PATH as String) buildProject(env.JENKINS_BUILD_FOLDER_PATH as String) } } } stage('Publish') { steps { publishProject(env.JENKINS_BUILD_FOLDER_PATH as String, env.JENKINS_PUBLISH_FOLDER_PATH as String) } } stage('Package (Compress Publish Files)') { steps { compressItems(env.COMPRESSED_FILE_PATH, env.JENKINS_PUBLISH_FOLDER_PATH) } } stage('Upload to Nexus') { steps { script { String groupPath = env.GROUP_ID.replace('.', '/') env.NEXUS_URL = "${env.NEXUS_REPO_URL}/${groupPath}/${env.ARTIFACT_ID}/${env.VERSION}" env.NEXUS_ARTIFACT_NAME = "${env.ARTIFACT_ID}-${env.FULL_VERSION}.${env.PACKAGING}" String nexusUploadUrl = "${env.NEXUS_URL}/${env.NEXUS_ARTIFACT_NAME}" uploadToNexus( env.NEXUS_CREDENTIALS_USR, env.NEXUS_CREDENTIALS_PSW, env.COMPRESSED_FILE_PATH, nexusUploadUrl) } } } stage('Create Metadata File') { steps { createMetadataFile( env.METADATA_FILENAME, env.GROUP_ID, env.ARTIFACT_ID, env.VERSION, env.NEXUS_URL, env.NEXUS_ARTIFACT_NAME) echo "metadataFileName: ${env.METADATA_FILENAME}" archiveArtifacts artifacts: "${env.METADATA_FILENAME}", allowEmptyArchive: false } } } post { always { echo 'Pipeline execution finished.' } success { echo "Job '${env.JOB_NAME}' completed successfully. Attempting to trigger Job '${TRIGGER_JOB_NAME}'..." def message = "Build thành công : API - Môi trường ${params.ENV} - Dự án ${env.PROJECT_NAME} ${currentBuild.fullDisplayName}\n${env.BUILD_URL} \n Đang tiến hành Deploy...!" 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}\"" script { try { def buildResult = build job: "${TRIGGER_JOB_NAME}", parameters:[ string(name: 'ENV', value: 'uat'), string(name: 'CI_JOB_BUILD_NUMBER', value: env.BUILD_NUMBER) ], propagate: false if (buildResult.result != 'SUCCESS') { echo "[WARNING] Job 2 failed with result: ${buildResult.result}" } } catch (Exception e) { echo "[ERROR] Failed to trigger job: ${TRIGGER_JOB_NAME}. Error: ${e.message}" throw e } } } failure { failure { script { def message = "Build thất bại: API - Môi trường ${params.ENV} - Dự án ${env.PROJECT_NAME}, ${currentBuild.fullDisplayName}\n Kiểm tra tại đây ${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 void checkoutFromGit(String gitUrl, String credentialsId, String branch) { try { echo 'Start checkoutFromGit' checkout([$class : 'GitSCM', userRemoteConfigs: [[url: gitUrl, credentialsId: credentialsId]], branches : [[name: "*/${branch}"]]]) } catch (Exception e) { echo "[ERROR] Unexpected error: ${e.message}" throw e } } //Thienvv- clear nuget caches void clearNuGetCaches() { try { // Xóa cache của NuGet Integer result = sh(script: 'dotnet nuget locals all --clear', returnStatus: true) echo "result:${result}" // Kiểm tra trạng thái trả về if (result == 0) { echo 'NuGet caches cleared successfully.' } else { error "Failed to clear NuGet caches with status: ${result}" } } catch (Exception e) { echo "[ERROR] Unexpected error: ${e.message}" throw e } } //Thienvv - Hàm set up file Nuget.config để restore các package dependencies void setupNuGetConfig(String applicationCorePath) { try { writeFile file: 'NuGet.config', text: """ """ // Kiểm tra xem tệp đã được ghi thành công if (fileExists('NuGet.config')) { echo 'NuGet.config has been created successfully.' } else { error 'Failed to create NuGet.config.' } } catch (Exception e) { echo "[ERROR] Unexpected error: ${e.message}" throw e } } // Thienvv - Định nghĩa hàm để restore các gói NuGet void restoreNuGetPackages(String restorePath, String nugetConfigPath) { echo 'Starting NuGet packages restore...' try { if (!fileExists(restorePath)) { error "restorePath is not exist : ${restorePath}" } if (!fileExists(nugetConfigPath)) { error "nugetConfigPath is not exist : ${nugetConfigPath}" } // Thực hiện restore các gói NuGet cần thiết Integer result = sh(script: "dotnet restore ${restorePath} --configfile ${nugetConfigPath}", returnStatus: true) // Kiểm tra kết quả trả về if (result == 0) { echo 'NuGet packages restored successfully.' } else { error "Restore NuGet packages failed with exit code: ${result}. Check NuGet config and restore path." } } catch (Exception e) { echo "[ERROR] Unexpected error: ${e.message}" throw e } } //Thienvv - clean project dotnet void cleanProject(String buildPath) { echo 'Start cleanProject' try { if (!fileExists(buildPath)) { error "buildPath is not exist : ${buildPath}" } Integer result = sh(script: "dotnet clean ${buildPath}", returnStatus: true) echo "result:${result}" if (result == 0) { echo 'Clean Project successfully' } else { error 'Clean Projectfailed' } } catch (Exception e) { echo "[ERROR] Unexpected error: ${e.message}" throw e } } //Thienvv - build project dotnet void buildProject(String buildPath) { echo 'Start buildProject' try { if (!fileExists(buildPath)) { error "buildPath is not exist : ${buildPath}" } Integer result = sh(script: "dotnet build ${buildPath} -c Release", returnStatus: true) echo "result:${result}" if (result == 0) { echo 'Build Project successfully' } else { error 'Build Project failed' } } catch (Exception e) { echo "[ERROR] Unexpected error: ${e.message}" throw e } } //Thienvv - package/publish project dotnet void publishProject(String buildPath, String publishFolderPath) { echo 'Start publishProject' try { if (!fileExists(buildPath)) { error "buildPath is not exist : ${buildPath}" } Integer result = sh(script: "dotnet publish ${buildPath} -c Release -o ${publishFolderPath}", returnStatus: true) echo "result : ${result}" if (result == 0) { echo 'Publish Project successfully' } else { error 'Publish Project failed' } } catch (Exception e) { echo "[ERROR] Unexpected error: ${e.message}" throw e } } //Thienvv - nén file void compressItems(String compressedFilePath, String parentFolderPath) { echo "Starting compression of the entire folder into a zip file : ${compressedFilePath}" try { if (!fileExists(parentFolderPath)) { error "parentFolderPath is not exist : ${parentFolderPath}" } dir(parentFolderPath) { // Thực hiện lệnh zip để nén tất cả các file trong thư mục Integer result = sh(script: "zip -r ${compressedFilePath} * ", returnStatus: true) // Kiểm tra kết quả if (result == 0) { echo "Compression completed successfully: ${compressedFilePath}" } else { error "Compression failed with exit code: ${result}." } } } catch (Exception e) { echo "[ERROR] Unexpected error: ${e.message}" throw e } } void uploadToNexus(String nexusUsername, String nexusPassword, String compressedFilePath, String uploadUrl) { echo "Starting upload ${compressedFilePath} To Nexus" try { // Truyền các biến môi trường vào lệnh sh mà không lộ ra trong log String result = sh(script: """ curl -u ${nexusUsername}:${nexusPassword} --upload-file ${compressedFilePath} ${uploadUrl} -w '%{http_code}' """, returnStdout: true).trim() if (result == '200' || result == '201') { echo 'uploadToNexus successfully' } else { error "uploadToNexus failed, HTTP status: ${result}" } } catch (Exception e) { echo "[ERROR] Unexpected error: ${e.message}" throw e } } def createMetadataFile( String metadataFileName, String groupId, String artifactId, String version, String nexusUrl, String nexusArtifactName) { echo 'Starting create metadata file' try { // Tạo metadata metadata = [ groupId: groupId, artifactId: artifactId, version: version, nexusUrl: nexusUrl, nexusArtifactName: nexusArtifactName ] // Ghi metadata vào file JSON writeJSON file: "${metadataFileName}", json: metadata if (!fileExists(metadataFileName)) { error "metadataFileName is not exist : ${metadataFileName}" } } catch (Exception e) { echo "[ERROR] Unexpected error: ${e.message}" throw e } }