Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
175 changes: 75 additions & 100 deletions .github/workflows/ci-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,182 +17,157 @@ permissions:

jobs:
# =========================================
# JOB 1: 버전 계산 및 빌드 준비
# JOB 1: 버전 계산 및 Git 태그 생성
# =========================================
build:
if: github.event_name == 'push'
calculate-version:
if: github.event_name == 'push' && !startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
permissions:
contents: write
outputs:
version_tag: ${{ steps.tagger.outputs.new_tag || github.ref_name }}

# ▼▼▼ [수정 2] 올바른 출력 변수 이름(new_tag)을 사용합니다. ▼▼▼
new_version: ${{ steps.tagger.outputs.new_tag }}
changelog: ${{ steps.tagger.outputs.changelog }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Calculate and Create Git Tag for Develop
id: tagger
# develop 브랜치 푸시일 때만 이 단계를 실행
if: github.ref_type == 'branch'
uses: anothrNick/github-tag-action@1.67.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
WITH_V: false
DEFAULT_BUMP: patch
CUSTOM_TAG_SCHEME: "feat:minor"

- name: Build image just for logging
run: |
# ▼▼▼ [수정] 버전 값을 올바른 출력 변수에서 가져오도록 수정 ▼▼▼
docker build . -t temp-image > build_log.txt 2>&1 || true

- name: Upload build log as artifact
uses: actions/upload-artifact@v4
with:
name: build-log-${{ steps.tagger.outputs.new_tag || github.ref_name }}
path: build_log.txt

# =======================================================
# JOB 2: 1차 승인 알림 발송 (ECR 푸시)
# JOB 2: 이미지 빌드 및 1차 승인 요청
# =======================================================
notify-for-push-approval:
needs: build
build-and-request-push:
needs: calculate-version
if: success() || (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/'))
runs-on: ubuntu-latest
environment:
name: ecr-push-approval
outputs:
# ▼▼▼ [수정 1] 태그 푸시일 때만 ref_name을 사용하도록 로직 수정 (가장 중요) ▼▼▼
new_version: ${{ startsWith(github.ref, 'refs/tags/') && github.ref_name || needs.calculate-version.outputs.new_version }}
changelog: ${{ needs.calculate-version.outputs.changelog }}
steps:
- name: Download build log artifact
uses: actions/download-artifact@v4
with:
name: build-log-${{ needs.build.outputs.version_tag }}
- uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Send Discord Notification with Correctly Formatted Log
- name: Build Docker image for logging
run: |
# 1. 이전과 같이 로그에서 문제 라인을 필터링합니다.
KEYWORDS="error|failed|warning|deprecated"
LOG_ISSUES=$(grep -i -E -C 2 "$KEYWORDS" build_log.txt || true)

# 2. 결과에 따라 요약 메시지를 준비합니다.
if [[ -z "$LOG_ISSUES" ]]; then
SUMMARY_CONTENT="✅ 빌드 로그에서 특별한 경고나 에러가 발견되지 않았습니다."
else
# JSON에 넣기 전에 " 와 \ 문자만 이스케이프 처리합니다. (줄바꿈 \n은 처리하지 않음)
ESCAPED_LOGS=$(echo "$LOG_ISSUES" | head -c 1500 | sed 's/\\/\\\\/g' | sed 's/"/\\"/g')
SUMMARY_CONTENT="⚠️ 빌드 로그에서 잠재적인 문제가 발견되었습니다. 아래 요약을 확인해주세요.\n\n**Log Issues Summary:**\n\`\`\`\n${ESCAPED_LOGS}\n\`\`\`"
fi

# 3. 최종 description 내용을 만듭니다.
FINAL_DESCRIPTION="${SUMMARY_CONTENT}\n\n[➡️ 전체 로그 및 승인 페이지로 이동](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})"
docker buildx build --platform linux/amd64 -t YOUR_ECR_URI/YOUR_SERVICE_NAME:${{ startsWith(github.ref, 'refs/tags/') && github.ref_name || needs.calculate-version.outputs.new_version }} . --load > build_log.txt 2>&1 || true

# 4. JSON에 넣기 위해 다시 한번 전체 description의 특수문자를 이스케이프 합니다.
JSON_FRIENDLY_DESCRIPTION=$(echo "$FINAL_DESCRIPTION" | sed 's/\\/\\\\/g' | sed 's/"/\\"/g' | sed ':a;N;$!ba;s/\n/\\n/g')
# 5. heredoc을 사용하여 JSON 페이로드를 생성하고 curl로 바로 전송합니다.
curl -X POST -H "Content-Type: application/json" \
-d @- \
"${{ secrets.DISCORD_WEBHOOK_URL }}" <<EOF
{
"embeds": [
{
"title": "🔎 [1차 승인] ECR Push 승인 요청: ${{ needs.build.outputs.version_tag }}",
"description": "${JSON_FRIENDLY_DESCRIPTION}",
"color": 49151
}
]
}
EOF
- name: Upload build log as artifact
uses: actions/upload-artifact@v4
with:
name: build-log-${{ startsWith(github.ref, 'refs/tags/') && github.ref_name || needs.calculate-version.outputs.new_version }}
path: build_log.txt

- name: Send Discord Notification for ECR Push Approval
uses: sarisia/actions-status-discord@v1
with:
webhook: ${{ secrets.DISCORD_WEBHOOK_URL }}
title: "🔎 [1차 승인] ECR Push 승인 요청: ${{ startsWith(github.ref, 'refs/tags/') && github.ref_name || needs.calculate-version.outputs.new_version }}"
description: |
Docker 이미지 빌드가 완료되었습니다. ECR에 이미지를 Push 하려면 아래 링크에서 승인해주세요.
**변경 내역:**
${{ needs.calculate-version.outputs.changelog }}
[➡️ 빌드 로그 확인 및 승인하기](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})
color: 49151

# =====================================
# JOB 3: ECR 푸시 실행 (1차 승인 게이트)
# JOB 3: ECR에 이미지 푸시
# =====================================
push-to-ecr:
needs: [build, notify-for-push-approval]
needs: build-and-request-push
runs-on: ubuntu-latest
# ▼▼▼ 실제 승인 대기는 이 잡에서 일어납니다 ▼▼▼
environment:
name: ecr-push-approval
steps:
- uses: actions/checkout@v4
- name: Set up QEMU & Docker Buildx
uses: docker/setup-qemu-action@v3
- uses: docker/setup-buildx-action@v3
- name: Configure AWS credentials & Login to ECR
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- 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: ap-northeast-2
- uses: aws-actions/amazon-ecr-login@v2
- name: Build and push Multi-Arch Docker image
- name: Login to Amazon ECR
uses: aws-actions/amazon-ecr-login@v2
- name: Build and push Multi-Arch Docker image to ECR
uses: docker/build-push-action@v5
with:
context: .
push: true
platforms: linux/amd64,linux/arm64
tags: 326536620954.dkr.ecr.ap-northeast-2.amazonaws.com/highfive/highfive-frontend:${{ needs.build.outputs.version_tag }}
tags: 326536620954.dkr.ecr.ap-northeast-2.amazonaws.com/highfive/highfive-frontend:${{ needs.build-and-request-push.outputs.new_version }}
cache-from: type=registry,ref=326536620954.dkr.ecr.ap-northeast-2.amazonaws.com/highfive/highfive-frontend:buildcache
cache-to: type=registry,ref=326536620954.dkr.ecr.ap-northeast-2.amazonaws.com/highfive/highfive-frontend:buildcache,mode=max

# ==================================================
# JOB 4: 2차 승인 알림 발송 (EKS 배포)
# JOB 4: 2차 승인 알림 발송 및 대기
# ==================================================
notify-for-deploy-approval:
needs: [build, push-to-ecr]
deploy-to-eks:
needs: [build-and-request-push, push-to-ecr]
runs-on: ubuntu-latest
environment:
name: production-deploy
steps:
- name: Send Discord Notification for Deployment Approval
uses: sarisia/actions-status-discord@v1
with:
webhook: ${{ secrets.DISCORD_WEBHOOK_URL }}
title: "🚀 [2차 승인] EKS 배포 승인 요청: ${{ needs.build.outputs.version_tag }}"
title: "🚀 [2차 승인] EKS 배포 승인 요청: ${{ needs.build-and-request-push.outputs.new_version }}"
description: |
이미지가 ECR에 준비되었습니다. 배포를 진행하려면 아래 링크에서 승인해주세요.
[➡️ 배포 승인하기](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})
color: 0xFF4500

