Copy import java.text.SimpleDateFormat
def TODAY = (new SimpleDateFormat("yyyyMMddHHmmss")).format(new Date())
pipeline {
agent none // 개별 스테이지마다 agent 지정
environment {
strDockerTag = "${TODAY}_${BUILD_ID}"
strDockerImage ="wombat1234/cicd_guestbook:${strDockerTag}"
strGitUrl = "https://github.com/wombatHero999/zenkins.git"
}
stages {
// 1. 깃헙 체크아웃(master)
stage('Checkout') {
agent { label 'agent1' }
steps {
git branch: 'master', url: strGitUrl
stash includes: '**', name: 'source'
}
}
// 2. 소스코드 빌드
stage('Build') {
agent { label 'agent1' }
steps {
sh 'chmod +x mvnw'
sh './mvnw clean package'
stash includes: '**', name: 'built'
}
}
// 3. 유닛테스트 수행
stage('Unit Test') {
agent { label 'agent1' }
steps {
sh './mvnw test'
}
post {
always {
junit '**/target/surefire-reports/TEST-*.xml'
}
}
}
// 4. 정적 테스트 수행 (SonarQube)
stage('SonarQube Analysis') {
agent { label 'master' }
steps {
withSonarQubeEnv('SonarQube-Server'){
sh '''
./mvnw sonar:sonar \
-Dsonar.projectKey=guestbook \
-Dsonar.host.url=http://192.168.10.2:9000 \
-Dsonar.login=dfaa78e1a63c7ed61b65e00f5daa646c1666a11e
'''
}
}
}
// 5. 도커 이미지 빌드
stage('Docker Image Build') {
agent { label 'agent2' }
steps {
unstash 'built'
script {
oDockImage = docker.build(strDockerImage, "--build-arg VERSION="+strDockerTag+" -f Dockerfile .")
}
}
}
// 6. 도커 이미지 푸쉬
stage('Docker Image Push') {
agent { label 'agent2' }
steps {
script {
docker.withRegistry('', 'DockerHub_Credential') {
oDockImage.push()
}
}
}
}
// 7. 스테이징 서버 배포 (docker run)
stage('Deploy Staging') {
agent { label 'agent2' }
steps {
sh '''
docker stop guestbookapp || true
docker rm guestbookapp || true
docker run --name=guestbookapp --rm -d \
-p 8081:10000 \
-e MYSQL_IP=host.docker.internal \
-e MYSQL_PORT=3306 \
-e MYSQL_DATABASE=guestbook \
-e MYSQL_USER=root \
-e MYSQL_PASSWORD=education \
wombat1234/cicd_guestbook:1.0
'''
}
}
// 8. 테스트 완료 후 배포 승인 여부 확인
stage('Manual Approval for Production') {
agent any
steps {
script {
input message: "스테이징 서버 테스트가 완료되었습니다. 프로덕션에 배포하시겠습니까?",
submitter: 'admin',
ok: "배포 승인"
echo 'Approval received. Proceeding with production deployment.'
}
}
}
// 9. 프로덕션 서버 배포
stage('Deploy Production') {
agent { label 'agent2' }
steps {
sshagent(credentials: ['Staing-PrivateKey']) {
sh "ssh -o StrictHostKeyChecking=no ec2-user@43.201.84.97 docker container rm -f guestbookapp"
sh "ssh -o StrictHostKeyChecking=no ec2-user@43.201.84.97 docker container run \
-d \
-p 8081:10000 \
--name=guestbookapp \
-e MYSQL_IP=172.31.0.120 \
-e MYSQL_PORT=3306 \
-e MYSQL_DATABASE=guestbook \
-e MYSQL_USER=guestbook \
-e MYSQL_PASSWORD=education \
wombat1234/cicd_guestbook:1.0 "
}
}
}
}
post {
success {
slackSend(tokenCredentialId: 'slack-token'
, channel: '#젠킨스-노티'
, color: 'good'
, message: "${JOB_NAME} (${BUILD_NUMBER}) 빌드 성공 ✅ Details: (<${BUILD_URL} | here >)")
}
failure {
slackSend(tokenCredentialId: 'slack-token'
, channel: '#젠킨스-노티'
, color: 'danger'
, message: "${JOB_NAME} (${BUILD_NUMBER}) 빌드 실패 ❌ Details: (<${BUILD_URL} | here >)")
}
}
}