Skip to content

Kast Framework Good Practices Guide

A comprehensive guide to best practices, patterns, and anti-patterns for developing with the kast-system framework.

Table of Contents

  1. TDD Best Practices
  2. Glyph Development Best Practices
  3. Book/Chapter/Spell Organization
  4. Lexicon Design Guidelines
  5. Testing Patterns and Anti-Patterns
  6. Code Review Checklist
  7. Common Pitfalls and Solutions
  8. Performance Considerations
  9. Security Best Practices
  10. GitOps Workflow Recommendations

TDD Best Practices

TDD Cycle: Red-Green-Refactor

Understanding the Mechanics

The TDD commands have specific behaviors that enforce discipline:

Red Phase (make tdd-red) - Uses || operator to celebrate failures - Runs tests expecting them to fail - Confirms your test actually tests something - When to use: After writing new examples, before implementation

Green Phase (make tdd-green) - Direct execution, no error suppression - Tests MUST pass or Make exits with error - Confirms your implementation works - When to use: After implementing features

Refactor Phase (make tdd-refactor) - Runs comprehensive test suite (test-all) - Ensures refactoring didn't break anything - Includes snapshots, glyphs, and all validations - When to use: After improving code quality

Core Rules

  1. ALWAYS write tests first

    # DO THIS
    make create-example CHART=summon EXAMPLE=new-feature
    # Edit the example file
    make tdd-red
    # Implement feature
    make tdd-green
    
    # DON'T DO THIS
    # Implement feature first, then add tests
    

  2. One test at a time

  3. Focus on making ONE test pass
  4. Don't write multiple failing tests
  5. Each test should validate one specific behavior

  6. Minimal implementation

    // RED: Test expects PodDisruptionBudget
    // GREEN: Add minimal template to generate PDB
    // REFACTOR: Add validation, defaults, documentation
    

  7. Never skip the red phase

  8. If test passes immediately, it might not be testing anything
  9. Seeing it fail confirms it's actually validating behavior

  10. Commit only passing tests

  11. All tests must pass before committing
  12. Run make test-all before every commit

TDD Workflow Patterns

Adding New Chart Features

# 1. RED PHASE - Write failing test
make create-example CHART=summon EXAMPLE=pod-disruption
cat > charts/summon/examples/pod-disruption.yaml <<EOF
workload:
  enabled: true
  type: deployment
  replicas: 3

podDisruptionBudget:
  enabled: true
  minAvailable: 2
EOF

# 2. Verify failure
make tdd-red
# Output: [FAIL] summon-pod-disruption (expectations failed)
#         [OK] Good! Tests are failing - now implement

# 3. GREEN PHASE - Implement
# Create charts/summon/templates/pod-disruption-budget.yaml

# 4. Verify success
make tdd-green
# Output: [PASS] summon-pod-disruption

# 5. REFACTOR PHASE - Improve
# Add validation, defaults, documentation
make tdd-refactor
# Output: [PASS] All tests pass

Adding New Glyph Features

# 1. RED PHASE - Create example
cat > charts/glyphs/vault/examples/dynamic-db-creds.yaml <<EOF
glyphs:
  vault:
    - type: databaseRole
      name: app-db-access
      enabled: true
EOF

# 2. Test failure
make glyphs vault
# Output: [FAIL] vault-dynamic-db-creds (template not found)

# 3. GREEN PHASE - Implement template
# Create charts/glyphs/vault/templates/database-role.tpl

# 4. Test success
make glyphs vault
# Output: [PASS] vault-dynamic-db-creds

# 5. Lock in expected output
make generate-expected GLYPH=vault

# 6. REFACTOR PHASE
make glyphs vault
# Output: [PASS] vault-dynamic-db-creds (output matches expected)

Five Whys for Problem Solving

When encountering errors, ask "Why?" five times to find root causes:

Problem: Tests failing after adding new feature

