GitHub adapter: runs, job logs and labels #85

Closed
opened 2026-10-09 09:36:02 -05:00 by deadstyle · 1 comment
Owner

Problem

A GitHub session has no Actions box data, no logs, and no label editing until the adapter implements the optional capabilities. Parent: #83. Depends on #84 (the internal/forge/github package); pick this up after #84 merges.

Acceptance criteria

  • The GitHub adapter implements forge.RunLister, forge.LogReader and forge.Labeler, so [3] Actions lists runs, R opens a run's page, and labels can be edited, as on Forgejo (design.md → Boxes [3]; Keymap R; ADR 0006 capabilities).
  • A run's state folds GitHub's status + conclusion into the same CIState values as #84's check-run fold.
  • Job logs stream from GitHub's redirect without sending the token to the log host.
  • Setting labels by ID works even though GitHub's API takes label names.

Plan

In internal/forge/github, following the client from #84:

  • ListRuns: GET …/actions/runs (branch, head_sha filters; body {total_count, workflow_runs}, Link paging). Field mapping: ID ← id, Number ← run_number, Workflow ← name, Title ← display_title, Branch ← head_branch, Commit ← head_sha, Event ← event, StartedAt ← run_started_at, Duration ← updated_at − run_started_at once completed, WebURL ← html_url.
  • Status fold: reuse #84's check-run fold. completed uses conclusion. Otherwise in_progress → running, and queued, waiting, requested and pending → pending.
  • ListJobs: GET …/actions/runs/{id}/jobs (paginated {total_count, jobs}), Attempt ← run_attempt.
  • JobLog: GET …/actions/jobs/{id}/logs, a 302 to a signed URL on another host. Go drops Authorization on a cross-host redirect. Add a test that proves the token isn't sent to the redirect target.
  • Labeler: ListLabels ← GET …/labels, ItemLabels ← GET …/issues/{n}/labels, SetLabels → PUT …/issues/{n}/labels with {labels: [names]}, mapping the IDs to names through ListLabels (an unknown ID is an error). GitHub colors are hex without #, so match the format the gitea adapter hands domain.Label.Color.
  • Fixtures recorded with gh api (runs, jobs, labels), plus a log fixture as in gitea/testdata/actions/.

Context

  • Gitea equivalents: internal/forge/gitea/actions.go, labels.go. Capabilities: internal/forge/forge.go.
  • The architecture.md API table GitHub column lists these endpoints, unverified until this ticket.

Out of scope

Re-run (Rerunner stays undefined, ADR 0006). The Logs tab UI (post-v1).

## Problem A GitHub session has no Actions box data, no logs, and no label editing until the adapter implements the optional capabilities. Parent: #83. **Depends on #84** (the `internal/forge/github` package); pick this up after #84 merges. ## Acceptance criteria - The GitHub adapter implements `forge.RunLister`, `forge.LogReader` and `forge.Labeler`, so `[3]` Actions lists runs, `R` opens a run's page, and labels can be edited, as on Forgejo *(design.md → Boxes `[3]`; Keymap `R`; ADR 0006 capabilities)*. - A run's state folds GitHub's `status` + `conclusion` into the same `CIState` values as #84's check-run fold. - Job logs stream from GitHub's redirect without sending the token to the log host. - Setting labels by ID works even though GitHub's API takes label names. ## Plan In `internal/forge/github`, following the client from #84: - `ListRuns`: `GET …/actions/runs` (`branch`, `head_sha` filters; body `{total_count, workflow_runs}`, `Link` paging). Field mapping: `ID` ← `id`, `Number` ← `run_number`, `Workflow` ← `name`, `Title` ← `display_title`, `Branch` ← `head_branch`, `Commit` ← `head_sha`, `Event` ← `event`, `StartedAt` ← `run_started_at`, `Duration` ← `updated_at − run_started_at` once completed, `WebURL` ← `html_url`. - Status fold: reuse #84's check-run fold. `completed` uses `conclusion`. Otherwise `in_progress` → running, and `queued`, `waiting`, `requested` and `pending` → pending. - `ListJobs`: `GET …/actions/runs/{id}/jobs` (paginated `{total_count, jobs}`), `Attempt` ← `run_attempt`. - `JobLog`: `GET …/actions/jobs/{id}/logs`, a 302 to a signed URL on another host. Go drops `Authorization` on a cross-host redirect. Add a test that proves the token isn't sent to the redirect target. - `Labeler`: `ListLabels` ← `GET …/labels`, `ItemLabels` ← `GET …/issues/{n}/labels`, `SetLabels` → `PUT …/issues/{n}/labels` with `{labels: [names]}`, mapping the IDs to names through `ListLabels` (an unknown ID is an error). GitHub colors are hex without `#`, so match the format the gitea adapter hands `domain.Label.Color`. - Fixtures recorded with `gh api` (runs, jobs, labels), plus a log fixture as in `gitea/testdata/actions/`. ## Context - Gitea equivalents: `internal/forge/gitea/actions.go`, `labels.go`. Capabilities: `internal/forge/forge.go`. - The `architecture.md` API table GitHub column lists these endpoints, unverified until this ticket. ## Out of scope Re-run (`Rerunner` stays undefined, ADR 0006). The Logs tab UI (post-v1).
Author
Owner

🤖 merged: #89

🤖 merged: https://git.bobparsons.dev/deadstyle/lazyforge/pulls/89
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#85
No description provided.