Skip to content

Deploy

Deploy #2

Workflow file for this run

name: Deploy
on:
push:
branches: [dev, main]
workflow_dispatch:
inputs:
target:
description: "배포 대상 (staging | prod)"
required: true
default: "staging"
type: choice
options: [staging, prod]
# 동시 배포 금지. 같은 대상에 새 push 가 오면 in-progress 취소.
concurrency:
group: deploy-${{ github.ref_name }}
cancel-in-progress: false
permissions:
contents: read
packages: write # ghcr.io push 권한
env:
REGISTRY: ghcr.io
IMAGE: ${{ github.repository }}
jobs:
# ---------------------------------------------------------------------------
# 1) build image → ghcr.io 푸시
# ---------------------------------------------------------------------------
build:
name: Build & push image
runs-on: ubuntu-latest
timeout-minutes: 15
outputs:
image_tag: ${{ steps.meta.outputs.image_tag }}
target: ${{ steps.meta.outputs.target }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Resolve target + tag
id: meta
run: |
# 우선순위: workflow_dispatch.inputs.target → branch
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
target="${{ inputs.target }}"
elif [ "${{ github.ref_name }}" = "main" ]; then
target="prod"
else
target="staging"
fi
sha_short="$(echo "${{ github.sha }}" | cut -c1-7)"
image_tag="${target}-${sha_short}"
echo "target=$target" >> "$GITHUB_OUTPUT"
echo "image_tag=$image_tag" >> "$GITHUB_OUTPUT"
echo "image_ref=${REGISTRY}/${IMAGE}:${image_tag}" >> "$GITHUB_OUTPUT"
echo "image_ref_target=${REGISTRY}/${IMAGE}:${target}" >> "$GITHUB_OUTPUT"
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to GHCR
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build & push
uses: docker/build-push-action@v6
with:
context: .
file: deploy/Dockerfile
push: true
tags: |
${{ steps.meta.outputs.image_ref }}
${{ steps.meta.outputs.image_ref_target }}
cache-from: type=gha
cache-to: type=gha,mode=max
# ---------------------------------------------------------------------------
# 2) SSH 로 N100 접속 → docker compose pull && up -d
# ---------------------------------------------------------------------------
deploy:
name: Deploy to ${{ needs.build.outputs.target }}
needs: build
runs-on: ubuntu-latest
timeout-minutes: 10
# prod 는 환경(environment) 보호로 수동 승인 가능
environment:
name: ${{ needs.build.outputs.target }}
steps:
- name: Sanity check secrets
run: |
missing=""
for v in N100_HOST N100_USER N100_SSH_KEY; do
eval val="\$$v"
if [ -z "$val" ]; then missing="$missing $v"; fi
done
if [ -n "$missing" ]; then
echo "::error::Missing required secrets:$missing"
echo "GitHub repo Settings → Secrets and variables → Actions 에서 등록하세요."
exit 1
fi
env:
N100_HOST: ${{ secrets.N100_HOST }}
N100_USER: ${{ secrets.N100_USER }}
N100_SSH_KEY: ${{ secrets.N100_SSH_KEY }}
- name: Pull & restart on N100
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.N100_HOST }}
username: ${{ secrets.N100_USER }}
key: ${{ secrets.N100_SSH_KEY }}
# 호스트의 deploy/ 디렉터리에서 pull → up.
# IMAGE_TAG selects the pushed GHCR image; MURUN_ENV_FILE selects .env.staging/.env.prod.
script: |
set -e
cd ${MURUN_DEPLOY_DIR:-~/murun-peterabcd/deploy}
export IMAGE_TAG="${{ needs.build.outputs.image_tag }}"
export MURUN_ENV_FILE=".env.${{ needs.build.outputs.target }}"
docker compose -p murun-${{ needs.build.outputs.target }} --env-file "$MURUN_ENV_FILE" pull
docker compose -p murun-${{ needs.build.outputs.target }} --env-file "$MURUN_ENV_FILE" up -d --remove-orphans
docker image prune -f