Developing

June 9, 2026 ยท View on GitHub

In this file you'll find all the references needed for you to start contributing code to the HTTP Add-on project.

Getting started

To get started, first fork this repository to your account. You'll need to have the following tools installed:

  • Go for development
  • golangci-lint for Go linting
  • ko for building container images and deploying
  • kustomize for generating Kubernetes manifests
  • Make for build automation
  • buf for protobuf code generation (optional, only needed when modifying proto files)
  • pre-commit for static checks (optional)

Setting up pre-commit hooks

Install pre-commit and golangci-lint, then register the git hooks:

pre-commit install --hook-type pre-commit --hook-type pre-push

This enables automatic static checks (formatting, linting, changelog validation, etc.) on git commit and git push as configured in .pre-commit-config.yaml. To run all checks manually: make pre-commit.

Prerequisites

Kubernetes cluster

You'll need a running Kubernetes cluster. You can use a cloud provider (AKS, GKE, EKS) or a local cluster like KinD, k3s, or Minikube.

KEDA

Install KEDA on your cluster before deploying the HTTP Add-on.

Makefile Reference

  • make build: Build all binaries locally
  • make test: Run unit tests
  • make lint: Run linter
  • make lint-fix: Run linter with auto-fix
  • make e2e-test-images: Build test images under test/images/ (needed for gRPC tests)
  • make e2e-test: Run all e2e tests against an existing cluster
  • make generate: Generate code (DeepCopy) and Kubernetes manifests (run after modifying CRD types or webhook configs)
  • make deploy: Build and deploy all components to the cluster
  • make deploy-interceptor: Build and deploy the interceptor
  • make deploy-operator: Build and deploy the operator
  • make deploy-scaler: Build and deploy the scaler
  • make pre-commit: Run all static checks

Local Development with ko

This project uses ko for building container images and deploying to Kubernetes. ko builds Go binaries and packages them into container images without requiring Docker, with automatic dependency caching for fast incremental builds.

make deploy builds from source and deploys the HTTP Add-on to your cluster. If you previously installed the HTTP Add-on via Helm, uninstall it first before using make deploy.

Set the KO_DOCKER_REPO environment variable for your target:

  • Local registry: export KO_DOCKER_REPO=localhost:<port>
  • KinD: export KO_DOCKER_REPO=kind.local (only works with Docker, not Podman)

After making code changes, deploy a single component:

make deploy-interceptor

Or deploy all components at once:

make deploy

ko will:

  1. Build the Go binary with dependency caching
  2. Create a container image with layer caching
  3. Push to the configured registry
  4. Apply manifests with resolved image references

Protobuf Code Generation

The gRPC e2e test image (test/images/grpc-echo/) uses protobuf. The proto definition and generated Go code live alongside the server in test/images/grpc-echo/proto/.

Code generation uses buf with protoc-gen-go and protoc-gen-go-grpc, all managed as Go tool dependencies in go.mod (no system-wide installation needed). The buf workspace is configured at the repo root (buf.yaml + buf.gen.yaml).

To regenerate after modifying proto files:

make generate-proto

The generated *.pb.go files are checked in. Commit them alongside any proto changes.

Running E2E Tests

E2E tests live in test/e2e/ and are organized by profile. Each profile groups tests that require a specific HTTP Add-on configuration. For example, the default profile covers standard routing and scaling behavior with the default configuration, while the tls profile tests TLS termination and requires the interceptor to be deployed with TLS certificates enabled.

Cluster setup

# Create a KinD cluster
kind create cluster

# Install all e2e dependencies and deploy the HTTP Add-on
make e2e-setup

# Or install individual dependencies (see Makefile for all targets)
make e2e-deps-otel-collector
make e2e-deps-jaeger

Test Images

Custom test images for e2e tests live under test/images/, each subdirectory is a standalone Go main package built with ko.

Build all test images and push them to $KO_DOCKER_REPO before running e2e tests that need them:

make e2e-test-images

Running tests

# Run all e2e tests (all profiles)
make e2e-test

# Run a specific profile
make e2e-test PROFILE=tls

# Run a specific test by name
make e2e-test PROFILE=default RUN=TestColdStart

# Run tests matching specific labels
make e2e-test E2E_ARGS="--labels=area=scaling"

# List tests without executing them
make e2e-test E2E_ARGS="--dry-run"

The PROFILE variable selects a test profile directory under test/e2e/ (e.g. PROFILE=tls runs ./test/e2e/tls/...). Each subdirectory in test/e2e/ is a profile. The RUN variable filters tests by name using Go's -run flag (supports regex, e.g. RUN=TestColdStart or RUN="TestHost|TestPath"). The E2E_ARGS variable passes flags to the e2e-framework via -args (e.g. --labels, --feature, --skip-labels, --dry-run).

Writing a new test

Add your test to the profile whose add-on configuration it needs (or propose a new profile if none fits).

Each test creates a feature spec with setup and assertions, then runs it against the profile's shared testenv. The test/helpers/ package provides a Framework that handles the common boilerplate: creating test apps, interceptor routes, scaled objects, sending requests, and waiting for expected replica counts. The framework also manages namespace lifecycle, so individual tests don't need explicit cleanup.

See test/e2e/default/cold_start_test.go for a complete example of this pattern.