v1.3.9: NAS 마이그레이션 루프 stdin 소비 버그 수정

psql이 파이프 입력을 읽어 baseline·migrate가 첫 파일만 처리되던 문제를 /dev/null 연결과 for 루프로 해결한다.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-05-20 14:49:59 +09:00
parent a396d1d022
commit f8e04003fd
4 changed files with 33 additions and 14 deletions

View File

@@ -1,5 +1,9 @@
# 업데이트 이력 # 업데이트 이력
## v1.3.9
- NAS 마이그레이션: `psql`이 while 루프 stdin을 소비해 001만 처리되던 `migrate-production-db.sh` 버그 수정.
## v1.3.8 ## v1.3.8
- NAS 마이그레이션: `.env.production`이 없을 때 `.env` 또는 실행 중 DB 컨테이너 환경 변수로 동작하도록 `migrate-production-db.sh` 보정. - NAS 마이그레이션: `.env.production`이 없을 때 `.env` 또는 실행 중 DB 컨테이너 환경 변수로 동작하도록 `migrate-production-db.sh` 보정.

6
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "sori.studio", "name": "sori.studio",
"version": "1.3.8", "version": "1.3.9",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "sori.studio", "name": "sori.studio",
"version": "1.3.8", "version": "1.3.9",
"hasInstallScript": true, "hasInstallScript": true,
"dependencies": { "dependencies": {
"@nuxtjs/tailwindcss": "^6.14.0", "@nuxtjs/tailwindcss": "^6.14.0",
@@ -4439,7 +4439,7 @@
} }
}, },
"node_modules/accepts": { "node_modules/accepts": {
"version": "1.3.8", "version": "1.3.9",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
"integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
"license": "MIT", "license": "MIT",

View File

@@ -1,6 +1,6 @@
{ {
"name": "sori.studio", "name": "sori.studio",
"version": "1.3.8", "version": "1.3.9",
"private": true, "private": true,
"type": "module", "type": "module",
"imports": { "imports": {

View File

@@ -77,8 +77,9 @@ load_db_env_from_container() {
fi fi
} }
# psql이 while 루프 stdin을 읽지 않도록 /dev/null 연결
psql_exec() { psql_exec() {
compose exec -T "$DB_SERVICE" psql -v ON_ERROR_STOP=1 -U "$POSTGRES_USER" -d "$POSTGRES_DB" "$@" compose exec -T "$DB_SERVICE" psql -v ON_ERROR_STOP=1 -U "$POSTGRES_USER" -d "$POSTGRES_DB" "$@" </dev/null
} }
query_sql() { query_sql() {
@@ -130,18 +131,32 @@ is_applied() {
[ "$(query_sql "SELECT EXISTS (SELECT 1 FROM $SCHEMA_MIGRATIONS_TABLE WHERE file_name = '$file_name');")" = "t" ] [ "$(query_sql "SELECT EXISTS (SELECT 1 FROM $SCHEMA_MIGRATIONS_TABLE WHERE file_name = '$file_name');")" = "t" ]
} }
matches_baseline_target() {
file_name=$1
if [ -z "$BASELINE_TARGET" ]; then
return 0
fi
if [ "$file_name" = "$BASELINE_TARGET" ]; then
return 0
fi
echo "$file_name" | grep -q "^${BASELINE_TARGET}_"
}
print_status() { print_status() {
if ! has_schema_migrations_table; then if ! has_schema_migrations_table; then
echo "schema_migrations 테이블이 없습니다." echo "schema_migrations 테이블이 없습니다."
echo "기존 운영 DB라면 먼저 sh scripts/migrate-production-db.sh baseline 으로 현재 파일들을 적용 완료로 기록하세요." echo "기존 운영 DB라면 먼저 sh scripts/migrate-production-db.sh baseline 으로 현재 파일들을 적용 완료로 기록하세요."
migration_files | while IFS= read -r file_name; do for file_name in $(migration_files); do
echo "pending $file_name" echo "pending $file_name"
done done
return 0 return 0
fi fi
migration_files | while IFS= read -r file_name; do for file_name in $(migration_files); do
if is_applied "$file_name"; then if is_applied "$file_name"; then
echo "applied $file_name" echo "applied $file_name"
else else
@@ -152,18 +167,18 @@ print_status() {
baseline_migrations() { baseline_migrations() {
ensure_schema_migrations_table ensure_schema_migrations_table
found_target=0 stop_after_current=0
migration_files | while IFS= read -r file_name; do for file_name in $(migration_files); do
if [ -n "$BASELINE_TARGET" ] && [ "$found_target" -eq 1 ]; then if [ "$stop_after_current" -eq 1 ]; then
continue break
fi fi
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"
if [ -n "$BASELINE_TARGET" ] && { [ "$file_name" = "$BASELINE_TARGET" ] || echo "$file_name" | grep -q "^${BASELINE_TARGET}_"; }; then if [ -n "$BASELINE_TARGET" ] && matches_baseline_target "$file_name"; then
found_target=1 stop_after_current=1
fi fi
done done
@@ -186,7 +201,7 @@ migrate_database() {
ensure_schema_migrations_table ensure_schema_migrations_table
migration_files | while IFS= read -r file_name; do for file_name in $(migration_files); do
if is_applied "$file_name"; then if is_applied "$file_name"; then
continue continue
fi fi