GitHub Actions를 활용한 CI/CD 파이프라인 구축

사이드 프로젝트 CI/CD 구축 방법에 대한 이야기 ( GitHub Actions, Docker, EC2, ECR )

19
단어: 2,509
게시글 썸네일
정보

현재 포스트는 GitHub Actions를 활용해서 ECR을 통해서 이미지를 관리하고 EC2에 배포하는 파이프라인을 구축하는 방법에 대한 이야기입니다.
( 이전 포스트: GitHub Action을 이용한 EC2 자동배포 ( with Docker ) )

💡 TIP

$GITHUB_ENV (환경변수) - 현재 job의 이후 모든 step에서 ${{ env.변수명 }}으로 접근 가능 - step 간 데이터 공유용 $GITHUB_OUTPUT (출력) - 다른 job에서 ${{ needs.job명.outputs.변수명 }}으로 접근 가능 - job 간 데이터 전달용

🚀 수동 트리거를 이용하여 배포

[01-GitHub_Action_수동_트리거]

01-GitHub_Action_수동_트리거

이전에는 master에 머지되면 자동으로 배포되게 액션을 만들었는데 현재 테스트로 액션도 많이 돌리고 실제 배포 시기를 명확하게 의도된 상황에 배포하는 게 좋을 것 같아서 수동으로 배포하도록 액션을 만들었어요.
workflow_dispatch를 이용하면 단순히 액션을 실행하는 것이 아니라 원하는 입력값을 받아서 ${{ github.event.inputs.environment }}와 같이 사용할 수 있어요.
( 현재는 값을 받아서 의미 있게 사용하지는 않아요. )

on: workflow_dispatch: inputs: environment: description: "배포할 환경을 선택하세요" required: true default: "production" type: choice options: - production - staging

⚙️ 환경 변수 설정

[02-GitHub_환경_변수_설정]

02-GitHub_환경_변수_설정

GitHub Actions에서는 환경 변수를 사용할 수 있는데 레포지토리 자체에 등록해두거나, 아래처럼 .yaml에서 선언할 수 있어요.
반복적으로 사용하는 부분들을 선언해두고 액션에서 사용하고 있어요.

env: # Slack 알림 색상 정의 SLACK_START_COLOR: "#155dfc" SLACK_SUCCESS_COLOR: "#00a63e" SLACK_FAILURE_COLOR: "#e7000b" # Docker 관련 설정 DOCKER_PLATFORM: "linux/arm64" DOCKER_COMPOSE_VERSION: "v2.24.5" # 프로젝트 관련 설정 PROJECT_NAME: "story-dict" ECR_FE_REPO: "1-blue/story-dict-fe" ECR_BE_REPO: "1-blue/story-dict-be" # 시간대 설정 TZ: "Asia/Seoul" # Slack 공통 필드 - 모든 알림에서 재사용 SLACK_COMMON_FIELDS: | { "title": "배포 환경", "value": "${{ github.event.inputs.environment }}", "short": true }, { "title": "워크플로우", "value": "<${{ github.server_url }}/${{ github.repository }}/actions/workflows/cicd.yaml|${{ github.workflow }} 워크플로우>", "short": true }, { "title": "액션 작업", "value": "<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|#${{ github.run_number }} 작업>", "short": true }, { "title": "레포지토리", "value": "<${{ github.server_url }}/${{ github.repository }}|${{ github.repository }}>", "short": true }, { "title": "브랜치", "value": "${{ github.ref_name }}", "short": true }, { "title": "실행자", "value": "${{ github.actor }}", "short": true }

📨 슬랙

정보

슬랙 알림 설정 방법은 GitHub Action + Slack 알림 포스트를 참고해주세요

0️⃣ 배포 소요 시간 계산

슬랙 결과를 보여줄 때 소요 시간을 계산하기 위해서 시작 시간을 설정해줘요.
echo "START_TIME=$(date +%s)" >> $GITHUB_ENV 이런 식으로 사용하면 환경 변수에 값을 넣을 수 있고, ${{ env.START_TIME }}와 같이 사용할 수 있어요.

jobs: Deploy: runs-on: ubuntu-latest steps: - name: Set start time run: | echo "START_TIME=$(date +%s)" >> $GITHUB_ENV echo "START_TIME_FORMATTED=$(date '+%Y년 %m월 %d일 %H시 %M분 %S초')" >> $GITHUB_ENV

1️⃣ 배포 알림

[03-슬랙_메시지_예시]

03-슬랙_메시지_예시

