Skip to content

Merge pull request #50 from prgrms-web-devcourse-final-project/chore/… #81

Merge pull request #50 from prgrms-web-devcourse-final-project/chore/…

Merge pull request #50 from prgrms-web-devcourse-final-project/chore/… #81

name: CI-CD_Pipeline
permissions:
contents: read
packages: write
id-token: write
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main, develop ]
workflow_dispatch:
jobs:
tests:
strategy:
fail-fast: false
matrix:
os: [ ubuntu-latest ]
include:
- os: ubuntu-latest
gradle_cmd: "./gradlew"
report_path: "backend/build/reports/tests"
domain_tasks: "testUser testExchange testTrade_log testWallet testCoin"
runs-on: ${{ matrix.os }}
env:
SPRING_PROFILES_ACTIVE: test-ci
# ✅ Redis 서비스 추가
services:
redis:
image: redis:7-alpine
ports:
- 6379:6379
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
env:
REDIS_PASSWORD: ""
steps:
- uses: actions/checkout@v4
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
cache: gradle
# ✅ gradlew 실행 권한 부여
- name: Grant execute permission for gradlew
run: chmod +x backend/gradlew
# ✅ Redis 연결 테스트
- name: Test Redis connection
run: |
echo "Testing Redis connection..."
timeout 10s bash -c 'until printf "" 2>>/dev/null >>/dev/tcp/localhost/6379; do sleep 1; done'
echo "Redis is ready!"
# ✅ application-test.yml에서 사용하는 모든 환경변수를 .env 파일에 생성
- name: Create test .env file
working-directory: backend
run: |
cat > .env << 'EOF'
# Datasource 설정 (application-test.yml에서 참조)
TEST_DATASOURCE_URL=jdbc:h2:mem:db_test;MODE=MySQL
TEST_DATASOURCE_USERNAME=sa
TEST_DATASOURCE_PASSWORD=
TEST_DATASOURCE_DRIVER=org.h2.Driver
# JPA 설정 (application-test.yml에서 참조)
TEST_JPA_HIBERNATE_DDL_AUTO=create-drop
# Redis 설정 (application-test.yml에서 참조, GitHub Actions 서비스 사용)
TEST_REDIS_HOST=localhost
TEST_REDIS_PORT=6379
TEST_REDIS_PASSWORD=
# CI/CD 환경에서는 Embedded Redis 끄기
SPRING_DATA_REDIS_EMBEDDED=false
# JWT 설정 (application-test.yml에서 참조)
CUSTOM_JWT_SECRET_KEY=${{ secrets.JWT_SECRET_KEY }}
CUSTOM_JWT_ACCESS_TOKEN_EXPIRATION_SECONDS=3600
EOF
- name: Run unit, and domain tests
run: ${{ matrix.gradle_cmd }} clean test
working-directory: backend
- name: Upload Test Reports
if: always()
uses: actions/upload-artifact@v4
with:
name: test-reports-${{ matrix.os }}
path: ${{ matrix.report_path }}
retention-days: 7
build-artifacts:
needs: tests
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main' # ✅ main 브랜치일 때만 실행
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 21
cache: gradle
# ✅ gradlew 실행 권한 부여
- name: Grant execute permission for gradlew
run: chmod +x backend/gradlew
# ✅ 빌드용 .env 파일 생성 (Configuration Properties 바인딩용 최소 환경변수만)
- name: Create build .env file
working-directory: backend
run: |
cat > .env << 'EOF'
# JWT Configuration Properties 바인딩용 (빌드 시 필요)
CUSTOM_JWT_SECRET_KEY=${{ secrets.JWT_SECRET_KEY }}
CUSTOM_JWT_ACCESS_TOKEN_EXPIRATION_SECONDS=3600
EOF
- name: Gradle bootJar
working-directory: backend
run: ./gradlew --no-daemon clean bootJar -x test
- name: Copy JAR to dist
working-directory: backend
run: |
mkdir -p dist
cp $(ls build/libs/*.jar | grep -v plain | head -n 1) dist/app.jar
- name: Upload backend jar
uses: actions/upload-artifact@v4
with:
name: backend-jar
path: backend/dist/app.jar
docker-build:
needs: build-artifacts
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main' # ✅ main 브랜치일 때만 실행
env:
REGISTRY: ghcr.io
IMAGE_PREFIX: ${{ github.repository_owner }}
steps:
- uses: actions/checkout@v4
- name: Download backend jar
uses: actions/download-artifact@v4
with:
name: backend-jar
path: backend/dist
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build & push backend (runtime-only)
uses: docker/build-push-action@v6
with:
context: backend
file: backend/Dockerfile
push: true
tags: |
${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}/balaw:${{ github.sha }}
${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}/balaw:latest
cache-from: type=gha
cache-to: type=gha,mode=max
deploy:
needs: docker-build
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main' # ✅ main 브랜치일 때만 실행
env:
DOCKER_IMAGE_NAME: balaw
steps:
- name: Create prod .env file
run: |
cat > .env << 'EOF'
SPRING_PROFILES_ACTIVE=prod
PROD_DATASOURCE_URL=jdbc:mysql://mysql_1:3306/${{ secrets.DB_NAME }}
PROD_DATASOURCE_USERNAME=${{ secrets.DB_USER }}
PROD_DATASOURCE_PASSWORD=${{ secrets.DB_PASSWORD }}
PROD_REDIS_HOST=redis_1
PROD_REDIS_PORT=6379
PROD_REDIS_PASSWORD=${{ secrets.REDIS_PASSWORD }}
EOF
- name: AWS SSM Send-Command
uses: peterkimzz/aws-ssm-send-command@master
id: ssm
with:
aws-region: ${{ secrets.AWS_REGION }}
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
instance-ids: "i-094fd5f8988b7330b"
working-directory: /
comment: Deploy
command: |
# EC2 내부에서 prod.env 파일 생성
cat > /home/ec2-user/prod.env << 'EOF'
SPRING_PROFILES_ACTIVE=prod
PROD_DATASOURCE_URL=jdbc:mysql://mysql_1:3306/${{ secrets.DB_NAME }}
PROD_DATASOURCE_USERNAME=${{ secrets.DB_USER }}
PROD_DATASOURCE_PASSWORD=${{ secrets.DB_PASSWORD }}
PROD_REDIS_HOST=redis_1
PROD_REDIS_PORT=6379
PROD_REDIS_PASSWORD=${{ secrets.REDIS_PASSWORD }}
EOF
# EC2에서 GHCR 로그인
echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u doohyojeong --password-stdin
# 최신 이미지 pull & 컨테이너 실행
docker pull ghcr.io/doohyojeong/${{ env.DOCKER_IMAGE_NAME }}:latest
docker stop app1 2>/dev/null
docker rm app1 2>/dev/null
docker run --env-file /home/ec2-user/prod.env -d --name app1 -p 8080:8080 \
ghcr.io/doohyojeong/${{ env.DOCKER_IMAGE_NAME }}:latest
# dangling image 정리 + .env 삭제
docker rmi $(docker images -f "dangling=true" -q)
rm -f /home/ec2-user/prod.env