The Nebari Operator uses a Makefile generated by Kubebuilder that provides convenient commands for development, testing, and deployment. This document describes the available targets and how they're used in CI/CD.
The Makefile is located at the root of the repository and provides a consistent interface for common operations. It's used both locally during development and in GitHub Actions workflows to ensure consistency.
Generates WebhookConfiguration, ClusterRole, and CustomResourceDefinition objects.
make manifestsUsed in CI:
- ✅ PR builds (.github/workflows/build-pr.yml)
- ✅ Release workflow (.github/workflows/release.yml)
When to use: After modifying CRD types, RBAC markers, or webhook configurations.
Generates code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations.
make generateUsed in CI:
- ✅ PR builds
- ✅ Release workflow
When to use: After modifying API types in api/v1/.
Runs go fmt against code to ensure consistent formatting.
make fmtUsed in CI:
- ✅ PR builds (with validation)
- ✅ Release workflow (with validation)
When to use: Before committing code.
Runs go vet against code to find suspicious constructs.
make vetUsed in CI:
- ✅ PR builds
- ✅ Release workflow
When to use: Before committing code, as part of pre-commit checks.
Runs golangci-lint linter with full rule set.
make lintUsed in CI:
- ✅ PR builds
- ✅ Release workflow
Alternatives:
make lint-fix- Runs linter with auto-fixmake lint-config- Verifies linter configuration
Runs unit tests with coverage report.
make testUsed in CI:
- ✅ PR builds
- ✅ Release workflow
Output: Generates cover.out coverage profile.
When to use: After making any code changes, before committing.
Builds the manager binary for local testing.
make build
# Output: bin/managerUsed in CI: ❌ Not used (we use docker-build instead)
When to use: Testing locally without Docker.
Runs the controller from your host (outside cluster).
make runUsed in CI: ❌ Not used
When to use: Local development and debugging.
Builds the Docker image with the manager.
make docker-build IMG=quay.io/nebari/nebari-operator:devUsed in CI: ❌ Not directly (we use docker-build-push-action for multi-arch)
When to use: Building single-arch images locally.
Pushes the Docker image to a registry.
make docker-push IMG=quay.io/nebari/nebari-operator:devUsed in CI: ❌ Not directly (handled by docker-build-push-action)
When to use: After building an image locally.
Builds and pushes multi-architecture Docker images.
make docker-buildx IMG=quay.io/nebari/nebari-operator:v1.0.0Platforms: linux/arm64, linux/amd64, linux/s390x, linux/ppc64le
Used in CI: ❌ Not directly (we use docker-build-push-action)
When to use: Building multi-arch images locally (requires Docker Buildx).
Generates a consolidated YAML with CRDs and deployment.
Important: Always specify the IMG parameter to ensure correct image references in the generated manifests.
make build-installer IMG=quay.io/nebari/nebari-operator:v1.0.0Output: dist/install.yaml
Used in CI:
- ✅ Release workflow
- ✅ Generates installer with version-specific image tag
When to use: Creating installation artifacts for releases.
Note: The IMG parameter updates all image references in the generated YAML to use the specified image.
Installs CRDs into the Kubernetes cluster specified in ~/.kube/config.
make installUsed in CI: ❌ Not used
When to use: Installing CRDs during development.
Uninstalls CRDs from the Kubernetes cluster.
make uninstall
# Or ignore errors if CRDs don't exist:
make uninstall ignore-not-found=trueUsed in CI: ❌ Not used
When to use: Cleaning up after development.
Deploys the controller to the Kubernetes cluster.
make deploy IMG=quay.io/nebari/nebari-operator:latestUsed in CI: ❌ Not used (deployment is manual)
When to use: Testing the operator in a development cluster.
Removes the controller from the Kubernetes cluster.
make undeploy
# Or ignore errors:
make undeploy ignore-not-found=trueUsed in CI: ❌ Not used
When to use: Cleaning up after testing.
The Makefile automatically downloads and manages required tools in the bin/ directory.
- kustomize - For customizing Kubernetes manifests
- controller-gen - For generating CRDs and RBAC
- setup-envtest - For setting up test environment
- golangci-lint - For linting
Downloads kustomize locally if not present.
Downloads controller-gen locally if not present.
Downloads setup-envtest and configures test binaries.
Downloads golangci-lint locally if not present.
Note: These are automatically invoked by other targets when needed.
The PR build workflow (.github/workflows/build-pr.yml) uses:
make fmt- Validate formattingmake vet- Run static analysismake test- Run unit testsmake lint- Run lintermake manifests- Validate manifests are up to datemake generate- Validate generated code is up to date
The release workflow (.github/workflows/release.yml) uses:
make fmt- Validate formattingmake vet- Run static analysismake test- Run unit testsmake lint- Run lintermake manifests- Generate CRDs and RBACmake generate- Generate DeepCopy methodsmake build-installer- Create installation YAML
Before committing code:
make fmt # Format code
make vet # Run static analysis
make test # Run tests
make lint # Run linter
make manifests # Update manifests if needed
make generate # Update generated code if neededTip: Create a git pre-commit hook:
#!/bin/bash
# .git/hooks/pre-commit
make fmt && make vet && make test && make lintFor active development:
# 1. Make changes to code
vim api/v1/nebariapp_types.go
# 2. Update generated code
make manifests generate
# 3. Test locally
make test
# 4. Run the operator locally
make run
# 5. Or deploy to cluster
make deploy IMG=quay.io/nebari/nebari-operator:devBefore creating a release:
# 1. Ensure everything is up to date
make manifests generate
# 2. Run full test suite
make test
# 3. Run linter
make lint
# 4. Build and test installer
make build-installer IMG=quay.io/nebari/nebari-operator:v1.0.0
# 5. Test the installer
kubectl apply -f dist/install.yamlYou can override these variables when invoking make:
| Variable | Default | Description |
|---|---|---|
IMG |
nebari-operator:latest |
Docker image name and tag |
PLATFORMS |
linux/arm64,linux/amd64,... |
Platforms for docker-buildx |
CONTAINER_TOOL |
docker |
Container tool (docker or podman) |
ENVTEST_K8S_VERSION |
(auto-detected) | Kubernetes version for envtest |
Example:
make docker-build IMG=quay.io/nebari/nebari-operator:dev CONTAINER_TOOL=podmanTo add custom targets to the Makefile:
.PHONY: my-custom-target
my-custom-target: ## Description of what this does
@echo "Running custom target"
# Your commands hereThe ## comment makes it appear in make help output.
Make sure you have make installed:
# macOS
brew install make
# Ubuntu/Debian
sudo apt-get install build-essential
# Fedora/RHEL
sudo dnf install makeIf tools fail to download, clear the bin directory:
rm -rf bin/
make test # This will re-download toolsIf tests fail with envtest errors:
make setup-envtestThis ensures the test environment binaries are properly configured.
For Docker-related issues:
- Check Docker is running:
docker ps - Check credentials:
docker login quay.io - Use verbose output:
make docker-build V=1
- Release Process - How releases use the Makefile
- Quick Reference - Quick command reference
- Kubebuilder Book - Official Kubebuilder documentation
- Always run
make testbefore committing - Catch issues early - Use
make fmtto format code - Ensures consistency - Run
make manifests generateafter API changes - Keeps generated code in sync - Use
make lintfrequently - Catch potential issues before CI - Leverage
make help- See all available targets - Keep tools updated - Delete
bin/occasionally to get latest versions