# ==================================================
# JOB 5: 최종 배포 실행 (2차 승인 게이트)
# ==================================================
deploy-to-eks:
needs: [build, notify-for-deploy-approval] # build 잡의 버전 정보가 필요합니다
runs-on: ubuntu-latest
# ▼▼▼ 실제 승인 대기는 이 잡에서 일어납니다 ▼▼▼
environment:
name: production-deploy
steps:

- name: Checkout Configuration Repo
uses: actions/checkout@v4
with:
repository: YOUR_ORG/YOUR_CONFIG_REPO_NAME
repository: highfive-goorm/hf-eks-config
token: ${{ secrets.CONFIG_REPO_PAT }}
# ▼▼▼ [개선 3] 안전한 체크아웃을 위해 경로 지정 ▼▼▼
path: 'config-repo'
- name: Update manifest file

- name: Update Kubernetes manifest image tag
run: |
sed -i -E "s|^(\s*image:\s*).*|\1326536620954.dkr.ecr.ap-northeast-2.amazonaws.com/highfive/highfive-frontend:${{ needs.build.outputs.version_tag }}|" config-repo/highfive-frontend-service.yaml
# ▼▼▼ [개선 3] 더 안전한 sed 명령어로 교체 ▼▼▼
sed -i -E "s|^(\s*image:\s*).*|\1326536620954.dkr.ecr.ap-northeast-2.amazonaws.com/highfive/highfive-frontend:${{ needs.build-and-request-push.outputs.new_version }}|" config-repo/highfive-frontend-service.yaml

