bab731bd21
Remove the workaround that derived REPO_TOPLEVEL from `git rev-parse --absolute-git-dir` and fall back to `git rev-parse --show-toplevel` directly. Also drop the related comments and debug echo. The simpler approach is sufficient for the hook's needs and makes the script easier to maintain.
146 lines
6.2 KiB
Bash
Executable File
146 lines
6.2 KiB
Bash
Executable File
#!/bin/sh
|
||
# Post-receive hook: push 后自动 build + start
|
||
#
|
||
|
||
# pnpm 环境变量
|
||
export NVM_DIR="$HOME/.nvm"
|
||
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
|
||
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion
|
||
|
||
REPO_TOPLEVEL="$(git rev-parse --show-toplevel 2>/dev/null || echo "$PWD")"
|
||
cd "$REPO_TOPLEVEL" || { echo "FATAL: cannot cd to $REPO_TOPLEVEL" >&2; exit 1; }
|
||
|
||
# ============================================================
|
||
# 0. sync_worktree —— 将**工**作**树**同步到**新** push 的 HEAD
|
||
# 背景:服务器 .git/config 设了 receive.denyCurrentBranch=updateInstead 时
|
||
# git 自**动**更**新**工作**树**但**会**跳过**此**钩子;**改**为 false 后
|
||
# git **不**会**更**新**工作**树**,**手**动 reset --hard 同步**才**能**让**下**面**
|
||
# 的 build **用**上**新**代**码**。
|
||
# ============================================================
|
||
sync_worktree() {
|
||
echo "=== sync_worktree: git reset --hard HEAD @ $(date -u +%Y-%m-%dT%H:%M:%SZ) ==="
|
||
git reset --hard HEAD
|
||
}
|
||
|
||
# ============================================================
|
||
# 1. init_log_file —— 定**义** LOG_FILE + 创**建** logs/ 目**录**
|
||
# ============================================================
|
||
init_log_file() {
|
||
LOG_FILE="$REPO_TOPLEVEL/logs/post-receive.log"
|
||
mkdir -p "$(dirname "$LOG_FILE")"
|
||
}
|
||
|
||
# ============================================================
|
||
# 2. write_metadata_header —— **覆**盖写**入**元信息(**首**次**写** → **覆**盖**让日志**开**头是**这**个)
|
||
# ============================================================
|
||
write_metadata_header() {
|
||
{
|
||
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"
|
||
}
|
||
|
||
# ============================================================
|
||
# 3. copy_env_by_branch —— 根**据**分支选 env-example → .env
|
||
# main 分支 → .env.production(prod 部署)
|
||
# test 分支 → .env.local(test **不**碰 .env.production,**避**免**读**到 prod 域名)
|
||
# dev 分支 → .env.local(**未**配远端**用**途,**但**保**留**)
|
||
# ============================================================
|
||
copy_env_by_branch() {
|
||
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
|
||
echo "=== branch: $CURRENT_BRANCH ===" >> "$LOG_FILE"
|
||
case "$CURRENT_BRANCH" in
|
||
main)
|
||
cp -f env-example/.env.production.example .env.production
|
||
echo "=== env: copied .env.production (main → prod) ===" >> "$LOG_FILE"
|
||
;;
|
||
test)
|
||
cp -f env-example/.env.local.example .env.local
|
||
echo "=== env: copied .env.local (test → test) ===" >> "$LOG_FILE"
|
||
;;
|
||
dev)
|
||
cp -f env-example/.env.development.example .env.local
|
||
echo "=== env: copied .env.local (dev → dev) ===" >> "$LOG_FILE"
|
||
;;
|
||
*)
|
||
echo "=== env: UNKNOWN branch '$CURRENT_BRANCH', skip env copy ===" >> "$LOG_FILE"
|
||
;;
|
||
esac
|
||
}
|
||
|
||
# ============================================================
|
||
# 4. run_build —— 跑 `pnpm run build`,输出**丢**,**捕**获退出码写日志
|
||
# 返回:build 退出码(main **用** if ! run_build 决**定**是否**继**续)
|
||
# ============================================================
|
||
run_build() {
|
||
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"
|
||
return $BUILD_EXIT
|
||
}
|
||
|
||
# ============================================================
|
||
# 5. stop_existing_next —— 两阶段 kill + 等 1s 确**保**端口**完**全释放
|
||
# 1) 优**雅**关**闭**(SIGTERM)—— 旧**进**程**自**己 drain
|
||
# 2) 等 2s
|
||
# 3) 强杀(SIGKILL)—— **还**在**的**话
|
||
# 4) 等 1s
|
||
# ============================================================
|
||
stop_existing_next() {
|
||
echo "=== stop existing next @ $(date -u +%Y-%m-%dT%H:%M:%SZ) ===" >> "$LOG_FILE"
|
||
pkill -f "next start" 2>/dev/null
|
||
pkill -f "next-server" 2>/dev/null
|
||
sleep 2
|
||
pkill -9 -f "next start" 2>/dev/null
|
||
pkill -9 -f "next-server" 2>/dev/null
|
||
sleep 1
|
||
echo "=== stop DONE @ $(date -u +%Y-%m-%dT%H:%M:%SZ) ===" >> "$LOG_FILE"
|
||
echo "" >> "$LOG_FILE"
|
||
}
|
||
|
||
# ============================================================
|
||
# 6. launch_next —— 后**台**启 `pnpm run start`,捕 PID
|
||
# ============================================================
|
||
launch_next() {
|
||
# next stdout/stderr 接**到** logs/next-server.log(**覆**盖**模式**,**每**次 deploy **重**新**开**始)
|
||
NEXT_LOG_FILE="$REPO_TOPLEVEL/logs/next-server.log"
|
||
echo "=== start LAUNCH @ $(date -u +%Y-%m-%dT%H:%M:%SZ) ===" >> "$LOG_FILE"
|
||
nohup pnpm run start > "$NEXT_LOG_FILE" 2>&1 &
|
||
START_PID=$!
|
||
echo "=== start PID=$START_PID @ $(date -u +%Y-%m-%dT%H:%M:%SZ) ===" >> "$LOG_FILE"
|
||
}
|
||
|
||
# ============================================================
|
||
# 7. log_abort —— build 失败**时**写**结**束**标**记(**不**输**出** START LAUNCH)
|
||
# ============================================================
|
||
log_abort() {
|
||
echo "=== ABORTED @ $(date -u +%Y-%m-%dT%H:%M:%SZ) (build failed, start skipped) ===" >> "$LOG_FILE"
|
||
}
|
||
|
||
# ============================================================
|
||
# main —— 调**度**所**有**步骤
|
||
# ============================================================
|
||
main() {
|
||
init_log_file
|
||
sync_worktree # **先**同步工作**树**到**新** HEAD(**与** git config denyCurrentBranch 配**合**)
|
||
write_metadata_header # **先**覆盖写元信息(**这**样 env copy 日**志****能**保留在**后**面)
|
||
copy_env_by_branch # **追**加 env copy 日志
|
||
|
||
if ! run_build; then
|
||
log_abort
|
||
exit $BUILD_EXIT # build 失败 → **不**启 start(**避**免**用**旧 .next **跑**新代码)
|
||
fi
|
||
|
||
stop_existing_next # build 成功 → **先**关旧**进**程
|
||
launch_next # 再启新
|
||
}
|
||
|
||
main "$@"
|
||
|
||
exit 0
|