From 5536b3813898b4fbfbe7a47fe2f729f5d2e6b73d Mon Sep 17 00:00:00 2001 From: HEX <123macanic@naver.com> Date: Sat, 15 Nov 2025 22:01:28 +0900 Subject: [PATCH 01/12] =?UTF-8?q?fix:=20Github=20App=EC=9D=B4=20=EB=B0=9C?= =?UTF-8?q?=ED=96=89=ED=95=9C=20=EC=9E=84=EC=8B=9C=20=ED=86=A0=ED=81=B0?= =?UTF-8?q?=EC=97=90=20=EB=8C=80=ED=95=B4=20=EC=9D=BD=EA=B8=B0=20=EA=B6=8C?= =?UTF-8?q?=ED=95=9C=20=EB=AA=85=EC=8B=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev-cd.yml | 1 + .github/workflows/prod-cd.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/dev-cd.yml b/.github/workflows/dev-cd.yml index 9a3ae34a4..a951b278e 100644 --- a/.github/workflows/dev-cd.yml +++ b/.github/workflows/dev-cd.yml @@ -73,6 +73,7 @@ jobs: with: app-id: ${{ secrets.GH_APP_ID }} private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} + permissions: "packages:read" # --- 5. 설정 파일들만 scp로 전송 --- - name: Copy config files to remote diff --git a/.github/workflows/prod-cd.yml b/.github/workflows/prod-cd.yml index c96074d19..0ce68d8e5 100644 --- a/.github/workflows/prod-cd.yml +++ b/.github/workflows/prod-cd.yml @@ -71,6 +71,7 @@ jobs: with: app-id: ${{ secrets.GH_APP_ID }} private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} + permissions: "packages:read" # --- 5. 설정 파일들만 scp로 전송 --- - name: Copy config files to remote From eb00efb603fc16a194cf7bd9f6834ff110001b79 Mon Sep 17 00:00:00 2001 From: HEX <123macanic@naver.com> Date: Sat, 15 Nov 2025 22:26:09 +0900 Subject: [PATCH 02/12] =?UTF-8?q?fix:=20Github=20App=EC=9D=B4=20=EB=B0=9C?= =?UTF-8?q?=ED=96=89=ED=95=9C=20=EC=9E=84=EC=8B=9C=20=ED=86=A0=ED=81=B0?= =?UTF-8?q?=EC=97=90=20=EB=8C=80=ED=95=B4=20=EC=9D=BD=EA=B8=B0=20=EA=B6=8C?= =?UTF-8?q?=ED=95=9C=20=EB=AA=85=EC=8B=9C=20=EB=AC=B8=EB=B2=95=20=EC=98=A4?= =?UTF-8?q?=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev-cd.yml | 2 +- .github/workflows/prod-cd.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dev-cd.yml b/.github/workflows/dev-cd.yml index a951b278e..2cd5474ed 100644 --- a/.github/workflows/dev-cd.yml +++ b/.github/workflows/dev-cd.yml @@ -73,7 +73,7 @@ jobs: with: app-id: ${{ secrets.GH_APP_ID }} private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} - permissions: "packages:read" + permission-packages: "read" # --- 5. 설정 파일들만 scp로 전송 --- - name: Copy config files to remote diff --git a/.github/workflows/prod-cd.yml b/.github/workflows/prod-cd.yml index 0ce68d8e5..d59b24f9c 100644 --- a/.github/workflows/prod-cd.yml +++ b/.github/workflows/prod-cd.yml @@ -71,7 +71,7 @@ jobs: with: app-id: ${{ secrets.GH_APP_ID }} private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} - permissions: "packages:read" + permission-packages: "read" # --- 5. 설정 파일들만 scp로 전송 --- - name: Copy config files to remote From f32d19345068da50da9e9bd434ff90a5a74e2ee1 Mon Sep 17 00:00:00 2001 From: HEX <123macanic@naver.com> Date: Sat, 15 Nov 2025 22:28:14 +0900 Subject: [PATCH 03/12] =?UTF-8?q?fix:=20Github=20App=EC=9D=B4=20=EB=B0=9C?= =?UTF-8?q?=ED=96=89=ED=95=9C=20=EC=9E=84=EC=8B=9C=20=ED=86=A0=ED=81=B0?= =?UTF-8?q?=EC=97=90=20=EB=8C=80=ED=95=B4=20=EC=9D=BD=EA=B8=B0=20=EA=B6=8C?= =?UTF-8?q?=ED=95=9C=20=EB=AA=85=EC=8B=9C=20=EB=AC=B8=EB=B2=95=20=EC=98=A4?= =?UTF-8?q?=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev-cd.yml | 2 +- .github/workflows/prod-cd.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dev-cd.yml b/.github/workflows/dev-cd.yml index a951b278e..2cd5474ed 100644 --- a/.github/workflows/dev-cd.yml +++ b/.github/workflows/dev-cd.yml @@ -73,7 +73,7 @@ jobs: with: app-id: ${{ secrets.GH_APP_ID }} private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} - permissions: "packages:read" + permission-packages: "read" # --- 5. 설정 파일들만 scp로 전송 --- - name: Copy config files to remote diff --git a/.github/workflows/prod-cd.yml b/.github/workflows/prod-cd.yml index 0ce68d8e5..d59b24f9c 100644 --- a/.github/workflows/prod-cd.yml +++ b/.github/workflows/prod-cd.yml @@ -71,7 +71,7 @@ jobs: with: app-id: ${{ secrets.GH_APP_ID }} private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} - permissions: "packages:read" + permission-packages: "read" # --- 5. 설정 파일들만 scp로 전송 --- - name: Copy config files to remote From ad0db060efc7a698d2ca1040e6b398db640b7536 Mon Sep 17 00:00:00 2001 From: HEX <123macanic@naver.com> Date: Sat, 15 Nov 2025 22:35:38 +0900 Subject: [PATCH 04/12] =?UTF-8?q?fix:=20Github=20App=EC=9D=B4=20=EB=B0=9C?= =?UTF-8?q?=ED=96=89=ED=95=9C=20=EC=9E=84=EC=8B=9C=20=ED=86=A0=ED=81=B0?= =?UTF-8?q?=EC=97=90=20=EB=8C=80=ED=95=B4=20Contents=20=EC=9D=BD=EA=B8=B0?= =?UTF-8?q?=20=EA=B6=8C=ED=95=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev-cd.yml | 1 + .github/workflows/prod-cd.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/dev-cd.yml b/.github/workflows/dev-cd.yml index 2cd5474ed..9de27ee19 100644 --- a/.github/workflows/dev-cd.yml +++ b/.github/workflows/dev-cd.yml @@ -74,6 +74,7 @@ jobs: app-id: ${{ secrets.GH_APP_ID }} private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} permission-packages: "read" + permission-contents: "read" # --- 5. 설정 파일들만 scp로 전송 --- - name: Copy config files to remote diff --git a/.github/workflows/prod-cd.yml b/.github/workflows/prod-cd.yml index d59b24f9c..6c8869a61 100644 --- a/.github/workflows/prod-cd.yml +++ b/.github/workflows/prod-cd.yml @@ -72,6 +72,7 @@ jobs: app-id: ${{ secrets.GH_APP_ID }} private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} permission-packages: "read" + permission-contents: "read" # --- 5. 설정 파일들만 scp로 전송 --- - name: Copy config files to remote From 2e8ee59cde67d01dbfe3bb41e4c53f01710eeec7 Mon Sep 17 00:00:00 2001 From: HEX <123macanic@naver.com> Date: Sat, 15 Nov 2025 23:46:07 +0900 Subject: [PATCH 05/12] =?UTF-8?q?fix:=20Github=20App=EC=9D=B4=20=EB=B0=9C?= =?UTF-8?q?=ED=96=89=ED=95=9C=20=EC=9E=84=EC=8B=9C=20=ED=86=A0=ED=81=B0?= =?UTF-8?q?=EC=97=90=20=EB=8C=80=ED=95=B4=20=EC=A1=B0=EC=A7=81=20=EB=A0=88?= =?UTF-8?q?=EB=B2=A8=EC=97=90=EC=84=9C=20=EC=9D=BD=EA=B8=B0=20=EA=B6=8C?= =?UTF-8?q?=ED=95=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev-cd.yml | 3 +-- .github/workflows/prod-cd.yml | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/dev-cd.yml b/.github/workflows/dev-cd.yml index 9de27ee19..2d6ca3106 100644 --- a/.github/workflows/dev-cd.yml +++ b/.github/workflows/dev-cd.yml @@ -73,8 +73,7 @@ jobs: with: app-id: ${{ secrets.GH_APP_ID }} private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} - permission-packages: "read" - permission-contents: "read" + permission-organization-packages: "read" # --- 5. 설정 파일들만 scp로 전송 --- - name: Copy config files to remote diff --git a/.github/workflows/prod-cd.yml b/.github/workflows/prod-cd.yml index 6c8869a61..73d57608c 100644 --- a/.github/workflows/prod-cd.yml +++ b/.github/workflows/prod-cd.yml @@ -71,8 +71,7 @@ jobs: with: app-id: ${{ secrets.GH_APP_ID }} private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} - permission-packages: "read" - permission-contents: "read" + permission-organization-packages: "read" # --- 5. 설정 파일들만 scp로 전송 --- - name: Copy config files to remote From 8145edcbe573d40233b7584112cb5c9a33b9de9c Mon Sep 17 00:00:00 2001 From: HEX <123macanic@naver.com> Date: Sun, 16 Nov 2025 00:06:50 +0900 Subject: [PATCH 06/12] =?UTF-8?q?fix:=20Github=20App=EC=9D=B4=20=EB=B0=9C?= =?UTF-8?q?=ED=96=89=ED=95=9C=20=EC=9E=84=EC=8B=9C=20=ED=86=A0=ED=81=B0?= =?UTF-8?q?=EC=97=90=20=EB=8C=80=ED=95=B4=20=EC=A1=B0=EC=A7=81=20=EB=A0=88?= =?UTF-8?q?=EB=B2=A8=EC=97=90=EC=84=9C=20=EC=9D=BD=EA=B8=B0=20=EA=B6=8C?= =?UTF-8?q?=ED=95=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev-cd.yml | 1 + .github/workflows/prod-cd.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/dev-cd.yml b/.github/workflows/dev-cd.yml index 2d6ca3106..5ea6d6769 100644 --- a/.github/workflows/dev-cd.yml +++ b/.github/workflows/dev-cd.yml @@ -73,6 +73,7 @@ jobs: with: app-id: ${{ secrets.GH_APP_ID }} private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} + owner: 'solid-connection' permission-organization-packages: "read" # --- 5. 설정 파일들만 scp로 전송 --- diff --git a/.github/workflows/prod-cd.yml b/.github/workflows/prod-cd.yml index 73d57608c..2146ce229 100644 --- a/.github/workflows/prod-cd.yml +++ b/.github/workflows/prod-cd.yml @@ -71,6 +71,7 @@ jobs: with: app-id: ${{ secrets.GH_APP_ID }} private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} + owner: 'solid-connection' permission-organization-packages: "read" # --- 5. 설정 파일들만 scp로 전송 --- From 870a026fe60c7d95c3aa1a6b0117552292353b46 Mon Sep 17 00:00:00 2001 From: HEX <123macanic@naver.com> Date: Sun, 16 Nov 2025 00:43:24 +0900 Subject: [PATCH 07/12] =?UTF-8?q?fix:=20Github=20App=EC=9D=B4=20=EB=B0=9C?= =?UTF-8?q?=ED=96=89=ED=95=9C=20=EC=9E=84=EC=8B=9C=20=ED=86=A0=ED=81=B0?= =?UTF-8?q?=EC=97=90=20=EB=8C=80=ED=95=B4=20=EC=A1=B0=EC=A7=81=20=EB=A0=88?= =?UTF-8?q?=EB=B2=A8=EC=97=90=EC=84=9C=20=EC=9D=BD=EA=B8=B0=20=EA=B6=8C?= =?UTF-8?q?=ED=95=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev-cd.yml | 2 +- .github/workflows/prod-cd.yml | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dev-cd.yml b/.github/workflows/dev-cd.yml index 5ea6d6769..7fe433a56 100644 --- a/.github/workflows/dev-cd.yml +++ b/.github/workflows/dev-cd.yml @@ -74,7 +74,7 @@ jobs: app-id: ${{ secrets.GH_APP_ID }} private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} owner: 'solid-connection' - permission-organization-packages: "read" + permission-packages: "read" # --- 5. 설정 파일들만 scp로 전송 --- - name: Copy config files to remote diff --git a/.github/workflows/prod-cd.yml b/.github/workflows/prod-cd.yml index 2146ce229..3272deb9e 100644 --- a/.github/workflows/prod-cd.yml +++ b/.github/workflows/prod-cd.yml @@ -72,7 +72,8 @@ jobs: app-id: ${{ secrets.GH_APP_ID }} private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} owner: 'solid-connection' - permission-organization-packages: "read" + permission-packages: "read" + # --- 5. 설정 파일들만 scp로 전송 --- - name: Copy config files to remote From 6e15220289b21429e9a77bc0ec4ad8a53be802da Mon Sep 17 00:00:00 2001 From: HEX <123macanic@naver.com> Date: Sun, 16 Nov 2025 00:52:51 +0900 Subject: [PATCH 08/12] =?UTF-8?q?test:=20fork=20repo=EC=9D=98=20=EC=9E=91?= =?UTF-8?q?=EC=97=85=20branch=EC=97=90=EC=84=9C=20=ED=95=B4=EB=8B=B9=20wor?= =?UTF-8?q?kflows=EA=B0=80=20=EC=8B=A4=ED=96=89=EB=90=98=EB=8F=84=EB=A1=9D?= =?UTF-8?q?=20=EC=9E=84=EC=8B=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev-cd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev-cd.yml b/.github/workflows/dev-cd.yml index 7fe433a56..d09083eb0 100644 --- a/.github/workflows/dev-cd.yml +++ b/.github/workflows/dev-cd.yml @@ -2,7 +2,7 @@ name: "[DEV] Build Gradle and Deploy" on: push: - branches: [ "develop" ] + branches: [ "develop", "fix/564-github-app-token-permission" ] workflow_dispatch: jobs: From fb4e700ec14a7e1947fe0f25dd7a188ef9cc0c12 Mon Sep 17 00:00:00 2001 From: HEX <123macanic@naver.com> Date: Sun, 16 Nov 2025 01:00:54 +0900 Subject: [PATCH 09/12] =?UTF-8?q?refactor:=20test=EC=9A=A9=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev-cd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev-cd.yml b/.github/workflows/dev-cd.yml index d09083eb0..7fe433a56 100644 --- a/.github/workflows/dev-cd.yml +++ b/.github/workflows/dev-cd.yml @@ -2,7 +2,7 @@ name: "[DEV] Build Gradle and Deploy" on: push: - branches: [ "develop", "fix/564-github-app-token-permission" ] + branches: [ "develop" ] workflow_dispatch: jobs: From 8d2c07bc5e16d770ed76ca0f57249e34468ff33e Mon Sep 17 00:00:00 2001 From: HEX <123macanic@naver.com> Date: Mon, 17 Nov 2025 11:18:59 +0900 Subject: [PATCH 10/12] =?UTF-8?q?fix:=20docker=20login=20username=20?= =?UTF-8?q?=EB=B6=88=EC=9D=BC=EC=B9=98=20=EB=AC=B8=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev-cd.yml | 2 +- .github/workflows/prod-cd.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dev-cd.yml b/.github/workflows/dev-cd.yml index 7fe433a56..45e231f1e 100644 --- a/.github/workflows/dev-cd.yml +++ b/.github/workflows/dev-cd.yml @@ -104,7 +104,7 @@ jobs: export FULL_IMAGE_NAME="ghcr.io/${OWNER_LOWERCASE}/solid-connection-dev:${IMAGE_TAG_ONLY}" # 2. 서버가 GHCR에 로그인 (pull 받기 위해) - echo "${{ steps.app.outputs.token }}" | docker login ghcr.io -u ${{ github.repository_owner }} --password-stdin + echo "${{ steps.app.outputs.token }}" | docker login ghcr.io -u x-access-token --password-stdin # 3. docker pull (전체 이미지 이름 사용) echo "Pulling new image layer from GHCR..." diff --git a/.github/workflows/prod-cd.yml b/.github/workflows/prod-cd.yml index 3272deb9e..fc67b3f02 100644 --- a/.github/workflows/prod-cd.yml +++ b/.github/workflows/prod-cd.yml @@ -106,7 +106,7 @@ jobs: export FULL_IMAGE_NAME="ghcr.io/${OWNER_LOWERCASE}/solid-connection-server:${IMAGE_TAG_ONLY}" # 2. 서버가 GHCR에 로그인 (pull 받기 위해) - echo "${{ steps.app.outputs.token }}" | docker login ghcr.io -u ${{ github.repository_owner }} --password-stdin + echo "${{ steps.app.outputs.token }}" | docker login ghcr.io -u x-access-token --password-stdin # 3. docker pull (전체 이미지 이름 사용) echo "Pulling new image layer from GHCR..." From 27eeefb5c630915b5a520d4b1f556f01a08b6410 Mon Sep 17 00:00:00 2001 From: HEX <123macanic@naver.com> Date: Thu, 20 Nov 2025 19:08:42 +0900 Subject: [PATCH 11/12] =?UTF-8?q?refactor:=20=EC=B5=9C=EC=86=8C=EA=B6=8C?= =?UTF-8?q?=ED=95=9C=20=EC=9B=90=EC=B9=99=20=EC=A0=81=EC=9A=A9=EC=9D=84=20?= =?UTF-8?q?=EC=9C=84=ED=95=9C=20Action=20Job=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev-cd.yml | 107 +++++++++++++----------- .github/workflows/prod-cd.yml | 153 +++++++++++++++++++--------------- 2 files changed, 143 insertions(+), 117 deletions(-) diff --git a/.github/workflows/dev-cd.yml b/.github/workflows/dev-cd.yml index 45e231f1e..3954c043e 100644 --- a/.github/workflows/dev-cd.yml +++ b/.github/workflows/dev-cd.yml @@ -6,12 +6,18 @@ on: workflow_dispatch: jobs: - build-gradle: + # --- Job 1: 빌드 및 이미지 푸시 (쓰기 권한 필요) --- + build-and-push: runs-on: ubuntu-latest + # 이 Job은 이미지를 올려야 하므로 write 권한 부여 permissions: contents: read packages: write + # 다음 Job(deploy)에서 사용할 이미지 태그를 output으로 내보냄 + outputs: + image_tag: ${{ steps.image_meta.outputs.image_tag }} + steps: - name: Checkout the code uses: actions/checkout@v4 @@ -27,7 +33,7 @@ jobs: distribution: 'temurin' - name: Setup Gradle uses: gradle/actions/setup-gradle@v3 - - name: Grant execute permission for Gradle wrapper(gradlew) + - name: Grant execute permission for Gradle wrapper run: chmod +x ./gradlew - name: Build with Gradle run: ./gradlew bootJar @@ -37,15 +43,15 @@ jobs: uses: docker/setup-buildx-action@v3 with: platforms: linux/arm64 + - name: Log in to GitHub Container Registry (GHCR) uses: docker/login-action@v3 with: registry: ghcr.io - username: ${{ github.repository_owner }} + username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - # --- 2. 이미지 메타데이터(이름, 태그) 정의 --- - # 빌드/푸시 단계와 SSH 단계에서 공통으로 사용할 변수를 미리 정의합니다. + # --- 이미지 메타데이터 정의 --- - name: Define image name and tag id: image_meta run: | @@ -54,8 +60,7 @@ jobs: echo "image_name=ghcr.io/${OWNER_LOWERCASE}/solid-connection-dev" >> $GITHUB_OUTPUT echo "image_tag=${IMAGE_TAG}" >> $GITHUB_OUTPUT - # --- 3. Docker 이미지 빌드, 푸시, 캐시 --- - # 'docker/build-push-action'을 사용하여 캐시 옵션을 적용합니다. + # --- Docker 빌드 및 푸시 --- - name: Build, push, and cache Docker image uses: docker/build-push-action@v5 with: @@ -66,17 +71,38 @@ jobs: cache-from: type=registry,ref=${{ steps.image_meta.outputs.image_name }}:buildcache cache-to: type=registry,ref=${{ steps.image_meta.outputs.image_name }}:buildcache,mode=max - # --- 4. Github App으로 임시 토큰 생성 --- - - name: Create installation token - id: app - uses: actions/create-github-app-token@v2 + # --- 이미지 정리 (이전 Job에 있던 것) --- + - name: Clean up old image versions from GHCR + uses: snok/container-retention-policy@v2 with: - app-id: ${{ secrets.GH_APP_ID }} - private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} - owner: 'solid-connection' - permission-packages: "read" + token: ${{ secrets.GITHUB_TOKEN }} + image-names: solid-connection-dev + delete-untagged: true + keep-n-tags: 5 + account-type: org + org-name: ${{ github.repository_owner }} + cut-off: '7 days ago UTC' + + # --- Job 2: 배포 (읽기 권한만 필요) --- + deploy: + needs: build-and-push + runs-on: ubuntu-latest + # 배포 Job은 이미지를 읽기만 하면 되므로 read 권한만 부여 (최소 권한) + permissions: + contents: read + packages: read - # --- 5. 설정 파일들만 scp로 전송 --- + steps: + # 설정 파일 전송을 위해 코드 체크아웃 (서브모듈 불필요) + - name: Checkout config files + uses: actions/checkout@v4 + with: + sparse-checkout: | + docker-compose.dev.yml + docs/infra-config + sparse-checkout-cone-mode: false + + # --- 설정 파일 전송 --- - name: Copy config files to remote run: | echo "${{ secrets.DEV_PRIVATE_KEY }}" > deploy_key.pem @@ -89,67 +115,52 @@ jobs: ./docs/infra-config/nginx.dev.conf \ ${{ secrets.DEV_USERNAME }}@${{ secrets.DEV_HOST }}:/home/${{ secrets.DEV_USERNAME }}/solid-connection-dev/ - # --- 6. 서버에서 'docker pull' 및 서비스 재시작 --- + # --- 서버에서 Docker Pull 및 재시작 --- - name: Run docker compose and apply nginx config run: | + # GITHUB_TOKEN을 이용해 서버에서 로그인 (App Token 불필요) ssh -i deploy_key.pem \ -o StrictHostKeyChecking=no \ ${{ secrets.DEV_USERNAME }}@${{ secrets.DEV_HOST }} \ ' set -e - # 1. 변수를 'image_meta' 단계의 출력값에서 가져옴 - export OWNER_LOWERCASE=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]') - export IMAGE_TAG_ONLY=${{ steps.image_meta.outputs.image_tag }} + # 1. 환경 변수 설정 (이전 Job의 Output 사용) + export OWNER_LOWERCASE=$(echo "${{ github.repository_owner }}" | tr "[:upper:]" "[:lower:]") + export IMAGE_TAG_ONLY="${{ needs.build-and-push.outputs.image_tag }}" export FULL_IMAGE_NAME="ghcr.io/${OWNER_LOWERCASE}/solid-connection-dev:${IMAGE_TAG_ONLY}" - # 2. 서버가 GHCR에 로그인 (pull 받기 위해) - echo "${{ steps.app.outputs.token }}" | docker login ghcr.io -u x-access-token --password-stdin + # 2. 서버가 GHCR에 로그인 (GITHUB_TOKEN 사용) + # App Token 대신 현재 워크플로우의 임시 토큰을 넘겨줍니다. + echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin - # 3. docker pull (전체 이미지 이름 사용) - echo "Pulling new image layer from GHCR..." + # 3. Docker Pull + echo "Pulling new image: $FULL_IMAGE_NAME" docker pull $FULL_IMAGE_NAME - # 4. 작업 디렉토리로 이동 및 Nginx 설정 이동 + # 4. 작업 및 Nginx 설정 적용 cd /home/${{ secrets.DEV_USERNAME }}/solid-connection-dev mkdir -p ./nginx mv ./nginx.dev.conf ./nginx/default.conf - - # 5. Nginx 재시작 sudo cp ./nginx/default.conf /etc/nginx/conf.d/default.conf sudo nginx -t sudo nginx -s reload - # 6. Docker Compose 재시작 + # 5. Docker Compose 재시작 echo "Restarting Docker Compose with tag: $IMAGE_TAG_ONLY" docker compose -f docker-compose.dev.yml down IMAGE_TAG=$IMAGE_TAG_ONLY docker compose -f docker-compose.dev.yml up -d - # 7. 이미지 정리 - echo "Pruning dangling docker images..." + # 6. 정리 작업 + echo "Pruning dangling images..." docker image prune -f - # 8. stage 인스턴스의 오래된 태그 이미지 정리 (최신 5개 유지) - echo "Cleaning up old tagged images on host, keeping last 5..." + echo "Cleaning up old tagged images (keeping last 5)..." IMAGE_NAME_BASE="ghcr.io/${OWNER_LOWERCASE}/solid-connection-dev" - docker images "${IMAGE_NAME_BASE}" --format "{{.Tag}}" | \ sort -r | \ tail -n +6 | \ xargs -I {} docker rmi "${IMAGE_NAME_BASE}:{}" || true - echo "Deploy and Docker Compose restart finished." - ' - - # --- 6. 이미지 정리 --- - - name: Clean up old image versions from GHCR - if: success() - uses: snok/container-retention-policy@v2 - with: - token: ${{ secrets.GITHUB_TOKEN }} - image-names: solid-connection-dev - delete-untagged: true - keep-n-tags: 5 - account-type: org - org-name: ${{ github.repository_owner }} - cut-off: '7 days ago UTC' + echo "Deployment finished successfully." + ' \ No newline at end of file diff --git a/.github/workflows/prod-cd.yml b/.github/workflows/prod-cd.yml index fc67b3f02..37401d37f 100644 --- a/.github/workflows/prod-cd.yml +++ b/.github/workflows/prod-cd.yml @@ -1,17 +1,28 @@ name: "[PROD] Build Gradle and Deploy" on: - push: - branches: [ "master" ] + release: + types: [published] + workflow_dispatch: + inputs: + tag_name: + description: 'Docker Tag Name (e.g., v1.0.0)' + required: true + default: 'latest' jobs: - build-gradle: + # --- Job 1: 빌드 및 이미지 푸시 (쓰기 권한) --- + build-and-push: runs-on: ubuntu-latest permissions: contents: read packages: write + # 다음 Job(deploy)으로 이미지 태그 전달 + outputs: + image_tag: ${{ steps.image_meta.outputs.image_tag }} + steps: - name: Checkout the code uses: actions/checkout@v4 @@ -19,7 +30,7 @@ jobs: token: ${{ secrets.SUBMODULE_ACCESS_TOKEN }} submodules: true - # --- Java, Gradle 설정 (dev와 동일하게 버전 통일) --- + # --- Java, Gradle 설정 --- - name: Set up JDK 17 uses: actions/setup-java@v4 with: @@ -27,33 +38,44 @@ jobs: distribution: 'temurin' - name: Setup Gradle uses: gradle/actions/setup-gradle@v3 - - name: Grant execute permission for Gradle wrapper(gradlew) + - name: Grant execute permission for Gradle wrapper run: chmod +x ./gradlew - name: Build with Gradle run: ./gradlew bootJar - # --- 1. Docker 설정 --- + # --- Docker 설정 --- - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 with: platforms: linux/arm64 + - name: Log in to GitHub Container Registry (GHCR) uses: docker/login-action@v3 with: registry: ghcr.io - username: ${{ github.repository_owner }} + username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - # --- 2. 이미지 메타데이터(이름, 태그) 정의 --- + # --- 이미지 메타데이터 정의 (Prod용 이미지 이름) --- - name: Define image name and tag id: image_meta run: | OWNER_LOWERCASE=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]') - IMAGE_TAG=$(date +'%Y%m%d-%H%M%S') + + # Trigger가 Release인 경우: Release의 Tag Name (예: v1.0.0) 사용 + if [ "${{ github.event_name }}" == "release" ]; then + IMAGE_TAG="${{ github.ref_name }}" + # Trigger가 수동(workflow_dispatch)인 경우: 입력받은 tag_name 사용 + else + IMAGE_TAG="${{ inputs.tag_name }}" + fi + + echo "Docker Image Tag: $IMAGE_TAG" + echo "image_name=ghcr.io/${OWNER_LOWERCASE}/solid-connection-server" >> $GITHUB_OUTPUT echo "image_tag=${IMAGE_TAG}" >> $GITHUB_OUTPUT - # --- 3. Docker 이미지 빌드, 푸시, 캐시 --- + # --- Docker 빌드 및 푸시 --- - name: Build, push, and cache Docker image uses: docker/build-push-action@v5 with: @@ -64,91 +86,84 @@ jobs: cache-from: type=registry,ref=${{ steps.image_meta.outputs.image_name }}:buildcache cache-to: type=registry,ref=${{ steps.image_meta.outputs.image_name }}:buildcache,mode=max - # --- 4. Github App으로 임시 토큰 생성 --- - - name: Create installation token - id: app - uses: actions/create-github-app-token@v2 + # --- 이미지 정리 --- + - name: Clean up old image versions from GHCR + uses: snok/container-retention-policy@v2 with: - app-id: ${{ secrets.GH_APP_ID }} - private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} - owner: 'solid-connection' - permission-packages: "read" + token: ${{ secrets.GITHUB_TOKEN }} + image-names: solid-connection-server + delete-untagged: true + keep-n-tags: 5 + account-type: org + org-name: ${{ github.repository_owner }} + cut-off: '7 days ago UTC' - - # --- 5. 설정 파일들만 scp로 전송 --- + # --- Job 2: 배포 (읽기 권한) --- + deploy: + needs: build-and-push + runs-on: ubuntu-latest + permissions: + contents: read + packages: read + + steps: + - name: Checkout config files + uses: actions/checkout@v4 + with: + sparse-checkout: | + docker-compose.prod.yml + docs/infra-config + sparse-checkout-cone-mode: false + + # --- 설정 파일 전송 --- - name: Copy config files to remote run: | echo "${{ secrets.PRIVATE_KEY }}" > deploy_key.pem chmod 600 deploy_key.pem - + scp -i deploy_key.pem \ -o StrictHostKeyChecking=no \ ./docker-compose.prod.yml \ ./docs/infra-config/config.alloy \ ./docs/infra-config/nginx.prod.conf \ ${{ secrets.USERNAME }}@${{ secrets.HOST }}:/home/${{ secrets.USERNAME }}/solid-connection-prod/ - - # --- 6. 서버에서 'docker pull' 및 서비스 재시작 --- + + # --- 서버에서 Docker Pull 및 재시작 --- - name: Run docker compose and apply nginx config run: | - echo "${{ secrets.PRIVATE_KEY }}" > deploy_key_ssh.pem - chmod 600 deploy_key_ssh.pem - - ssh -i deploy_key_ssh.pem \ + ssh -i deploy_key.pem \ -o StrictHostKeyChecking=no \ ${{ secrets.USERNAME }}@${{ secrets.HOST }} \ ' set -e - - # 1. 변수 설정 - export OWNER_LOWERCASE=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]') - export IMAGE_TAG_ONLY=${{ steps.image_meta.outputs.image_tag }} + + # 1. 변수 설정 (이전 Job의 Output 사용) + export OWNER_LOWERCASE=$(echo "${{ github.repository_owner }}" | tr "[:upper:]" "[:lower:]") + export IMAGE_TAG_ONLY="${{ needs.build-and-push.outputs.image_tag }}" export FULL_IMAGE_NAME="ghcr.io/${OWNER_LOWERCASE}/solid-connection-server:${IMAGE_TAG_ONLY}" - - # 2. 서버가 GHCR에 로그인 (pull 받기 위해) - echo "${{ steps.app.outputs.token }}" | docker login ghcr.io -u x-access-token --password-stdin - - # 3. docker pull (전체 이미지 이름 사용) - echo "Pulling new image layer from GHCR..." + + # 2. 서버가 GHCR에 로그인 (GITHUB_TOKEN 사용) + # App Token 대신 현재 워크플로우의 임시 토큰을 사용합니다. + echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin + + # 3. docker pull + echo "Pulling new image: $FULL_IMAGE_NAME" docker pull $FULL_IMAGE_NAME - - # 4. 작업 디렉토리로 이동 및 Nginx 설정 이동 + + # 4. Nginx 설정 적용 cd /home/${{ secrets.USERNAME }}/solid-connection-prod mkdir -p ./nginx mv ./nginx.prod.conf ./nginx/default.conf - - # 5. Nginx 재시작 sudo cp ./nginx/default.conf /etc/nginx/conf.d/default.conf sudo nginx -t sudo nginx -s reload - - # 6. Docker Compose 재시작 (안정성 확보 로직 포함) + + # 5. Docker Compose 재시작 echo "Restarting Docker Compose with tag: $IMAGE_TAG_ONLY" - echo "Stopping containers gracefully..." - docker compose -f docker-compose.prod.yml stop - - echo "Removing old containers and networks..." - docker compose -f docker-compose.prod.yml down --remove-orphans - - echo "Starting new containers..." + docker compose -f docker-compose.prod.yml down OWNER_LOWERCASE=$OWNER_LOWERCASE IMAGE_TAG=$IMAGE_TAG_ONLY docker compose -f docker-compose.prod.yml up -d - - # 7. 이미지 정리 - echo "Pruning dangling docker images..." - docker image prune -f - - echo "Deploy and Docker Compose restart finished." - ' - # --- 6. 이미지 정리 --- - - name: Clean up old image versions from GHCR - if: success() - uses: snok/container-retention-policy@v2 - with: - token: ${{ secrets.GITHUB_TOKEN }} - image-names: solid-connection-server - delete-untagged: true - keep-n-tags: 5 - account-type: org - org-name: ${{ github.repository_owner }} - cut-off: '7 days ago UTC' + # 6. 정리 + docker image prune -f + echo "Deployment finished successfully." + ' \ No newline at end of file From e0ae334ea6adbf13ae6b538240f684bd65536122 Mon Sep 17 00:00:00 2001 From: HEX <123macanic@naver.com> Date: Thu, 20 Nov 2025 19:10:09 +0900 Subject: [PATCH 12/12] =?UTF-8?q?refactor:=20=ED=95=84=EC=9A=94=EC=97=86?= =?UTF-8?q?=EB=8A=94=20=EC=A3=BC=EC=84=9D=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev-cd.yml | 3 --- .github/workflows/prod-cd.yml | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/dev-cd.yml b/.github/workflows/dev-cd.yml index 3954c043e..3e8d994f6 100644 --- a/.github/workflows/dev-cd.yml +++ b/.github/workflows/dev-cd.yml @@ -9,12 +9,10 @@ jobs: # --- Job 1: 빌드 및 이미지 푸시 (쓰기 권한 필요) --- build-and-push: runs-on: ubuntu-latest - # 이 Job은 이미지를 올려야 하므로 write 권한 부여 permissions: contents: read packages: write - # 다음 Job(deploy)에서 사용할 이미지 태그를 output으로 내보냄 outputs: image_tag: ${{ steps.image_meta.outputs.image_tag }} @@ -87,7 +85,6 @@ jobs: deploy: needs: build-and-push runs-on: ubuntu-latest - # 배포 Job은 이미지를 읽기만 하면 되므로 read 권한만 부여 (최소 권한) permissions: contents: read packages: read diff --git a/.github/workflows/prod-cd.yml b/.github/workflows/prod-cd.yml index 37401d37f..d71f832a3 100644 --- a/.github/workflows/prod-cd.yml +++ b/.github/workflows/prod-cd.yml @@ -19,7 +19,6 @@ jobs: contents: read packages: write - # 다음 Job(deploy)으로 이미지 태그 전달 outputs: image_tag: ${{ steps.image_meta.outputs.image_tag }} @@ -107,6 +106,7 @@ jobs: packages: read steps: + # 설정 파일 전송을 위해 코드 체크아웃 (서브모듈 불필요) - name: Checkout config files uses: actions/checkout@v4 with: