Files
blog/scripts/fetch_snapshots.sh
T

73 lines
3.4 KiB
Bash
Raw Normal View History

#!/usr/bin/env bash
# =============================================================================
# 构建期数据快照 —— 把「模板渲染时必须用、但只能从远端拿」的数据先 curl 成本地文件
# =============================================================================
# 为什么必须这么做(2026-10-04 实战教训):
# footer.html 原先用 resources.GetRemote 拉 /api/links 与 /api/feeds。Hugo 的
# GetRemote 是**在模板渲染过程中同步发请求**的,而 footer 每个页面都要走一遍。
# 构建节点(国内)到 api.200181.xyz(Cloudflare)一旦抖动:
# WARN Links API fetch failed: dial tcp 104.21.58.236:443: i/o timeout
# WARN Links API fetch failed: ... connection reset by peer
# Artalk 无关,但这两个拉取会一直重试 → 撞穿 Hugo 的 `partial` 30 秒超时 →
# ERROR render of "home" failed: partial "footer.html" timed out after 30s
# Error: error building site → exit code: 1
# 整站构建失败、站点不更新(实测白等 14.5 分钟)。
#
# 改成「stage 里 curl 一次 + 模板只读本地文件」后:
# 网络问题最多让某个快照变旧/为空(模板 with 判空 → 渲染空值),
# **永远不会再让构建挂掉**。命中失败时一律删文件,绝不留半截内容。
#
# 在流水线里由 .cnb.yml 的「Hugo 构建」stage 调用;本地预览想拿到同款数据
# 也可以直接跑:bash scripts/fetch_snapshots.sh
#
# 产物(均在 .gitignore 里,不入库):
# data/artalk_conf.json 评论 /conf(首屏省一跳跨境往返,见 partials/artalk.html)
# data/friend_links.json 友链 → window.friendLinks(评论区「友链」徽章)
# data/friend_feeds.json 友圈 → window.friendFeeds(评论区「友圈」徽章)
# =============================================================================
set -u
BASE="${RSSAPI_BASE:-https://api.200181.xyz}"
BASE="${BASE%/}"
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
DATA_DIR="$ROOT/data"
mkdir -p "$DATA_DIR"
# JSON 合法性校验:python3 不一定有(本机 Windows 可能没有),没有就跳过校验
validate_json() {
command -v python3 >/dev/null 2>&1 || return 0
python3 -c 'import json,sys;json.load(open(sys.argv[1],encoding="utf-8"))' "$1" 2>/dev/null
}
# snap <输出文件名> <URL>
# 成功:原子替换(先写 .tmp 再 mv),并打印字节数
# 失败:删除目标文件(含 .tmp),返回非 0 —— 但本脚本最后统一 exit 0,
# 因为「快照拿不到」是可接受的降级,不该阻断构建。
snap() {
local name="$1" url="$2" out tmp ok=1
out="$DATA_DIR/$name"
tmp="$out.tmp"
if curl -fsS --max-time 30 --retry 2 --retry-delay 2 --retry-connrefused \
-H 'User-Agent: hugo-build-snapshot' "$url" -o "$tmp" 2>/dev/null; then
if [ -s "$tmp" ] && validate_json "$tmp"; then
mv -f "$tmp" "$out"
echo "✅ $name 就绪 $(wc -c < "$out" | tr -d ' ') 字节"
return 0
fi
echo "⚠️ $name 内容校验失败(空文件或非法 JSON)"
else
echo "⚠️ $name 拉取失败:$url"
fi
rm -f "$tmp" "$out"
return 1
}
echo "── 构建期快照(源:$BASE)──"
snap artalk_conf.json "$BASE/api/v2/conf" || true
snap friend_links.json "$BASE/api/links?all=1" || true
snap friend_feeds.json "$BASE/api/feeds" || true
exit 0