instruction: Design a GitOps workflow with ArgoCD for application deployment
output: Here's a comprehensive GitOps workflow with ArgoCD:
  
  ```yaml
  # argocd-install.yaml - ArgoCD Installation
  apiVersion: v1
  kind: Namespace
  metadata:
   name: argocd
  
  ---
  # Install ArgoCD using official manifests
  # kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
  
  # argocd-server-service.yaml - Expose ArgoCD Server
  apiVersion: v1
  kind: Service
  metadata:
   labels:
   app.kubernetes.io/component: server
   app.kubernetes.io/name: argocd-server
   app.kubernetes.io/part-of: argocd
   name: argocd-server-nodeport
   namespace: argocd
  spec:
   ports:
   - name: https
   nodePort: 30443
   port: 443
   protocol: TCP
   targetPort: 8080
   selector:
   app.kubernetes.io/name: argocd-server
   type: NodePort
  
  ---
  # argocd-ingress.yaml - Ingress for ArgoCD
  apiVersion: networking.k8s.io/v1
  kind: Ingress
  metadata:
   name: argocd-server-ingress
   namespace: argocd
   annotations:
   kubernetes.io/ingress.class: nginx
   cert-manager.io/cluster-issuer: "letsencrypt-prod"
   nginx.ingress.kubernetes.io/ssl-redirect: "true"
   nginx.ingress.kubernetes.io/backend-protocol: "GRPC"
  spec:
   tls:
   - hosts:
   - argocd.example.com
   secretName: argocd-server-tls
   rules:
   - host: argocd.example.com
   http:
   paths:
   - path: /
   pathType: Prefix
   backend:
   service:
   name: argocd-server
   port:
   number: 443
  
  ---
  # argocd-cm.yaml - ArgoCD Configuration
  apiVersion: v1
  kind: ConfigMap
  metadata:
   name: argocd-cm
   namespace: argocd
   labels:
   app.kubernetes.io/name: argocd-cm
   app.kubernetes.io/part-of: argocd
  data:
   url: https://argocd.example.com
   
   # Dex configuration for OIDC
   dex.config: |
   connectors:
   - type: oidc
   id: oidc
   name: OpenID Connect
   config:
   issuer: https://your-oidc-provider.com
   clientId: argocd
   clientSecret: $oidc.clientSecret
   requestedScopes: ["openid", "profile", "email", "groups"]
   requestedIDTokenClaims: {"groups": {"essential": true}}
   
   # Repository credentials
   repositories: |
   - type: git
   url: https://github.com/your-org/app-config
   - type: git
   url: https://github.com/your-org/infrastructure
   
   # Application instance label key
   application.instanceLabelKey: argocd.argoproj.io/instance
   
   # Server configuration
   server.insecure: "false"
   server.grpc.web: "true"
   
   # Enable status badge
   statusbadge.enabled: "true"
   
   # Resource customizations
   resource.customizations: |
   argoproj.io/Application:
   health.lua: |
   hs = {}
   hs.status = "Healthy"
   if obj.status ~= nil then
   if obj.status.health ~= nil then
   hs.status = obj.status.health.status
   if obj.status.health.message ~= nil then
   hs.message = obj.status.health.message
   end
   end
   end
   return hs
  
  ---
  # argocd-rbac-cm.yaml - RBAC Configuration
  apiVersion: v1
  kind: ConfigMap
  metadata:
   name: argocd-rbac-cm
   namespace: argocd
   labels:
   app.kubernetes.io/name: argocd-rbac-cm
   app.kubernetes.io/part-of: argocd
  data:
   policy.default: role:readonly
   policy.csv: |
   # Admin role
   p, role:admin, applications, *, */*, allow
   p, role:admin, certificates, *, *, allow
   p, role:admin, clusters, *, *, allow
   p, role:admin, repositories, *, *, allow
   
   # Developer role
   p, role:developer, applications, get, */*, allow
   p, role:developer, applications, sync, */*, allow
   p, role:developer, applications, action/*, */*, allow
   p, role:developer, logs, get, */*, allow
   p, role:developer, exec, create, */*, allow
   
   # DevOps role
   p, role:devops, applications, *, */*, allow
   p, role:devops, repositories, *, *, allow
   p, role:devops, certificates, *, *, allow
   
   # Group mappings
   g, argocd-admins, role:admin
   g, developers, role:developer
   g, devops-team, role:devops
  
  ---
  # app-of-apps.yaml - App of Apps Pattern
  apiVersion: argoproj.io/v1alpha1
  kind: Application
  metadata:
   name: app-of-apps
   namespace: argocd
   finalizers:
   - resources-finalizer.argocd.argoproj.io
  spec:
   project: default
   source:
   repoURL: https://github.com/your-org/gitops-apps
   targetRevision: HEAD
   path: apps
   destination:
   server: https://kubernetes.default.svc
   namespace: argocd
   syncPolicy:
   automated:
   prune: true
   selfHeal: true
   allowEmpty: false
   syncOptions:
   - Validate=true
   - CreateNamespace=true
   - PrunePropagationPolicy=foreground
   - PruneLast=true
   retry:
   limit: 5
   backoff:
   duration: 5s
   factor: 2
   maxDuration: 3m
  
  ---
  # apps/web-app-dev.yaml - Development Application
  apiVersion: argoproj.io/v1alpha1
  kind: Application
  metadata:
   name: web-app-dev
   namespace: argocd
   annotations:
   argocd.argoproj.io/sync-wave: "1"
   finalizers:
   - resources-finalizer.argocd.argoproj.io
  spec:
   project: development
   source:
   repoURL: https://github.com/your-org/web-app-config
   targetRevision: HEAD
   path: environments/dev
   helm:
   valueFiles:
   - values-dev.yaml
   parameters:
   - name: image.tag
   value: "latest"
   - name: replicaCount
   value: "1"
   destination:
   server: https://kubernetes.default.svc
   namespace: web-app-dev
   syncPolicy:
   automated:
   prune: true
   selfHeal: true
   syncOptions:
   - CreateNamespace=true
   - Validate=true
   retry:
   limit: 3
   backoff:
   duration: 5s
   factor: 2
   maxDuration: 3m
   ignoreDifferences:
   - group: apps
   kind: Deployment
   jsonPointers:
   - /spec/replicas
   revisionHistoryLimit: 10
  
  ---
  # apps/web-app-staging.yaml - Staging Application
  apiVersion: argoproj.io/v1alpha1
  kind: Application
  metadata:
   name: web-app-staging
   namespace: argocd
   annotations:
   argocd.argoproj.io/sync-wave: "2"
   notifications.argoproj.io/ finalizers:
   - resources-finalizer.argocd.argoproj.io
  spec:
   project: staging
   source:
   repoURL: https://github.com/your-org/web-app-config
   targetRevision: release
   path: environments/staging
   helm:
   valueFiles:
   - values-staging.yaml
   destination:
   server: https://kubernetes.default.svc
   namespace: web-app-staging
   syncPolicy:
   syncOptions:
   - CreateNamespace=true
   - Validate=true
   retry:
   limit: 5
   backoff:
   duration: 5s
   factor: 2
   maxDuration: 5m
   revisionHistoryLimit: 5
  
  ---
  # apps/web-app-prod.yaml - Production Application
  apiVersion: argoproj.io/v1alpha1
  kind: Application
  metadata:
   name: web-app-prod
   namespace: argocd
   annotations:
   argocd.argoproj.io/sync-wave: "3"
   notifications.argoproj.io/ notifications.argoproj.io/ finalizers:
   - resources-finalizer.argocd.argoproj.io
  spec:
   project: production
   source:
   repoURL: https://github.com/your-org/web-app-config
   targetRevision: v1.0.0 # Use specific version tags for production
   path: environments/production
   helm:
   valueFiles:
   - values-production.yaml
   destination:
   server: https://kubernetes.default.svc
   namespace: web-app-prod
   syncPolicy:
   # Manual sync for production
   syncOptions:
   - CreateNamespace=true
   - Validate=true
   retry:
   limit: 2
   backoff:
   duration: 10s
   factor: 2
   maxDuration: 10m
   revisionHistoryLimit: 10
  
  ---
  # projects/development-project.yaml - Development Project
  apiVersion: argoproj.io/v1alpha1
  kind: AppProject
  metadata:
   name: development
   namespace: argocd
  spec:
   description: Development environment projects
   
   sourceRepos:
   - 'https://github.com/your-org/*'
   - 'https://charts.helm.sh/stable'
   - 'https://charts.bitnami.com/bitnami'
   
   destinations:
   - namespace: 'web-app-dev'
   server: https://kubernetes.default.svc
   - namespace: 'api-dev'
   server: https://kubernetes.default.svc
   
   clusterResourceWhitelist:
   - group: ''
   kind: Namespace
   - group: 'rbac.authorization.k8s.io'
   kind: ClusterRole
   - group: 'rbac.authorization.k8s.io'
   kind: ClusterRoleBinding
   
   namespaceResourceWhitelist:
   - group: ''
   kind: ConfigMap
   - group: ''
   kind: Secret
   - group: ''
   kind: Service
   - group: 'apps'
   kind: Deployment
   - group: 'apps'
   kind: ReplicaSet
   - group: 'networking.k8s.io'
   kind: Ingress
   
   roles:
   - name: developer
   description: Developer access to development apps
   policies:
   - p, proj:development:developer, applications, get, development/*, allow
   - p, proj:development:developer, applications, sync, development/*, allow
   - p, proj:development:developer, applications, action/*, development/*, allow
   groups:
   - developers
  
  ---
  # projects/production-project.yaml - Production Project
  apiVersion: argoproj.io/v1alpha1
  kind: AppProject
  metadata:
   name: production
   namespace: argocd
  spec:
   description: Production environment projects
   
   sourceRepos:
   - 'https://github.com/your-org/web-app-config'
   
   destinations:
   - namespace: 'web-app-prod'
   server: https://kubernetes.default.svc
   
   clusterResourceWhitelist:
   - group: ''
   kind: Namespace
   
   namespaceResourceWhitelist:
   - group: ''
   kind: ConfigMap
   - group: ''
   kind: Secret
   - group: ''
   kind: Service
   - group: 'apps'
   kind: Deployment
   - group: 'networking.k8s.io'
   kind: Ingress
   
   # Signature verification for production
   signatureKeys:
   - keyID: ABCDEF1234567890
   
   roles:
   - name: admin
   description: Admin access to production apps
   policies:
   - p, proj:production:admin, applications, *, production/*, allow
   groups:
   - argocd-admins
   - devops-team
  
  ---
  # notification-config.yaml - ArgoCD Notifications
  apiVersion: v1
  kind: ConfigMap
  metadata:
   name: argocd-notifications-cm
   namespace: argocd
  data:
   service.slack: |
   token: $slack-token
   
   template.app-deployed: |
   message: |
   Application {{.app.metadata.name}} has been successfully deployed to {{.app.spec.destination.namespace}}.
   Revision: {{.app.status.sync.revision}}
   Repository: {{.app.spec.source.repoURL}}
   
   template.app-health-degraded: |
   message: |
   🚨 Application {{.app.metadata.name}} health status changed to {{.app.status.health.status}}.
   Repository: {{.app.spec.source.repoURL}}
   
   template.app-sync-failed: |
   message: |
   ❌ Application {{.app.metadata.name}} sync failed.
   Repository: {{.app.spec.source.repoURL}}
   Error: {{.app.status.operationState.message}}
   
   trigger.on-deployed: |
   - when: app.status.operationState.phase in ['Succeeded'] and app.status.health.status == 'Healthy'
   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]
  
  ---
  # argocd-notifications-secret.yaml
  apiVersion: v1
  kind: Secret
  metadata:
   name: argocd-notifications-secret
   namespace: argocd
  type: Opaque
  data:
   slack-token: <base64-encoded-slack-token>
  
  ---
  # image-updater.yaml - ArgoCD Image Updater
  apiVersion: argoproj.io/v1alpha1
  kind: Application
  metadata:
   name: argocd-image-updater
   namespace: argocd
  spec:
   project: default
   source:
   repoURL: https://argoproj.github.io/argo-helm
   chart: argocd-image-updater
   targetRevision: 0.8.1
   helm:
   values: |
   config:
   applications: |
   - name: web-app-dev
   image_list:
   - name: web-app
   image_name: your-registry/web-app
   image_tag: latest
   update_strategy: latest
   registry_api: docker
   write_back_method: git
   git_branch: main
   
   authScripts:
   enabled: true
   scripts:
   git-ask-pass.sh: |
   #!/bin/sh
   echo $GIT_TOKEN
   
   env:
   - name: GIT_TOKEN
   valueFrom:
   secretKeyRef:
   name: git-credentials
   key: token
   
   destination:
   server: https://kubernetes.default.svc
   namespace: argocd
   syncPolicy:
   automated:
   prune: true
   selfHeal: true
  
  ---
  # repository-secret.yaml - Git Repository Access
  apiVersion: v1
  kind: Secret
  metadata:
   name: private-repo
   namespace: argocd
   labels:
   argocd.argoproj.io/secret-type: repository
  type: Opaque
  stringData:
   type: git
   url: https://github.com/your-org/private-repo
   password: <github-token>
   username: not-used
  
  ---
  # cluster-secret.yaml - External Cluster Access
  apiVersion: v1
  kind: Secret
  metadata:
   name: staging-cluster
   namespace: argocd
   labels:
   argocd.argoproj.io/secret-type: cluster
  type: Opaque
  stringData:
   name: staging-cluster
   server: https://staging-cluster.example.com
   config: |
   {
   "bearerToken": "<service-account-token>",
   "tlsClientConfig": {
   "insecure": false,
   "caData": "<base64-encoded-ca-cert>"
   }
   }
  ```
  
  This GitOps setup provides:
  - Complete ArgoCD installation and configuration
  - App of Apps pattern for managing multiple applications
  - Environment-specific applications (dev, staging, production)
  - RBAC with role-based access control
  - Notifications integration with Slack
  - Image updater for automatic updates
  - Multi-cluster deployment support
  - Security best practices with signature verification