시작, 성공/실패 알림 모두 비슷한 형태로 알림을 보내요.
이렇게 알림을 보내려면 웹훅을 설정해서 URL을 얻고 아래처럼 설정만 하면 돼요.

jobs: Deploy: runs-on: ubuntu-latest steps: - name: Notify Slack on Start id: slack-start uses: slackapi/slack-github-action@v1.26.0 with: payload: | { "attachments": [ { "color": "${{ env.SLACK_START_COLOR }}", "title": "🚀 배포 시작", "text": "배포 환경: ${{ github.event.inputs.environment }}\n커밋: ${{ env.COMMIT_SUBJECT }}", "fields": [ { "title": "시작 시간", "value": "${{ env.START_TIME_FORMATTED }}", "short": true }, { "title": "이미지 태그 (SHA)", "value": "${{ github.sha }}", "short": true }, ${{ env.SLACK_COMMON_FIELDS }} ] } ] } env: SLACK_WEBHOOK_URL: ${{ secrets.SLACK_DEPLOY_WEBHOOK_URL }} SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK

🧩 파일 변경 감지 후 선택적 빌드

현재 프로젝트는 apps/fe, apps/be, packages/.. 등의 모노레포로 구성되어 있어서 항상 모든 레포를 수정할 필요는 없어요.
따라서 커밋 내역을 가져와서 특정 위치에 변경된 파일이 있는지 확인하고 변경된 파일이 있다면 해당 레포만 빌드하도록 설정해줘요.
현재는 apps/fe, apps/be가 변경되면 fe, be 레포만 빌드하도록 했고, packages/..가 변경되면 모든 레포를 빌드하도록 설정했어요.

jobs: Deploy: runs-on: ubuntu-latest steps: - name: Check for changes id: changes run: | set -e FE_CHANGED=false BE_CHANGED=false ANY_CHANGED=false # 기준 커밋 계산 BASE=$(git rev-parse HEAD~1 2>/dev/null || echo "") # 첫 커밋이거나 얕은 히스토리인 경우 안전하게 모든 앱 빌드 if [ -z "$BASE" ]; then git fetch --deepen=1 origin "$GITHUB_REF" || true BASE=$(git rev-parse HEAD~1 2>/dev/null || echo "") fi if [ -z "$BASE" ]; then FE_CHANGED=true BE_CHANGED=true ANY_CHANGED=true else CHANGED_FILES=$(git diff --name-only "$BASE"...HEAD || true) # 각 앱별 변경사항 확인 echo "$CHANGED_FILES" | grep -E '^apps/fe/' >/dev/null && FE_CHANGED=true || true echo "$CHANGED_FILES" | grep -E '^apps/be/' >/dev/null && BE_CHANGED=true || true # 공유 패키지 변경 시 모든 앱 빌드 if echo "$CHANGED_FILES" | grep -E '^packages/' >/dev/null; then FE_CHANGED=true BE_CHANGED=true fi [ "$FE_CHANGED" = "true" ] || [ "$BE_CHANGED" = "true" ] && ANY_CHANGED=true fi # 환경변수 설정 echo "FE_CHANGED=$FE_CHANGED" >> $GITHUB_ENV echo "BE_CHANGED=$BE_CHANGED" >> $GITHUB_ENV echo "ANY_CHANGED=$ANY_CHANGED" >> $GITHUB_ENV

🏷️ 빌드 및 태그 설정 및 ECR 푸시

[04-빌드_및_태그_설정_및_ECR_푸시]

04-빌드_및_태그_설정_및_ECR_푸시

태그를 두 가지 설정해 주는데 첫 번째로는 최신을 쉽게 사용하기 위해서 latest 태그를 설정하고 두 번째로는 독립적인 태그를 위해서 commit SHA로 태그를 설정해줘요.
그 이유는 latest만 올렸다가 롤백해야 하는 상황이 생긴다면 다시 되돌릴 수 없기 때문에 latest만 올리는 것보다 commit SHA로 태그를 설정하는 것이 좋아요.