Why? → Template rendering fails
Why? → Missing parameter validation
Why? → Parameter extraction pattern wrong
Why? → Using . instead of (list $root $glyph)
Why? → Didn't follow coding standards

Root Cause: Need to standardize parameter passing across all templates
Solution: Update template to use standard pattern + add validation

Test-First Thinking

Good example:

# Write this FIRST (the test)
workload:
  enabled: true
  type: statefulset
  volumeClaimTemplates:
    data:
      size: 10Gi
      storageClass: fast-ssd

# Then implement the feature
# Then verify it works

Bad example:

# Implementing features then trying to write tests that match
# This leads to confirmation bias and weak tests


Glyph Development Best Practices

Template Structure Standards

Standard Glyph Template Pattern

{{/*kast - Kubernetes arcane spelling technology
Copyright (C) 2023 namenmalkv@gmail.com
Licensed under the GNU GPL v3. See LICENSE file for details.

glyph.resourceType creates [description].
[Optional: Integration details, special behavior]

Parameters:
- $root: Chart root context (index . 0)
- $glyphDefinition: [Resource] configuration object (index . 1)

Required Configuration:
- glyphDefinition.requiredField: [description]

Optional Configuration:
- glyphDefinition.optionalField: [description with default]

Usage: {{- include "glyph.resourceType" (list $root $glyph) }}
*/}}
{{- define "glyph.resourceType" }}
{{- $root := index . 0 -}}
{{- $glyphDefinition := index . 1 }}

{{/* Parameter validation */}}
{{- if not $glyphDefinition.enabled }}
{{- else }}

{{/* Optional: External system integration */}}
{{- $externalResources := get (include "runicIndexer.runicIndexer"
    (list $root.Values.lexicon
          (default dict $glyphDefinition.selector)
          "resource-type"
          $root.Values.chapter.name) | fromJson) "results" }}

{{/* Resource generation */}}
{{- range $resource := $externalResources }}
---
apiVersion: {api.version}
kind: {ResourceKind}
metadata:
  name: {{ default (include "common.name" $root) $glyphDefinition.nameOverride }}
  labels:
    {{- include "common.labels" $root | nindent 4 }}
spec:
  # Resource-specific configuration
{{- end }}
{{- end }}
{{- end }}

Naming Conventions

Template Names

// [CORRECT]:
{{- define "istio.virtualService" }}
{{- define "vault.secret" }}
{{- define "summon.persistentVolumeClaim" }}
{{- define "certManager.certificate" }}

// [INCORRECT]:
{{- define "summon.pvc" }}              // Abbreviation
{{- define "istio.vs" }}                // Abbreviation
{{- define "summon.persistante" }}      // Typo
{{- define "summon.statefullSet" }}     // Typo

File Names

[CORRECT]:
- virtualService.tpl
- persistentVolumeClaim.tpl
- certificate.yaml
- _helpers.tpl

[INCORRECT]:
- pvc.tpl                    # Abbreviation
- VirtualService.tpl         # Capital letter
- secret-template.tpl        # Redundant suffix

Parameter Passing

Standard Pattern (ALWAYS use this)

{{- define "glyph.template" }}
{{- $root := index . 0 -}}
{{- $glyphDefinition := index . 1 }}

// Access glyph configuration
name: {{ $glyphDefinition.name }}
enabled: {{ default true $glyphDefinition.enabled }}

// Access root context
release: {{ $root.Release.Name }}
namespace: {{ $root.Release.Namespace }}
{{- end }}

// Invocation
{{- include "glyph.template" (list $root $glyphDefinition) }}

Common Glyph Exception

// Common glyph templates take $root directly (not list)
{{- include "common.name" $root }}
{{- include "common.labels" $root | nindent 4 }}

Validation and Defaults

Always Validate Required Fields

{{- if not $glyphDefinition.name }}
  {{- fail "glyph.resource requires 'name' field" }}
{{- end }}

