Files
playbook/skills/gitea-fix-ci/SKILL.md
T

211 lines
12 KiB
Markdown
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.
---
name: gitea-fix-ci
description: "Use when a user asks to debug or fix failing Gitea Actions, Gitea PR checks, or CI workflow runs for a Gitea-hosted repository. Also triggers on Chinese phrasing such as CI 挂了/流水线红了/构建失败/工作流失败."
---
# Gitea Fix CI
## 概述
从 pull request 或 workflow run 诊断失败的 Gitea Actions,提取最小可用的失败上下文,
然后在改代码之前先给出修复计划。核心原则:CI 日志是证据,不要仅凭红色状态臆测原因。
本 skill 不是独立执行器。它指导你在当前工作区中使用随附的取证脚本
`scripts/fetch_ci_logs.py``tea`、本地 `git` 和 Gitea API。
取证阶段(step 2-4)优先使用随附脚本,把「探测版本 → 找失败 run → 列 job →
下载失败 job 日志」这段易记错 API 路径的逻辑交给它。脚本仅取证到日志,分类、
修复计划与改代码仍由你按本文档执行。将 `<skill-dir>` 替换为包含本 `SKILL.md`
的目录:
```bash
# 方式一(优先):通过环境变量提供 API token
export GITEA_TOKEN=<token>
python <skill-dir>/scripts/fetch_ci_logs.py version # 探测实例版本并确认连通性
python <skill-dir>/scripts/fetch_ci_logs.py runs --status failure --branch <branch>
python <skill-dir>/scripts/fetch_ci_logs.py jobs <run-id> # 标注 failure 的 job
python <skill-dir>/scripts/fetch_ci_logs.py logs <job-id> # 日志存临时文件并回显尾部
# 方式二:显式复用当前仓库的 Git HTTP 凭据
python <skill-dir>/scripts/fetch_ci_logs.py --use-git-credential version
python <skill-dir>/scripts/fetch_ci_logs.py --use-git-credential runs --status failure
```
`base-url`、owner 和 repo 默认从 git remote 推导。认证规则如下:
- 设置了 `GITEA_TOKEN` 时始终优先使用它,即使同时传入 `--use-git-credential`
- 只有显式传入 `--use-git-credential` 才会非交互调用 `git credential fill`,并将
当前仓库对应的用户名和密码用于 HTTP Basic 认证;脚本不会静默读取 Git 凭据。
- 未设置 token 且未传入该参数时按匿名方式访问,私有仓库通常会返回 401。
- 所有携带凭据的请求必须使用 HTTPS;认证 header 只发送到配置的 Gitea 同源地址,
跨源请求和跨源重定向会被拒绝。凭据不会出现在命令参数、日志或异常文本中。
脚本不可用(未装 Python、旧版 Gitea 无 job-log API、脱离 Gitea 环境)时,回退到
下文的手动 `tea`/API/web 路径。
## 适用场景
- Gitea 托管的仓库出现失败的 Gitea Actions 或 PR checks
- 用户要求检查某个失败的 workflow run、job 或 CI 状态
- 用户要求在 push、更新分支或更新 pull request 之后修复 CI
- 本地测试通过,但远端 Gitea Actions 失败
## 不适用场景
- 仓库并非托管在 Gitea 或 Forgejo 兼容的基础设施上
- 失败属于外部 CI 服务,只是从 Gitea 链接出去
- 用户只想在本地跑测试或 lint
- 没有凭据、token 或网络访问权限,且用户也未提供失败的日志文本
## 输入
- 仓库路径,默认为当前工作区
- Gitea base URL 和仓库 owner/name,尽量从 `git remote -v` 获取
- Pull request 编号、分支、commit SHA 或 workflow run ID
- 认证方式:`tea` 登录 profile、用于 API 请求的 `GITEA_TOKEN`,或通过
`--use-git-credential` 显式读取的当前仓库 Git HTTP 凭据
- 若无法远端访问,则由用户粘贴的 CI 日志
## 流程
1. **基线本地状态**
- 记录 `git status --short`、当前分支和最新 commit SHA。
-`git remote -v` 识别 remote URL 和 owner/repo。
- 继续之前先确认 remote 是 Gitea/Forgejo:对照已知的 Gitea 实例核对 host
或探测 `/api/v1/version`。若 remote 是 GitHub、GitLab 或其他服务,按"不适用场景"停止。
- 收集 CI 证据期间不要修改文件。
2. **验证 Gitea 访问**
- 优先运行 `fetch_ci_logs.py version` 探测实例版本并确认脚本能连通实例。脚本从
remote 推导 base URL,认证按 `GITEA_TOKEN` → 显式 `--use-git-credential`
匿名的顺序选择。注意:`version` 只读 `/api/v1/version`,成功仅代表连通与鉴权
可用,**不代表 Actions API 一定可用**。Actions 端点是否存在需在后续
`runs`/`jobs` 步骤中实际验证;旧版 Gitea(见下)会在此才暴露 404。
- 脚本不可用时,回退到手动方式。优先使用已安装并已认证的 `tea`
- `tea login list`
- 使用前先运行 `tea actions --help` 确认已安装的 `tea` 版本存在 `actions`
子命令;并非所有版本都带这些子命令。
- `tea actions runs list --status failure --branch <branch>`
- `tea actions runs view <run-id>`
- `tea actions runs logs <run-id> --job <job-id>`
- `tea pulls view <pr>`
-`tea` 不可用,或已安装版本缺少 Actions 命令,则直接使用 Gitea API。
- 当 API 行为不明确时,检查 `/api/v1/version``/swagger.v1.json`。较旧的
Gitea1.21 及更早)在 web UI 中提供 Actions 页面,但不提供 workflow
run/job/log 的 API 端点;应对照上报的版本确认可用性,而不是想当然。
- 绝不打印 token、用户名或密码。API token 只通过环境变量传递;Git 凭据只通过
`git credential fill` 的标准输入/输出在脚本进程内传递,不放入 argv。
3. **定位失败的 workflow run**
- 若入口是 PR 而非 run ID,先把 PR 解析成 run:取 PR 的 head 分支与 head SHA
`fetch_ci_logs.py``runs` 支持 `--branch`/`--sha`;手动则
`GET /api/v1/repos/<owner>/<repo>/pulls/<pr>``head.ref`/`head.sha`),
再按该 SHA 过滤 runs。PR 页面的 checks 列表可能聚合多个 workflow,逐一定位到
具体失败 run,不要假设只有一个。
- 优先用脚本:`fetch_ci_logs.py runs --status failure --branch <branch>`
(也支持 `--sha`/`--event`/`--limit`),已知 run ID 时用
`fetch_ci_logs.py jobs <run-id>` 直接列出各 job 并标注失败项。
- 脚本不可用时回退到手动方式。已知 run ID 时,直接获取该 run。
- 否则按分支、事件、状态或 commit SHA 过滤,列出最近的 workflow runs。
- API 模式:
- `GET /api/v1/repos/<owner>/<repo>/actions/runs`
- `GET /api/v1/repos/<owner>/<repo>/actions/runs/<run>`
- `GET /api/v1/repos/<owner>/<repo>/actions/runs/<run>/jobs`
- 较旧 Gitea 的 web 回退:
- `GET /<owner>/<repo>/actions`
- 解析 `/<owner>/<repo>/actions/runs/<run>` 链接和状态标签。
- 区别对待 `failure``cancelled` 和缺失的必需 checks。被取消(cancelled)的
job 可能需要重跑或排查队列,而非改代码。
4. **获取 job 日志**
- 优先用脚本:`fetch_ci_logs.py logs <job-id>`。它把日志存到受跟踪源码路径
之外的临时文件、只回显尾部若干行,并打印临时文件路径供进一步查看
`--tail N` 调整行数,`--json` 输出结构化结果)。
- 脚本不可用时回退到手动方式。对每个失败的 job,下载其日志:
- `GET /api/v1/repos/<owner>/<repo>/actions/jobs/<job_id>/logs`
- 在较旧 Gitea 的 web 回退(无 job-log API)下,按 UI 的 job index 下载日志:
- `GET /<owner>/<repo>/actions/runs/<run>/jobs/<job-index>/logs`
- 先打开 run 页面读取每个 job 的状态;取状态为 `failure` 的 job 的 index
不要默认用 index `0`。失败的 job 很少是第一个,盲目用 index `0` 通常会返回
某个通过的 job 的日志。只有当 run 页面不暴露每个 job 的状态时,才回退到逐一
扫描 index。
- 大日志保存到受跟踪源码路径之外的临时文件。
- 提取首个可操作的错误块、其上下文命令、job 名、workflow 名、run URL、分支和 SHA。
- 若日志缺失,明确报告,而不是编造原因。
5. **分类失败**
- 代码/测试失败:断言失败、编译错误、lint 错误、类型错误
- 环境失败:缺失 secret、runner 镜像、依赖安装、网络、缓存、权限或服务启动
- 工作流失败:YAML 非法、语法不支持、触发条件错误、路径错误、分支/ref 假设错误
- 基础设施失败:runner 离线、队列卡住、run 被取消、超时
6. **制定修复计划**
- 用确切的 job/run 标识总结失败证据。
- 提出与证据匹配的最小代码或工作流改动。
- 包含本地验证命令和远端复检路径。
- 在用户批准修复计划之前不要实施。
7. **批准后实施**
- 只应用已批准的修复。
- 运行最接近复现该失败 job 的本地命令。
- 若失败仅涉及工作流,验证工作流文件语法及其引用的路径或脚本。
8. **复检**
- 告诉用户需要在 Gitea 中 push 或重跑什么。
- 若获准,使用 Gitea API 检查重跑状态。
- 最终输出必须区分本地验证与远端 CI 状态。
## 输出约定
- `Target:` 仓库、分支/SHA、PR 或 run ID
- `Failed CI:` workflow、job、状态、run URL 或 API 路径
- `Evidence:` 精简的日志片段与分类
- `Plan:` 提出的修复、本地验证、远端复检
- `Changes:` 批准后改动的文件
- `Result:` 已运行的本地检查与剩余的远端状态
## 成功标准
- 失败分析基于 Gitea Actions 的 run/job 数据或粘贴的日志
- 修复计划指明其针对的确切 workflow run 或 job
- 计划批准前不发生任何代码或工作流改动
- 验证区分本地命令与远端 Gitea Actions 结果
- 不回显 token;私有日志只保留可操作的片段,不整段外泄
## 危险信号(Red Flags
出现以下情况说明流程走偏,停下纠正而非继续:
- **凭红色状态臆测原因**:还没下载 job 日志就断言失败原因或动手改代码。
- **误读双字段结果**:把 `status`(生命周期)当成结果判定。Gitea Actions 沿用
GitHub 兼容的双字段模型——`status=completed` 只表示跑完了,真正的成败在
`conclusion``failure`/`success`/`cancelled`)。判定失败必须看有效结果,
而非 `status=completed` 就当通过。
- **盲取 job index `0`**:在 web 回退下不看每个 job 状态就用 index `0` 下载日志;
失败的 job 很少是第一个,通常会误取到某个通过 job 的日志。
- **把 `version` 成功当作 Actions API 可用**`version` 只探连通与鉴权,Actions
端点可能仍返回 404(旧版 Gitea)。
- **把 `cancelled`/基础设施问题当代码 bug 修**:被取消、runner 离线、队列卡住、
超时应重跑或排查环境,不是改代码。
- **回显 token 或整段私有日志**:只保留可操作的最小片段。
- **静默读取或降级传输凭据**:Git 凭据必须由 `--use-git-credential` 显式启用;
token 和 Git 凭据都不得通过 HTTP 或跨源重定向发送。
## 失败处理
- 401 且未使用认证时,通过环境提供 `GITEA_TOKEN` 或显式传入
`--use-git-credential`;401 且已使用认证时检查凭据是否有效,不要在对话中索要 secret
- 403 表示所选凭据缺少仓库或 Actions 读取权限;补足权限,而不是切换到匿名访问
- 404 优先核对 owner/repo、端点和 Gitea 版本;旧版本缺少 Actions API 时使用 web 回退
- 若 Gitea 版本缺少 Actions API 端点,请用户提供相关日志文本或从浏览器复制的 job 日志
- 若失败的 check 归属外部 CI 服务,报告外部 URL 并在证据收集处停止
- 若失败仅为基础设施问题,建议重跑/排查 runner,而非改代码