New to Kestra?
Use blueprints to kickstart your first workflows.
Detect Argo CD targetRevision drift, alert Slack or auto-patch it back to the approved revision, and log the result for platform teams.
Argo CD enforces that the cluster matches whatever targetRevision an Application's spec
currently points to, but it has no opinion on whether that targetRevision itself is still
the one your team approved. Someone with cluster or Argo CD UI access can point an
Application at a different branch, a stale tag, or a one-off commit, and Argo CD will happily
sync to it, fully "Synced" and "Healthy" the entire time. This blueprint checks the live spec
against the revision you expect, and only corrects it once you have explicitly said this flow
is allowed to.
This blueprint was created by Mohit Jeswani.
check_app_spec (io.kestra.plugin.argocd.apps.Status) reads the full Application object
via argocd app get --output json. The task only parses sync/health state into typed
outputs, so evaluate reads the live spec.source.targetRevision back out of
rawOutput.evaluate (io.kestra.plugin.core.output.OutputValues) compares the live
targetRevision against expected_target_revision and classifies the result as
ALIGNED, DRIFT_AUTO_PATCH, DRIFT_NEEDS_HUMAN, or UNREACHABLE, folding
confirm_patch into the drifted classification itself.route (io.kestra.plugin.core.flow.Switch):io.kestra.plugin.argocd.apps.Patch with a merge patch
restoring spec.source.targetRevision (the safe remediation, since it restores the
already-approved value), then posts a Slack notice that it happened automatically.summary logs the severity, closing the governance cycle.errors alerts Slack if the flow itself fails, for example a revoked Argo CD token.confirm_patch to allow it.apps.Patch used as a
governance remediation, distinct from this repo's existing Argo CD blueprints, which watch
sync and health status rather than the spec's own source configuration.Argo CD reconciles the cluster to whatever targetRevision is currently set; it has no
policy engine comparing that value against an approved one, and no Slack integration of its
own. Kestra keeps expected_target_revision and confirm_patch as flow inputs, turns a raw
app get response into a policy decision, and keeps a full execution history of every drift
this flow has seen and what it did about it.
A local Argo CD instance can be installed into a kind (Kubernetes-in-Docker) cluster via
Argo CD's official install manifests for a fully local end-to-end test, no managed account
required.
ARGOCD_SERVER: the Argo CD API server URL used by check_app_spec and
patch_target_revision. In Kestra OSS, provide it as the base64-encoded environment
variable SECRET_ARGOCD_SERVER.ARGOCD_TOKEN: the Argo CD authentication token. In Kestra OSS, provide it as the
base64-encoded environment variable SECRET_ARGOCD_TOKEN.SLACK_WEBHOOK_URL: used by all three Slack alert cases and the errors block. In Kestra
OSS, provide it as the base64-encoded environment variable SECRET_SLACK_WEBHOOK_URL.| Input | Default | Purpose |
|---|---|---|
argocd_application |
my-argocd-app |
Application to check |
expected_target_revision |
main |
GitOps-approved branch, tag, or commit |
confirm_patch |
false |
Authorizes this flow to patch the application itself |
{{ outputs.check_app_spec.rawOutput }}: the full argocd app get --output json response,
as text.{{ outputs.evaluate.values.live_target_revision }} / .severity: the application's live
targetRevision, and ALIGNED, DRIFT_AUTO_PATCH, DRIFT_NEEDS_HUMAN, or UNREACHABLE.io.kestra.plugin.argocd.apps.Status's Output does not expose spec at all, only
syncStatus, healthStatus, conditions, resources, and rawOutput; this is verified
directly against the task's source, since neither its Javadoc examples nor its field list
make that limitation obvious. evaluate works around it by parsing rawOutput itself with
fromjson inside a jq filter.spec.source.targetRevision for a single-source Application. A
multi-source Application keeps its revisions under spec.sources[].targetRevision
instead, which this blueprint does not read.confirm_patch applies to the whole flow, not one specific drift; a scheduled run with
confirm_patch: true will patch back any drift this flow finds on every run, so treat it as
"this application's revision is fully policy-enforced," not a one-time approval.ARGOCD_SERVER, ARGOCD_TOKEN, and SLACK_WEBHOOK_URL secrets.argocd_application at a real Application and expected_target_revision at its
current, correct revision; run manually and confirm log_aligned fires.targetRevision (via the Argo CD UI or CLI) and run again with
confirm_patch: false; confirm alert_drift fires.confirm_patch: true; confirm patch_target_revision restores it and
alert_auto_patched fires.hourly trigger once the inputs reflect a real application and policy.jq filter to also compare spec.source.repoURL and spec.source.path, so a
redirected repository or path counts as drift too, not just the revision.io.kestra.plugin.core.flow.ForEach to
run this policy check across an entire Argo CD project in one scheduled run.