# Build, Codegen & Repository Tools

> Make targets, the codegen.go shim, deepcopy/CRD generation, lint configuration, and the dev/tools scripts that power local development.

- Repository: kubernetes-sigs/agent-sandbox
- GitHub: https://github.com/kubernetes-sigs/agent-sandbox
- Human wiki: https://grok-wiki.com/public/wiki/kubernetes-sigs-agent-sandbox-c3f2597a654a
- Complete Markdown: https://grok-wiki.com/public/wiki/kubernetes-sigs-agent-sandbox-c3f2597a654a/llms-full.txt

## Source Files

- `Makefile`
- `codegen.go`
- `tools.mod`
- `dev/tools/client-gen-go.sh`
- `dev/tools/lint-api`
- `dev/tools/test-unit`
- `docs/development.md`

---

<details>
<summary>Relevant source files</summary>
The following files were used as context for generating this wiki page:
- [Makefile](Makefile)
- [codegen.go](codegen.go)
- [tools.mod](tools.mod)
- [dev/tools/client-gen-go.sh](dev/tools/client-gen-go.sh)
- [dev/tools/lint-api](dev/tools/lint-api)
- [dev/tools/test-unit](dev/tools/test-unit)
- [dev/tools/lint-go](dev/tools/lint-go)
- [dev/tools/fix-go-generate](dev/tools/fix-go-generate)
- [dev/tools/build-kal](dev/tools/build-kal)
- [dev/tools/.golangci.yaml](dev/tools/.golangci.yaml)
- [dev/tools/.golangci-kal.yml](dev/tools/.golangci-kal.yml)
- [dev/tools/client-gen-go.sh](dev/tools/client-gen-go.sh)
- [dev/tools/go.mod](dev/tools/go.mod)
- [dev/tools/shared/utils.py](dev/tools/shared/utils.py)
- [dev/tools/fix-boilerplate](dev/tools/fix-boilerplate)
- [dev/tools/update-toc](dev/tools/update-toc)
- [dev/tools/verify-toc](dev/tools/verify-toc)
- [docs/development.md](docs/development.md)
</details>

# Build, Codegen & Repository Tools

This page documents how `kubernetes-sigs/agent-sandbox` is built, how its generated code (CRDs, RBAC, deepcopy methods, typed clientsets/listers/informers) is produced, how Go and Kubernetes-API lint checks are configured, and how the `dev/tools/` Python helpers tie those steps together. The repository keeps developer tooling deliberately co-located: a single top-level `Makefile` exposes named targets that shell out to per-script entry points under `dev/tools/`, while a separate `tools.mod` / `dev/tools/go.mod` keeps developer-tool dependencies out of the production `go.mod`.

The flow matters because the controller's CRDs, RBAC manifests (under `k8s/` and `helm/`), `zz_generated.deepcopy.go`, and the typed clients under `clients/k8s/` are all derived from the Go API packages — they must be regenerated whenever `api/` or `extensions/` change, and the same generators are wired into both `make all` and CI.

## Make targets and the `make all` pipeline

The `Makefile` declares a single canonical orchestration target `all` that runs the full local-validation pipeline:

```make
all: fix-go-generate build lint-go lint-api test-unit toc-verify
```

Sources: [Makefile:1-2](Makefile)

Each phase is a thin shell-out to a script under `dev/tools/`, so the Makefile acts mostly as a dispatcher rather than encoding logic itself.

| Target | Action | Underlying tool |
|---|---|---|
| `fix-go-generate` | Runs all `//go:generate` directives | `dev/tools/fix-go-generate` ([Makefile:4-6](Makefile)) |
| `build` | Builds the controller binary to `bin/manager` with version ldflags | `go build` ([Makefile:27-29](Makefile)) |
| `lint-go` / `fix-go` | Runs `golangci-lint` (with or without `--fix`) | `dev/tools/lint-go` ([Makefile:70-76](Makefile)) |
| `lint-api` / `fix-api` | Runs Kube-API Linter (KAL) on `api/` and `extensions/api/` | `dev/tools/lint-api` ([Makefile:78-84](Makefile)) |
| `test-unit` | Runs Go and Python unit suites | `dev/tools/test-unit` ([Makefile:54-56](Makefile)) |
| `test-e2e` / `test-e2e-race` / `test-e2e-benchmarks` | Drives `dev/ci/presubmits/test-e2e` | `RACE` env toggles `-race` ([Makefile:58-68](Makefile)) |
| `deploy-kind` | Creates a kind cluster, pushes images, deploys controller | `dev/tools/create-kind-cluster`, `push-images`, `deploy-to-kube` ([Makefile:33-40](Makefile)) |
| `toc-update` / `toc-verify` | Updates/verifies KEP table-of-contents using `mdtoc` | `dev/tools/update-toc`, `dev/tools/verify-toc` ([Makefile:128-134](Makefile)) |
| `generate-api-docs` | Generates `docs/api.md` from CRD markers | `crd-ref-docs` ([Makefile:10-15](Makefile)) |
| `release-promote` / `release-publish` / `release-manifests` / `release-python-sdk` | Tag/publish flows; require `TAG=` | `dev/tools/tag-promote-images`, `dev/tools/release`, `dev/tools/release-python` ([Makefile:98-126](Makefile)) |
| `clean` | Removes `dev/tools/tmp` and `bin/manager` | (none) ([Makefile:136-139](Makefile)) |

### Version ldflags

The `build` target injects build metadata into `internal/version` via linker flags. `GIT_VERSION`, `GIT_SHA`, and `BUILD_DATE` are computed from `git describe`/`git rev-parse`/`date -u`, and stamped through `-X` flags into `sigs.k8s.io/agent-sandbox/internal/version`:

```make
VERSION_PKG := sigs.k8s.io/agent-sandbox/internal/version
LD_FLAGS := -s -w -X $(VERSION_PKG).gitVersion=$(GIT_VERSION) \
    -X $(VERSION_PKG).gitSHA=$(GIT_SHA) \
    -X $(VERSION_PKG).buildDate=$(BUILD_DATE)
```

Sources: [Makefile:17-29](Makefile)

## The `codegen.go` shim and `tools.mod`

`codegen.go` is a tiny, otherwise-empty file at the repo root whose sole purpose is to host project-wide `//go:generate` directives. The package compiles as part of the module but contributes no runtime code:

```go
// This file just exists as a place to put //go:generate directives that should apply to the entire project
package agentsandbox
```

Sources: [codegen.go:15-17](codegen.go)

It declares eight `controller-gen` invocations plus the clientset script:

```go
//go:generate go tool -modfile=tools.mod sigs.k8s.io/controller-tools/cmd/controller-gen object crd:maxDescLen=0 paths=./api/... output:crd:dir=k8s/crds
//go:generate go tool -modfile=tools.mod sigs.k8s.io/controller-tools/cmd/controller-gen object crd:maxDescLen=0 paths=./extensions/... output:crd:dir=k8s/crds
//go:generate go tool -modfile=tools.mod sigs.k8s.io/controller-tools/cmd/controller-gen paths=./controllers/... output:rbac:dir=k8s rbac:roleName=agent-sandbox-controller,fileName=rbac.generated.yaml
//go:generate go tool -modfile=tools.mod sigs.k8s.io/controller-tools/cmd/controller-gen paths=./extensions/controllers/... output:rbac:dir=k8s rbac:roleName=agent-sandbox-controller-extensions,fileName=extensions-rbac.generated.yaml
//go:generate go tool -modfile=tools.mod sigs.k8s.io/controller-tools/cmd/controller-gen object crd:maxDescLen=0 paths=./api/... output:crd:dir=helm/crds
//go:generate go tool -modfile=tools.mod sigs.k8s.io/controller-tools/cmd/controller-gen object crd:maxDescLen=0 paths=./extensions/... output:crd:dir=helm/crds
//go:generate go tool -modfile=tools.mod sigs.k8s.io/controller-tools/cmd/controller-gen paths=./controllers/... output:rbac:dir=helm/templates rbac:roleName=agent-sandbox-controller,fileName=rbac.generated.yaml
//go:generate go tool -modfile=tools.mod sigs.k8s.io/controller-tools/cmd/controller-gen paths=./extensions/controllers/... output:rbac:dir=helm/templates rbac:roleName=agent-sandbox-controller-extensions,fileName=extensions-rbac.generated.yaml
//go:generate ./dev/tools/client-gen-go.sh
```

Sources: [codegen.go:20-28](codegen.go)

Two design choices are worth calling out:

1. **`go tool -modfile=tools.mod`** invokes `controller-gen` from a sibling module file, not from `go.mod`. `tools.mod` declares it as a Go tool: `tool sigs.k8s.io/controller-tools/cmd/controller-gen` ([tools.mod:97](tools.mod)). That keeps `controller-tools`, `code-generator`, and `gengo` out of the production module while still pinning their versions reproducibly.
2. **Each `paths=...` invocation emits to two output trees** (`k8s/...` and `helm/...`). The repository deliberately duplicates the generated CRDs and RBAC into both a raw manifest tree (`k8s/crds`, `k8s/rbac.generated.yaml`) and the Helm chart tree (`helm/crds`, `helm/templates/...`). The matching files under those trees (e.g., `k8s/crds/agents.x-k8s.io_sandboxes.yaml`) are written by the `object` + `crd` generators; deepcopy methods land alongside the API types as `zz_generated.deepcopy.go` ([api/v1beta1/zz_generated.deepcopy.go:1-5](api/v1beta1/zz_generated.deepcopy.go)).

### `controller-gen` generators in use

| Generator | Inputs | Outputs |
|---|---|---|
| `object` | `./api/...`, `./extensions/...` | `zz_generated.deepcopy.go` next to API types |
| `crd:maxDescLen=0` | same | `k8s/crds/*.yaml`, `helm/crds/*.yaml` |
| `rbac:roleName=agent-sandbox-controller` | `./controllers/...` | `k8s/rbac.generated.yaml`, `helm/templates/rbac.generated.yaml` |
| `rbac:roleName=agent-sandbox-controller-extensions` | `./extensions/controllers/...` | `k8s/extensions-rbac.generated.yaml`, `helm/templates/extensions-rbac.generated.yaml` |

`maxDescLen=0` disables the default truncation of CRD description text, so the on-cluster schemas keep full kubebuilder-doc descriptions.

Sources: [codegen.go:20-28](codegen.go), [k8s/crds/](k8s/crds), [helm/crds/](helm/crds)

### `fix-go-generate`

`make fix-go-generate` delegates to `dev/tools/fix-go-generate`, which simply runs `go generate -v ./...` from the repo root so every package's `//go:generate` lines (in practice just `codegen.go`) fire:

```python
subprocess.check_call(["go", "generate", "-v", "./..."], cwd=repo_root)
```

Sources: [dev/tools/fix-go-generate:30-31](dev/tools/fix-go-generate)

## Typed-client generation: `client-gen-go.sh`

The last `//go:generate` directive in `codegen.go` is a shell script that produces Kubernetes typed clients, listers, and informers for both the core and extensions API groups. It bootstraps the `k8s.io/code-generator` binaries through `go run -modfile=tools.mod`, so they too come from the dev-only tool module rather than `go.mod`.

```bash
CMD="go run -modfile=tools.mod k8s.io/code-generator"
API_PKG="sigs.k8s.io/agent-sandbox/api/v1beta1"
CLIENT_PKG="sigs.k8s.io/agent-sandbox/clients/k8s"
```

Sources: [dev/tools/client-gen-go.sh:24-26](dev/tools/client-gen-go.sh)

It then invokes three generators in sequence per API group:

```text
client-gen   --output-dir clients/k8s/clientset            --clientset-name versioned   --input <API_PKG>
lister-gen   --output-dir clients/k8s/listers              <API_PKG>
informer-gen --output-dir clients/k8s/informers
             --versioned-clientset-package <CLIENT_PKG>/clientset/versioned
             --listers-package <CLIENT_PKG>/listers        <API_PKG>
```

The same three calls run again for `extensions/api/v1beta1`, writing into `clients/k8s/extensions/{clientset,listers,informers}`. Finally, the script applies repo-standard Apache license headers to the freshly generated files:

```bash
echo "Fixing license headers..."
"${SCRIPT_ROOT}"/dev/tools/fix-boilerplate
```

Sources: [dev/tools/client-gen-go.sh:24-79](dev/tools/client-gen-go.sh)

`fix-boilerplate` walks the tree and prepends the Apache 2.0 header (skipping `**/zz_generated.*` and `site/**`) using the `dev/tools/shared/headers.py` helper:

```python
excludes = [
    "**/zz_generated.*",
    "**/site/**",
]
headers.apply_headers_to_tree(repo_root, excludes=excludes)
```

Sources: [dev/tools/fix-boilerplate:31-38](dev/tools/fix-boilerplate), [dev/tools/shared/headers.py:40-72](dev/tools/shared/headers.py)

### End-to-end codegen view

```mermaid
flowchart LR
    subgraph Sources["Source packages"]
        APIv["api/v1beta1/*.go"]
        EXTAPI["extensions/api/v1beta1/*.go"]
        CTL["controllers/**.go"]
        EXTCTL["extensions/controllers/**.go"]
    end

    subgraph Driver["go generate driver"]
        CODEGEN["codegen.go<br/>//go:generate"]
        FIXGEN["dev/tools/fix-go-generate"]
    end

    subgraph Tools["tools.mod (dev-only deps)"]
        CG["controller-gen<br/>(object / crd / rbac)"]
        CODEGEN_K["k8s.io/code-generator<br/>(client/lister/informer)"]
    end

    subgraph Outputs["Generated artifacts"]
        DC["api/**/zz_generated.deepcopy.go"]
        CRDK["k8s/crds/*.yaml"]
        CRDH["helm/crds/*.yaml"]
        RBACK["k8s/*rbac.generated.yaml"]
        RBACH["helm/templates/*rbac.generated.yaml"]
        CLS["clients/k8s/{clientset,listers,informers}"]
        EXTCLS["clients/k8s/extensions/{clientset,listers,informers}"]
    end

    FIXGEN -->|go generate ./...| CODEGEN
    CODEGEN --> CG
    CODEGEN --> CODEGEN_K
    APIv --> CG
    EXTAPI --> CG
    CTL --> CG
    EXTCTL --> CG
    CG --> DC
    CG --> CRDK
    CG --> CRDH
    CG --> RBACK
    CG --> RBACH
    APIv --> CODEGEN_K
    EXTAPI --> CODEGEN_K
    CODEGEN_K --> CLS
    CODEGEN_K --> EXTCLS
    CLS -->|fix-boilerplate| CLS
    EXTCLS -->|fix-boilerplate| EXTCLS
```

Sources: [codegen.go:20-28](codegen.go), [dev/tools/client-gen-go.sh:24-79](dev/tools/client-gen-go.sh), [dev/tools/fix-go-generate:30-31](dev/tools/fix-go-generate), [tools.mod:88-97](tools.mod)

## Lint configuration

The repository runs two distinct Go linters: a general-purpose `golangci-lint` and a Kubernetes-API-specific KAL (Kube-API Linter). Both pull their binaries from the dev tool module via `go tool -modfile=dev/tools/go.mod`.

### General Go lint (`lint-go`)

`dev/tools/lint-go` shells out to `golangci-lint` with the repo's config:

```python
args = ["golangci-lint", "run", f"--config={repo_root}/dev/tools/.golangci.yaml"]
if "--fix" in sys.argv:
    args.append("--fix")
result = subprocess.run(utils.go_tool_args(*args), cwd=repo_root)
```

Sources: [dev/tools/lint-go:22-28](dev/tools/lint-go)

The helper `utils.go_tool_args` prepends `go tool -modfile=<repo>/dev/tools/go.mod`:

```python
def go_tool_args(*args):
    repo_root = get_repo_root()
    return ["go", "tool", f"-modfile={repo_root}/dev/tools/go.mod", *args]
```

Sources: [dev/tools/shared/utils.py:64-67](dev/tools/shared/utils.py)

`.golangci.yaml` enables a curated set of linters (`depguard`, `revive`, `staticcheck`, `govet`, `errcheck`, `ineffassign`, `unparam`, `testifylint`, `sloglint`, `misspell`, modernize, …) and bans `import "sort"` via `depguard`, steering callers to the `slices` package. Formatters (`gofmt`, `goimports`) are configured alongside, with `third_party`, `builtin`, and `examples` excluded:

```yaml
depguard:
  rules:
    forbid-pkg-errors:
      deny:
        - pkg: sort
          desc: Should be replaced with slices package
```

Sources: [dev/tools/.golangci.yaml:1-55](dev/tools/.golangci.yaml)

### Kube-API Linter (`lint-api`)

KAL is shipped as a `golangci-lint` plugin and must be compiled into a custom golangci-lint binary. `dev/tools/lint-api` builds it on first use, then runs it against the API trees only:

```python
kal_binary = os.path.join(tools_dir, "tmp", "bin", "golangci-kube-api-linter")
if not os.path.exists(kal_binary):
    build_script = os.path.join(tools_dir, "build-kal")
    build_result = subprocess.run([build_script], cwd=repo_root)
...
args = [kal_binary, "run", "--config", kal_config]
if "--fix" in sys.argv:
    args.append("--fix")
args.extend(["./api/...", "./extensions/api/..."])
```

Sources: [dev/tools/lint-api:31-53](dev/tools/lint-api)

`build-kal` compiles the custom binary using `golangci-lint custom`:

```bash
(cd "${SCRIPT_DIR}" && go tool -modfile "${SCRIPT_DIR}/go.mod" golangci-lint custom)
```

Sources: [dev/tools/build-kal:19-26](dev/tools/build-kal)

The output lives at `dev/tools/tmp/bin/golangci-kube-api-linter` — note that `make clean` removes `dev/tools/tmp` to force a rebuild ([Makefile:136-139](Makefile)).

`.golangci-kal.yml` disables all default linters (`default: none`) and enables only `kubeapilinter` with an explicit whitelist of KAL checks for CRD authoring discipline. The list includes:

| KAL linter | Enforces |
|---|---|
| `nobools` / `nofloats` | No `bool`/`float` fields in API types |
| `commentstart` / `jsontags` | godoc starts with field name, all fields have JSON tags |
| `optionalorrequired` | Every field is marked `+optional` or `+required` |
| `statussubresource` / `statusoptional` | `status` is a subresource with optional fields |
| `nophase` / `nomaps` / `nonullable` | No `phase` field, no maps, no `nullable` markers |
| `conflictingmarkers` | `default` cannot coexist with `required` |
| `duplicatemarkers` / `uniquemarkers` | No duplicate or non-unique markers on a field |
| `forbiddenmarkers` | Bans `PreserveUnknownFields`, `XPreserveUnknownFields`, `EmbeddedResource`, etc. |

Sources: [dev/tools/.golangci-kal.yml:11-57](dev/tools/.golangci-kal.yml)

Path rules restrict KAL to `api/.*` paths, and explicitly exclude `_test.go` and `zz_generated.*\.go$` so generated deepcopy code is not flagged:

```yaml
exclusions:
  generated: strict
  paths:
    - _test\.go
    - zz_generated.*\.go$
  rules:
  - path-except: "api/.*"
    linters:
      - kubeapilinter
```

Sources: [dev/tools/.golangci-kal.yml:58-68](dev/tools/.golangci-kal.yml)

## Unit tests: `test-unit`

`dev/tools/test-unit` is the single entry point used by both `make test-unit` and CI. It runs Go and Python suites and emits JUnit XML files under `bin/`.

### Go tests

It enumerates all packages with `go list ./...`, filters out `test/e2e`, then runs them under `gotestsum` (a Go test wrapper that produces JUnit), with `-race` enabled:

```python
go_list_output = subprocess.check_output(["go", "list", "./..."], cwd=repo_root, text=True)
filtered_packages = [pkg for pkg in packages if "test/e2e" not in pkg]

result = subprocess.run(utils.go_tool_args(
    "gotestsum",
    f"--junitfile={repo_root}/bin/unit-junit.xml",
    "--",
    "-race",
    *filtered_packages
), cwd=repo_root)
```

Sources: [dev/tools/test-unit:37-53](dev/tools/test-unit)

`gotestsum` is provided by `tool gotest.tools/gotestsum` in `dev/tools/go.mod` ([dev/tools/go.mod:5-10](dev/tools/go.mod)), so it runs via the same `go tool -modfile=…` mechanism as the other dev tools.

### Python tests

Two Python suites under `clients/python/agentic-sandbox-client/` are exercised inside a clean per-suite venv:

```python
PYTHON_TEST_SUITES = [
    {"name": "sandbox-router",     "dir": "clients/python/.../sandbox-router",     "requirements": "requirements.txt"},
    {"name": "k8s-agent-sandbox",  "dir": "clients/python/.../k8s_agent_sandbox", "requirements": "requirements.txt"},
]
```

For each suite the runner:

1. Wipes any existing venv at `bin/python-venv-<name>` (verifying `pyvenv.cfg` exists before removal, to avoid trashing an unrelated directory).
2. Creates a fresh venv with `python -m venv`.
3. Installs `requirements.txt`; if absent and the suite is `k8s-agent-sandbox`, installs the package itself with `pip install -e .[test]`.
4. Installs `pytest` separately.
5. Runs `pytest` with `--junitxml=bin/python-<name>-junit.xml -v`.

Sources: [dev/tools/test-unit:55-108](dev/tools/test-unit)

The runner returns the Go exit code first if non-zero, otherwise the Python exit code — both must pass for `make test-unit` to succeed.

## Shared helpers and tool module layout

The Python scripts under `dev/tools/` share a small library:

| Module | Purpose |
|---|---|
| `shared/utils.py` | `get_repo_root()`, `go_tool_args()`, image-tag/git helpers used by deploy/release scripts |
| `shared/headers.py` | Apache-header insertion engine used by `fix-boilerplate` |
| `shared/golang.py` | Walks the repo's Go modules (used by `fix-gomod`, `fix-go-format`) |
| `shared/git_ops.py` | Git helpers used by release/tagging flows |

Sources: [dev/tools/shared/utils.py:21-67](dev/tools/shared/utils.py), [dev/tools/shared/headers.py:23-72](dev/tools/shared/headers.py), [dev/tools/fix-boilerplate:31-38](dev/tools/fix-boilerplate), [dev/tools/fix-gomod:24-39](dev/tools/fix-gomod)

A compact map of the repository's module/tool surfaces:

```text
repo/
├── go.mod              -> production module (controller, controllers, api)
├── tools.mod           -> codegen tools: controller-gen, code-generator
│                          (used by //go:generate via `go tool -modfile=tools.mod`)
├── codegen.go          -> hosts all //go:generate directives
├── api/                -> kubebuilder-marked source for CRDs / deepcopy
├── extensions/api/     -> same, for extensions group
├── clients/k8s/        -> code-generator output (clientset/listers/informers)
├── k8s/crds/, k8s/*rbac.generated.yaml         -> raw manifest output
├── helm/crds/, helm/templates/*rbac.generated.yaml -> Helm chart output
└── dev/tools/
    ├── go.mod          -> lint/test tools: golangci-lint, gotestsum,
    │                       kube-api-linter, benchstat
    ├── .golangci.yaml  -> general Go lint config
    ├── .golangci-kal.yml -> KAL config (CRD conventions)
    ├── client-gen-go.sh -> drives client/lister/informer-gen
    ├── fix-go-generate, fix-boilerplate, fix-go-format, fix-gomod
    ├── lint-go, lint-api, build-kal
    ├── test-unit, test-e2e
    ├── update-toc, verify-toc
    └── shared/         -> Python helpers
```

Sources: [tools.mod:1-97](tools.mod), [dev/tools/go.mod:1-12](dev/tools/go.mod), [codegen.go:20-28](codegen.go)

The three-module split is the key invariant: production code depends only on `go.mod`; CRD/client codegen tools come from `tools.mod`; lint/test tools come from `dev/tools/go.mod`. Each has its own `tool` block so `go tool -modfile=<path>` is the universal invocation pattern.

## Documentation utilities

Two small Bash scripts maintain table-of-contents stability on KEP docs:

- `update-toc` (`make toc-update`) installs `sigs.k8s.io/mdtoc@v1.1.0` into a `mktemp -d` directory (to avoid mutating the project go.mod/go.sum), then runs it across `docs/keps/**.md` with `--max-depth=5`, filtering out the names listed in `dev/tools/.notableofcontents`. Sources: [dev/tools/update-toc:22-52](dev/tools/update-toc)
- `verify-toc` (`make toc-verify`) does the same install, then runs `mdtoc --dryrun` to fail when the TOCs are out of date. The two scripts share a `TOOL_VERSION=v1.1.0` constant with a "keep in sync" comment. Sources: [dev/tools/verify-toc:21-53](dev/tools/verify-toc)

`generate-api-docs` follows the same temp-install pattern for `github.com/elastic/crd-ref-docs`, rendering `docs/api.md` from the CRD markers ([Makefile:10-15](Makefile)).

## Putting it together

The combined effect is that a maintainer editing an API type only needs to run `make all` ([Makefile:1-2](Makefile)) to:

1. Re-run all `//go:generate` directives → updated deepcopy, CRDs (in both `k8s/` and `helm/`), RBAC, and typed clients with license headers fixed up.
2. Rebuild the controller binary with embedded version metadata.
3. Run general Go lint (`golangci-lint`) and the CRD-convention lint (KAL) against `api/`/`extensions/api/`.
4. Run Go + Python unit tests with race detection and JUnit output.
5. Verify KEP TOCs are current.

The same scripts run under Prow CI (presubmits and postsubmits) so local and CI behavior remain identical, anchored on `dev/tools/` and the two side-car module files (`tools.mod`, `dev/tools/go.mod`) that isolate developer tooling from production dependencies.

Sources: [Makefile:1-2](Makefile), [codegen.go:20-28](codegen.go), [dev/tools/client-gen-go.sh:24-79](dev/tools/client-gen-go.sh), [dev/tools/test-unit:37-108](dev/tools/test-unit), [docs/development.md:34-49](docs/development.md)