{{- if not (hasKey $glyphDefinition "type") }}
  {{- fail "glyph.resource requires 'type' field" }}
{{- end }}

{{- if and $glyphDefinition.replicas (lt ($glyphDefinition.replicas | int) 0) }}
  {{- fail "replicas must be >= 0" }}
{{- end }}

Provide Sensible Defaults

// Simple default
enabled: {{ default true $glyphDefinition.enabled }}
replicas: {{ default 1 $glyphDefinition.replicas }}

// Conditional default
timeout: {{ default (ternary 300 60 $glyphDefinition.production) $glyphDefinition.timeout }}

// Default from root values
image: {{ default $root.Values.defaultImage $glyphDefinition.image }}

Single Responsibility Principle

// [GOOD]: One template per resource type
{{- define "myglyph.deployment" }}    // Generates Deployment
{{- define "myglyph.service" }}       // Generates Service
{{- define "myglyph.configmap" }}     // Generates ConfigMap

// [BAD]: One template generating multiple unrelated resources
{{- define "myglyph.everything" }}    // Generates Deployment + Service + ConfigMap

Book/Chapter/Spell Organization

Book Structure

# bookrack/my-book/index.yaml
name: my-book

# Trinkets (special charts)
trinkets:
  kaster:
    key: glyphs
    repository: https://github.com/kast-spells/kast-system.git
    path: ./charts/kaster
    revision: master

# Default trinket for regular spells
defaultTrinket:
  repository: https://github.com/kast-spells/kast-system.git
  path: ./charts/summon
  revision: master

# Book-wide appendix (shared configuration)
appendix:
  lexicon:
    # Infrastructure resources available to all chapters

# Chapters (environments/namespaces)
chapters:
  - development
  - staging
  - production

Chapter Organization

bookrack/my-book/
├── index.yaml                      # Book definition
├── _appendix/
│   └── lexicon.yaml               # Book-wide infrastructure
├── development/
│   ├── values.yaml                # Chapter configuration
│   ├── service-a/
│   │   └── values.yaml           # Spell for service-a
│   └── service-b/
│       └── values.yaml           # Spell for service-b
├── staging/
│   ├── values.yaml
│   ├── service-a/
│   │   └── values.yaml
│   └── service-b/
│       └── values.yaml
└── production/
    ├── values.yaml
    ├── service-a/
    │   └── values.yaml
    └── service-b/
        └── values.yaml

Spell (Application) Organization

Basic Spell Structure

# bookrack/my-book/production/my-app/values.yaml

# Workload configuration
workload:
  enabled: true
  type: deployment
  replicas: 3

# Container image
image:
  name: myapp
  tag: v1.2.3
  pullPolicy: IfNotPresent

# Service exposure
service:
  enabled: true
  type: ClusterIP
  ports:
    - port: 80
      name: http

# Glyphs (infrastructure integrations)
glyphs:
  istio:
    external-route:
      type: virtualService
      enabled: true
      selector:
        access: external
        environment: production

  vault:
    db-credentials:
      type: secret
      enabled: true
      format: env
      keys:
        - DB_USERNAME
        - DB_PASSWORD

Hierarchical Configuration Strategy

Appendix (Book-wide)

Use for: - Shared infrastructure (databases, message queues) - Organization-wide defaults - Cross-chapter resources

# _appendix/lexicon.yaml
appendix:
  lexicon:
    - name: org-wide-vault
      type: vault
      url: https://vault.company.com
      labels:
        default: book

Chapter Values

Use for: - Environment-specific configuration - Chapter-wide defaults - Resource quotas and limits

# production/values.yaml
chapter:
  name: production
  namespace: production

# Environment-specific infrastructure
lexicon:
  - name: production-database
    type: database
    host: postgres.prod.svc
    labels:
      environment: production
      default: chapter

Spell Values

Use for: - Application-specific configuration - Service parameters - Feature flags

