Skip to content

Commit f3fb02d

Browse files
authored
fix: GitHub app token permission 권한 오류 해결 (#570)
* fix: Github App이 발행한 임시 토큰에 대해 읽기 권한 명시 * fix: Github App이 발행한 임시 토큰에 대해 읽기 권한 명시 문법 오류 수정 * fix: Github App이 발행한 임시 토큰에 대해 읽기 권한 명시 문법 오류 수정 * fix: Github App이 발행한 임시 토큰에 대해 Contents 읽기 권한 추가 * fix: Github App이 발행한 임시 토큰에 대해 조직 레벨에서 읽기 권한 추가 * fix: Github App이 발행한 임시 토큰에 대해 조직 레벨에서 읽기 권한 추가 * fix: Github App이 발행한 임시 토큰에 대해 조직 레벨에서 읽기 권한 추가 * test: fork repo의 작업 branch에서 해당 workflows가 실행되도록 임시 수정 * refactor: test용 설정 제거 * fix: docker login username 불일치 문제 * refactor: 최소권한 원칙 적용을 위한 Action Job 분리 * refactor: 필요없는 주석 제거
1 parent f5c4034 commit f3fb02d

File tree

2 files changed

+140
-117
lines changed

2 files changed

+140
-117
lines changed

.github/workflows/dev-cd.yml

Lines changed: 56 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,16 @@ on:
66
workflow_dispatch:
77

88
jobs:
9-
build-gradle:
9+
# --- Job 1: 빌드 및 이미지 푸시 (쓰기 권한 필요) ---
10+
build-and-push:
1011
runs-on: ubuntu-latest
1112
permissions:
1213
contents: read
1314
packages: write
1415

16+
outputs:
17+
image_tag: ${{ steps.image_meta.outputs.image_tag }}
18+
1519
steps:
1620
- name: Checkout the code
1721
uses: actions/checkout@v4
@@ -27,7 +31,7 @@ jobs:
2731
distribution: 'temurin'
2832
- name: Setup Gradle
2933
uses: gradle/actions/setup-gradle@v3
30-
- name: Grant execute permission for Gradle wrapper(gradlew)
34+
- name: Grant execute permission for Gradle wrapper
3135
run: chmod +x ./gradlew
3236
- name: Build with Gradle
3337
run: ./gradlew bootJar
@@ -37,15 +41,15 @@ jobs:
3741
uses: docker/setup-buildx-action@v3
3842
with:
3943
platforms: linux/arm64
44+
4045
- name: Log in to GitHub Container Registry (GHCR)
4146
uses: docker/login-action@v3
4247
with:
4348
registry: ghcr.io
44-
username: ${{ github.repository_owner }}
49+
username: ${{ github.actor }}
4550
password: ${{ secrets.GITHUB_TOKEN }}
4651

47-
# --- 2. 이미지 메타데이터(이름, 태그) 정의 ---
48-
# 빌드/푸시 단계와 SSH 단계에서 공통으로 사용할 변수를 미리 정의합니다.
52+
# --- 이미지 메타데이터 정의 ---
4953
- name: Define image name and tag
5054
id: image_meta
5155
run: |
@@ -54,8 +58,7 @@ jobs:
5458
echo "image_name=ghcr.io/${OWNER_LOWERCASE}/solid-connection-dev" >> $GITHUB_OUTPUT
5559
echo "image_tag=${IMAGE_TAG}" >> $GITHUB_OUTPUT
5660
57-
# --- 3. Docker 이미지 빌드, 푸시, 캐시 ---
58-
# 'docker/build-push-action'을 사용하여 캐시 옵션을 적용합니다.
61+
# --- Docker 빌드 및 푸시 ---
5962
- name: Build, push, and cache Docker image
6063
uses: docker/build-push-action@v5
6164
with:
@@ -66,17 +69,37 @@ jobs:
6669
cache-from: type=registry,ref=${{ steps.image_meta.outputs.image_name }}:buildcache
6770
cache-to: type=registry,ref=${{ steps.image_meta.outputs.image_name }}:buildcache,mode=max
6871

69-
# --- 4. Github App으로 임시 토큰 생성 ---
70-
- name: Create installation token
71-
id: app
72-
uses: actions/create-github-app-token@v2
72+
# --- 이미지 정리 (이전 Job에 있던 것) ---
73+
- name: Clean up old image versions from GHCR
74+
uses: snok/container-retention-policy@v2
7375
with:
74-
app-id: ${{ secrets.GH_APP_ID }}
75-
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
76-
owner: 'solid-connection'
77-
permission-packages: "read"
76+
token: ${{ secrets.GITHUB_TOKEN }}
77+
image-names: solid-connection-dev
78+
delete-untagged: true
79+
keep-n-tags: 5
80+
account-type: org
81+
org-name: ${{ github.repository_owner }}
82+
cut-off: '7 days ago UTC'
83+
84+
# --- Job 2: 배포 (읽기 권한만 필요) ---
85+
deploy:
86+
needs: build-and-push
87+
runs-on: ubuntu-latest
88+
permissions:
89+
contents: read
90+
packages: read
7891

79-
# --- 5. 설정 파일들만 scp로 전송 ---
92+
steps:
93+
# 설정 파일 전송을 위해 코드 체크아웃 (서브모듈 불필요)
94+
- name: Checkout config files
95+
uses: actions/checkout@v4
96+
with:
97+
sparse-checkout: |
98+
docker-compose.dev.yml
99+
docs/infra-config
100+
sparse-checkout-cone-mode: false
101+
102+
# --- 설정 파일 전송 ---
80103
- name: Copy config files to remote
81104
run: |
82105
echo "${{ secrets.DEV_PRIVATE_KEY }}" > deploy_key.pem
@@ -89,67 +112,52 @@ jobs:
89112
./docs/infra-config/nginx.dev.conf \
90113
${{ secrets.DEV_USERNAME }}@${{ secrets.DEV_HOST }}:/home/${{ secrets.DEV_USERNAME }}/solid-connection-dev/
91114
92-
# --- 6. 서버에서 'docker pull' 및 서비스 재시작 ---
115+
# --- 서버에서 Docker Pull 및 재시작 ---
93116
- name: Run docker compose and apply nginx config
94117
run: |
118+
# GITHUB_TOKEN을 이용해 서버에서 로그인 (App Token 불필요)
95119
ssh -i deploy_key.pem \
96120
-o StrictHostKeyChecking=no \
97121
${{ secrets.DEV_USERNAME }}@${{ secrets.DEV_HOST }} \
98122
'
99123
set -e
100124
101-
# 1. 변수를 'image_meta' 단계의 출력값에서 가져옴
102-
export OWNER_LOWERCASE=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]')
103-
export IMAGE_TAG_ONLY=${{ steps.image_meta.outputs.image_tag }}
125+
# 1. 환경 변수 설정 (이전 Job의 Output 사용)
126+
export OWNER_LOWERCASE=$(echo "${{ github.repository_owner }}" | tr "[:upper:]" "[:lower:]")
127+
export IMAGE_TAG_ONLY="${{ needs.build-and-push.outputs.image_tag }}"
104128
export FULL_IMAGE_NAME="ghcr.io/${OWNER_LOWERCASE}/solid-connection-dev:${IMAGE_TAG_ONLY}"
105129
106-
# 2. 서버가 GHCR에 로그인 (pull 받기 위해)
107-
echo "${{ steps.app.outputs.token }}" | docker login ghcr.io -u ${{ github.repository_owner }} --password-stdin
130+
# 2. 서버가 GHCR에 로그인 (GITHUB_TOKEN 사용)
131+
# App Token 대신 현재 워크플로우의 임시 토큰을 넘겨줍니다.
132+
echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
108133
109-
# 3. docker pull (전체 이미지 이름 사용)
110-
echo "Pulling new image layer from GHCR..."
134+
# 3. Docker Pull
135+
echo "Pulling new image: $FULL_IMAGE_NAME"
111136
docker pull $FULL_IMAGE_NAME
112137
113-
# 4. 작업 디렉토리로 이동 및 Nginx 설정 이동
138+
# 4. 작업 및 Nginx 설정 적용
114139
cd /home/${{ secrets.DEV_USERNAME }}/solid-connection-dev
115140
mkdir -p ./nginx
116141
mv ./nginx.dev.conf ./nginx/default.conf
117-
118-
# 5. Nginx 재시작
119142
sudo cp ./nginx/default.conf /etc/nginx/conf.d/default.conf
120143
sudo nginx -t
121144
sudo nginx -s reload
122145
123-
# 6. Docker Compose 재시작
146+
# 5. Docker Compose 재시작
124147
echo "Restarting Docker Compose with tag: $IMAGE_TAG_ONLY"
125148
docker compose -f docker-compose.dev.yml down
126149
IMAGE_TAG=$IMAGE_TAG_ONLY docker compose -f docker-compose.dev.yml up -d
127150
128-
# 7. <none> 이미지 정리
129-
echo "Pruning dangling docker images..."
151+
# 6. 정리 작업
152+
echo "Pruning dangling images..."
130153
docker image prune -f
131154
132-
# 8. stage 인스턴스의 오래된 태그 이미지 정리 (최신 5개 유지)
133-
echo "Cleaning up old tagged images on host, keeping last 5..."
155+
echo "Cleaning up old tagged images (keeping last 5)..."
134156
IMAGE_NAME_BASE="ghcr.io/${OWNER_LOWERCASE}/solid-connection-dev"
135-
136157
docker images "${IMAGE_NAME_BASE}" --format "{{.Tag}}" | \
137158
sort -r | \
138159
tail -n +6 | \
139160
xargs -I {} docker rmi "${IMAGE_NAME_BASE}:{}" || true
140161
141-
echo "Deploy and Docker Compose restart finished."
142-
'
143-
144-
# --- 6. 이미지 정리 ---
145-
- name: Clean up old image versions from GHCR
146-
if: success()
147-
uses: snok/container-retention-policy@v2
148-
with:
149-
token: ${{ secrets.GITHUB_TOKEN }}
150-
image-names: solid-connection-dev
151-
delete-untagged: true
152-
keep-n-tags: 5
153-
account-type: org
154-
org-name: ${{ github.repository_owner }}
155-
cut-off: '7 days ago UTC'
162+
echo "Deployment finished successfully."
163+
'

0 commit comments

Comments
 (0)