Spike: Forgejo Actions API coverage on our instance #1

Closed
opened 2026-10-01 21:55:15 -05:00 by deadstyle · 1 comment
Owner

Problem

The Actions box ([3]), the Logs tab and the R (re-run) key all depend on what the Forgejo API exposes for Actions on our instance (git.bobparsons.dev). We know fj can't re-run a job or fetch logs, which suggests gaps. Designing those features before knowing what's available risks building UI for data we can't get.

Plan

Time-boxed investigation (half a day). Against the deployed Forgejo version, with a read-scoped token:

  1. Record the Forgejo version (/api/v1/version).
  2. For each of these, find the endpoint (Swagger at /api/swagger), call it on a real repo with runs, and save a trimmed sample response:
    • list workflow runs for a repo (filter by branch / status)
    • list jobs for a run
    • fetch a job's log
    • re-run a run or a single job
    • commit status / checks for a PR head (feeds CI state on PR rows)
  3. For anything missing, note the fallback: hide the feature, derive it (e.g. CI state from commit statuses), or o opens the web page.

Deliverable

A comment on this ticket with a table: operation → endpoint (or "missing") → sample saved at → fallback. Samples committed under internal/forge/gitea/testdata/actions/ so the adapter's tests can use them later.

Context

  • docs/architecture.md → "API mapping", where the Forgejo Actions rows are marked "⚠ check".
  • docs/design.md → boxes table: [3] Actions, Logs tab, R key.
  • ADR 0002: missing features become capability interfaces (forge.RunLister, forge.LogReader, forge.Rerunner). This spike decides which ones the gitea adapter can implement.
  • Known: fj cannot re-run jobs or fetch logs; raw logs live zstd-compressed inside the Forgejo container, which lazyforge can't use.

Out of scope

Writing adapter code.

## Problem The Actions box ([3]), the Logs tab and the `R` (re-run) key all depend on what the Forgejo API exposes for Actions on our instance (git.bobparsons.dev). We know `fj` can't re-run a job or fetch logs, which suggests gaps. Designing those features before knowing what's available risks building UI for data we can't get. ## Plan Time-boxed investigation (half a day). Against the deployed Forgejo version, with a read-scoped token: 1. Record the Forgejo version (`/api/v1/version`). 2. For each of these, find the endpoint (Swagger at `/api/swagger`), call it on a real repo with runs, and save a trimmed sample response: - list workflow runs for a repo (filter by branch / status) - list jobs for a run - fetch a job's log - re-run a run or a single job - commit status / checks for a PR head (feeds CI state on PR rows) 3. For anything missing, note the fallback: hide the feature, derive it (e.g. CI state from commit statuses), or `o` opens the web page. ## Deliverable A comment on this ticket with a table: operation → endpoint (or "missing") → sample saved at → fallback. Samples committed under `internal/forge/gitea/testdata/actions/` so the adapter's tests can use them later. ## Context - `docs/architecture.md` → "API mapping", where the Forgejo Actions rows are marked "⚠ check". - `docs/design.md` → boxes table: `[3] Actions`, Logs tab, `R` key. - ADR 0002: missing features become capability interfaces (`forge.RunLister`, `forge.LogReader`, `forge.Rerunner`). This spike decides which ones the gitea adapter can implement. - Known: `fj` cannot re-run jobs or fetch logs; raw logs live zstd-compressed inside the Forgejo container, which lazyforge can't use. ## Out of scope Writing adapter code.
Author
Owner

🤖 Spike result. Forgejo 16.0.5+gitea-1.22.0. Samples in internal/forge/gitea/testdata/actions/ on spike/1-actions-api (1b9db17; MR to follow once SSH on :2222 is back).

Operation Endpoint Sample Fallback
List runs (filters: event, status, head_sha, workflow_id, run_number, ref — full ref only) GET /repos/{o}/{r}/actions/runs runs_list.json —
Get run GET …/actions/runs/{run_id} run_get.json —
Jobs for a run GET …/actions/runs/{run_id}/jobs (bare array, no pagination) run_jobs.json —
Job log GET …/actions/jobs/{job_id}/logs (text/plain, Range supported) job_log.txt —
Re-run run / job missing (no swagger path; probes 404) — hide R; o opens the run page
CI state for PR head GET …/commits/{sha}/status (combined state) commit_status_combined_*.json —

Engineering notes for #6:

  • RunLister and LogReader: implementable. Rerunner: not on Forgejo 16.
  • Runs: limit is ignored unless page is sent; page cap 50; response {workflow_runs,total_count}, no X-Total-Count.
  • Field names differ from GitHub/Gitea: single status (no conclusion), index_in_repo, prettyref, commit_sha, workflow_id = file name. API routes take the global run id; web URLs use the per-repo index.
  • Logs take the job id, not task_id. Skipped jobs (attempt:0) have no log (404).
  • Combined status target_url is a relative path; prefix the host.
  • All reads work unauthenticated on public repos; writes need a token.

Product consequence: with no re-run API, item 12 on #13 recommendation (a) stands — no R in v1 on Forgejo.

🤖 Spike result. Forgejo `16.0.5+gitea-1.22.0`. Samples in `internal/forge/gitea/testdata/actions/` on `spike/1-actions-api` (1b9db17; MR to follow once SSH on :2222 is back). | Operation | Endpoint | Sample | Fallback | |---|---|---|---| | List runs (filters: `event`, `status`, `head_sha`, `workflow_id`, `run_number`, `ref` — full ref only) | `GET /repos/{o}/{r}/actions/runs` | `runs_list.json` | — | | Get run | `GET …/actions/runs/{run_id}` | `run_get.json` | — | | Jobs for a run | `GET …/actions/runs/{run_id}/jobs` (bare array, no pagination) | `run_jobs.json` | — | | Job log | `GET …/actions/jobs/{job_id}/logs` (`text/plain`, `Range` supported) | `job_log.txt` | — | | Re-run run / job | **missing** (no swagger path; probes 404) | — | hide `R`; `o` opens the run page | | CI state for PR head | `GET …/commits/{sha}/status` (combined `state`) | `commit_status_combined_*.json` | — | Engineering notes for #6: - `RunLister` and `LogReader`: implementable. `Rerunner`: not on Forgejo 16. - Runs: `limit` is ignored unless `page` is sent; page cap 50; response `{workflow_runs,total_count}`, no `X-Total-Count`. - Field names differ from GitHub/Gitea: single `status` (no `conclusion`), `index_in_repo`, `prettyref`, `commit_sha`, `workflow_id` = file name. API routes take the global run `id`; web URLs use the per-repo index. - Logs take the job `id`, not `task_id`. Skipped jobs (`attempt:0`) have no log (404). - Combined status `target_url` is a relative path; prefix the host. - All reads work unauthenticated on public repos; writes need a token. Product consequence: with no re-run API, item 12 on #13 recommendation (a) stands — no `R` in v1 on Forgejo.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
deadstyle/lazyforge#1
No description provided.