Skip to content
64 changes: 57 additions & 7 deletions .github/workflows/prod-server.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
- name: Checkout code
uses: actions/checkout@v4

- name: Deploy to Test Environment
- name: Deploy to Production Environment
uses: appleboy/[email protected]
with:
host: ${{ secrets.PROD_SERVER_HOST }}
Expand All @@ -39,6 +39,58 @@ jobs:
# 최신 이미지 pull
docker pull ghcr.io/${{ github.repository }}/zoopzoop:latest

# .env 파일 생성
cat << EOF > .env
# DB
SPRING_DATASOURCE_URL=${{secrets.PROD_DB_URL}}
SPRING_DATASOURCE_USERNAME=${{secrets.PROD_DB_USERNAME}}
SPRING_DATASOURCE_PASSWORD=${{secrets.PROD_DB_PASSWORD}}

# RabbitMQ
SPRING_RABBITMQ_HOST=${{secrets.PROD_RABBITMQ_HOST}}
SPRING_RABBITMQ_USERNAME=${{secrets.PROD_RABBITMQ_USERNAME}}
SPRING_RABBITMQ_PASSWORD=${{secrets.PROD_RABBITMQ_PASSWORD}}

# Kakao OAuth
OAUTH_KAKAO_CLIENT_ID=${{secrets.OAUTH_KAKAO_CLIENT_ID}}
OAUTH_KAKAO_CLIENT_SECRET=${{secrets.OAUTH_KAKAO_CLIENT_SECRET}}
OAUTH_KAKAO_REDIRECT_URI=${{secrets.PROD_OAUTH_KAKAO_REDIRECT_URI}}

# Google OAuth
OAUTH_GOOGLE_CLIENT_ID=${{secrets.OAUTH_GOOGLE_CLIENT_ID}}
OAUTH_GOOGLE_CLIENT_SECRET=${{secrets.OAUTH_GOOGLE_CLIENT_SECRET}}
OAUTH_GOOGLE_REDIRECT_URI=${{secrets.PROD_OAUTH_GOOGLE_REDIRECT_URI}}

# AWS
AWS_ACCESS_KEY_ID=${{secrets.AWS_ACCESS_KEY_ID}}
AWS_SECRET_ACCESS_KEY=${{secrets.AWS_SECRET_ACCESS_KEY}}
AWS_REGION=${{secrets.AWS_REGION}}
AWS_S3_BUCKET_NAME=${{secrets.AWS_S3_BUCKET_NAME}}

# Redis
REDIS_HOST=${{secrets.REDIS_HOST}}
REDIS_PORT=${{secrets.REDIS_PORT}}
REDIS_PASSWORD=${{secrets.REDIS_PASSWORD}}

# Naver API
NAVER_CLIENT_ID=${{secrets.NAVER_CLIENT_ID}}
NAVER_CLIENT_SECRET=${{secrets.NAVER_CLIENT_SECRET}}

# JWT
JWT_SECRET_KEY=${{secrets.JWT_SECRET_KEY}}
JWT_ACCESS_TOKEN_VALIDITY=${{secrets.JWT_ACCESS_TOKEN_VALIDITY}}
JWT_REFRESH_TOKEN_VALIDITY=${{secrets.JWT_REFRESH_TOKEN_VALIDITY}}

# Frontend Redirect
FRONT_REDIRECT_DOMAIN=${{secrets.FRONT_REDIRECT_DOMAIN}}

# Liveblocks
LIVEBLOCKS_SECRET_KEY=${{secrets.LIVEBLOCKS_SECRET_KEY}}

# Sentry
SENTRY_DSN=${{secrets.SENTRY_DSN}}
EOF

# NPM API 설정
NPM_HOST="localhost:81"
NPM_EMAIL="${{secrets.NPM_ADMIN_EMAIL}}"
Expand Down Expand Up @@ -77,17 +129,15 @@ jobs:
NEW_PORT=8081
fi

# 스크립트 종료 시 .env 파일 자동 삭제
trap 'rm -f .env' EXIT

