This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
@AGENTS.md
OpsLevel Runner is a Kubernetes-based job processor for OpsLevel. It polls for jobs from the OpsLevel API (or Faktory queue), spins up Kubernetes pods to execute commands, and streams logs back to OpsLevel.
All commands use Task and should be run from the repository root:
# Initial setup (installs tools, sets up go workspace)
task setup
# Build the binary (from src/ directory)
cd src && go build
# Run tests with coverage
task test
# Run a single test
cd src && go test -v ./pkg -run TestSanitizeLogProcessor
# Lint and format check
task lint
# Auto-fix formatting and linting issues
task fix
# Start local Faktory development environment
task start-faktoryTest a job against a local Kubernetes cluster:
cd src
OPSLEVEL_API_TOKEN=XXX go run main.go test -f job.yaml
# Or from stdin:
cat job.yaml | OPSLEVEL_API_TOKEN=XXX go run main.go test -f -Run an end-to-end test with Faktory and a local Kubernetes cluster:
# Terminal 1: Start Faktory server and worker
task start-faktory
# Terminal 2: Enqueue test jobs (requires Faktory running)
cd src && go run scripts/enqueue-test-jobs.go 50
# Monitor jobs at http://localhost:7420root.go- CLI configuration with Cobra/Viper, initializes logging, Sentry, and K8s clientrun.go- Main execution mode with two backends:- API mode (default): Polls OpsLevel GraphQL API for pending jobs, uses worker pool
- Faktory mode: Consumes jobs from Faktory queue
test.go- Local job testing against a K8s cluster
k8s.go-JobRunnercreates K8s pods, ConfigMaps, and PDBs to execute jobs. Each job gets an ephemeral pod with:- Init container that copies the runner binary
- Job container running the specified image with commands
- ConfigMap mounting custom scripts from job definition
api.go- GraphQL client wrapper for OpsLevel APIlogs.go-LogStreamerwith pluggableLogProcessorchain for stdout/stderr processingleaderElection.go- K8s lease-based leader election for pod scaling
Log processors form a pipeline that transforms job output:
sanitizeLogProcessor.go- Redacts sensitive variablesprefixLogProcessor.go- Adds timestampssetOutcomeVarLogProcessor.go- Parses::set-outcome-var key=valuedirectivesopslevelAppendLogProcessor.go- Batches and sends logs to OpsLevel APIfaktoryAppendJobLogProcessor.go/faktorySetOutcomeProcessor.go- Faktory-specific processors
- Graceful shutdown via context cancellation on SIGINT/SIGTERM
Environment variables (or CLI flags):
OPSLEVEL_API_TOKEN- Required for API authenticationOPSLEVEL_API_URL- API endpoint (default: https://api.opslevel.com)OPSLEVEL_JOB_POD_NAMESPACE- K8s namespace for job podsOPSLEVEL_JOB_POD_MAX_WAIT- Pod startup timeoutOPSLEVEL_JOB_POD_MAX_LIFETIME- Max job duration
- Uses
opslevel-goclient library (available as git submodule insrc/submodules/opslevel-go) - K8s client-go for cluster interaction
- Zerolog for structured logging
- Prometheus client for metrics