Release:v1.0.0-beta.18 #18
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: CI/CD | |
# workflow가 작동될 branch와, 작동시킬 trigger 설정 | |
on: | |
pull_request: | |
types: [ closed ] | |
branches: [ "main" ] | |
# git repo에 대해 읽기 권한만 부여 | |
permissions: | |
contents: read | |
# workflow에서 실행할 작업 정의 | |
jobs: | |
CI-CD: | |
# PR이 merge된 경우에만 실행 | |
if: github.event.pull_request.merged == true | |
# ubuntu 24.04 환경에서 실행 | |
runs-on: ubuntu-24.04 | |
steps: | |
- uses: actions/checkout@v4 | |
# JDK 17 설정 | |
- name: Set up JDK 17 | |
uses: actions/setup-java@v4 | |
with: | |
java-version: '17' | |
distribution: 'temurin' | |
# Gradle 캐싱 설정 | |
- name: Gradle Caching | |
uses: actions/cache@v4 | |
with: | |
path: | | |
~/.gradle/caches | |
~/.gradle/wrapper | |
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} | |
restore-keys: | | |
${{ runner.os }}-gradle- | |
# 도커 레이어 캐싱 설정 | |
## Buildx 설정 (효율적인 캐싱을 위한 도커 빌더) | |
- name: Set up Docker Buildx | |
uses: docker/setup-buildx-action@v3 | |
## 캐시 저장소 설정 | |
- name: Cache Docker layers | |
uses: actions/cache@v4 | |
with: | |
path: /tmp/.buildx-cache # 캐시가 저장될 경로 | |
key: ${{ runner.os }}-buildx-${{ github.sha }} # 캐시 식별자 | |
restore-keys: | # 일치하는 캐시가 없을 때 사용할 이전 캐시 | |
${{ runner.os }}-buildx- | |
# application-prod.yml 생성 | |
- name: make application-prod.yml | |
run: | | |
mkdir -p ./src/main/resources | |
cd ./src/main/resources | |
touch ./application-prod.yml | |
echo '${{ secrets.PRODUCTION_YML }}' > ./application-prod.yml | |
shell: bash | |
# gradle wrapper 파일에 실행 권한을 부여 | |
# (gradle wrapper = 개발자가 특정 버전의 Gradle을 미리 설치하지 않고도 Gradle 빌드를 실행할 수 있게 해주는 편리한 도구) | |
- name: Grant execute permission for gradlew | |
run: chmod +x gradlew | |
# 프로젝트 build: -x test 옵션을 사용하면 테스트 없이 빌드 | |
- name: Build with Gradle | |
run: ./gradlew build -i -x test | |
# 도커 이미지 빌드 & 이미지를 도커허브로 push | |
## DOCKER_PASSWORD: 도커 허브 Token | |
## DOCKER_USERNAME: 도커 허브 유저네임 | |
## PRODUCTION_REPO: 도커 허브 레포지토리 이름 | |
- name: Docker build & push to dockerhub | |
run: | | |
echo ${{ secrets.DOCKER_PASSWORD }} | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin | |
docker build --build-arg PROFILE=prod -t ${{ secrets.DOCKER_USERNAME }}/${{ secrets.PRODUCTION_REPO }}:${{ github.run_number }} . | |
docker push ${{ secrets.DOCKER_USERNAME }}/${{ secrets.PRODUCTION_REPO }}:${{ github.run_number }} | |
# ec2에 ssh로 접속하여 도커 이미지 실행 | |
- name: Deploy to prod | |
uses: appleboy/ssh-action@master | |
id: deploy-prod | |
with: | |
# EC2 Public IP | |
host: ${{ secrets.PRODUCTION_HOST_EC2 }} | |
username: ubuntu | |
# EC2 ssh 접속 pem-key | |
key: ${{ secrets.EC2_PRIVATE_KEY }} | |
envs: GITHUB_SHA | |
script: | | |
sudo docker login -u "${{ secrets.DOCKER_USERNAME }}" -p "${{ secrets.DOCKER_PASSWORD }}" | |
sudo docker ps | |
sudo docker stop "${{ secrets.SERVICE_NAME }}" || true | |
sudo docker rm "${{ secrets.SERVICE_NAME }}" || true | |
sudo docker pull "${{ secrets.DOCKER_USERNAME }}"/"${{ secrets.PRODUCTION_REPO }}":"${{ github.run_number }}" | |
sudo docker run -d --name "${{ secrets.SERVICE_NAME }}" -p "${{ secrets.PRODUCTION_SERVICE_PORT }}":"${{ secrets.PRODUCTION_SERVICE_PORT }}" --network "${{ secrets.PRODUCTION_DOCKER_NETWORK }}" "${{ secrets.DOCKER_USERNAME }}"/"${{ secrets.PRODUCTION_REPO }}":"${{ github.run_number }}" | |
sudo docker image prune -a -f | |
# 배포 실패시 롤백 | |
- name: Rollback on failure | |
if: failure() && steps.deploy-prod.outcome == 'failure' | |
uses: appleboy/ssh-action@master | |
with: | |
host: ${{ secrets.PRODUCTION_HOST_EC2 }} | |
username: ubuntu | |
key: ${{ secrets.EC2_PRIVATE_KEY }} | |
script: | | |
sudo docker login -u "${{ secrets.DOCKER_USERNAME }}" -p "${{ secrets.DOCKER_PASSWORD }}" | |
sudo docker ps | |
sudo docker stop "${{ secrets.SERVICE_NAME }}" || true | |
sudo docker rm "${{ secrets.SERVICE_NAME }}" || true | |
sudo docker pull "${{ secrets.DOCKER_USERNAME }}"/"${{ secrets.PRODUCTION_REPO }}":$((${github.run_number}-1)) | |
sudo docker run -d \ | |
-e DB_PASSWORD="${{ secrets.DB_PASSWORD }}" \ | |
-e MAIL_PASSWORD="${{ secrets.MAIL_PASSWORD }}" \ | |
-e AWS_ACCESS_KEY="${{ secrets.AWS_ACCESS_KEY }}" \ | |
-e AWS_SECRET_KEY="${{ secrets.AWS_SECRET_KEY }}" \ | |
-e JWT_SECRET_KEY="${{ secrets.JWT_SECRET_KEY }}" \ | |
--name "${{ secrets.SERVICE_NAME }}" -p "${{ secrets.PRODUCTION_SERVICE_PORT }}":"${{ secrets.PRODUCTION_SERVICE_PORT }}" --network "${{ secrets.PRODUCTION_DOCKER_NETWORK }}" "${{ secrets.DOCKER_USERNAME }}"/"${{ secrets.PRODUCTION_REPO }}":$((${github.run_number}-1)) | |
sudo docker image prune -a -f |