GitOps with ArgoCD for ChatGPT Apps: Continuous Deployment

Deploying ChatGPT apps to production requires robust continuous deployment pipelines that ensure reliability, traceability, and rapid rollback capabilities. GitOps with ArgoCD provides a declarative approach to Kubernetes deployments where Git repositories serve as the single source of truth for your infrastructure and application state.

In this comprehensive guide, you'll learn how to implement production-grade GitOps workflows for ChatGPT apps using ArgoCD. We'll cover application manifests, sync policies, multi-environment management, advanced features like ApplicationSets, and production best practices including secrets management and disaster recovery.

Whether you're deploying a single ChatGPT app or managing dozens of MCP servers across multiple clusters, ArgoCD's automated synchronization, health monitoring, and declarative configuration will transform your deployment workflow. By the end of this guide, you'll have a complete GitOps pipeline that automatically deploys changes from Git to Kubernetes with zero manual intervention.

Ready to automate your ChatGPT app deployments? Let's dive into ArgoCD architecture and start building production-ready GitOps workflows.

ArgoCD Architecture for ChatGPT Apps

ArgoCD is a declarative, GitOps continuous delivery tool for Kubernetes that automates the deployment of applications by synchronizing desired state (defined in Git) with actual state (running in Kubernetes clusters). Understanding ArgoCD's architecture is essential for designing robust deployment pipelines for ChatGPT apps.

Core Components

ArgoCD consists of three primary components that work together to enable GitOps workflows:

1. Application Controller: The brain of ArgoCD that continuously monitors Git repositories for changes and compares the desired state with the actual state in Kubernetes. When it detects drift (differences between desired and actual state), it triggers synchronization to bring the cluster back to the desired state. For ChatGPT apps, this means your MCP server deployments, services, and configurations are automatically updated whenever you push changes to Git.

2. Repo Server: A lightweight component that clones Git repositories, renders Kubernetes manifests (supporting Helm, Kustomize, Jsonnet, and plain YAML), and provides rendered manifests to the Application Controller. The Repo Server caches repository contents to improve performance and reduce Git API rate limits—critical when managing multiple ChatGPT app deployments.

3. API Server: Exposes ArgoCD's functionality via REST/gRPC APIs and serves the web UI. This component handles authentication, authorization (RBAC), and provides the interface for managing applications, viewing sync status, and triggering manual operations. For teams deploying ChatGPT apps, the API Server enables integration with CI/CD pipelines and custom automation workflows.

Sync Strategies for ChatGPT Apps

ArgoCD offers three synchronization strategies that determine how changes are applied to your ChatGPT app deployments:

Automatic Sync: ArgoCD automatically applies changes from Git to Kubernetes as soon as it detects drift. This is ideal for non-production environments where you want rapid iteration and testing of ChatGPT app updates. Enable with syncPolicy.automated.prune: true to automatically delete resources removed from Git.

Manual Sync: Requires explicit approval before applying changes. This provides a safety gate for production ChatGPT apps where you want to review changes, run tests, or coordinate deployments with business requirements. Manual sync is recommended for critical MCP servers serving production traffic.

Sync Waves: Control the order of resource deployment using annotations like argocd.argoproj.io/sync-wave: "1". This is essential for ChatGPT apps with dependencies—for example, deploying ConfigMaps and Secrets (wave 0) before Deployments (wave 1) before Services (wave 2). Sync waves prevent race conditions and ensure proper initialization order.

For production ChatGPT apps, we recommend a hybrid approach: automatic sync for development/staging environments with sync waves for orchestration, and manual sync with approval gates for production environments. This balances speed with safety.

Health Assessment for MCP Servers

ArgoCD continuously monitors the health of deployed resources using Kubernetes health checks and custom health assessment logic. For ChatGPT apps running MCP servers, ArgoCD can detect:

  • Deployment health: Checks if desired replicas match available replicas, pods are running, and containers are ready
  • Service health: Validates that Services have endpoints and are routing traffic correctly
  • Custom resource health: For ChatGPT apps using custom CRDs (e.g., MCP server operators), you can define custom health checks using Lua scripts
  • Degraded state detection: Identifies resources stuck in CrashLoopBackOff, ImagePullBackOff, or other error states

This comprehensive health monitoring ensures your ChatGPT apps remain available and performant. When ArgoCD detects unhealthy resources, it updates the application status in the UI and can trigger notifications via Slack, email, or webhooks.

Application Configuration for ChatGPT Apps

ArgoCD applications are defined using Kubernetes custom resources (Application CRD) that specify the Git repository, target cluster, sync policies, and health assessment rules. Here's a production-ready ArgoCD application manifest for deploying a ChatGPT MCP server:

# argocd-application.yaml - Complete ArgoCD Application for ChatGPT MCP Server
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: chatgpt-mcp-server
  namespace: argocd
  # Finalizer ensures proper cleanup when application is deleted
  finalizers:
    - resources-finalizer.argocd.argoproj.io
  # Labels for organization and filtering
  labels:
    app.kubernetes.io/name: chatgpt-mcp-server
    app.kubernetes.io/component: mcp-server
    environment: production
    team: platform
