# Gitea Actions: 从 PR 失败 status check 拿到具体 job 日志

**Date**: 2026-05-18
**Context**: PR #417 `backend-integration` check 失败，需要定位根因日志

## 问题

PR 上 status check 给的 `target_url` 形如：
```
/FFAIWorkspace/workspace/actions/runs/3890/jobs/11220
```

直觉上跟着试 API：
- `GET /api/v1/repos/.../actions/runs/{run_id}/jobs/{job_id}/logs` → **404**
- `GET /repos/.../actions/runs/{run_id}/jobs/{job_id}/logs` (web UI 路径) → **404**
- `GET /api/v1/repos/.../actions/tasks/{job_id}/logs` → **404**

## 正确路径

```
GET /api/v1/repos/{owner}/{repo}/actions/jobs/{job_id}/logs
```

注意 **没有 `runs/{run_id}`**——job_id 在仓库下全局唯一，直接挂在 `actions/jobs/` 下，不嵌套在 run 里。返回纯文本日志（不是 JSON）。

## 完整调查流程（可复用）

```bash
GITEA_TOKEN="${GITEA_API_TOKEN}"
SHA=<head_sha>  # 从 PR --json 的 head.sha 拿

# 1. 拿 combined status，找 failure 的 target_url
curl -s -H "Authorization: token $GITEA_TOKEN" \
  "http://43.130.59.228/api/v1/repos/FFAIWorkspace/workspace/commits/$SHA/status" \
  | python3 -c "import json,sys; [print(s['status'],s['context'],s.get('target_url')) for s in json.load(sys.stdin)['statuses']]"

# 2. 从 target_url 提 job_id（最后一段），拉日志
JOB_ID=11220
curl -s -H "Authorization: token $GITEA_TOKEN" \
  "http://43.130.59.228/api/v1/repos/FFAIWorkspace/workspace/actions/jobs/$JOB_ID/logs" \
  -o /tmp/job.log

# 3. 扫错误
grep -nE "FAIL|Error|exit code|npm ERR|ENOSPC" /tmp/job.log | head -40
```

## 提炼建议

如果未来 AI 经常排查 CI 失败，值得把这套流程做成 `scripts/ops/gitea ci-log <PR#>` 子命令——
自动 PR → head_sha → failing job_id → 日志尾部 + 错误高亮。当前频次还够不上，先记 learning。

## 相关坑

同次排查发现：当前 runner 磁盘满（`ENOSPC`）是 backend-integration 反复挂的真实根因，
正在通过 `ops/runner-disk-clean-workflow` 分支引入 cron 周期清盘解决（HEAD d8839684）。
