Local development¶
Prerequisites¶
- Go version from
go.mod(1.26+) - just for the recipe runner (
justfile) - golangci-lint for
just lint - Docker + Compose v2 for the full stack and smoke script
Common commands¶
just build # go build ./... with version ldflags
just test # go test -race ./...
just lint # golangci-lint run
cp config.example.yaml config.yaml
go run ./cmd/grex -config config.yaml
Helm chart (requires helm; e2e also needs Docker + kind or k3d):
just helm-lint # lint + template render
just helm-package # package into dist/charts/
just helm-e2e-kind # build image, kind cluster, install, smoke + helm test
just helm-e2e-k3d # same with k3d (k3s)
# or install into an existing cluster:
helm install grex ./deploy/charts/grex -n grex --create-namespace
See Deploy with Helm
and deploy/charts/smoke.sh --help.
Suggested workflow¶
- Create a branch from
main - Prefer TDD: package tests under
internal/... - Run
just testandjust lintbefore pushing - For OpAMP/TLS/gateway behavior, extend unit tests first; use compose smoke for multi-container confidence
- If you change metrics names/labels, update
observability docs and any golden compares
in
internal/metrics - If you change chart templates or values, run
just helm-lintand update admin/helm / reference/helm-chart
Config for local runs¶
- Plaintext OpAMP is fine for unit tests (
internal/testcertwhen TLS is needed) - Compose enables mTLS and
log.level: debug/jsonfor grex - UI poll interval defaults to 5s; lower it only if you are UI-polishing
- Compose runs two grex instances (
grex,grex-2) behind an Envoy least-connections tier (deploy/compose/envoy.yaml), soopamp-gateway's upstream connections actually spread across replicas — see Scaling with gateways.grex-2is reachable directly on host ports8081/9092/4321(same layout asgrex's8080/9090/4320) forgxcurl/debugging. - Want to poke around the UI or
/riveruiin a browser without installing a client cert?grex-browser(deploy/compose/grex-browser.yaml) has noui_tlsat all, plain HTTP: http://127.0.0.1:8082. Not part of the Envoy/gateway pool, but shares the same Postgres, so it shows the same fleet via the cross-replica DB merge. - If certs generated before this topology existed are still on disk
(
deploy/compose/certs/),gen-certs.sh's per-file idempotency means the server cert won't pick up the newgrex-2/envoySANs automatically — deletedeploy/compose/certs/server*.pem(or the whole directory) and rerungen-certsif TLS handshakes togrex-2or throughenvoyfail hostname verification. - Occasionally
smoke.shreports both gateway-relayed agents landing on one grex replica instead of splitting across both — this is expected, not a regression.opamp-gatewayopens its 2 upstream connections microseconds apart at startup, tighter than a TCP handshake, so Envoy'sLEAST_REQUESTactive-connection count sometimes has no signal yet for the second pick.smoke.shreports this, it doesn't fail on it; see the comments indeploy/compose/envoy.yamlanddeploy/compose/opamp-gateway.yamlfor why this is left as-is rather than worked around (switching toROUND_ROBINor raisingconnectionswould either give up the production LB policy's actual justification or just mask the race behind more trials).
Documentation site¶
pip install -r requirements-docs.txt
cp logo.png docs/assets/logo.png # workflow does this in CI
mkdocs serve
# http://127.0.0.1:8000
Strict build (as in CI; also packages the Helm chart into site/charts/ when
helm is on PATH):
IDE notes¶
- Module path:
github.com/dennisme/grex - Go 1.22+
ServeMuxmethod patterns (GET /api/agents/{id}) are required - Do not register pprof on
http.DefaultServeMux; telemetry uses grex’s mux