spec:
  # Git repository containing Kubernetes manifests
  source:
    repoURL: https://github.com/your-org/chatgpt-apps-gitops
    targetRevision: main
    path: apps/mcp-server/overlays/production

    # Kustomize configuration (alternative to Helm)
    kustomize:
      # Set common labels on all resources
      commonLabels:
        app.kubernetes.io/managed-by: argocd
        app.kubernetes.io/instance: chatgpt-mcp-server

      # Set common annotations
      commonAnnotations:
        managed-by: argocd
        contact: platform-team@company.com

      # Image tag override (can be set by CI/CD)
      images:
        - ghcr.io/your-org/chatgpt-mcp-server:v1.2.3

      # Namespace override
      namespace: chatgpt-production

      # Build options
      buildOptions: "--enable-alpha-plugins --load-restrictor=LoadRestrictionsNone"

  # Destination cluster and namespace
  destination:
    server: https://kubernetes.default.svc
    namespace: chatgpt-production

  # Sync policy - controls how ArgoCD applies changes
  syncPolicy:
    # Automated sync - apply changes automatically
    automated:
      # Prune resources that are no longer defined in Git
      prune: true
      # Self-heal - automatically sync if cluster state drifts from Git
      selfHeal: true
      # Allow empty - permit sync with zero resources
      allowEmpty: false

    # Sync options for additional control
    syncOptions:
      # Create namespace if it doesn't exist
      - CreateNamespace=true
      # Validate resources against Kubernetes API
      - Validate=true
      # Use server-side apply (recommended for large resources)
      - ServerSideApply=true
      # Prune last - delete resources after creating new ones
      - PruneLast=true
      # Replace resources instead of applying patches
      - Replace=false
      # Respect ignore differences
      - RespectIgnoreDifferences=true

    # Retry policy for failed syncs
    retry:
      limit: 5
      backoff:
        duration: 5s
        factor: 2
        maxDuration: 3m

  # Ignore differences in specific fields (prevents constant drift)
  ignoreDifferences:
    # Ignore replicas managed by HPA
    - group: apps
      kind: Deployment
      jsonPointers:
        - /spec/replicas

    # Ignore mutating webhook modifications
    - group: ""
      kind: Secret
      jsonPointers:
        - /data
      # Only ignore secrets with specific annotation
      jqPathExpressions:
        - .metadata.annotations."sealedsecrets.bitnami.com/managed"

  # Health assessment configuration
  revisionHistoryLimit: 10

  # Info section - metadata displayed in ArgoCD UI
  info:
    - name: Environment
      value: Production
    - name: Team
      value: Platform Engineering
    - name: Documentation
      value: https://docs.company.com/chatgpt-mcp-server
    - name: Slack Channel
      value: "#chatgpt-ops"
    - name: PagerDuty
      value: https://company.pagerduty.com/services/chatgpt-mcp

---
# AppProject - RBAC and resource restrictions for ChatGPT apps
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: chatgpt-apps
  namespace: argocd
