KEDA adapter for auto-scaling runners https://carverauto.dev
  • Go 97.3%
  • Dockerfile 2.7%
Find a file
2026-07-14 17:44:57 +00:00
.forgejo/workflows ci: keep pull request checks daemonless 2026-07-14 12:29:28 -05:00
cmd/forgejo-keda-adapter adapter: restrict metrics to allowed repositories 2026-07-14 12:15:58 -05:00
examples/kubernetes Use ServiceRadar Harbor image path 2026-04-02 18:42:11 -05:00
.gitignore Add Go-based Forgejo KEDA adapter 2026-04-02 17:34:52 -05:00
.golangci.yml Add golangci-lint config and clean up adapter 2026-04-02 18:49:12 -05:00
Dockerfile Add Go-based Forgejo KEDA adapter 2026-04-02 17:34:52 -05:00
go.mod Add Go-based Forgejo KEDA adapter 2026-04-02 17:34:52 -05:00
LICENSE Add CI and release automation 2026-04-02 17:40:18 -05:00
README.md docs: describe daemonless pull request checks 2026-07-14 12:31:01 -05:00

Forgejo KEDA Adapter

forgejo-keda-adapter is a small Go service that converts Forgejo runner jobs into a single numeric metric for KEDA's metrics-api scaler.

It polls Forgejo's runner jobs API and exposes a KEDA-friendly response:

{"value":7,"jobs_total":7,"counted_statuses":["running","waiting"]}

The intended module and source location is:

code.carverauto.dev/carverauto/forgejo-keda-adapter

Why This Exists

Forgejo exposes runner jobs as a JSON list, not as a scalar metric. KEDA only needs a number. This adapter is the shim between those two shapes.

The pattern is:

  1. Query Forgejo for runner jobs.
  2. Count jobs in the statuses you care about.
  3. Return {"value": N} over HTTP.
  4. Point a KEDA metrics-api trigger at that endpoint.

No Prometheus exporter or Kubernetes custom metrics adapter is required.

Endpoints

  • GET /jobs
  • GET /healthz

Configuration

  • FORGEJO_JOBS_URL: required
  • FORGEJO_API_TOKEN: required
  • FORGEJO_COUNT_STATUSES: default waiting,running
  • FORGEJO_TIMEOUT_SECONDS: default 3
  • PORT: default 8080

If you only want queued jobs, set:

export FORGEJO_COUNT_STATUSES=waiting

Forgejo API Notes

This was proven against:

/api/v1/admin/runners/jobs

The adapter polls the unfiltered admin jobs API and can expose a pool-specific metric with /jobs?labels=label-a,label-b&repo_ids=2,5. Forgejo 15 reports each job's runner requirements in runs_on and its repository in repo_id. A filtered metric counts a job only when its status is configured, every runs_on value is present in the requested pool's advertised labels, and its repo_id is in the pool's explicit allowlist. Missing fields, invalid IDs, and empty requested filters fail closed instead of counting the job in an unrelated or more privileged pool.

Local Run

go run ./cmd/forgejo-keda-adapter

With env:

export FORGEJO_JOBS_URL='https://forgejo.example.com/api/v1/admin/runners/jobs'
export FORGEJO_API_TOKEN='replace-me'
export FORGEJO_COUNT_STATUSES='waiting,running'

Then:

curl http://127.0.0.1:8080/jobs
curl http://127.0.0.1:8080/healthz

Tests

go test ./...

Container Build

docker build -t forgejo-keda-adapter:dev .
docker run --rm -p 8080:8080 \
  -e FORGEJO_JOBS_URL='https://forgejo.example.com/api/v1/admin/runners/jobs' \
  -e FORGEJO_API_TOKEN='replace-me' \
  forgejo-keda-adapter:dev

Kubernetes Example

Example manifests live under examples/kubernetes:

  • deployment.yaml
  • service.yaml
  • scaledobject.yaml

The example ScaledObject targets one counted job per runner pod with delayed scale-down:

  • pollingInterval: 15
  • cooldownPeriod: 300
  • stabilizationWindowSeconds: 300
  • targetValue: 1

CI And Release Automation

This repo includes Forgejo Actions workflows under .forgejo/workflows:

  • ci.yml: runs go test ./... and builds the binary without exposing a Docker daemon to pull-request jobs
  • release.yml: on v* tags, builds a linux/amd64 release tarball, pushes the linux/amd64 container image to registry.carverauto.dev/serviceradar/forgejo-keda-adapter, and creates or updates a Forgejo release

Required secrets:

  • HARBOR_ROBOT_USERNAME
  • HARBOR_ROBOT_SECRET
  • FORGEJO_TOKEN

License

This project is licensed under MIT. See LICENSE.