Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
98b7c03
fix: deprecated된 base image를 eclipse-temurin:17-jdk로 변경
Hexeong Nov 4, 2025
83d611f
refactor: scp 파일 전송하는 방식에서 GHCR로 push/pull하도록 변경
Hexeong Nov 4, 2025
216e83a
fix: GHCR image 제거시 Org의 GITHUB_TOKEN 사용하도록 변경
Hexeong Nov 4, 2025
898d594
refactor : scp 파일 전송하는 방식에서 GHCR로 push/pull하도록 prod-cd.yml과 docker-co…
Hexeong Nov 4, 2025
a76e446
fix: prod 인스턴스 old image 이름 통일
Hexeong Nov 4, 2025
59c0116
fix: prod-cd.yml StrictHostKeyChecking 옵션 문법 오류 수정
Hexeong Nov 5, 2025
c86901a
fix: prod-cd.yml StrictHostKeyChecking 옵션 문법 오류 수정
Hexeong Nov 6, 2025
595c6aa
fix: dev-cd.yml Old images 정리 작업 중 이미지 이름 불일치 문제 해결
Hexeong Nov 6, 2025
63a16fa
chore: 마지막 줄 개행 추가
Hexeong Nov 6, 2025
ab3054e
chore: 마지막 줄 개행 추가
Hexeong Nov 6, 2025
01114c3
feat: stage 인스턴스에 대한 최신 이미지 5개 유지 기능 및 old 이미지 제거 기능 추가
Hexeong Nov 10, 2025
229d9aa
chore: 중복된 환경변수 지정 제거
Hexeong Nov 10, 2025
1b57e74
chore: 중복된 pem키 생성 로직 제거
Hexeong Nov 10, 2025
0c431df
fix: 잘못된 pem키 이름 수정
Hexeong Nov 10, 2025
7ae94b1
refactor: 원격 호스트에서 pull할 경우, 최소 권한으로 실행하도록 Github App으로 임시토큰 발급하도록 수정
Hexeong Nov 15, 2025
be3d47a
Merge remote-tracking branch 'origin/develop' into refactor/529-short…
Hexeong Nov 15, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
165 changes: 110 additions & 55 deletions .github/workflows/dev-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ jobs:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write

steps:
- name: Checkout the code
Expand All @@ -18,81 +19,135 @@ jobs:
token: ${{ secrets.SUBMODULE_ACCESS_TOKEN }}
submodules: true

# --- Java, Gradle 설정 ---
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'

# Configure Gradle for optimal use in GitHub Actions, including caching of downloaded dependencies.
# See: https://github.com/gradle/actions/blob/main/setup-gradle/README.md
- name: Setup Gradle
uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0

uses: gradle/actions/setup-gradle@v3
- name: Grant execute permission for Gradle wrapper(gradlew)
run: chmod +x ./gradlew

- name: Build with Gradle
run: ./gradlew bootJar

- name: Copy jar file to remote
uses: appleboy/scp-action@master
# --- Docker 설정 ---
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
host: ${{ secrets.DEV_HOST }}
username: ${{ secrets.DEV_USERNAME }}
key: ${{ secrets.DEV_PRIVATE_KEY }}
source: "./build/libs/*.jar"
target: "/home/${{ secrets.DEV_USERNAME }}/solid-connection-dev/"

- name: Copy docker file to remote
uses: appleboy/scp-action@master
platforms: linux/arm64
- name: Log in to GitHub Container Registry (GHCR)
uses: docker/login-action@v3
with:
host: ${{ secrets.DEV_HOST }}
username: ${{ secrets.DEV_USERNAME }}
key: ${{ secrets.DEV_PRIVATE_KEY }}
source: "./Dockerfile"
target: "/home/${{ secrets.DEV_USERNAME }}/solid-connection-dev/"
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Copy docker compose file to remote
uses: appleboy/scp-action@master
with:
host: ${{ secrets.DEV_HOST }}
username: ${{ secrets.DEV_USERNAME }}
key: ${{ secrets.DEV_PRIVATE_KEY }}
source: "./docker-compose.dev.yml"
target: "/home/${{ secrets.DEV_USERNAME }}/solid-connection-dev/"
# --- 2. 이미지 메타데이터(이름, 태그) 정의 ---
# 빌드/푸시 단계와 SSH 단계에서 공통으로 사용할 변수를 미리 정의합니다.
- name: Define image name and tag
id: image_meta
run: |
OWNER_LOWERCASE=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

