Skip to content

Commit 3bd5a99

Browse files
committed
Feat: CD
1 parent 68993be commit 3bd5a99

File tree

2 files changed

+91
-0
lines changed

2 files changed

+91
-0
lines changed

.github/workflows/cd.yml

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
name: CD - Deploy Backend
2+
3+
on:
4+
workflow_run:
5+
workflows: ["CI - Build & Push Backend"]
6+
types: [completed]
7+
branches: [release]
8+
9+
workflow_dispatch:
10+
inputs:
11+
tag:
12+
description: "Deploy image tag (default: release)"
13+
required: false
14+
default: "release"
15+
16+
permissions:
17+
contents: read
18+
19+
concurrency:
20+
group: deploy-docsa
21+
cancel-in-progress: false
22+
23+
jobs:
24+
deploy:
25+
if: ${{ github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' }}
26+
runs-on: ubuntu-latest
27+
environment: production
28+
steps:
29+
- name: Decide tag
30+
id: tag
31+
run: |
32+
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
33+
echo "value=${{ github.event.inputs.tag }}" >> $GITHUB_OUTPUT
34+
else
35+
echo "value=release" >> $GITHUB_OUTPUT
36+
fi
37+
38+
- name: Deploy via SSH
39+
uses: appleboy/[email protected]
40+
with:
41+
host: ${{ secrets.CD_HOST }}
42+
username: ${{ secrets.CD_USER }}
43+
key: ${{ secrets.CD_SSH_KEY }}
44+
port: ${{ secrets.CD_PORT }}
45+
script: |
46+
export DEPLOY_TAG='${{ steps.tag.outputs.value }}'
47+
bash -lc '/srv/docsa/infra/deploy.sh'

infra/deploy.sh

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
cd /srv/docsa/infra
5+
6+
# 특정 태그로 배포시 DEPLOY_TAG=...
7+
IMAGE_BASE="ghcr.io/prgrms-web-devcourse-final-project/docsa-backend"
8+
TAG="${DEPLOY_TAG:-}" # 비어있으면 compose에 적힌 태그 사용
9+
OVR=""
10+
if [[ -n "$TAG" ]]; then
11+
OVR="docker-compose.override.deploy.yml"
12+
cat > "$OVR" <<EOF
13+
services:
14+
app:
15+
image: ${IMAGE_BASE}:${TAG}
16+
EOF
17+
fi
18+
19+
FILES=(-f docker-compose.yml)
20+
[[ -n "$OVR" ]] && FILES+=(-f "$OVR")
21+
22+
# 최신 이미지 받고 교체
23+
docker compose "${FILES[@]}" pull app
24+
docker compose "${FILES[@]}" up -d app
25+
26+
# 헬스체크 대기 (최대 120s)
27+
echo -n "Waiting for app (docsa-app) to be healthy"
28+
ok=0
29+
for i in {1..60}; do
30+
status="$(docker inspect -f '{{.State.Health.Status}}' docsa-app 2>/dev/null || echo none)"
31+
if [[ "$status" == "healthy" ]]; then ok=1; echo -e "\nApp healthy"; break; fi
32+
sleep 2; echo -n "."
33+
done
34+
35+
# 임시 override 제거 & 청소
36+
[[ -n "$OVR" ]] && rm -f "$OVR"
37+
docker image prune -f >/dev/null 2>&1 || true
38+
39+
# 실패 처리
40+
if [[ $ok -eq 0 ]]; then
41+
echo -e "\nApp failed to become healthy (status=$status)"
42+
docker logs --tail=200 docsa-app || true
43+
exit 1
44+
fi

0 commit comments

Comments
 (0)