spec:
  description: Project for all ChatGPT application deployments

  # Source repositories allowed for this project
  sourceRepos:
    - https://github.com/your-org/chatgpt-apps-gitops
    - https://ghcr.io/your-org/*

  # Destination clusters and namespaces
  destinations:
    # Production cluster
    - server: https://kubernetes.default.svc
      namespace: chatgpt-production
    # Staging cluster
    - server: https://staging-cluster.company.com
      namespace: chatgpt-staging
    # Development cluster
    - server: https://dev-cluster.company.com
      namespace: 'chatgpt-*'

  # Cluster resource whitelist (allowed resource types)
  clusterResourceWhitelist:
    - group: ''
      kind: Namespace
    - group: rbac.authorization.k8s.io
      kind: ClusterRole
    - group: rbac.authorization.k8s.io
      kind: ClusterRoleBinding

  # Namespace resource whitelist
  namespaceResourceWhitelist:
    - group: apps
      kind: Deployment
    - group: apps
      kind: StatefulSet
    - group: ''
      kind: Service
    - group: ''
      kind: ConfigMap
    - group: ''
      kind: Secret
    - group: networking.k8s.io
      kind: Ingress
    - group: autoscaling
      kind: HorizontalPodAutoscaler

  # Deny certain resource types (security)
  namespaceResourceBlacklist:
    - group: ''
      kind: ResourceQuota
    - group: ''
      kind: LimitRange

  # RBAC roles for this project
  roles:
    # Developers - read-only access
    - name: developer
      description: Read-only access to ChatGPT apps
      policies:
        - p, proj:chatgpt-apps:developer, applications, get, chatgpt-apps/*, allow
        - p, proj:chatgpt-apps:developer, applications, list, chatgpt-apps/*, allow
      groups:
        - chatgpt-developers

    # Operators - full sync/rollback access
    - name: operator
      description: Full operational access to ChatGPT apps
      policies:
        - p, proj:chatgpt-apps:operator, applications, *, chatgpt-apps/*, allow
        - p, proj:chatgpt-apps:operator, applications, sync, chatgpt-apps/*, allow
        - p, proj:chatgpt-apps:operator, applications, override, chatgpt-apps/*, allow
      groups:
        - chatgpt-operators
        - sre-team

This comprehensive application manifest includes sync policies, health checks, RBAC controls, and metadata for effective ChatGPT app management. The AppProject provides multi-tenant isolation and security boundaries for different teams deploying ChatGPT apps.

Diff Customization for Sensitive Data

ChatGPT apps often contain sensitive configuration (API keys, model credentials) that shouldn't appear in ArgoCD diffs. Configure diff customization to prevent credential exposure:

# argocd-cm ConfigMap - Diff customization rules
apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cm
  namespace: argocd
data:
  # Ignore differences in Secret data fields
  resource.customizations.ignoreDifferences.core_Secret: |
    jsonPointers:
    - /data
    - /stringData

  # Custom health check for MCP server Deployment
  resource.customizations.health.apps_Deployment: |
    hs = {}
    if obj.status ~= nil then
      if obj.status.conditions ~= nil then
        for i, condition in ipairs(obj.status.conditions) do
          if condition.type == "Progressing" and condition.reason == "ProgressDeadlineExceeded" then
            hs.status = "Degraded"
            hs.message = condition.message
            return hs
          end
          if condition.type == "Available" and condition.status == "True" then
            hs.status = "Healthy"
            hs.message = "Deployment is available"
            return hs
          end
        end
      end
    end
    hs.status = "Progressing"
    hs.message = "Waiting for deployment"
    return hs

Learn more about monitoring ChatGPT apps in production and Kubernetes security best practices.

Multi-Environment Management with Kustomize

Managing ChatGPT apps across development, staging, and production environments requires a structured approach to configuration management. Kustomize provides a template-free way to customize Kubernetes manifests for different environments while maintaining a single base configuration.

Base Configuration for MCP Servers

The base directory contains common Kubernetes resources shared across all environments:

# apps/mcp-server/base/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

# Common labels applied to all resources
commonLabels:
  app.kubernetes.io/name: chatgpt-mcp-server
  app.kubernetes.io/component: mcp-server

# Common annotations
commonAnnotations:
  managed-by: argocd

# Base resources
resources:
  - deployment.yaml
  - service.yaml
  - configmap.yaml
  - hpa.yaml
  - ingress.yaml

# ConfigMap generator for environment-agnostic config
configMapGenerator:
  - name: mcp-server-config
    literals:
      - LOG_LEVEL=info
      - MCP_PROTOCOL_VERSION=2024-11-05
      - HEALTH_CHECK_PATH=/health
      - METRICS_PORT=9090

# Secret generator placeholder (override in overlays)
secretGenerator:
  - name: mcp-server-secrets
    literals:
      - OPENAI_API_KEY=placeholder

# Image configuration
images:
  - name: mcp-server
    newName: ghcr.io/your-org/chatgpt-mcp-server
    newTag: latest

---
# apps/mcp-server/base/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: chatgpt-mcp-server
spec:
  replicas: 2
  selector:
    matchLabels:
      app.kubernetes.io/name: chatgpt-mcp-server
  template:
    metadata:
      labels:
        app.kubernetes.io/name: chatgpt-mcp-server
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "9090"
        prometheus.io/path: "/metrics"
    spec:
      serviceAccountName: chatgpt-mcp-server

      # Security context
      securityContext:
        runAsNonRoot: true
        runAsUser: 1000
        fsGroup: 1000
        seccompProfile:
          type: RuntimeDefault

      containers:
        - name: mcp-server
          image: mcp-server
          imagePullPolicy: IfNotPresent

          ports:
            - name: http
              containerPort: 3000
              protocol: TCP
            - name: metrics
              containerPort: 9090
              protocol: TCP

          env:
            - name: NODE_ENV
              value: production
            - name: PORT
              value: "3000"
            - name: OPENAI_API_KEY
              valueFrom:
                secretKeyRef:
                  name: mcp-server-secrets
                  key: OPENAI_API_KEY

          envFrom:
            - configMapRef:
                name: mcp-server-config

          resources:
            requests:
              cpu: 100m
              memory: 128Mi
            limits:
              cpu: 500m
              memory: 512Mi

          livenessProbe:
            httpGet:
              path: /health
              port: http
            initialDelaySeconds: 30
            periodSeconds: 10
            timeoutSeconds: 5
            failureThreshold: 3

          readinessProbe:
            httpGet:
              path: /ready
              port: http
            initialDelaySeconds: 10
            periodSeconds: 5
            timeoutSeconds: 3
            failureThreshold: 2

          # Container security context
          securityContext:
            allowPrivilegeEscalation: false
            readOnlyRootFilesystem: true
            runAsNonRoot: true
            capabilities:
              drop:
                - ALL

          volumeMounts:
            - name: tmp
              mountPath: /tmp
            - name: cache
              mountPath: /app/.cache

      volumes:
        - name: tmp
          emptyDir: {}
        - name: cache
          emptyDir: {}

      # Topology spread for high availability
      topologySpreadConstraints:
        - maxSkew: 1
          topologyKey: topology.kubernetes.io/zone
          whenUnsatisfiable: DoNotSchedule
          labelSelector:
            matchLabels:
              app.kubernetes.io/name: chatgpt-mcp-server

Production Overlay with Advanced Configuration

The production overlay customizes base resources with production-specific settings, resource limits, and replica counts:

# apps/mcp-server/overlays/production/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

# Reference base configuration
bases:
  - ../../base

# Production namespace
namespace: chatgpt-production

# Production-specific labels
commonLabels:
  environment: production
  team: platform
  cost-center: engineering

# Production annotations
commonAnnotations:
  managed-by: argocd
  contact: platform-team@company.com
  documentation: https://docs.company.com/chatgpt-mcp-server

# Replica count for production
replicas:
  - name: chatgpt-mcp-server
    count: 5

# Production image tag (updated by CI/CD)
images:
  - name: mcp-server
    newName: ghcr.io/your-org/chatgpt-mcp-server
    newTag: v1.2.3

# ConfigMap overrides for production
configMapGenerator:
  - name: mcp-server-config
    behavior: merge
    literals:
      - LOG_LEVEL=warn
      - REQUEST_TIMEOUT=30s
      - MAX_CONNECTIONS=1000
      - RATE_LIMIT_RPM=600
      - CACHE_TTL=3600
      - ENABLE_METRICS=true
      - ENABLE_TRACING=true
      - TRACING_SAMPLE_RATE=0.1

# Sealed Secrets for production credentials
secretGenerator:
  - name: mcp-server-secrets
    behavior: replace
    files:
      - OPENAI_API_KEY=secrets/openai-api-key.txt
      - JWT_SECRET=secrets/jwt-secret.txt
      - DATABASE_URL=secrets/database-url.txt

# Strategic merge patches
patchesStrategicMerge:
  - deployment-patch.yaml
  - hpa-patch.yaml
  - ingress-patch.yaml

# JSON patches for fine-grained control
patchesJson6902:
  # Add production-specific environment variables
  - target:
      group: apps
      version: v1
      kind: Deployment
      name: chatgpt-mcp-server
    patch: |-
      - op: add
        path: /spec/template/spec/containers/0/env/-
        value:
          name: DD_AGENT_HOST
          valueFrom:
            fieldRef:
              fieldPath: status.hostIP
      - op: add
        path: /spec/template/spec/containers/0/env/-
        value:
          name: DD_SERVICE
          value: chatgpt-mcp-server
      - op: add
        path: /spec/template/spec/containers/0/env/-
        value:
          name: DD_ENV
          value: production

---
# apps/mcp-server/overlays/production/deployment-patch.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: chatgpt-mcp-server
spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0

  template:
    spec:
      # Production-grade resource limits
      containers:
        - name: mcp-server
          resources:
            requests:
              cpu: 500m
              memory: 1Gi
            limits:
              cpu: 2000m
              memory: 4Gi

          # Production health checks with tighter thresholds
          livenessProbe:
            httpGet:
              path: /health
              port: http
            initialDelaySeconds: 60
            periodSeconds: 10
            timeoutSeconds: 5
            failureThreshold: 3

          readinessProbe:
            httpGet:
              path: /ready
              port: http
            initialDelaySeconds: 30
            periodSeconds: 5
            timeoutSeconds: 3
            failureThreshold: 2

      # Production affinity rules
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchLabels:
                  app.kubernetes.io/name: chatgpt-mcp-server
              topologyKey: kubernetes.io/hostname
        nodeAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
            - weight: 100
              preference:
                matchExpressions:
                  - key: node.kubernetes.io/instance-type
                    operator: In
                    values:
                      - c5.2xlarge
                      - c6i.2xlarge

---
# apps/mcp-server/overlays/production/hpa-patch.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: chatgpt-mcp-server
spec:
  minReplicas: 5
  maxReplicas: 20
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70
    - type: Resource
      resource:
        name: memory
        target:
          type: Utilization
          averageUtilization: 80
    # Custom metric from Prometheus
    - type: Pods
      pods:
        metric:
          name: http_requests_per_second
        target:
          type: AverageValue
          averageValue: "1000"

  behavior:
    scaleDown:
      stabilizationWindowSeconds: 300
      policies:
        - type: Percent
          value: 50
          periodSeconds: 60
    scaleUp:
      stabilizationWindowSeconds: 0
      policies:
        - type: Percent
          value: 100
          periodSeconds: 30
        - type: Pods
          value: 4
          periodSeconds: 30
      selectPolicy: Max

This Kustomize structure provides environment-specific configurations while maintaining DRY principles. Development and staging overlays follow the same pattern with adjusted replica counts, resource limits, and configuration values.

Explore more about ChatGPT app scaling strategies and configuration management patterns.

Advanced ArgoCD Features for ChatGPT Apps

Beyond basic application deployment, ArgoCD provides advanced features for managing complex ChatGPT app architectures, multi-cluster deployments, and sophisticated workflows.

App of Apps Pattern for Microservices

The "App of Apps" pattern enables hierarchical application management where a parent ArgoCD application manages child applications. This is ideal for ChatGPT platforms with multiple MCP servers, databases, and supporting services:

# apps/chatgpt-platform/app-of-apps.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: chatgpt-platform
  namespace: argocd
  finalizers:
    - resources-finalizer.argocd.argoproj.io
spec:
  project: chatgpt-apps

  source:
    repoURL: https://github.com/your-org/chatgpt-apps-gitops
    targetRevision: main
    path: apps/chatgpt-platform/applications

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

  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - CreateNamespace=true

---
# apps/chatgpt-platform/applications/mcp-server-app.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: mcp-server
  namespace: argocd
spec:
  project: chatgpt-apps
  source:
    repoURL: https://github.com/your-org/chatgpt-apps-gitops
    targetRevision: main
    path: apps/mcp-server/overlays/production
  destination:
    server: https://kubernetes.default.svc
    namespace: chatgpt-production
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - CreateNamespace=true
  # Sync wave - deploy after infrastructure
  metadata:
    annotations:
      argocd.argoproj.io/sync-wave: "2"

---
# apps/chatgpt-platform/applications/database-app.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: postgres-db
  namespace: argocd
spec:
  project: chatgpt-apps
  source:
    repoURL: https://github.com/your-org/chatgpt-apps-gitops
    targetRevision: main
    path: infrastructure/postgres/overlays/production
  destination:
    server: https://kubernetes.default.svc
    namespace: chatgpt-production
  syncPolicy:
    automated:
      prune: false  # Never auto-delete database
      selfHeal: true
  # Sync wave - deploy before applications
  metadata:
    annotations:
      argocd.argoproj.io/sync-wave: "1"

---
# apps/chatgpt-platform/applications/redis-cache-app.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: redis-cache
  namespace: argocd
spec:
  project: chatgpt-apps
  source:
    repoURL: https://github.com/your-org/chatgpt-apps-gitops
    targetRevision: main
    path: infrastructure/redis/overlays/production
  destination:
    server: https://kubernetes.default.svc
    namespace: chatgpt-production
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
  metadata:
    annotations:
      argocd.argoproj.io/sync-wave: "1"

ApplicationSets for Multi-Cluster Deployments

ApplicationSets automate the creation of ArgoCD applications across multiple clusters and environments. This is essential for ChatGPT apps deployed to multiple regions or customer-specific clusters:

# applicationsets/chatgpt-mcp-multi-cluster.yaml
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: chatgpt-mcp-multi-cluster
  namespace: argocd
spec:
  # Generator creates applications from cluster list
  generators:
    # List generator - define clusters explicitly
    - list:
        elements:
          - cluster: production-us-east
            url: https://prod-us-east.company.com
            region: us-east-1
            environment: production
            replicas: "5"
            resources: high

          - cluster: production-eu-west
            url: https://prod-eu-west.company.com
            region: eu-west-1
            environment: production
            replicas: "5"
            resources: high

          - cluster: staging-us-east
            url: https://staging-us-east.company.com
            region: us-east-1
            environment: staging
            replicas: "2"
            resources: medium

          - cluster: development
            url: https://dev-cluster.company.com
            region: us-east-1
            environment: development
            replicas: "1"
            resources: low

  # Template for generated applications
  template:
    metadata:
      name: 'chatgpt-mcp-{{cluster}}'
      labels:
        environment: '{{environment}}'
        region: '{{region}}'
      annotations:
        managed-by: applicationset
        cluster: '{{cluster}}'

    spec:
      project: chatgpt-apps

      source:
        repoURL: https://github.com/your-org/chatgpt-apps-gitops
        targetRevision: main
        path: 'apps/mcp-server/overlays/{{environment}}'

        # Kustomize with cluster-specific overrides
        kustomize:
          commonLabels:
            cluster: '{{cluster}}'
            region: '{{region}}'

          # Replica count per cluster
          replicas:
            - name: chatgpt-mcp-server
              count: '{{replicas}}'

          # Resource profile per cluster
          patches:
            - patch: |-
                apiVersion: apps/v1
                kind: Deployment
                metadata:
                  name: chatgpt-mcp-server
                spec:
                  template:
                    spec:
                      containers:
                        - name: mcp-server
                          resources:
                            {{#if (eq resources "high")}}
                            requests:
                              cpu: 1000m
                              memory: 2Gi
                            limits:
                              cpu: 4000m
                              memory: 8Gi
                            {{else if (eq resources "medium")}}
                            requests:
                              cpu: 500m
                              memory: 1Gi
                            limits:
                              cpu: 2000m
                              memory: 4Gi
                            {{else}}
                            requests:
                              cpu: 100m
                              memory: 256Mi
                            limits:
                              cpu: 500m
                              memory: 1Gi
                            {{/if}}

      destination:
        server: '{{url}}'
        namespace: chatgpt-{{environment}}

      syncPolicy:
        automated:
          prune: true
          selfHeal: true
        syncOptions:
          - CreateNamespace=true
          - ServerSideApply=true

        retry:
          limit: 5
          backoff:
            duration: 5s
            factor: 2
            maxDuration: 3m

      # Progressive sync - wait for health before continuing
      syncPolicy:
        syncOptions:
          - RespectIgnoreDifferences=true
          - ApplyOutOfSyncOnly=true

---
# applicationsets/chatgpt-tenant-generator.yaml
# ApplicationSet with Git File generator for per-tenant deployments
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: chatgpt-tenant-apps
  namespace: argocd
spec:
  generators:
    # Git file generator - discover tenants from directory structure
    - git:
        repoURL: https://github.com/your-org/chatgpt-apps-gitops
        revision: main
        files:
          - path: "tenants/*/config.json"

  template:
    metadata:
      name: 'chatgpt-tenant-{{tenant.name}}'
      labels:
        tenant: '{{tenant.name}}'
        tier: '{{tenant.tier}}'

    spec:
      project: chatgpt-tenants

      source:
        repoURL: https://github.com/your-org/chatgpt-apps-gitops
        targetRevision: main
        path: 'apps/mcp-server/overlays/tenant'

        kustomize:
          commonLabels:
            tenant: '{{tenant.name}}'

          # Tenant-specific namespace
          namespace: 'chatgpt-tenant-{{tenant.name}}'

          # Tenant-specific configuration
          patches:
            - patch: |-
                apiVersion: v1
                kind: ConfigMap
                metadata:
                  name: tenant-config
                data:
                  TENANT_ID: "{{tenant.id}}"
                  TENANT_NAME: "{{tenant.name}}"
                  API_RATE_LIMIT: "{{tenant.rateLimit}}"
                  MAX_CONNECTIONS: "{{tenant.maxConnections}}"

      destination:
        server: https://kubernetes.default.svc
        namespace: 'chatgpt-tenant-{{tenant.name}}'

      syncPolicy:
        automated:
          prune: true
          selfHeal: true
        syncOptions:
          - CreateNamespace=true