# production/my-app/values.yaml
workload:
  enabled: true
  replicas: 5  # Production needs more replicas

resources:
  limits:
    memory: 2Gi  # Production needs more memory

Configuration Inheritance

Book Appendix (lowest priority)
Chapter Values (medium priority)
Spell Values (highest priority)

Example:

# Book appendix: 1 replica default
# Chapter values: 2 replicas for staging
# Spell values: 5 replicas for critical service
# Result: Spell gets 5 replicas


Lexicon Design Guidelines

Resource Entry Structure

lexicon:
  - name: descriptive-unique-name
    type: resource-type
    labels:
      # Selection labels
      environment: production
      region: us-west-2
      tier: primary
      # Default strategy
      default: book|chapter
    # Resource-specific fields
    field1: value1
    field2: value2

Label Design Patterns

Hierarchical Labels

labels:
  # Broadest - Environment
  environment: production

  # Medium - Access/Region
  access: external
  region: us-west-2

  # Narrowest - Specific features
  ssl: enabled
  tier: primary

Default Strategy

Book Default - Organization-wide fallback:

labels:
  default: book
# Used when: No exact match and no chapter default

Chapter Default - Environment-specific fallback:

labels:
  default: chapter
  environment: production
chapter: production
# Used when: No exact match in current chapter

No Default - Must be explicitly selected:

labels:
  access: admin-only
  security-level: high
# Used when: Must never be selected accidentally

Resource Type Conventions

# Infrastructure types
type: istio-gw          # Istio Gateway
type: vault             # Vault server
type: database          # Database server
type: eventbus          # Argo Events EventBus
type: storage-class     # StorageClass

# Integration types
type: oauth-provider    # OAuth/OIDC provider
type: monitoring        # Monitoring system
type: logging           # Logging aggregator

Naming Best Practices

# [GOOD]: Descriptive and specific
- name: external-production-gateway
- name: vault-production-server
- name: postgres-primary-database
- name: jetstream-production-eventbus

# [BAD]: Vague and ambiguous
- name: gateway1
- name: server
- name: db
- name: bus

Lexicon Organization

Book-Level Lexicon

# _appendix/infrastructure.yaml
appendix:
  lexicon:
    # Shared across all chapters
    - name: org-wide-vault
      type: vault
      labels:
        default: book
      url: https://vault.company.com

    # Production-only (no default)
    - name: production-database
      type: database
      labels:
        environment: production
      host: postgres.prod.svc

Chapter-Level Lexicon

# staging/values.yaml
lexicon:
  # Chapter-specific resources
  - name: staging-gateway
    type: istio-gw
    labels:
      environment: staging
      default: chapter
    chapter: staging
    gateway: istio-system/staging-gateway

Selector Design

Start Broad, Get Specific

Development:

selector:
  environment: dev  # Broad - matches any dev resource

Production:

selector:
  environment: production
  region: us-west-2
  tier: primary  # Specific - matches exact resource

Using Fallbacks

# Try specific resource
selector:
  environment: production
  region: us-west-2

# If no match, falls back to:
# 1. Chapter default (if in production chapter)
# 2. Book default (organization-wide)

Testing Patterns and Anti-Patterns

Testing Patterns (DO THESE)

1. Comprehensive Example Coverage

charts/summon/examples/
├── basic-deployment.yaml          # Minimal valid configuration
├── statefulset-with-storage.yaml  # StatefulSet with PVCs
├── job-with-config.yaml           # Job workload
├── cronjob-schedule.yaml          # CronJob workload
├── complex-production.yaml        # All features enabled
├── autoscaling.yaml               # HPA configuration
└── service-mesh.yaml              # Istio integration

2. Resource Completeness Validation

The validation script ensures all expected resources are generated:

# Example expectations:
# workload.enabled=true → Must generate Deployment/StatefulSet/Job
# service.enabled=true → Must generate Service
# autoscaling.enabled=true → Must generate HPA
# volumes.*.type=pvc → Must generate PVC (if not volumeClaimTemplate)

