forked from bai/curriculum-project-hub
fix(hub): 修复 Hub 部署脚本失败处理
This commit is contained in:
@@ -24,3 +24,6 @@ AssertPathExists=/usr/bin/bwrap
|
|||||||
# bwrap user-namespace setup. The OS-level sandbox (ADR-0018) is the hard
|
# bwrap user-namespace setup. The OS-level sandbox (ADR-0018) is the hard
|
||||||
# boundary; systemd hardening is kept minimal to avoid interfering with it.
|
# boundary; systemd hardening is kept minimal to avoid interfering with it.
|
||||||
NoNewPrivileges=true
|
NoNewPrivileges=true
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
|||||||
@@ -7,9 +7,11 @@
|
|||||||
# PLATFORM_DEPLOY_USER optional, defaults to deploy
|
# PLATFORM_DEPLOY_USER optional, defaults to deploy
|
||||||
# PLATFORM_DEPLOY_PORT optional, defaults to 22
|
# PLATFORM_DEPLOY_PORT optional, defaults to 22
|
||||||
# PLATFORM_DEPLOY_BASE optional, defaults to /srv/curriculum-project-hub
|
# PLATFORM_DEPLOY_BASE optional, defaults to /srv/curriculum-project-hub
|
||||||
|
# PLATFORM_DEPLOY_HEALTH_URL optional, defaults to http://127.0.0.1:8788/api/healthz
|
||||||
# The target host must have Node.js, npm, rsync, PostgreSQL, systemd, bubblewrap
|
# The target host must have Node.js, npm, rsync, PostgreSQL, systemd, bubblewrap
|
||||||
# (`bwrap`, for the ADR-0018 agent sandbox), and a writable $PLATFORM_DEPLOY_BASE.
|
# (`bwrap`, for the ADR-0018 agent sandbox), and a writable $PLATFORM_DEPLOY_BASE.
|
||||||
# Use a dedicated `deploy` user that has passwordless sudo for:
|
# Use a dedicated `deploy` user that has passwordless sudo for systemctl and
|
||||||
|
# writing /etc/systemd/system/cph-hub.service through deploy/install_service.sh.
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
HOST="${PLATFORM_DEPLOY_HOST:?PLATFORM_DEPLOY_HOST required}"
|
HOST="${PLATFORM_DEPLOY_HOST:?PLATFORM_DEPLOY_HOST required}"
|
||||||
@@ -17,12 +19,15 @@ SSH_KEY="${PLATFORM_DEPLOY_SSH_KEY:?PLATFORM_DEPLOY_SSH_KEY required}"
|
|||||||
DEPLOY_USER="${PLATFORM_DEPLOY_USER:-deploy}"
|
DEPLOY_USER="${PLATFORM_DEPLOY_USER:-deploy}"
|
||||||
PORT="${PLATFORM_DEPLOY_PORT:-22}"
|
PORT="${PLATFORM_DEPLOY_PORT:-22}"
|
||||||
BASE="${PLATFORM_DEPLOY_BASE:-/srv/curriculum-project-hub}"
|
BASE="${PLATFORM_DEPLOY_BASE:-/srv/curriculum-project-hub}"
|
||||||
|
HEALTH_URL="${PLATFORM_DEPLOY_HEALTH_URL:-http://127.0.0.1:8788/api/healthz}"
|
||||||
HUB_DIR="$BASE/hub"
|
HUB_DIR="$BASE/hub"
|
||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||||
|
|
||||||
SSH_OPTS=(-i "$SSH_KEY" -p "$PORT" -o StrictHostKeyChecking=accept-new)
|
SSH_OPTS=(-i "$SSH_KEY" -p "$PORT" -o StrictHostKeyChecking=accept-new)
|
||||||
|
|
||||||
|
ssh "${SSH_OPTS[@]}" "$DEPLOY_USER@$HOST" "mkdir -p '$HUB_DIR'"
|
||||||
|
|
||||||
# 1. Rsync the hub/ directory (exclude node_modules/dist, they rebuild on host).
|
# 1. Rsync the hub/ directory (exclude node_modules/dist, they rebuild on host).
|
||||||
rsync -az --delete \
|
rsync -az --delete \
|
||||||
--exclude node_modules --exclude dist --exclude .env \
|
--exclude node_modules --exclude dist --exclude .env \
|
||||||
@@ -34,11 +39,23 @@ ssh "${SSH_OPTS[@]}" "$DEPLOY_USER@$HOST" "cd '$HUB_DIR' && npm ci && npm run bu
|
|||||||
|
|
||||||
# 3. Ensure the service is installed (idempotent), then restart.
|
# 3. Ensure the service is installed (idempotent), then restart.
|
||||||
ssh "${SSH_OPTS[@]}" "$DEPLOY_USER@$HOST" "
|
ssh "${SSH_OPTS[@]}" "$DEPLOY_USER@$HOST" "
|
||||||
BASE='$BASE' HUB_DIR='$HUB_DIR' bash '$HUB_DIR/deploy/install_service.sh' || true
|
set -euo pipefail
|
||||||
sudo systemctl restart cph-hub.service
|
if [ \"\$(id -u)\" = \"0\" ]; then
|
||||||
sleep 2
|
BASE='$BASE' HUB_DIR='$HUB_DIR' bash '$HUB_DIR/deploy/install_service.sh'
|
||||||
sudo systemctl is-active --quiet cph-hub.service || { echo 'service failed to start'; exit 1; }
|
systemctl restart cph-hub.service
|
||||||
curl -sf http://127.0.0.1:8788/api/healthz || { echo 'healthz failed'; exit 1; }
|
systemctl is-active --quiet cph-hub.service
|
||||||
|
else
|
||||||
|
sudo -n BASE='$BASE' HUB_DIR='$HUB_DIR' bash '$HUB_DIR/deploy/install_service.sh'
|
||||||
|
sudo -n systemctl restart cph-hub.service
|
||||||
|
sudo -n systemctl is-active --quiet cph-hub.service
|
||||||
|
fi
|
||||||
|
for attempt in \$(seq 1 30); do
|
||||||
|
if curl --fail --silent '$HEALTH_URL' >/dev/null 2>&1; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
curl --fail --silent --show-error '$HEALTH_URL' >/dev/null
|
||||||
"
|
"
|
||||||
|
|
||||||
echo "Deployed cph-hub to $HOST ($HUB_DIR)"
|
echo "Deployed cph-hub to $HOST ($HUB_DIR)"
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ HOST="${HOST:-127.0.0.1}"
|
|||||||
PORT="${PORT:-8788}"
|
PORT="${PORT:-8788}"
|
||||||
ENV_FILE="${ENV_FILE:-$BASE/.secrets/platform.env}"
|
ENV_FILE="${ENV_FILE:-$BASE/.secrets/platform.env}"
|
||||||
NODE_BIN="${NODE_BIN:-$(command -v node || true)}"
|
NODE_BIN="${NODE_BIN:-$(command -v node || true)}"
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
|
||||||
if [ -z "$NODE_BIN" ]; then
|
if [ -z "$NODE_BIN" ]; then
|
||||||
echo "node must be on PATH, or set NODE_BIN." >&2
|
echo "node must be on PATH, or set NODE_BIN." >&2
|
||||||
@@ -29,6 +30,10 @@ if [ ! -f "$HUB_DIR/dist/server.js" ]; then
|
|||||||
echo "build missing: run 'npm ci && npm run build' in $HUB_DIR first." >&2
|
echo "build missing: run 'npm ci && npm run build' in $HUB_DIR first." >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
if [ ! -f "$SCRIPT_DIR/cph-hub.service" ]; then
|
||||||
|
echo "service template missing: $SCRIPT_DIR/cph-hub.service" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
# Seed the env file if absent. Secrets stay on the server, never in the repo.
|
# Seed the env file if absent. Secrets stay on the server, never in the repo.
|
||||||
if [ ! -f "$ENV_FILE" ]; then
|
if [ ! -f "$ENV_FILE" ]; then
|
||||||
@@ -47,18 +52,23 @@ FEISHU_BOT_OPEN_ID=
|
|||||||
PORT=$PORT
|
PORT=$PORT
|
||||||
HOST=$HOST
|
HOST=$HOST
|
||||||
EOF
|
EOF
|
||||||
|
chmod 0600 "$ENV_FILE"
|
||||||
echo "Seeded $ENV_FILE — edit it to fill in ANTHROPIC_AUTH_TOKEN and Feishu creds, then re-run."
|
echo "Seeded $ENV_FILE — edit it to fill in ANTHROPIC_AUTH_TOKEN and Feishu creds, then re-run."
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Render the unit with concrete paths.
|
# Render the unit with concrete paths.
|
||||||
UNIT=/etc/systemd/system/cph-hub.service
|
UNIT=/etc/systemd/system/cph-hub.service
|
||||||
|
TMP_UNIT="$(mktemp)"
|
||||||
sed \
|
sed \
|
||||||
-e "s|__SERVICE_USER__|$SERVICE_USER|g" \
|
-e "s|__SERVICE_USER__|$SERVICE_USER|g" \
|
||||||
-e "s|__HUB_DIR__|$HUB_DIR|g" \
|
-e "s|__HUB_DIR__|$HUB_DIR|g" \
|
||||||
-e "s|__BASE_DIR__|$BASE|g" \
|
-e "s|__BASE_DIR__|$BASE|g" \
|
||||||
-e "s|__ENV_FILE__|$ENV_FILE|g" \
|
-e "s|__ENV_FILE__|$ENV_FILE|g" \
|
||||||
-e "s|__NODE_BIN__|$NODE_BIN|g" \
|
-e "s|__NODE_BIN__|$NODE_BIN|g" \
|
||||||
|
"$SCRIPT_DIR/cph-hub.service" >"$TMP_UNIT"
|
||||||
|
install -m 0644 "$TMP_UNIT" "$UNIT"
|
||||||
|
rm -f "$TMP_UNIT"
|
||||||
|
|
||||||
systemctl daemon-reload
|
systemctl daemon-reload
|
||||||
systemctl enable cph-hub.service
|
systemctl enable cph-hub.service
|
||||||
|
|||||||
Reference in New Issue
Block a user