ApplicationSets dramatically reduce operational overhead for multi-cluster and multi-tenant ChatGPT deployments, enabling centralized management with cluster-specific customization.

Notification Templates for Deployment Events

ArgoCD integrations with notification systems (Slack, email, PagerDuty) provide real-time alerts for sync status, health changes, and deployment events:

# argocd-notifications-cm.yaml - Notification configuration
apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-notifications-cm
  namespace: argocd
data:
  # Slack service configuration
  service.slack: |
    token: $slack-token
    username: ArgoCD Bot
    icon: ":rocket:"

  # Email service configuration
  service.email.gmail: |
    username: $email-username
    password: $email-password
    host: smtp.gmail.com
    port: 587
    from: argocd@company.com

  # Webhook service for custom integrations
  service.webhook.chatgpt-ops: |
    url: https://api.company.com/argocd-webhooks
    headers:
      - name: Authorization
        value: Bearer $webhook-token

  # Notification templates
  template.app-deployed: |
    message: |
      ChatGPT app {{.app.metadata.name}} deployed successfully!
      Environment: {{.app.metadata.labels.environment}}
      Version: {{.app.status.sync.revision}}
      Sync Status: {{.app.status.sync.status}}
      Health Status: {{.app.status.health.status}}
    slack:
      attachments: |
        [{
          "title": "{{ .app.metadata.name}}",
          "title_link": "{{.context.argocdUrl}}/applications/{{.app.metadata.name}}",
          "color": "#18be52",
          "fields": [
            {
              "title": "Environment",
              "value": "{{.app.metadata.labels.environment}}",
              "short": true
            },
            {
              "title": "Version",
              "value": "{{.app.status.sync.revision}}",
              "short": true
            },
            {
              "title": "Sync Status",
              "value": "{{.app.status.sync.status}}",
              "short": true
            },
            {
              "title": "Health",
              "value": "{{.app.status.health.status}}",
              "short": true
            }
          ]
        }]

  template.app-health-degraded: |
    message: |
      ⚠️ ChatGPT app {{.app.metadata.name}} health degraded!
      Environment: {{.app.metadata.labels.environment}}
      Health Status: {{.app.status.health.status}}
      Health Message: {{.app.status.health.message}}
    slack:
      attachments: |
        [{
          "title": "🚨 {{ .app.metadata.name}} - Health Degraded",
          "title_link": "{{.context.argocdUrl}}/applications/{{.app.metadata.name}}",
          "color": "#f4c030",
          "fields": [
            {
              "title": "Environment",
              "value": "{{.app.metadata.labels.environment}}",
              "short": true
            },
            {
              "title": "Health Status",
              "value": "{{.app.status.health.status}}",
              "short": true
            },
            {
              "title": "Health Message",
              "value": "{{.app.status.health.message}}",
              "short": false
            }
          ]
        }]

  template.app-sync-failed: |
    message: |
      ❌ ChatGPT app {{.app.metadata.name}} sync failed!
      Environment: {{.app.metadata.labels.environment}}
      Sync Status: {{.app.status.sync.status}}
      Error: {{.app.status.operationState.message}}
    slack:
      attachments: |
        [{
          "title": "❌ {{ .app.metadata.name}} - Sync Failed",
          "title_link": "{{.context.argocdUrl}}/applications/{{.app.metadata.name}}",
          "color": "#E96D76",
          "fields": [
            {
              "title": "Environment",
              "value": "{{.app.metadata.labels.environment}}",
              "short": true
            },
            {
              "title": "Sync Status",
              "value": "{{.app.status.sync.status}}",
              "short": true
            },
            {
              "title": "Error Message",
              "value": "{{.app.status.operationState.message}}",
              "short": false
            }
          ]
        }]

  # Notification triggers
  trigger.on-deployed: |
    - when: app.status.operationState.phase in ['Succeeded']
      send: [app-deployed]

  trigger.on-health-degraded: |
    - when: app.status.health.status == 'Degraded'
      send: [app-health-degraded]

  trigger.on-sync-failed: |
    - when: app.status.operationState.phase in ['Error', 'Failed']
      send: [app-sync-failed]

  # Subscription annotations (add to applications)
  subscriptions: |
    # Production apps notify Slack + PagerDuty
    - recipients:
      - slack:chatgpt-ops
      - webhook:chatgpt-ops
      selector: environment=production
      triggers:
      - on-deployed
      - on-health-degraded
      - on-sync-failed

    # Staging apps notify Slack only
    - recipients:
      - slack:chatgpt-staging
      selector: environment=staging
      triggers:
      - on-deployed
      - on-sync-failed

