Argo CD can react to Git commits without polling, by receiving real-time notifications via webhooks.

Let’s see this in action. Imagine we have a simple Git repository with our Kubernetes manifests.

# repo/app.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-app
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/your-username/your-repo.git
    targetRevision: HEAD
    path: repo/
  destination:
    server: https://kubernetes.default.svc
    namespace: my-app
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

Normally, Argo CD would check repoURL periodically (defaulting to every 3 minutes) to see if targetRevision has changed. If it has, and automated sync is enabled, it would trigger a sync. With webhooks, we bypass this polling.

Here’s how it works:

  1. Git Provider Setup: Your Git provider (GitHub, GitLab, Bitbucket, Gitea, etc.) is configured to send an HTTP POST request to a specific URL whenever a push event occurs. This URL is an endpoint exposed by Argo CD.
  2. Argo CD Endpoint: Argo CD has a built-in webhook receiver. When it receives a POST request from your Git provider, it parses the payload to identify the repository and branch that was updated.
  3. Application Matching: Argo CD then looks for Application resources in its own cluster that are configured to track the specific repoURL and targetRevision (often HEAD for the default branch).
  4. Sync Trigger: If an Application matches the webhook’s origin and has an automated sync policy enabled, Argo CD will immediately initiate a sync to the latest commit.

The key to making this work is configuring the webhook in your Git provider to point to your Argo CD instance. The exact URL format is typically:

https://<argocd-server-address>/api/webhook

You’ll need to ensure that your Argo CD server is accessible from your Git provider. This often involves:

  • Publicly Accessible Argo CD: If your Git provider is external (like GitHub.com), your Argo CD instance needs to be reachable from the internet. This might mean exposing it via an Ingress controller with a TLS certificate.
  • Internal Argo CD: If you’re using a self-hosted Git provider (like Gitea or GitLab self-managed), your Argo CD instance can be on the same network.

Crucially, you need to secure this webhook. Git providers allow you to set a "secret" when configuring the webhook. This secret is then sent in a header (e.g., X-Hub-Signature-256 for GitHub) with each webhook request. Argo CD can be configured to verify this signature, ensuring that only legitimate requests from your Git provider trigger syncs.

To configure Argo CD to verify the webhook secret, you’d typically add an annotation to your Application resource or configure it at the argocd-secret level in the Argo CD namespace. The exact mechanism depends on your Argo CD version and how you’re deploying it. For instance, if using a secret named argocd-notifications-secret in the argocd namespace, you might add:

apiVersion: v1
kind: Secret
metadata:
  name: argocd-notifications-secret
  namespace: argocd
type: Opaque
stringData:
  # For GitHub:
  github.appsecret: "your-github-webhook-secret"
  # For GitLab:
  gitlab.appsecret: "your-gitlab-webhook-secret"

And your Application would need to reference this. However, a more common and direct approach for Argo CD’s built-in webhook is to use the argocd-secret in the argocd namespace with a key like webhook.github.secret (for GitHub).

When setting up the webhook in your Git provider, you’ll select "Push" as the event type. For GitHub, this looks like:

  • Payload URL: https://your-argocd-domain.com/api/webhook
  • Content type: application/json
  • Secret: your-super-secret-string
  • Which events would you like to trigger this webhook? Just the push event

Argo CD’s webhook receiver then processes this payload. It extracts the repository URL and the commit SHA. It compares this information against the source.repoURL and targetRevision of your Application resources. If they match and the application is configured for automated sync, the sync is initiated.

The benefit is immediate synchronization. Instead of waiting for the next 3-minute poll interval, your cluster can reflect the latest commit within seconds of it being pushed. This drastically reduces the latency between code commit and deployment.

A common pitfall is forgetting to add the argocd-server service to your Git provider’s IP allowlist if your Git provider requires it and your Argo CD is behind a firewall. Another is using the wrong webhook secret or not configuring the secret verification in Argo CD, which leads to the webhook being received but ignored because it fails the signature check.

The next thing you’ll likely want to explore is how to fine-tune which branches trigger syncs, or even how to use webhooks to trigger specific ApplicationSet generators.

Want structured learning?

Take the full Argocd course →