Configure ArgoCD with SonarQube quality gates for GitOps deployment validation

Advanced 45 min Apr 25, 2026 16 views
Ubuntu 24.04 Debian 12 AlmaLinux 9 Rocky Linux 9

Set up automated quality gate validation in ArgoCD using SonarQube webhooks and pre-sync hooks to prevent deployments that fail code quality standards. This integration ensures only code that passes your quality criteria gets deployed to production.

Prerequisites

  • Running Kubernetes cluster with ArgoCD
  • SonarQube server with API access
  • kubectl configured
  • Basic understanding of webhooks and Kubernetes Jobs

What this solves

This tutorial shows you how to integrate SonarQube quality gates with ArgoCD to automatically validate code quality before GitOps deployments. When SonarQube detects quality gate failures, ArgoCD will block the deployment, preventing broken or insecure code from reaching production environments.

Prerequisites

  • Running Kubernetes cluster with ArgoCD installed
  • SonarQube server accessible from your ArgoCD cluster
  • Git repository with your application code and manifests
  • Basic understanding of Kubernetes webhooks and ArgoCD sync policies

Step-by-step configuration

Create SonarQube webhook configuration

First, configure SonarQube to send quality gate status updates to a webhook endpoint that ArgoCD can process.

kubectl create namespace sonarqube-webhook
kubectl create configmap webhook-config -n sonarqube-webhook --from-literal=sonar-url="http://sonarqube.example.com:9000"

Deploy webhook service for quality gate validation

Create a webhook service that receives SonarQube quality gate notifications and stores the results for ArgoCD to check.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: sonarqube-webhook
  namespace: sonarqube-webhook
spec:
  replicas: 2
  selector:
    matchLabels:
      app: sonarqube-webhook
  template:
    metadata:
      labels:
        app: sonarqube-webhook
    spec:
      containers:
      - name: webhook
        image: nginx:alpine
        ports:
        - containerPort: 80
        env:
        - name: SONAR_URL
          valueFrom:
            configMapKeyRef:
              name: webhook-config
              key: sonar-url
---
apiVersion: v1
kind: Service
metadata:
  name: sonarqube-webhook-service
  namespace: sonarqube-webhook
spec:
  selector:
    app: sonarqube-webhook
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
  type: ClusterIP
kubectl apply -f webhook-deployment.yaml

Configure SonarQube project webhook

In your SonarQube project, add a webhook that sends quality gate results to your Kubernetes webhook service.

curl -u admin:admin123 -X POST "http://sonarqube.example.com:9000/api/webhooks/create" \
  -d "name=ArgoCD-QualityGate" \
  -d "url=http://sonarqube-webhook-service.sonarqube-webhook.svc.cluster.local/webhook" \
  -d "project=your-project-key"

Create ArgoCD pre-sync hook script

Create a script that ArgoCD will run before each sync to check the latest SonarQube quality gate status.

#!/bin/bash
set -e

SONAR_PROJECT_KEY="${SONAR_PROJECT_KEY}"
SONAR_URL="${SONAR_URL}"
SONAR_TOKEN="${SONAR_TOKEN}"
GIT_COMMIT="${ARGOCD_APP_REVISION}"

Check if quality gate passed for this commit

echo "Checking quality gate for commit: ${GIT_COMMIT}"

Get quality gate status from SonarQube API

QUALITY_GATE_STATUS=$(curl -s -u "${SONAR_TOKEN}:" \ "${SONAR_URL}/api/qualitygates/project_status?projectKey=${SONAR_PROJECT_KEY}" \ | jq -r '.projectStatus.status') echo "Quality gate status: ${QUALITY_GATE_STATUS}" if [ "${QUALITY_GATE_STATUS}" != "OK" ]; then echo "Quality gate failed. Blocking deployment." echo "View details: ${SONAR_URL}/dashboard?id=${SONAR_PROJECT_KEY}" exit 1 fi echo "Quality gate passed. Proceeding with deployment." exit 0

Create ConfigMap for the quality gate script

Store the validation script in a ConfigMap so ArgoCD can access it during pre-sync hooks.

kubectl create configmap quality-gate-script -n argocd \
  --from-file=quality-gate-check.sh

Create pre-sync hook Job template

Define a Kubernetes Job that runs the quality gate validation before each ArgoCD sync operation.

