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:
parent
3a260a3130
commit
036673e783
5 changed files with 308 additions and 0 deletions
56
.github/workflows/helm-pages.yml
vendored
56
.github/workflows/helm-pages.yml
vendored
|
|
@ -31,6 +31,29 @@ jobs:
|
||||||
with:
|
with:
|
||||||
version: v3.15.2
|
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
|
- name: Determine chart version
|
||||||
id: version
|
id: version
|
||||||
run: |
|
run: |
|
||||||
|
|
@ -73,6 +96,39 @@ jobs:
|
||||||
|
|
||||||
echo "✓ Chart validation passed"
|
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
|
- name: Run chart-releaser
|
||||||
uses: helm/chart-releaser-action@v1.6.0
|
uses: helm/chart-releaser-action@v1.6.0
|
||||||
with:
|
with:
|
||||||
|
|
|
||||||
|
|
@ -19,3 +19,22 @@ annotations:
|
||||||
org.opencontainers.image.source: https://github.com/rcourtman/Pulse
|
org.opencontainers.image.source: https://github.com/rcourtman/Pulse
|
||||||
org.opencontainers.image.description: Helm chart for deploying Pulse monitoring system
|
org.opencontainers.image.description: Helm chart for deploying Pulse monitoring system
|
||||||
org.opencontainers.image.licenses: MIT
|
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
|
||||||
|
|
|
||||||
33
deploy/helm/pulse/templates/servicemonitor.yaml
Normal file
33
deploy/helm/pulse/templates/servicemonitor.yaml
Normal 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 }}
|
||||||
189
deploy/helm/pulse/values.schema.json
Normal file
189
deploy/helm/pulse/values.schema.json
Normal 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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -138,3 +138,14 @@ agent:
|
||||||
hostPathType: Socket
|
hostPathType: Socket
|
||||||
extraVolumes: []
|
extraVolumes: []
|
||||||
extraVolumeMounts: []
|
extraVolumeMounts: []
|
||||||
|
|
||||||
|
# Monitoring configuration
|
||||||
|
monitoring:
|
||||||
|
serviceMonitor:
|
||||||
|
enabled: false
|
||||||
|
interval: 30s
|
||||||
|
scrapeTimeout: 10s
|
||||||
|
path: /metrics
|
||||||
|
labels: {}
|
||||||
|
relabelings: []
|
||||||
|
metricRelabelings: []
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue