From 47946296e0eba7a88e0ec145e6bb15134a789d70 Mon Sep 17 00:00:00 2001 From: ooheunda Date: Wed, 25 Mar 2026 07:22:13 +0900 Subject: [PATCH 1/7] =?UTF-8?q?refactor:=20=EC=A3=BC=EC=84=9D=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EC=9E=88=EB=8D=98=20CD=20Script=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC=20=EB=B0=8F=20=EC=A3=BC=EC=84=9D=20=ED=95=B4=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/api-cd.yaml | 22 ++++++++++++++ .../workflows/{api-ci-cd.yaml => api-ci.yaml} | 29 ------------------- 2 files changed, 22 insertions(+), 29 deletions(-) rename .github/workflows/{api-ci-cd.yaml => api-ci.yaml} (72%) diff --git a/.github/workflows/api-cd.yaml b/.github/workflows/api-cd.yaml index 83c5698..3381d93 100644 --- a/.github/workflows/api-cd.yaml +++ b/.github/workflows/api-cd.yaml @@ -6,3 +6,25 @@ on: jobs: docker-deploy: runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + # Docker 로그인 + - name: Log in to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + # Docker 이미지 빌드 + - name: Build Docker Image + run: | + docker build -t velog-dashboard-v2-api:latest . + + # Docker Hub에 푸시 + - name: Push Docker Image + run: | + docker tag velog-dashboard-v2-api:latest ${{ secrets.DOCKER_USERNAME }}/velog-dashboard-v2-api:latest + docker push ${{ secrets.DOCKER_USERNAME }}/velog-dashboard-v2-api:latest diff --git a/.github/workflows/api-ci-cd.yaml b/.github/workflows/api-ci.yaml similarity index 72% rename from .github/workflows/api-ci-cd.yaml rename to .github/workflows/api-ci.yaml index e13c71e..824b53f 100644 --- a/.github/workflows/api-ci-cd.yaml +++ b/.github/workflows/api-ci.yaml @@ -80,32 +80,3 @@ jobs: - name: Run build run: pnpm run build - - # 환경 변수 이슈로 잠깐 disable - # docker-deploy: - # runs-on: ubuntu-latest - # needs: build-and-test - # # 하나의 버전이라도 성공하면 실행 (일부 실패해도 진행) - # if: ${{ !cancelled() && contains(needs.build-and-test.result, 'success') }} - - # steps: - # - name: Checkout repository - # uses: actions/checkout@v4 - - # # Docker 로그인 - # - name: Log in to Docker Hub - # uses: docker/login-action@v3 - # with: - # username: ${{ secrets.DOCKER_USERNAME }} - # password: ${{ secrets.DOCKER_PASSWORD }} - - # # Docker 이미지 빌드 - # - name: Build Docker Image - # run: | - # docker build -t velog-dashboard-v2-api:latest . - - # # Docker Hub에 푸시 - # - name: Push Docker Image - # run: | - # docker tag velog-dashboard-v2-api:latest ${{ secrets.DOCKER_USERNAME }}/velog-dashboard-v2-api:latest - # docker push ${{ secrets.DOCKER_USERNAME }}/velog-dashboard-v2-api:latest \ No newline at end of file From b4a9225158c50f2a9da5ed37e84599ea6bb0d9f0 Mon Sep 17 00:00:00 2001 From: ooheunda Date: Wed, 25 Mar 2026 07:37:21 +0900 Subject: [PATCH 2/7] =?UTF-8?q?chore:=20=EC=84=9C=EB=B2=84=20=EC=A7=81?= =?UTF-8?q?=EC=A0=91=20=EB=B0=B0=ED=8F=AC=20=EC=8A=A4=ED=81=AC=EB=A6=BD?= =?UTF-8?q?=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/api-cd.yaml | 54 ++++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 11 deletions(-) diff --git a/.github/workflows/api-cd.yaml b/.github/workflows/api-cd.yaml index 3381d93..fb58895 100644 --- a/.github/workflows/api-cd.yaml +++ b/.github/workflows/api-cd.yaml @@ -4,27 +4,59 @@ on: workflow_dispatch: jobs: - docker-deploy: + build-and-push: runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v4 - # Docker 로그인 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Log in to Docker Hub uses: docker/login-action@v3 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - # Docker 이미지 빌드 - - name: Build Docker Image - run: | - docker build -t velog-dashboard-v2-api:latest . + - name: Build and Push Docker Image + uses: docker/build-push-action@v6 + with: + context: . + push: true + tags: ${{ secrets.DOCKER_USERNAME }}/velog-dashboard-v2-api:latest + platforms: linux/amd64 + cache-from: type=gha + cache-to: type=gha,mode=max + + deploy: + runs-on: ubuntu-latest + needs: build-and-push + + steps: + - name: Deploy to Server 1 + uses: appleboy/ssh-action@v1 + with: + host: ${{ secrets.DEPLOY_HOST_1 }} + username: ${{ secrets.DEPLOY_USER }} + key: ${{ secrets.DEPLOY_SSH_KEY_1 }} + command_timeout: 10m + script: | + export GIT_SSH_COMMAND='ssh -i ~/.ssh/velog-dashboard-v2-api' + cd ${{ secrets.DEPLOY_PATH }} + git pull origin main + sed '/docker compose logs -f/d' run.sh | bash - # Docker Hub에 푸시 - - name: Push Docker Image - run: | - docker tag velog-dashboard-v2-api:latest ${{ secrets.DOCKER_USERNAME }}/velog-dashboard-v2-api:latest - docker push ${{ secrets.DOCKER_USERNAME }}/velog-dashboard-v2-api:latest + # - name: Deploy to Server 2 + # uses: appleboy/ssh-action@v1 + # with: + # host: ${{ secrets.DEPLOY_HOST_2 }} + # username: ${{ secrets.DEPLOY_USER }} + # key: ${{ secrets.DEPLOY_SSH_KEY_2 }} + # command_timeout: 10m + # script: | + # export GIT_SSH_COMMAND='ssh -i ~/.ssh/velog-dashboard-v2-api' + # cd ${{ secrets.DEPLOY_PATH }} + # git pull origin main + # sed '/docker compose logs -f/d' run.sh | bash From 69163615183f3d3c248b2d25741bfa4946bf0de3 Mon Sep 17 00:00:00 2001 From: ooheunda Date: Wed, 25 Mar 2026 08:42:12 +0900 Subject: [PATCH 3/7] =?UTF-8?q?chore:=20=EB=B0=B0=ED=8F=AC=20=EB=B2=84?= =?UTF-8?q?=EC=A0=80=EB=8B=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/api-cd.yaml | 41 +++++++++++++++++++++++------------ docker-compose.yml | 2 +- 2 files changed, 28 insertions(+), 15 deletions(-) diff --git a/.github/workflows/api-cd.yaml b/.github/workflows/api-cd.yaml index fb58895..f6cb82c 100644 --- a/.github/workflows/api-cd.yaml +++ b/.github/workflows/api-cd.yaml @@ -1,11 +1,19 @@ name: API CD on: + push: + tags: + - 'v*' workflow_dispatch: + inputs: + version: + description: '롤백할 버전 (ex: v1.6.0)' + required: true jobs: build-and-push: runs-on: ubuntu-latest + if: github.event_name == 'push' steps: - name: Checkout repository @@ -25,14 +33,17 @@ jobs: with: context: . push: true - tags: ${{ secrets.DOCKER_USERNAME }}/velog-dashboard-v2-api:latest + tags: | + ${{ secrets.DOCKER_USERNAME }}/velog-dashboard-v2-api:latest + ${{ secrets.DOCKER_USERNAME }}/velog-dashboard-v2-api:${{ github.ref_name }} platforms: linux/amd64 cache-from: type=gha cache-to: type=gha,mode=max deploy: runs-on: ubuntu-latest - needs: build-and-push + needs: [build-and-push] + if: always() && (needs.build-and-push.result == 'success' || needs.build-and-push.result == 'skipped') steps: - name: Deploy to Server 1 @@ -44,19 +55,21 @@ jobs: command_timeout: 10m script: | export GIT_SSH_COMMAND='ssh -i ~/.ssh/velog-dashboard-v2-api' + export API_VERSION=${{ github.event_name == 'workflow_dispatch' && github.event.inputs.version || github.ref_name }} cd ${{ secrets.DEPLOY_PATH }} git pull origin main sed '/docker compose logs -f/d' run.sh | bash - # - name: Deploy to Server 2 - # uses: appleboy/ssh-action@v1 - # with: - # host: ${{ secrets.DEPLOY_HOST_2 }} - # username: ${{ secrets.DEPLOY_USER }} - # key: ${{ secrets.DEPLOY_SSH_KEY_2 }} - # command_timeout: 10m - # script: | - # export GIT_SSH_COMMAND='ssh -i ~/.ssh/velog-dashboard-v2-api' - # cd ${{ secrets.DEPLOY_PATH }} - # git pull origin main - # sed '/docker compose logs -f/d' run.sh | bash + - name: Deploy to Server 2 + uses: appleboy/ssh-action@v1 + with: + host: ${{ secrets.DEPLOY_HOST_2 }} + username: ${{ secrets.DEPLOY_USER }} + key: ${{ secrets.DEPLOY_SSH_KEY_2 }} + command_timeout: 10m + script: | + export GIT_SSH_COMMAND='ssh -i ~/.ssh/velog-dashboard-v2-api' + export API_VERSION=${{ github.event_name == 'workflow_dispatch' && github.event.inputs.version || github.ref_name }} + cd ${{ secrets.DEPLOY_PATH }} + git pull origin main + sed '/docker compose logs -f/d' run.sh | bash diff --git a/docker-compose.yml b/docker-compose.yml index a83a957..c678777 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,7 +7,7 @@ services: # context: . # dockerfile: Dockerfile # image: velog-dashboard-v2-api - image: nuung/velog-dashboard-v2-api:latest + image: nuung/velog-dashboard-v2-api:${API_VERSION:-latest} hostname: velog-dashboard-v2-api container_name: velog-dashboard-v2-api ports: From 752e39b9145520f4147c512d2dd45b79781e54e5 Mon Sep 17 00:00:00 2001 From: ooheunda Date: Wed, 25 Mar 2026 09:26:05 +0900 Subject: [PATCH 4/7] =?UTF-8?q?chore:=20CI=20actions=20=EC=9D=B4=EB=A6=84?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD=20(CD=EC=99=80=20=ED=86=B5=EC=9D=BC)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/api-ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/api-ci.yaml b/.github/workflows/api-ci.yaml index 824b53f..b7bcc04 100644 --- a/.github/workflows/api-ci.yaml +++ b/.github/workflows/api-ci.yaml @@ -1,4 +1,4 @@ -name: Test CI +name: API CI on: workflow_dispatch: From 80d14f391567d969dea41e96d0ff5f4312c0ab9c Mon Sep 17 00:00:00 2001 From: ooheunda Date: Wed, 25 Mar 2026 09:26:29 +0900 Subject: [PATCH 5/7] =?UTF-8?q?chore:=20CD=20=EC=99=84=EB=A3=8C/=EC=8B=A4?= =?UTF-8?q?=ED=8C=A8=EC=8B=9C=20=EC=8A=AC=EB=9E=99=20=EC=95=8C=EB=A6=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/api-cd.yaml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/.github/workflows/api-cd.yaml b/.github/workflows/api-cd.yaml index f6cb82c..ff545b4 100644 --- a/.github/workflows/api-cd.yaml +++ b/.github/workflows/api-cd.yaml @@ -73,3 +73,25 @@ jobs: cd ${{ secrets.DEPLOY_PATH }} git pull origin main sed '/docker compose logs -f/d' run.sh | bash + + - name: Notify Slack on Success + if: success() + uses: slackapi/slack-github-action@v1.24.0 + with: + payload: | + { + "text": "✅ API 배포 성공\n• 버전: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.version || github.ref_name }}\n• 트리거: ${{ github.actor }}\n• <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|액션 로그>" + } + env: + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} + + - name: Notify Slack on Failure + if: failure() + uses: slackapi/slack-github-action@v1.24.0 + with: + payload: | + { + "text": "❌ API 배포 실패\n• 버전: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.version || github.ref_name }}\n• 트리거: ${{ github.actor }}\n• <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|액션 로그>" + } + env: + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} From 1b74cc6ed6701c1fe8949f74350108c637e25f05 Mon Sep 17 00:00:00 2001 From: ooheunda Date: Sat, 4 Apr 2026 12:45:21 +0900 Subject: [PATCH 6/7] =?UTF-8?q?chore:=20run.sh=EC=97=90=20-f=20(follow)=20?= =?UTF-8?q?=ED=94=8C=EB=9E=98=EA=B7=B8=20=EB=B0=9B=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/api-cd.yaml | 4 ++-- run.sh | 17 ++++++++++++++--- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/.github/workflows/api-cd.yaml b/.github/workflows/api-cd.yaml index ff545b4..499f6de 100644 --- a/.github/workflows/api-cd.yaml +++ b/.github/workflows/api-cd.yaml @@ -58,7 +58,7 @@ jobs: export API_VERSION=${{ github.event_name == 'workflow_dispatch' && github.event.inputs.version || github.ref_name }} cd ${{ secrets.DEPLOY_PATH }} git pull origin main - sed '/docker compose logs -f/d' run.sh | bash + bash run.sh - name: Deploy to Server 2 uses: appleboy/ssh-action@v1 @@ -72,7 +72,7 @@ jobs: export API_VERSION=${{ github.event_name == 'workflow_dispatch' && github.event.inputs.version || github.ref_name }} cd ${{ secrets.DEPLOY_PATH }} git pull origin main - sed '/docker compose logs -f/d' run.sh | bash + bash run.sh - name: Notify Slack on Success if: success() diff --git a/run.sh b/run.sh index 11c8f4c..fa58719 100755 --- a/run.sh +++ b/run.sh @@ -144,6 +144,15 @@ check_services() { fi } +# 인자 파싱 +FOLLOW=false +while [[ $# -gt 0 ]]; do + case $1 in + -f) FOLLOW=true; shift ;; + *) shift ;; + esac +done + # 메인 실행 로직 main() { print_step "Velog Dashboard V2 배포 스크립트 시작" @@ -162,9 +171,11 @@ main() { echo -e " Frontend: ${YELLOW}http://localhost:3000${NC}" echo -e " API Health Check: ${YELLOW}http://localhost:8080/health${NC}" - echo -e "\n${YELLOW}로그 모니터링을 시작합니다... (Ctrl+C로 종료)${NC}" - sleep 2 - docker compose logs -f + if [[ "$FOLLOW" == true ]]; then + echo -e "\n${YELLOW}로그 모니터링을 시작합니다... (Ctrl+C로 종료)${NC}" + sleep 2 + docker compose logs -f + fi } # 스크립트 실행 From 462540b4af97fad702d7add660dbf5e5ecd602c9 Mon Sep 17 00:00:00 2001 From: ooheunda Date: Sat, 4 Apr 2026 17:06:34 +0900 Subject: [PATCH 7/7] =?UTF-8?q?chore:=20=EC=BD=94=EB=93=9C=EB=9E=98?= =?UTF-8?q?=EB=B9=97=20=EC=BD=94=EB=A9=98=ED=8A=B8=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/api-cd.yaml | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/.github/workflows/api-cd.yaml b/.github/workflows/api-cd.yaml index 499f6de..948a6ca 100644 --- a/.github/workflows/api-cd.yaml +++ b/.github/workflows/api-cd.yaml @@ -46,18 +46,29 @@ jobs: if: always() && (needs.build-and-push.result == 'success' || needs.build-and-push.result == 'skipped') steps: + - name: Validate deploy version + id: version + run: | + RAW="${{ github.event_name == 'workflow_dispatch' && github.event.inputs.version || github.ref_name }}" + if [[ ! "$RAW" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + echo "Invalid version format: $RAW" + exit 1 + fi + echo "value=$RAW" >> $GITHUB_OUTPUT + - name: Deploy to Server 1 uses: appleboy/ssh-action@v1 with: host: ${{ secrets.DEPLOY_HOST_1 }} username: ${{ secrets.DEPLOY_USER }} key: ${{ secrets.DEPLOY_SSH_KEY_1 }} - command_timeout: 10m + command_timeout: 15m script: | export GIT_SSH_COMMAND='ssh -i ~/.ssh/velog-dashboard-v2-api' - export API_VERSION=${{ github.event_name == 'workflow_dispatch' && github.event.inputs.version || github.ref_name }} + export API_VERSION="${{ steps.version.outputs.value }}" cd ${{ secrets.DEPLOY_PATH }} - git pull origin main + git fetch --tags + git checkout "$API_VERSION" bash run.sh - name: Deploy to Server 2 @@ -66,12 +77,13 @@ jobs: host: ${{ secrets.DEPLOY_HOST_2 }} username: ${{ secrets.DEPLOY_USER }} key: ${{ secrets.DEPLOY_SSH_KEY_2 }} - command_timeout: 10m + command_timeout: 15m script: | export GIT_SSH_COMMAND='ssh -i ~/.ssh/velog-dashboard-v2-api' - export API_VERSION=${{ github.event_name == 'workflow_dispatch' && github.event.inputs.version || github.ref_name }} + export API_VERSION="${{ steps.version.outputs.value }}" cd ${{ secrets.DEPLOY_PATH }} - git pull origin main + git fetch --tags + git checkout "$API_VERSION" bash run.sh - name: Notify Slack on Success @@ -80,7 +92,7 @@ jobs: with: payload: | { - "text": "✅ API 배포 성공\n• 버전: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.version || github.ref_name }}\n• 트리거: ${{ github.actor }}\n• <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|액션 로그>" + "text": "✅ API 배포 성공\n• 버전: ${{ steps.version.outputs.value }}\n• 트리거: ${{ github.actor }}\n• <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|액션 로그>" } env: SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} @@ -91,7 +103,7 @@ jobs: with: payload: | { - "text": "❌ API 배포 실패\n• 버전: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.version || github.ref_name }}\n• 트리거: ${{ github.actor }}\n• <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|액션 로그>" + "text": "❌ API 배포 실패\n• 버전: ${{ steps.version.outputs.value }}\n• 트리거: ${{ github.actor }}\n• <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|액션 로그>" } env: SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}