3. Snapshot Testing

# Generate snapshots for new features
make generate-snapshots CHART=summon

# Update snapshot after intentional changes
make update-snapshot CHART=summon EXAMPLE=basic-deployment

# Show differences
make show-snapshot-diff CHART=summon EXAMPLE=basic-deployment

4. Glyph Testing Through Kaster

# Correct: Test glyph through kaster orchestration
make glyphs vault

# Incorrect: Test glyph directly (will fail)
helm template charts/glyphs/vault

5. Covenant Book Testing

# Test main covenant (ApplicationSet generation)
make test-covenant-book BOOK=covenant-tyl

# Test specific chapter
make test-covenant-chapter BOOK=covenant-tyl CHAPTER=tyl

# Test all chapters (RECOMMENDED)
make test-covenant-all-chapters BOOK=covenant-tyl

Testing Anti-Patterns (AVOID THESE)

1. Implementation-First Testing

# Bad: Writing tests to match existing implementation
# This leads to weak tests that don't validate behavior

# Good: Write tests defining expected behavior first
# Then implement to make tests pass

2. Single Example per Chart

# [BAD]:
charts/summon/examples/
└── basic.yaml  # Only one scenario

# [GOOD]:
charts/summon/examples/
├── basic-deployment.yaml
├── statefulset-with-storage.yaml
├── complex-production.yaml
└── autoscaling.yaml

3. Ignoring Test Failures

# [BAD]: Continuing development with failing tests
make test
# Output: Some tests failing
# Continues working on new features

# [GOOD]: Fix all failures before proceeding
make test
# Output: Some tests failing
# Stops, investigates, fixes root cause

4. Manual Testing Only

# [BAD]: Only testing manually with kubectl
helm install test-release charts/summon
kubectl get pods

# [GOOD]: Automated testing with TDD commands
make test-all

5. Not Testing Edge Cases

# [BAD]: Only testing happy path
workload:
  enabled: true
  replicas: 2

# [GOOD]: Testing edge cases
workload:
  enabled: false  # Disabled workload
  replicas: 0     # Zero replicas
# (empty)         # Missing configuration

Test Coverage Checklist

  • Basic configuration (minimal valid input)
  • Advanced configuration (all features enabled)
  • Edge cases (empty, zero, nil values)
  • Validation errors (invalid inputs should fail)
  • Integration scenarios (multiple glyphs together)
  • Resource completeness (all expected K8s resources)
  • Snapshot matching (output matches expected)
  • K8s schema validation (dry-run succeeds)

Code Review Checklist

Pre-Review (Author)

  • All tests passing (make test-all)
  • TDD cycle followed (Red → Green → Refactor)
  • Examples added for new features
  • Snapshots generated/updated
  • Documentation updated
  • Copyright headers present
  • No hardcoded values (use lexicon/runic indexer)
  • Validation for required parameters
  • Sensible defaults for optional parameters

Template Review

  • Follows naming conventions (no abbreviations, correct spelling)
  • Standard parameter pattern: (list $root $glyphDefinition)
  • Uses common glyph for labels/names
  • Proper documentation header
  • Error messages are informative
  • No deprecated functions
  • Conditional resources use {{- if }} properly

Testing Review

  • Examples cover all code paths
  • Edge cases tested
  • Resource completeness validated
  • Snapshots match expected output
  • Integration with other glyphs tested

Documentation Review

  • Template parameters documented
  • Usage examples provided
  • Integration points explained (runic indexer, lexicon)
  • Special behaviors noted
  • Added to relevant reference docs

Security Review

  • No secrets in values files
  • Secrets managed through Vault
  • RBAC properly configured
  • Network policies considered
  • No privileged containers (unless required + documented)

Common Pitfalls and Solutions

1. Wrong Parameter Pattern

Pitfall

