Files
kindle-calendar/scripts/publish-calendar-dist.sh
2026-03-21 18:44:12 +08:00

163 lines
3.8 KiB
Bash
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 sh
set -eu
ROOT_DIR="$(CDPATH= cd -- "$(dirname "$0")/.." && pwd)"
CALENDAR_DIR="$ROOT_DIR/calendar"
DIST_DIR="$CALENDAR_DIR/dist"
OUTPUT_DIR=""
INTERVAL_MINUTES=60
RUN_ONCE=false
print_usage() {
cat <<'EOF'
用法:
sh scripts/publish-calendar-dist.sh --output-dir <dir> [选项]
作用:
1. 调用 calendar 现有导出链路生成最新背景图与主题资源
2. 把 calendar/dist 整体发布到指定目录
3. 默认每 60 分钟自动重跑一次;加 --once 只跑一轮
选项:
-o, --output-dir <dir> 发布目标目录,通常是 Web 服务器实际对外提供静态文件的目录
--interval-minutes <n> 自动生成间隔,默认 60 分钟
--once 只生成并发布一轮
-h, --help 查看帮助
示例:
sh scripts/publish-calendar-dist.sh --output-dir /srv/calendar-dashboard --once
sh scripts/publish-calendar-dist.sh --output-dir /srv/calendar-dashboard
EOF
}
log() {
printf '[%s] %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$1"
}
validate_positive_integer() {
value=$1
name=$2
case "$value" in
''|*[!0-9]*)
echo "$name 必须是正整数:$value" >&2
exit 1
;;
esac
if [ "$value" -le 0 ]; then
echo "$name 必须大于 0$value" >&2
exit 1
fi
}
publish_once() {
temp_publish_dir=$(mktemp -d "${TMPDIR:-/tmp}/kindle-dash-publish.XXXXXX")
publish_status=0
log "开始生成 Web 端背景图与主题资源"
(
cd "$CALENDAR_DIR"
npm run export:themes
) || publish_status=$?
if [ "$publish_status" -ne 0 ]; then
rm -rf "$temp_publish_dir"
return "$publish_status"
fi
log "开始发布到目标目录:$OUTPUT_DIR"
mkdir -p "$OUTPUT_DIR"
# 先把本轮导出结果完整复制到临时目录,确认结构无误后再整体 rsync 到目标目录,
# 避免 Web 根目录在导出过程中暴露半成品文件。
rsync -a --delete "$DIST_DIR"/ "$temp_publish_dir"/ || publish_status=$?
if [ "$publish_status" -eq 0 ]; then
rsync -a --delete "$temp_publish_dir"/ "$OUTPUT_DIR"/ || publish_status=$?
fi
rm -rf "$temp_publish_dir"
if [ "$publish_status" -ne 0 ]; then
return "$publish_status"
fi
log "发布完成:$OUTPUT_DIR"
}
sleep_until_next_run() {
interval_seconds=$((INTERVAL_MINUTES * 60))
now_epoch=$(date '+%s')
next_epoch=$(( ((now_epoch / interval_seconds) + 1) * interval_seconds ))
sleep_seconds=$((next_epoch - now_epoch))
if [ "$sleep_seconds" -le 0 ]; then
sleep_seconds=$interval_seconds
fi
log "等待 ${sleep_seconds} 秒后执行下一轮生成"
sleep "$sleep_seconds"
}
while [ "$#" -gt 0 ]; do
case "$1" in
-o|--output-dir)
shift
OUTPUT_DIR=${1:?"missing output dir"}
;;
--interval-minutes)
shift
INTERVAL_MINUTES=${1:?"missing interval minutes"}
;;
--once)
RUN_ONCE=true
;;
-h|--help)
print_usage
exit 0
;;
*)
echo "未知参数: $1" >&2
echo >&2
print_usage >&2
exit 1
;;
esac
shift
done
if [ -z "$OUTPUT_DIR" ]; then
echo "必须通过 --output-dir 指定发布目录。" >&2
echo >&2
print_usage >&2
exit 1
fi
validate_positive_integer "$INTERVAL_MINUTES" "interval-minutes"
# 当前导图链路依赖 macOS 自带的 Swift + WKWebView。
# 如果部署机不是 macOS这一步会失败届时需要单独换成跨平台截图方案。
if [ ! -x /usr/bin/swift ]; then
echo "未找到 /usr/bin/swift当前机器无法使用现有 WebKit 导图链路。" >&2
exit 1
fi
while true; do
if publish_once; then
:
else
status=$?
log "本轮发布失败,退出码:$status"
if [ "$RUN_ONCE" = true ]; then
exit "$status"
fi
fi
if [ "$RUN_ONCE" = true ]; then
break
fi
sleep_until_next_run
done