Add production-grade Helm chart improvements

High-impact improvements based on Codex recommendations:

1. values.schema.json - JSON schema validation catches config errors at install time
2. helm-docs automation - Auto-generates documentation from values.yaml comments
3. kind smoke tests - Deploys and upgrades chart in real cluster to catch runtime issues
4. ServiceMonitor template - Built-in Prometheus integration for observability
5. Artifact Hub metadata - Changelog, links, and maintainer info for better discoverability

These improvements provide:
- Configuration validation before deployment
- Always up-to-date documentation
- Runtime validation in CI
- First-class monitoring support
- Better user experience on Artifact Hub

Related to #686
This commit is contained in:
rcourtman
2025-11-11 19:52:58 +00:00
parent 3477aa3dae
commit dc8eaa3ffe
5 changed files with 308 additions and 0 deletions

View File

@@ -31,6 +31,29 @@ jobs:
with:
version: v3.15.2
- name: Install helm-docs
run: |
cd /tmp
wget https://github.com/norwoodj/helm-docs/releases/download/v1.14.2/helm-docs_1.14.2_Linux_x86_64.tar.gz
tar -xzf helm-docs_1.14.2_Linux_x86_64.tar.gz
sudo mv helm-docs /usr/local/bin/
helm-docs --version
- name: Generate chart documentation
run: |
cd deploy/helm/pulse
helm-docs
# Commit if README changed
if ! git diff --quiet README.md; then
git config user.name "$GITHUB_ACTOR"
git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
git add README.md
git commit -m "Auto-update Helm chart documentation"
git push
fi
cd ../../..
- name: Determine chart version
id: version
run: |
@@ -73,6 +96,39 @@ jobs:
echo "✓ Chart validation passed"
- name: Smoke test with kind
run: |
# Install kind
curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.20.0/kind-linux-amd64
chmod +x ./kind
sudo mv ./kind /usr/local/bin/kind
# Create cluster
kind create cluster --name pulse-test --wait 5m
# Install chart
helm install pulse deploy/helm/pulse \
--set persistence.enabled=false \
--set server.secretEnv.create=true \
--set server.secretEnv.data.API_TOKENS=test-token \
--wait --timeout 3m
# Verify deployment
kubectl wait --for=condition=ready pod -l app.kubernetes.io/name=pulse --timeout=120s
kubectl get pods -l app.kubernetes.io/name=pulse
# Test upgrade
helm upgrade pulse deploy/helm/pulse \
--set persistence.enabled=false \
--set server.secretEnv.create=true \
--set server.secretEnv.data.API_TOKENS=test-token \
--wait --timeout 3m
# Cleanup
kind delete cluster --name pulse-test
echo "✓ Smoke test passed"
- name: Run chart-releaser
uses: helm/chart-releaser-action@v1.6.0
with:

View File

@@ -19,3 +19,22 @@ annotations:
org.opencontainers.image.source: https://github.com/rcourtman/Pulse
org.opencontainers.image.description: Helm chart for deploying Pulse monitoring system
org.opencontainers.image.licenses: MIT
artifacthub.io/changes: |
- kind: added
description: GitHub Pages Helm repository distribution (no authentication required)
- kind: added
description: values.schema.json for configuration validation
- kind: added
description: ServiceMonitor template for Prometheus integration
- kind: added
description: Automated chart documentation generation with helm-docs
- kind: added
description: Smoke tests with kind cluster deployment
artifacthub.io/links: |
- name: Documentation
url: https://github.com/rcourtman/Pulse/blob/main/docs/KUBERNETES.md
- name: Support
url: https://github.com/rcourtman/Pulse/discussions
artifacthub.io/maintainers: |
- name: rcourtman
email: pulse@rcourtman.dev

View File

