Files
cleveragents-core/features/k8s_helm_chart.feature
freemo e5398e3cc7
CI / lint (push) Successful in 17s
CI / build (push) Successful in 16s
CI / security (push) Has been cancelled
CI / docker (push) Has been cancelled
CI / typecheck (push) Has been cancelled
CI / unit_tests (push) Has been cancelled
CI / coverage (push) Has been cancelled
CI / integration_tests (push) Has been cancelled
CI / e2e_tests (push) Has been cancelled
CI / status-check (push) Has been cancelled
CI / benchmark-regression (push) Has been cancelled
CI / benchmark-publish (push) Has been cancelled
CI / quality (push) Has been cancelled
CI / helm (push) Has been cancelled
feat(server): implement serve CLI subcommand and align Dockerfile entrypoint
The `cleveragents server serve` CLI subcommand already exists in server.py and Dockerfile.server already uses `python -m cleveragents` as its ENTRYPOINT with `server serve` as the CMD.

Add BDD scenarios to k8s_helm_chart.feature that explicitly verify:
- Dockerfile.server ENTRYPOINT uses `python -m cleveragents`
- Dockerfile.server CMD includes the `server serve` subcommand tokens

Add corresponding step definitions to k8s_helm_chart_steps.py.

Closes #1088

Co-authored-by: Jeffrey Phillips Freeman <the@jeffreyfreeman.me>
Co-committed-by: Jeffrey Phillips Freeman <the@jeffreyfreeman.me>
2026-04-02 16:59:14 +00:00

298 lines
13 KiB
Gherkin