apiVersion: batch/v1
kind: Job
metadata:
  name: quality-gate-check
  namespace: default
  annotations:
    argocd.argoproj.io/hook: PreSync
    argocd.argoproj.io/hook-delete-policy: BeforeHookCreation
    argocd.argoproj.io/sync-wave: "-1"
spec:
  template:
    spec:
      restartPolicy: Never
      containers:
      - name: quality-gate-checker
        image: curlimages/curl:latest
        command: ["/bin/sh"]
        args: ["/scripts/quality-gate-check.sh"]
        env:
        - name: SONAR_PROJECT_KEY
          value: "your-project-key"
        - name: SONAR_URL
          value: "http://sonarqube.example.com:9000"
        - name: SONAR_TOKEN
          valueFrom:
            secretKeyRef:
              name: sonarqube-token
              key: token
        - name: ARGOCD_APP_REVISION
          valueFrom:
            fieldRef:
              fieldPath: metadata.annotations['argocd.argoproj.io/revision']
        volumeMounts:
        - name: script-volume
          mountPath: /scripts
      volumes:
      - name: script-volume
        configMap:
          name: quality-gate-script
          defaultMode: 0755
  backoffLimit: 3

Create SonarQube authentication secret

Store your SonarQube authentication token securely in a Kubernetes secret.

kubectl create secret generic sonarqube-token -n default \
  --from-literal=token="your-sonarqube-token-here"

Configure ArgoCD Application with sync policy

Update your ArgoCD Application to include the pre-sync hook and configure sync policies that respect quality gates.

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-application
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/example/my-app.git
    targetRevision: main
    path: k8s
  destination:
    server: https://kubernetes.default.svc
    namespace: default
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
    - CreateNamespace=true
    - PrunePropagationPolicy=foreground
    retry:
      limit: 3
      backoff:
        duration: 5s
        factor: 2
        maxDuration: 3m
kubectl apply -f argocd-app.yaml

Configure RBAC for ArgoCD service account

Grant necessary permissions for ArgoCD to execute pre-sync hooks and access quality gate information.

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: argocd-quality-gate-checker
rules:
  • apiGroups: ["batch"]
resources: ["jobs"] verbs: ["create", "delete", "get", "list", "patch", "update", "watch"]
  • apiGroups: [""]
