Merge pull request #81 from KTB16Team/feature/76-refactor-n+1-problem #163
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: BE CI/CD with Rolling Deployment | |
on: | |
push: | |
branches: [ "develop" ] | |
pull_request: | |
branches: [ "develop" ] | |
jobs: | |
# Job 1: 빌드 및 S3 업로드 | |
build-and-upload: | |
runs-on: ubuntu-latest | |
env: | |
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} | |
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} | |
AWS_REGION: ${{ secrets.AWS_REGION }} | |
S3_BUCKET_NAME: aimo-be-server | |
steps: | |
# 1. 소스 코드 체크아웃 | |
- name: Checkout code | |
uses: actions/checkout@v4 | |
# 2. JDK 17 설정 | |
- name: Set up JDK 17 | |
uses: actions/setup-java@v4 | |
with: | |
java-version: '17' | |
distribution: 'temurin' | |
# 환경별 application.yml 파일 생성 | |
- name: Create application.yml files | |
working-directory: backend | |
run: | | |
mkdir -p src/main/resources/ | |
echo "${{ secrets.APPLICATION_DEFAULT }}" > src/main/resources/application.yml | |
echo "${{ secrets.APPLICATION_DEV }}" > src/main/resources/application-dev.yml | |
# 3. Gradle 실행 권한 설정 | |
- name: Grant execute permission to gradlew | |
run: chmod +x gradlew | |
working-directory: backend | |
# 4. Gradle 빌드 및 테스트 | |
- name: Build and Test with Gradle | |
run: ./gradlew clean build | |
working-directory: backend | |
env: | |
SPRING_DATASOURCE_URL: jdbc:mysql://aimodb.cbimeayem48r.ap-northeast-2.rds.amazonaws.com:3306/aimo | |
SPRING_DATASOURCE_USERNAME: admin | |
SPRING_DATASOURCE_PASSWORD: ${{ secrets.DB_PASSWORD }} | |
# 5. 빌드된 JAR 파일을 S3로 업로드 | |
- name: Upload JAR to S3 | |
run: | | |
aws s3 cp backend/build/libs/backend-server.jar s3://$S3_BUCKET_NAME/ | |
env: | |
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} | |
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} | |
AWS_REGION: ${{ secrets.AWS_REGION }} | |
# Job 2: EC2 배포 | |
deploy-to-ec2: | |
runs-on: ubuntu-latest | |
needs: build-and-upload | |
env: | |
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} | |
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} | |
AWS_REGION: ${{ secrets.AWS_REGION }} | |
TARGET_GROUP_ARN: ${{ secrets.TARGET_GROUP_ARN }} | |
EC2_USER: ${{ secrets.EC2_USER }} | |
EC2_SSH_KEY: ${{ secrets.EC2_SSH_KEY }} | |
EC2_HOST_1: ${{ secrets.EC2_HOST_1 }} | |
EC2_HOST_2: ${{ secrets.EC2_HOST_2 }} | |
EC2_INSTANCE_ID_1: ${{ secrets.EC2_INSTANCE_ID_1 }} | |
EC2_INSTANCE_ID_2: ${{ secrets.EC2_INSTANCE_ID_2 }} | |
S3_BUCKET_NAME: aimo-be-server | |
steps: | |
# EC2_HOST_1에서 배포 및 대상 그룹 관리 | |
- name: Deploy to EC2_HOST_1 | |
uses: appleboy/ssh-action@master | |
with: | |
host: ${{ secrets.EC2_HOST_1 }} | |
username: ${{ secrets.EC2_USER }} | |
key: ${{ secrets.EC2_SSH_KEY }} | |
script: | | |
# GitHub Secrets에서 환경 변수 설정 | |
export AWS_ACCESS_KEY_ID="${{ secrets.AWS_ACCESS_KEY_ID }}" | |
export AWS_SECRET_ACCESS_KEY="${{ secrets.AWS_SECRET_ACCESS_KEY }}" | |
export AWS_REGION="${{ secrets.AWS_REGION }}" | |
TARGET_GROUP_ARN="${{ secrets.TARGET_GROUP_ARN }}" | |
INSTANCE_ID="${{ secrets.EC2_INSTANCE_ID_1 }}" | |
S3_BUCKET_NAME="aimo-be-server" | |
# 변수 값 확인 | |
echo "TARGET_GROUP_ARN: $TARGET_GROUP_ARN" | |
echo "INSTANCE_ID: $INSTANCE_ID" | |
# 대상 그룹에서 인스턴스 제거 | |
if [ -z "$TARGET_GROUP_ARN" ]; then | |
echo "Error: TARGET_GROUP_ARN is empty" | |
exit 1 | |
fi | |
if [ -z "$INSTANCE_ID" ]; then | |
echo "Error: INSTANCE_ID is empty" | |
exit 1 | |
fi | |
echo "Deregistering instance $INSTANCE_ID from target group $TARGET_GROUP_ARN" | |
aws elbv2 deregister-targets --target-group-arn "$TARGET_GROUP_ARN" --targets Id="$INSTANCE_ID" | |
# 기존 애플리케이션 종료 | |
if screen -list | grep -q "\bbe\b"; then screen -S be -X quit; fi | |
# S3에서 새로운 JAR 파일 다운로드 | |
echo "Downloading JAR file from S3" | |
aws s3 cp s3://$S3_BUCKET_NAME/backend-server.jar /home/ubuntu/backend-server.jar | |
# 새로운 애플리케이션 실행 | |
echo "Starting new application instance" | |
screen -dmS be java -jar /home/ubuntu/backend-server.jar | |
# 애플리케이션 시작 대기 | |
sleep 30 | |
# 대상 그룹에 인스턴스 등록 (포트 8080 사용) | |
echo "Registering instance $INSTANCE_ID to target group $TARGET_GROUP_ARN using port 8080" | |
aws elbv2 register-targets --target-group-arn "$TARGET_GROUP_ARN" --targets Id="$INSTANCE_ID",Port=8080 | |
# 인위적인 헬스 체크 (3회 반복) | |
echo "Performing manual health checks with curl (3 times)" | |
for i in {1..3}; do | |
echo "Health check attempt $i" | |
curl -X GET http://localhost:8080/actuator/health | |
sleep 5 | |
done | |
# 인스턴스가 정상 상태가 될 때까지 대기 | |
echo "Waiting for instance $INSTANCE_ID to be in service in target group $TARGET_GROUP_ARN" | |
aws elbv2 wait target-in-service --target-group-arn "$TARGET_GROUP_ARN" --targets Id="$INSTANCE_ID",Port=8080 | |
# EC2_HOST_2에서 배포 및 대상 그룹 관리 | |
- name: Deploy to EC2_HOST_2 | |
uses: appleboy/ssh-action@master | |
with: | |
host: ${{ secrets.EC2_HOST_2 }} | |
username: ${{ secrets.EC2_USER }} | |
key: ${{ secrets.EC2_SSH_KEY }} | |
script: | | |
# GitHub Secrets에서 환경 변수 설정 | |
export AWS_ACCESS_KEY_ID="${{ secrets.AWS_ACCESS_KEY_ID }}" | |
export AWS_SECRET_ACCESS_KEY="${{ secrets.AWS_SECRET_ACCESS_KEY }}" | |
export AWS_REGION="${{ secrets.AWS_REGION }}" | |
TARGET_GROUP_ARN="${{ secrets.TARGET_GROUP_ARN }}" | |
INSTANCE_ID="${{ secrets.EC2_INSTANCE_ID_2 }}" | |
S3_BUCKET_NAME="aimo-be-server" | |
# 대상 그룹에서 인스턴스 제거 | |
echo "Deregistering instance $INSTANCE_ID from target group $TARGET_GROUP_ARN" | |
aws elbv2 deregister-targets --target-group-arn "$TARGET_GROUP_ARN" --targets Id="$INSTANCE_ID" | |
# 기존 애플리케이션 종료 | |
if screen -list | grep -q "\bbe\b"; then screen -S be -X quit; fi | |
# S3에서 새로운 JAR 파일 다운로드 | |
echo "Downloading JAR file from S3" | |
aws s3 cp s3://$S3_BUCKET_NAME/backend-server.jar /home/ubuntu/backend-server.jar | |
# 새로운 애플리케이션 실행 | |
echo "Starting new application instance" | |
screen -dmS be java -jar /home/ubuntu/backend-server.jar | |
# 애플리케이션 시작 대기 | |
sleep 30 | |
# 대상 그룹에 인스턴스 등록 (포트 8080 사용) | |
echo "Registering instance $INSTANCE_ID to target group $TARGET_GROUP_ARN using port 8080" | |
aws elbv2 register-targets --target-group-arn "$TARGET_GROUP_ARN" --targets Id="$INSTANCE_ID",Port=8080 | |
# 인위적인 헬스 체크 (3회 반복) | |
echo "Performing manual health checks with curl (3 times)" | |
for i in {1..3}; do | |
echo "Health check attempt $i" | |
curl -X GET http://localhost:8080/actuator/health | |
sleep 5 | |
done | |
# 인스턴스가 정상 상태가 될 때까지 대기 | |
echo "Waiting for instance $INSTANCE_ID to be in service in target group $TARGET_GROUP_ARN" | |
aws elbv2 wait target-in-service --target-group-arn "$TARGET_GROUP_ARN" --targets Id="$INSTANCE_ID",Port=8080 | |