Skip to content

Merge pull request #241 from kakao-tech-campus-2nd-step3/feat/#240-sc… #195

Merge pull request #241 from kakao-tech-campus-2nd-step3/feat/#240-sc…

Merge pull request #241 from kakao-tech-campus-2nd-step3/feat/#240-sc… #195

Workflow file for this run

name: Java CI with Gradle
# Master, develop, weekly/* 브랜치에 push가 발생할 경우 동작한다.
on:
push:
branches: [ "Master", "develop", "weekly/*" ]
permissions:
contents: read
jobs:
# Spring Boot 애플리케이션을 빌드하여 도커허브에 푸시하는 과정
build-docker-image:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# Java 17 세팅
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
# Gradle Wrapper 파일 실행 권한 주기
- name: Run chmod to make gradlew executable
run: chmod +x ./gradlew
# Spring Boot 애플리케이션 빌드
- name: Build with Gradle
uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1
with:
arguments: clean bootJar
# 테스트 실행
# - name: Run tests
# run: ./gradlew test
# Docker 이미지 빌드
- name: docker image build
run: docker build -t ${{ secrets.DOCKERHUB_USERNAME }}/inplace .
# DockerHub 로그인
- name: docker login
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
# Docker Hub 이미지 푸시
- name: docker Hub push
run: docker push ${{ secrets.DOCKERHUB_USERNAME }}/inplace
# 위 과정에서 푸시한 이미지를 ec2에서 풀받아서 실행시키는 과정
run-docker-image-on-ec2:
# build-docker-image 과정이 완료되어야 실행된다.
needs: build-docker-image
runs-on: self-hosted
# weekly/* 브랜치에서는 실행되지 않도록 조건 추가
# if: startsWith(github.ref, 'refs/heads/Master') || startsWith(github.ref, 'refs/heads/develop')
# weekly/* 브랜치에서만 실행되도록
if: startsWith(github.ref, 'refs/heads/weekly/')
steps:
# 최신 이미지를 pull
- name: docker pull
run: sudo docker pull ${{ secrets.DOCKERHUB_USERNAME }}/inplace
# 현재 실행 중인 버전을 확인
- name: Check current active container
id: check_version
run: |
CURRENT_VERSION=$(sudo docker ps --format "{{.Names}}" | grep -oE "inplace-(blue|green)" || echo "")
if [[ -z "$CURRENT_VERSION" ]]; then
echo "No active container found"
echo "current_version=none" >> $GITHUB_ENV
else
CURRENT_VERSION=$(echo "$CURRENT_VERSION" | grep -oE "(blue|green)")
echo "Current running version is $CURRENT_VERSION"
echo "current_version=${CURRENT_VERSION}" >> $GITHUB_ENV
fi
# 다음 배포 버전을 결정
- name: Set next version
run: |
if [[ "${{ env.current_version }}" == "blue" ]]; then
NEXT_VERSION="green"
PORT=8081
else
NEXT_VERSION="blue"
PORT=8080
fi
echo "Next version to deploy is inplace-${NEXT_VERSION}"
echo "next_version=${NEXT_VERSION}" >> $GITHUB_ENV
echo "port=${PORT}" >> $GITHUB_ENV
# .env 파일 생성
- name: Create .env file
run: |
rm -f .env
echo "${{ secrets.ENV }}" >> .env
# 다음 버전으로 새 컨테이너를 실행
- name: Run New Container on Next Version
run: |
echo "Running new container inplace-${{ env.next_version }}"
sudo docker run --name "inplace-${{ env.next_version }}" --rm -d -p ${{ env.port }}:8080 --env-file .env ${{ secrets.DOCKERHUB_USERNAME }}/inplace
# 스프링부트 시작을 기다리기 위해 헬스 체크로 대기
- name: Wait for Spring Boot Application to Start
run: |
echo "Waiting for the application to be healthy on PORT: ${{ env.port }}..."
for i in {1..40}; do
if curl -s http://localhost:${{ env.port }}/actuator/health | grep '"status":"UP"' > /dev/null; then
echo "Application is healthy"
break
fi
echo "Waiting for new application to start...($i)"
sleep 5
done
if [ $i -eq 40 ]; then
echo "Application failed to start after 40 attempts."
exit 1
fi
# 로드 밸런서 타겟 그룹을 업데이트하여 트래픽을 새 컨테이너로 전환
- name: Update Load Balancer Target Group
if: success()
run: |
TARGET_GROUP_ARN_BLUE="${{ secrets.TARGET_GROUP_ARN_8080 }}"
TARGET_GROUP_ARN_GREEN="${{ secrets.TARGET_GROUP_ARN_8081 }}"
if [[ "${{ env.next_version }}" == "blue" ]]; then
aws elbv2 modify-listener --listener-arn ${{ secrets.LISTENER_ARN_443 }} --default-actions Type=forward,TargetGroupArn=$TARGET_GROUP_ARN_BLUE
else
aws elbv2 modify-listener --listener-arn ${{ secrets.LISTENER_ARN_443 }} --default-actions Type=forward,TargetGroupArn=$TARGET_GROUP_ARN_GREEN
fi
# 이전 컨테이너 정리 전 드레이닝 시간 부여
- name: Wait for connection draining
run: |
if [[ "${{ env.current_version }}" != "none" ]]; then
echo "Waiting 30 seconds for connection draining..."
sleep 30
fi
# 이전 컨테이너 정리
- name: Remove previous docker container
run: |
if [[ "${{ env.current_version }}" != "none" ]]; then
echo "Removing previous container inplace-${{ env.current_version }}"
sudo docker stop inplace-${{ env.current_version }} || true
sudo docker rm inplace-${{ env.current_version }} || true
else
echo "No active container to remove"
fi
# 미사용 이미지를 정리
- name: delete old docker image
run: sudo docker system prune -f