github.repository_owner 로 설정하면 레포 소유자 이름(e.g. whqtker)으로 고정되는 건가요 ? 만약 그렇다면, solid-connection 과 같이 사용자에 종속되지 않는 이름으로 설정하는 게 좋을 거 같습니다 !

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Organization에 속한 레포의 워크플로우 실행의 경우 github.repository_owner은 Organization 이름인 solid-connection이 됩니다! 때문에 사용자 이름으로 종속되지는 않아 해당 문제는 없을 것 같아요!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

확인했습니다 ~!

IMAGE_TAG=$(date +'%Y%m%d-%H%M%S')
echo "image_name=ghcr.io/${OWNER_LOWERCASE}/solid-connection-dev" >> $GITHUB_OUTPUT
echo "image_tag=${IMAGE_TAG}" >> $GITHUB_OUTPUT

- name: Copy alloy config file to remote
uses: appleboy/scp-action@master
# --- 3. Docker 이미지 빌드, 푸시, 캐시 ---
# 'docker/build-push-action'을 사용하여 캐시 옵션을 적용합니다.
- name: Build, push, and cache Docker image
uses: docker/build-push-action@v5
with:
host: ${{ secrets.DEV_HOST }}
username: ${{ secrets.DEV_USERNAME }}
key: ${{ secrets.DEV_PRIVATE_KEY }}
source: "./docs/infra-config/config.alloy"
target: "/home/${{ secrets.DEV_USERNAME }}/solid-connection-dev/"
context: .
platforms: linux/arm64
push: true
tags: ${{ format('{0}:{1}', steps.image_meta.outputs.image_name, steps.image_meta.outputs.image_tag) }}
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

- name: Copy nginx config to remote
uses: appleboy/scp-action@master
# --- 4. Github App으로 임시 토큰 생성 ---
- name: Create installation token
id: app
uses: actions/create-github-app-token@v2
with:
host: ${{ secrets.DEV_HOST }}
username: ${{ secrets.DEV_USERNAME }}
key: ${{ secrets.DEV_PRIVATE_KEY }}
source: "./docs/infra-config/nginx.dev.conf"
target: "/home/${{ secrets.DEV_USERNAME }}/solid-connection-dev/nginx"
rename: "default.conf"
app-id: ${{ secrets.GH_APP_ID }}
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}

# --- 5. 설정 파일들만 scp로 전송 ---
- name: Copy config files to remote
run: |
echo "${{ secrets.DEV_PRIVATE_KEY }}" > deploy_key.pem
chmod 600 deploy_key.pem

scp -i deploy_key.pem \
-o StrictHostKeyChecking=no \
./docker-compose.dev.yml \
./docs/infra-config/config.alloy \
./docs/infra-config/nginx.dev.conf \
${{ secrets.DEV_USERNAME }}@${{ secrets.DEV_HOST }}:/home/${{ secrets.DEV_USERNAME }}/solid-connection-dev/

# --- 6. 서버에서 'docker pull' 및 서비스 재시작 ---
- name: Run docker compose and apply nginx config
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.DEV_HOST }}
username: ${{ secrets.DEV_USERNAME }}
key: ${{ secrets.DEV_PRIVATE_KEY }}
script_stop: true
script: |
sudo cp /home/${{ secrets.DEV_USERNAME }}/solid-connection-dev/nginx/default.conf /etc/nginx/conf.d/default.conf
run: |
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 }}
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

# 3. docker pull (전체 이미지 이름 사용)
echo "Pulling new image layer from GHCR..."
docker pull $FULL_IMAGE_NAME

# 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

cd /home/${{ secrets.DEV_USERNAME }}/solid-connection-dev

# 6. Docker Compose 재시작
echo "Restarting Docker Compose with tag: $IMAGE_TAG_ONLY"
docker compose -f docker-compose.dev.yml down
docker compose -f docker-compose.dev.yml up -d --build
IMAGE_TAG=$IMAGE_TAG_ONLY docker compose -f docker-compose.dev.yml up -d

# 7. <none> 이미지 정리
echo "Pruning dangling docker images..."
docker image prune -f

# 8. stage 인스턴스의 오래된 태그 이미지 정리 (최신 5개 유지)
echo "Cleaning up old tagged images on host, 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'
Loading
Loading