chore(githooks): rename hooks dir to .githooks and stop old next processes

Move repository-managed git hooks from `git_hooks/` to `.githooks/` to follow the conventional hidden-directory naming, and add a graceful shutdown step in `post-receive` that terminates any running `next start` / `next-server` processes (SIGTERM → wait 2s → SIGKILL → wait 1s) before relaunching, avoiding EADDRINUSE port conflicts so the freshly built code actually takes effect. README updated to reference the new path.
This commit is contained in:
2026-06-12 18:24:08 +08:00
parent 8afcc40b9c
commit 546e5f4b3d
2 changed files with 18 additions and 3 deletions
+62
View File
@@ -0,0 +1,62 @@
#!/bin/sh
# Post-receive hook: push 后自动 build + start
#
# 触发场景:
# - 非 bare repo + receive.denyCurrentBranch=updateInstead:本地推送自动部署
#
# 用途:执行 package.json 中的 `build` + `start` 脚本
# - 实际调用 `pnpm run build`(输出丢,仅记退出码)
# - 再后台启 `pnpm run start`nohup,输出丢,hook 立即返回)
# 准备生产环境变量(从 env-example/.env.production.example 复制 → .env.production
cp -f env-example/.env.production.example .env.production
# 日志文件路径(**覆盖**模式:每次推送都生成全新日志)
LOG_FILE="$(git rev-parse --show-toplevel)/logs/post-receive.log"
mkdir -p "$(dirname "$LOG_FILE")"
# 元信息头(**首**次写 → 覆盖)
{
echo "=== post-receive @ $(date -u +%Y-%m-%dT%H:%M:%SZ) ==="
echo "branch: $(git rev-parse --abbrev-ref HEAD)"
echo "commit: $(git rev-parse --short HEAD)"
echo "cwd: $(pwd)"
echo ""
} > "$LOG_FILE"
# pnpm run build → 输出**丢**>/dev/null 2>&1),仅捕获退出码写日志
echo "=== build START @ $(date -u +%Y-%m-%dT%H:%M:%SZ) ===" >> "$LOG_FILE"
pnpm run build > /dev/null 2>&1
BUILD_EXIT=$?
echo "=== build EXIT_CODE=$BUILD_EXIT @ $(date -u +%Y-%m-%dT%H:%M:%SZ) ===" >> "$LOG_FILE"
echo "" >> "$LOG_FILE"
# build 失败 → **不**启 start(避免用旧 .next 跑新代码),立即退出
if [ $BUILD_EXIT -ne 0 ]; then
echo "=== ABORTED @ $(date -u +%Y-%m-%dT%H:%M:%SZ) (build failed, start skipped) ===" >> "$LOG_FILE"
exit $BUILD_EXIT
fi
# build 成功 → **先**关闭旧 next 进程(**避**免端口 EADDRINUSE 冲突,新代码**能**生效)
echo "=== stop existing next @ $(date -u +%Y-%m-%dT%H:%M:%SZ) ===" >> "$LOG_FILE"
# 1) **优**雅**关**闭(SIGTERM)—— 旧进程**自**己 drain 现有请求
pkill -f "next start" 2>/dev/null
pkill -f "next-server" 2>/dev/null
# 2) 等 2s 让**优**雅**关**闭**完**成
sleep 2
# 3) 强杀(SIGKILL)—— **还**在**的**话
pkill -9 -f "next start" 2>/dev/null
pkill -9 -f "next-server" 2>/dev/null
# 4) **最**后等 1s 确**保**端口**完**全释放
sleep 1
echo "=== stop DONE @ $(date -u +%Y-%m-%dT%H:%M:%SZ) ===" >> "$LOG_FILE"
echo "" >> "$LOG_FILE"
# pnpm run start → **后台**跑(nohup ... &),long-running 进程
# 输出**丢**> /dev/null 2>&1)—— 真实 next 日志要看 next 自身 stdout/stderr**不**在本任务范围
echo "=== start LAUNCH @ $(date -u +%Y-%m-%dT%H:%M:%SZ) ===" >> "$LOG_FILE"
nohup pnpm run start > /dev/null 2>&1 &
START_PID=$!
echo "=== start PID=$START_PID @ $(date -u +%Y-%m-%dT%H:%M:%SZ) ===" >> "$LOG_FILE"
exit 0