863e49e518
Unify upgrade-agent with install.sh via agent_deploy; auto-sync Git web/app after Docker upgrade to prevent vite hash drift; extend prod_probe for Beijing TZ checks. Co-authored-by: Cursor <cursoragent@cursor.com>
88 lines
3.0 KiB
Bash
88 lines
3.0 KiB
Bash
#!/usr/bin/env bash
|
|
# Sync Git-tracked web/app into the running Nexus Docker container.
|
|
#
|
|
# Root cause: Dockerfile.prod runs vite build inside the image; Docker layer cache
|
|
# can produce asset hashes that differ from committed web/app on the host.
|
|
#
|
|
# Usage (on production host after git pull / upgrade):
|
|
# NEXUS_ROOT=/opt/nexus bash deploy/sync_webapp_to_container.sh
|
|
#
|
|
# Called automatically from deploy/nexus-1panel.sh cmd_upgrade and deploy-production.sh.
|
|
set -euo pipefail
|
|
|
|
NEXUS_ROOT="${NEXUS_ROOT:-/opt/nexus}"
|
|
CONTAINER="${NEXUS_CONTAINER:-}"
|
|
NEXUS_PUBLISH_PORT="${NEXUS_PUBLISH_PORT:-8600}"
|
|
|
|
info() { echo -e "\033[0;32m[INFO]\033[0m $*"; }
|
|
warn() { echo -e "\033[1;33m[WARN]\033[0m $*"; }
|
|
error() { echo -e "\033[0;31m[ERROR]\033[0m $*" >&2; }
|
|
|
|
docker_cmd() {
|
|
if docker "$@" 2>/dev/null; then return 0; fi
|
|
sudo docker "$@" 2>/dev/null
|
|
}
|
|
|
|
resolve_container() {
|
|
if [[ -n "$CONTAINER" ]]; then
|
|
return 0
|
|
fi
|
|
CONTAINER="$(docker_cmd ps --format '{{.Names}}' | grep -E 'nexus-prod-nexus|nexus-nexus-1' | head -1 || true)"
|
|
if [[ -z "$CONTAINER" ]]; then
|
|
error "未找到运行中的 Nexus 容器(可设 NEXUS_CONTAINER=名称)"
|
|
exit 1
|
|
fi
|
|
info "容器: $CONTAINER"
|
|
}
|
|
|
|
verify_entry_bundle() {
|
|
local html bundle_path code
|
|
html="$(curl -sf "http://127.0.0.1:${NEXUS_PUBLISH_PORT}/app/" 2>/dev/null || true)"
|
|
bundle_path="$(printf '%s' "$html" | sed -n 's/.*src="\(\/app\/assets\/index-[^"]*\.js\)".*/\1/p' | head -1)"
|
|
if [[ -z "$bundle_path" ]]; then
|
|
error "/app/ index.html 未解析到主 bundle"
|
|
exit 1
|
|
fi
|
|
code="$(curl -s -o /dev/null -w '%{http_code}' "http://127.0.0.1:${NEXUS_PUBLISH_PORT}${bundle_path}" 2>/dev/null || echo 000)"
|
|
if [[ "$code" != "200" ]]; then
|
|
error "主 bundle ${bundle_path} → HTTP ${code}"
|
|
exit 1
|
|
fi
|
|
info "入口校验 OK: ${bundle_path} → HTTP 200"
|
|
}
|
|
|
|
main() {
|
|
local app="${NEXUS_ROOT}/web/app"
|
|
if [[ ! -f "${app}/index.html" ]]; then
|
|
error "缺少 ${app}/index.html,请先 git pull"
|
|
exit 1
|
|
fi
|
|
if [[ ! -d "${app}/assets" ]]; then
|
|
error "缺少 ${app}/assets"
|
|
exit 1
|
|
fi
|
|
|
|
resolve_container
|
|
|
|
info "同步 web/app → 容器 /app/web/app ..."
|
|
docker_cmd exec "$CONTAINER" rm -rf /app/web/app/assets
|
|
docker_cmd exec "$CONTAINER" mkdir -p /app/web/app
|
|
docker_cmd cp "${app}/index.html" "${CONTAINER}:/app/web/app/index.html"
|
|
docker_cmd cp "${app}/assets" "${CONTAINER}:/app/web/app/assets"
|
|
|
|
if [[ -f "${app}/favicon.ico" ]]; then
|
|
docker_cmd cp "${app}/favicon.ico" "${CONTAINER}:/app/web/app/favicon.ico" 2>/dev/null || true
|
|
fi
|
|
|
|
if [[ -x "${NEXUS_ROOT}/deploy/prune_frontend_assets.py" ]]; then
|
|
info "容器内 prune 未引用 assets(可选)..."
|
|
docker_cmd exec "$CONTAINER" python3 /app/deploy/prune_frontend_assets.py --dry-run 2>/dev/null || \
|
|
warn "容器内 prune 跳过(脚本或路径不可用)"
|
|
fi
|
|
|
|
verify_entry_bundle
|
|
info "web/app 同步完成"
|
|
}
|
|
|
|
main "$@"
|