Claude-skill-registry helm-argocd-gitops

Configure ArgoCD Applications and ApplicationSets for GitOps-based Helm deployments with sync policies and multi-environment support. Use when setting up ArgoCD Applications for Helm charts, configuring multi-environment deployments with ApplicationSets, implementing GitOps workflows, configuring sync policies and strategies, or setting up progressive delivery with Argo Rollouts.

install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/helm-argocd-gitops" ~/.claude/skills/majiayu000-claude-skill-registry-helm-argocd-gitops && rm -rf "$T"
manifest: skills/data/helm-argocd-gitops/SKILL.md
source content

Helm ArgoCD GitOps Integration

Purpose

Guide the configuration of ArgoCD Applications and ApplicationSets for GitOps-based Helm chart deployments with proper sync policies, multi-environment support, and progressive delivery patterns.

Basic ArgoCD Application Setup

Step 1: Create Basic Application

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: myapp
  namespace: argocd
  finalizers:
    - resources-finalizer.argocd.argoproj.io
spec:
  project: default

  source:
    repoURL: https://github.com/myorg/charts
    targetRevision: main
    path: charts/myapp
    helm:
      releaseName: myapp
      valueFiles:
        - values.yaml
        - values-prod.yaml
      parameters:
        - name: image.tag
          value: v1.0.0

  destination:
    server: https://kubernetes.default.svc
    namespace: myapp

  syncPolicy:
    automated:
      prune: false # Manual approval for deletions
      selfHeal: false # Manual approval for drift correction
    syncOptions:
      - CreateNamespace=true
      - PruneLast=true
    retry:
      limit: 5
      backoff:
        duration: 5s
        factor: 2
        maxDuration: 3m

Key configuration points:

  • ✅ Add finalizer to ensure clean deletion
  • ✅ Use multiple value files for environment overrides
  • ✅ Set
    PruneLast=true
    to delete resources in correct order
  • ✅ Configure retry with exponential backoff
  • ✅ Be cautious with
    automated.prune
    in production

Step 2: Deploy Application

# Create application
kubectl apply -f application.yaml

# Or use argocd CLI
argocd app create myapp \
  --repo https://github.com/myorg/charts \
  --path charts/myapp \
  --dest-server https://kubernetes.default.svc \
  --dest-namespace myapp \
  --values values.yaml \
  --values values-prod.yaml

# Sync application
argocd app sync myapp

# Get application status
argocd app get myapp

# View application diff
argocd app diff myapp

Multi-Environment with ApplicationSet

ApplicationSet for Multiple Environments

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: myapp-environments
  namespace: argocd
spec:
  generators:
    - list:
        elements:
          - env: dev
            cluster: https://dev.k8s.local
            namespace: myapp-dev
            autoPrune: "true"
            autoHeal: "true"
            imageTag: latest
          - env: staging
            cluster: https://staging.k8s.local
            namespace: myapp-staging
            autoPrune: "true"
            autoHeal: "true"
            imageTag: staging
          - env: prod
            cluster: https://prod.k8s.local
            namespace: myapp-prod
            autoPrune: "false" # Manual approval for prod
            autoHeal: "false"
            imageTag: v1.0.0

  template:
    metadata:
      name: "myapp-{{env}}"
      labels:
        environment: "{{env}}"
    spec:
      project: default
      source:
        repoURL: https://github.com/myorg/charts
        targetRevision: main
        path: charts/myapp
        helm:
          valueFiles:
            - values.yaml
            - environments/{{env}}/values.yaml
          parameters:
            - name: image.tag
              value: "{{imageTag}}"
      destination:
        server: "{{cluster}}"
        namespace: "{{namespace}}"
      syncPolicy:
        automated:
          prune: "{{autoPrune}}"
          selfHeal: "{{autoHeal}}"
        syncOptions:
          - CreateNamespace=true
          - PruneLast=true

ApplicationSet benefits:

  • ✅ Single source of truth for all environments
  • ✅ DRY principle - no duplicated manifests
  • ✅ Easy to add new environments
  • ✅ Consistent configuration with environment-specific overrides

Git-Based ApplicationSet (Auto-Discovery)

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: cluster-apps
  namespace: argocd
