122 lines
3.0 KiB
Bash
Executable File
122 lines
3.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -Eeuo pipefail
|
|
|
|
# 待发布的构建产物(tar.gz),由 CI 上传到服务器后传入
|
|
DEPLOY_TAR="${DEPLOY_TAR:-}"
|
|
# 静态站点目录(与 Nginx location /panel/ 对齐)
|
|
TARGET_DIR="${TARGET_DIR:-}"
|
|
# 发布标识(通常用 commit sha)
|
|
RELEASE_ID="${RELEASE_ID:-}"
|
|
# 文件归属用户/组
|
|
RUN_USER="${RUN_USER:-}"
|
|
RUN_GROUP="${RUN_GROUP:-}"
|
|
# 备份保留数量
|
|
KEEP_BACKUPS="${KEEP_BACKUPS:-}"
|
|
# 可选:发布后探活地址,例如 http://example.com/panel/
|
|
HEALTHCHECK_URL="${HEALTHCHECK_URL:-}"
|
|
|
|
BACKUP_ROOT="${BACKUP_ROOT:-$(dirname "$TARGET_DIR")/backups}"
|
|
|
|
log() {
|
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"
|
|
}
|
|
|
|
require_env() {
|
|
local name="$1"
|
|
local value="$2"
|
|
if [ -z "$value" ]; then
|
|
echo "missing required env: $name" >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
health_check() {
|
|
if [ -z "$HEALTHCHECK_URL" ]; then
|
|
return 0
|
|
fi
|
|
|
|
if ! command -v curl >/dev/null 2>&1; then
|
|
log "curl 不存在,跳过 HEALTHCHECK_URL 检查"
|
|
return 0
|
|
fi
|
|
|
|
local tries=15
|
|
while [ "$tries" -gt 0 ]; do
|
|
if curl -fsS --max-time 5 "$HEALTHCHECK_URL" >/dev/null; then
|
|
return 0
|
|
fi
|
|
tries=$((tries - 1))
|
|
sleep 2
|
|
done
|
|
|
|
return 1
|
|
}
|
|
|
|
require_env "DEPLOY_TAR" "$DEPLOY_TAR"
|
|
require_env "TARGET_DIR" "$TARGET_DIR"
|
|
require_env "RELEASE_ID" "$RELEASE_ID"
|
|
require_env "RUN_USER" "$RUN_USER"
|
|
require_env "RUN_GROUP" "$RUN_GROUP"
|
|
require_env "KEEP_BACKUPS" "$KEEP_BACKUPS"
|
|
|
|
if [ ! -f "$DEPLOY_TAR" ]; then
|
|
echo "deploy tar not found: $DEPLOY_TAR" >&2
|
|
exit 1
|
|
fi
|
|
|
|
tmp_dir="/tmp/admin-frontend-${RELEASE_ID:0:12}-$$"
|
|
backup_file=""
|
|
|
|
cleanup() {
|
|
rm -rf "$tmp_dir"
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
log "deploy start, release: ${RELEASE_ID}"
|
|
mkdir -p "$tmp_dir" "$TARGET_DIR" "$BACKUP_ROOT"
|
|
|
|
log "extracting artifact"
|
|
tar -xzf "$DEPLOY_TAR" -C "$tmp_dir"
|
|
|
|
if [ ! -f "$tmp_dir/index.html" ]; then
|
|
echo "invalid artifact: index.html not found" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# 发布前备份当前站点,支持快速回滚
|
|
if [ -n "$(ls -A "$TARGET_DIR" 2>/dev/null)" ]; then
|
|
backup_file="$BACKUP_ROOT/admin-frontend.${RELEASE_ID}.tar.gz"
|
|
tar -czf "$backup_file" -C "$TARGET_DIR" .
|
|
log "backup created: $backup_file"
|
|
fi
|
|
|
|
# 覆盖发布:先清空目录再写入新构建
|
|
find "$TARGET_DIR" -mindepth 1 -maxdepth 1 -exec rm -rf {} +
|
|
tar -cf - -C "$tmp_dir" . | tar -xf - -C "$TARGET_DIR"
|
|
chown -R "$RUN_USER:$RUN_GROUP" "$TARGET_DIR" || true
|
|
|
|
if health_check; then
|
|
if [ -n "$HEALTHCHECK_URL" ]; then
|
|
log "health check success: $HEALTHCHECK_URL"
|
|
fi
|
|
else
|
|
log "health check failed, rolling back"
|
|
if [ -n "$backup_file" ] && [ -f "$backup_file" ]; then
|
|
find "$TARGET_DIR" -mindepth 1 -maxdepth 1 -exec rm -rf {} +
|
|
tar -xzf "$backup_file" -C "$TARGET_DIR"
|
|
chown -R "$RUN_USER:$RUN_GROUP" "$TARGET_DIR" || true
|
|
log "rollback done"
|
|
fi
|
|
exit 1
|
|
fi
|
|
|
|
# 清理上传到 /tmp 的临时制品
|
|
if [[ "$DEPLOY_TAR" == /tmp/* ]]; then
|
|
rm -f "$DEPLOY_TAR"
|
|
fi
|
|
|
|
# 清理旧备份,仅保留最近 KEEP_BACKUPS 份
|
|
ls -1t "$BACKUP_ROOT"/admin-frontend.*.tar.gz 2>/dev/null | tail -n +$((KEEP_BACKUPS + 1)) | xargs -r rm -f
|
|
|
|
log "deploy done"
|