From 6e58f3bf867dbdcf3ff760ec34447e92419cfea5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EB=8F=99=ED=9B=88?= <2dh2@naver.com> Date: Wed, 18 Feb 2026 23:53:15 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EB=B0=B0=ED=8F=AC=20=EC=A0=84=20stage/?= =?UTF-8?q?prod=20DB=20=EC=9E=90=EB=8F=99=20=EB=B0=B1=EC=97=85=20=EB=8B=A8?= =?UTF-8?q?=EA=B3=84=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deploy-prod.yml | 48 +++++++++++++++++++++++++++++ .github/workflows/deploy-stage.yml | 49 ++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) diff --git a/.github/workflows/deploy-prod.yml b/.github/workflows/deploy-prod.yml index 2fa3136c..b5a4385c 100644 --- a/.github/workflows/deploy-prod.yml +++ b/.github/workflows/deploy-prod.yml @@ -68,6 +68,54 @@ jobs: cache-from: type=gha cache-to: type=gha,mode=max + - name: Backup prod database before deploy + uses: appleboy/ssh-action@v0.1.8 + with: + host: ${{ secrets.PROD_SERVER_IP }} + username: ${{ secrets.PROD_SERVER_USER }} + key: ${{ secrets.PROD_SERVER_SSH_KEY }} + port: ${{ secrets.PROD_SERVER_PORT }} + script: | + set -euo pipefail + + cd "${{ secrets.PROD_WORK_DIR }}" + + set -a + source .env + set +a + + BACKUP_DIR="${PWD}/dumps" + TS="$(date '+%Y%m%d_%H%M%S')" + DUMP_FILE="${BACKUP_DIR}/${TS}.sql" + + mkdir -p "${BACKUP_DIR}" + + # n일 지난 백업 정리 (원하면 주석 해제) + find "${BACKUP_DIR}" -type f -name "*.sql" -mtime +5 -delete + cleanup() { unset MYSQL_PWD || true; } + trap cleanup EXIT + + : "${MYSQL_HOST:?MYSQL_HOST is required}" + : "${MYSQL_PORT:=3306}" + : "${MYSQL_USERNAME:?MYSQL_USERNAME is required}" + : "${MYSQL_PASSWORD:?MYSQL_PASSWORD is required}" + : "${MYSQL_DATABASE:?MYSQL_DATABASE is required}" + + export MYSQL_PWD="${MYSQL_PASSWORD}" + + mysqldump \ + -h "${MYSQL_HOST}" \ + -P "${MYSQL_PORT}" \ + -u "${MYSQL_USERNAME}" \ + --single-transaction --quick \ + --routines --triggers --events \ + --default-character-set=utf8mb4 \ + --set-gtid-purged=OFF \ + "${MYSQL_DATABASE}" > "${DUMP_FILE}" + + test -s "${DUMP_FILE}" + ls -lh "${DUMP_FILE}" + - name: Deploy to prod server uses: appleboy/ssh-action@v0.1.8 with: diff --git a/.github/workflows/deploy-stage.yml b/.github/workflows/deploy-stage.yml index d713af51..26e2f07d 100644 --- a/.github/workflows/deploy-stage.yml +++ b/.github/workflows/deploy-stage.yml @@ -68,6 +68,55 @@ jobs: cache-from: type=gha cache-to: type=gha,mode=max + - name: Backup stage database before deploy + uses: appleboy/ssh-action@v0.1.8 + with: + host: ${{ secrets.STAGE_SERVER_IP }} + username: ${{ secrets.STAGE_SERVER_USER }} + key: ${{ secrets.STAGE_SERVER_SSH_KEY }} + port: ${{ secrets.STAGE_SERVER_PORT }} + envs: DB_HOST,DB_PORT,DB_USER,DB_PASSWORD,DB_NAME,DB_BACKUP_DIR + script: | + set -euo pipefail + + cd "${{ secrets.STAGE_WORK_DIR }}" + + set -a + source .env + set +a + + BACKUP_DIR="${PWD}/dumps" + TS="$(date '+%Y%m%d_%H%M%S')" + DUMP_FILE="${BACKUP_DIR}/${TS}.sql" + + mkdir -p "${BACKUP_DIR}" + + # n일 지난 백업 정리 (원하면 주석 해제) + find "${BACKUP_DIR}" -type f -name "*.sql" -mtime +5 -delete + cleanup() { unset MYSQL_PWD || true; } + trap cleanup EXIT + + : "${MYSQL_HOST:?MYSQL_HOST is required}" + : "${MYSQL_PORT:=3306}" + : "${MYSQL_USERNAME:?MYSQL_USERNAME is required}" + : "${MYSQL_PASSWORD:?MYSQL_PASSWORD is required}" + : "${MYSQL_DATABASE:?MYSQL_DATABASE is required}" + + export MYSQL_PWD="${MYSQL_PASSWORD}" + + mysqldump \ + -h "${MYSQL_HOST}" \ + -P "${MYSQL_PORT}" \ + -u "${MYSQL_USERNAME}" \ + --single-transaction --quick \ + --routines --triggers --events \ + --default-character-set=utf8mb4 \ + --set-gtid-purged=OFF \ + "${MYSQL_DATABASE}" > "${DUMP_FILE}" + + test -s "${DUMP_FILE}" + ls -lh "${DUMP_FILE}" + - name: Deploy to stage server uses: appleboy/ssh-action@v0.1.8 with: