Developer Quickstart — Day 1¶
The single happy path from a fresh clone to your first iterated change. Follow it top to bottom; each step gates the next. For the full reference see CONTRIBUTING.md (root) and makefile_reference.md.
Kind only. This project uses Kind (Kubernetes in Docker) for all dev/test/CI. minikube, k3s, Docker Desktop K8s, and friends are not supported. The operator always runs in-cluster — never
make dev-run(DNS resolution fails outside the cluster).
0. Prerequisites¶
Install these before you start. Versions are what CI runs against — older may work but is unsupported.
| Tool | Version | Why / check | Install |
|---|---|---|---|
| Docker | running daemon | image builds + Kind nodes; docker info must succeed |
docs.docker.com/get-docker |
| Go | 1.27 | matches go.mod (go 1.27.0) and CI (GO_VERSION: '1.27') |
golang.org/doc/install |
| Kind | 0.27.0+ | local Kubernetes; kind version |
brew install kind |
| kubectl | 1.36.x | talks to the Kind cluster | kubernetes.io/docs/tasks/tools |
| make + git | any | drives every workflow | pre-installed on macOS/Linux |
.tool-versions lists the tool versions for mise / asdf
(mise install pins them): Go 1.27.0, Kind 0.27.0, kubectl 1.36.0, kustomize
5.4.3, helm 3.16.0, golangci-lint 2.14.0. The Go-based tools (kustomize,
controller-gen, envtest, ginkgo, golangci-lint, etc.) are auto-downloaded into
bin/ by the Makefile at the versions pinned there (e.g. GINKGO_VERSION,
GOLANGCI_LINT_VERSION) — those are what CI uses, and you don't install them by
hand. Where the two disagree, the Makefile wins.
1. Clone¶
2. Verify your machine is ready¶
Checks that go, docker (+ running daemon), kubectl, kind, and make
are present, and fails with an install hint for anything missing. Fix what it
flags before continuing.
3. Bring up the dev environment¶
One command chains check-prereqs → dev-cluster (Kind cluster
neo4j-operator-dev + cert-manager v1.20.0 + ca-cluster-issuer) → install
(CRDs) → deploy-dev-local (builds neo4j-operator:dev, loads it into Kind,
deploys), then waits for the operator rollout. First run takes ~3 minutes
(image pulls); later runs reuse the cluster and are faster.
Confirm the operator is running:
kubectl get deploy -n neo4j-operator-dev neo4j-operator-controller-manager
make operator-logs # follow logs
4. Run the unit tests¶
Fast (~30s), no cluster needed — it spins up envtest in-process. This is your
inner feedback loop. make test-unit also runs fmt and vet as
prerequisites, so it doubles as a quick sanity gate before you commit.
5. Make a change and redeploy¶
Edit code under internal/, api/, or cmd/, then rebuild + redeploy:
For a tighter loop, use a watcher instead of re-running by hand:
make dev-watch— re-runsmanifests generate build deploy-dev-localon saves underapi/,internal/,cmd/(needswatchexecorfswatch).tilt up— live reload (~5s) with a web dashboard (needs Tilt).
If you touched
api/v1beta1/*_types.goor a+kubebuilder:rbac:marker, regenerate the derived artifacts (CRDs, RBAC, Helm chart, kustomize lists, OperatorHub bundle) or CI's drift gate will fail your PR:make sync-all # fast: every regeneration step, no bundle # or, before tagging a release: make ship-prep # sync-all + bundle + helm-lint + CSV coverageSee
## Generated artifactsinCLAUDE.mdfor the full source→artifact map.
6. Verify end-to-end (optional but recommended)¶
Deploys a minimal Neo4j Enterprise standalone (hack/smoke-test-standalone.yaml),
waits for Ready (up to 5 min), then cleans up — a quick real-cluster sanity
check. To run one integration test by name:
(Wraps Ginkgo --focus; assumes a cluster + operator already exist.)
7. Tear down¶
Deletes the neo4j-operator-dev Kind cluster and cleans up dev artifacts.
Essential make targets¶
make help lists the curated set; make help-all lists everything.
| Target | What it does |
|---|---|
make check-prereqs |
Verify go/docker/kubectl/kind/make are installed |
make dev-up |
Create Kind cluster + cert-manager + deploy operator (one command) |
make dev-down |
Tear the whole dev environment down |
make deploy-dev-local |
Rebuild image + reload into Kind + redeploy (~60s) |
make dev-watch |
Auto rebuild+redeploy on file saves (needs watchexec/fswatch) |
make test-unit |
Fast unit tests + fmt + vet, no cluster (~30s) |
make test-one TEST="..." |
Run a single integration test by name |
make smoke-test |
Deploy a standalone, assert it reaches Ready, clean up |
make sync-all |
Regenerate all derived artifacts (run after API/RBAC edits) |
make check-drift |
CI gate: regenerate + fail if any generated file is stale |
Before you push¶
make test-unitpasses (also runs fmt + vet).make lintpasses locally — CI runs the same golangci-lint config in itsGo Lintjob, so a failure there is a failed PR check.- If you touched API types or RBAC markers,
make sync-all(orship-prep) and commit the regenerated files — CI'scheck-driftjob blocks the PR otherwise. - Read AGENT-GUARDRAILS.md — the project invariants (no webhooks, Kind only, Enterprise only, V2_ONLY discovery, server-based architecture) are non-negotiable and partly machine-enforced.
- Conventional Commit messages (
feat:,fix:,docs:, …).
Run make install-hooks once to wire the pre-commit drift/fmt/lint/gitleaks
hooks (needs pre-commit on your PATH).