chore: 初始开源发布

iotlcm-bot:独立飞书应用机器人(读取 Worker 终态 Run JSON,渲染并发送全量同步结果卡片)。

- Go module:git.5iot.com/iotlcm/iotlcm-bot → git.5iot.com/iotlcm-public/iotlcm-bot
- 飞书凭据占位:appId/appSecret/chatId → ${FEISHU_APP_ID}/${FEISHU_APP_SECRET}/${FEISHU_CHAT_ID}
- 移除内部资产:CI 触发器
- Dockerfile 改用公共基础镜像(golang:1.25-alpine → scratch)
- README 重写(命令/配置/挂载契约/常见问题),去掉内部环境路径
- 补 Apache-2.0 LICENSE,LF 行尾 + .gitattributes
This commit is contained in:
MiFaZhan
2026-10-22 16:14:24 +08:00
commit 5732bf3384
33 changed files with 2676 additions and 0 deletions
+127
View File
@@ -0,0 +1,127 @@
# iotlcm-bot
独立飞书应用机器人:读取 Worker 终态 Run JSON,渲染并发送全量同步结果卡片。
本服务是 [iotlcm](https://git.5iot.com/iotlcm-public) 物联网卡全生命周期管理平台的配套组件,用于把异步全量同步(卡状态、流量、IMEI 等)的执行结果推送到飞书群。
## 特性
- **零外部依赖**:只依赖 `gopkg.in/yaml.v3`,不需要 Redis、数据库或 Worker HTTP 接口
- **只读归档**:只读挂载 Worker 的归档目录,按 `runId` 去重后发送
- **多类卡片**:全量同步汇总卡、告警卡、供料提醒卡
- **健康自检**:检测归档目录被宿主删除(inode 丢失)这类静默故障并告警
- **单镜像**:`scratch` 基础镜像,非 root 运行
## V1 范围
- 只接受 `version=1` 且包含 `run` 和非空 `rounds` 的归档 JSON
- 不兼容旧版 `rounds=[]` 文件
- 不读取 Redis、Worker HTTP 接口或日志
- 不实现 Replay、事件回调、卡片按钮和错误聚合
## 快速开始
```bash
go mod tidy
go test ./...
```
本地渲染一张卡片(不调用飞书 API):
```bash
go run ./cmd/iotlcm-bot render --file testdata/current-run.json
go run ./cmd/iotlcm-bot render --file testdata/current-run.json --json
```
## 配置
配置文件为 `config.yaml`。**公开版里的飞书凭据是占位符**,真实值请用环境变量或本地覆盖文件注入:
```yaml
environment: preview
archiveDir: /data/full-sync
stateDir: ./state
pollInterval: 10s
feishu:
appId: "${FEISHU_APP_ID}"
appSecret: "${FEISHU_APP_SECRET}"
chatId: "${FEISHU_CHAT_ID}"
```
| 配置项 | 说明 |
| --- | --- |
| `archiveDir` | Worker 归档目录(只读挂载) |
| `stateDir` | 已发送 Run 的标记目录(可写) |
| `pollInterval` | 扫描间隔,默认 `10s` |
| `feishu.appId` / `appSecret` | 飞书应用凭据 |
| `feishu.chatId` | 目标群 ID |
## 命令
| 命令 | 作用 |
| --- | --- |
| `watch` | 常驻扫描归档目录,自动发送新 Run(默认模式) |
| `send` | 发送指定 Run JSON |
| `send-text` | 向配置里的群发一条纯文本(用于连通性验证) |
| `render` | 只渲染卡片内容,不调用飞书 API |
```bash
go run ./cmd/iotlcm-bot watch --config /path/to/iotlcm-bot.yaml
go run ./cmd/iotlcm-bot send --config /path/to/iotlcm-bot.yaml --file /path/to/run.json
go run ./cmd/iotlcm-bot send --config /path/to/iotlcm-bot.yaml --file /path/to/run.json --force
```
`--force` 用于确需重发时;正常运行不要使用。发送成功会写入 `state/sent/<runId>.json`,同一 Run 再次执行会跳过。
## 容器化部署
```bash
docker build -t iotlcm-bot:latest .
docker run -d \
-v /host/worker/full-sync:/data/full-sync:ro \
-v /host/bot/state:/data/state \
-v /host/bot/config.yaml:/app/config/config.yaml:ro \
iotlcm-bot:latest
```
容器内路径约定:
| 容器内路径 | 用途 | 挂载方式 |
| --- | --- | --- |
| `/data/full-sync` | Worker 归档目录 | **只读** |
| `/data/state` | 已发送标记 | 可写 |
| `/app/config/config.yaml` | 配置文件 | 只读 |
## 目录结构
```text
iotlcm-bot/
├── cmd/iotlcm-bot/main.go # CLI 入口
├── internal/
│ ├── archive/ # 归档 JSON 解析
│ ├── config/ # 配置加载
│ ├── feishu/ # 飞书 API 客户端
│ ├── notify/ # 通知服务与健康自检
│ ├── render/ # 卡片渲染
│ └── state/ # 已发送标记
├── config.yaml # 配置(公开版为占位值)
├── testdata/ # 测试用归档样例
└── Dockerfile
```
## 常见问题
**卡片不发送?** 检查归档目录是否可读、`runId` 是否已发送过(`state/sent/` 下有标记则跳过)、群机器人是否被移出。
**日志刷满?** `watch` 模式对同一文件只记一次错误,文件被重写后会重新记录。
**归档目录被宿主删了?** Bot 会检测到(inode 丢失)并降级告警——此时应检查宿主的日志清理脚本是否误删了挂载源目录。
## 相关项目
- [iotlcm-worker-svr](https://git.5iot.com/iotlcm-public/iotlcm-worker-svr) —— 异步执行中枢,产出归档 JSON
- [iotlcm-openapi](https://git.5iot.com/iotlcm-public/iotlcm-openapi) —— 对外 API 网关
## License
[Apache License 2.0](./LICENSE)