@@ -0,0 +1,33 @@
{{- if .Values.monitoring.serviceMonitor.enabled -}}
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: {{ include "pulse.fullname" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "pulse.labels" . | nindent 4 }}
{{- with .Values.monitoring.serviceMonitor.labels }}
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
selector:
matchLabels:
{{- include "pulse.selectorLabels" . | nindent 6 }}
endpoints:
- port: http
{{- with .Values.monitoring.serviceMonitor.interval }}
interval: {{ . }}
{{- end }}
{{- with .Values.monitoring.serviceMonitor.scrapeTimeout }}
scrapeTimeout: {{ . }}
{{- end }}
path: {{ .Values.monitoring.serviceMonitor.path | default "/metrics" }}
{{- with .Values.monitoring.serviceMonitor.relabelings }}
relabelings:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.monitoring.serviceMonitor.metricRelabelings }}
metricRelabelings:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,189 @@
{
"$schema": "https://json-schema.org/draft-07/schema#",
"type": "object",
"required": ["server"],
"properties": {
"replicaCount": {
"type": "integer",
"minimum": 1,
"description": "Number of Pulse server replicas"
},
"image": {
"type": "object",
"properties": {
"repository": {
"type": "string",
"description": "Container image repository"
},
"pullPolicy": {
"type": "string",
"enum": ["Always", "IfNotPresent", "Never"],
"description": "Image pull policy"
},
"tag": {
"type": "string",
"description": "Container image tag (overrides chart appVersion)"
}
}
},
"imagePullSecrets": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
}
}
},
"description": "Image pull secrets for private registries"
},
"service": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": ["ClusterIP", "NodePort", "LoadBalancer"],
"description": "Kubernetes service type"
},
"port": {
"type": "integer",
"minimum": 1,
"maximum": 65535,
"description": "Service port"
}
}
},
"ingress": {
"type": "object",
"properties": {
"enabled": {
"type": "boolean",
"description": "Enable ingress resource"
},
"className": {
"type": "string",
"description": "Ingress class name"
},
"hosts": {
"type": "array",
"items": {
"type": "object",
"properties": {
"host": {
"type": "string",
"format": "hostname"
},
"paths": {
"type": "array",
"items": {
"type": "object",
"properties": {
"path": {
"type": "string"
},
"pathType": {
"type": "string",
"enum": ["Prefix", "Exact", "ImplementationSpecific"]
}
}
}
}
}
}
}
}
},
"persistence": {
"type": "object",
"properties": {
"enabled": {
"type": "boolean",
"description": "Enable persistent storage"
},
"existingClaim": {
"type": "string",
"description": "Use existing PVC"
},
"storageClass": {
"type": "string",
"description": "Storage class name"
},
"accessMode": {
"type": "string",
"enum": ["ReadWriteOnce", "ReadOnlyMany", "ReadWriteMany", "ReadWriteOncePod"],
"description": "PVC access mode"
},
"size": {
"type": "string",
"pattern": "^[0-9]+[EPTGMK]i?$",
"description": "Storage size (e.g., 8Gi)"
}
}
},
"server": {
"type": "object",
"properties": {
"resources": {
"type": "object",
"description": "Resource requests and limits"
},
"env": {
"type": "array",
"description": "Environment variables"
},
"secretEnv": {
"type": "object",
"properties": {
"create": {
"type": "boolean"
},
"name": {
"type": "string"
},
"data": {
"type": "object"
}
}
}
}
},
"agent": {
"type": "object",
"properties": {
"enabled": {
"type": "boolean",
"description": "Enable Docker monitoring agent"
},
"kind": {
"type": "string",
"enum": ["DaemonSet", "Deployment"],
"description": "Agent deployment type"
}
}
},
"monitoring": {
"type": "object",
"properties": {
"serviceMonitor": {
"type": "object",
"properties": {
"enabled": {
"type": "boolean",
"description": "Create ServiceMonitor for Prometheus"
},
"interval": {
"type": "string",
"pattern": "^[0-9]+[smh]$",
"description": "Scrape interval (e.g., 30s)"
},
"path": {
"type": "string",
"description": "Metrics endpoint path"
}
}
}
}
}
}
}

View File

@@ -138,3 +138,14 @@ agent:
hostPathType: Socket
extraVolumes: []
extraVolumeMounts: []
# Monitoring configuration
monitoring:
serviceMonitor:
enabled: false
interval: 30s
scrapeTimeout: 10s
path: /metrics
labels: {}
relabelings: []
metricRelabelings: []