Skip to content

[deploy] #58 health check add #56

[deploy] #58 health check add

[deploy] #58 health check add #56

Workflow file for this run

name: ECS Production Deployment

Check failure on line 1 in .github/workflows/deploy.yml

View workflow run for this annotation

GitHub Actions / .github/workflows/deploy.yml

Invalid workflow file

(Line: 150, Col: 22): Unrecognized named-value: 'env'. Located at position 1 within expression: env.ECS_SERVICE, (Line: 151, Col: 22): Unrecognized named-value: 'env'. Located at position 1 within expression: env.ECS_CLUSTER
on:
push:
branches: ["dev", "ci/#28_server_re_deploy"]
workflow_dispatch: # 수동 배포 가능
env:
AWS_REGION: ap-northeast-2 # 서울 리전
ECR_REPOSITORY: returnwork # ECR 저장소 이름
ECS_SERVICE: returnwork-service # ECS 서비스 이름
ECS_CLUSTER: return-work-cluster # ECS 클러스터 이름
ECS_TASK_DEFINITION: returnwork-task # Task Definition 이름
CONTAINER_NAME: returnwork-app # 컨테이너 이름
jobs:
# Stage 1: Build & Push to ECR
build-and-push:
name: Build and Push to ECR
runs-on: ubuntu-latest
outputs:
image: ${{ steps.image.outputs.image }}
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 1 # 최신 커밋만 가져오기
# 2. application yml 파일 생성 (병렬 처리)
- name: Create application yml files
run: |
cd ./src/main/resources
cat << 'EOF' > ./application-prod.yml &
${{ secrets.APPLICATION_PROD_YML }}
EOF
cat << 'EOF' > ./application-jwt.yml &
${{ secrets.APPLICATION_JWT_YML }}
EOF
cat << 'EOF' > ./application-email.yml &
${{ secrets.APPLICATION_EMAIL_YML }}
EOF
cat << 'EOF' > ./application-redis.yml &
${{ secrets.APPLICATION_REDIS_YML }}
EOF
cat << 'EOF' > ./application-oauth.yml &
${{ secrets.APPLICATION_OAUTH_YML }}
EOF
wait # 모든 백그라운드 작업 완료 대기
shell: bash
# 3. Docker Buildx 설정 (캐시 활용)
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
driver-opts: |
image=moby/buildkit:latest
network=host
# 4. AWS 자격 증명 설정
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
# 5. Amazon ECR 로그인
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
# 6. 캐시 설정
- name: Cache Docker layers
uses: actions/cache@v3
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-
# 7. JDK 17 설정 (Gradle 빌드용)
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
cache: 'gradle' # 자동 Gradle 캐시
# 8. Gradle 빌드 (병렬 처리 & 데몬 활용)
- name: Build with Gradle
run: |
chmod +x ./gradlew
./gradlew clean build -x test \
--parallel \
--build-cache \
--configuration-cache \
--no-daemon
env:
SPRING_PROFILES_ACTIVE: prod
GRADLE_OPTS: "-Dorg.gradle.jvmargs=-Xmx2048m -XX:+UseParallelGC"
# 9. Docker 이미지 빌드 및 푸시 (멀티스테이지 + 캐시)
- name: Build and push Docker image
id: image
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: |
${{ steps.login-ecr.outputs.registry }}/${{ env.ECR_REPOSITORY }}:${{ github.sha }}
${{ steps.login-ecr.outputs.registry }}/${{ env.ECR_REPOSITORY }}:latest
cache-from: |
type=local,src=/tmp/.buildx-cache
type=registry,ref=${{ steps.login-ecr.outputs.registry }}/${{ env.ECR_REPOSITORY }}:buildcache
cache-to: |
type=local,dest=/tmp/.buildx-cache-new,mode=max
type=registry,ref=${{ steps.login-ecr.outputs.registry }}/${{ env.ECR_REPOSITORY }}:buildcache,mode=max
platforms: linux/amd64
build-args: |
BUILDKIT_INLINE_CACHE=1
outputs: type=image,push=true,push-by-digest=true,name-canonical=true,name=${{ steps.login-ecr.outputs.registry }}/${{ env.ECR_REPOSITORY }}
# 9. ECR 이미지 정리 (선택사항 - 최근 5개 이미지만 유지)
- name: Clean up old ECR images
run: |
# 이미지 리스트 가져오기 (최신 5개 제외)
IMAGES_TO_DELETE=$(aws ecr list-images \
--repository-name $ECR_REPOSITORY \
--query 'imageIds[?type(imageTag)!=`null`]|sort_by(@, &imageTag)|[:-5]' \
--output json)
# 오래된 이미지 삭제
if [ "$IMAGES_TO_DELETE" != "[]" ]; then
aws ecr batch-delete-image \
--repository-name $ECR_REPOSITORY \
--image-ids "$IMAGES_TO_DELETE"
fi
continue-on-error: true # 실패해도 배포 계속 진행
# Stage 2: Deploy to ECS
deploy-to-ecs:
name: Deploy to ECS
needs: build-and-push
runs-on: ubuntu-latest
strategy:
matrix:
include:
- service: ${{ env.ECS_SERVICE }}
cluster: ${{ env.ECS_CLUSTER }}
steps:
# 1. AWS 자격 증명 설정 (체크아웃 불필요)
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
# 2. Task Definition 다운로드 및 업데이트 (한 번에 처리)
- name: Update Task Definition
id: update-task-def
run: |
# 현재 Task Definition 가져오기
TASK_DEF=$(aws ecs describe-task-definition \
--task-definition ${{ env.ECS_TASK_DEFINITION }} \
--query taskDefinition)
# 새 이미지로 업데이트 (jq 사용)
NEW_TASK_DEF=$(echo $TASK_DEF | jq \
--arg IMAGE "${{ needs.build-and-push.outputs.image }}" \
--arg CONTAINER "${{ env.CONTAINER_NAME }}" \
'.containerDefinitions[] | select(.name==$CONTAINER).image = $IMAGE')
# 새 Task Definition 등록
TASK_ARN=$(echo $NEW_TASK_DEF | \
aws ecs register-task-definition --cli-input-json file:///dev/stdin \
--query 'taskDefinition.taskDefinitionArn' --output text)
echo "task-arn=$TASK_ARN" >> $GITHUB_OUTPUT
# 3. Blue/Green 배포 (무중단)
- name: Deploy with Circuit Breaker
run: |
aws ecs update-service \
--cluster ${{ env.ECS_CLUSTER }} \
--service ${{ env.ECS_SERVICE }} \
--task-definition ${{ steps.update-task-def.outputs.task-arn }} \
--force-new-deployment \
--deployment-configuration \
"maximumPercent=200,minimumHealthyPercent=100,deploymentCircuitBreaker={enable=true,rollback=true}" \
--health-check-grace-period-seconds 60
# 4. 배포 상태 모니터링 (비동기)
- name: Monitor Deployment
run: |
echo "Starting deployment monitoring..."
# 최대 10분간 모니터링
end_time=$(($(date +%s) + 600))
while [ $(date +%s) -lt $end_time ]; do
STATUS=$(aws ecs describe-services \
--cluster ${{ env.ECS_CLUSTER }} \
--services ${{ env.ECS_SERVICE }} \
--query 'services[0].deployments[0].status' \
--output text)
if [ "$STATUS" = "PRIMARY" ]; then
echo "Deployment successful!"
exit 0
elif [ "$STATUS" = "FAILED" ]; then
echo "Deployment failed!"
exit 1
fi
echo "Current status: $STATUS - waiting..."
sleep 15
done
echo "Deployment timeout!"
exit 1
# 6. 배포 상태 확인
- name: Verify deployment
run: |
echo "=== Checking ECS Service Status ==="
aws ecs describe-services \
--cluster ${{ env.ECS_CLUSTER }} \
--services ${{ env.ECS_SERVICE }} \
--query 'services[0].{Status:status,Running:runningCount,Desired:desiredCount,Pending:pendingCount}' \
--output table
echo "=== Recent ECS Events ==="
aws ecs describe-services \
--cluster ${{ env.ECS_CLUSTER }} \
--services ${{ env.ECS_SERVICE }} \
--query 'services[0].events[:5]' \
--output table
# 7. CloudWatch 로그 확인 (선택사항)
- name: Check CloudWatch Logs
run: |
echo "=== Recent Application Logs ==="
aws logs tail /ecs/${{ env.ECS_TASK_DEFINITION }} \
--since 5m \
--follow \
--format short &
LOGS_PID=$!
sleep 30
kill $LOGS_PID || true
continue-on-error: true
# 8. 배포 성공 알림 (선택사항 - Slack 등)
- name: Notify deployment success
if: success()
run: |
echo "Deployment successful!"
echo "Image: ${{ needs.build-and-push.outputs.image }}"
echo "Service: ${{ env.ECS_SERVICE }}"
echo "Cluster: ${{ env.ECS_CLUSTER }}"