- AI agents: Automate bug fixes and repository tasks with minimal context
- Contributors: Humans using AI assistants or working directly on the codebase
- Maintainers: Ensure AI assistants follow project conventions and CI rules
AI agents should:
- Make atomic, minimal, and reversible changes.
- Prefer local analysis (
make build,make test,make lint) before proposing commits. - NEVER modify configuration, CI/CD, or release automation unless explicitly requested.
- Use
AGENTS.mdandMakefileas the source of truth for development commands. - Ignore the
clients/ui/directory — it has its own development workflow and is not covered here. - Follow the Kubeflow AI Policy, specifically:
- Include in the commit message:
Assisted-by: [Agent Name], orCo-authored-by: [Agent Name]. - Avoid automated responses/comments to the Pull Requests or Issues on GitHub.
- Include in the commit message:
Agents must NOT:
- Bypass tests or linters
- Introduce dependencies without updating
go.mod/go.sum(Go),pyproject.toml(Python), orpackage.json(TypeScript) - Generate or commit large autogenerated files (use the
gen/*Make targets instead) - Modify OpenAPI specs (
api/openapi/) without regenerating dependent code - Modify CRD schemas or API versions without explicit instruction
Before writing code, agents should:
- Read existing test cases and source files for pattern alignment
- Match import patterns and error-handling conventions from neighboring files
- Preserve existing logging style (uses
golang/glog) - Understand the module boundary — this is a Go workspace with multiple
go.modfiles - Review OpenAPI specs in
api/openapi/before changing API structures - Call out any breaking changes introduced and follow the deprecation policy
For additional context see the Model Registry documentation.
api/openapi/ # OpenAPI specs (model-registry.yaml, catalog.yaml)
├── src/ # Source YAML files merged into final specs
catalog/ # Catalog service — federated model discovery
├── clients/python/ # Python client for catalog API (Poetry)
├── internal/ # Catalog business logic & server
├── pkg/openapi/ # Generated OpenAPI client for catalog
├── Makefile # Catalog-specific build/test targets
clients/ # Client libraries and UI
├── python/ # Python client for model-registry API (Poetry)
└── ui/ # React UI + Go BFF (separate workflow, see UI Development below)
├── bff/ # Backend-for-Frontend (Go)
└── frontend/ # React/TypeScript frontend
cmd/ # CLI entry points
├── controller/ # Kubernetes controller for ModelRegistry CRDs
├── csi/ # Container Storage Interface (storage-initializer)
internal/ # Core server implementation (NOT importable externally)
├── apiutils/ # API utility functions
├── converter/ # Type converters (generated via goverter)
│ └── generated/ # Auto-generated converter code
├── core/ # Business logic / domain services
├── datastore/ # Database layer
│ └── embedmd/ # Embedded migrations (MySQL & PostgreSQL)
├── db/ # Database service layer & query filtering
│ ├── filter/ # Query filter parser (participle-based)
│ └── service/ # DB-backed service implementations
├── defaults/ # Default value helpers
├── mapper/ # Request/response mappers
├── proxy/ # REST proxy logic
├── server/ # HTTP server setup
│ └── openapi/ # Generated OpenAPI server stubs
├── testutils/ # Shared test utilities
└── tls/ # TLS configuration
pkg/ # Public Go packages (importable by others)
├── api/ # Public API interfaces
├── openapi/ # Generated OpenAPI client for model-registry
└── inferenceservice-controller/ # InferenceService controller logic
jobs/ # Background jobs
└── async-upload/ # Async model upload job (Python, uses Poetry)
manifests/kustomize/ # Kubernetes deployment manifests (Kustomize)
scripts/ # Build and utility scripts
devenv/ # Local development environment (Tilt-based)
docs/ # Documentation (see docs/dev_kind_environment.md for Kind setup)
test/ # Integration/E2E test scripts
make deps # Install tool dependencies (golangci-lint, goverter, openapi-generator, envtest)make build # Full build: generate code, vet, lint, then compile
make build/compile # Compile only (skip generation/lint — useful after a clean build)
make build/csi # Build the CSI storage-initializer binary
make -C catalog build # Build catalog service (if applicable)The build target runs gen (code generation), vet, and lint before compiling. If you only changed Go source and not OpenAPI specs or converters, make build/compile is faster.
make lint # Run golangci-lint on all Go code
make vet # Run go vet on all packagesgolangci-lint v2.9.0 is used. There is no project-level .golangci.yml config file — the default golangci-lint configuration applies.
make test # Run all unit tests (internal/... and pkg/..., excludes controller)
make test-nocache # Run tests without cache
make test-cover # Run tests with coverage report (outputs coverage.html)make controller/test # Run controller tests (requires envtest/kubebuilder assets)make -C catalog test # Run catalog unit tests
make -C catalog test-cover # Run catalog tests with coveragecd clients/python
make install # Generate OpenAPI client and install dependencies via Poetry
make test # Run unit tests (pytest)
make lint # Run ruff + mypyE2E tests (fully automated — creates a KinD cluster, builds and deploys the server image, Minio, OCI registry, runs tests, then cleans up):
cd clients/python
make test-e2e # All-in-one: deploy infra + run E2E + cleanupIf you need to manage the environment manually:
cd clients/python
make deploy-latest-mr # Build image, create KinD cluster, deploy MR, start port-forward
make deploy-test-minio # Deploy Minio for storage tests
make deploy-local-registry # Deploy local OCI registry
make test-e2e-run # Run E2E tests only (infra must already be running)
make test-e2e-cleanup # Cleanup DB and stop port-forwardscd catalog/clients/python
make install # Generate OpenAPI client and install dependencies via Poetry
make lint # Run ruff + mypyE2E tests (two-step — deploy, then test):
cd catalog/clients/python
make deploy # All-in-one: KinD cluster + build image + deploy catalog + port-forward
make test-e2e # Run E2E tests (requires catalog already deployed)
make deploy-cleanup # Tear down KinD cluster and port-forwardsIf you need finer control over deployment:
cd catalog/clients/python
make deploy-kind # Create KinD cluster
make deploy-build # Build Docker image
make deploy-load # Load image into KinD
make deploy-k8s # Deploy to existing cluster (namespace + kustomize)
make deploy-forward # Start port-forward to catalog service
make deploy-restart # Rebuild and redeploy catalog only (quick dev cycle)cd jobs/async-upload
make install # Install Python dependencies via Poetry
make test # Run unit tests (pytest)
make test-e2e # Run E2E tests (requires KinD cluster)go test ./internal/core/ -run TestSpecificFunction -v # Run a specific test
go test ./internal/db/service/ -count=1 # Run package tests without cachemake gen # Run all code generation (OpenAPI + converters)
make gen/openapi # Regenerate OpenAPI client (pkg/openapi/)
make gen/openapi-server # Regenerate OpenAPI server stubs (internal/server/openapi/)
make gen/converter # Regenerate type converters (internal/converter/generated/)
make gen/gorm # Regenerate GORM structs from DB schema (requires Docker)After changing api/openapi/src/*.yaml, run:
make api/openapi/model-registry.yaml # Merge OpenAPI source files
make openapi/validate # Validate merged spec
make gen/openapi gen/openapi-server # Regenerate Go code from specmake image/build # Build the server container image
make compose/up # Start services with MySQL (pre-built images)
make compose/up/postgres # Start services with PostgreSQL
make compose/local/up # Start services built from source (MySQL)
make compose/local/up/postgres # Start services built from source (PostgreSQL)
make compose/down # Stop services
make compose/clean # Remove all volumes and networks# From clients/ui/
make dev-install-dependencies # Install all UI dependencies
make dev-start # Start BFF + frontend for standalone mode
# Or individually:
cd clients/ui/bff && go run ./cmd --port=4000 --dev-mode --deployment-mode=standalone
cd clients/ui/frontend && DEPLOYMENT_MODE=standalone STYLE_THEME=patternfly npm run start:dev
# UI tests
cd clients/ui/frontend && npm run test:unit
cd clients/ui/frontend && npm run test:type-checkFor Kind-based UI development with Tilt, see docs/dev_kind_environment.md.
The following checks run automatically on pull requests:
| Check | Workflow | What it does |
|---|---|---|
| Build + Unit Tests | build.yml |
make build/compile, make test-cover, catalog tests |
| Go Mod Tidy | go-mod-tidy-diff-check.yml |
Ensures go.mod / go.sum are tidy |
| Controller Tests | controller-test.yml |
make controller/test (triggered by controller path changes) |
| CSI Tests | csi-test.yml |
E2E tests on KinD cluster (triggered by CSI path changes) |
| Python Client Tests | python-tests.yml |
Lint, unit tests, E2E on KinD (model-registry + catalog Python clients) |
| Async Upload Tests | async-upload-test.yml |
Python pytest + E2E (triggered by jobs/async-upload/ changes) |
Before submitting a PR, at minimum run:
make build/compile && make test && make lint && make vet- Read existing code patterns in the file you're modifying and its neighbors
- Check if the file is auto-generated (look for
.openapi-generatormarkers orgenerateddirectories) — if so, modify the source/template instead - Run
make vetandmake lintto confirm a clean starting state
make vet # Go vet
make lint # Linter
make test # Unit tests
go mod tidy # Ensure module files are cleanThe following directories contain auto-generated code. Modify the sources and regenerate instead:
api/openapi/model-registry.yaml— merged output, do NOT edit. Edit source files inapi/openapi/src/model-registry.yamlandapi/openapi/src/lib/*.yaml, then runmake api/openapi/model-registry.yamlapi/openapi/catalog.yaml— merged output, do NOT edit. Edit source files inapi/openapi/src/catalog.yamlandapi/openapi/src/lib/*.yaml, then runmake api/openapi/catalog.yamlpkg/openapi/— generated from the mergedapi/openapi/model-registry.yamlviamake gen/openapicatalog/pkg/openapi/— generated from the mergedapi/openapi/catalog.yamlviamake -C catalog gen/openapiinternal/server/openapi/— generated from OpenAPI specs viamake gen/openapi-serverinternal/converter/generated/— generated from converter interfaces viamake gen/converter
- Use DCO sign-off on all commits (
git commit -s) - Keep diffs minimal — only modify files relevant to the task
- Do not push secrets, credentials, or modify git config
- Run
go mod tidyif you changed dependencies - Keep commit messages brief
- Follow the Conventional Commit specification (e.g.
feat(catalog): <description>,fix: some bug)
- Follow standard Go conventions:
gofmt,go vet, effective Go patterns - Use
snake_casefor file names,PascalCasefor exported identifiers,camelCasefor unexported - Capitalize acronyms (prefer
parseIPtoparseIp) - Error handling: always check and return errors, no bare
_ignoring errors unless justified - Use the
stretchr/testifypackage for test assertions (already a project dependency) - Use Testcontainers for integration tests that need a real database
- Follow existing component patterns in
clients/ui/frontend/src/ - Use PatternFly components for UI elements
- Prefer functional components with hooks
- Write unit tests for new components
- Follow existing patterns in
clients/python/andcatalog/clients/python/ - Use Poetry for dependency management
- Write tests with pytest
- Bug fixes MUST include a test that reproduces the bug
- Unit tests live alongside source files as
*_test.go(Go),*.test.ts/*.test.tsx(TypeScript),*_test.py/test_*.py(Python) - Integration tests use Testcontainers (MySQL and PostgreSQL) — see
internal/db/service/*_test.gofor patterns - Controller tests use
envtest(kubebuilder test framework) — seecmd/controller/
- No
evalor equivalent dynamic code execution on user-controlled input - Proper error handling — no silently swallowed errors
- No secrets in code, logs, or test fixtures
- Ensure proper resource cleanup (database connections, HTTP clients)
When modifying the database schema:
- Add migration files in
internal/datastore/embedmd/{mysql,postgres}/migrations/ - Regenerate GORM structs:
make gen/gorm - Test against both MySQL and PostgreSQL
When modifying the REST API:
- Edit ONLY the source specs in
api/openapi/src/(e.g.,api/openapi/src/model-registry.yaml,api/openapi/src/lib/*.yaml). NEVER edit the merged output filesapi/openapi/model-registry.yamlorapi/openapi/catalog.yamldirectly — they are generated. - Merge sources into the final spec:
make api/openapi/model-registry.yaml(ormake api/openapi/catalog.yaml) - Validate:
make openapi/validate - Regenerate server and client code:
make gen/openapi gen/openapi-server - Update any affected handler logic in
internal/
- CONTRIBUTING.md — DCO, code of conduct, ARM/Mac setup, Kind deployment
- clients/ui/CONTRIBUTING.md — UI-specific contribution guide
- docs/dev_kind_environment.md — Kind local dev environment setup and troubleshooting
- devenv/README.md — Tilt-based dev environment
- Model Registry documentation