From b1f5ff2566315bee18bc4273d2d4a364e69845c9 Mon Sep 17 00:00:00 2001 From: yaaan7 Date: Thu, 18 Jun 2026 14:18:50 +0900 Subject: [PATCH 1/3] =?UTF-8?q?refactor:=20=EB=8F=99=EC=8B=9C=20=EB=B0=B0?= =?UTF-8?q?=ED=8F=AC=20=EB=B0=A9=EC=A7=80,=20OIDC=20=EA=B8=B0=EB=B0=98=20A?= =?UTF-8?q?WS=20Role=20Assume=20=EA=B8=B0=EB=B0=98=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deploy.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 01911e5..7af4ca6 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -8,6 +8,11 @@ on: permissions: contents: read + id-token: write + +concurrency: + group: issueissyu-prod-deploy + cancel-in-progress: false jobs: build: @@ -97,8 +102,9 @@ jobs: id: deploy uses: einaregilsson/beanstalk-deploy@v22 with: - aws_access_key: ${{ secrets.AWS_ACCESS_KEY_ID }} - aws_secret_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws_access_key: ${{ steps.aws-creds.outputs.aws-access-key-id }} + aws_secret_key: ${{ steps.aws-creds.outputs.aws-secret-access-key }} + aws_session_token: ${{ steps.aws-creds.outputs.aws-session-token }} application_name: 'issueissyu-backend-prod' environment_name: 'issueissyu-backend-prod-env' region: ap-northeast-2 From 321dac66ee12bc1f8265768477ca4f7495efb64c Mon Sep 17 00:00:00 2001 From: yaaan7 Date: Thu, 18 Jun 2026 14:31:09 +0900 Subject: [PATCH 2/3] =?UTF-8?q?refactor:=20curl=20timeout=20=EC=98=B5?= =?UTF-8?q?=EC=85=98=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=EC=B2=B4=ED=81=AC?= =?UTF-8?q?=EC=95=84=EC=9B=83=20main=20=EB=AA=85=EC=8B=9C=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deploy.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 7af4ca6..8e5e47d 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -25,8 +25,10 @@ jobs: steps: # 코드 체크아웃 - - name: Checkout + - name: Checkout main uses: actions/checkout@v4 + with: + ref: main # JDK 21 설치 - name: Set up JDK 21 @@ -130,7 +132,7 @@ jobs: for attempt in $(seq 1 $MAX_RETRY); do echo "=== 스모크 테스트 시도 $attempt / $MAX_RETRY ===" for i in {1..30}; do - code="$(curl -sS -o /dev/null -w '%{http_code}' $HEALTH_URL || true)" + code="$(curl -sS --connect-timeout 5 --max-time 10 -o /dev/null -w '%{http_code}' "$HEALTH_URL" || true)" echo "health check $i: $code" if [ "$code" = "200" ]; then echo "health OK (시도 $attempt)" From 7a6cb787a752916b212374fe754a2bf9a0e12f56 Mon Sep 17 00:00:00 2001 From: yaaan7 Date: Thu, 18 Jun 2026 15:44:10 +0900 Subject: [PATCH 3/3] =?UTF-8?q?refactor:=20=EB=A1=A4=EB=B0=B1=20=ED=9B=84?= =?UTF-8?q?=20=EA=B2=80=EC=A6=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deploy.yml | 82 ++++++++++++++++++++++++++---------- 1 file changed, 60 insertions(+), 22 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 8e5e47d..794598d 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -23,6 +23,10 @@ jobs: github.event.pull_request.base.ref == 'main') || github.event_name == 'workflow_dispatch' + env: + AWS_DEFAULT_REGION: ap-northeast-2 + HEALTH_URL: ${{ vars.PROD_HEALTH_URL }} + steps: # 코드 체크아웃 - name: Checkout main @@ -87,6 +91,15 @@ jobs: unzip -l deploy/deploy.zip | head -n 50 unzip -l deploy/deploy.zip | egrep -i "pom.xml|Buildfile|src/|repository/" && exit 1 || echo "OK" + # OIDC 기반 AWS Role Assume + - name: Configure AWS credentials + id: aws-creds + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: ${{ vars.AWS_ROLE_ARN }} + aws-region: ap-northeast-2 + output-credentials: true + # 현재 배포 버전 저장 (롤백용) - name: Save current version run: | @@ -94,11 +107,14 @@ jobs: --environment-names issueissyu-backend-prod-env \ --query 'Environments[0].VersionLabel' \ --output text) + + echo "CURRENT_VERSION=$CURRENT" + + if [ "$CURRENT" = "None" ] || [ "$CURRENT" = "null" ]; then + CURRENT="" + fi + echo "PREVIOUS_VERSION=$CURRENT" >> $GITHUB_ENV - env: - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - AWS_DEFAULT_REGION: ap-northeast-2 - name: Deploy to Elastic Beanstalk id: deploy @@ -116,32 +132,38 @@ jobs: wait_for_deployment: true wait_for_environment_recovery: 180 - # EB 상태와 무관하게 /health 응답으로만 배포 성공 판단 + # EB 상태와 무관하게 운영 HTTPS URL의 /health 응답으로 배포 성공 판단 # 최대 3회 재시도, 각 시도마다 30회 health check - name: Smoke test with retry id: smoke_test run: | MAX_RETRY=3 - CNAME=$(aws elasticbeanstalk describe-environments \ - --environment-names issueissyu-backend-prod-env \ - --query 'Environments[0].CNAME' \ - --output text) - HEALTH_URL="http://${CNAME}/health" + + if [ -z "$HEALTH_URL" ]; then + echo "PROD_HEALTH_URL GitHub Actions Variable이 설정되지 않았습니다." + exit 1 + fi + echo "HEALTH_URL=$HEALTH_URL" for attempt in $(seq 1 $MAX_RETRY); do echo "=== 스모크 테스트 시도 $attempt / $MAX_RETRY ===" + for i in {1..30}; do code="$(curl -sS --connect-timeout 5 --max-time 10 -o /dev/null -w '%{http_code}' "$HEALTH_URL" || true)" echo "health check $i: $code" + if [ "$code" = "200" ]; then echo "health OK (시도 $attempt)" exit 0 fi + sleep 10 done + echo "시도 $attempt 실패" - if [ $attempt -lt $MAX_RETRY ]; then + + if [ "$attempt" -lt "$MAX_RETRY" ]; then echo "30초 후 재시도..." sleep 30 fi @@ -149,20 +171,36 @@ jobs: echo "최대 재시도 횟수($MAX_RETRY) 초과 - 배포 실패" exit 1 - env: - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - AWS_DEFAULT_REGION: ap-northeast-2 # 스모크 테스트 최종 실패 시 이전 버전으로 롤백 + # 롤백 명령 후 EB 환경 업데이트 완료까지 대기하고, 운영 HTTPS URL로 다시 검증 - name: Rollback on failure - if: failure() && env.PREVIOUS_VERSION != '' && (steps.deploy.outcome == 'failure' || steps.smoke_test.outcome == 'failure') + if: failure() && env.PREVIOUS_VERSION != '' && env.PREVIOUS_VERSION != 'None' && (steps.deploy.outcome == 'failure' || steps.smoke_test.outcome == 'failure') run: | - echo "배포 실패 - ${{ env.PREVIOUS_VERSION }} 으로 롤백" + echo "배포 실패 - $PREVIOUS_VERSION 으로 롤백" + aws elasticbeanstalk update-environment \ --environment-name issueissyu-backend-prod-env \ - --version-label ${{ env.PREVIOUS_VERSION }} - env: - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - AWS_DEFAULT_REGION: ap-northeast-2 \ No newline at end of file + --version-label "$PREVIOUS_VERSION" + + echo "롤백 배포 완료 대기" + aws elasticbeanstalk wait environment-updated \ + --environment-names issueissyu-backend-prod-env + + echo "롤백 후 smoke test 시작" + echo "HEALTH_URL=$HEALTH_URL" + + for i in {1..30}; do + code="$(curl -sS --connect-timeout 5 --max-time 10 -o /dev/null -w '%{http_code}' "$HEALTH_URL" || true)" + echo "rollback health check $i: $code" + + if [ "$code" = "200" ]; then + echo "rollback health OK" + exit 0 + fi + + sleep 10 + done + + echo "롤백 후에도 health check 실패" + exit 1 \ No newline at end of file