// GUARDiA ITSM — 롤백 파이프라인 // 이전 빌드 아티팩트로 즉시 롤백한다. pipeline { agent any parameters { string(name: 'ITSM_SESSION_ID', defaultValue: '', description: 'GUARDiA 바이브 세션 ID') string(name: 'ITSM_SR_ID', defaultValue: '', description: '연결된 SR ID') string(name: 'TARGET_SERVER', defaultValue: '', description: '배포 대상 서버명 (필수)') choice(name: 'DEPLOY_ENV', choices: ['prd', 'stg', 'dev'], description: '롤백 환경') string(name: 'ROLLBACK_VERSION', defaultValue: '', description: '롤백 버전 (빌드 번호, 비워두면 이전 빌드)') string(name: 'ROLLBACK_REASON', defaultValue: '서비스 장애', description: '롤백 사유') string(name: 'SOURCE_JOB', defaultValue: '', description: '아티팩트 소스 Job 이름') string(name: 'WAS_TYPE', defaultValue: 'tomcat', description: 'WAS 종류') } environment { SCRIPTS_ROOT = "${WORKSPACE}/cicd/scripts/pipeline" NOTIFY_SCRIPT = "${WORKSPACE}/cicd/scripts/notify/itsm_callback.sh" } options { timeout(time: 20, unit: 'MINUTES') buildDiscarder(logRotator(numToKeepStr: '30')) } stages { stage('Confirm Rollback') { steps { script { def version = params.ROLLBACK_VERSION ?: '(이전 빌드)' echo """ ╔══════════════════════════════════════════════╗ ║ 롤백 파이프라인 시작 ║ ╠══════════════════════════════════════════════╣ ║ 대상 서버: ${params.TARGET_SERVER.padRight(30)}║ ║ 환경: ${params.DEPLOY_ENV.padRight(30)} ║ ║ 버전: ${version.padRight(30)} ║ ║ 사유: ${params.ROLLBACK_REASON.take(30)} ║ ╚══════════════════════════════════════════════╝ """ } sh "bash ${NOTIFY_SCRIPT} DEPLOYING '롤백 시작: ${params.ROLLBACK_REASON}'" } } stage('Resolve Rollback Artifact') { steps { script { def jobName = params.SOURCE_JOB ?: env.JOB_NAME.replaceAll('-rollback', '') def buildNum = params.ROLLBACK_VERSION echo "롤백 소스 Job: ${jobName}" echo "롤백 버전: ${buildNum ?: '이전 빌드'}" copyArtifacts( projectName: jobName, selector: buildNum ? specific(buildNum) : lastWithArtifacts(), target: 'artifacts/', flatten: true, optional: false ) sh "ls -la artifacts/" } } } stage('Rollback Deploy') { steps { withCredentials([sshUserPrivateKey( credentialsId: "ssh-${params.TARGET_SERVER}", keyFileVariable: 'SSH_KEY', usernameVariable: 'SSH_USER' )]) { sh """ ARTIFACT=\$(ls artifacts/*.jar artifacts/*.war artifacts/*.tar.gz 2>/dev/null | head -1) echo "롤백 아티팩트: \${ARTIFACT}" bash ${SCRIPTS_ROOT}/deploy.sh \ --server "${params.TARGET_SERVER}" \ --env "${params.DEPLOY_ENV}" \ --ssh-key "\${SSH_KEY}" \ --ssh-user "\${SSH_USER}" \ --artifact "\${ARTIFACT}" \ --rollback true """ } } } stage('WAS Restart') { steps { withCredentials([sshUserPrivateKey( credentialsId: "ssh-${params.TARGET_SERVER}", keyFileVariable: 'SSH_KEY', usernameVariable: 'SSH_USER' )]) { sh """ bash ${SCRIPTS_ROOT}/was_restart.sh \ --server "${params.TARGET_SERVER}" \ --ssh-key "${SSH_KEY}" \ --ssh-user "${SSH_USER}" \ --was-type "${params.WAS_TYPE}" """ } } } stage('Health Check') { steps { retry(3) { sh """ bash ${SCRIPTS_ROOT}/health_check.sh \ --url "${env.HEALTH_CHECK_URL ?: 'http://localhost:8080/health'}" \ --timeout 60 """ } } } stage('ITSM Callback') { steps { sh """ bash ${NOTIFY_SCRIPT} ROLLED_BACK \ "롤백 완료: ${params.ROLLBACK_REASON} (버전 ${params.ROLLBACK_VERSION ?: '이전 빌드'})" """ } } } post { always { cleanWs() } success { echo "✅ 롤백 완료: ${params.TARGET_SERVER} → 버전 ${params.ROLLBACK_VERSION ?: '이전 빌드'}" } failure { sh "bash ${NOTIFY_SCRIPT} FAILED '롤백 실패 — 즉시 수동 조치 필요' || true" } } }