v1.3.8: NAS 마이그레이션 환경 파일 없을 때 보정
.env.production이 없으면 .env 또는 실행 중 DB 컨테이너 환경 변수로 migrate-production-db.sh가 동작한다. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -199,6 +199,7 @@ docker compose --env-file .env.production up -d --build
|
|||||||
- 로컬 개발 Docker Compose 실행 시 `ENV_FILE=.env.development`와 `--env-file .env.development`를 함께 사용
|
- 로컬 개발 Docker Compose 실행 시 `ENV_FILE=.env.development`와 `--env-file .env.development`를 함께 사용
|
||||||
- 로컬 개발 DB 마이그레이션은 `npm run db:migrate:dev`로 실행
|
- 로컬 개발 DB 마이그레이션은 `npm run db:migrate:dev`로 실행
|
||||||
- NAS 운영 DB 마이그레이션은 NAS 호스트에 npm이 없어도 실행할 수 있도록 `sh scripts/migrate-production-db.sh status`로 적용 상태를 확인하고, `sh scripts/migrate-production-db.sh migrate`로 미적용 파일만 실행한다.
|
- NAS 운영 DB 마이그레이션은 NAS 호스트에 npm이 없어도 실행할 수 있도록 `sh scripts/migrate-production-db.sh status`로 적용 상태를 확인하고, `sh scripts/migrate-production-db.sh migrate`로 미적용 파일만 실행한다.
|
||||||
|
- 운영 환경 파일은 프로젝트 루트의 `.env.production`을 우선 사용한다. 없으면 `.env`를 읽고, 둘 다 없으면 실행 중인 `sori-studio-db` 컨테이너의 `POSTGRES_DB`·`POSTGRES_USER`를 사용한다.
|
||||||
- `schema_migrations`가 없는 기존 운영 DB에서 `posts` 테이블이 감지되면 `migrate`는 001부터 자동 실행하지 않는다. 현재 코드 기준 최신 DB라면 최초 1회 `sh scripts/migrate-production-db.sh baseline`으로 기존 파일을 적용 완료로 기록한다. 특정 번호까지만 기록하려면 예: `sh scripts/migrate-production-db.sh baseline 031`.
|
- `schema_migrations`가 없는 기존 운영 DB에서 `posts` 테이블이 감지되면 `migrate`는 001부터 자동 실행하지 않는다. 현재 코드 기준 최신 DB라면 최초 1회 `sh scripts/migrate-production-db.sh baseline`으로 기존 파일을 적용 완료로 기록한다. 특정 번호까지만 기록하려면 예: `sh scripts/migrate-production-db.sh baseline 031`.
|
||||||
- 네비게이션 계층(`parent_id`, `is_folder`)은 `017_navigation_hierarchy.sql` 적용 후 저장 API가 정상 동작한다(미적용 시 `INSERT` 컬럼 불일치).
|
- 네비게이션 계층(`parent_id`, `is_folder`)은 `017_navigation_hierarchy.sql` 적용 후 저장 API가 정상 동작한다(미적용 시 `INSERT` 컬럼 불일치).
|
||||||
- 회원 마지막 로그인 표시(`previous_last_seen_at`, `previous_last_seen_ip`)는 `021_add_member_previous_login.sql` 적용 후 정상 동작한다.
|
- 회원 마지막 로그인 표시(`previous_last_seen_at`, `previous_last_seen_ip`)는 `021_add_member_previous_login.sql` 적용 후 정상 동작한다.
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
# 업데이트 이력
|
# 업데이트 이력
|
||||||
|
|
||||||
|
## v1.3.8
|
||||||
|
|
||||||
|
- NAS 마이그레이션: `.env.production`이 없을 때 `.env` 또는 실행 중 DB 컨테이너 환경 변수로 동작하도록 `migrate-production-db.sh` 보정.
|
||||||
|
|
||||||
## v1.3.7
|
## v1.3.7
|
||||||
|
|
||||||
- NAS 마이그레이션: npm 없는 NAS 호스트에서도 실행 가능한 `scripts/migrate-production-db.sh` 추가.
|
- NAS 마이그레이션: npm 없는 NAS 호스트에서도 실행 가능한 `scripts/migrate-production-db.sh` 추가.
|
||||||
|
|||||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "sori.studio",
|
"name": "sori.studio",
|
||||||
"version": "1.3.7",
|
"version": "1.3.8",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "sori.studio",
|
"name": "sori.studio",
|
||||||
"version": "1.3.7",
|
"version": "1.3.8",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nuxtjs/tailwindcss": "^6.14.0",
|
"@nuxtjs/tailwindcss": "^6.14.0",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "sori.studio",
|
"name": "sori.studio",
|
||||||
"version": "1.3.7",
|
"version": "1.3.8",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"imports": {
|
"imports": {
|
||||||
|
|||||||
@@ -2,28 +2,79 @@
|
|||||||
set -eu
|
set -eu
|
||||||
|
|
||||||
ROOT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)
|
ROOT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)
|
||||||
ENV_FILE=${ENV_FILE:-.env.production}
|
|
||||||
DB_SERVICE=${DB_SERVICE:-sori-studio-db}
|
DB_SERVICE=${DB_SERVICE:-sori-studio-db}
|
||||||
MIGRATIONS_DIR="$ROOT_DIR/db/migrations"
|
MIGRATIONS_DIR="$ROOT_DIR/db/migrations"
|
||||||
CONTAINER_MIGRATIONS_DIR=${CONTAINER_MIGRATIONS_DIR:-/docker-entrypoint-initdb.d}
|
CONTAINER_MIGRATIONS_DIR=${CONTAINER_MIGRATIONS_DIR:-/docker-entrypoint-initdb.d}
|
||||||
SCHEMA_MIGRATIONS_TABLE=${SCHEMA_MIGRATIONS_TABLE:-schema_migrations}
|
SCHEMA_MIGRATIONS_TABLE=${SCHEMA_MIGRATIONS_TABLE:-schema_migrations}
|
||||||
MODE=${1:-migrate}
|
MODE=${1:-migrate}
|
||||||
BASELINE_TARGET=${2:-}
|
BASELINE_TARGET=${2:-}
|
||||||
|
COMPOSE_ENV_FILE=
|
||||||
|
|
||||||
cd "$ROOT_DIR"
|
cd "$ROOT_DIR"
|
||||||
|
|
||||||
if [ -f "$ENV_FILE" ]; then
|
|
||||||
set -a
|
|
||||||
# shellcheck disable=SC1090
|
|
||||||
. "$ENV_FILE"
|
|
||||||
set +a
|
|
||||||
fi
|
|
||||||
|
|
||||||
POSTGRES_DB=${POSTGRES_DB:-sori_studio}
|
POSTGRES_DB=${POSTGRES_DB:-sori_studio}
|
||||||
POSTGRES_USER=${POSTGRES_USER:-sori_studio}
|
POSTGRES_USER=${POSTGRES_USER:-sori_studio}
|
||||||
|
|
||||||
|
# 환경 파일(.env.production → .env) 선택
|
||||||
|
pick_compose_env_file() {
|
||||||
|
if [ -n "${ENV_FILE:-}" ] && [ -r "$ENV_FILE" ]; then
|
||||||
|
COMPOSE_ENV_FILE=$ENV_FILE
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -r .env.production ]; then
|
||||||
|
COMPOSE_ENV_FILE=.env.production
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -r .env ]; then
|
||||||
|
COMPOSE_ENV_FILE=.env
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
COMPOSE_ENV_FILE=
|
||||||
|
}
|
||||||
|
|
||||||
|
# 환경 파일 로드(없으면 컨테이너 환경 변수 사용)
|
||||||
|
load_env_file() {
|
||||||
|
pick_compose_env_file
|
||||||
|
|
||||||
|
if [ -z "$COMPOSE_ENV_FILE" ]; then
|
||||||
|
echo "환경 파일(.env.production 또는 .env)이 없습니다. 실행 중인 DB 컨테이너 환경 변수를 사용합니다." >&2
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
set -a
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
. "./$COMPOSE_ENV_FILE"
|
||||||
|
set +a
|
||||||
|
}
|
||||||
|
|
||||||
compose() {
|
compose() {
|
||||||
docker compose --env-file "$ENV_FILE" "$@"
|
if [ -n "$COMPOSE_ENV_FILE" ]; then
|
||||||
|
docker compose --env-file "$COMPOSE_ENV_FILE" "$@"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
docker compose "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 실행 중인 DB 컨테이너에서 PostgreSQL 계정 정보 읽기
|
||||||
|
load_db_env_from_container() {
|
||||||
|
if ! compose exec -T "$DB_SERVICE" true >/dev/null 2>&1; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
container_db=$(compose exec -T "$DB_SERVICE" printenv POSTGRES_DB 2>/dev/null | tr -d '\r' || true)
|
||||||
|
container_user=$(compose exec -T "$DB_SERVICE" printenv POSTGRES_USER 2>/dev/null | tr -d '\r' || true)
|
||||||
|
|
||||||
|
if [ -n "$container_db" ]; then
|
||||||
|
POSTGRES_DB=$container_db
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$container_user" ]; then
|
||||||
|
POSTGRES_USER=$container_user
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
psql_exec() {
|
psql_exec() {
|
||||||
@@ -101,7 +152,6 @@ print_status() {
|
|||||||
|
|
||||||
baseline_migrations() {
|
baseline_migrations() {
|
||||||
ensure_schema_migrations_table
|
ensure_schema_migrations_table
|
||||||
baseline_count=0
|
|
||||||
found_target=0
|
found_target=0
|
||||||
|
|
||||||
migration_files | while IFS= read -r file_name; do
|
migration_files | while IFS= read -r file_name; do
|
||||||
@@ -111,7 +161,6 @@ baseline_migrations() {
|
|||||||
|
|
||||||
run_sql "INSERT INTO $SCHEMA_MIGRATIONS_TABLE (file_name) VALUES ('$file_name') ON CONFLICT (file_name) DO NOTHING;"
|
run_sql "INSERT INTO $SCHEMA_MIGRATIONS_TABLE (file_name) VALUES ('$file_name') ON CONFLICT (file_name) DO NOTHING;"
|
||||||
echo "baseline $file_name"
|
echo "baseline $file_name"
|
||||||
baseline_count=$((baseline_count + 1))
|
|
||||||
|
|
||||||
if [ -n "$BASELINE_TARGET" ] && { [ "$file_name" = "$BASELINE_TARGET" ] || echo "$file_name" | grep -q "^${BASELINE_TARGET}_"; }; then
|
if [ -n "$BASELINE_TARGET" ] && { [ "$file_name" = "$BASELINE_TARGET" ] || echo "$file_name" | grep -q "^${BASELINE_TARGET}_"; }; then
|
||||||
found_target=1
|
found_target=1
|
||||||
@@ -136,7 +185,6 @@ migrate_database() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
ensure_schema_migrations_table
|
ensure_schema_migrations_table
|
||||||
applied_count=0
|
|
||||||
|
|
||||||
migration_files | while IFS= read -r file_name; do
|
migration_files | while IFS= read -r file_name; do
|
||||||
if is_applied "$file_name"; then
|
if is_applied "$file_name"; then
|
||||||
@@ -146,13 +194,15 @@ migrate_database() {
|
|||||||
echo "apply $file_name"
|
echo "apply $file_name"
|
||||||
psql_exec -f "$CONTAINER_MIGRATIONS_DIR/$file_name"
|
psql_exec -f "$CONTAINER_MIGRATIONS_DIR/$file_name"
|
||||||
run_sql "INSERT INTO $SCHEMA_MIGRATIONS_TABLE (file_name) VALUES ('$file_name') ON CONFLICT (file_name) DO NOTHING;"
|
run_sql "INSERT INTO $SCHEMA_MIGRATIONS_TABLE (file_name) VALUES ('$file_name') ON CONFLICT (file_name) DO NOTHING;"
|
||||||
applied_count=$((applied_count + 1))
|
|
||||||
done
|
done
|
||||||
|
|
||||||
echo "마이그레이션 실행 완료"
|
echo "마이그레이션 실행 완료"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
load_env_file
|
||||||
|
load_db_env_from_container
|
||||||
ensure_database_ready
|
ensure_database_ready
|
||||||
|
load_db_env_from_container
|
||||||
|
|
||||||
case "$MODE" in
|
case "$MODE" in
|
||||||
status)
|
status)
|
||||||
|
|||||||
Reference in New Issue
Block a user