内容
# github-watcher
[](https://github.com/IanCou/github-watcher/actions/workflows/ci.yml)
[](https://github.com/IanCou/github-watcher/actions/workflows/codeql.yml)
[](LICENSE)
[](https://github.com/IanCou/github-watcher/pkgs/container/github-watcher)
轮询 **任意** GitHub 仓库的 **提交记录或问题**,**过滤** 消息 / 作者 / 更改文件 /
差异内容,并通过 ntfy、Discord、Slack、Telegram、电子邮件等任意 [Apprise](https://github.com/caronc/apprise) 支持的渠道接收 **通知**。
为你 **不拥有** 的仓库(Webhook 和 GitHub Actions 不可用的情况)而设计:它通过 ETag 条件请求高效地轮询公共 REST API,因此空闲轮询不会消耗你的速率限制。
驱动它的四种方式,均共享同一个后端:
- 🖥️ **Web UI** - 管理监视/通道,浏览匹配历史,查看实时状态
- 🔌 **REST API** - OpenAPI 文档,位于 `/docs`
- ⌨️ **CLI** - `github-watcher watch add …`
- 🤖 **MCP 服务器** - 允许代理(Claude 等)直接管理和查询
> 它存在的原因:通知工具假设你控制仓库。对于第三方仓库 - 例如,监视 [SimplifyJobs/Summer2026-Internships](https://github.com/SimplifyJobs/Summer2026-Internships)
> 以获取 **Google** 发布 - 轮询 + 内容过滤是唯一的途径。本项目对此进行了泛化。
---
## 快速开始(Docker)
```sh
cp .env.example .env # 填写你实际使用的令牌
docker compose up -d
open http://localhost:8000 # UI + API 文档位于 /docs
```
从配置文件中导入种子数据(可选):
```sh
docker compose exec github-watcher github-watcher config import /app/config.yml
```
## 过滤器工作原理
监视器最多有四个过滤器类别。提交记录仅在通过 **所有** 配置的类别(AND)时才会通知。在一个类别中,它必须匹配 `include`(如果有)和不匹配 `exclude`。
| 类别 | 匹配对象 | 模式类型 | 需要差异获取? |
| --------- | ------------------------ | ------------ | ----------------- |
| `message` | 提交消息 | 正则表达式 | 否 |
| `author` | 作者姓名 + 电子邮件 | 子字符串 | 否 |
| `files` | 更改的文件路径 | 通配符(`**`) | 是 |
| `diff` | 添加/删除的差异行 | 正则表达式 | 是 |
仅使用 `message`/`author` 的监视器会消耗 **一次** API 调用。`files`/`diff` 过滤器会获取每个新提交记录的差异(需选择开启)。匹配的关键词存储在每次匹配中,可用于你的通知模板。
### 提交记录或问题
监视器有一个 `kind`: **`commits`** (默认)或 **`issues`** 。问题监视器会轮询仓库的新问题(不包括拉取请求);对于它们,`message` 匹配问题 **标题 + 正文**,`author` 匹配开启者 - `files`/`diff` 仅限提交记录。模板公开一个与种类无关的 `{{ item.title/author/ref/url }}`,以及 `{{ commit.* }}` / `{{ issue.* }}`。
```yaml
watches:
- name: new-internship-issues
repo: SimplifyJobs/Summer2026-Internships
kind: issues
channels: [ntfy-main]
filters:
message: { include: ['(?i)公司名称\s*\n+\s*(amazon|google|meta)'] }
```
### “Google 实习生” 示例
> _仅当实习生列表中添加了 Google 发布时通知我。_
```yaml
watches:
- name: simplify-google-internships
repo: SimplifyJobs/Summer2026-Internships
branch: dev
interval: 60
channels: [ntfy-main, discord-jobs]
filters:
files: { include: ["**/listings.json"] } # 忽略 README/badge 噪音
diff: { include: ['(?i)\bgoogle\b'] } # 仅当添加/删除 "google" 时
template:
title: "{{ repo }} 中的新匹配:{{ matched_keywords | join(', ') }}"
body: "{{ commit.message_first_line }} - {{ commit.author }} · {{ commit.short_sha }}"
```
更多信息请参见 [`config.example.yml`](config.example.yml)。
## 通道
通道是 [Apprise URL](https://github.com/caronc/apprise/wiki)。使用 `${VAR}` 占位符可以让密钥保留在环境中,而不是数据库中:
```
ntfy://${NTFY_TOKEN}@ntfy.example.net/commits
discord://${DISCORD_WEBHOOK_ID}/${DISCORD_WEBHOOK_TOKEN}
```
在 UI、CLI (`github-watcher channel test ntfy-main`) 或 MCP 上测试其中一个。
## CLI
```sh
github-watcher channel add ntfy-main 'ntfy://${NTFY_TOKEN}@ntfy.example.net/commits'
github-watcher watch add -f watch.yml # 一个监视器作为 YAML/JSON
github-watcher watch list
github-watcher watch dry-run 1 # 评估最新的提交记录,不发送通知
github-watcher watch run 1 # 立即轮询一次
github-watcher matches --limit 20
github-watcher status
github-watcher config export -o config.yml
github-watcher serve # API + 轮询器(容器运行的内容)
```
## MCP(代理访问)
运行 stdio 服务器:
```sh
python -m github_watcher.mcp_server
```
使用 MCP 客户端(例如 Claude Code)注册:
```json
{
"mcpServers": {
"github-watcher": {
"command": "python",
"args": ["-m", "github_watcher.mcp_server"]
}
}
}
```
工具:`list_watches`、`add_watch`、`update_watch`、`delete_watch`、`list_channels`、`add_channel`、
`test_channel`、`get_matches`、`run_now`、`dry_run`、`get_status`.
## 可观察性
- `GET /healthz` - 存活检测(用于 Docker 健康检查)
- `GET /metrics` - Prometheus:轮询、提交记录、匹配、通知、GitHub 速率限制、错误 - 全部带有标签。
## 开发
```sh
# 后端
cd backend && python3.12 -m venv .venv && . .venv/bin/activate
pip install -e ".[dev]"
pytest -q && ruff check .
DISABLE_POLLER=1 uvicorn github_watcher.api.app:app --reload # 仅限 API
# 前端(代理 /api 至 :8000)
cd frontend && npm install && npm run dev
```
## 架构
一个具有共享 **服务层** 的 Python 服务,支持每个接口,因此 UI、CLI、MCP 和后台轮询器永远不会漂移。**SQLite** 是事实的来源;YAML 导入/导出用于可移植性。参见源代码中的 [文档](backend/github_watcher/) - `services.py` 是所有业务逻辑的入口点,`core/filters.py` 是过滤器引擎,`core/github.py` 是 ETag 感知客户端。
## 设计与决策
- [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) - 模块映射、核心轮询→过滤→通知管道,以及如何扩展它。
- [docs/decisions/](docs/decisions/index.md) - 架构决策记录:**为什么** 采用轮询、ETag、共享服务层、SQLite、Apprise、提交记录+问题、MCP,以及 CI/供应链设置。
- [docs/STORY.md](docs/STORY.md) - 项目发展历程。
- [CHANGELOG.md](CHANGELOG.md) - 发布历史。
## 许可证
MIT - 参见 [LICENSE](LICENSE)。