Skip to content

Latest commit

 

History

History
379 lines (289 loc) · 16.9 KB

File metadata and controls

379 lines (289 loc) · 16.9 KB

AGENTS.md — Model Registry

Who This Is For

  • 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

Agent Behavior Policy

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.md and Makefile as 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], or Co-authored-by: [Agent Name].
    • Avoid automated responses/comments to the Pull Requests or Issues on GitHub.

Agents must NOT:

  • Bypass tests or linters
  • Introduce dependencies without updating go.mod / go.sum (Go), pyproject.toml (Python), or package.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

Context Awareness

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.mod files
  • 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.

Repository Map

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

Commands

Setup

make deps                         # Install tool dependencies (golangci-lint, goverter, openapi-generator, envtest)

Building

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.

Linting

make lint                         # Run golangci-lint on all Go code
make vet                          # Run go vet on all packages

golangci-lint v2.9.0 is used. There is no project-level .golangci.yml config file — the default golangci-lint configuration applies.

Testing

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)

Controller tests

make controller/test              # Run controller tests (requires envtest/kubebuilder assets)

Catalog tests

make -C catalog test              # Run catalog unit tests
make -C catalog test-cover        # Run catalog tests with coverage

Model Registry Python client tests

cd clients/python
make install                      # Generate OpenAPI client and install dependencies via Poetry
make test                         # Run unit tests (pytest)
make lint                         # Run ruff + mypy

E2E 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 + cleanup

If 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-forwards

Model Catalog Python client tests

cd catalog/clients/python
make install                      # Generate OpenAPI client and install dependencies via Poetry
make lint                         # Run ruff + mypy

E2E 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-forwards

If 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)

Async upload job tests (Python)

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)

Running a single Go test

go test ./internal/core/ -run TestSpecificFunction -v    # Run a specific test
go test ./internal/db/service/ -count=1                  # Run package tests without cache

Code Generation

make 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 spec

Docker / Container Images

make 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

UI Development

# 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-check

For Kind-based UI development with Tilt, see docs/dev_kind_environment.md.

CI Checks (what runs on PRs)

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

Development Workflow for AI Agents

Before making changes

  1. Read existing code patterns in the file you're modifying and its neighbors
  2. Check if the file is auto-generated (look for .openapi-generator markers or generated directories) — if so, modify the source/template instead
  3. Run make vet and make lint to confirm a clean starting state

Validation before proposing changes

make vet                          # Go vet
make lint                         # Linter
make test                         # Unit tests
go mod tidy                       # Ensure module files are clean

Auto-generated files — do NOT edit directly

The following directories contain auto-generated code. Modify the sources and regenerate instead:

  • api/openapi/model-registry.yamlmerged output, do NOT edit. Edit source files in api/openapi/src/model-registry.yaml and api/openapi/src/lib/*.yaml, then run make api/openapi/model-registry.yaml
  • api/openapi/catalog.yamlmerged output, do NOT edit. Edit source files in api/openapi/src/catalog.yaml and api/openapi/src/lib/*.yaml, then run make api/openapi/catalog.yaml
  • pkg/openapi/ — generated from the merged api/openapi/model-registry.yaml via make gen/openapi
  • catalog/pkg/openapi/ — generated from the merged api/openapi/catalog.yaml via make -C catalog gen/openapi
  • internal/server/openapi/ — generated from OpenAPI specs via make gen/openapi-server
  • internal/converter/generated/ — generated from converter interfaces via make gen/converter

Commit / PR hygiene

  • 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 tidy if you changed dependencies
  • Keep commit messages brief
  • Follow the Conventional Commit specification (e.g. feat(catalog): <description>, fix: some bug)

Core Development Principles

Go conventions

  • Follow standard Go conventions: gofmt, go vet, effective Go patterns
  • Use snake_case for file names, PascalCase for exported identifiers, camelCase for unexported
  • Capitalize acronyms (prefer parseIP to parseIp)
  • Error handling: always check and return errors, no bare _ ignoring errors unless justified
  • Use the stretchr/testify package for test assertions (already a project dependency)
  • Use Testcontainers for integration tests that need a real database

TypeScript/React conventions

  • 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

Python conventions

  • Follow existing patterns in clients/python/ and catalog/clients/python/
  • Use Poetry for dependency management
  • Write tests with pytest

Testing requirements

  • 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.go for patterns
  • Controller tests use envtest (kubebuilder test framework) — see cmd/controller/

Security checklist

  • No eval or 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)

Database changes

When modifying the database schema:

  1. Add migration files in internal/datastore/embedmd/{mysql,postgres}/migrations/
  2. Regenerate GORM structs: make gen/gorm
  3. Test against both MySQL and PostgreSQL

OpenAPI changes

When modifying the REST API:

  1. 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 files api/openapi/model-registry.yaml or api/openapi/catalog.yaml directly — they are generated.
  2. Merge sources into the final spec: make api/openapi/model-registry.yaml (or make api/openapi/catalog.yaml)
  3. Validate: make openapi/validate
  4. Regenerate server and client code: make gen/openapi gen/openapi-server
  5. Update any affected handler logic in internal/

Additional Resources