Automatic review apps for microservices with ArgoCD
Learn how to use ArgoCD’s ApplicationSet to automatically deploy review apps for microservices using the PullRequestGenerator
In this article, we will explain how to set up ArgoCD to automatically deploy review apps for GitLab Merge Requests (MRs), enabling your QA Tester or Customer to easily test and approve new features.
The principles for GitHub PRs or any other platform are almost identical, and if you have any additional questions on these platforms, feel free to reach out!
Application configuration
Creating a separate application on MR creation
To ensure that ArgoCD creates a new application once the MR has been created, we can use an ApplicationSet and add the Pull Request Generator. The Pull Request Generator utilizes the GitLab API to periodically poll for new/updated MRs and mirror applications for these MRs.
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
spec:
generators:
- pullRequest:
gitlab:
project: "48042720"
api: https://gitlab.com/
tokenRef:
secretName: gitlab-token
key: token
pullRequestState: opened
template:
metadata:
name: 'example-app-{{branch}}-{{number}}'
spec:
source:
repoURL: https://gitlab.com/argo-review-app-example/k8s-configuration-kustomize.git
path: example-app/overlays/qa
targetRevision: main
kustomize:
commonAnnotations:
app/param-host: pr-{{number}}.somedomain.com
project: default
destination:
server: https://kubernetes.default.svc
namespace: 'example-app-{{branch}}-{{number}}'
syncPolicy:
automated: {}
syncOptions:
- CreateNamespace=true
When you’ve got this running, great! You are actually done and ready to use Review apps for a simple/single repository!
However, if we are using multiple repositories, such as a backend and frontend service, we may need to test the frontend MR alongside the backend MR in the same environment.
ArgoCD’s generators allow us to define multiple sources, so we can add both repositories to the generator list.
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
spec:
generators:
- pullRequest:
gitlab:
project: "48042720"
api: https://gitlab.com/
tokenRef:
secretName: gitlab-token
key: token
pullRequestState: opened
- pullRequest:
gitlab:
project: "48042732"
api: https://gitlab.com/
tokenRef:
secretName: gitlab-token
key: token
pullRequestState: opened
Handle duplicate branches across repositories
With two Git repositories configured as sources for the generator, we can create the frontend MR and have it spawn an application. However, generating the backend MR using the same branch name will attempt to create an already existing application.
To resolve this issue, we can utilize the Merge Generator from ArgoCD, which enables us to remove duplicate values and merge the configuration if the branch name matches. We use the mergeKeys
value to check if the value is identical, and not create a second (or third) application for the same branch in a different repository.
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: example-app-pr-generator
spec:
generators:
- merge:
mergeKeys:
- branch
generators:
- pullRequest:
gitlab:
project: "48042720"
api: https://gitlab.com/
tokenRef:
secretName: gitlab-token
key: token
pullRequestState: opened
- pullRequest:
gitlab:
project: "48042732"
api: https://gitlab.com/
tokenRef:
secretName: gitlab-token
key: token
pullRequestState: opened
Because we are working with multiple repositories, we must overwrite the generated application with the CI images from the project repositories, as we cannot guess both SHA’s from the application set (maybe the backend service does not have this branch because it only affects the frontend change).
To do this, we need to allow the Application to be modified, as the ApplicationSet keeps this in sync by default (so it replaces any modifications we apply to it). We can change this policy for the application set to only create and delete the application, but not update it with any changes.
Because review apps are short lived environments, the application set not applying new updates is only a minor disadvantage. If a change on the application set is made, which is important to propagate to a existing review app, you could use GitLab to re-open the PR or remove and re-add the “preview” label (or any other label you use to trigger the creation of the review app).
ArgoCD’s latest release candidate (v2.8.0) includes a major QoL feature which allows us to set the policy per application set, instead of for the entire controller.
Argo ≥ 2.8.0
From ArgoCD 2.8.0 and later, you will be able to set the sync policy in the application set:
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
spec:
template:
spec:
syncPolicy:
applicationSync: create-delete
Argo < 2.8.0
In ArgoCD, we need to make a change to the applicationset-controller deployment. We can either add a flag to the command arguments --policy create-delete
or set the ARGOCD_APPLICATIONSET_CONTROLLER_POLICY
environment variable to create-delete
.
Setting the ingress URL
Finally, we need to be able to access the application(s). This is possible by using commonAnnotations
in Kustomize (or Helm values when you are using Helm).
To do this, we need to add some commonAnnotations
for the hostname of each application. These commonAnnotations
will be applied to every manifest/resource that is included in this kustomization repository.
kustomize:
commonAnnotations:
backend/param-host: pr-{{number}}.somedomain.com
frontend/param-host: fe-pr-{{number}}.somedomain.com
We can now use this value in our kustomization.yaml
to generate the correct URL, using a replacement taking the value from the annotation and placing it on the right keys in the Ingress manifest.
replacements:
- source:
kind: Ingress
name: example
fieldPath: metadata.annotations.backend/param-host
targets:
fieldPaths:
- spec.rules.0.host
- spec.tls.0.hosts.0
- select:
kind: Certificate
name: example-tls-certificate
fieldPaths:
- spec.dnsNames.0
You can also use commonAnnotations
for setting environment variables. For instance, to let your frontend display the branch name as version or set up communication between frontend and backend.
Pipeline configuration
In GitLab, our primary concern for deploying a review app is to ensure that we build a container that we can deploy. The initial CI step would involve building and pushing the container to the registry path, which is also specified in your Kubernetes manifests.
After the build process, we can utilize the Argo CD CLI to update the image tag for the image to the most recent build container. To ensure that GitLab is also aware of this review app and its running state, we should implement a CI pipeline to start and stop the environment. This ensures that the running state in GitLab remains accurate and up-to-date.
The pipeline should run after the image container has been built and pushed, and you should run the following command (when using Kustomize):
argocd app set example-app-${CI_BRANCH_NAME}-${CI_MERGE_REQUEST_ID} --kustomize-image yourimage:${CI_COMMIT_SHA}
Conclusion
By following these steps, you’ll unleash the power of ArgoCD, streamlining your testing process, and boosting your team’s productivity. Automated review apps not only enhance efficiency but also ensure that your products maintain the highest quality.
As always, if you have any questions after reading this article, feel free to ask for any additional guidelines or help.