echo "Starting new container: $NEW_CONTAINER on port $NEW_PORT"
docker run -d --restart unless-stopped \
-p $NEW_PORT:8080 \
--name $NEW_CONTAINER \
--network common \
-e SPRING_DATASOURCE_URL="${{secrets.PROD_DB_URL}}" \
-e SPRING_DATASOURCE_USERNAME="${{secrets.PROD_DB_USERNAME}}" \
-e SPRING_DATASOURCE_PASSWORD="${{secrets.PROD_DB_PASSWORD}}" \
-e SPRING_RABBITMQ_HOST="${{secrets.PROD_RABBITMQ_HOST}}" \
-e SPRING_RABBITMQ_USERNAME="${{secrets.PROD_RABBITMQ_USERNAME}}" \
-e SPRING_RABBITMQ_PASSWORD="${{secrets.PROD_RABBITMQ_PASSWORD}}" \
--env-file .env \
ghcr.io/${{ github.repository }}/zoopzoop:latest


Expand Down
73 changes: 63 additions & 10 deletions .github/workflows/test-server-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,69 @@ jobs:
echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u "${{ github.repository_owner }}" --password-stdin
docker pull ghcr.io/${{ github.repository }}/zoopzoop:latest

# .env 파일 생성
cat << EOF > .env
# DB
SPRING_DATASOURCE_URL=${{secrets.TEST_DB_URL}}
SPRING_DATASOURCE_USERNAME=${{secrets.TEST_DB_USERNAME}}
SPRING_DATASOURCE_PASSWORD=${{secrets.TEST_DB_PASSWORD}}

# RabbitMQ
SPRING_RABBITMQ_HOST=${{secrets.TEST_RABBITMQ_HOST}}
SPRING_RABBITMQ_USERNAME=${{secrets.TEST_RABBITMQ_USERNAME}}
SPRING_RABBITMQ_PASSWORD=${{secrets.TEST_RABBITMQ_PASSWORD}}

# Kakao OAuth
OAUTH_KAKAO_CLIENT_ID=${{secrets.OAUTH_KAKAO_CLIENT_ID}}
OAUTH_KAKAO_CLIENT_SECRET=${{secrets.OAUTH_KAKAO_CLIENT_SECRET}}
OAUTH_KAKAO_REDIRECT_URI=${{secrets.TEST_OAUTH_KAKAO_REDIRECT_URI}}

# Google OAuth
OAUTH_GOOGLE_CLIENT_ID=${{secrets.OAUTH_GOOGLE_CLIENT_ID}}
OAUTH_GOOGLE_CLIENT_SECRET=${{secrets.OAUTH_GOOGLE_CLIENT_SECRET}}
OAUTH_GOOGLE_REDIRECT_URI=${{secrets.TEST_OAUTH_GOOGLE_REDIRECT_URI}}

# AWS
AWS_ACCESS_KEY_ID=${{secrets.AWS_ACCESS_KEY_ID}}
AWS_SECRET_ACCESS_KEY=${{secrets.AWS_SECRET_ACCESS_KEY}}
AWS_REGION=${{secrets.AWS_REGION}}
AWS_S3_BUCKET_NAME=${{secrets.AWS_S3_BUCKET_NAME}}

# Redis
REDIS_HOST=${{secrets.REDIS_HOST}}
REDIS_PORT=${{secrets.REDIS_PORT}}
REDIS_PASSWORD=${{secrets.REDIS_PASSWORD}}

# Naver API
NAVER_CLIENT_ID=${{secrets.NAVER_CLIENT_ID}}
NAVER_CLIENT_SECRET=${{secrets.NAVER_CLIENT_SECRET}}

# JWT
JWT_SECRET_KEY=${{secrets.JWT_SECRET_KEY}}
JWT_ACCESS_TOKEN_VALIDITY=${{secrets.JWT_ACCESS_TOKEN_VALIDITY}}
JWT_REFRESH_TOKEN_VALIDITY=${{secrets.JWT_REFRESH_TOKEN_VALIDITY}}

# Frontend Redirect
FRONT_REDIRECT_DOMAIN=${{secrets.FRONT_REDIRECT_DOMAIN}}

# Liveblocks
LIVEBLOCKS_SECRET_KEY=${{secrets.LIVEBLOCKS_SECRET_KEY}}

# Sentry
SENTRY_DSN=${{secrets.SENTRY_DSN}}
EOF

# NPM API 설정
NPM_HOST="localhost:81"
NPM_EMAIL="${{ secrets.NPM_ADMIN_EMAIL }}"
NPM_PASSWORD="${{ secrets.NPM_ADMIN_PASSWORD }}"
PROXY_HOST_ID="${{ secrets.NPM_PROXY_HOST_ID }}"

