Skip to content

Feature: rabbitmq 구현(85) #170

Feature: rabbitmq 구현(85)

Feature: rabbitmq 구현(85) #170

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