Skip to content

Merge pull request #158 from TimeBank-Sparta/20152842-patch-61 #107

Merge pull request #158 from TimeBank-Sparta/20152842-patch-61

Merge pull request #158 from TimeBank-Sparta/20152842-patch-61 #107

Workflow file for this run

name: Deploy to EC2 (Blue-Green)
on:
push:
branches:
- develop
- main
workflow_dispatch:
jobs:
deploy:
runs-on: ubuntu-latest
env:
SLACK_DEV_WEBHOOK_URL: ${{ secrets.SLACK_DEV_WEBHOOK_URL }}
SLACK_PROD_WEBHOOK_URL: ${{ secrets.SLACK_PROD_WEBHOOK_URL }}
SERVICES: "gateway-service help-service notification-service review-service point-service user-service config-server eureka-server"
EC2_HOST: ${{ secrets.EC2_HOST }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Define TAG
id: define_tag
run: echo "TAG=$(date +'%Y%m%d%H%M%S')" >> $GITHUB_ENV
- name: Detect Changed Services
id: detect_services
run: |
CHANGED_FILES=$(git diff --name-only ${{ github.event.before }} ${{ github.sha }})
if echo "$CHANGED_FILES" | grep -Eq '(^build.gradle|^settings.gradle|^gradlew|^gradlew\.bat|^build\.gradle\.kts|^common/)'; then
echo "CHANGED=ALL" >> $GITHUB_ENV
else
CHANGED=$(echo "$CHANGED_FILES" \
| grep -E '^(gateway-service|help-service|notification-service|review-service|point-service|user-service|config-server|eureka-server)/' \
| awk -F/ '{print $1}' | sort -u | xargs)
echo "CHANGED=$CHANGED" >> $GITHUB_ENV
fi
- name: Count existing services on EC2
id: remote_count
uses: appleboy/ssh-action@v0.1.8
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USER }}
key: ${{ secrets.EC2_SSH_KEY }}
port: 22
sync: true
script: |
docker ps \
--filter name=gateway-blue \
--filter name=gateway-green \
--filter name=help-service \
--filter name=notification-service \
--filter name=review-service \
--filter name=point-service \
--filter name=user-service \
--filter name=config-server \
--filter name=eureka-server \
--format '{{.Names}}' | wc -l
- name: Export EXISTING_COUNT
run: |
RAW="${{ steps.remote_count.outputs.stdout || '0' }}"
NUM=$(echo "$RAW" | tr -cd '0-9')
echo "EXISTING_COUNT=$NUM" >> $GITHUB_ENV
- name: Decide whether to skip deploy
run: |
echo "Existing containers: $EXISTING_COUNT"
if [ -z "$CHANGED" ] && [ "$EXISTING_COUNT" -gt 13 ]; then
echo "No changes & already deployed → skipping"
exit 0
fi
- name: Build & Push images
id: build_push
run: |
if [ "$CHANGED" = "ALL" ] || { [ -z "$CHANGED" ] && [ "$EXISTING_COUNT" -le 13 ]; }; then
TARGETS=($SERVICES)
else
TARGETS=($CHANGED)
fi
echo "Deploy targets: ${TARGETS[*]}"
for svc in "${TARGETS[@]}"; do
docker build -t namgyu967/$svc:${TAG} -f $svc/Dockerfile .
docker push namgyu967/$svc:${TAG}
docker tag namgyu967/$svc:${TAG} namgyu967/$svc:latest
docker push namgyu967/$svc:latest
done
echo "TARGETS=${TARGETS[*]}" >> $GITHUB_ENV
- name: EC2에 Blue-Green 및 서비스 배포
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USER }}
key: ${{ secrets.EC2_SSH_KEY }}
port: 22
protocol: tcp
sync: true
debug: true
capture_stdout: true
curl_insecure: false
envs: |
TAG=${{ env.TAG }}
SERVICES=${{ env.SERVICES }}
CHANGED=${{ env.CHANGED }}
script: |
set -e
cd ~/timebank
source .env-tag
docker-compose up -d nginx
if docker-compose ps | grep -q gateway-blue; then
NEW=green; OLD=blue
else
NEW=blue; OLD=green
fi
docker-compose pull gateway-$NEW
docker-compose up -d gateway-$NEW
sed -i "s/server gateway-$OLD:8080;/server gateway-$NEW:8080;/" nginx-conf/gw.conf
docker exec nginx nginx -s reload
if [ "${CHANGED}" = "ALL" ] || [ -z "${CHANGED}" ]; then
IFS=' ' read -r -a targets <<< "${SERVICES}"
else
IFS=' ' read -r -a targets <<< "${CHANGED}"
fi
echo "=== DEBUG:Final deploy targets ==="
for svc in "${targets[@]}"; do
echo " - $svc"
done
for svc in "${targets[*]}"; do
[ "$svc" = "gateway-service" ] && continue
echo "Deploying $svc..."
docker-compose pull $svc
docker-compose up -d $svc
done
- name: 헬스체크 및 결과 수집
id: health
shell: bash
run: |
set +e
SUCCESS=""; FAILED=""
BASE="http://${{ env.EC2_HOST }}"
# 헬스체크 대상도 동일하게 계산
if [ "${CHANGED}" = "ALL" ] || [ -z "${CHANGED}" ]; then
IFS=' ' read -r -a targets <<< "${SERVICES}"
else
IFS=' ' read -r -a targets <<< "${CHANGED}"
fi
for svc in "${targets[@]}"; do
if [ "$svc" = "gateway-service" ]; then
END="$BASE/actuator/health"
else
END="$BASE/$svc/actuator/health"
fi
for i in {1..10}; do
sleep 5
CODE=$(curl -s -o /dev/null -w "%{http_code}" "$END" || echo "000")
if [ "$CODE" = "200" ]; then
SUCCESS="$SUCCESS $svc"
break
fi
[ "$i" -eq 10 ] && FAILED="$FAILED $svc"
done
done
echo "SUCCESS=${SUCCESS:-none}" >> $GITHUB_ENV
echo "FAILED=${FAILED:-none}" >> $GITHUB_ENV
- name: Slack Notification (Success)
if: success()
uses: slackapi/slack-github-action@v1.24.0
with:
payload: |
{
"text": "${{ github.ref == 'refs/heads/main' && ':white_check_mark: *[PROD]* 배포 성공!*' || ':white_check_mark: *[DEV]* 배포 성공!*' }}\n> 대상: ${{ env.TARGETS || 'all' }}\n> 정상: ${{ env.SUCCESS }}\n> 실패: ${{ env.FAILED }}\n> 태그: ${{ env.TAG }}\n> Eureka Server: http://${{ env.EC2_HOST }}:8761"
}
env:
SLACK_WEBHOOK_URL: ${{ github.ref == 'refs/heads/main' && secrets.SLACK_PROD_WEBHOOK_URL || secrets.SLACK_DEV_WEBHOOK_URL }}
- name: Slack Notification (Failure)
if: failure()
uses: slackapi/slack-github-action@v1.24.0
with:
payload: |
{
"text": "${{ github.ref == 'refs/heads/main' && ':x: *[PROD]* 배포 실패!*' || ':x: *[DEV]* 배포 실패!*' }}\n> 에러 확인해주세요."
}
env:
SLACK_WEBHOOK_URL: ${{ github.ref == 'refs/heads/main' && secrets.SLACK_PROD_WEBHOOK_URL || secrets.SLACK_DEV_WEBHOOK_URL }}