These notification templates provide real-time visibility into ChatGPT app deployments, enabling rapid response to issues and automated incident management workflows.

Learn more about ChatGPT app observability and incident response automation.

Production Best Practices for ChatGPT Apps

Deploying ChatGPT apps with ArgoCD requires adherence to production best practices covering secrets management, monitoring, backup, and disaster recovery.

Sealed Secrets for Credential Management

Never commit plain-text secrets to Git. Use Sealed Secrets to encrypt sensitive data before committing:

#!/bin/bash
# sealed-secrets-setup.sh - Install and configure Sealed Secrets controller

set -euo pipefail

# Install Sealed Secrets controller
kubectl apply -f https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.24.0/controller.yaml

# Wait for controller to be ready
kubectl wait --for=condition=ready pod -l name=sealed-secrets-controller -n kube-system --timeout=300s

# Install kubeseal CLI
KUBESEAL_VERSION='0.24.0'
wget "https://github.com/bitnami-labs/sealed-secrets/releases/download/v${KUBESEAL_VERSION}/kubeseal-${KUBESEAL_VERSION}-linux-amd64.tar.gz"
tar -xvzf "kubeseal-${KUBESEAL_VERSION}-linux-amd64.tar.gz" kubeseal
sudo install -m 755 kubeseal /usr/local/bin/kubeseal

