.gemini/skills/kubernetes-deployment-validator/SKILL.md
Validate Kubernetes deployments before execution. Run pre-flight checks for password generation, environment variables, database authentication, CORS configuration, and docker-compose parity. Use this skill BEFORE every Helm install/upgrade to prevent deployment failures.
npx skillsauth add anasahmed07/doit kubernetes-deployment-validatorInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Pre-flight validation checks for Kubernetes deployments to prevent common configuration errors and deployment failures.
ALWAYS run BEFORE:
helm install or helm upgradeWhat to Check:
Validation:
# Test password generation
PASSWORD=$(openssl rand -hex 16)
echo "Generated password: $PASSWORD"
# Check for URL-encoding issues (should have NONE with hex)
echo "$PASSWORD" | grep -E '[+/=]' && echo "❌ FAIL: Special chars found" || echo "✅ PASS: Alphanumeric only"
# Test with PostgreSQL
echo "Testing PostgreSQL authentication with generated password..."
PGPASSWORD="$PASSWORD" psql -h localhost -p 5432 -U test_user -d postgres -c "SELECT 1;"
Pass Criteria:
openssl rand -hex (alphanumeric only)+, /, =Fail Indicators:
openssl rand -base64 (contains special chars)Fix:
# Wrong
POSTGRES_PASSWORD=$(openssl rand -base64 16) # ❌ Can generate: xK+3/zA9=mQ2pL1w
# Right
POSTGRES_PASSWORD=$(openssl rand -hex 16) # ✅ Always generates: dadaf807863a952b
What to Check: Complete path from .env → Helm → ConfigMap/Secret → Pod → Application
Validation:
# Check .env file
echo "📄 Checking .env file..."
grep -E "(SMTP_|EMAIL_|NODE_ENV|ALLOWED_ORIGINS)" .env
# Simulate Helm deployment (dry-run)
echo "🎯 Checking Helm values..."
helm template taskflow ./helm/taskflow --set sso.smtp.password="test" | grep -A5 ConfigMap
# Verify variables would reach pod
echo "🔍 Checking environment injection..."
helm template taskflow ./helm/taskflow | grep -E "(SMTP|NODE_ENV|ALLOWED_ORIGINS)" | head -20
Pass Criteria:
Fail Indicators:
Fix:
# 1. Add to values.yaml
sso:
smtp:
enabled: true
host: smtp.gmail.com
password: changeme # Override with --set
# 2. Add to ConfigMap (non-sensitive)
data:
SMTP_HOST: {{ .Values.sso.smtp.host }}
# 3. Add to Secret (sensitive)
stringData:
SMTP_PASS: {{ .Values.sso.smtp.password }}
# 4. Inject in Deployment
envFrom:
- configMapRef:
name: sso-config
env:
- name: SMTP_PASS
valueFrom:
secretKeyRef:
name: sso-secret
key: SMTP_PASS
What to Check:
Validation:
# Get password from Secret
SECRET_PASSWORD=$(kubectl get secret sso-postgres-secret -n taskflow -o jsonpath='{.data.POSTGRES_PASSWORD}' | base64 -d 2>/dev/null || echo "none")
# Test connection with Secret password
echo "Testing database connection with Secret password..."
PGPASSWORD="$SECRET_PASSWORD" psql -h localhost -p 5432 -U sso_user -d sso_db -c "SELECT 1;" 2>&1
# Check for auth errors
kubectl logs -n taskflow -l app.kubernetes.io/component=sso --tail=50 | grep -i "password authentication failed"
Pass Criteria:
Fail Indicators:
Fix:
# Reset database password to match Secret
PASSWORD=$(kubectl get secret sso-postgres-secret -n taskflow -o jsonpath='{.data.POSTGRES_PASSWORD}' | base64 -d)
kubectl exec -n taskflow sso-postgres-0 -- sh -c "
PGPASSWORD='old_password' psql -U sso_user -d postgres -c \"ALTER USER sso_user WITH PASSWORD '$PASSWORD';\"
"
# Restart application pods
kubectl delete pod -n taskflow -l app.kubernetes.io/component=sso
What to Check:
Validation:
# Check Helm values
echo "📋 Checking CORS configuration..."
helm get values taskflow -n taskflow | grep -E "(NODE_ENV|BETTER_AUTH_URL|ALLOWED_ORIGINS)"
# Verify in pod (after deployment)
echo "🔍 Verifying in pod..."
kubectl exec -n taskflow -l app.kubernetes.io/component=sso -- sh -c 'env | grep -E "(NODE_ENV|BETTER_AUTH_URL|ALLOWED_ORIGINS)"'
# Test CORS headers
echo "🌐 Testing CORS headers..."
curl -X OPTIONS http://localhost:3001/api/auth/session \
-H "Origin: http://localhost:3000" \
-H "Access-Control-Request-Method: POST" \
-v 2>&1 | grep -i "access-control"
Pass Criteria:
Fail Indicators:
Fix (Development):
sso:
env:
NODE_ENV: development # Not production!
BETTER_AUTH_URL: http://localhost:3001 # Not http://sso.taskflow.local
ALLOWED_ORIGINS: "http://localhost:3000,http://localhost:3001"
Fix (Production):
sso:
env:
NODE_ENV: production
BETTER_AUTH_URL: https://sso.taskflow.com # HTTPS domain
ALLOWED_ORIGINS: "https://app.taskflow.com,https://dashboard.taskflow.com"
What to Check:
Validation:
# List docker-compose services
echo "📦 docker-compose services:"
docker-compose config --services
# List Kubernetes services
echo "☸️ Kubernetes services:"
kubectl get svc -n taskflow -o custom-columns=NAME:.metadata.name
# Check for common dev tools
echo "🔍 Checking dev tools..."
kubectl get deployment -n taskflow | grep -E "(pgadmin|redis-commander|mailhog)"
Pass Criteria:
Fail Indicators:
Fix:
# Add pgAdmin to Kubernetes
./scripts/add-pgadmin.sh
# Add any missing services
helm upgrade taskflow ./helm/taskflow \
--set pgadmin.enabled=true \
--set redisCommander.enabled=true
What to Check:
Validation:
# Check .env
echo "📧 Checking SMTP in .env..."
grep -E "SMTP_" .env
# Check Helm values
echo "📋 Checking SMTP in Helm..."
helm get values taskflow -n taskflow | grep -A6 smtp
# Check pod environment
echo "🔍 Checking SMTP in pod..."
kubectl exec -n taskflow -l app.kubernetes.io/component=sso -- sh -c 'env | grep -E "(SMTP|EMAIL)" | sort'
Pass Criteria:
Fail Indicators:
Fix:
# Deploy with SMTP support
export $(grep -v '^#' .env | xargs)
helm upgrade taskflow ./helm/taskflow \
--set sso.smtp.password="${SMTP_PASS}" \
--wait
# Restart SSO pod
kubectl delete pod -n taskflow -l app.kubernetes.io/component=sso
Create .spec/scripts/validate-deployment.sh:
#!/usr/bin/env bash
set -euo pipefail
echo "🚀 Kubernetes Deployment Pre-Flight Checks"
echo "=========================================="
echo ""
FAILED=0
# 1. Password Generation
echo "1️⃣ Validating password generation strategy..."
PASSWORD=$(openssl rand -hex 16)
if echo "$PASSWORD" | grep -qE '[+/=]'; then
echo " ❌ FAIL: Password contains URL-encoding characters"
FAILED=$((FAILED + 1))
else
echo " ✅ PASS: Alphanumeric-only passwords"
fi
echo ""
# 2. Environment Variables
echo "2️⃣ Validating environment variable flow..."
if [ ! -f .env ]; then
echo " ❌ FAIL: .env file not found"
FAILED=$((FAILED + 1))
elif ! grep -q "SMTP_HOST" .env; then
echo " ⚠️ WARN: SMTP_HOST not in .env"
else
echo " ✅ PASS: .env file complete"
fi
echo ""
# 3. Helm Values
echo "3️⃣ Validating Helm values..."
if helm template taskflow ./helm/taskflow 2>/dev/null | grep -q "SMTP_HOST"; then
echo " ✅ PASS: SMTP configuration in Helm"
else
echo " ❌ FAIL: SMTP not configured in Helm"
FAILED=$((FAILED + 1))
fi
echo ""
# 4. CORS Configuration
echo "4️⃣ Validating CORS configuration..."
NODE_ENV=$(helm get values taskflow -n taskflow 2>/dev/null | grep "NODE_ENV" | awk '{print $2}' || echo "none")
if [ "$NODE_ENV" == "development" ]; then
echo " ✅ PASS: NODE_ENV=development for localhost"
elif [ "$NODE_ENV" == "production" ]; then
echo " ⚠️ WARN: NODE_ENV=production (ensure HTTPS URLs)"
else
echo " ❌ FAIL: NODE_ENV not set"
FAILED=$((FAILED + 1))
fi
echo ""
# 5. Summary
echo "=========================================="
if [ $FAILED -eq 0 ]; then
echo "✅ All checks passed! Ready to deploy."
exit 0
else
echo "❌ $FAILED check(s) failed. Fix issues before deploying."
exit 1
fi
# Run pre-flight checks
./scripts/validate-deployment.sh
# If all pass, deploy
./scripts/deploy-one-command.sh
# Verify everything works
./scripts/verify-deployment.sh
Symptom: Pods stuck in CrashLoopBackOff with "password authentication failed" errors
Cause: base64 passwords with special characters
Prevention:
# Before deployment, verify password generation
PASSWORD=$(openssl rand -hex 16)
echo "$PASSWORD" | grep -E '[+/=]' && echo "FAIL" || echo "PASS"
Symptom: OAuth flow fails with "Invalid origin" error
Cause: NODE_ENV=production with HTTP localhost URLs
Prevention:
# Before deployment, check CORS configuration
helm template taskflow ./helm/taskflow | grep -E "(NODE_ENV|ALLOWED_ORIGINS)"
Symptom: Email verification doesn't send emails
Cause: SMTP variables not propagated to pod
Prevention:
# Before deployment, verify SMTP configuration
helm template taskflow ./helm/taskflow | grep -B2 -A2 "SMTP_HOST"
# .github/workflows/deploy.yml
- name: Validate Deployment Configuration
run: ./scripts/validate-deployment.sh
- name: Deploy to Kubernetes
if: success()
run: ./scripts/deploy-one-command.sh
kubernetes-postgres-ops skill for database managementhelm-charts skill for Helm best practicesbetter-auth-sso/references/cors-configuration.md for CORS detailsbetter-auth-sso/references/smtp-configuration.md for SMTP detailsWhat to Check:
| default "password" patterns with different defaultsValidation:
# Check for hardcoded passwords in values.yaml
echo "🔍 Checking for hardcoded DATABASE_URL passwords..."
grep -n "databaseUrl.*://" helm/taskflow/values.yaml | grep -v "{{" && echo "❌ FAIL: Hardcoded passwords in URLs" || echo "✅ PASS"
# Check for scattered defaults in secrets.yaml
echo "🔍 Checking for inconsistent password defaults..."
grep -o 'default "[^"]*password[^"]*"' helm/taskflow/templates/secrets.yaml | sort | uniq -c | awk '$1 > 1 {print "❌ FAIL: Multiple different defaults found"; exit 1}'
echo "✅ PASS: No scattered password defaults"
# Verify single source definition
echo "🔍 Verifying single source in values.yaml..."
grep -n "password:" helm/taskflow/values.yaml
Pass Criteria:
values.yaml has explicit password: field for each databasesecrets.yaml templates ALL passwords from values.yaml| default "changeme-xyz" patterns with varying defaultsFail Indicators:
databaseUrl: "postgresql://user:hardcoded-password@..." in values.yaml| default "changeme-xxx-password" with different valuesCorrect Pattern:
# values.yaml - SINGLE SOURCE
api:
postgresql:
password: "changeme-api-db" # THE source
# secrets.yaml - TEMPLATE from source
stringData:
POSTGRES_PASSWORD: {{ .Values.api.postgresql.password | quote }}
DATABASE_URL: "postgresql://{{ .Values.api.database.user }}:{{ .Values.api.postgresql.password }}@..."
CHATKIT_DATABASE_URL: "postgresql://{{ .Values.api.database.user }}:{{ .Values.api.postgresql.password }}@..."
Anti-Pattern (12 hours of debugging):
# values.yaml - SCATTERED
chatkit:
databaseUrl: "postgresql://user:changeme-api-db-password@..." # HARDCODED!
# secrets.yaml - DIFFERENT DEFAULT
POSTGRES_PASSWORD: {{ .Values.api.postgresql.password | default "changeme-api-db-password" }}
# ^ What if values.yaml says "changeme-api-db" but default says "changeme-api-db-password"?
Fix:
development
Use when building real-time communication systems with WebSockets or Socket.IO. Invoke for bidirectional messaging, horizontal scaling with Redis, presence tracking, room management.
development
Review UI code for Web Interface Guidelines compliance. Use when asked to "review my UI", "check accessibility", "audit design", "review UX", or "check my site against best practices".
development
React and Next.js performance optimization guidelines from Vercel Engineering. This skill should be used when writing, reviewing, or refactoring React/Next.js code to ensure optimal performance patterns. Triggers on tasks involving React components, Next.js pages, data fetching, bundle optimization, or performance improvements.
tools
Guide for creating effective skills. This skill should be used when users want to create a new skill (or update an existing skill) that extends Claude's capabilities with specialized knowledge, workflows, or tool integrations.