Sync Phases and Hooks: Run Your Own Code Around a Sync
The Other Phases
You have built one hook and we've quickly gone through some of the other phases. However, there are more. The other phases use the same mechanism, the same way to define them, and the same delete policy options. The only difference is when they run in the sync. This is the full list of phases and their use cases:
| Phase | Runs | Use it for |
|---|---|---|
PreSync | Before the Sync-phase resources apply | Schema migration, cache seeding, a precondition check |
Sync | Alongside the normal manifests, in the same phase | A resource applied with the rest but tracked as a hook. Niche; most apps never need it |
PostSync | After the Sync-phase resources report healthy | Smoke tests, deploy notifications |
SyncFail | When the sync operation fails | Undo a PreSync side effect, send a failure alert |
PreDelete | Before Application resources are deleted, on full Application deletion only | A final backup or snapshot before teardown; a destructive cleanup you want to gate (a failed PreDelete blocks the deletion) |
PostDelete | After all Application resources are deleted, during teardown | External cleanup Kubernetes won't garbage-collect: deregister from an external system, delete cloud resources, drop external state |
Skip is the seventh value the argocd.argoproj.io/hook annotation accepts, but it isn't a timing phase. It tells Argo CD never to apply the resource, which is a way to disable one without removing it from the repo.
Choosing the right hook phases
Beyond PreSync, PostSync, and SyncFail, PreDelete can also be useful. Here are examples of jobs you might put in each phase.
A PostSync email notification:
apiVersion: batch/v1
kind: Job
metadata:
generateName: email-
namespace: argocd
annotations:
argocd.argoproj.io/hook: PostSync
argocd.argoproj.io/hook-delete-policy: HookSucceeded
spec:
backoffLimit: 4
activeDeadlineSeconds: 120 # a stuck relay must not block the sync
template:
spec:
restartPolicy: Never
containers:
- name: email
# Use an image that ships a mail client and reads SMTP
# settings from the environment. Verify the env var names
# against the image you choose; they vary.
image: juanluisbaptiste/postfix:1.7.1 # pin a real tag
command: ["/bin/sh", "-c"]
args:
- echo 'Deploy finished' | mail -s 'Argo CD: deploy finished' "$MAIL_TO"
env:
- name: MAIL_TO
value:
- name: SMTP_SERVER
value:
- name: SMTP_PORT
value: "587"
- name: SMTP_USERNAME
value:
- name: SMTP_PASSWORD
valueFrom:
secretKeyRef:
name: smtp-password
key: password
A PostSync Slack notification:
This one sends a message to a Slack channel when a deploy finishes. It uses Slack webhooks, which are a simple way to send messages without setting up a full Slack app.
apiVersion: batch/v1
kind: Job
metadata:
generateName: slack-notify-
namespace: argocd
annotations:
argocd.argoproj.io/hook: PostSync
argocd.argoproj.io/hook-delete-policy: HookSucceeded
specGitOps the Hard Way, with Argo CD
Build Real GitOps Pipelines From Empty Clusters to Automated DeploysEnroll now to unlock all content and receive all future updates for free.