jobs: Deploy: runs-on: ubuntu-latest steps: - name: Build and tag FE image if: env.FE_CHANGED == 'true' run: | export ECR_REGISTRY=${{ steps.login-ecr.outputs.registry }} # ARM64 플랫폼용 빌드 DOCKER_DEFAULT_PLATFORM=${{ env.DOCKER_PLATFORM }} docker-compose build fe # 태그 설정 (latest 및 commit SHA) docker tag ${{ env.ECR_FE_REPO }}:latest $ECR_REGISTRY/${{ env.ECR_FE_REPO }}:latest docker tag ${{ env.ECR_FE_REPO }}:latest $ECR_REGISTRY/${{ env.ECR_FE_REPO }}:${{ github.sha }} - name: Build and tag BE image if: env.BE_CHANGED == 'true' run: | export ECR_REGISTRY=${{ steps.login-ecr.outputs.registry }} # ARM64 플랫폼용 빌드 DOCKER_DEFAULT_PLATFORM=${{ env.DOCKER_PLATFORM }} docker-compose build be # 태그 설정 (latest 및 commit SHA) docker tag ${{ env.ECR_BE_REPO }}:latest $ECR_REGISTRY/${{ env.ECR_BE_REPO }}:latest docker tag ${{ env.ECR_BE_REPO }}:latest $ECR_REGISTRY/${{ env.ECR_BE_REPO }}:${{ github.sha }} # ECR에 이미지 푸시 - name: Push FE image to ECR if: env.FE_CHANGED == 'true' run: | export ECR_REGISTRY=${{ steps.login-ecr.outputs.registry }} docker push $ECR_REGISTRY/${{ env.ECR_FE_REPO }}:latest docker push $ECR_REGISTRY/${{ env.ECR_FE_REPO }}:${{ github.sha }} - name: Push BE image to ECR if: env.BE_CHANGED == 'true' run: | export ECR_REGISTRY=${{ steps.login-ecr.outputs.registry }} docker push $ECR_REGISTRY/${{ env.ECR_BE_REPO }}:latest docker push $ECR_REGISTRY/${{ env.ECR_BE_REPO }}:${{ github.sha }}

🔐 보안 그룹 설정

GitHub Actions 러너의 IP를 보안 그룹에 추가하는 부분이에요.
always()를 이용해서 이전 단계가 실패하더라도 추가된 보안 그룹은 반드시 닫히도록 해요.

