Skip to content

Sumte CD Workflow using github actions & docker compose #18

Sumte CD Workflow using github actions & docker compose

Sumte CD Workflow using github actions & docker compose #18

name: Sumte CD Workflow using github actions & docker compose
on:
push:
branches: [ "main" ] # main 브랜치에 push될 때만 동작
workflow_dispatch:
jobs:
build-and-push-image:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'adopt'
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Gradle Caching
uses: actions/cache@v3
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Build jar
run: ./gradlew clean --no-build-cache bootJar -x test #./gradlew --info clean bootJar -x test
# Actuator 포함 여부 검증
- name: Assert actuator present
run: |
JAR=$(ls -t build/libs/*.jar | head -n1)
echo "Checking newest JAR: $JAR"
jar tf "$JAR" | grep spring-boot-actuator || {
echo "❌ Actuator not found in $JAR"; exit 1
}
- name: docker login
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: docker build and push
uses: docker/build-push-action@v5.1.0
with:
context: .
push: true
tags: ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_HUB_REPOSITORY }}:latest
no-cache: true # 💡 매 빌드마다 새 이미지
pull: true # 💡 베이스 이미지도 최신으로
deploy:
runs-on: ubuntu-latest
needs: build-and-push-image
steps:
# - name: Load SSH key into agent
# uses: webfactory/ssh-agent@v0.5.4
# with:
# ssh-private-key: ${{ secrets.EC2_SSH_KEY }}
#
# - name: Test SSH
# run: ssh -o StrictHostKeyChecking=no \
# ubuntu@${{ secrets.EC2_HOST }} whoami
- name: Checkout repository
uses: actions/checkout@v4
- name: Copy compose file
uses: appleboy/scp-action@v0.1.4
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USER }}
key: ${{ secrets.EC2_SSH_KEY }}
source: ./docker-compose.yml
target: /home/ubuntu
overwrite: true
- name: SSH into EC2 and deploy
uses: appleboy/ssh-action@v1.0.0
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USER }}
key: ${{ secrets.EC2_SSH_KEY }}
script: |
set -eo pipefail
# 디스크 청소 두 줄 / Docker 이미지, 로그 정리
docker system prune -af || true
docker builder prune -af
docker volume prune -f
# Docker Compose V2 플러그인 설치 (Ubuntu 공식 레포)
sudo apt-get update
sudo apt-get install -y docker-compose-plugin
docker compose version
# 최신 이미지 pull
docker pull ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_HUB_REPOSITORY }}:latest
# .env 파일 생성
cat <<EOF > /home/ubuntu/.env
SPRING_PROFILES_ACTIVE=prod
DOCKER_HUB_USERNAME=${{ secrets.DOCKER_USERNAME }}
DOCKER_HUB_REPOSITORY=${{ secrets.DOCKER_HUB_REPOSITORY }}
RDS_HOST=${{ secrets.RDS_HOST }}
RDS_PORT=${{ secrets.RDS_PORT }}
RDS_DB=${{ secrets.RDS_DB }}
RDS_USERNAME=${{ secrets.RDS_USERNAME }}
RDS_PASSWORD=${{ secrets.RDS_PASSWORD }}
JWT_SECRET=${{ secrets.JWT_SECRET }}
S3_ACCESS_KEY=${{ secrets.S3_ACCESS_KEY }}
S3_SECRET_KEY=${{ secrets.S3_SECRET_KEY }}
EOF
# .env 파일 권한 설정
chmod 600 /home/ubuntu/.env
# 기존 app 컨테이너 강제 제거 (없어도 에러 무시)
docker rm -f app || true
# docker-compose로 재배포
docker compose -f /home/ubuntu/docker-compose.yml pull
docker compose -f /home/ubuntu/docker-compose.yml up -d --force-recreate --remove-orphans
- name: Send Discord Notification
if: always()
run: |
STATUS="${{ job.status }}"
if [ "$STATUS" == "success" ]; then
EMOJI="✅"
else
EMOJI="❌"
fi
# 반복 폴링 헬스체크
HEALTH_STATUS="❌ 서버 비정상 작동"
for i in {1..30}; do
if curl -sSf https://sumteapi.duckdns.org/actuator/health >/dev/null; then
HEALTH_STATUS="✅ 서버 정상 작동"
break
fi
sleep 5
done
MESSAGE="$EMOJI **sumte 배포 결과**\\n상태: $STATUS\\n$HEALTH_STATUS\\n🔗 프로젝트: ${{ github.repository }}\\n👤 커밋: ${{ github.actor }}"
curl -H "Content-Type: application/json" \
-X POST \
-d "{\"content\": \"$MESSAGE\"}" \
${{ secrets.DISCORD_WEBHOOK_URL }} || true