diff --git a/.claude/rules/api.md b/.claude/rules/api.md new file mode 100644 index 000000000..ff5aea1e7 --- /dev/null +++ b/.claude/rules/api.md @@ -0,0 +1,12 @@ +--- +paths: + - "api/**/*.go" +--- + +# API Types Rules + +- New API versions go in `api/v1alphaN/` following the existing version directories. +- All exported types and fields must have godoc comments (Go convention: comment starts with the symbol name). +- After modifying any type in `api/`, run `make manifests generate` — the generated CRD YAML and deepcopy code must be committed with the source change. +- Validation markers (`+kubebuilder:validation:*`) go on struct fields, not separately. +- Check `api/current-types.go` to understand which API version is current/promoted. diff --git a/.claude/rules/controller.md b/.claude/rules/controller.md new file mode 100644 index 000000000..76b96339d --- /dev/null +++ b/.claude/rules/controller.md @@ -0,0 +1,12 @@ +--- +paths: + - "internal/controller/**/*.go" +--- + +# Controller Rules + +- Reconcile logic lives in `internal/controller/backstage_controller.go`. +- Use server-side apply (`r.Patch(.., client.Apply, ..)`) for idempotent resource management — avoid plain `Create` which fails on re-reconcile. +- Gate optional features on CRD presence before registering scheme or adding RBAC. +- Do not hard-code `replicas` in any Deployment/StatefulSet template — omit to allow HPA. +- After any controller change, run `make manifests generate fmt vet` before committing. diff --git a/.claude/rules/integration-tests.md b/.claude/rules/integration-tests.md new file mode 100644 index 000000000..e40b6532b --- /dev/null +++ b/.claude/rules/integration-tests.md @@ -0,0 +1,12 @@ +--- +paths: + - "integration_tests/**/*.go" + - "tests/**/*.go" +--- + +# Integration & E2E Test Rules + +- Some integration tests may require a running Kubernetes cluster and/or existing controller. Use `make integration-test USE_EXISTING_CLUSTER=true USE_EXISTING_CONTROLLER=true`. +- The `PROFILE` variable selects the test suite: `backstage.io` (faster, default for CI) or `rhdh`. +- Staticcheck (ST1001) is excluded for test files — dot-imports are allowed. +- Use `--focus` to run a single test: `make integration-test ARGS='--focus "test name"' USE_EXISTING_CLUSTER=true USE_EXISTING_CONTROLLER=true`. diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 000000000..bd09f6e05 --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,15 @@ +{ + "hooks": { + "PostToolUse": [ + { + "matcher": "Edit|Write", + "hooks": [ + { + "type": "command", + "command": "case \"$CLAUDE_FILE_PATH\" in *.go) gofmt -w \"$CLAUDE_FILE_PATH\" 2>/dev/null || true ;; esac" + } + ] + } + ] + } +} diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 000000000..a48f6ad61 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,41 @@ +# rhdh-operator + +Kubernetes operator for Red Hat Developer Hub (RHDH), based on the Backstage operator. +Manages `Backstage` CRs and reconciles them into Deployments, ConfigMaps, and related resources. + +## Build & Test Commands + +- Build: `make build` +- Test (unit and integration tests not requiring real cluster): `make test` +- Integration test (on running cluster and controller): `make integration-test PROFILE=backstage.io USE_EXISTING_CLUSTER=true USE_EXISTING_CONTROLLER=true` +- Lint: `make lint` (golangci-lint + yamllint) +- Lint fix: `make lint-fix` +- Format: `make fmt` (goimports) +- Security scan: `make gosec` +- Generate CRD/deepcopy: `make manifests generate` +- Single-file lint: `golangci-lint run ./path/to/package/...` +- Single-file vet: `go vet ./path/to/package/...` + +## Key Conventions + + + +## Architecture + +- Design and configuration overview: `docs/design.md` + + + +## Pattern References + +- CR examples and dependent resources: `examples/` +- Operator coding patterns (from PR reviews): `best_practices.md` +- Design and configuration docs: `docs/` + +## PR Conventions + +- PR description must link the related issue (`Fixes #`) and include test and documentation checkboxes. +- Agent-assisted commits should include an `Assisted-by: ` footer. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 000000000..43c994c2d --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +@AGENTS.md diff --git a/Makefile b/Makefile index fae5219f7..9af711187 100644 --- a/Makefile +++ b/Makefile @@ -204,7 +204,7 @@ gosec: addgosec ## run the gosec scanner for non-test files in this repo $(GOSEC) -no-fail -fmt $(GOSEC_FMT) -out $(GOSEC_OUTPUT_FILE) ./... .PHONY: lint -lint: golangci-lint ## Run golangci-lint linter & yamllint +lint: golangci-lint vet ## Run golangci-lint linter & yamllint & go vet $(GOLANGCI_LINT) run --timeout 15m .PHONY: lint-fix