feat(actions): add bounded workflow job logs #378

Merged
dismantl merged 0 commits from codex/forgejo-v16-action-logs into main 2026-07-23 03:21:55 +00:00
dismantl commented 2026-07-16 17:37:32 +00:00 (Migrated from codeberg.org)

Forgejo version 16 was released today and I'm eager to start using the new API endpoints for retrieving workflow logs. Thanks for considering this PR.

Summary

Closes #212.

Adds two Forgejo v16+ Actions tools:

  • list_action_run_jobs lists the jobs belonging to a workflow run.
  • get_action_job_logs reads bounded, resumable ranges from a job's plaintext log.

Together, these let MCP clients identify a failed job and inspect its output through the Forgejo API, without scraping the web UI or requiring SSH/filesystem access to the server.

Design

Forgejo v16 exposes:

  • GET /repos/{owner}/{repo}/actions/runs/{run_id}/jobs
  • GET /repos/{owner}/{repo}/actions/jobs/{job_id}/logs

The pinned forgejo-sdk/v3 does not expose either endpoint, so this reuses the repository's established raw-HTTP layer:

  • Job metadata uses pkg/forgejo.DoJSON.
  • Plaintext logs use a new DoAPIRaw counterpart in the same package, preserving existing authentication, user-agent, request logging, and error handling.
  • Log responses use SafeTextResult so CI output is not copied into debug logs.

No SDK dependency change is required.

The run-wide ZIP endpoint is intentionally omitted because it does not support ranged reads. Per-job plaintext logs provide a bounded and resumable MCP surface.

Output-bounding checklist

list_action_run_jobs

  • Output is data-proportional.
  • Caller-controlled bounds: page and limit, capped at 100 jobs per response.
  • Forgejo returns the complete list, so pagination is applied client-side.
  • Resumption metadata: total_count, has_next, and next_page.

get_action_job_logs

  • Output is data-proportional.
  • Caller-controlled bounds: offset and max_bytes.
  • Omitting offset returns the log tail.
  • Forgejo receives an HTTP Range request, bounding both transfer and MCP output.
  • The response reports the actual byte range, total size, truncation state, and forward/backward continuation values.
  • previous_max_bytes prevents overlap when the preceding chunk is shorter than the requested size.

Both tools document their bounds in the tool schema and README.

Tests

Automated coverage includes:

  • Job-list pagination and continuation metadata.
  • Tail reads and explicit offsets.
  • Forward and backward log continuation.
  • Non-overlapping short preceding chunks.
  • Empty logs and optional job attempts.
  • Invalid IDs, offsets, sizes, and inconsistent Content-Range responses.
  • Raw API authentication, Accept/Range headers, response metadata, and over-limit rejection.

Verification

  • make build
  • go mod tidy and go mod verify
  • go vet ./...
  • gofmt clean
  • golangci-lint
  • go test -race -shuffle=on -count=1 ./...
  • govulncheck ./... with Go 1.26.5
  • License policy check
  • MCP stdio initialize and tool-inventory smoke
  • MCP SSE initialize and tool-inventory smoke

The API contracts are exercised with httptest servers.

Documentation

  • Adds both tools to the README inventory and CLI examples.
  • Adds shared Actions parameter descriptions.
  • Synchronizes the extension manifest with the binary's registered tool inventory.

This supersedes the approach proposed in #126 using the now-stable Forgejo v16 API and incorporates its review feedback: centralized HTTP handling, automated tests, README coverage, and standardized bounded/resumable output.

Forgejo version 16 was released today and I'm eager to start using the [new API endpoints for retrieving workflow logs](https://forgejo.org/2026-07-release-v16-0/#actions-related-api-additions). Thanks for considering this PR. ## Summary Closes #212. Adds two Forgejo v16+ Actions tools: - `list_action_run_jobs` lists the jobs belonging to a workflow run. - `get_action_job_logs` reads bounded, resumable ranges from a job's plaintext log. Together, these let MCP clients identify a failed job and inspect its output through the Forgejo API, without scraping the web UI or requiring SSH/filesystem access to the server. ## Design Forgejo v16 exposes: - `GET /repos/{owner}/{repo}/actions/runs/{run_id}/jobs` - `GET /repos/{owner}/{repo}/actions/jobs/{job_id}/logs` The pinned `forgejo-sdk/v3` does not expose either endpoint, so this reuses the repository's established raw-HTTP layer: - Job metadata uses `pkg/forgejo.DoJSON`. - Plaintext logs use a new `DoAPIRaw` counterpart in the same package, preserving existing authentication, user-agent, request logging, and error handling. - Log responses use `SafeTextResult` so CI output is not copied into debug logs. No SDK dependency change is required. The run-wide ZIP endpoint is intentionally omitted because it does not support ranged reads. Per-job plaintext logs provide a bounded and resumable MCP surface. ## Output-bounding checklist ### `list_action_run_jobs` - Output is data-proportional. - Caller-controlled bounds: `page` and `limit`, capped at 100 jobs per response. - Forgejo returns the complete list, so pagination is applied client-side. - Resumption metadata: `total_count`, `has_next`, and `next_page`. ### `get_action_job_logs` - Output is data-proportional. - Caller-controlled bounds: `offset` and `max_bytes`. - Omitting `offset` returns the log tail. - Forgejo receives an HTTP `Range` request, bounding both transfer and MCP output. - The response reports the actual byte range, total size, truncation state, and forward/backward continuation values. - `previous_max_bytes` prevents overlap when the preceding chunk is shorter than the requested size. Both tools document their bounds in the tool schema and README. ## Tests Automated coverage includes: - Job-list pagination and continuation metadata. - Tail reads and explicit offsets. - Forward and backward log continuation. - Non-overlapping short preceding chunks. - Empty logs and optional job attempts. - Invalid IDs, offsets, sizes, and inconsistent `Content-Range` responses. - Raw API authentication, `Accept`/`Range` headers, response metadata, and over-limit rejection. ## Verification - [x] `make build` - [x] `go mod tidy` and `go mod verify` - [x] `go vet ./...` - [x] `gofmt` clean - [x] `golangci-lint` - [x] `go test -race -shuffle=on -count=1 ./...` - [x] `govulncheck ./...` with Go 1.26.5 - [x] License policy check - [x] MCP stdio initialize and tool-inventory smoke - [x] MCP SSE initialize and tool-inventory smoke The API contracts are exercised with `httptest` servers. ## Documentation - Adds both tools to the README inventory and CLI examples. - Adds shared Actions parameter descriptions. - Synchronizes the extension manifest with the binary's registered tool inventory. This supersedes the approach proposed in #126 using the now-stable Forgejo v16 API and incorporates its review feedback: centralized HTTP handling, automated tests, README coverage, and standardized bounded/resumable output.
op1st-gitops commented 2026-07-16 17:37:37 +00:00 (Migrated from codeberg.org)

op1st Pipelines as Code is skipping this commit.
User dismantl is not allowed to trigger CI via pull_request in this repo.

op1st Pipelines as Code is skipping this commit. User dismantl is not allowed to trigger CI via pull_request in this repo.
goern commented 2026-07-16 21:02:49 +00:00 (Migrated from codeberg.org)

/ok-to-test

/ok-to-test
op1st-gitops commented 2026-07-16 21:02:59 +00:00 (Migrated from codeberg.org)

op1st Pipelines as Code/forgejo-mcp-code-scans-mp4bz is running.

Starting Pipelinerun forgejo-mcp-code-scans-mp4bz in namespace op1st-pipelines

You can monitor the execution using the op1st Pipelines as Code PipelineRun viewer or through the command line by
using the tkn CLI with the following command:

tkn pr logs -n op1st-pipelines forgejo-mcp-code-scans-mp4bz -f

