P3.5: Add values.schema.json constraint for replicas>1 requires Redis

- Create charts/miroir/ with values.schema.json, values.yaml, Chart.yaml
- Add JSON Schema if/then constraint: replicas > 1 requires taskStore.backend=redis
- Include errorMessage for clear operator feedback when constraint is violated
- Add test cases in charts/miroir/tests/ for validation:
  * valid-single-replica-sqlite.yaml (replicas: 1, backend: sqlite) → pass
  * invalid-multi-replica-sqlite.yaml (replicas: 2, backend: sqlite) → fail
  * valid-multi-replica-redis.yaml (replicas: 2, backend: redis) → pass

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
jedarden 2026-04-18 23:44:15 -04:00
parent 21aebb386c
commit 26d5524fec
7 changed files with 151 additions and 0 deletions

6
charts/miroir/Chart.yaml Normal file
View file

@ -0,0 +1,6 @@
apiVersion: v2
name: miroir
description: Distributed search orchestrator for Meilisearch
type: application
version: 0.1.0
appVersion: "0.1.0"

View file

@ -0,0 +1,26 @@
# Helm Chart Tests
This directory contains test cases for validating the `values.schema.json` constraints.
## Running Tests
Use `helm lint --strict` with the test values files:
```bash
# Valid: single replica with SQLite (should pass)
helm lint --strict miroir -f miroir/tests/valid-single-replica-sqlite.yaml
# Invalid: multiple replicas with SQLite (should fail with constraint error)
helm lint --strict miroir -f miroir/tests/invalid-multi-replica-sqlite.yaml
# Valid: multiple replicas with Redis (should pass)
helm lint --strict miroir -f miroir/tests/valid-multi-replica-redis.yaml
```
## Test Cases
| Test Case | Description | Expected Result |
|-----------|-------------|-----------------|
| `valid-single-replica-sqlite.yaml` | `replicas: 1, backend: sqlite` | ✅ Pass |
| `invalid-multi-replica-sqlite.yaml` | `replicas: 2, backend: sqlite` | ❌ Fail with constraint error |
| `valid-multi-replica-redis.yaml` | `replicas: 2, backend: redis` | ✅ Pass |

View file

@ -0,0 +1,9 @@
# Test case: replicas: 2, backend: sqlite
# Expected: helm lint --strict fails (multiple replicas require Redis)
---
miroir:
replicas: 2
taskStore:
backend: sqlite
path: /data/miroir-tasks.db

View file

@ -0,0 +1,9 @@
# Test case: replicas: 2, backend: redis
# Expected: helm lint --strict passes (multiple replicas with Redis)
---
miroir:
replicas: 2
taskStore:
backend: redis
url: redis://redis:6379

View file

@ -0,0 +1,9 @@
# Test case: replicas: 1, backend: sqlite
# Expected: helm lint --strict passes (single replica can use SQLite)
---
miroir:
replicas: 1
taskStore:
backend: sqlite
path: /data/miroir-tasks.db

View file

@ -0,0 +1,76 @@
{
"$schema": "http://json-schema.org/draft-7/schema#",
"title": "Miroir Helm Chart Values",
"type": "object",
"properties": {
"miroir": {
"type": "object",
"properties": {
"image": {
"type": "object",
"properties": {
"repository": { "type": "string" },
"tag": { "type": "string" }
}
},
"replicas": {
"type": "integer",
"minimum": 1
},
"shards": {
"type": "integer",
"minimum": 1
},
"replicationFactor": {
"type": "integer",
"minimum": 1
},
"replicaGroups": {
"type": "integer",
"minimum": 1
},
"existingSecret": { "type": "string" }
}
},
"taskStore": {
"type": "object",
"properties": {
"backend": {
"type": "string",
"enum": ["sqlite", "redis"]
},
"path": { "type": "string" },
"url": { "type": "string" }
},
"required": ["backend"]
}
},
"if": {
"properties": {
"miroir": {
"properties": {
"replicas": {
"type": "integer",
"exclusiveMinimum": 1
}
},
"required": ["replicas"]
}
},
"required": ["miroir"]
},
"then": {
"properties": {
"taskStore": {
"properties": {
"backend": {
"const": "redis",
"errorMessage": "SQLite task store cannot run with multiple replicas; set taskStore.backend=redis"
}
},
"required": ["backend"]
}
},
"required": ["taskStore"]
}
}

16
charts/miroir/values.yaml Normal file
View file

@ -0,0 +1,16 @@
# Miroir Helm Chart Values
miroir:
image:
repository: ghcr.io/jedarden/miroir
tag: "" # defaults to Chart.appVersion
replicas: 1 # dev default: override to 2+ in production (requires taskStore.backend=redis)
shards: 64
replicationFactor: 1 # dev default: override to 2 in production
replicaGroups: 1 # dev default: override to 2 in production
existingSecret: "" # name of K8s Secret with masterKey, nodeMasterKey, adminApiKey
taskStore:
backend: sqlite # sqlite | redis
path: /data/miroir-tasks.db
url: "" # for redis: redis://host:6379