Feature: Kubernetes Helm Chart Structure
As a DevOps engineer
I want a valid Helm chart in the k8s/ directory
So that I can deploy the CleverAgents server to Kubernetes
Background:
Given the project root directory
# -- Chart.yaml validation --
Scenario: Chart.yaml exists with required Helm v2 fields
When I read the Helm chart metadata
Then the chart API version should be "v2"
And the chart name should be "cleveragents"
And the chart type should be "application"
And the chart version should be set
Scenario: Chart.yaml declares optional Redis dependency
When I read the Helm chart metadata
Then the chart should have a dependency named "redis"
And the Redis dependency should be conditional on "redis.enabled"
# -- values.yaml validation --
Scenario: values.yaml has configurable replica count
When I read the Helm chart values
Then the values should contain key "replicaCount"
And the default replica count should be 1
Scenario: values.yaml has configurable resource limits
When I read the Helm chart values
Then the values should contain key "resources"
And the resources should have CPU and memory limits
And the resources should have CPU and memory requests
Scenario: values.yaml has ingress configuration with TLS support
When I read the Helm chart values
Then the values should contain key "ingress"
And the ingress should have an enabled toggle
And the ingress should have a TLS configuration section
Scenario: values.yaml has optional Redis configuration
When I read the Helm chart values
Then the values should contain key "redis"
And the Redis configuration should have an enabled toggle
And the Redis configuration should have authentication settings
Scenario: values.yaml has server configuration
When I read the Helm chart values
Then the values should contain key "server"
And the server config should have host setting
And the server config should have port setting
And the server config should have workers setting
Scenario: values.yaml has database configuration
When I read the Helm chart values
Then the values should contain key "database"
And the database config should support existing secrets
Scenario: values.yaml has security context for non-root execution
When I read the Helm chart values
Then the pod security context should enforce non-root execution
And the container security context should drop all capabilities
# -- Template file content validation --
Scenario: Deployment template has correct kind and API version
When I read the template "k8s/templates/deployment.yaml"
Then the template should contain "kind: Deployment"
And the template should contain "apiVersion: apps/v1"
And the template should contain "volumeMounts:"
And the template should contain "mountPath: /tmp"
And the template should contain "mountPath: /app/data"
And the template should contain "sizeLimit: 100Mi"
And the template should contain "sizeLimit: 1Gi"
Scenario: Service template has correct kind and API version
When I read the template "k8s/templates/service.yaml"
Then the template should contain "kind: Service"
And the template should contain "apiVersion: v1"
Scenario: Ingress template has correct kind and API version
When I read the template "k8s/templates/ingress.yaml"
Then the template should contain "kind: Ingress"
And the template should contain "networking.k8s.io/v1"
And the template should match pattern "^\s+tls:"
Scenario: ConfigMap template has correct kind and API version
When I read the template "k8s/templates/configmap.yaml"
Then the template should contain "kind: ConfigMap"
And the template should contain "apiVersion: v1"
Scenario: ServiceAccount template has correct kind and API version
When I read the template "k8s/templates/serviceaccount.yaml"
Then the template should contain "kind: ServiceAccount"
And the template should contain "apiVersion: v1"
And the template should contain "automountServiceAccountToken: false"
Scenario: Secrets template has correct kind
When I read the template "k8s/templates/secrets.yaml"
Then the template should contain "kind: Secret"
Scenario: Helpers template exists with chart helpers
When I read the template "k8s/templates/_helpers.tpl"
Then the template should contain "cleveragents.fullname"
And the template should contain "cleveragents.labels"
Scenario: NOTES.txt template exists with deployment info
When I read the template "k8s/templates/NOTES.txt"
Then the template should contain "CleverAgents Server has been deployed"
# -- Server Dockerfile --
Scenario: Server-specific Dockerfile exists
Then the chart file "Dockerfile.server" should exist
Scenario: Server Dockerfile uses multi-stage build
When I read the server Dockerfile
Then it should have a builder stage
And it should have a runtime stage
Scenario: Server Dockerfile uses non-root user
When I read the server Dockerfile
Then it should create a non-root user with uid 1000
Scenario: Server Dockerfile exposes port 8000
When I read the server Dockerfile
Then it should expose port 8000
Scenario: Server Dockerfile pins uv image version
When I read the server Dockerfile
Then it should not use unpinned uv latest tag
Scenario: Server Dockerfile uses python -m cleveragents as ENTRYPOINT
When I read the server Dockerfile
Then the ENTRYPOINT should use "python -m cleveragents"
Scenario: Server Dockerfile CMD uses server serve subcommand
When I read the server Dockerfile
Then the CMD should include "server" and "serve"
# -- Secrets structure --
Scenario: Secrets template guards database secret with existingSecret check
When I read the template "k8s/templates/secrets.yaml"
Then the template should contain "database.existingSecret"
And the template should contain "database.url"
And the template should contain "database-url"
Scenario: Secrets template guards Redis secret with existingSecret check
When I read the template "k8s/templates/secrets.yaml"
Then the template should contain "redis.auth.existingSecret"
And the template should contain "redis.auth.password"
And the template should contain "redis-password"
# -- Deployment command/args --
Scenario: Deployment template overrides command with CLI server serve values
When I read the template "k8s/templates/deployment.yaml"
Then the template should contain "python"
And the template should contain "cleveragents"
And the template should contain "server"
And the template should contain "serve"
And the template should contain "--app"
And the template should contain "cleveragents.a2a.asgi:app"
And the template should contain "server.host"
And the template should contain "server.port"
And the template should contain "server.workers"
And the template should contain "server.logLevel"
# -- envFrom wiring --
Scenario: Deployment template injects ConfigMap via envFrom
When I read the template "k8s/templates/deployment.yaml"
Then the template should contain "envFrom"
And the template should contain "configMapRef"
# -- Redis host helper --
Scenario: Helpers template defines Redis host using Release.Name
When I read the template "k8s/templates/_helpers.tpl"
Then the template should contain "cleveragents.redisHost"
And the template should contain ".Release.Name"
# -- Probes --
Scenario: values.yaml splits liveness and readiness probe endpoints
When I read the Helm chart values
Then the liveness probe should target the live endpoint
And the readiness probe should target the ready endpoint
# -- Image defaults --
Scenario: values.yaml has sensible image defaults
When I read the Helm chart values
Then the image pull policy should be "IfNotPresent"
And the image tag should default to empty for appVersion fallback
# -- Service defaults --
Scenario: values.yaml service defaults to ClusterIP on port 8000
When I read the Helm chart values
Then the service type should be "ClusterIP"
And the service port should be 8000
# -- Conditional template branch validation --
Scenario: Ingress template is guarded by ingress.enabled condition
When I read the template "k8s/templates/ingress.yaml"
Then the template should match pattern "^\{\{-\s*if\s+\.Values\.ingress\.enabled"
Scenario: Ingress template guards ssl-redirect against user annotation override
When I read the template "k8s/templates/ingress.yaml"
Then the template should match pattern "not.*hasKey.*\.Values\.ingress\.annotations.*ssl-redirect"
Scenario: ServiceAccount template is guarded by serviceAccount.create condition
When I read the template "k8s/templates/serviceaccount.yaml"
Then the template should match pattern "^\{\{-\s*if\s+\.Values\.serviceAccount\.create"
Scenario: Secrets template guards database secret with conditional logic
When I read the template "k8s/templates/secrets.yaml"
Then the template should match pattern "if\s+and\s+\.Values\.database\.url.*not\s+\.Values\.database\.existingSecret"
Scenario: Secrets template guards Redis secret with conditional logic
When I read the template "k8s/templates/secrets.yaml"
Then the template should match pattern "if\s+and\s+\.Values\.redis\.enabled\s+\.Values\.redis\.auth\.enabled\s+\.Values\.redis\.auth\.password.*not\s+\.Values\.redis\.auth\.existingSecret"
Scenario: Deployment template has database credential 3-way branching
When I read the template "k8s/templates/deployment.yaml"
Then the template should match pattern "if\s+\.Values\.database\.existingSecret"
And the template should match pattern "else\s+if\s+\.Values\.database\.url"
Scenario: Deployment template has Redis credential 3-way branching
When I read the template "k8s/templates/deployment.yaml"
Then the template should match pattern "if\s+\.Values\.redis\.auth\.existingSecret"
And the template should match pattern "else\s+if\s+\.Values\.redis\.auth\.password"
And the template should contain "name: {{ .Release.Name }}-redis"
And the template should contain "key: redis-password"
Scenario: Deployment template gates Redis env vars behind redis.enabled
When I read the template "k8s/templates/deployment.yaml"
Then the template should match pattern "if\s+\.Values\.redis\.enabled"
And the template should match pattern "CLEVERAGENTS_REDIS_HOST"
And the template should match pattern "CLEVERAGENTS_REDIS_PASSWORD"
Scenario: Deployment template requires explicit database configuration
When I read the template "k8s/templates/deployment.yaml"
Then the template should contain "database configuration is required"
Scenario: Helm render fails fast without database configuration
When I render the Helm chart without database configuration
Then the render should fail with required database configuration error
Scenario: Helm render fails when ingress is enabled without TLS by default
When I render the Helm chart with ingress enabled and no TLS
Then the render should fail with required ingress TLS configuration error
Scenario: Helm render allows explicit insecure ingress opt-out for development
When I render the Helm chart with ingress enabled and insecure opt-out enabled
Then the ingress render should succeed in insecure dev mode
Scenario: Helm render succeeds when ingress TLS is explicitly configured
When I render the Helm chart with ingress enabled and TLS configured
Then the ingress render should succeed with TLS enabled
Scenario: Deployment template disables service account token mounting
When I read the template "k8s/templates/deployment.yaml"
Then the template should match pattern "^\s+automountServiceAccountToken:\s+false"
Scenario: Security context includes seccomp profile
When I read the Helm chart values
Then the container security context should have a seccomp profile
Scenario: Security context enforces readOnlyRootFilesystem
When I read the Helm chart values
Then the container security context should set readOnlyRootFilesystem to true
Scenario: Security context disables privilege escalation
When I read the Helm chart values
Then the container security context should set allowPrivilegeEscalation to false
Scenario: Server Dockerfile pins uv version to specific semver
When I read the server Dockerfile
Then the uv image reference should use a specific semver tag
Scenario: Server Dockerfile removes uv from runtime image
When I read the server Dockerfile
Then the Dockerfile should remove uv after installation
# -- Deployment README --
Scenario: Deployment README exists with instructions
When I read the deployment README
Then it should contain quick start instructions
And it should contain TLS configuration documentation
And it should contain Redis configuration documentation
And it should contain scaling instructions