Skip to content

Commit

Permalink
Merge pull request KU-rum#128 from kmw10693/chore/KU-rum#127
Browse files Browse the repository at this point in the history
chore: 젠킨스를 이용한 무중단 배포 적용 (KU-rum#127)
  • Loading branch information
kmw10693 authored Feb 28, 2025
2 parents 9290bb3 + 7b52be8 commit 348e0c4
Show file tree
Hide file tree
Showing 11 changed files with 239 additions and 23 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
.env
HELP.md
src/main/resources/application.yml
src/main/resources/application-prod.yml
src/main/resources/application-local.yml
.gradle
build/
!gradle/wrapper/gradle-wrapper.jar
Expand Down
22 changes: 0 additions & 22 deletions Dockerfile

This file was deleted.

53 changes: 53 additions & 0 deletions Jenkinsfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
pipeline{
agent any
environment {
SCRIPT_PATH = '/var/jenkins_home/custom/kurum'
}
tools {
gradle 'kurum'
}
stages{
stage('Checkout') {
steps {
checkout scm
}
}
stage('Prepare'){
steps {
sh 'gradle clean'
}
}
stage('Replace Prod Properties') {
steps {
withCredentials([file(credentialsId: 'kurumprod', variable: 'kurumprod')]) {
script {
sh 'cp $kurumprod ./src/main/resources/application-prod.yml'
}
}
}
}
stage('Build') {
steps {
sh 'gradle build -x test'
}
}
stage('Test') {
steps {
sh 'gradle test'
}
}
stage('Deploy') {
steps {
sh '''
cp ./docker/docker-compose.blue.yml ${SCRIPT_PATH}
cp ./docker/docker-compose.green.yml ${SCRIPT_PATH}
cp ./docker/Dockerfile ${SCRIPT_PATH}
cp ./scripts/deploy.sh ${SCRIPT_PATH}
cp ./build/libs/*.jar ${SCRIPT_PATH}
chmod +x ${SCRIPT_PATH}/deploy.sh
${SCRIPT_PATH}/deploy.sh
'''
}
}
}
}
4 changes: 4 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,10 @@ tasks.named('test') {
useJUnitPlatform()
}

tasks.named('jar') {
enabled = false
}

// 10. openapi3가 먼저 실행
tasks.withType(GenerateSwaggerUI) {
dependsOn 'openapi3'
Expand Down
11 changes: 11 additions & 0 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Java 17 베이스 이미지 사용
FROM openjdk:17-jdk-slim

# Dockerfile 내에서 사용할 변수 JAR_FILE을 정의
ARG JAR_FILE=*.jar

# JAR_FILE 경로에 해당하는 파일을 Docker 이미지 내부로 복사
COPY ${JAR_FILE} spring-prod.jar

# Docker 컨테이너가 시작될 때 실행할 명령을 지정
ENTRYPOINT ["java", "-jar", "/spring-prod.jar"]
19 changes: 19 additions & 0 deletions docker/docker-compose.blue.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
version: '3'
services:
backend:
# 현재 디렉토리에서의 Dockerfile을 사용하여 Docker 이미지를 빌드
build: .
# 호스트의 8111 포트와 컨테이너의 8080 포트를 매핑
ports:
- "8111:8080"
# 컨테이너의 이름
container_name: spring-kurum-blue
environment:
- TZ=Asia/Seoul
networks:
- servernetwork

networks:
servernetwork:
external: true
driver: bridge
16 changes: 16 additions & 0 deletions docker/docker-compose.green.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
version: '3'
services:
backend:
build: .
ports:
- "8112:8080"
container_name: spring-kurum-green
environment:
- TZ=Asia/Seoul
networks:
- servernetwork

networks:
servernetwork:
external: true
driver: bridge
File renamed without changes.
58 changes: 58 additions & 0 deletions scripts/deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#!/bin/bash
# 작업 디렉토리를 /var/jenkins_home/custom/snapcampus으로 변경
cd /var/jenkins_home/custom/kurum

# 환경변수 DOCKER_APP_NAME : 컨테이너 메인 이름
DOCKER_APP_NAME=spring-kurum
LOG_FILE=./deploy.log

# 실행중인 blue가 있는지 확인
# 프로젝트의 실행 중인 컨테이너를 확인하고, 해당 컨테이너가 실행 중인지 여부를 EXIST_BLUE 변수에 저장
EXIST_BLUE=$(docker-compose -p "${DOCKER_APP_NAME}-blue" -f docker-compose.blue.yml ps | grep -E "Up|running")

# 배포 시작한 날짜와 시간을 기록
echo "배포 시작일자 : $(date +%Y)-$(date +%m)-$(date +%d) $(date +%H):$(date +%M):$(date +%S)" >> $LOG_FILE


# green이 실행중이면 blue up
# EXIST_BLUE 변수가 비어있는지 확인
if [ -z "$EXIST_BLUE" ]; then

# 로그 파일에 "blue up - blue 배포 : port:8081"이라는 내용을 추가
echo "blue 배포 시작 : $(date +%Y)-$(date +%m)-$(date +%d) $(date +%H):$(date +%M):$(date +%S)" >> $LOG_FILE

# docker-compose.blue.yml 파일을 사용하여 blue 컨테이너를 빌드하고 실행
docker-compose -p ${DOCKER_APP_NAME}-blue -f docker-compose.blue.yml up -d --build

# 30초 동안 대기
sleep 30

# 로그 파일에 "green 중단 시작"이라는 내용을 추가
echo "green 중단 시작 : $(date +%Y)-$(date +%m)-$(date +%d) $(date +%H):$(date +%M):$(date +%S)" >> $LOG_FILE

# docker-compose.green.yml 파일을 사용하여 green 컨테이너를 중지
docker-compose -p ${DOCKER_APP_NAME}-green -f docker-compose.green.yml down

# 사용하지 않는 이미지 삭제
docker image prune -af

echo "green 중단 완료 : $(date +%Y)-$(date +%m)-$(date +%d) $(date +%H):$(date +%M):$(date +%S)" >> $LOG_FILE

# blue가 실행중이면 green up
else
echo "green 배포 시작 : $(date +%Y)-$(date +%m)-$(date +%d) $(date +%H):$(date +%M):$(date +%S)" >> $LOG_FILE
docker-compose -p ${DOCKER_APP_NAME}-green -f docker-compose.green.yml up -d --build

sleep 30

echo "blue 중단 시작 : $(date +%Y)-$(date +%m)-$(date +%d) $(date +%H):$(date +%M):$(date +%S)" >> $LOG_FILE
docker-compose -p ${DOCKER_APP_NAME}-blue -f docker-compose.blue.yml down
docker image prune -af

echo "blue 중단 완료 : $(date +%Y)-$(date +%m)-$(date +%d) $(date +%H):$(date +%M):$(date +%S)" >> $LOG_FILE

fi
echo "배포 종료 : $(date +%Y)-$(date +%m)-$(date +%d) $(date +%H):$(date +%M):$(date +%S)" >> $LOG_FILE

echo "===================== 배포 완료 =====================" >> $LOG_FILE
echo >> $LOG_FILE
17 changes: 17 additions & 0 deletions src/main/resources/application.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
spring:
application:
name: kurum
profiles:
active: prod

thymeleaf:
prefix: classpath:/templates/
suffix: .html
cache: false
encoding: UTF-8
mode: HTML
enabled: true

logging:
level:
org.springframework.cache: trace
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package ku_rum.backend.domain.common.wein.application;

import ku_rum.backend.domain.common.wein.dto.request.WeinLoginRequest;
import ku_rum.backend.global.exception.wein.WeinException;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.http.*;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import static org.junit.jupiter.api.Assertions.*;

@ExtendWith(MockitoExtension.class)
@DataJpaTest
@AutoConfigureMockMvc
public class WeinServiceTest {

@InjectMocks
private WeinService weinService;

@Mock
private RestTemplate restTemplate;

@Mock
private HttpHeaders headers;

@Mock
private CloseableHttpClient httpClient;

@Test
void loginToWein_ExceptionHandling() {
// given
WeinLoginRequest request = new WeinLoginRequest("testUser", "testPass");

// when & then
assertThrows(WeinException.class, () -> weinService.loginToWein(request));
}

@Test
void createRequestBody_CorrectlyCreatesForm() {
// given
WeinLoginRequest request = new WeinLoginRequest("testUser", "testPass");

// when
MultiValueMap<String, String> requestBody = weinService.createRequestBody(request);

// then
assertEquals("testUser", requestBody.getFirst("userId"));
assertEquals("testPass", requestBody.getFirst("pw"));
assertEquals("", requestBody.getFirst("rtnUrl"));
}
}

0 comments on commit 348e0c4

Please sign in to comment.