157 lines
5.2 KiB
Bash
157 lines
5.2 KiB
Bash
#!/usr/bin/env bash
|
||
# datahub 更新脚本:git pull + 智能重建 + 滚动重启
|
||
#
|
||
# 用法:bash update.sh [选项]
|
||
# --force-rebuild 不看 git diff,强制重建所有镜像
|
||
# --skip-migrate 检测到新迁移时不提示,直接跳过
|
||
|
||
set -euo pipefail
|
||
|
||
B='\033[34m'; G='\033[32m'; Y='\033[33m'; R='\033[31m'; N='\033[0m'
|
||
step() { echo -e "\n${B}=> $*${N}"; }
|
||
ok() { echo -e "${G}[OK]${N} $*"; }
|
||
warn() { echo -e "${Y}[!]${N} $*"; }
|
||
err() { echo -e "${R}[ERR]${N} $*" >&2; }
|
||
|
||
FORCE_REBUILD=false
|
||
SKIP_MIGRATE=false
|
||
for arg in "$@"; do
|
||
case "$arg" in
|
||
--force-rebuild) FORCE_REBUILD=true ;;
|
||
--skip-migrate) SKIP_MIGRATE=true ;;
|
||
-h|--help)
|
||
sed -n '2,7p' "$0"
|
||
exit 0
|
||
;;
|
||
*) echo "未知参数: $arg" >&2; exit 1 ;;
|
||
esac
|
||
done
|
||
|
||
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
||
REPO_ROOT=$(cd "$SCRIPT_DIR/../../.." && pwd)
|
||
QUADLET_DIR="$HOME/.config/containers/systemd"
|
||
|
||
cd "$REPO_ROOT"
|
||
|
||
# 1. 必须是 git 仓库且工作区干净
|
||
if [ ! -d .git ]; then
|
||
err "$REPO_ROOT 不是 git 仓库"
|
||
exit 1
|
||
fi
|
||
if ! git diff --quiet || ! git diff --cached --quiet; then
|
||
err "工作区有未提交的变更,先 stash 或 commit"
|
||
git status --short
|
||
exit 1
|
||
fi
|
||
|
||
# 2. git pull
|
||
step "git pull"
|
||
OLD_HEAD=$(git rev-parse HEAD)
|
||
git pull --ff-only
|
||
NEW_HEAD=$(git rev-parse HEAD)
|
||
|
||
if [ "$OLD_HEAD" = "$NEW_HEAD" ] && [ "$FORCE_REBUILD" = false ]; then
|
||
ok "代码已是最新,无需更新(如需强制重建请加 --force-rebuild)"
|
||
exit 0
|
||
fi
|
||
|
||
# 3. 检测变更范围
|
||
if [ "$FORCE_REBUILD" = true ]; then
|
||
CH_BACKEND=true; CH_FRONTEND=true; CH_QUADLET=true
|
||
CH_PG_IMAGE=true; CH_MIGRATIONS=true
|
||
warn "强制重建:忽略 git diff"
|
||
else
|
||
DIFF=$(git diff --name-only "$OLD_HEAD" "$NEW_HEAD")
|
||
matches() { echo "$DIFF" | grep -qE "$1"; }
|
||
|
||
CH_BACKEND=$(matches '^backend/' && echo true || echo false)
|
||
CH_FRONTEND=$(matches '^(frontend/|deploy/podman/images/frontend/)' && echo true || echo false)
|
||
CH_QUADLET=$(matches '^deploy/podman/quadlet/' && echo true || echo false)
|
||
CH_PG_IMAGE=$(matches '^deploy/podman/images/postgres/' && echo true || echo false)
|
||
CH_MIGRATIONS=$(matches '^backend/migrations/' && echo true || echo false)
|
||
fi
|
||
|
||
echo
|
||
echo "变更检测:"
|
||
printf " %-20s %s\n" "backend image:" "$CH_BACKEND"
|
||
printf " %-20s %s\n" "frontend image:" "$CH_FRONTEND"
|
||
printf " %-20s %s\n" "postgres image:" "$CH_PG_IMAGE"
|
||
printf " %-20s %s\n" "quadlet files:" "$CH_QUADLET"
|
||
printf " %-20s %s\n" "migrations:" "$CH_MIGRATIONS"
|
||
|
||
# 4. 重建镜像
|
||
if [ "$CH_PG_IMAGE" = "true" ]; then
|
||
step "重建 postgres 镜像"
|
||
podman build -t localhost/datahub-postgres:latest \
|
||
-f deploy/podman/images/postgres/Dockerfile .
|
||
fi
|
||
|
||
if [ "$CH_BACKEND" = "true" ]; then
|
||
step "重建 backend 镜像"
|
||
podman build -t localhost/datahub-backend:latest \
|
||
-f backend/Dockerfile backend/
|
||
fi
|
||
|
||
if [ "$CH_FRONTEND" = "true" ]; then
|
||
step "重建 frontend 镜像"
|
||
podman build -t localhost/datahub-frontend:latest \
|
||
-f deploy/podman/images/frontend/Dockerfile .
|
||
fi
|
||
|
||
# 5. 同步 Quadlet(任何 quadlet 改动或强制时)
|
||
if [ "$CH_QUADLET" = "true" ] || [ "$FORCE_REBUILD" = true ]; then
|
||
step "同步 Quadlet 单元"
|
||
cp deploy/podman/quadlet/* "$QUADLET_DIR/"
|
||
systemctl --user daemon-reload
|
||
ok "Quadlet 已更新"
|
||
fi
|
||
|
||
# 6. 滚动重启受影响的服务
|
||
step "重启受影响的服务"
|
||
restart_svc() {
|
||
local svc=$1
|
||
echo " 重启 $svc.service"
|
||
systemctl --user restart "$svc.service"
|
||
sleep 2
|
||
if ! systemctl --user is-active --quiet "$svc.service"; then
|
||
err "$svc 重启失败"
|
||
journalctl --user -u "$svc.service" -n 40 --no-pager
|
||
exit 1
|
||
fi
|
||
}
|
||
|
||
[ "$CH_PG_IMAGE" = "true" ] && restart_svc datahub-postgres
|
||
[ "$CH_BACKEND" = "true" ] && restart_svc datahub-backend
|
||
[ "$CH_FRONTEND" = "true" ] && restart_svc datahub-frontend
|
||
|
||
# Quadlet 改了但镜像没改时,仍需重启对应服务
|
||
if [ "$CH_QUADLET" = "true" ]; then
|
||
DIFF_Q=$(git diff --name-only "$OLD_HEAD" "$NEW_HEAD" -- deploy/podman/quadlet/ 2>/dev/null || true)
|
||
[ "$CH_PG_IMAGE" = "false" ] && echo "$DIFF_Q" | grep -q "datahub-postgres" && restart_svc datahub-postgres
|
||
[ "$CH_BACKEND" = "false" ] && echo "$DIFF_Q" | grep -q "datahub-backend" && restart_svc datahub-backend
|
||
[ "$CH_FRONTEND" = "false" ] && echo "$DIFF_Q" | grep -q "datahub-frontend" && restart_svc datahub-frontend
|
||
echo "$DIFF_Q" | grep -q "datahub-rabbitmq" && restart_svc datahub-rabbitmq
|
||
fi
|
||
|
||
# 7. 迁移提示
|
||
if [ "$CH_MIGRATIONS" = "true" ] && [ "$SKIP_MIGRATE" = false ]; then
|
||
echo
|
||
warn "检测到新迁移文件:"
|
||
git diff --name-only "$OLD_HEAD" "$NEW_HEAD" -- backend/migrations/ | sed 's/^/ /'
|
||
read -rp "立即执行迁移?(Y/n): " ans
|
||
ans="${ans,,}"
|
||
if [[ -z "$ans" || "$ans" == "y" ]]; then
|
||
podman exec -it datahub-backend php bin/hyperf.php migrate
|
||
ok "迁移完成"
|
||
else
|
||
warn "跳过。后续可手动执行:podman exec -it datahub-backend php bin/hyperf.php migrate"
|
||
fi
|
||
elif [ "$CH_MIGRATIONS" = "true" ]; then
|
||
warn "检测到新迁移但已 --skip-migrate,请手动执行"
|
||
fi
|
||
|
||
echo
|
||
ok "更新完成"
|
||
echo " $OLD_HEAD"
|
||
echo " → $NEW_HEAD"
|