spec:
  generators:
    - git:
        repoURL: https://github.com/myorg/cluster-config
        revision: HEAD
        directories:
          - path: apps/*

  template:
    metadata:
      name: "{{path.basename}}"
    spec:
      project: default
      source:
        repoURL: https://github.com/myorg/cluster-config
        targetRevision: HEAD
        path: "{{path}}"
        helm:
          valueFiles:
            - values.yaml
            - ../common-values.yaml
      destination:
        server: https://kubernetes.default.svc
        namespace: "{{path.basename}}"
      syncPolicy:
        automated:
          prune: true
          selfHeal: true

Sync Policies for Different Environments

Conservative (Production)

syncPolicy:
  automated:
    prune: false # Manual approval for deletions
    selfHeal: false # Manual approval for drift correction
  syncOptions:
    - CreateNamespace=true
    - PruneLast=true
    - ApplyOutOfSyncOnly=true
  retry:
    limit: 5
    backoff:
      duration: 5s
      factor: 2
      maxDuration: 3m

Progressive (Staging)

syncPolicy:
  automated:
    prune: true # Auto-delete removed resources
    selfHeal: true # Auto-correct drift
  syncOptions:
    - CreateNamespace=true
    - PruneLast=true
  retry:
    limit: 5
    backoff:
      duration: 5s
      factor: 2
      maxDuration: 3m

Aggressive (Development)

syncPolicy:
  automated:
    prune: true
    selfHeal: true
    allowEmpty: false
  syncOptions:
    - CreateNamespace=true
    - PruneLast=true
    - Replace=true # Use replace instead of apply
  retry:
    limit: 2
    backoff:
      duration: 5s
      factor: 2
      maxDuration: 30s

Sync Waves for Ordered Deployment

Control deployment order with sync waves:

# Wave -1: Prerequisites (namespaces, CRDs)
apiVersion: v1
kind: Namespace
metadata:
  name: myapp
  annotations:
    argocd.argoproj.io/sync-wave: "-1"

---
# Wave 0: Configuration (ConfigMaps, Secrets)
apiVersion: v1
kind: ConfigMap
metadata:
  name: myapp-config
  annotations:
    argocd.argoproj.io/sync-wave: "0"

---
# Wave 1: Core services (Databases)
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: postgres
  annotations:
    argocd.argoproj.io/sync-wave: "1"

---
# Wave 2: Application deployments
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
  annotations:
    argocd.argoproj.io/sync-wave: "2"

---
# Wave 3: Ingress and routing
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: myapp
  annotations:
    argocd.argoproj.io/sync-wave: "3"

Resource Hooks for Lifecycle Management

Pre-Sync: Database Migration

apiVersion: batch/v1
kind: Job
metadata:
  name: myapp-migration
  annotations:
    argocd.argoproj.io/hook: PreSync
    argocd.argoproj.io/hook-delete-policy: HookSucceeded
spec:
  template:
    spec:
      containers:
        - name: migrate
          image: myapp:v1.0.0
          command: ["./migrate"]
      restartPolicy: Never

Post-Sync: Smoke Test

apiVersion: batch/v1
kind: Job
metadata:
  name: myapp-smoke-test
  annotations:
    argocd.argoproj.io/hook: PostSync
    argocd.argoproj.io/hook-delete-policy: HookSucceeded
spec:
  template:
    spec:
      containers:
        - name: test
          image: curlimages/curl:latest
          command:
            - sh
            - -c
            - |
              curl -f http://myapp:80/healthz || exit 1
      restartPolicy: Never

Helm Value File Structure for GitOps

Organize values for multi-environment:

charts/myapp/
├── values.yaml                    # Base defaults
├── environments/
│   ├── dev/
│   │   ├── values.yaml           # Dev overrides
│   │   └── secrets.enc.yaml      # Encrypted secrets
│   ├── staging/
│   │   ├── values.yaml
│   │   └── secrets.enc.yaml
│   └── prod/
│       ├── values.yaml
│       └── secrets.enc.yaml
└── clusters/
    ├── cluster-1-values.yaml
    └── cluster-2-values.yaml

ArgoCD Application references:

helm:
  valueFiles:
    - values.yaml # Base
    - environments/{{env}}/values.yaml # Environment
    - clusters/{{cluster}}-values.yaml # Cluster-specific

App of Apps Pattern

Root application that manages other applications:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: root-app
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/myorg/cluster-config
    targetRevision: HEAD
    path: apps
  destination:
    server: https://kubernetes.default.svc
    namespace: argocd
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

Monitoring ArgoCD Deployments

Check Application Status

# Get application details
argocd app get myapp

# List all applications
argocd app list

# View sync history
argocd app history myapp

# View application events
argocd app events myapp

Prometheus Metrics

# Application sync status
argocd_app_sync_status{name="myapp",namespace="argocd"}

# Application health
argocd_app_health_status{name="myapp",namespace="argocd"}

# Sync operation duration
argocd_app_sync_duration_seconds{name="myapp"}

Alerting Rules

groups:
  - name: argocd
    rules:
      - alert: ApplicationOutOfSync
        expr: argocd_app_sync_status{sync_status="OutOfSync"} == 1
        for: 15m
        annotations:
          summary: "Application {{ $labels.name }} is out of sync"

      - alert: ApplicationUnhealthy
        expr: argocd_app_health_status{health_status="Degraded"} == 1
        for: 5m
        annotations:
          summary: "Application {{ $labels.name }} is unhealthy"

Troubleshooting Common Issues

Issue: Application stuck in "OutOfSync"

Diagnosis:

# Check app details
argocd app get myapp

# View diff
argocd app diff myapp

# Check sync status
argocd app sync myapp --dry-run

Common causes:

  • Resource field managed by controller (add to
    ignoreDifferences
    )
  • Invalid Helm template syntax
  • Missing CRD
  • Namespace doesn't exist

Issue: Sync fails with "resource already exists"

Solution:

# Add annotation to take ownership
metadata:
  annotations:
    argocd.argoproj.io/sync-options: Replace=true

Issue: Helm values not being applied

Diagnosis:

# Check rendered values
argocd app manifests myapp

# Verify value file exists in repo
# Check Application spec for correct valueFiles path

Common ArgoCD Commands

# Create application
argocd app create myapp \
  --repo https://github.com/myorg/charts \
  --path charts/myapp \
  --dest-server https://kubernetes.default.svc \
  --dest-namespace myapp

# Sync application
argocd app sync myapp

# Sync with prune
argocd app sync myapp --prune

# Delete application
argocd app delete myapp

# Rollback to previous version
argocd app rollback myapp

# View application logs
argocd app logs myapp

# Set application parameters
argocd app set myapp --parameter image.tag=v2.0.0

Resources


Related Agent

For comprehensive Helm/Kubernetes guidance that coordinates this and other Helm skills, use the

helm-kubernetes-expert
agent.