HomeBlogGitOps with GitHub Actions + ArgoCD: End-to-End Walkthrough
GitOpsArgoCDKubernetesGitHub Actions

GitOps with GitHub Actions + ArgoCD: End-to-End Walkthrough

April 28, 2026·18 min read·Omphora Engineering

What GitOps actually means

GitOps is a deployment methodology where Git is the single source of truth for your infrastructure and application state. Instead of running kubectl apply or helm upgrade in a CI pipeline, you commit the desired state to a Git repository, and a controller (ArgoCD or Flux) continuously reconciles the live cluster state to match it.

The key benefit: every production change is a Git commit. With a full audit trail, instant rollback (just revert the commit), and no direct cluster access required from CI systems.

The architecture

Developer pushes → CI builds image → updates GitOps repo → ArgoCD syncs to cluster

Two repositories:

  • App repo: application code + Dockerfile + CI workflow
  • GitOps repo: Kubernetes manifests + Helm values for all environments

ArgoCD installation

Install ArgoCD with Helm into your EKS cluster:

helm repo add argo https://argoproj.github.io/argo-helm
helm install argocd argo/argo-cd \
  --namespace argocd \
  --create-namespace \
  --values argocd-values.yaml
# argocd-values.yaml
global:
  domain: argocd.example.com

server:
  ingress:
    enabled: true
    ingressClassName: nginx
    tls: true

configs:
  params:
    server.insecure: false
  rbac:
    policy.default: role:readonly

App-of-Apps pattern

For managing multiple applications, use the app-of-apps pattern. One root ArgoCD Application manages all your other Applications:

# apps/root.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: root
  namespace: argocd
spec:
  source:
    repoURL: https://github.com/your-org/k8s-configs
    path: apps/
    targetRevision: HEAD
  destination:
    server: https://kubernetes.default.svc
    namespace: argocd
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

Automated image tag updates

After a successful CI build, update the image tag in the GitOps repo:

# .github/workflows/deploy.yml
- name: Checkout GitOps repo
  uses: actions/checkout@v4
  with:
    repository: your-org/k8s-configs
    token: ${{ secrets.GITOPS_PAT }}
    path: k8s-configs

- name: Update image tag
  run: |
    cd k8s-configs
    yq e -i '.image.tag = "${{ github.sha }}"' \
      apps/my-app/overlays/staging/values.yaml
    git config user.name "github-actions[bot]"
    git config user.email "github-actions[bot]@users.noreply.github.com"
    git commit -am "chore: promote my-app to ${{ github.sha }}"
    git push

ArgoCD detects the push within 3 minutes (or immediately with a webhook) and syncs the new image to the cluster.

Canary rollouts with Argo Rollouts

For production deployments, replace the standard Kubernetes Deployment with an Argo Rollout:

apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: my-app
spec:
  replicas: 10
  strategy:
    canary:
      canaryService: my-app-canary
      stableService: my-app-stable
      trafficRouting:
        nginx:
          stableIngress: my-app-ingress
      steps:
        - setWeight: 10          # 10% traffic to canary
        - pause: { duration: 5m }
        - analysis:              # Auto-check error rates
            templates:
              - templateName: success-rate
        - setWeight: 50
        - pause: { duration: 10m }
        - setWeight: 100
      autoPromotionEnabled: false  # Require explicit promotion

The AnalysisTemplate queries Prometheus to verify the canary is healthy:

apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
  name: success-rate
spec:
  metrics:
    - name: success-rate
      interval: 1m
      successCondition: result[0] >= 0.95
      failureLimit: 3
      provider:
        prometheus:
          address: http://prometheus:9090
          query: |
            sum(rate(http_requests_total{status!~"5..", app="my-app", canary="true"}[5m]))
            /
            sum(rate(http_requests_total{app="my-app", canary="true"}[5m]))

If the error rate drops below 95%, Argo Rollouts automatically aborts the canary and routes all traffic back to stable.

Summary

  • ArgoCD watches your GitOps repo, not your CI system
  • CI only pushes images and commits tag updates — never touches the cluster
  • App-of-apps simplifies managing many services
  • Argo Rollouts adds progressive delivery with automatic rollback
  • Full audit trail of every deployment in Git history

Not sure where to start?
Let's talk.

One conversation, no commitment. We listen to what your team is struggling with and give you an honest picture of what needs to change — and what doesn't.

  • What's slowing down your team's deployment process
  • Where your cloud spend is going — and what's being wasted
  • Security vulnerabilities in your current setup
  • Reliability gaps that could cause downtime
  • Blind spots in your monitoring and alerting
Available for new projectsResponse within 1 business dayNo long-term commitment required
your-infra ~ after-omphora
$ terraform apply
✓ 23 resources. Apply complete in 4m 12s
$ kubectl get nodes
NAME STATUS ROLES AGE
ip-10-0-1 Ready worker 2d
ip-10-0-2 Ready worker 2d
ip-10-0-3 Ready worker 2d
$ argocd app list
production Synced Healthy
staging Synced Healthy
$ # Commit → production: 3m 42s
✓ Zero downtime · p99: 82ms · cost ↓ 38%
$ # Example output — results vary by workload.
3m 42s
Deploy time
38%
Cost saved
99.9%
Uptime