Skip to content

Configuration

The five controllers and the status-server share one configuration system; the agent-runner is deliberately different. There are no config files — configuration is flags and environment only, and the GitHub credentials are not configuration: they live in Secrets referenced by your Integration and Forge custom resources (secrets and CRs), read on demand through the Kubernetes API.

Flags, environment, precedence

Every controller flag --foo-bar is bound to the environment variable PATCHY_FOO_BAR (dashes become underscores, uppercased, PATCHY_ prefix — so --claude-agent-image is PATCHY_CLAUDE_AGENT_IMAGE). Precedence, highest first:

  1. An explicit flag on the command line
  2. The PATCHY_* environment variable
  3. The built-in default

In Kubernetes you configure patchy with environment, not flags: the Deployments pass nothing but the serve subcommand, and the PATCHY_* variables arrive via envFrom — one shared ConfigMap in the kustomize base, one ConfigMap per controller in the Helm chart. A key a given binary does not bind is simply ignored by that binary, which is why one ConfigMap can serve all five.

The agent-runner has no flags at all: it reads only PATCHY_* environment variables, injected into the Job pod by the job controllers. See agent-runner.

Shared flags (all five controllers)

From internal/cli.Options (persistent flags) plus the flags every serve command registers:

Flag Env Default Purpose
--listen-addr PATCHY_LISTEN_ADDR :8080 HTTP listen address — only the integration-controller's webhook server uses it
--log-level PATCHY_LOG_LEVEL warn Log level: debug, info, warn, or error
--namespace PATCHY_NAMESPACE $POD_NAMESPACE Namespace the patchy resources live in. Required (flag or POD_NAMESPACE)
--kubeconfig PATCHY_KUBECONFIG Kubeconfig path; empty = in-cluster config
--health-addr PATCHY_HEALTH_ADDR :8081 healthz/readyz probe listen address

Every binary also answers --version and --help. All five controllers run leader election (a coordination Lease named per controller, in --namespace) — insurance against a botched rollout racing two replicas, not a scaling mechanism; the Deployments stay single-replica.

The HTTP surface

Only two controllers serve anything beyond kubelet probes:

Endpoint Controller Purpose
POST /github/webhooks on --listen-addr integration-controller GitHub deliveries — 202 accepted, 204 ping, 401 bad signature, 503 queue full
POST /google-cloud/webhooks on --listen-addr integration-controller SCC notifications via Pub/Sub push, OIDC-validated
POST /wiz/webhooks on --listen-addr integration-controller Wiz automation-rule deliveries, bearer-token-validated
POST /generic/<name>/webhooks on --listen-addr integration-controller Generic integrations' findings, HMAC-validated per name
GET /artifacts/… on --artifact-addr source-controller The repository tarballs agent pods fetch (in-cluster only)
GET /healthz / GET /readyz on --health-addr every controller Liveness / readiness probes

Telemetry

PATCHY_TELEMETRY_DIR (environment-only, no flag) switches OpenTelemetry export to per-signal JSON files; otherwise standard OTEL_* variables select exporters. See Observability.

Per-binary reference