NPM_EMAIL="${{secrets.NPM_ADMIN_EMAIL}}"
NPM_PASSWORD="${{secrets.NPM_ADMIN_PASSWORD}}"
PROXY_HOST_ID="${{secrets.NPM_PROXY_HOST_ID}}"
# NPM 토큰
TOKEN=$(curl -s -X POST "http://${NPM_HOST}/api/tokens" \
-H "Content-Type: application/json" \
-d "{\"identity\":\"${NPM_EMAIL}\",\"secret\":\"${NPM_PASSWORD}\"}" | jq -r '.token')

if [ -z "$TOKEN" ] || [ "$TOKEN" == "null" ]; then
echo "❌ Failed to get NPM API token"
exit 1
Expand All @@ -54,17 +108,16 @@ jobs:
OLD_CONTAINER=zoopzoop-green
NEW_PORT=8081
fi

# 스크립트 종료 시 .env 파일 자동 삭제
trap 'rm -f .env' EXIT

# 새 컨테이너 실행 (.env 사용)
docker run -d --restart unless-stopped \
-p $NEW_PORT:8080 \
--name $NEW_CONTAINER \
--network common \
-e SPRING_DATASOURCE_URL="${{secrets.TEST_DB_URL}}" \
-e SPRING_DATASOURCE_USERNAME="${{secrets.TEST_DB_USERNAME}}" \
-e SPRING_DATASOURCE_PASSWORD="${{secrets.TEST_DB_PASSWORD}}" \
-e SPRING_RABBITMQ_HOST="${{secrets.TEST_RABBITMQ_HOST}}" \
-e SPRING_RABBITMQ_USERNAME="${{secrets.TEST_RABBITMQ_USERNAME}}" \
-e SPRING_RABBITMQ_PASSWORD="${{secrets.TEST_RABBITMQ_PASSWORD}}" \
--env-file .env \
ghcr.io/${{ github.repository }}/zoopzoop:latest

# 헬스체크
Expand Down
86 changes: 35 additions & 51 deletions .github/workflows/test-server-ci.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# 워크플로우 이름
name: Spring CI/CD Pipeline (Develop)

# develop 브랜치 PR에서만 실행
on:
pull_request:
branches:
Expand All @@ -15,41 +14,32 @@ on:
- '.github/workflows/**'

jobs:
# ==================================
# CI: Test and Build and Push Docker Image
# ==================================
ci:
runs-on: ubuntu-latest
env:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}


# CI 작업이 실행되는 동안 RabbitMQ 서비스 컨테이너를 함께 실행
services:
rabbitmq:
image: rabbitmq:3-management
ports:
- 5672:5672
# RabbitMQ가 완전히 준비될 때까지 기다리는 상태 확인 옵션
options: >-
--health-cmd "rabbitmq-diagnostics check_running"
--health-interval 10s
--health-timeout 5s
--health-retries 5

steps:
# 1. 소스 코드 체크아웃
- name: Checkout source code
uses: actions/checkout@v4

# 2. JDK 21 설치
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'

# 3. Gradle 캐시 설정
- name: Cache Gradle packages
uses: actions/cache@v4
with:
Expand All @@ -60,43 +50,43 @@ jobs:
restore-keys: |
${{ runner.os }}-gradle-

# 4. gradlew 실행 권한 부여
- name: Grant execute permission for gradlew
run: chmod +x ./gradlew

# 5. application-secrets.yml 생성
- name: Generate application-secrets.yml
run: |
mkdir -p src/main/resources
echo "${{ secrets.APPLICATION_SECRET_YML }}" > src/main/resources/application-secrets.yml
echo "OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}" >> src/main/resources/application-secrets.yml

echo "spring.cloud.aws.region.static: ${{ secrets.AWS_REGION }}" >> src/main/resources/application-secrets.yml
echo "spring.cloud.aws.credentials.access-key: ${{ secrets.AWS_ACCESS_KEY_ID }}" >> src/main/resources/application-secrets.yml
echo "spring.cloud.aws.credentials.secret-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}" >> src/main/resources/application-secrets.yml
echo "spring.cloud.aws.s3.bucket: ${{ secrets.AWS_S3_BUCKET_NAME }}" >> src/main/resources/application-secrets.yml
echo "spring.cloud.aws.stack.auto: false" >> src/main/resources/application-secrets.yml

echo "liveblocks.secret-key: ${{ secrets.LIVEBLOCKS_SECRET_KEY }}" >> src/main/resources/application-secrets.yml

