feat(upstream): 上游更新检查——定期比上游、落后了推企业微信
Deploy VitePress site to Pages / build (push) Canceled after 0s
Deploy VitePress site to Pages / Deploy (push) Canceled after 0s

本仓库在上游 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 用的还是旧镜像。
This commit is contained in:
2026-10-10 09:17:06 +08:00
parent 44cbe8e2aa
commit e348de48d3
15 changed files with 1183 additions and 6 deletions
+52 -1
View File
@@ -297,7 +297,7 @@ set MC_PASSWORD=我的新密码 # Windows cmd
| 位置 | 范围 | 内容 |
|---|---|---|
| 左侧导航「设置」 | **按平台** | 登录 Cookie、采集策略、代理 |
| 右上角「系统设置」 | **全局** | 通知、活跃时段、账号安全 |
| 右上角「系统设置」 | **全局** | 通知、活跃时段、上游更新、账号安全 |
**这不是随便分的**:企业微信只有一个群、调度器只有一套时段规则、密码只有一份 ——
把它们放进"小红书专属"的页面里,会让人以为它们是按平台存的。
@@ -308,6 +308,54 @@ set MC_PASSWORD=我的新密码 # Windows cmd
---
## 二·十一、上游更新检查
本仓库在 [NanmiCoder/MediaCrawler](https://github.com/NanmiCoder/MediaCrawler) 之上加了一整层
(监控 / 鉴权 / 多平台面板),差异管理与合并流程在根目录 `UPSTREAM.md` 里。但那份流程有个
隐含前提:**得有人知道上游动了**。部署脚本只从我们自己的 Gitea `git pull`,上游的提交不主动
去 fetch 就永远看不见 —— 拖着不合并的代价是复利的,越久越难合。
这一项就是替你定时去 fetch 的:按间隔(默认每天一次)拉一次上游,算出「当前部署落后几个
提交」,有更新就推一条企业微信,并把结果与提交列表显示在**右上角「系统设置」→「上游更新」**。
### 配置
| 项 | 默认 | 说明 |
|---|---|---|
| 检查上游仓库更新 | **关** | 总开关。默认关:它要联网 fetch,且需要容器里有 git(见下) |
| 上游检查间隔(分钟) | 1440 | 每天一次。最小 30 分钟 |
| 上游仓库地址 | GitHub 上游 | 国内直连 GitHub 不稳时改成 gitcode 镜像,见 `UPSTREAM.md` |
| 上游分支 | `main` | |
| 上游有更新时推送通知 | 开 | 只在出现**此前没推过**的提交时发一条,同一个更新不会反复推 |
### 几个刻意的行为
- **只读,不写工作区**:只 `git fetch <地址> <分支>` 到 `FETCH_HEAD` —— 不建 remote、不写
`refs/remotes`、不碰索引与工作区。所以它不会打断正在跑的采集,也不会和 `./deploy.sh`
的 `git pull` 抢锁。
- **不受活跃时段限制**:活跃时段是给采集定的(避免半夜去抓平台)。检查只是 fetch 一个公开
仓库,半夜跑反而更合适。
- **失败也是一种结果**:上游不通(尤其直连 GitHub)很常见。界面会显示失败原因与上次检查
时间,失败不推送,也**不会**因此改变下一次检查的时间 —— 每个间隔重试一次,而不是每个
调度 tick(20 秒)都去撞一次。
- **同一个更新只推一次**:推送状态记的是上游 tip。推过之后,上下游没动就不会再推;上游又
有新提交(tip 变了)时会再推一条。
- **「立即检查」不发通知**:点这个按钮的人正看着结果,没必要再给自己推一条群消息。那次
检查只写结果,没推的那批提交留给下一次定时检查推。
### 部署前提:镜像里要有 git
`python:3.11-slim` 不带 git,`Dockerfile` 里已显式安装。**因此这次更新需要重建镜像**:
```bash
docker compose build && ./deploy.sh
```
`./deploy.sh` 只重建前端,不会重建镜像。漏了这步的话,检查会报「未找到 git 命令」——
界面上看得见,不会静默。
---
## 三、必须知道的限制
### 1. 「新增评论」是近似值 —— 最重要的一条
@@ -459,6 +507,9 @@ GET /api/monitor/webhook 通知配置状态(**只返回打码
POST /api/monitor/webhook 保存 Webhook 地址
DELETE /api/monitor/webhook 删除 Webhook
POST /api/monitor/webhook/test 发送测试消息
GET /api/monitor/upstream 最近一次上游检查的缓存结果(没查过返回 {})
POST /api/monitor/upstream/check 立刻检查一次(等 fetch 跑完才返回,**不发通知**)
```
> `task_id` 用**重复参数**而非逗号拼接(`?task_id=1&task_id=2`);不传表示统计全部任务。