66 workflow_dispatch :
77
88jobs :
9- build-gradle :
9+ # --- Job 1: 빌드 및 이미지 푸시 (쓰기 권한 필요) ---
10+ build-and-push :
1011 runs-on : ubuntu-latest
1112 permissions :
1213 contents : read
14+ packages : write
15+
16+ outputs :
17+ image_tag : ${{ steps.image_meta.outputs.image_tag }}
1318
1419 steps :
1520 - name : Checkout the code
@@ -18,81 +23,128 @@ jobs:
1823 token : ${{ secrets.SUBMODULE_ACCESS_TOKEN }}
1924 submodules : true
2025
26+ # --- Java, Gradle 설정 ---
2127 - name : Set up JDK 17
2228 uses : actions/setup-java@v4
2329 with :
2430 java-version : ' 17'
2531 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
2932 - name : Setup Gradle
30- uses : gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0
31-
32- - name : Grant execute permission for Gradle wrapper(gradlew)
33+ uses : gradle/actions/setup-gradle@v3
34+ - name : Grant execute permission for Gradle wrapper
3335 run : chmod +x ./gradlew
34-
3536 - name : Build with Gradle
3637 run : ./gradlew bootJar
3738
38- - name : Copy jar file to remote
39- uses : appleboy/scp-action@master
39+ # --- Docker 설정 ---
40+ - name : Set up Docker Buildx
41+ uses : docker/setup-buildx-action@v3
4042 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/"
43+ platforms : linux/arm64
4644
47- - name : Copy docker file to remote
48- uses : appleboy/scp -action@master
45+ - name : Log in to GitHub Container Registry (GHCR)
46+ uses : docker/login -action@v3
4947 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/"
48+ registry : ghcr.io
49+ username : ${{ github.actor }}
50+ password : ${{ secrets.GITHUB_TOKEN }}
5551
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/ "
52+ # --- 이미지 메타데이터 정의 ---
53+ - name : Define image name and tag
54+ id : image_meta
55+ run : |
56+ OWNER_LOWERCASE=$(echo " ${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]')
57+ IMAGE_TAG=$(date +'%Y%m%d-%H%M%S')
58+ echo "image_name=ghcr.io/${OWNER_LOWERCASE}/solid-connection- dev" >> $GITHUB_OUTPUT
59+ echo "image_tag=${IMAGE_TAG}" >> $GITHUB_OUTPUT
6460
65- - name : Copy alloy config file to remote
66- uses : appleboy/scp-action@master
61+ # --- Docker 빌드 및 푸시 ---
62+ - name : Build, push, and cache Docker image
63+ uses : docker/build-push-action@v5
6764 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/"
65+ context : .
66+ platforms : linux/arm64
67+ push : true
68+ tags : ${{ format('{0}:{1}', steps.image_meta.outputs.image_name, steps.image_meta.outputs.image_tag) }}
69+ cache-from : type=registry,ref=${{ steps.image_meta.outputs.image_name }}:buildcache
70+ cache-to : type=registry,ref=${{ steps.image_meta.outputs.image_name }}:buildcache,mode=max
7371
74- - name : Copy nginx config to remote
75- uses : appleboy/scp-action@master
72+ # --- 이미지 정리 (이전 Job에 있던 것) ---
73+ - name : Clean up old image versions from GHCR
74+ uses : snok/container-retention-policy@v2
7675 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"
76+ token : ${{ secrets.PACKAGE_DELETE_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
8391
84- - name : Run docker compose and apply nginx config
85- uses : appleboy/ssh-action@master
92+ steps :
93+ # 설정 파일 전송을 위해 코드 체크아웃 (서브모듈 불필요)
94+ - name : Checkout config files
95+ uses : actions/checkout@v4
8696 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
93- sudo nginx -t
94- sudo nginx -s reload
97+ sparse-checkout : |
98+ docker-compose.dev.yml
99+ docs/infra-config
100+ sparse-checkout-cone-mode : false
101+
102+ # --- 설정 파일 전송 ---
103+ - name : Copy config files to remote
104+ run : |
105+ echo "${{ secrets.DEV_PRIVATE_KEY }}" > deploy_key.pem
106+ chmod 600 deploy_key.pem
107+
108+ scp -i deploy_key.pem \
109+ -o StrictHostKeyChecking=no \
110+ ./docker-compose.dev.yml \
111+ ${{ secrets.DEV_USERNAME }}@${{ secrets.DEV_HOST }}:/home/${{ secrets.DEV_USERNAME }}/solid-connection-dev/
95112
113+ # --- 서버에서 Docker Pull 및 재시작 ---
114+ - name : Run deployment on server
115+ run : |
116+ ssh -i deploy_key.pem \
117+ -o StrictHostKeyChecking=no \
118+ ${{ secrets.DEV_USERNAME }}@${{ secrets.DEV_HOST }} \
119+ '
120+ set -e
121+
122+ # 1. 환경 변수 설정 (이전 Job의 Output 사용)
123+ export OWNER_LOWERCASE=$(echo "${{ github.repository_owner }}" | tr "[:upper:]" "[:lower:]")
124+ export IMAGE_TAG_ONLY="${{ needs.build-and-push.outputs.image_tag }}"
125+ export FULL_IMAGE_NAME="ghcr.io/${OWNER_LOWERCASE}/solid-connection-dev:${IMAGE_TAG_ONLY}"
126+
127+ # 2. GHCR 로그인 & Pull
128+ echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
129+ echo "Pulling new image: $FULL_IMAGE_NAME"
130+ docker pull $FULL_IMAGE_NAME
131+
132+ # 3. Spring Boot 앱 재시작
133+ echo "Restarting Docker Compose with tag: $IMAGE_TAG_ONLY"
96134 cd /home/${{ secrets.DEV_USERNAME }}/solid-connection-dev
97- docker compose -f docker-compose.dev.yml down
98- docker compose -f docker-compose.dev.yml up -d --build
135+ docker compose -f docker-compose.dev.yml down || true
136+ OWNER_LOWERCASE=$OWNER_LOWERCASE IMAGE_TAG=$IMAGE_TAG_ONLY docker compose -f docker-compose.dev.yml up -d
137+
138+ # 4. 정리 작업
139+ echo "Pruning dangling images..."
140+ docker image prune -f
141+
142+ echo "Cleaning up old tagged images (keeping last 5)..."
143+ IMAGE_NAME_BASE="ghcr.io/${OWNER_LOWERCASE}/solid-connection-dev"
144+ docker images "${IMAGE_NAME_BASE}" --format "{{.Tag}}" | \
145+ sort -r | \
146+ tail -n +6 | \
147+ xargs -I {} docker rmi "${IMAGE_NAME_BASE}:{}" || true
148+
149+ echo "Deployment finished successfully."
150+ '
0 commit comments