🐛 fix(gitea-fix-ci): trace workflow_run CI chains

This commit is contained in:
csh
2026-08-20 15:56:40 +08:00
parent 5a8d95ebcf
commit 77ab8211b1
6 changed files with 429 additions and 194 deletions
@@ -0,0 +1,78 @@
# Actions API 取证
仅在 `fetch_ci_logs.py` 可运行且 Gitea Actions API 可用时读取本文件。
## CLI 规则
全局选项放在子命令前:`--remote``--base-url``--owner``--repo`
`--use-git-credential``--json``logs``--tail``--out` 放在 job ID 后。
```bash
python <skill-dir>/scripts/fetch_ci_logs.py --remote origin --json runs --limit 20
python <skill-dir>/scripts/fetch_ci_logs.py --json logs <job-id> --tail 80 --out /tmp/job.log
```
`runs` 默认过滤 `failure`;发现触发链时用 `--status all`,查上游门禁结果时也检查
`cancelled``skipped``--sha` 使用完整 SHA。`--workflow checks.yml` 通过 workflow
专用 endpoint 过滤,并在输出中保留 `path`、时间、run number 与 attempt。
## 直接触发
1.`GET /pulls/<pr>` 取得 `head.ref` 与完整 `head.sha`
2. 按目标 workflow、事件和完整 SHA 列 runs。Gitea 的 PR run 可能保存隐藏 PR ref
`head_branch` 不一定等于 `head.ref`;只有在目标实例实测匹配时才追加 `--branch`
3.`path` 确认 workflow,再列 jobs 和失败日志。
```bash
python <skill-dir>/scripts/fetch_ci_logs.py --json runs \
--workflow <workflow.yml> --event pull_request --status all --sha <full-pr-head-sha>
```
## Prepare → workflow_run 链
先读取仓库 workflow 的 `on:` 段,确认上游 workflow 名与下游文件。
1. **定位上游**:按 PR 完整 head SHA 定位 Prepare 候选;用 workflow path、事件和时间
排除无关 run,记录 run ID、attempt、`conclusion``completed_at`。同一 SHA 有多个
run 或 attempt 时逐个保留,不静默任选。
2. **判断门禁**
- `failure`/`cancelled`:列上游 jobs 并读取上游失败日志;分类为“上游门禁未通过”。
下游通常会产生 `skipped` run/job,也可能缺失,不要寻找下游失败日志。
- `success`:继续查对应下游 workflow。
3. **定位下游候选**:按 workflow 文件、`event=workflow_run``status=all` 列 runs,选择
`started_at` 紧随该上游 attempt 完成时间的候选;重跑上游会生成新一组下游 run。
4. **处理缺失**:上游成功却没有下游候选时,核对默认分支上是否存在并启用了下游
workflow、`workflow_run.workflows` 名称是否与上游一致,以及事件/条件是否排除了该
run。仍无下游时,把“应存在但缺失”作为工作流或 Actions 基础设施证据,不虚构下游
日志。
5. **核验关联**:公开 Gitea run API 不暴露父 run ID 或事件 payload。下游 API 的
`head_branch/head_sha` 属于默认分支 run 本身,不是 PR head。必须用 job 日志中实际
checkout/ref/SHA、PR 页给出的 run URL,或 workflow 自己输出的 provenance 核验。
未核验前把关联标为推断。
```bash
python <skill-dir>/scripts/fetch_ci_logs.py --json runs \
--workflow prepare.yml --event pull_request --status all --sha <full-pr-head-sha>
python <skill-dir>/scripts/fetch_ci_logs.py --json runs \
--workflow checks.yml --event workflow_run --status all --limit 30
```
## Jobs 与日志
```bash
python <skill-dir>/scripts/fetch_ci_logs.py --json jobs <run-id>
python <skill-dir>/scripts/fetch_ci_logs.py --json logs <job-id> --tail 80
```
下载失败 job 日志;取消或基础设施场景读取最后执行或被取消的相关 job。上游门禁场景
只取上游证据。完整日志默认写临时文件,或用 `--out` 指向仓库外路径。提取首个可操作
错误块,不输出凭据或整段私有日志。
## 原始 API
- `/api/v1/version` 只证明实例连通;Actions endpoint 仍需实际调用验证
- API 字段或过滤器不明确时读取 `/swagger.v1.json`,不要猜参数语义
- `GET /api/v1/repos/<owner>/<repo>/actions/runs`
- `GET /api/v1/repos/<owner>/<repo>/actions/workflows/<workflow>/runs`
- `GET /api/v1/repos/<owner>/<repo>/actions/runs/<run>/jobs`
- `GET /api/v1/repos/<owner>/<repo>/actions/jobs/<job_id>/logs`
+37
View File
@@ -0,0 +1,37 @@
# 取证回退路径
仅在脚本不可用、Actions API 返回 404,或只有用户日志时读取本文件。
## tea actions
先确认安装、登录和子命令能力;不同 tea 版本不一定提供 Actions
```bash
tea login list
tea actions --help
tea pulls view <pr>
tea actions runs list --status failure
tea actions runs view <run-id>
tea actions runs logs <run-id> --job <job-id>
```
仍需先读取 workflow `on:` 段。遇到 `workflow_run` 链时,先查 Prepare,再按下游
workflow 和时间定位候选;不要用 PR 分支过滤下游 run。
## Legacy web
Gitea 1.21 及更早可能有 Actions web UI,但没有 run/job/log API
1. 打开 `/<owner>/<repo>/actions`,找到目标 run。
2. 打开 `/<owner>/<repo>/actions/runs/<run>`,读取每个 job 的状态。
3. 选择状态为 `failure` 的 job index,再下载
`/<owner>/<repo>/actions/runs/<run>/jobs/<job-index>/logs`
4. 不要默认 index `0`;只有页面不暴露 job 状态时才逐一扫描。
Prepare 失败时读取 Prepare 页和其失败 job;下游可能显示 `skipped` 或根本不出现在
PR checks 中,不要把它误报为“找不到失败 run”。
## 用户粘贴日志
把日志标记为用户提供的证据,并明确:远端 run/job、workflow、SHA 与状态均未核验。
只引用首个可操作错误块;日志不含 run/job 身份时,不把推测写成事实。