Skip to content

Latest commit

 

History

History
197 lines (141 loc) · 7.21 KB

File metadata and controls

197 lines (141 loc) · 7.21 KB

Contributing to k8s-httpcache

Thanks for your interest in contributing! This document covers everything you need to get started.

Prerequisites

  • Go 1.26+
  • Docker
  • kubectl
  • golangci-lint
  • hadolint for Dockerfile linting
  • Helm for chart linting
  • hurl for E2E test assertions
  • A Kubernetes cluster for E2E testing (the CI uses kind)
  • curl for HTTP assertions in E2E tests
  • jq for JSON assertions in E2E tests
  • oha (optional, only needed for the zero-downtime rollout test)

Local development setup

Clone the repository and build:

git clone https://github.com/HBTGmbH/k8s-httpcache.git
cd k8s-httpcache
go build .

Build a static Linux binary (matching the CI):

CGO_ENABLED=0 GOOS=linux go build -trimpath -ldflags '-s -w -extldflags "-static" -buildid=' -o k8s-httpcache .

Testing

Unit tests

go test -race ./...

The CI uses gotestsum for nicer output and JUnit reports:

gotestsum --format testdox -- -race ./...

Linting

Run all linting checks (aborts on first failure):

.github/test/lint-all.sh

The project uses golangci-lint with an extensive rule set (see .golangci.yml). Run it locally:

golangci-lint run

YAML files are linted with yamllint (config in .yamllint.yml), shell scripts with ShellCheck, and Markdown files with markdownlint-cli2 (config in .markdownlint-cli2.yaml):

yamllint --strict .
shellcheck .github/test/*.sh
npx --yes markdownlint-cli2 "**/*.md"

Dockerfiles are linted with hadolint and the Helm chart with helm lint:

hadolint .github/build/Dockerfile .github/test/*/Dockerfile
helm lint --strict charts/k8s-httpcache

The CI also runs govulncheck and deadcode detection:

go install golang.org/x/vuln/cmd/govulncheck@latest
govulncheck ./...

go install golang.org/x/tools/cmd/deadcode@latest
deadcode -test ./...

When modifying GitHub Actions workflows, run actionlint locally before pushing:

actionlint

E2E tests

The CI runs E2E tests against a kind cluster. To run them locally:

  1. Create a kind cluster:

    kind create cluster --name test --config .github/test/kind-config.yaml
  2. Build and load the test image:

    CGO_ENABLED=0 GOOS=linux go build -trimpath -ldflags '-s -w -extldflags "-static" -buildid=' -o k8s-httpcache .
    mkdir -p .docker-context
    cp k8s-httpcache .docker-context/
    docker build -f .github/test/varnish8/Dockerfile -t localhost/k8s-httpcache:test .docker-context
    kind load docker-image localhost/k8s-httpcache:test --name test
  3. Install ingress-nginx and deploy:

    kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml
    kubectl patch configmap -n ingress-nginx ingress-nginx-controller --type merge -p '{"data":{"upstream-keepalive-timeout":"5"}}'
    kubectl wait -n ingress-nginx --for=condition=ready pod --selector=app.kubernetes.io/component=controller --timeout=120s
    kubectl apply -f .github/test/manifest.yaml
    kubectl rollout status deployment/k8s-httpcache --timeout=120s
  4. Run all E2E tests (aborts on first failure):

    .github/test/test-all.sh

    Or run individual tests:

    .github/test/smoke-test.sh               # HTTP proxying, shard consistency
    .github/test/metrics-test.sh             # Prometheus metrics, broadcast fan-out
    .github/test/debounce-test.sh            # debounce coalescing and debounce-max
    .github/test/shard-test.sh               # shard distribution across pods
    .github/test/values-update-test.sh       # ConfigMap values live update
    .github/test/values-dir-update-test.sh   # values-dir (mounted volume) live update
    .github/test/vcl-update-test.sh          # VCL template live reload, retry & rollback
    .github/test/file-watch-disable-test.sh  # file-watch disable verification
    .github/test/drain-sessions-test.sh      # drain timing verification
    .github/test/drain-test.sh               # connection draining
    .github/test/topology-test.sh            # topology-aware routing
    .github/test/rollout-test.sh             # zero-downtime rollout (requires oha)

    metrics-test.sh automatically sets up kubectl port-forward for the metrics (:9101) and broadcast (:8088) ports if they are not already reachable, and cleans them up on exit.

  5. Quick rebuild cycle (no cluster recreation needed):

    mkdir -p .docker-context \
      && CGO_ENABLED=0 GOOS=linux go build -trimpath -ldflags '-s -w -extldflags "-static" -buildid=' -o k8s-httpcache . \
      && cp k8s-httpcache .docker-context/ \
      && docker build -t localhost/k8s-httpcache:test .docker-context -f .github/test/varnish8/Dockerfile \
      && kind load docker-image localhost/k8s-httpcache:test --name test \
      && kubectl rollout restart deployment/k8s-httpcache \
      && kubectl rollout status deployment/k8s-httpcache --timeout=120s
  6. Clean up:

    kind delete cluster --name test

Pull request workflow

  1. Fork and branch — Create a feature branch from main. Use a descriptive name (e.g. fix-backend-port-resolution, add-health-check-endpoint).

  2. Make your changes — Keep commits focused. Each commit should compile and pass tests.

  3. Run checks locally before pushing:

    go test -race ./...
    golangci-lint run
  4. Open a pull request against main. The PR description should explain what changed and why. Link any related issues.

  5. CI must pass — The Test and Build workflow runs unit tests, linting, govulncheck, deadcode analysis, a full build, and E2E tests. All checks must be green before merging.

  6. Review — A maintainer will review your PR. Please address feedback and keep the PR up to date with main.

Code style

  • Follow standard Go conventions (Effective Go, Go Code Review Comments).
  • The .golangci.yml enforces the project's style rules — if the linter is happy, the style is fine.
  • Use gofmt for formatting (enforced by CI).
  • VCL templates use << / >> delimiters by default (configurable via --template-delims).

Releasing

Releases are automated. When a tag matching v* is pushed to main, the CI builds multi-arch binaries and container images, creates checksums, and publishes a GitHub release with auto-generated release notes.