fix: ci-log durable persisted-log fallback for pruned runs

ci-log drove only the live run-view streamer (POST .../runs/<n>/jobs/<j>
with logCursors), which reads the live act_runner task record. Forgejo
prunes that record once a run completes, so the streamer 500s with
'task ... resource does not exist' on quick or older runs even though
the web UI still shows the logs — the reader (argus, atlas) then had to
ask the operator to relay the error.

Add a fallback: when the streamer errors or returns no lines, download
the persisted whole-job log via the same web route the run page's view-
raw-logs link uses, .../runs/<n>/jobs/<job>/attempt/<a>/logs, keyed by
the per-repo run number with the attempt segment. It survives the task
prune. Live and recent runs keep the rich per-step streamed view; only
the pruned case takes the flat fallback (where --step can't apply). New
--attempt flag (default 1) selects the run attempt for re-runs.

Verified against a real pruned run whose streamer 500'd: the fallback
prints the full persisted log; a completed short job ends cleanly at
'Job succeeded', confirming the route returns complete logs.
This commit is contained in:
atlas 2026-06-23 22:16:18 +02:00 committed by mara
commit d340c1773a
2 changed files with 124 additions and 68 deletions

View file

@ -165,16 +165,21 @@ plain comment show under `last comment`, not `reviews`.
the run's internal global id, so the verb translates the run number
first. Saves a zip to `/tmp/forge-artifact-<name>.zip` by default; pass
`-o -` to stream to stdout.
- `ci-log --run <n> [--job i] [--step i]` prints a CI run's job step
logs. `<n>` is the run number from the run-page URL (same value
`artifact-get` takes; `pr-status` surfaces it as a CI context's
target_url). Forgejo exposes no REST endpoint for job logs, so the
verb drives the web run-view streamer the run page polls. `--job`
selects the job within the run (0-based, default 0); `--step` narrows
to one step. `act_runner` garbage-collects completed-run logs, so this
is reliable for live + recently-finished runs; when logs are gone the
verb says so rather than printing nothing. `--json` dumps the raw
run-view response.
- `ci-log --run <n> [--job i] [--step i] [--attempt n]` prints a CI
run's job step logs. `<n>` is the run number from the run-page URL
(same value `artifact-get` takes; `pr-status` surfaces it as a CI
context's target_url). Two log sources are tried in order: first the
web run-view **streamer** the run page polls (rich per-step framing,
honors `--step`) — but that reads the live `act_runner` task record,
which Forgejo prunes once a run completes; then, when the streamer is
pruned (500 / no lines), the **durable persisted-log download** the
run page's "view raw logs" link uses
(`…/runs/<n>/jobs/<job>/attempt/<a>/logs`), a flat whole-job log that
survives the prune (`--step` is not honored on this path). So quick /
older runs that the streamer can no longer serve still print instead
of erroring. `--job` selects the job (0-based, default 0); `--attempt`
picks the run attempt for the durable path (default 1; re-runs
increment it). `--json` wraps the output.
- `ci-rerun` re-runs CI without pushing an empty commit (the old
retrigger path, which littered PR history). Forgejo has no token-usable
REST endpoint to re-run an *existing* run (the run-page rerun buttons