fix(deploy): Mac SSH 배포 지원 + .env.local 자동 로드
- .env.local 파일에서 NAS_SSH_TARGET 등 SSH 설정 자동 로드 - NAS_SSH_TARGET 설정 시 SMB 마운트보다 SSH 우선 사용 - SMB 쓰기 실패(EIO) 시 스택트레이스 대신 SSH 설정 안내 메시지 출력 - .env.local을 .gitignore에 추가 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -22,3 +22,4 @@ dist-ssr
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
.env.local
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
const { execSync } = require("child_process");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
// Load .env.local from project root if present (persists NAS_SSH_TARGET etc.)
|
||||
const envLocalPath = path.join(__dirname, "..", ".env.local");
|
||||
if (fs.existsSync(envLocalPath)) {
|
||||
for (const line of fs.readFileSync(envLocalPath, "utf8").split("\n")) {
|
||||
const trimmed = line.trim();
|
||||
if (!trimmed || trimmed.startsWith("#")) continue;
|
||||
const idx = trimmed.indexOf("=");
|
||||
if (idx < 0) continue;
|
||||
const k = trimmed.slice(0, idx).trim();
|
||||
const v = trimmed.slice(idx + 1).trim();
|
||||
if (!(k in process.env)) process.env[k] = v;
|
||||
}
|
||||
}
|
||||
|
||||
const isWin = process.platform === "win32";
|
||||
const isMac = process.platform === "darwin";
|
||||
@@ -12,10 +27,6 @@ if (!fs.existsSync(src)) {
|
||||
console.error("dist not found. Run build first.");
|
||||
process.exit(1);
|
||||
}
|
||||
if (!fs.existsSync(dst)) {
|
||||
console.error("NAS path not found. Check mount: " + dst);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (isWin) {
|
||||
const cmd =
|
||||
@@ -26,33 +37,43 @@ if (isWin) {
|
||||
const sshPath =
|
||||
process.env.NAS_SSH_PATH || "/volume1/docker/webpage/frontend/";
|
||||
const sshPort = process.env.NAS_SSH_PORT;
|
||||
|
||||
// SSH 경로: NAS_SSH_TARGET이 설정된 경우 항상 우선
|
||||
if (sshTarget) {
|
||||
console.log(`Deploying via SSH → ${sshTarget}:${sshPath}`);
|
||||
const sshCmd = sshPort ? `ssh -p ${sshPort}` : "ssh";
|
||||
execSync(
|
||||
`rsync -r --delete --delete-delay -e \"${sshCmd}\" ${src}/ ${sshTarget}:${sshPath}`,
|
||||
`rsync -r --delete --delete-delay -e "${sshCmd}" ${src}/ ${sshTarget}:${sshPath}`,
|
||||
{ stdio: "inherit" }
|
||||
);
|
||||
process.exit(0);
|
||||
}
|
||||
// rsync on macOS + SMB/NAS can be flaky; use ditto after a safe clean.
|
||||
|
||||
// SMB 마운트 경로 fallback
|
||||
if (!fs.existsSync(dst)) {
|
||||
console.error("NAS path not found: " + dst);
|
||||
printSshHint();
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!dst.includes("docker/webpage/frontend")) {
|
||||
console.error("Safety check failed: unexpected dst path: " + dst);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
try {
|
||||
const testPath = `${dst}.deploy-write-test`;
|
||||
fs.writeFileSync(testPath, "ok");
|
||||
fs.unlinkSync(testPath);
|
||||
} catch (err) {
|
||||
console.error("NAS write test failed (EIO / permission error).");
|
||||
console.error(
|
||||
"NAS write test failed. Files may be locked or permissions are read-only."
|
||||
"macOS SMB → Synology 쓰기 실패는 흔한 이슈입니다. SSH 배포를 사용하세요.\n"
|
||||
);
|
||||
console.error(
|
||||
"Try stopping services using the folder, remounting the share with write access,",
|
||||
"or set NAS_SSH_TARGET to deploy over SSH instead."
|
||||
);
|
||||
throw err;
|
||||
printSshHint();
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const sleep = (ms) =>
|
||||
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
||||
const retry = (fn, attempts = 6) => {
|
||||
@@ -96,3 +117,15 @@ if (isWin) {
|
||||
const cmd = `${baseArgs.join(" ")} ${src}/ ${dst}`;
|
||||
execSync(cmd, { stdio: "inherit" });
|
||||
}
|
||||
|
||||
function printSshHint() {
|
||||
console.error("──────────────────────────────────────────────────");
|
||||
console.error("SSH 배포 설정 방법:");
|
||||
console.error(" 프로젝트 루트에 .env.local 파일을 만들고 아래 내용을 입력하세요:");
|
||||
console.error("");
|
||||
console.error(" NAS_SSH_TARGET=<NAS_유저명>@gahusb.synology.me");
|
||||
console.error(" NAS_SSH_PORT=<SSH_포트> # 기본 22, DSM에서 확인");
|
||||
console.error("");
|
||||
console.error(" 이후 npm run release:nas 를 다시 실행하면 rsync over SSH로 배포됩니다.");
|
||||
console.error("──────────────────────────────────────────────────");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user