Files
MediaCrawler/deploy.sh
T
butubb e348de48d3
Deploy VitePress site to Pages / build (push) Canceled after 0s
Deploy VitePress site to Pages / Deploy (push) Canceled after 0s
feat(upstream): 上游更新检查——定期比上游、落后了推企业微信
本仓库在上游 MediaCrawler 之上加了一整层(见 UPSTREAM.md),可合并流程默认
「有人知道上游动了」。而部署是 git pull --ff-only,只从自己的 Gitea 拉——上游的
提交不主动 fetch 就永远看不见。拖着不合并的代价是复利的:越久越难合。

于是把「上游动了没有」变成一条会自己跑、会推企业微信的通知:

* api/monitor/upstream.py:git fetch <url> <branch> 到 FETCH_HEAD,用
  rev-list --count HEAD..FETCH_HEAD 算落后数、FETCH_HEAD..HEAD 算领先数。
  用 git 而非托管商 API,因为只有 git 知道共同祖先在哪——本仓库含有上游没有的
  提交,直接比 tip 会得出错误结论。增量 fetch 只传几个新提交,不会遇到
  UPSTREAM.md 里说的「大包必断」。
* 只 fetch 到 FETCH_HEAD:不配 remote、不写 refs/remotes、不碰索引与工作区,
  所以不打断正在跑的采集,也不和 deploy.sh 的 git pull 抢锁。
* 挂在调度器 tick 上(不是采集,所以不看 is_busy、不受活跃时段限制——定时检查
  放在半夜反而最合适),按 checked_at + 间隔 到期才跑;失败也写 checked_at,
  于是 GitHub 不通时是每间隔重试一次,而不是每个 tick 撞一次墙。
* 同一个 tip 只推一次(记 tip 而不是「推过没」),上游真又动了会再推。
* 两个接口:GET /monitor/upstream 只读缓存;POST /monitor/upstream/check 手动
  查一次且刻意不推通知——点按钮的人正看着结果。
* 默认关闭,间隔默认一天。

Dockerfile 显式装 git(python:slim 不带,而这是唯一的依赖);deploy.sh 顺带补上
一个真 bug 的提示:Dockerfile/requirements.txt 变了只 up -d 用的还是旧镜像。
2026-10-10 09:17:06 +08:00

72 lines
2.9 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
#
# 更新这台机器上的部署。用法:
#
# ./deploy.sh
#
# 为什么需要脚本而不是一句 `git pull && docker compose up -d`:
# 前端产物 api/webui 是 gitignore 的(它由 vite 生成),git pull 带不过来。
# 所以代码更新之后必须在服务器上重建一次前端,否则页面还是旧的。
# 这一步在容器里做,好处是服务器不需要装 Node —— 只有 Docker。
#
# node_modules 和 npm 缓存都留在挂载目录内,重复构建不会重新下载。
set -euo pipefail
cd "$(dirname "$0")"
# 用镜像里的解释器跑,宿主机的 Python 版本无关。
IMAGE=mediacrawler:latest
before=$(git rev-parse HEAD)
git pull --ff-only
after=$(git rev-parse HEAD)
if [ "$before" = "$after" ]; then
echo "== 代码已是最新($after)"
else
echo "== 代码更新 $before -> $after"
git --no-pager log --oneline "$before..$after" | sed 's/^/ /'
fi
# 镜像层(依赖)改动只能靠重建,而这一步不是自动的:Dockerfile 或 requirements.txt 变了,
# 下面那句 `docker compose up -d --force-recreate` 用的是旧镜像,改动根本不会生效。
# 至少要说出来,否则现象是「代码明明更新了,功能却报缺依赖」。
if [ "$before" != "$after" ] && ! git diff --quiet "$before" "$after" -- Dockerfile requirements.txt; then
echo "!! Dockerfile / requirements.txt 有改动,需要重建镜像后重跑本脚本:"
echo " docker compose build"
fi
# 前端重建的两种情况:产物根本不存在(首次部署),或 webui/ 有改动。
if [ ! -f api/webui/index.html ]; then
need_build=1
reason="前端产物不存在"
elif [ "$before" != "$after" ] && ! git diff --quiet "$before" "$after" -- webui/; then
need_build=1
reason="webui/ 有改动"
else
need_build=0
reason=""
fi
if [ "$need_build" = "1" ]; then
echo "== 重建前端($reason)"
# -u 1000:1000 而不是 root:这里产出的文件要留在这个目录里给后面用,
# 以 root 生成的 node_modules 会让下次构建和人工清理都变得别扭。
# HOME 指向挂载目录,这样 npm 的缓存在宿主机上,重建时能复用。
docker run --rm \
-u 1000:1000 \
-w /app/webui \
-v "$PWD:/app" \
-e HOME=/app/webui \
-e npm_config_registry=https://registry.npmmirror.com \
"$IMAGE" sh -c 'npm ci --no-audit --no-fund && npm run build'
else
echo "== 前端无改动,跳过构建"
fi
# --force-recreate,而不是裸的 `up -d`:代码是 bind mount,容器配置和镜像都没变,
# 所以 `up -d` 会判定"无需变更"直接跳过,Python 代码的改动根本不会生效。前端产物是
# 磁盘上的静态文件,能即时生效,这一点很容易掩盖上面那个问题,直到有人改了 .py 才发现。
echo "== 重启容器"
docker compose up -d --force-recreate
docker compose ps