{{- define "myglyph.resource" }}
{{- $root := . }}  // [INCORRECT] Wrong!
{{- $glyph := .Values.glyph }}  // [INCORRECT] Wrong!

Solution

{{- define "myglyph.resource" }}
{{- $root := index . 0 -}}  // [CORRECT]
{{- $glyphDefinition := index . 1 }}  // [CORRECT]

2. Testing Glyphs Directly

Pitfall

# [FAIL] This will fail
helm template charts/glyphs/vault

Solution

# [CORRECT] Test through kaster
make glyphs vault

3. Hardcoded Infrastructure References

Pitfall

# [INCORRECT] Hardcoded gateway
spec:
  gateways:
    - istio-system/external-gateway

Solution

// [CORRECT] Use runic indexer
{{- $gateways := get (include "runicIndexer.runicIndexer"
    (list $root.Values.lexicon $glyphDefinition.selector "istio-gw" $root.Values.chapter.name)
    | fromJson) "results" }}
{{- range $gateway := $gateways }}
spec:
  gateways:
    - {{ $gateway.gateway }}
{{- end }}

4. Missing Validation

Pitfall

{{- define "myglyph.resource" }}
// [INCORRECT] No validation - will fail with cryptic error
name: {{ $glyphDefinition.name }}

Solution

{{- define "myglyph.resource" }}
// [CORRECT] Validate required fields
{{- if not $glyphDefinition.name }}
  {{- fail "myglyph.resource requires 'name' field" }}
{{- end }}
name: {{ $glyphDefinition.name }}

5. No Defaults for Optional Fields

Pitfall

// [INCORRECT] Will fail if field not provided
replicas: {{ $glyphDefinition.replicas }}

Solution

// [CORRECT] Provide sensible default
replicas: {{ default 1 $glyphDefinition.replicas }}

6. Incorrect Common Glyph Usage

Pitfall

// [INCORRECT] Wrong - common glyph doesn't take list
{{- include "common.name" (list $root $glyph) }}

Solution

// [CORRECT] - common glyph takes $root directly
{{- include "common.name" $root }}

7. Not Following Five Whys

Pitfall

Error: Template rendering failed
Action: Change random things hoping to fix it
Result: More things broken

Solution

Error: Template rendering failed
Why? → Parameter access failed
Why? → $glyphDefinition is nil
Why? → Wrong parameter extraction pattern
Why? → Used . instead of (list $root $glyph)
Why? → Didn't follow coding standards
Fix: Update to standard parameter pattern

8. Skipping Test Phases

Pitfall

# [INCORRECT] Implementing without seeing tests fail
make create-example CHART=summon EXAMPLE=new-feature
# Edit template immediately
make tdd-green

Solution

# [CORRECT] Follow proper TDD cycle
make create-example CHART=summon EXAMPLE=new-feature
make tdd-red        # See it fail
# Edit template
make tdd-green      # See it pass
# Improve code
make tdd-refactor   # Verify still passes

Performance Considerations

Template Rendering Performance

Avoid Deep Nesting

// [BAD]: Deep nested loops
{{- range $chapter := .Values.chapters }}
  {{- range $spell := $chapter.spells }}
    {{- range $glyph := $spell.glyphs }}
      {{- range $resource := $glyph.resources }}
        // This is slow
      {{- end }}
    {{- end }}
  {{- end }}
{{- end }}

// [GOOD]: Flatten when possible
{{- $allResources := list }}
{{- range $chapter := .Values.chapters }}
  {{- $allResources = concat $allResources $chapter.resources }}
{{- end }}
{{- range $resource := $allResources }}
  // Process once
{{- end }}

Cache Expensive Operations

// [BAD]: Repeated expensive calls
{{- range $item := .Values.items }}
  name: {{ include "expensive.computation" $root }}
{{- end }}