resources: ["configmaps", "secrets"] verbs: ["get", "list"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: argocd-quality-gate-checker roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: argocd-quality-gate-checker subjects:
  • kind: ServiceAccount
name: argocd-application-controller namespace: argocd
kubectl apply -f rbac-config.yaml

Implement deployment validation policies

Create additional validation rules that complement SonarQube quality gates for comprehensive deployment safety.

apiVersion: v1
kind: ConfigMap
metadata:
  name: deployment-policies
  namespace: argocd
data:
  policy.rego: |
    package argocd.quality
    
    # Allow deployment only if quality gate passes
    allow {
        input.quality_gate.status == "OK"
        input.security_scan.vulnerabilities.critical == 0
        input.test_coverage.percentage >= 80
    }
    
    # Block deployment on quality gate failure
    deny[msg] {
        input.quality_gate.status != "OK"
        msg := "Quality gate failed. Deployment blocked."
    }
    
    # Block deployment on critical vulnerabilities
    deny[msg] {
        input.security_scan.vulnerabilities.critical > 0
        msg := "Critical security vulnerabilities detected."
    }
kubectl apply -f validation-policy.yaml

Configure ArgoCD notifications for quality gate events

Set up notifications to alert teams when deployments are blocked due to quality gate failures.

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-notifications-cm
  namespace: argocd
data:
  service.slack: |
    token: your-slack-bot-token
  template.quality-gate-failed: |
    message: |
      🚫 Deployment blocked for {{.app.metadata.name}}
      Quality gate failed in SonarQube
      Repository: {{.app.spec.source.repoURL}}
      Revision: {{.app.status.sync.revision}}
      View details: http://sonarqube.example.com:9000/dashboard?id={{.app.metadata.annotations.sonar-project}}
  trigger.on-sync-failed: |
    - when: app.status.operationState.phase in ['Failed']
      send: [quality-gate-failed]
  subscriptions: |
    - recipients:
      - slack:dev-team-channel
      triggers:
      - on-sync-failed
kubectl apply -f argocd-notifications-config.yaml

Monitor quality gate integration

Set up monitoring for webhook service

Monitor the webhook service that processes SonarQube quality gate notifications to ensure reliable operation.

apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: sonarqube-webhook-monitor
  namespace: sonarqube-webhook
spec:
  selector:
    matchLabels:
      app: sonarqube-webhook
  endpoints:
  - port: http
    path: /metrics
    interval: 30s
kubectl apply -f webhook-monitor.yaml

Create alerting rules for quality gate failures

Set up Prometheus alerts to notify when quality gates consistently fail or when the webhook service is unavailable.

apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: quality-gate-alerts
  namespace: sonarqube-webhook
spec:
  groups:
  - name: quality-gate.rules
    rules:
    - alert: QualityGateWebhookDown
      expr: up{job="sonarqube-webhook"} == 0
      for: 5m
      labels:
        severity: critical
      annotations:
        summary: "SonarQube webhook service is down"
        description: "The webhook service for SonarQube quality gates has been down for more than 5 minutes"
    - alert: HighQualityGateFailureRate
      expr: rate(quality_gate_failures_total[5m]) > 0.5
      for: 10m
      labels:
        severity: warning
      annotations:
        summary: "High rate of quality gate failures"
        description: "Quality gate failure rate is {{ $value }} failures per second over the last 5 minutes"
kubectl apply -f quality-gate-alerts.yaml

Verify your setup

Test the integration by triggering a deployment with code that fails SonarQube quality gates.

# Check ArgoCD application status
kubectl get applications -n argocd

Verify pre-sync hook execution

kubectl get jobs -n default | grep quality-gate

Check webhook service status

kubectl get pods -n sonarqube-webhook kubectl logs -l app=sonarqube-webhook -n sonarqube-webhook

Test SonarQube webhook connectivity

curl -X POST http://sonarqube-webhook-service.sonarqube-webhook.svc.cluster.local/webhook \ -H "Content-Type: application/json" \ -d '{"status":"ERROR","projectKey":"test"}'

View ArgoCD sync history

argocd app history my-application

Troubleshoot quality gate failures

Debug pre-sync hook failures

When deployments are blocked, examine the pre-sync hook logs to understand why quality gates failed.

# Get failed job logs
kubectl logs -l job-name=quality-gate-check -n default

Check ArgoCD sync operation details

argocd app get my-application --show-operation

Verify SonarQube project status manually

curl -u "your-token:" "http://sonarqube.example.com:9000/api/qualitygates/project_status?projectKey=your-project"

Check webhook service connectivity

kubectl exec -it deploy/sonarqube-webhook -n sonarqube-webhook -- wget -O- http://sonarqube.example.com:9000/api/system/status

Override quality gates for emergency deployments

In emergency situations, you can temporarily bypass quality gate validation while maintaining audit trails.

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-application
  namespace: argocd
  annotations:
    quality-gate.override: "emergency-deployment-ticket-12345"
    quality-gate.override-reason: "Critical security patch deployment"
    quality-gate.override-authorized-by: "team-lead@company.com"
spec:
  # ... rest of application spec
  syncPolicy:
    syncOptions:
    - SkipHooks=true  # Temporarily skip pre-sync hooks
kubectl apply -f emergency-override.yaml

Common issues

Symptom Cause Fix
Pre-sync hook job fails with network timeout SonarQube server unreachable from cluster Verify network policies and DNS resolution: kubectl exec -it deploy/sonarqube-webhook -n sonarqube-webhook -- nslookup sonarqube.example.com
Quality gate check returns "ERROR" for passing projects Wrong project key or authentication token Verify project key and regenerate SonarQube token: kubectl get secret sonarqube-token -o yaml
ArgoCD shows sync successful but hook wasn't executed Pre-sync hook annotation missing or incorrect Check hook annotations: kubectl get job quality-gate-check -o yaml | grep annotations
Webhook receives duplicate notifications Multiple webhook configurations in SonarQube List and clean up webhooks: curl -u admin:admin123 "http://sonarqube.example.com:9000/api/webhooks/list"
Job pod fails with permission denied Missing RBAC permissions for service account Verify cluster role binding: kubectl get clusterrolebinding argocd-quality-gate-checker -o yaml

Next steps

Running this in production?

Want this handled for you? Running this at scale adds a second layer of work: capacity planning, failover drills, cost control, and on-call. Our managed platform covers monitoring, backups and 24/7 response by default.

Automated install script

Run this to automate the entire setup

Need help?

Don't want to manage this yourself?

We handle managed devops services for businesses that depend on uptime. From initial setup to ongoing operations.