feat: take advantage of Forgejo 15.0 Actions/runner changes #30

Open
opened 2026-05-01 06:04:48 +00:00 by rcsheets · 0 comments
Owner

Forgejo 15.0 (release notes, full changelog) introduced several runner-side changes that the operator could meaningfully exploit. Grouping by impact for triage.

High-impact opportunities

Ephemeral runners

Forgejo now supports runners that execute exactly one job and then terminate, with their registration credentials auto-deleted. The runner exposes a new one-job command for this mode, and registration accepts an "ephemeral": true parameter.

This is a near-perfect fit for a Kubernetes operator: rather than maintaining long-lived Deployments of runners, the operator could create a Job (or pod) per queued workflow run, scale to zero when idle, and never reuse a pod across jobs. Eliminates "leaky state between jobs" classes of bugs (which is partly why we currently rebuild the storage path on every run in pr-reviewer's build-push).

Worth designing for explicitly — what does a RunnerPool CR look like when "pool" really means "controller for ephemeral runner Jobs"? Do we keep the long-lived pool model alongside as a fallback?

OIDC workload identity federation

Runners can now obtain short-lived signed JWTs to authenticate to external systems (Harbor, OpenBao, etc.) instead of relying on static secrets baked into the runner pod or pulled from OpenBao at job start. Requires Forgejo Runner v12.5.0+.

If we adopt this, the OpenBao step in pr-reviewer's build-push.yaml (and equivalents) gets a lot simpler — no more "fetch a service-account token, exchange it for a Bao token, exchange that for Harbor creds, write a docker config." The runner mints a JWT, exchanges with OpenBao directly via OIDC auth method, done. Adjacent work in OpenBao to add a JWT/OIDC auth role for the Forgejo issuer.

New HTTP API for runner registration

Forgejo 15.0 adds a proper HTTP API endpoint for runner registration and deprecates the old token-acquisition endpoints. The operator currently relies on the older flow (presumably). Migrate before the deprecated endpoints are removed in a future release.

Medium-impact / hygiene

  • Pin runner image to ≥ v12.5.0: required for OIDC and one-job. Audit current pinned versions in runner pool definitions; bump as needed.
  • Error handling: 403 → 404: Forgejo now returns 404 (not 403) for resources the token can't see, to prevent enumeration. Any operator code that distinguishes "missing" from "forbidden" needs adjustment.
  • Permission scope tightening: template generation/deletion APIs and admin-level permissions on repo-specific tokens. Verify the operator's service token doesn't rely on now-removed admin scopes.

Low-impact / informational

  • Runner search by UUID + new filter/visibility flags on runner list endpoints — useful for reconciliation logic when checking whether currently-registered runners match desired CR state.
  • Multiple-tasks-per-fetch and job-specific runner requests are runner-internal optimizations; nothing for the operator to wire up, but they shift the cost model in favor of larger pools / longer-lived runners staying interesting alongside ephemeral ones.
  • Workflow-side changes (reusable workflow expansion, dispatch input limit raised to 100, scheduled workflow timezone, etc.) — workflow authors' concern, not the operator's, but worth keeping in mind when documenting.

Suggested ordering

  1. Bump runner image version to 12.5.x in the existing pool definitions. Smallest blast radius; unblocks everything below.
  2. Migrate registration to the new HTTP API. Pure plumbing change; preserves current architecture.
  3. Add ephemeral runner mode as a new option on the RunnerPool CR (alongside the existing long-lived shape).
  4. OIDC workload identity — design the OpenBao auth role first, then a workflow proof-of-concept (probably in pr-reviewer since it's the one with the most secret-handling), then expose via operator config.
Forgejo 15.0 ([release notes](https://forgejo.org/2026-04-release-v15-0/), [full changelog](https://codeberg.org/forgejo/forgejo/raw/branch/forgejo/release-notes-published/15.0.0.md)) introduced several runner-side changes that the operator could meaningfully exploit. Grouping by impact for triage. ## High-impact opportunities ### Ephemeral runners Forgejo now supports runners that execute exactly one job and then terminate, with their registration credentials auto-deleted. The runner exposes a new `one-job` command for this mode, and registration accepts an `"ephemeral": true` parameter. This is a near-perfect fit for a Kubernetes operator: rather than maintaining long-lived `Deployment`s of runners, the operator could create a `Job` (or pod) per queued workflow run, scale to zero when idle, and never reuse a pod across jobs. Eliminates "leaky state between jobs" classes of bugs (which is partly why we currently rebuild the storage path on every run in `pr-reviewer`'s build-push). Worth designing for explicitly — what does a `RunnerPool` CR look like when "pool" really means "controller for ephemeral runner Jobs"? Do we keep the long-lived pool model alongside as a fallback? ### OIDC workload identity federation Runners can now obtain short-lived signed JWTs to authenticate to external systems (Harbor, OpenBao, etc.) instead of relying on static secrets baked into the runner pod or pulled from OpenBao at job start. Requires Forgejo Runner v12.5.0+. If we adopt this, the OpenBao step in `pr-reviewer`'s `build-push.yaml` (and equivalents) gets a lot simpler — no more "fetch a service-account token, exchange it for a Bao token, exchange that for Harbor creds, write a docker config." The runner mints a JWT, exchanges with OpenBao directly via OIDC auth method, done. Adjacent work in OpenBao to add a JWT/OIDC auth role for the Forgejo issuer. ### New HTTP API for runner registration Forgejo 15.0 adds a proper HTTP API endpoint for runner registration and **deprecates** the old token-acquisition endpoints. The operator currently relies on the older flow (presumably). Migrate before the deprecated endpoints are removed in a future release. ## Medium-impact / hygiene - **Pin runner image to ≥ v12.5.0**: required for OIDC and `one-job`. Audit current pinned versions in runner pool definitions; bump as needed. - **Error handling: 403 → 404**: Forgejo now returns 404 (not 403) for resources the token can't see, to prevent enumeration. Any operator code that distinguishes "missing" from "forbidden" needs adjustment. - **Permission scope tightening**: template generation/deletion APIs and admin-level permissions on repo-specific tokens. Verify the operator's service token doesn't rely on now-removed admin scopes. ## Low-impact / informational - **Runner search by UUID** + new filter/visibility flags on runner list endpoints — useful for reconciliation logic when checking whether currently-registered runners match desired CR state. - **Multiple-tasks-per-fetch and job-specific runner requests** are runner-internal optimizations; nothing for the operator to wire up, but they shift the cost model in favor of larger pools / longer-lived runners staying interesting alongside ephemeral ones. - **Workflow-side changes** (reusable workflow expansion, dispatch input limit raised to 100, scheduled workflow timezone, etc.) — workflow authors' concern, not the operator's, but worth keeping in mind when documenting. ## Suggested ordering 1. Bump runner image version to 12.5.x in the existing pool definitions. Smallest blast radius; unblocks everything below. 2. Migrate registration to the new HTTP API. Pure plumbing change; preserves current architecture. 3. Add ephemeral runner mode as a new option on the `RunnerPool` CR (alongside the existing long-lived shape). 4. OIDC workload identity — design the OpenBao auth role first, then a workflow proof-of-concept (probably in `pr-reviewer` since it's the one with the most secret-handling), then expose via operator config.
Sign in to join this conversation.
No labels
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
brooktrails/forgejo-runner-operator#30
No description provided.