personal-homepage/scripts/deploy-homepage.sh

180 lines
4.5 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env bash
set -Eeuo pipefail
# 日志源目录:由日志生产服务写入
# 默认值:/home/basil/bot/data/git-summary
LOG_SOURCE_DIR="${LOG_SOURCE_DIR:-/home/basil/bot/data/git-summary}"
# 静态资源同步清单
# 默认值:$SITE_DIR/src/content/static-assets/index.json
STATIC_ASSET_MANIFEST="${STATIC_ASSET_MANIFEST:-src/content/static-assets/index.json}"
# 个人主页仓库目录
# 默认值:/home/basil/source/personal-homepage
SITE_DIR="${SITE_DIR:-/home/basil/source/personal-homepage}"
# 日志目标目录:复制到 homepage 仓库内
# 默认值:$SITE_DIR/src/content/logs
LOG_TARGET_DIR="${LOG_TARGET_DIR:-${SITE_DIR}/src/content/logs}"
# Docker Compose 配置与服务名
# 默认 compose 文件:$SITE_DIR/docker-compose.yml
# 默认服务名homepage
DOCKER_COMPOSE_FILE="${DOCKER_COMPOSE_FILE:-${SITE_DIR}/docker-compose.yml}"
DOCKER_SERVICE_NAME="${DOCKER_SERVICE_NAME:-homepage}"
# 是否在同步时删除目标目录中源目录已不存在的文件
# 默认值false
RSYNC_DELETE="${RSYNC_DELETE:-false}"
# 是否先在宿主机执行一次 npm run rebuild
# 默认值true
RUN_LOCAL_REBUILD="${RUN_LOCAL_REBUILD:-true}"
# 是否在 log 同步前先同步静态资源
# 默认值true
RUN_STATIC_ASSET_SYNC="${RUN_STATIC_ASSET_SYNC:-true}"
# 锁文件路径,避免定时任务重入
# 默认值:/tmp/personal-homepage-deploy.lock
LOCK_FILE="${LOCK_FILE:-/tmp/personal-homepage-deploy.lock}"
timestamp() {
date '+%Y-%m-%d %H:%M:%S'
}
log() {
printf '[%s] %s\n' "$(timestamp)" "$*"
}
fail() {
log "ERROR: $*"
exit 1
}
require_command() {
command -v "$1" >/dev/null 2>&1 || fail "缺少命令: $1"
}
is_true() {
case "${1,,}" in
1|true|yes|on) return 0 ;;
*) return 1 ;;
esac
}
sync_logs() {
mkdir -p "$LOG_TARGET_DIR"
if command -v rsync >/dev/null 2>&1; then
local -a rsync_args=(-av)
if is_true "$RSYNC_DELETE"; then
rsync_args+=(--delete)
fi
log "同步日志: $LOG_SOURCE_DIR -> $LOG_TARGET_DIR"
rsync "${rsync_args[@]}" "${LOG_SOURCE_DIR}/" "${LOG_TARGET_DIR}/"
return 0
fi
log "未找到 rsync改用 cp -a 复制日志"
if is_true "$RSYNC_DELETE"; then
find "$LOG_TARGET_DIR" -mindepth 1 -maxdepth 1 -exec rm -rf {} +
fi
cp -a "${LOG_SOURCE_DIR}/." "$LOG_TARGET_DIR/"
}
sync_static_assets() {
log "同步静态资源清单: $STATIC_ASSET_MANIFEST"
(
cd "$SITE_DIR"
STATIC_ASSET_MANIFEST="$STATIC_ASSET_MANIFEST" \
node --env-file-if-exists=.env --experimental-strip-types ./scripts/sync-static-assets.ts
)
}
run_local_rebuild() {
log "开始宿主机构建校验: npm run rebuild"
(
cd "$SITE_DIR"
npm run rebuild
)
}
refresh_docker_service() {
log "刷新 Docker 服务: $DOCKER_SERVICE_NAME"
(
cd "$SITE_DIR"
docker compose -f "$DOCKER_COMPOSE_FILE" up -d --build "$DOCKER_SERVICE_NAME"
)
}
main_impl() {
require_command docker
if is_true "$RUN_STATIC_ASSET_SYNC"; then
require_command node
fi
if is_true "$RUN_LOCAL_REBUILD"; then
require_command npm
fi
docker compose version >/dev/null 2>&1 || fail "当前环境不可用 docker compose"
[[ -d "$LOG_SOURCE_DIR" ]] || fail "日志源目录不存在: $LOG_SOURCE_DIR"
[[ -d "$SITE_DIR" ]] || fail "站点目录不存在: $SITE_DIR"
[[ -f "$DOCKER_COMPOSE_FILE" ]] || fail "docker compose 文件不存在: $DOCKER_COMPOSE_FILE"
log "部署开始"
log "LOG_SOURCE_DIR=$LOG_SOURCE_DIR"
log "LOG_TARGET_DIR=$LOG_TARGET_DIR"
log "SITE_DIR=$SITE_DIR"
log "STATIC_ASSET_MANIFEST=$STATIC_ASSET_MANIFEST"
log "DOCKER_COMPOSE_FILE=$DOCKER_COMPOSE_FILE"
log "DOCKER_SERVICE_NAME=$DOCKER_SERVICE_NAME"
log "RSYNC_DELETE=$RSYNC_DELETE"
log "RUN_STATIC_ASSET_SYNC=$RUN_STATIC_ASSET_SYNC"
log "RUN_LOCAL_REBUILD=$RUN_LOCAL_REBUILD"
log "LOCK_FILE=$LOCK_FILE"
if is_true "$RUN_STATIC_ASSET_SYNC"; then
sync_static_assets
else
log "跳过静态资源同步RUN_STATIC_ASSET_SYNC=false"
fi
sync_logs
if is_true "$RUN_LOCAL_REBUILD"; then
run_local_rebuild
else
log "跳过宿主机 npm run rebuildRUN_LOCAL_REBUILD=false"
fi
refresh_docker_service
log "部署完成"
}
main() {
if ! command -v flock >/dev/null 2>&1; then
log "未找到 flock跳过锁保护"
main_impl "$@"
return 0
fi
mkdir -p "$(dirname "$LOCK_FILE")"
exec 9>"$LOCK_FILE"
if ! flock -n 9; then
fail "已有部署任务在执行中,锁文件: $LOCK_FILE"
fi
log "已获取部署锁: $LOCK_FILE"
main_impl "$@"
}
main "$@"