ark-controller-development
Provides workflow commands for managing Ark Kubernetes CRDs, Go types, and Helm chart updates.
Install
mkdir -p .claude/skills/ark-controller-development && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/2551" && unzip -o skill.zip -d .claude/skills/ark-controller-development && rm skill.zipInstalls to .claude/skills/ark-controller-development
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Guidance for developing the Ark Kubernetes operator. Use when modifying Go types, CRDs, controllers, or webhooks. Helps with CRD generation and Helm chart sync issues.Key capabilities
- →Modify Go type definitions
- →Generate CRDs from Go markers
- →Sync CRDs with Helm charts
- →Run controller reconciliation tests
- →Execute linting and build validation
How it works
The skill uses makefile targets to process Go type markers, generate CRDs, and sync them to the Helm chart, followed by mandatory linting and test suite execution.
Inputs & outputs
When to use ark-controller-development
- →Update CRD fields in Go types
- →Sync CRDs with the Ark Helm chart
- →Fix CRD validation errors during build
- →Reconcile Kubernetes controller logic
About this skill
Ark Controller Development
Guidance for developing the Ark Kubernetes operator in ark/.
When to use this skill
- Modifying Go type definitions (
api/v1alpha1/*_types.go) - Fixing CRD/Helm chart sync errors
- Adding new CRD fields or resources
CRD Generation Flow
api/v1alpha1/*_types.go # Go types with markers
↓
make manifests # Generates CRDs and syncs to Helm chart
↓
config/crd/bases/*.yaml # Source CRDs (auto-generated)
dist/chart/templates/crd/ # Helm chart CRDs (auto-synced)
make manifests automatically syncs source CRDs to the Helm chart while preserving templated headers.
Fixing "CRDs out of sync" Errors
When make build fails with CRD validation errors:
cd ark
make manifests
make build
Key Directories
| Directory | Purpose |
|---|---|
api/v1alpha1/ | Go type definitions |
config/crd/bases/ | Auto-generated source CRDs |
dist/chart/templates/crd/ | Helm chart CRDs (auto-synced) |
internal/controller/ | Reconciliation logic |
internal/webhook/ | Admission webhooks |
internal/genai/ | AI/ML execution logic |
Common Tasks
After Modifying Types or Comments
Go type comments become CRD field descriptions:
cd ark
make manifests
make build
After Any Go Code Change
make lint-fix # Format and auto-fix what the linter can fix
make lint # Fail fast on issues CI will reject — MANDATORY
make build # Build and validate
make test # Run unit + envtest suites
Before Opening a PR
Run the chainsaw e2e suite against a live cluster — unit + envtest don't exercise the full apply → reconcile → status loop. Prefer the deterministic mock-llm suite; only run the LLM-backed tests when the change specifically touches that path (saves cost + avoids flakes from real LLM providers).
# Deterministic suite (default)
(cd tests && chainsaw test --selector '!llm')
# LLM suite — only when your change needs it
(cd tests && chainsaw test --selector 'llm')
See the chainsaw skill for patterns and antipatterns (e.g. prefer
chainsaw assert over shell grep; prefer wait over polling).
make lint runs the same golangci-lint rules CI enforces. Running it
locally before pushing is non-negotiable — red PR checks cost more than
the minute the lint takes.
Leverage Existing Code — Don't Reinvent
Before writing a parser, struct, helper, retry loop, URL builder, or any utility, check whether it already exists in:
- Go standard library.
- Direct or transitive dependencies in
go.mod(controller-runtime,apimachinery, the SDK for whatever spec you're implementing,golang.org/x/...).
Hand-rolled code drifts, duplicates tests, and becomes maintenance burden. A short adapter delegating to a library is almost always better than a reimplementation.
Heuristic: if the thing you're writing mirrors an existing spec, file
format, header syntax, or common infra pattern, someone has already
written it. Search first: go doc <import-path>, ls $(go env GOMODCACHE)/<dep>.
Re-export library types via alias (type X = lib.X) rather than
defining a parallel struct with the same fields.
Worked example
Started this project by hand-rolling a WWW-Authenticate parser, RFC 9728
struct, RFC 8414 struct, and HTTP fetchers — ~150 LOC. The go-sdk
already shipped them in oauthex:
// Bad — 40-line parser, partial struct, duplicated HTTP wrapper.
func parseHeader(h string) (string, bool) { /* ... */ }
type Metadata struct { /* partial mirror of RFC */ }
func fetch(ctx, url) (*Metadata, error) { /* 30 lines */ }
// Good — thin adapter, full spec support, ~10 LOC.
import "github.com/modelcontextprotocol/go-sdk/oauthex"
type Metadata = oauthex.ProtectedResourceMetadata
func Fetch(ctx context.Context, metaURL, resourceURL string, timeout time.Duration) (*Metadata, error) {
return oauthex.GetProtectedResourceMetadata(ctx, metaURL, resourceURL, &http.Client{Timeout: timeout})
}
Same principle applies to retry/backoff (k8s.io/apimachinery/pkg/util/wait),
JSON patch (strategicpatch), condition updates
(meta.SetStatusCondition), HTTP clients, workqueues — whatever you're
touching, check the existing deps first.
Avoid Magic Numbers — Reuse Configurable Values
Never inline numeric durations, retry counts, or buffer sizes. Priority:
- User-configurable spec field — if the resource already has
spec.timeout,spec.pollInterval,spec.retries, use it. One operator knob should govern all related code paths in the same reconcile. - Package-level const with a name explaining why that number.
- Test-local const (e.g.
const testTimeout = 5 * time.Second) — never inline literals in tests.
Worked example
// Bad — parallel constant invented out of thin air.
const discoveryTimeout = 10 * time.Second
client := &http.Client{Timeout: discoveryTimeout}
// Good — plumb the MCPServer's spec.timeout; single source of truth.
func Fetch(ctx, url string, timeout time.Duration) ...
timeout := parseTimeout(mcpServer.Spec.Timeout)
Testing — not optional
Every code change ships with tests. A PR touching ark/internal/ with
no _test.go is incomplete. Applies to controller branches, webhooks,
helpers — not just public APIs.
| Change | Where | Framework |
|---|---|---|
Helper / parser in internal/<pkg>/ | <file>_test.go | stdlib testing, table-driven |
| Controller branch | internal/controller/<scenario>_test.go | Ginkgo + envtest |
| Webhook rule | internal/webhook/v1/<resource>_webhook_test.go | Ginkgo |
| HTTP logic | httptest.NewServer in same package | stdlib testing |
Required coverage for a controller branch:
- Happy path → expected status + conditions.
- Each failure mode → distinct stable condition reason (no string-matching).
- Idempotency → re-reconcile doesn't emit duplicate events or bump
lastTransitionTime. - Regression guard → pre-existing branches unaffected.
Completion Checklist
Before saying "done":
-
make manifestsclean (if types changed) -
make lintclean — same rules CI enforces -
make buildgreen -
make testgreen — paste or reference output - Chainsaw deterministic suite (
chainsaw test --selector '!llm') green; LLM suite only if change requires it - New
_test.goexists for every new function / branch - Helm chart CRDs regenerated and committed
- OpenAPI / Python SDK / TypeScript SDK regenerated if CRD changed
- Running pod re-verified — devspace syncs source, but only a container restart picks up new Go binaries; tail controller logs after any reconciliation-path change
When not to use it
- →Reinventing existing utilities already present in Go dependencies
Prerequisites
Limitations
- →Requires local makefile execution for all changes
- →LLM-backed tests should only run when specifically required
How it compares
It automates the synchronization between Go types and Helm charts, preventing manual drift that occurs when updating CRDs without makefile targets.
Compared to similar skills
ark-controller-development side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| ark-controller-development (this skill) | 2 | 3mo | Review | Advanced |
| linkerd-patterns | 6 | 5mo | Review | Advanced |
| k8s-helm | 8 | 6mo | Review | Intermediate |
| gitops-workflow | 5 | 2mo | Review | Advanced |
Try saying
Example prompts that trigger this skill in your AI assistant.
More by mckinsey
View all by mckinsey →You might also like
linkerd-patterns
wshobson
Implement Linkerd service mesh patterns for lightweight, security-focused service mesh deployments. Use when setting up Linkerd, configuring traffic policies, or implementing zero-trust networking with minimal overhead.
k8s-helm
rohitg00
Manage Helm charts, releases, and repositories. Use for Helm installations, upgrades, rollbacks, chart development, and release management.
gitops-workflow
sickn33
Implement GitOps workflows with ArgoCD and Flux for automated, declarative Kubernetes deployments with continuous reconciliation. Use when implementing GitOps practices, automating Kubernetes deployments, or setting up declarative infrastructure management.
devops-iac-engineer
davila7
Implements infrastructure as code using Terraform, Kubernetes, and cloud platforms. Designs scalable architectures, CI/CD pipelines, and observability solutions. Provides security-first DevOps practices and site reliability engineering guidance.
deployment-engineer
sickn33
Expert deployment engineer specializing in modern CI/CD pipelines, GitOps workflows, and advanced deployment automation. Masters GitHub Actions, ArgoCD/Flux, progressive delivery, container security, and platform engineering. Handles zero-downtime deployments, security scanning, and developer experience optimization. Use PROACTIVELY for CI/CD design, GitOps implementation, or deployment automation.
k8s-rollouts
rohitg00
Progressive delivery with Argo Rollouts and Flagger. Use when implementing canary deployments, blue-green deployments, or traffic shifting strategies.