1+ name : Deploy to EC2
2+
3+ env :
4+ IMAGE_REPOSITORY : fivelogic
5+ CONTAINER_NAME : spring-boot
6+ EC2_INSTANCE_TAG_NAME : devcos-team10-main
7+ DOCKER_NETWORK : app-network
8+ BACKEND_DIR : back
9+
10+ on :
11+ push :
12+ branches :
13+ - main
14+ workflow_dispatch :
15+
16+ permissions :
17+ contents : write
18+ packages : write
19+
20+ defaults :
21+ run :
22+ shell : bash
23+
24+ jobs :
25+ test :
26+ runs-on : ubuntu-latest
27+
28+ steps :
29+ - name : 코드 체크아웃
30+ uses : actions/checkout@v4
31+
32+ - name : Java 21 설정
33+ uses : actions/setup-java@v4
34+ with :
35+ distribution : ' temurin'
36+ java-version : ' 21'
37+ cache : ' gradle'
38+
39+ - name : 테스트 실행
40+ run : |
41+ cd back
42+ chmod +x gradlew
43+ ./gradlew test
44+
45+ - name : 테스트 결과 업로드
46+ if : always()
47+ uses : actions/upload-artifact@v4
48+ with :
49+ name : test-results
50+ path : back/build/reports/tests/test/
51+
52+ makeTagAndRelease :
53+ needs : test
54+ if : github.ref == 'refs/heads/main' && github.event_name == 'push'
55+ runs-on : ubuntu-latest
56+ outputs :
57+ tag_name : ${{ steps.create_tag.outputs.new_tag }}
58+
59+ steps :
60+ - name : 코드 체크아웃
61+ uses : actions/checkout@v4
62+
63+ - name : Create Tag
64+ id : create_tag
65+ uses : mathieudutour/github-tag-action@v6.2
66+ with :
67+ github_token : ${{ secrets.GITHUB_TOKEN }}
68+
69+ - name : Create Release
70+ uses : actions/create-release@v1
71+ env :
72+ GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
73+ with :
74+ tag_name : ${{ steps.create_tag.outputs.new_tag }}
75+ release_name : Release ${{ steps.create_tag.outputs.new_tag }}
76+ body : ${{ steps.create_tag.outputs.changelog }}
77+ draft : false
78+ prerelease : false
79+
80+ buildImageAndPush :
81+ name : 도커 이미지 빌드와 푸시
82+ needs : makeTagAndRelease
83+ runs-on : ubuntu-latest
84+
85+ steps :
86+ - name : 코드 체크아웃
87+ uses : actions/checkout@v4
88+
89+ - name : .env 파일 생성
90+ env :
91+ DOT_ENV : ${{ secrets.DOT_ENV }}
92+ run : |
93+ mkdir -p "${{ env.BACKEND_DIR }}"
94+ printf "%s" "${DOT_ENV}" > "${{ env.BACKEND_DIR }}/.env"
95+
96+ - name : Docker Buildx 설치
97+ uses : docker/setup-buildx-action@v3
98+
99+ - name : 레지스트리 로그인
100+ uses : docker/login-action@v3
101+ with :
102+ registry : ghcr.io
103+ username : ${{ github.actor }}
104+ password : ${{ secrets.GITHUB_TOKEN }}
105+
106+ - name : set lower case owner name
107+ run : |
108+ echo "OWNER_LC=${OWNER,,}" >> "${GITHUB_ENV}"
109+ env :
110+ OWNER : " ${{ github.repository_owner }}"
111+
112+ - name : 빌드 앤 푸시
113+ uses : docker/build-push-action@v6
114+ with :
115+ context : ${{ env.BACKEND_DIR }}
116+ push : true
117+ cache-from : type=gha
118+ cache-to : type=gha,mode=max
119+ tags : |
120+ ghcr.io/${{ env.OWNER_LC }}/${{ env.IMAGE_REPOSITORY }}:${{ needs.makeTagAndRelease.outputs.tag_name }}
121+ ghcr.io/${{ env.OWNER_LC }}/${{ env.IMAGE_REPOSITORY }}:latest
122+
123+ deploy :
124+ name : 배포
125+ needs : [makeTagAndRelease, buildImageAndPush]
126+ runs-on : ubuntu-latest
127+
128+ steps :
129+ - name : AWS 자격 구성
130+ uses : aws-actions/configure-aws-credentials@v4
131+ with :
132+ aws-region : ${{ secrets.AWS_REGION }}
133+ aws-access-key-id : ${{ secrets.AWS_ACCESS_KEY_ID }}
134+ aws-secret-access-key : ${{ secrets.AWS_SECRET_ACCESS_KEY }}
135+
136+ - name : 인스턴스 ID 가져오기
137+ run : |
138+ INSTANCE_ID=$(aws ec2 describe-instances \
139+ --filters "Name=tag:Name,Values=${{ env.EC2_INSTANCE_TAG_NAME }}" "Name=instance-state-name,Values=running" \
140+ --query "Reservations[].Instances[].InstanceId" --output text)
141+
142+ if [[ -z "${INSTANCE_ID}" || "${INSTANCE_ID}" == "None" ]]; then
143+ echo "❌ 실행 중인 EC2 인스턴스를 찾을 수 없습니다."
144+ exit 1
145+ fi
146+
147+ echo "✅ EC2 인스턴스 발견: ${INSTANCE_ID}"
148+ echo "INSTANCE_ID=${INSTANCE_ID}" >> "${GITHUB_ENV}"
149+
150+ - name : AWS SSM Send-Command로 배포
151+ uses : peterkimzz/aws-ssm-send-command@master
152+ with :
153+ aws-region : ${{ secrets.AWS_REGION }}
154+ aws-access-key-id : ${{ secrets.AWS_ACCESS_KEY_ID }}
155+ aws-secret-access-key : ${{ secrets.AWS_SECRET_ACCESS_KEY }}
156+ instance-ids : ${{ env.INSTANCE_ID }}
157+ working-directory : /home/ssm-user
158+ comment : Deploy Spring Boot Application
159+ command : |
160+ set -Eeuo pipefail
161+
162+ LOG="/tmp/deploy-$(date +%Y%m%d_%H%M%S).log"
163+ exec > >(awk '{ fflush(); print strftime("[%Y-%m-%d %H:%M:%S]"), $0 }' | tee -a "$LOG")
164+ exec 2> >(awk '{ fflush(); print strftime("[%Y-%m-%d %H:%M:%S]"), $0 }' | tee -a "$LOG" >&2)
165+
166+ echo "🚀 배포 시작..."
167+
168+ source /etc/environment || true
169+
170+ OWNER_LC="${{ github.repository_owner }}"
171+ OWNER_LC="${OWNER_LC,,}"
172+ IMAGE_TAG='${{ needs.makeTagAndRelease.outputs.tag_name }}'
173+ IMAGE_REPOSITORY='${{ env.IMAGE_REPOSITORY }}'
174+ IMAGE="ghcr.io/${OWNER_LC}/${IMAGE_REPOSITORY}:${IMAGE_TAG}"
175+ CONTAINER_NAME="${{ env.CONTAINER_NAME }}"
176+
177+ echo "📦 이미지: ${IMAGE}"
178+ echo "📦 컨테이너: ${CONTAINER_NAME}"
179+
180+ cd /home/ssm-user/WEB6_8_FiveLogic_BE || exit 1
181+
182+ echo "📥 Docker 이미지 다운로드 중..."
183+ docker pull $IMAGE
184+
185+ echo "🛑 기존 컨테이너 중지 중..."
186+ docker-compose stop $CONTAINER_NAME || true
187+ docker-compose rm -f $CONTAINER_NAME || true
188+
189+ sed -i "s|image:.*${IMAGE_REPOSITORY}.*|image: ${IMAGE}|g" docker-compose.yml
190+
191+ echo "🚀 새 컨테이너 시작 중..."
192+ docker-compose up -d $CONTAINER_NAME
193+
194+ echo "🏥 헬스체크 중..."
195+ for i in {1..30}; do
196+ if docker exec $CONTAINER_NAME curl -f http://localhost:8080/health > /dev/null 2>&1; then
197+ echo "✅ 서버 정상 구동!"
198+ break
199+ fi
200+ echo "대기 중... ($i/30)"
201+ sleep 2
202+ done
203+
204+ echo "📊 컨테이너 상태:"
205+ docker-compose ps $CONTAINER_NAME
206+
207+ echo "📋 최근 로그:"
208+ docker-compose logs --tail=50 $CONTAINER_NAME
209+
210+ echo "🧹 오래된 이미지 정리 중..."
211+ {
212+ docker images --format '{{.Repository}}:{{.Tag}}' \
213+ | grep -F "ghcr.io/${OWNER_LC}/${IMAGE_REPOSITORY}:" \
214+ | grep -v -F ":${IMAGE_TAG}" \
215+ | grep -v -F ":latest" \
216+ | xargs -r docker rmi
217+ } || true
218+
219+ echo "✅ 배포 완료!"
0 commit comments