# 6. application-secrets-server.yml 생성
- name: Generate application-secrets-server.yml
# ----------------------------------
# 1. 테스트용 임시 디렉토리 생성 + secrets yml 생성
# ----------------------------------
- name: Create temp directory for secrets
run: |
mkdir -p src/main/resources
echo "${{ secrets.APPLICATION_SECRET_SERVER_YML }}" > src/main/resources/application-secrets-server.yml
echo "OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}" >> src/main/resources/application-secrets-server.yml

# 7. Gradle 테스트 실행
TMP_DIR=$(mktemp -d)
# application-secrets.yml
echo "${{ secrets.APPLICATION_SECRET_YML }}" > $TMP_DIR/application-secrets.yml
echo "OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}" >> $TMP_DIR/application-secrets.yml
echo "spring.cloud.aws.region.static: ${{ secrets.AWS_REGION }}" >> $TMP_DIR/application-secrets.yml
echo "spring.cloud.aws.credentials.access-key: ${{ secrets.AWS_ACCESS_KEY_ID }}" >> $TMP_DIR/application-secrets.yml
echo "spring.cloud.aws.credentials.secret-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}" >> $TMP_DIR/application-secrets.yml
echo "spring.cloud.aws.s3.bucket: ${{ secrets.AWS_S3_BUCKET_NAME }}" >> $TMP_DIR/application-secrets.yml
echo "spring.cloud.aws.stack.auto: false" >> $TMP_DIR/application-secrets.yml
echo "liveblocks.secret-key: ${{ secrets.LIVEBLOCKS_SECRET_KEY }}" >> $TMP_DIR/application-secrets.yml
# application-secrets-server.yml
echo "${{ secrets.APPLICATION_SECRET_SERVER_YML }}" > $TMP_DIR/application-secrets-server.yml
echo "OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}" >> $TMP_DIR/application-secrets-server.yml
echo "TMP_DIR=$TMP_DIR" >> $GITHUB_ENV

# ----------------------------------
# 2. Gradle 테스트 실행
# ----------------------------------
- name: Test with Gradle
# 테스트 단계에서 RabbitMQ 연결을 위한 환경 변수 설정
env:
SPRING_RABBITMQ_HOST: localhost
SPRING_RABBITMQ_PORT: 5672
SPRING_RABBITMQ_USERNAME: guest
SPRING_RABBITMQ_PASSWORD: guest
SPRING_CONFIG_ADDITIONAL_LOCATION: "file://$TMP_DIR/application-secrets.yml,file://$TMP_DIR/application-secrets-server.yml"
run: ./gradlew test

# 8. 테스트 결과 요약 출력
# ----------------------------------
# 3. 테스트 결과 요약
# ----------------------------------
- name: Show test results
run: |
echo "==== Test Results ===="
Expand All @@ -113,35 +103,29 @@ jobs:
echo "No test results found."
fi

# 8-1. S3 자격 증명 제거 (빌드 전에만)
- name: Remove only S3 credentials before building
run: |
CONFIG_FILE="src/main/resources/application-secrets.yml"
sed -i '/spring.cloud.aws.credentials.access-key/d' $CONFIG_FILE
sed -i '/spring.cloud.aws.credentials.secret-key/d' $CONFIG_FILE
sed -i '/spring.cloud.aws.region.static/d' $CONFIG_FILE
sed -i '/spring.cloud.aws.stack.auto/d' $CONFIG_FILE
# ----------------------------------
# 4. 테스트용 secrets 임시 디렉토리 삭제
# ----------------------------------
- name: Remove temp secrets directory
run: rm -rf ${TMP_DIR}

# 9. Gradle 빌드 실행 (테스트 성공 시)
# ----------------------------------
# 5. Gradle 빌드 (테스트 제외)
# ----------------------------------
- name: Build with Gradle
run: ./gradlew build -x test

# 10. GHCR 로그인
- name: Log in to GHCR
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}

# 11. Docker 이미지 빌드 & 푸시
- name: Build & Push Docker Image
run: |
IMAGE_NAME=ghcr.io/${{ github.repository }}/zoopzoop

docker build -t $IMAGE_NAME:${GITHUB_SHA} .
docker build -t $IMAGE_NAME:${GITHUB_SHA} .
docker tag $IMAGE_NAME:${GITHUB_SHA} $IMAGE_NAME:latest

docker push $IMAGE_NAME:${GITHUB_SHA}
docker push $IMAGE_NAME:latest

Loading
Loading