1010 runs-on : ubuntu-latest
1111 permissions :
1212 contents : read
13+ packages : write
1314
1415 steps :
1516 - name : Checkout the code
@@ -18,81 +19,135 @@ jobs:
1819 token : ${{ secrets.SUBMODULE_ACCESS_TOKEN }}
1920 submodules : true
2021
22+ # --- Java, Gradle 설정 ---
2123 - name : Set up JDK 17
2224 uses : actions/setup-java@v4
2325 with :
2426 java-version : ' 17'
2527 distribution : ' temurin'
26-
27- # Configure Gradle for optimal use in GitHub Actions, including caching of downloaded dependencies.
28- # See: https://github.com/gradle/actions/blob/main/setup-gradle/README.md
2928 - name : Setup Gradle
30- uses : gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0
31-
29+ uses : gradle/actions/setup-gradle@v3
3230 - name : Grant execute permission for Gradle wrapper(gradlew)
3331 run : chmod +x ./gradlew
34-
3532 - name : Build with Gradle
3633 run : ./gradlew bootJar
3734
38- - name : Copy jar file to remote
39- uses : appleboy/scp-action@master
35+ # --- Docker 설정 ---
36+ - name : Set up Docker Buildx
37+ uses : docker/setup-buildx-action@v3
4038 with :
41- host : ${{ secrets.DEV_HOST }}
42- username : ${{ secrets.DEV_USERNAME }}
43- key : ${{ secrets.DEV_PRIVATE_KEY }}
44- source : " ./build/libs/*.jar"
45- target : " /home/${{ secrets.DEV_USERNAME }}/solid-connection-dev/"
46-
47- - name : Copy docker file to remote
48- uses : appleboy/scp-action@master
39+ platforms : linux/arm64
40+ - name : Log in to GitHub Container Registry (GHCR)
41+ uses : docker/login-action@v3
4942 with :
50- host : ${{ secrets.DEV_HOST }}
51- username : ${{ secrets.DEV_USERNAME }}
52- key : ${{ secrets.DEV_PRIVATE_KEY }}
53- source : " ./Dockerfile"
54- target : " /home/${{ secrets.DEV_USERNAME }}/solid-connection-dev/"
43+ registry : ghcr.io
44+ username : ${{ github.repository_owner }}
45+ password : ${{ secrets.GITHUB_TOKEN }}
5546
56- - name : Copy docker compose file to remote
57- uses : appleboy/scp-action@master
58- with :
59- host : ${{ secrets.DEV_HOST }}
60- username : ${{ secrets.DEV_USERNAME }}
61- key : ${{ secrets.DEV_PRIVATE_KEY }}
62- source : " ./docker-compose.dev.yml"
63- target : " /home/${{ secrets.DEV_USERNAME }}/solid-connection-dev/"
47+ # --- 2. 이미지 메타데이터(이름, 태그) 정의 ---
48+ # 빌드/푸시 단계와 SSH 단계에서 공통으로 사용할 변수를 미리 정의합니다.
49+ - name : Define image name and tag
50+ id : image_meta
51+ run : |
52+ OWNER_LOWERCASE=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]')
53+ IMAGE_TAG=$(date +'%Y%m%d-%H%M%S')
54+ echo "image_name=ghcr.io/${OWNER_LOWERCASE}/solid-connection-dev" >> $GITHUB_OUTPUT
55+ echo "image_tag=${IMAGE_TAG}" >> $GITHUB_OUTPUT
6456
65- - name : Copy alloy config file to remote
66- uses : appleboy/scp-action@master
57+ # --- 3. Docker 이미지 빌드, 푸시, 캐시 ---
58+ # 'docker/build-push-action'을 사용하여 캐시 옵션을 적용합니다.
59+ - name : Build, push, and cache Docker image
60+ uses : docker/build-push-action@v5
6761 with :
68- host : ${{ secrets.DEV_HOST }}
69- username : ${{ secrets.DEV_USERNAME }}
70- key : ${{ secrets.DEV_PRIVATE_KEY }}
71- source : " ./docs/infra-config/config.alloy"
72- target : " /home/${{ secrets.DEV_USERNAME }}/solid-connection-dev/"
62+ context : .
63+ platforms : linux/arm64
64+ push : true
65+ tags : ${{ format('{0}:{1}', steps.image_meta.outputs.image_name, steps.image_meta.outputs.image_tag) }}
66+ cache-from : type=registry,ref=${{ steps.image_meta.outputs.image_name }}:buildcache
67+ cache-to : type=registry,ref=${{ steps.image_meta.outputs.image_name }}:buildcache,mode=max
7368
74- - name : Copy nginx config to remote
75- uses : appleboy/scp-action@master
69+ # --- 4. Github App으로 임시 토큰 생성 ---
70+ - name : Create installation token
71+ id : app
72+ uses : actions/create-github-app-token@v2
7673 with :
77- host : ${{ secrets.DEV_HOST }}
78- username : ${{ secrets.DEV_USERNAME }}
79- key : ${{ secrets.DEV_PRIVATE_KEY }}
80- source : " ./docs/infra-config/nginx.dev.conf"
81- target : " /home/${{ secrets.DEV_USERNAME }}/solid-connection-dev/nginx"
82- rename : " default.conf"
74+ app-id : ${{ secrets.GH_APP_ID }}
75+ private-key : ${{ secrets.GH_APP_PRIVATE_KEY }}
76+
77+ # --- 5. 설정 파일들만 scp로 전송 ---
78+ - name : Copy config files to remote
79+ run : |
80+ echo "${{ secrets.DEV_PRIVATE_KEY }}" > deploy_key.pem
81+ chmod 600 deploy_key.pem
82+
83+ scp -i deploy_key.pem \
84+ -o StrictHostKeyChecking=no \
85+ ./docker-compose.dev.yml \
86+ ./docs/infra-config/config.alloy \
87+ ./docs/infra-config/nginx.dev.conf \
88+ ${{ secrets.DEV_USERNAME }}@${{ secrets.DEV_HOST }}:/home/${{ secrets.DEV_USERNAME }}/solid-connection-dev/
8389
90+ # --- 6. 서버에서 'docker pull' 및 서비스 재시작 ---
8491 - name : Run docker compose and apply nginx config
85- uses : appleboy/ssh-action@master
86- with :
87- host : ${{ secrets.DEV_HOST }}
88- username : ${{ secrets.DEV_USERNAME }}
89- key : ${{ secrets.DEV_PRIVATE_KEY }}
90- script_stop : true
91- script : |
92- sudo cp /home/${{ secrets.DEV_USERNAME }}/solid-connection-dev/nginx/default.conf /etc/nginx/conf.d/default.conf
92+ run : |
93+ ssh -i deploy_key.pem \
94+ -o StrictHostKeyChecking=no \
95+ ${{ secrets.DEV_USERNAME }}@${{ secrets.DEV_HOST }} \
96+ '
97+ set -e
98+
99+ # 1. 변수를 'image_meta' 단계의 출력값에서 가져옴
100+ export OWNER_LOWERCASE=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]')
101+ export IMAGE_TAG_ONLY=${{ steps.image_meta.outputs.image_tag }}
102+ export FULL_IMAGE_NAME="ghcr.io/${OWNER_LOWERCASE}/solid-connection-dev:${IMAGE_TAG_ONLY}"
103+
104+ # 2. 서버가 GHCR에 로그인 (pull 받기 위해)
105+ echo "${{ steps.app.outputs.token }}" | docker login ghcr.io -u ${{ github.repository_owner }} --password-stdin
106+
107+ # 3. docker pull (전체 이미지 이름 사용)
108+ echo "Pulling new image layer from GHCR..."
109+ docker pull $FULL_IMAGE_NAME
110+
111+ # 4. 작업 디렉토리로 이동 및 Nginx 설정 이동
112+ cd /home/${{ secrets.DEV_USERNAME }}/solid-connection-dev
113+ mkdir -p ./nginx
114+ mv ./nginx.dev.conf ./nginx/default.conf
115+
116+ # 5. Nginx 재시작
117+ sudo cp ./nginx/default.conf /etc/nginx/conf.d/default.conf
93118 sudo nginx -t
94119 sudo nginx -s reload
95-
96- cd /home/${{ secrets.DEV_USERNAME }}/solid-connection-dev
120+
121+ # 6. Docker Compose 재시작
122+ echo "Restarting Docker Compose with tag: $IMAGE_TAG_ONLY"
97123 docker compose -f docker-compose.dev.yml down
98- docker compose -f docker-compose.dev.yml up -d --build
124+ IMAGE_TAG=$IMAGE_TAG_ONLY docker compose -f docker-compose.dev.yml up -d
125+
126+ # 7. <none> 이미지 정리
127+ echo "Pruning dangling docker images..."
128+ docker image prune -f
129+
130+ # 8. stage 인스턴스의 오래된 태그 이미지 정리 (최신 5개 유지)
131+ echo "Cleaning up old tagged images on host, keeping last 5..."
132+ IMAGE_NAME_BASE="ghcr.io/${OWNER_LOWERCASE}/solid-connection-dev"
133+
134+ docker images "${IMAGE_NAME_BASE}" --format "{{.Tag}}" | \
135+ sort -r | \
136+ tail -n +6 | \
137+ xargs -I {} docker rmi "${IMAGE_NAME_BASE}:{}" || true
138+
139+ echo "Deploy and Docker Compose restart finished."
140+ '
141+
142+ # --- 6. 이미지 정리 ---
143+ - name : Clean up old image versions from GHCR
144+ if : success()
145+ uses : snok/container-retention-policy@v2
146+ with :
147+ token : ${{ secrets.GITHUB_TOKEN }}
148+ image-names : solid-connection-dev
149+ delete-untagged : true
150+ keep-n-tags : 5
151+ account-type : org
152+ org-name : ${{ github.repository_owner }}
153+ cut-off : ' 7 days ago UTC'
0 commit comments