Skip to content

Provide scaler for Gitea Actions runners #8086

Description

@chris417

Proposal

Gitea Actions has no dedicated KEDA scaler. Today the options are the forgejo-runner scaler, which does not work against Gitea, or the github-runner scaler, which does work but is expensive against a self-hosted instance.

The forgejo-runner scaler calls /api/v1/admin/runners/jobs. Gitea has never implemented that endpoint — it returns 404 (verified against Gitea 1.27.2), and go-gitea/gitea#32862, which requested it, is still open. The response shapes also differ: Forgejo returns a bare array, Gitea returns {jobs, total_count}. Gitea also ignores the labels query parameter the scaler relies on, so even a path fix would silently return the page cap rather than a real count.

The github-runner scaler does work against Gitea (see #6765), because Gitea implements GitHub-compatible Actions endpoints. But it was written for an API with no instance-wide jobs endpoint, so it enumerates repos, then runs per repo, then jobs per run — roughly 1 + 2R + W requests per poll. Its enableEtags mitigation does not help here either, as Gitea sends no ETag on these endpoints.

Gitea exposes something GitHub does not: /api/v1/admin/actions/jobs, instance-wide, where total_count honours a status filter and repeated status parameters are OR-ed. That answers the scaling question in a single request.

Scaler Source

Gitea Actions job queue — /api/v1/admin/actions/jobs, plus the org, repo and user equivalents.

Scaling Mechanics

Count jobs whose status is queued or in_progress — both, so that replicas are not torn down the moment their jobs start running. Gitea accepts both statuses in a single call.

With no label filter, read total_count: one request per poll regardless of queue size. With labels, Gitea has no server-side filter for this endpoint, so the scaler pages and matches client-side. Page size is capped by MAX_RESPONSE_ITEMS (50 by default) and pagination is bounded at 20 pages, logging a line when the bound is hit so the lower bound is never silent.

Scopes: global (admin), org, owner+repo, and the token owner's own jobs.

Authentication Source

Gitea access token supplied via TriggerAuthentication, scoped to match the level used: read:admin for global, read:organization, read:repository, or read:user.

Anything else?

I have a working implementation with unit tests, validated against a live Gitea 1.27.2 instance: the no-label path returned the correct count in exactly one request, and the label path paginated and stopped at the cap as designed. Happy to open a PR.

Related: #6488 (closed by the stale bot), #6765, go-gitea/gitea#32862.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status
    To Triage

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions