-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathJenkinsfile
More file actions
162 lines (141 loc) · 7.25 KB
/
Jenkinsfile
File metadata and controls
162 lines (141 loc) · 7.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
pipeline {
agent any
environment {
IMAGE_NAME = 'kimkangyeon/hanok-backend'
CONTAINER_NAME = 'hanok-backend-prod'
COMPOSE_FILE = 'infra/docker-compose.yaml'
ENV_FILE = 'infra/.env.prod'
}
stages {
stage('Check Branch') {
when {
expression { env.GIT_BRANCH == 'origin/master' }
}
stages {
stage('Build') {
parallel {
stage('Backend Build') {
steps {
dir('be') {
sh 'chmod +x gradlew'
withSonarQubeEnv('sonarqube') {
// 🚨 [수정됨] || true 제거! 이제 컴파일/테스트 실패 시 여기서 배포가 즉시 멈춥니다.
sh '''./gradlew bootJar sonar --no-daemon --build-cache --continue -x test -x compileTestJava \
-Dsonar.projectKey=hanok \
-Dsonar.projectName=hanok \
-Dsonar.host.url=http://j14d105.p.ssafy.io:9000'''
}
}
}
}
stage('Frontend Build') {
steps {
dir('fe') {
sh 'cp /var/jenkins_home/env/.env.fe .env'
sh 'npm install --legacy-peer-deps'
sh 'npm run build'
sh 'gzip -k dist/landging_model.glb || true'
}
}
}
}
}
stage('Docker Build & Push') {
steps {
dir('be') {
withCredentials([usernamePassword(
credentialsId: 'dockerhub-credentials',
usernameVariable: 'DOCKER_USER',
passwordVariable: 'DOCKER_PASS'
)]) {
sh '''
docker login -u $DOCKER_USER -p $DOCKER_PASS
docker build -t $DOCKER_USER/hanok-backend:prod \
-t $DOCKER_USER/hanok-backend:${BUILD_NUMBER} .
docker push $DOCKER_USER/hanok-backend:prod
docker push $DOCKER_USER/hanok-backend:${BUILD_NUMBER}
docker images $DOCKER_USER/hanok-backend --format "{{.Tag}}" | \
grep -v prod | sort -rn | tail -n +4 | \
xargs -I {} docker rmi $DOCKER_USER/hanok-backend:{} 2>/dev/null || true
'''
}
}
}
}
stage('Deploy') {
steps {
sh '''
set +e
# Nginx 상태 확인 및 기동
if ! docker ps | grep -q hanok-nginx; then
docker-compose -f ${COMPOSE_FILE} --env-file ${ENV_FILE} up -d nginx
sleep 3
fi
cp /var/jenkins_home/env/.env.prod infra/.env.prod
LIVEKIT_SECRET=$(grep LIVEKIT_API_SECRET infra/.env.prod | cut -d '=' -f2)
cat > infra/livekit.yaml << LKEOF
port: 7880
keys:
devkey: ${LIVEKIT_SECRET}
webhook:
urls:
- http://13.124.238.68/api/v1/streams/webhook
api_key: devkey
LKEOF
# upstream.conf 파일 자동 생성 (초기화)
if [ ! -f infra/nginx/conf.d/upstream.conf ]; then
echo "upstream backend { server backend-prod:8080; }" > infra/nginx/conf.d/upstream.conf
fi
# 기본 인프라 컨테이너 실행
docker-compose -f ${COMPOSE_FILE} --env-file ${ENV_FILE} up -d mysql redis redis-exporter livekit prometheus grafana loki promtail influxdb
# 배포 타겟 결정
ACTIVE_TARGET=$(grep -oP 'server \\K[^:]+' infra/nginx/conf.d/upstream.conf || echo "backend-green")
if [ "$ACTIVE_TARGET" = "backend-prod" ] || [ -z "$ACTIVE_TARGET" ]; then
TARGET="backend-green"
TARGET_PORT="8081"
STOP_TARGET="backend-prod"
else
TARGET="backend-prod"
TARGET_PORT="8080"
STOP_TARGET="backend-green"
fi
echo "현재 활성 상태: ${STOP_TARGET} → ${TARGET} 배포 시작"
docker-compose -f ${COMPOSE_FILE} --env-file ${ENV_FILE} pull ${TARGET}
docker-compose -f ${COMPOSE_FILE} --env-file ${ENV_FILE} up -d --no-deps ${TARGET}
# 헬스체크
HEALTH="000"
for i in $(seq 1 30); do
HEALTH=$(curl -s -o /dev/null -w "%{http_code}" http://172.26.0.24:${TARGET_PORT}/actuator/health)
if [ "$HEALTH" = "200" ]; then break; fi
echo "헬스체크 대기 중... ($i/30)"
sleep 10
done
if [ "$HEALTH" = "200" ]; then
echo "upstream backend { server ${TARGET}:8080; }" > infra/nginx/conf.d/upstream.conf
docker exec hanok-nginx nginx -s reload
sleep 3
docker-compose -f ${COMPOSE_FILE} --env-file ${ENV_FILE} stop ${STOP_TARGET}
echo "배포 완료 - ${TARGET} 활성화"
else
echo "❌ ${TARGET} 헬스체크 실패! 기존 서버(${STOP_TARGET}) 유지"
docker-compose -f ${COMPOSE_FILE} --env-file ${ENV_FILE} stop ${TARGET}
exit 1
fi
# 프론트엔드 파일 복사
rm -rf /var/www/hanok/*
cp -r fe/dist/* /var/www/hanok/
'''
}
}
}
}
}
post {
success {
echo '배포 성공!'
}
failure {
echo '배포 실패!'
}
}
}