op1st Pipelines as Code/forgejo-mcp-code-scans-mp4bz is running. Starting Pipelinerun <b>[forgejo-mcp-code-scans-mp4bz](https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/forgejo-mcp-code-scans-mp4bz)</b> in namespace <b>op1st-pipelines</b> You can monitor the execution using the [op1st Pipelines as Code](https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/forgejo-mcp-code-scans-mp4bz) PipelineRun viewer or through the command line by using the [tkn](https://tekton.dev/docs/cli/#installation) CLI with the following command: <code>tkn pr logs -n op1st-pipelines forgejo-mcp-code-scans-mp4bz -f</code>
op1st-gitops commented 2026-07-16 21:02:59 +00:00 (Migrated from codeberg.org)

op1st Pipelines as Code/forgejo-mcp-on-pull-request-mlp9s is running.

Starting Pipelinerun forgejo-mcp-on-pull-request-mlp9s in namespace op1st-pipelines

You can monitor the execution using the op1st Pipelines as Code PipelineRun viewer or through the command line by
using the tkn CLI with the following command:

tkn pr logs -n op1st-pipelines forgejo-mcp-on-pull-request-mlp9s -f

op1st Pipelines as Code/forgejo-mcp-on-pull-request-mlp9s is running. Starting Pipelinerun <b>[forgejo-mcp-on-pull-request-mlp9s](https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/forgejo-mcp-on-pull-request-mlp9s)</b> in namespace <b>op1st-pipelines</b> You can monitor the execution using the [op1st Pipelines as Code](https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/forgejo-mcp-on-pull-request-mlp9s) PipelineRun viewer or through the command line by using the [tkn](https://tekton.dev/docs/cli/#installation) CLI with the following command: <code>tkn pr logs -n op1st-pipelines forgejo-mcp-on-pull-request-mlp9s -f</code>
op1st-gitops commented 2026-07-16 21:03:32 +00:00 (Migrated from codeberg.org)

op1st Pipelines as Code/forgejo-mcp-code-scans-mp4bz has successfully validated your commit.


Task Statuses:

StatusDurationName
Succeeded 18 seconds

fetch-source

Succeeded 8 seconds

gitleaks-version

Succeeded 13 seconds

gitleaks

op1st Pipelines as Code/forgejo-mcp-code-scans-mp4bz has <b>successfully</b> validated your commit. <ul> <li><b>Namespace</b>: <a href="https://detailurl.setting.custom-console-url-namespace.is.not.configured">op1st-pipelines</a></li> <li><b>PipelineRun:</b> <a href="https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/forgejo-mcp-code-scans-mp4bz">forgejo-mcp-code-scans-mp4bz</a></li> </ul> <hr> <h4>Task Statuses:</h4> <table> <tr><th>Status</th><th>Duration</th><th>Name</th></tr> <tr> <td>Succeeded</td> <td>18 seconds</td><td> [fetch-source](https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/forgejo-mcp-code-scans-mp4bz/logs/fetch-source) </td></tr> <tr> <td>Succeeded</td> <td>8 seconds</td><td> [gitleaks-version](https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/forgejo-mcp-code-scans-mp4bz/logs/gitleaks-version) </td></tr> <tr> <td>Succeeded</td> <td>13 seconds</td><td> [gitleaks](https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/forgejo-mcp-code-scans-mp4bz/logs/gitleaks) </td></tr> </table>
op1st-gitops commented 2026-07-16 21:05:51 +00:00 (Migrated from codeberg.org)

op1st Pipelines as Code/forgejo-mcp-on-pull-request-mlp9s has successfully validated your commit.


Task Statuses:

StatusDurationName
Succeeded 14 seconds

fetch-source

Succeeded 2 minutes

build-and-test

Succeeded 19 seconds

commit-title-check

op1st Pipelines as Code/forgejo-mcp-on-pull-request-mlp9s has <b>successfully</b> validated your commit. <ul> <li><b>Namespace</b>: <a href="https://detailurl.setting.custom-console-url-namespace.is.not.configured">op1st-pipelines</a></li> <li><b>PipelineRun:</b> <a href="https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/forgejo-mcp-on-pull-request-mlp9s">forgejo-mcp-on-pull-request-mlp9s</a></li> </ul> <hr> <h4>Task Statuses:</h4> <table> <tr><th>Status</th><th>Duration</th><th>Name</th></tr> <tr> <td>Succeeded</td> <td>14 seconds</td><td> [fetch-source](https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/forgejo-mcp-on-pull-request-mlp9s/logs/fetch-source) </td></tr> <tr> <td>Succeeded</td> <td>2 minutes</td><td> [build-and-test](https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/forgejo-mcp-on-pull-request-mlp9s/logs/build-and-test) </td></tr> <tr> <td>Succeeded</td> <td>19 seconds</td><td> [commit-title-check](https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/forgejo-mcp-on-pull-request-mlp9s/logs/commit-title-check) </td></tr> </table>
Sign in to join this conversation.
No reviewers
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
agentic-forges/forgejo-mcp!378
No description provided.