jobs: Deploy: runs-on: ubuntu-latest steps: - name: Add GitHub Actions IP to Security Group id: add-ip run: | RUNNER_IP=$(curl -s https://api.ipify.org) echo "RUNNER_IP=$RUNNER_IP" >> $GITHUB_ENV echo "Adding GitHub Actions IP to Security Group: $RUNNER_IP" aws ec2 authorize-security-group-ingress \ --group-id ${{ secrets.AWS_SECURITY_GROUP_ID }} \ --protocol tcp \ --port 22 \ --cidr $RUNNER_IP/32 # ... 생략 - name: Remove GitHub Actions IP from Security Group if: always() run: | echo "Removing GitHub Actions IP from Security Group: ${{ env.RUNNER_IP }}" aws ec2 revoke-security-group-ingress \ --group-id ${{ secrets.AWS_SECURITY_GROUP_ID }} \ --protocol tcp \ --port 22 \ --cidr ${{ env.RUNNER_IP }}/32 || true

🖥️ EC2 배포

SSH를 이용해서 EC2에 배포하는 부분이에요.
login-ecr 단계에서 설정한 ECR 정보를 사용하고 있어요.
현재 실행 중인 컨테이너를 중지하고 도커 초기화 후 최신 이미지로 서비스를 시작하는 명령어를 적었어요.

jobs: Deploy: runs-on: ubuntu-latest steps: - name: Deploy to EC2 uses: appleboy/ssh-action@v1.0.3 with: host: ${{ secrets.AWS_EC2_SSH_DNS }} username: ${{ secrets.AWS_EC2_SSH_USER_NAME }} key: ${{ secrets.AWS_EC2_SSH_PEM_KEY }} port: ${{ secrets.AWS_EC2_SSH_PORT }} script: | cd workspace # ECR 인증 및 로그인 export ECR_REGISTRY=${{ steps.login-ecr.outputs.registry }} aws ecr get-login-password --region ${{ secrets.AWS_REGION }} | sudo docker login --username AWS --password-stdin $ECR_REGISTRY # 기존 컨테이너 정리 sudo docker stop $(sudo docker ps -aq) || true sudo docker system prune -a --volumes -f # 최신 이미지로 서비스 시작 sudo docker-compose pull sudo docker-compose up -d # 서비스 상태 확인 sudo docker-compose ps

🎉 마무리

정보

GitHub 코드를 참고해주세요

이전에는 Docker Hub를 통해서 이미지를 관리했었는데 현재는 ECR을 통해서 이미지를 관리하도록 변경했어요.
바꾼 이유는 초기에 만든 당시에 ECR이라는 존재를 몰랐었는데 이후에 알게 되었고 하는 김에 AWS에서 제공하는 서비스로 만들어두면 이후 ECS와 같이 새로운 도전을 할 때 더 쉽게 적용할 수 있을 것 같아서 변경했어요.

그리고 하는 김에 비효율적인 부분이나 사용성이 아쉬운 부분도 수정하고 GitHub Actions.yaml에서 사용할 수 있는 문법들에 대해서 배우고 익혀서 유용했던 것 같아요.

name: CD with Docker on: workflow_dispatch: inputs: environment: description: "배포할 환경을 선택하세요" required: true default: "production" type: choice options: - production - staging permissions: contents: read env: # Slack 알림 색상 정의 SLACK_START_COLOR: "#155dfc" SLACK_SUCCESS_COLOR: "#00a63e" SLACK_FAILURE_COLOR: "#e7000b" # Docker 관련 설정 DOCKER_PLATFORM: "linux/arm64" DOCKER_COMPOSE_VERSION: "v2.24.5" # 프로젝트 관련 설정 PROJECT_NAME: "story-dict" ECR_FE_REPO: "1-blue/story-dict-fe" ECR_BE_REPO: "1-blue/story-dict-be" # 시간대 설정 TZ: "Asia/Seoul" # Slack 공통 필드 - 모든 알림에서 재사용 SLACK_COMMON_FIELDS: | { "title": "배포 환경", "value": "${{ github.event.inputs.environment }}", "short": true }, { "title": "워크플로우", "value": "<${{ github.server_url }}/${{ github.repository }}/actions/workflows/cicd.yaml|${{ github.workflow }} 워크플로우>", "short": true }, { "title": "액션작업", "value": "<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|#${{ github.run_number }} 작업>", "short": true }, { "title": "레포지토리", "value": "<${{ github.server_url }}/${{ github.repository }}|${{ github.repository }}>", "short": true }, { "title": "브랜치", "value": "${{ github.ref_name }}", "short": true }, { "title": "실행자", "value": "${{ github.actor }}", "short": true } jobs: Deploy: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 with: fetch-depth: 2 # 시작 시간 추적을 통한 배포 소요시간 계산 - name: Set start time run: | echo "START_TIME=$(date +%s)" >> $GITHUB_ENV echo "START_TIME_FORMATTED=$(date '+%Y년 %m월 %d일 %H시 %M분 %S초')" >> $GITHUB_ENV # 마지막 커밋 메시지 추출 - name: Extract last commit message run: | SUBJECT=$(git log -1 --pretty=%s) echo "COMMIT_SUBJECT=$SUBJECT" >> $GITHUB_ENV # 모노레포 환경에서 변경 감지를 통한 선택적 빌드 - name: Check for changes id: changes run: | set -e FE_CHANGED=false BE_CHANGED=false ANY_CHANGED=false # 기준 커밋 계산 BASE=$(git rev-parse HEAD~1 2>/dev/null || echo "") # 첫 커밋이거나 얕은 히스토리인 경우 안전하게 모든 앱 빌드 if [ -z "$BASE" ]; then git fetch --deepen=1 origin "$GITHUB_REF" || true BASE=$(git rev-parse HEAD~1 2>/dev/null || echo "") fi if [ -z "$BASE" ]; then FE_CHANGED=true BE_CHANGED=true ANY_CHANGED=true else CHANGED_FILES=$(git diff --name-only "$BASE"...HEAD || true) # 각 앱별 변경사항 확인 echo "$CHANGED_FILES" | grep -E '^apps/fe/' >/dev/null && FE_CHANGED=true || true echo "$CHANGED_FILES" | grep -E '^apps/be/' >/dev/null && BE_CHANGED=true || true # 공유 패키지 변경 시 모든 앱 빌드 if echo "$CHANGED_FILES" | grep -E '^packages/' >/dev/null; then FE_CHANGED=true BE_CHANGED=true fi [ "$FE_CHANGED" = "true" ] || [ "$BE_CHANGED" = "true" ] && ANY_CHANGED=true fi # 환경변수 설정 echo "FE_CHANGED=$FE_CHANGED" >> $GITHUB_ENV echo "BE_CHANGED=$BE_CHANGED" >> $GITHUB_ENV echo "ANY_CHANGED=$ANY_CHANGED" >> $GITHUB_ENV # Slack 웹훅을 통한 실시간 배포 알림 - name: Notify Slack on Start id: slack-start uses: slackapi/slack-github-action@v1.26.0 with: payload: | { "attachments": [ { "color": "${{ env.SLACK_START_COLOR }}", "title": "🚀 배포 시작", "text": "배포 환경: ${{ github.event.inputs.environment }}\n커밋: ${{ env.COMMIT_SUBJECT }}", "fields": [ { "title": "시작시간", "value": "${{ env.START_TIME_FORMATTED }}", "short": true }, { "title": "이미지 태그 (SHA)", "value": "${{ github.sha }}", "short": true }, ${{ env.SLACK_COMMON_FIELDS }} ] } ] } env: SLACK_WEBHOOK_URL: ${{ secrets.SLACK_DEPLOY_WEBHOOK_URL }} SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK # 환경 파일 설정 - name: Create Frontend env files run: | mkdir -p ./envs/fe ./apps/fe echo "${{ secrets.FRENTEND_ENV_FILE }}" > ./envs/fe/.env.production echo "${{ secrets.FRENTEND_ENV_FILE }}" > ./apps/fe/.env.production - name: Create Backend env files run: | mkdir -p ./envs/be ./apps/be echo "${{ secrets.BACKEND_ENV_FILE }}" > ./envs/be/.env.production echo "${{ secrets.BACKEND_ENV_FILE }}" > ./apps/be/.env.production # Docker Compose 최신 버전 설치 - name: Install Docker Compose run: | sudo curl -L "https://github.com/docker/compose/releases/download/${{ env.DOCKER_COMPOSE_VERSION }}/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose docker-compose --version # AWS 인증 및 ECR 로그인 - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v2 with: aws-region: ${{ secrets.AWS_REGION }} aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }} aws-secret-access-key: ${{ secrets.AWS_ACCESS_SECRET_KEY }} - name: Login to Amazon ECR id: login-ecr uses: aws-actions/amazon-ecr-login@v2 # 멀티아키텍처 빌드를 위한 Docker Buildx 설정 - name: Setup buildx if: env.ANY_CHANGED == 'true' run: | docker buildx create --use docker buildx inspect --bootstrap # 조건부 이미지 빌드 및 태깅 전략 - name: Build and tag FE image if: env.FE_CHANGED == 'true' run: | export ECR_REGISTRY=${{ steps.login-ecr.outputs.registry }} # ARM64 플랫폼용 빌드 DOCKER_DEFAULT_PLATFORM=${{ env.DOCKER_PLATFORM }} docker-compose build fe # 태그 설정 (latest 및 commit SHA) docker tag ${{ env.ECR_FE_REPO }}:latest $ECR_REGISTRY/${{ env.ECR_FE_REPO }}:latest docker tag ${{ env.ECR_FE_REPO }}:latest $ECR_REGISTRY/${{ env.ECR_FE_REPO }}:${{ github.sha }} - name: Build and tag BE image if: env.BE_CHANGED == 'true' run: | export ECR_REGISTRY=${{ steps.login-ecr.outputs.registry }} # ARM64 플랫폼용 빌드 DOCKER_DEFAULT_PLATFORM=${{ env.DOCKER_PLATFORM }} docker-compose build be # 태그 설정 (latest 및 commit SHA) docker tag ${{ env.ECR_BE_REPO }}:latest $ECR_REGISTRY/${{ env.ECR_BE_REPO }}:latest docker tag ${{ env.ECR_BE_REPO }}:latest $ECR_REGISTRY/${{ env.ECR_BE_REPO }}:${{ github.sha }} # ECR에 이미지 푸시 - name: Push FE image to ECR if: env.FE_CHANGED == 'true' run: | export ECR_REGISTRY=${{ steps.login-ecr.outputs.registry }} docker push $ECR_REGISTRY/${{ env.ECR_FE_REPO }}:latest docker push $ECR_REGISTRY/${{ env.ECR_FE_REPO }}:${{ github.sha }} - name: Push BE image to ECR if: env.BE_CHANGED == 'true' run: | export ECR_REGISTRY=${{ steps.login-ecr.outputs.registry }} docker push $ECR_REGISTRY/${{ env.ECR_BE_REPO }}:latest docker push $ECR_REGISTRY/${{ env.ECR_BE_REPO }}:${{ github.sha }} # 동적 보안 그룹 관리로 SSH 접근 제한 - name: Add GitHub Actions IP to Security Group id: add-ip run: | RUNNER_IP=$(curl -s https://api.ipify.org) echo "RUNNER_IP=$RUNNER_IP" >> $GITHUB_ENV echo "Adding GitHub Actions IP to Security Group: $RUNNER_IP" aws ec2 authorize-security-group-ingress \ --group-id ${{ secrets.AWS_SECURITY_GROUP_ID }} \ --protocol tcp \ --port 22 \ --cidr $RUNNER_IP/32 # SSH를 통한 EC2 배포 및 ECR 이미지 자동 배포 - name: Deploy to EC2 uses: appleboy/ssh-action@v1.0.3 with: host: ${{ secrets.AWS_EC2_SSH_DNS }} username: ${{ secrets.AWS_EC2_SSH_USER_NAME }} key: ${{ secrets.AWS_EC2_SSH_PEM_KEY }} port: ${{ secrets.AWS_EC2_SSH_PORT }} script: | cd workspace # ECR 인증 및 로그인 export ECR_REGISTRY=${{ steps.login-ecr.outputs.registry }} aws ecr get-login-password --region ${{ secrets.AWS_REGION }} | sudo docker login --username AWS --password-stdin $ECR_REGISTRY # 기존 컨테이너 정리 sudo docker stop $(sudo docker ps -aq) || true sudo docker system prune -a --volumes -f # 최신 이미지로 서비스 시작 sudo docker-compose pull sudo docker-compose up -d # 서비스 상태 확인 sudo docker-compose ps # 보안 그룹 정리 (실패 시에도 실행) - name: Remove GitHub Actions IP from Security Group if: always() run: | echo "Removing GitHub Actions IP from Security Group: ${{ env.RUNNER_IP }}" aws ec2 revoke-security-group-ingress \ --group-id ${{ secrets.AWS_SECURITY_GROUP_ID }} \ --protocol tcp \ --port 22 \ --cidr ${{ env.RUNNER_IP }}/32 || true # 배포 소요시간 계산 - name: Calculate duration if: always() run: | END_TIME=$(date +%s) DURATION=$((END_TIME - START_TIME)) MINUTES=$((DURATION / 60)) SECONDS=$((DURATION % 60)) echo "DURATION=${MINUTES}분 ${SECONDS}초" >> $GITHUB_ENV echo "Total deployment time: ${MINUTES}분 ${SECONDS}초" # 배포 결과 알림 - name: Notify Slack on Success if: success() uses: slackapi/slack-github-action@v1.26.0 with: payload: | { "attachments": [ { "color": "${{ env.SLACK_SUCCESS_COLOR }}", "title": "✅ 배포 성공", "text": "배포 환경: ${{ github.event.inputs.environment }}\n커밋: ${{ env.COMMIT_SUBJECT }}", "fields": [ { "title": "소요시간", "value": "${{ env.DURATION }}", "short": true }, { "title": "이미지 태그 (SHA)", "value": "${{ github.sha }}", "short": true }, { "title": "FE 빌드", "value": "${{ env.FE_CHANGED == 'true' && '빌드됨' || '스킵됨' }}", "short": true }, { "title": "BE 빌드", "value": "${{ env.BE_CHANGED == 'true' && '빌드됨' || '스킵됨' }}", "short": true }, ${{ env.SLACK_COMMON_FIELDS }} ] } ] } env: SLACK_WEBHOOK_URL: ${{ secrets.SLACK_DEPLOY_WEBHOOK_URL }} SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK - name: Notify Slack on Failure if: failure() uses: slackapi/slack-github-action@v1.26.0 with: payload: | { "attachments": [ { "color": "${{ env.SLACK_FAILURE_COLOR }}", "title": "❌ 배포 실패", "text": "배포 환경: ${{ github.event.inputs.environment }}\n커밋: ${{ env.COMMIT_SUBJECT }}", "fields": [ { "title": "소요시간", "value": "${{ env.DURATION }}", "short": true }, { "title": "이미지 태그 (SHA)", "value": "${{ github.sha }}", "short": true }, { "title": "FE 빌드", "value": "${{ env.FE_CHANGED == 'true' && '시도됨' || '스킵됨' }}", "short": true }, { "title": "BE 빌드", "value": "${{ env.BE_CHANGED == 'true' && '시도됨' || '스킵됨' }}", "short": true }, ${{ env.SLACK_COMMON_FIELDS }} ] } ] } env: SLACK_WEBHOOK_URL: ${{ secrets.SLACK_DEPLOY_WEBHOOK_URL }} SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK
연관된 포스트