# Create sealed secret from plain text
kubectl create secret generic mcp-server-secrets \
  --from-literal=OPENAI_API_KEY="sk-..." \
  --from-literal=JWT_SECRET="your-jwt-secret" \
  --from-literal=DATABASE_URL="postgresql://..." \
  --dry-run=client -o yaml | \
  kubeseal --controller-name=sealed-secrets-controller \
  --controller-namespace=kube-system \
  --format yaml > sealed-secret.yaml

# Commit sealed secret to Git (safe - encrypted)
git add sealed-secret.yaml
git commit -m "feat: Add sealed secrets for MCP server"
git push origin main

echo "✅ Sealed Secrets setup complete"
echo "📝 Sealed secret created: sealed-secret.yaml"
echo "🔐 Original secrets are encrypted and safe to commit to Git"

Automated Rollback on Failure

Implement automated rollback policies to revert failed deployments and minimize downtime:

#!/bin/bash
# argocd-rollback-automation.sh - Automated rollback on sync failure

set -euo pipefail

APP_NAME="${1:-chatgpt-mcp-server}"
HEALTH_THRESHOLD=300  # 5 minutes

echo "🔍 Monitoring ArgoCD application: $APP_NAME"

# Function to get app sync status
get_sync_status() {
  argocd app get "$APP_NAME" -o json | jq -r '.status.sync.status'
}

# Function to get app health status
get_health_status() {
  argocd app get "$APP_NAME" -o json | jq -r '.status.health.status'
}

# Function to get current revision
get_current_revision() {
  argocd app get "$APP_NAME" -o json | jq -r '.status.sync.revision'
}

# Function to get previous successful revision
get_previous_revision() {
  argocd app get "$APP_NAME" -o json | \
    jq -r '.status.history[] | select(.deployedAt != null) | .revision' | \
    head -n 2 | tail -n 1
}

# Function to rollback to previous revision
rollback_app() {
  local previous_revision=$1
  echo "⚠️ Initiating rollback to revision: $previous_revision"

  argocd app rollback "$APP_NAME" "$previous_revision" --prune

  echo "✅ Rollback initiated"

  # Notify Slack about rollback
  curl -X POST https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK \
    -H 'Content-Type: application/json' \
    -d "{
      \"text\": \"🔄 ArgoCD Rollback: $APP_NAME\",
      \"attachments\": [{
        \"color\": \"warning\",
        \"fields\": [
          {\"title\": \"Application\", \"value\": \"$APP_NAME\", \"short\": true},
          {\"title\": \"Revision\", \"value\": \"$previous_revision\", \"short\": true},
          {\"title\": \"Reason\", \"value\": \"Health check failed after deployment\", \"short\": false}
        ]
      }]
    }"
}

# Monitor sync operation
SYNC_STATUS=$(get_sync_status)
echo "📊 Current sync status: $SYNC_STATUS"

if [ "$SYNC_STATUS" == "Synced" ]; then
  echo "✅ Application synced successfully"

  # Monitor health for 5 minutes
  echo "🏥 Monitoring health status for $HEALTH_THRESHOLD seconds..."

  for i in $(seq 1 $((HEALTH_THRESHOLD / 10))); do
    HEALTH_STATUS=$(get_health_status)
    echo "[$i/30] Health status: $HEALTH_STATUS"

    if [ "$HEALTH_STATUS" == "Degraded" ] || [ "$HEALTH_STATUS" == "Missing" ]; then
      echo "❌ Health check failed: $HEALTH_STATUS"

      PREVIOUS_REVISION=$(get_previous_revision)

      if [ -n "$PREVIOUS_REVISION" ]; then
        rollback_app "$PREVIOUS_REVISION"
        exit 1
      else
        echo "⚠️ No previous revision found - cannot rollback"
        exit 2
      fi
    fi

    if [ "$HEALTH_STATUS" == "Healthy" ]; then
      echo "✅ Application is healthy"

      # Notify Slack about successful deployment
      CURRENT_REVISION=$(get_current_revision)
      curl -X POST https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK \
        -H 'Content-Type: application/json' \
        -d "{
          \"text\": \"✅ ArgoCD Deployment Successful: $APP_NAME\",
          \"attachments\": [{
            \"color\": \"good\",
            \"fields\": [
              {\"title\": \"Application\", \"value\": \"$APP_NAME\", \"short\": true},
              {\"title\": \"Revision\", \"value\": \"$CURRENT_REVISION\", \"short\": true}
            ]
          }]
        }"

      exit 0
    fi

    sleep 10
  done

  echo "⚠️ Health check timeout - manual investigation required"
  exit 3

elif [ "$SYNC_STATUS" == "OutOfSync" ]; then
  echo "⚠️ Application out of sync - waiting for sync operation..."
  sleep 30
  exec "$0" "$APP_NAME"

else
  echo "❌ Unexpected sync status: $SYNC_STATUS"
  exit 4
fi

Disaster Recovery with Backup

Implement regular backups of ArgoCD configuration and application state:

#!/bin/bash
# argocd-backup.sh - Backup ArgoCD applications and configuration

set -euo pipefail

BACKUP_DIR="/backups/argocd/$(date +%Y%m%d-%H%M%S)"
mkdir -p "$BACKUP_DIR"

echo "📦 Starting ArgoCD backup to: $BACKUP_DIR"

# Backup all ArgoCD applications
echo "💾 Backing up applications..."
argocd app list -o json > "$BACKUP_DIR/applications.json"

# Backup each application manifest
argocd app list -o name | while read -r app; do
  echo "  - Backing up $app"
  argocd app get "$app" -o yaml > "$BACKUP_DIR/app-${app}.yaml"
  argocd app manifests "$app" > "$BACKUP_DIR/manifests-${app}.yaml"
done

# Backup ArgoCD projects
echo "💾 Backing up projects..."
kubectl get appproject -n argocd -o yaml > "$BACKUP_DIR/projects.yaml"

# Backup ArgoCD configuration
echo "💾 Backing up configuration..."
kubectl get configmap argocd-cm -n argocd -o yaml > "$BACKUP_DIR/argocd-cm.yaml"
kubectl get configmap argocd-rbac-cm -n argocd -o yaml > "$BACKUP_DIR/argocd-rbac-cm.yaml"
kubectl get configmap argocd-notifications-cm -n argocd -o yaml > "$BACKUP_DIR/argocd-notifications-cm.yaml"

# Backup ArgoCD secrets (encrypted)
echo "💾 Backing up secrets..."
kubectl get secret -n argocd -o yaml > "$BACKUP_DIR/secrets.yaml"

# Create tarball
echo "📦 Creating backup archive..."
tar -czf "$BACKUP_DIR.tar.gz" -C /backups/argocd "$(basename "$BACKUP_DIR")"

# Upload to S3 (or your backup storage)
echo "☁️ Uploading to S3..."
aws s3 cp "$BACKUP_DIR.tar.gz" "s3://company-backups/argocd/$(basename "$BACKUP_DIR").tar.gz"

# Cleanup local backup
rm -rf "$BACKUP_DIR"

# Retention policy - keep last 30 days
echo "🗑️ Cleaning up old backups..."
aws s3 ls s3://company-backups/argocd/ | \
  awk '{print $4}' | \
  sort -r | \
  tail -n +31 | \
  while read -r file; do
    echo "  - Deleting $file"
    aws s3 rm "s3://company-backups/argocd/$file"
  done

echo "✅ Backup complete: $BACKUP_DIR.tar.gz"
echo "📊 Backup size: $(du -h "$BACKUP_DIR.tar.gz" | cut -f1)"

Monitoring Dashboard with Prometheus

Monitor ArgoCD and ChatGPT app metrics with Prometheus and Grafana:

# prometheus-argocd-servicemonitor.yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: argocd-metrics
  namespace: argocd
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: argocd-metrics
  endpoints:
    - port: metrics
      interval: 30s
      path: /metrics

---
# prometheus-argocd-rules.yaml
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: argocd-alerts
  namespace: argocd
spec:
  groups:
    - name: argocd
      interval: 30s
      rules:
        # Alert when app is out of sync for > 5 minutes
        - alert: ArgoCDAppOutOfSync
          expr: argocd_app_info{sync_status="OutOfSync"} > 0
          for: 5m
          labels:
            severity: warning
            component: argocd
          annotations:
            summary: "ArgoCD app {{ $labels.name }} out of sync"
            description: "Application {{ $labels.name }} has been out of sync for more than 5 minutes"

        # Alert when app health is degraded
        - alert: ArgoCDAppHealthDegraded
          expr: argocd_app_info{health_status="Degraded"} > 0
          for: 2m
          labels:
            severity: critical
            component: argocd
          annotations:
            summary: "ArgoCD app {{ $labels.name }} health degraded"
            description: "Application {{ $labels.name }} health is degraded"

        # Alert when sync operation fails
        - alert: ArgoCDSyncFailed
          expr: increase(argocd_app_sync_total{phase="Failed"}[5m]) > 0
          labels:
            severity: warning
            component: argocd
          annotations:
            summary: "ArgoCD sync failed for {{ $labels.name }}"
            description: "Sync operation failed for application {{ $labels.name }}"

        # Alert when app hasn't synced in 24 hours
        - alert: ArgoCDAppNotSynced
          expr: (time() - argocd_app_reconcile_timestamp) > 86400
          labels:
            severity: warning
            component: argocd
          annotations:
            summary: "ArgoCD app {{ $labels.name }} not synced in 24h"
            description: "Application {{ $labels.name }} hasn't reconciled in over 24 hours"

These production best practices ensure ChatGPT apps deployed via ArgoCD maintain high availability, security, and operational excellence.

Discover more about ChatGPT app reliability engineering and production readiness checklists.

Conclusion: Transform ChatGPT App Deployments with GitOps

GitOps with ArgoCD revolutionizes ChatGPT app deployments by providing declarative infrastructure, automated synchronization, and comprehensive health monitoring. By treating Git as the single source of truth, you eliminate configuration drift, enable rapid rollbacks, and create auditable deployment histories.

Key takeaways from this guide:

  • ArgoCD architecture provides automated sync, health checks, and multi-cluster management for ChatGPT apps
  • Kustomize overlays enable environment-specific configurations while maintaining DRY principles
  • ApplicationSets automate multi-cluster and multi-tenant deployments with centralized management
  • App of Apps pattern orchestrates complex microservices architectures with dependency management
  • Production best practices including Sealed Secrets, automated rollback, and disaster recovery ensure operational excellence

With ArgoCD managing your ChatGPT app deployments, you achieve continuous delivery with zero manual intervention, comprehensive observability, and enterprise-grade reliability.

Ready to automate your ChatGPT app deployments? Start building with MakeAIHQ.com and deploy production-ready ChatGPT apps with built-in GitOps workflows, one-click deployment to the ChatGPT App Store, and comprehensive DevOps tooling—no manual Kubernetes configuration required.


Related Resources

  • Kubernetes Deployment Strategies for ChatGPT Apps
  • CI/CD Pipelines for ChatGPT App Development
  • Monitoring ChatGPT Apps in Production
  • Kubernetes Security Best Practices
  • Multi-Cluster Kubernetes Management
  • ChatGPT App Scaling Strategies
  • Configuration Management Patterns
  • Observability for ChatGPT Apps
  • Incident Response Automation
  • SRE for ChatGPT Apps

External Resources: