Give a push-triggered job somewhere to report a failure
report_job_log live-smoke-test passed: live smoke test log line REGRESSION-CHECK-LIVE-SMOKE

report_job_log.py only ever commented on an open PR, so a push to
development/main -- the shape of a publish pipeline, which has no
pull_request trigger -- had nowhere to post: the branch pushed to is the
merge's target, not the already-closed PR that produced it. Combined with
job logs 500ing on this Gitea, that made a push-triggered failure completely
invisible (weblib-viewer run 1769, diagnosed only by hardcoding --pr on a
throwaway commit).

A GitHub-style commit-comment endpoint, the first thing tried, does not
exist on this Gitea: 404, and absent from /swagger.v1.json entirely. What
does exist and was verified live: GET commits/{sha}/pull resolves the PR
that produced a given commit, open or closed, across both merge styles this
org uses -- so the closed PR the push actually came from can still be found
and commented on as before. When even that finds nothing (a commit that was
never part of any PR), fall back to a commit status, since that endpoint is
already proven to work here.

No CLI changes; existing callers are unaffected.

Closes #14

Co-authored-by: bit <bit@das-labor.org>
This commit is contained in:
2026-09-10 10:46:23 +00:00
co-authored by bit
parent 8c0088987b
commit c2947db08a
3 changed files with 340 additions and 21 deletions
+46 -2
View File
@@ -14,7 +14,7 @@ fetch it — which was measured to be the difference between one step and three.
| file | what it does |
|---|---|
| `with-nixpkgs.sh` | Runs a command with one nixpkgs package on PATH, pinned to the *consuming* repo's `flake.lock`. Avoids `nix shell nixpkgs#x`, which re-resolves the registry and refetches a channel tarball whenever the branch moves. |
| `report_job_log.py` | Posts the tail of a build log as a PR comment. Exists because `actions/jobs/{id}/logs` returns 500 for every id on Gitea 1.25.2, so a red job otherwise says only that it failed. Takes `--status`; see below. |
| `report_job_log.py` | Posts the tail of a build log as a PR comment, falling back to a commit status when a `push`-triggered job has no PR to comment on. Exists because `actions/jobs/{id}/logs` returns 500 for every id on Gitea 1.25.2, so a red job otherwise says only that it failed. Takes `--status`; see below. |
| `sync_blocked_label.py` | Keeps `Status/Blocked` in step with Gitea's dependency graph. Resolves the label from the repo *or the organisation*, never touches an issue marked `Status/On Hold` or `Status/Abandoned`, and leaves the label alone (rather than guessing) on a blocker whose state a repo-scoped token cannot resolve — see weblib-ci#11. |
All three are standard library / plain bash only. They are *run*, not built, so
@@ -27,7 +27,7 @@ test reads state back rather than trusting an exit status of 0 (which the
reporter in particular returns even when its POST failed).
```bash
python3 test_report_job_log.py # 22 tests, ~1.2s, no network
python3 test_report_job_log.py # 28 tests, ~3s, no network
python3 test_sync_blocked_label.py # 12 tests, no network
```
@@ -100,6 +100,50 @@ status is put in the header verbatim rather than rejected: `argparse`'s
`choices=` would exit 2 on a value this list has not heard of, and the log —
the entire reason the script exists — would never be posted.
### `push`-triggered jobs: no open PR does not mean no channel
Found the hard way on weblib-ci#14: a `push` to `development`/`main` — the
common shape of a workflow like a publish pipeline, which has no
`pull_request` trigger at all — has no *open* PR for `report_job_log.py` to
comment on. The branch that was pushed to is the merge's **target**, not the
PR that produced it, and that PR is already closed. The old behaviour was to
print "no pull request for this run" and exit 0, so a failure there was
completely invisible: not the log (500 on this Gitea), not a comment
(nowhere to put it), nothing. That is how weblib-viewer run 1769's failure
(`publish.sh` refusing to overwrite an existing APK) went unnoticed until it
was reproduced by hand.
Two things changed, tried in order, neither needing a new flag:
1. **Ask Gitea which PR produced this exact commit.**
`GET repos/{repo}/commits/{sha}/pull` resolves the PR a commit came from —
open or closed — keyed on the commit itself rather than a branch name.
Verified against both merge styles used in this org: an explicit merge
commit, and a fast-forward promotion where the "merge commit" is just the
PR branch's own tip. This needs the **full** 40-character `GITHUB_SHA`; a
short sha gets the same 404 shape as a commit with no PR at all, so it
would silently look like "not found". This covers the ordinary case —
almost every push to a protected branch here is a merge landing.
2. **If that also finds nothing** — a commit that was never part of any
PR — post a **commit status** instead
(`POST repos/{repo}/statuses/{sha}`, context `report_job_log`). It is not
a substitute for the full log: this Gitea did not truncate a 3000-character
description in testing, but a status is UI chrome, not a page, so what
goes there is deliberately a short snippet (`STATUS_TAIL`, 500 characters),
not the whole tail. `state` follows the same outcome as the header phrase
(`failed → failure`, `passed → success`, `cancelled → warning`,
`skipped → skipped`; an unrecognised status maps to `error` rather than
guessing pass or fail), and `target_url` points at the commit.
**A commit *comment* API (GitHub-style, `commits/{sha}/comments`) does not
exist on this Gitea** — 404, and absent from `/swagger.v1.json` entirely, not
merely unauthorised. That ruled out the most direct-looking option; the
commit-status endpoint is the one that is actually there.
If a PR *is* found (by either the original lookups or the new sha lookup),
behaviour is identical to before: a comment, same format. The status path is
only reached when no PR exists anywhere for the commit.
### Why not a flake input
These are scripts a workflow runs, not derivations. A flake input would cost a