- name: Commit and push changes
uses: stefanzweifel/git-auto-commit-action@v5
with:
commit_message: "Deploy image ${{ needs.build.outputs.version_tag }} for highfive-frontend-service"
commit_message: "Deploy image version ${{ needs.build-and-request-push.outputs.new_version }} for highfive-frontend-service"
repository: 'config-repo'
file_pattern: 'highfive-frontend-service.yaml'

# ==========================================================
# JOB 6: 워크플로우 실패 시 알림
# JOB 5: 워크플로우 실패 시 알림
# ==========================================================
notify-on-failure:
# 'if: failure()'는 이전 잡 중 하나라도 실패하면 이 잡을 실행시킵니다.
if: failure()
# 실패 여부와 상관없이 항상 실행되어야 하는 이전 잡들에 대한 needs 설정
# 이 잡이 모든 주요 잡들이 끝난 후에 실행되도록 보장합니다.
needs: [build, push-to-ecr, deploy-to-eks]
needs: [calculate-version, build-and-request-push, push-to-ecr, deploy-to-eks]
runs-on: ubuntu-latest
steps:
- name: Send Discord Failure Notification
run: |
JSON_PAYLOAD=$(printf '{"embeds":[{"title":"❌ CI/CD 파이프라인 실패","description":"`${{ github.repository }}` 레포지토리의 워크플로우 실행에 실패했습니다.\n자세한 내용은 아래 링크에서 확인해주세요.\n\n[➡️ 실패한 워크플로우 로그 확인하기](https://github.com/%s/actions/runs/%s)","color":15158332}]}' \
"${{ github.repository }}" \
"${{ github.run_id }}")

curl -X POST -H "Content-Type: application/json" \
-d "$JSON_PAYLOAD" \
"${{ secrets.DISCORD_WEBHOOK_URL }}"
uses: sarisia/actions-status-discord@v1
with:
webhook: ${{ secrets.DISCORD_WEBHOOK_URL }}
status: failure
title: "❌ CI/CD 파이프라인 실패"
description: |
`${{ github.repository }}` 레포지토리의 워크플로우 실행에 실패했습니다.
[➡️ 실패한 워크플로우 로그 확인하기](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})
color: 0xE74C3C