What I want is to have ArgoCD approve a job that is in the approval step in CircleCI when a deployment was successful.
However, this has been a multi week journey with no results. I first looked at this:
https://argo-cd.readthedocs.io/en/stable/user-guide/resource_hooks/
I spent the time building out an entire argo workflow, and job. Then setup a pipeline to capture the waiting job id (before updating the yaml file) and run the workflow with that id that would generate a PostSync
that could use that id to approve the waiting circleci job only AFTER a successful deploy, then destroy itself. I also had one for SyncFail as well. My hopes were dashed when I realized this was generic. I couldn't see a way to only run this job for a specific application in argocd, it appears to run on ANY sync event. (What??)
Now I'm looking at this: https://argo-cd.readthedocs.io/en/stable/operator-manual/notifications/
However, yet again I see hiccups already before I event started. There seems no possible way to run custom code, therefore I can't run the API to approve my job. Has anyone gotten a callback system for a specific app working? I can try and hack something together by calling back to a pipeline to run an API, but that just seems dumb. There has to be a better way....
Nearly a month of searching, building, and digging through code later and I have something working. Wasn't exactly what I wanted above but I think this is probably better in the long run anyway.
Instead of a callback mechanism I went with a async callback, although I will give you some ideas of ways you can implement the callback approval mechanism below.
Background
I'm using the following services:
By default
argocd-notifications
comes bundled withargocd
whileargocd-workflows
does not and is required to have a separate install. (all done via the community helm charts).ArgoCD-Notifications Setup
argocd-notifications-cm
(configmap MUST be named this,argocd
will auto pickup this configmap name)argocd-notifications-secret
(secret MUST be named this for the same reason)argocd-notifications-cm
Please note, if you just use this as is you will overwrite the one that is generated by default. You can append this to the existing map if you want, just be sure to capture that information BEFORE applying your own.
argocd-notifications-secret
This secret must also exist so that it will know what the $ARGO_WORKFLOWS_API_TOKEN is:
In the above I'm using an external secret so I can maintain the secret elsewhere and have it synced to kuberentes but you can also just use a plain Secret if you want. Subscription
Now this one got me for a while, but you can ONLY add these annotations to the kubernetes resource
kind: Application
. This is something that only argocd understands. You can add it like:This takes advantage of the
{{.recipient}}
as defined in the configmap above. It will add the following into the{{.recipient}}
entry on that configmap BEFORE firing the event:Now the
argo-notifications
side is completed. We need to setup the argo-workflows side....Argo-Workflows Setup
You will need to setup some way to communicate with
argo-workflows
. That means you will need to setup a webhook (sorry won't go into detail how to do that here, just know you need to have it). Get API TokenNext we need to setup a service account,
rolebinding
, androle
that will we use to access the api ofargo-workflows
. In order to get the api token that we use in the configmap above for notifications we need to generate a secret:Doing this will then allow us to run the following command to get the api token and place it either into the external secret or the
argocd-notifications-secret
directly:Setup Job Manifest
Now that we have the token we can setup a job manifest that will be triggered by the noficiation which will be in charge of calling back to any pipeline we want (circleci, github, bitbucket, etc.) -- in this example I'm using
github
:Note: I don't spell everything out for you here, as you will need to get your
GITHUB_TOKEN
into the workflow. I would just use my provided example for "secrets" via a volume mount. I would use a github app to dynamically generate the token as well, more secure.NOTE2:
While first building I would probably remove this until you're ready for it. Github Setup
Now that we have
argo-notifications
andargo-workflows
setup we can setup a repository dispatch event inside ourgithub
pipeline (or something equivalent for other pipelines)As long as I didn't typo something and you filled everything out it should be working.
However, what if it isn't? Lets talk about debugging. Debugging
Argo-Notifications
Should spit out the notifications controller. Then you can look at it's logs:
I added -f if you want to follow along the logs in realtime.
Argo-Workflows
there is a server and a controller just like
argo-notifications
. Look at those logs using the same method. That should give you all the information you need to succeed! Good luck!Argo-Notifications documentation was hell. Also here is some helpful info on un-documented things like app.status etc.
https://github.com/argoproj/gitops-engine/blob/187312fe86ed627b1cf4147c13dccf9ff331424b/pkg/sync/sync_task.go
https://github.com/argoproj/gitops-engine/blob/master/pkg/sync/common/types.go#L54
Callback Approval
Now with all the above you can achieve a callback approval if you use a database, something like dynamo db to store the hash that is triggering the deployment. Then use the undocument app.status.operationState.syncResult.revision (Which is basically the short hash for the commit) parameter inside your configmap to send it to
argo-workflows
. Thenargo-workflows
will use that hash to lookup that information in the database to know who it should respond to.I know this is going to be a super valuable resource for anyone working with workflows or notifications.