// [GOOD]: Compute once, reuse
{{- $computedValue := include "expensive.computation" $root }}
{{- range $item := .Values.items }}
  name: {{ $computedValue }}
{{- end }}

Minimize Lexicon Queries

// [BAD]: Query lexicon in loop
{{- range $service := .Values.services }}
  {{- $gateway := get (include "runicIndexer.runicIndexer" ...) "results" }}
{{- end }}

// [GOOD]: Query once, reuse
{{- $gateways := get (include "runicIndexer.runicIndexer" ...) "results" }}
{{- range $service := .Values.services }}
  {{- range $gateway := $gateways }}
    // Use cached gateway
  {{- end }}
{{- end }}

Example File Size

Keep examples focused and reasonably sized:

# [GOOD]: Focused example (< 100 lines)
workload:
  enabled: true
  type: deployment

service:
  enabled: true

# [BAD]: Kitchen sink example (> 500 lines)
# Every possible configuration option
# Makes tests slow and hard to debug

Security Best Practices

Secret Management

Never Hardcode Secrets

# [INCORRECT] NEVER DO THIS
apiVersion: v1
kind: Secret
metadata:
  name: my-secret
stringData:
  password: "hardcoded-password"  # NEVER!

Use Vault Integration

# [CORRECT]: Use Vault glyph
glyphs:
  vault:
    my-secret:
      type: secret
      enabled: true
      format: env
      keys:
        - DB_PASSWORD
        - API_KEY

RBAC Configuration

Principle of Least Privilege

# [GOOD]: Minimal permissions
serviceAccount:
  enabled: true

rbac:
  enabled: true
  rules:
    - apiGroups: [""]
      resources: ["configmaps"]
      verbs: ["get", "list"]  # Only what's needed
# [BAD]: Excessive permissions
rbac:
  enabled: true
  rules:
    - apiGroups: ["*"]
      resources: ["*"]
      verbs: ["*"]  # Too permissive!

Network Policies

Default Deny

# [GOOD]: Explicit allow
networkPolicy:
  enabled: true
  policyTypes:
    - Ingress
    - Egress
  ingress:
    - from:
      - podSelector:
          matchLabels:
            app: allowed-app

Container Security

Non-Root Containers

# [GOOD]: Run as non-root
securityContext:
  runAsNonRoot: true
  runAsUser: 1000
  fsGroup: 1000
  capabilities:
    drop:
      - ALL
# [BAD]: Running as root
securityContext:
  runAsUser: 0  # Root user
  privileged: true  # Privileged container

Image Security

Use Specific Tags

# [GOOD]: Specific version
image:
  name: myapp
  tag: v1.2.3-sha256-abc123
  pullPolicy: IfNotPresent
# [BAD]: Latest tag
image:
  name: myapp
  tag: latest  # Unpredictable

Summary

Core Principles

  1. TDD is mandatory - Red → Green → Refactor
  2. Test first, implement second - Always
  3. Follow naming conventions - No abbreviations
  4. Use standard patterns - (list $root $glyphDefinition)
  5. Validate inputs - Fail fast with clear messages
  6. Provide defaults - Sensible fallbacks
  7. Document everything - Parameters, usage, examples
  8. Never hardcode - Use lexicon and runic indexer
  9. Security first - Vault, RBAC, least privilege
  10. GitOps workflow - Automated, repeatable, auditable

Quick Reference

# TDD Cycle
make tdd-red          # See it fail
make tdd-green        # Make it pass
make tdd-refactor     # Keep it passing

# Testing
make test-all         # Full test suite
make test-status      # Coverage report
make glyphs <name>    # Test specific glyph

# Development
make create-example CHART=<chart> EXAMPLE=<name>
make generate-snapshots CHART=<chart>
make update-snapshot CHART=<chart> EXAMPLE=<name>

Additional Resources


Remember: Good practices aren't just rules - they're lessons learned from mistakes. Follow them to avoid common pitfalls and build reliable, maintainable Kubernetes deployments.