DEV Community

Cover image for Using ArgoCD Pull Request Generator to review application modifications
Julien Acroute for Camptocamp Infrastructure Solutions

Posted on • Edited on

Using ArgoCD Pull Request Generator to review application modifications

As a developer, when modifications are pushed to a feature branch, you and your team want to test this new feature. If you have the chance to work with a stateless application, you can deploy another instance of the application with modifications from the feature branch.

An interesting feature of ArgoCD is the Pull Request Generator. It's a generator for ApplicationSet. An ApplicationSet is a template of ArgoCD Application associated with a generator. Generator can be a directory: an application will be created for every sub-folder. There is also the Cluster generator that deploy the same Application but in every cluster managed by ArgoCD.

The syntax for the Pull Request generator is quite simple:

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: myapps
spec:
  generators:
  - pullRequest:
      github:
        owner: camptocamp
        repo: myrepository
        tokenRef:
          secretName: github-token
          key: token
        labels:
        - deploy
  template:
    ...
Enter fullscreen mode Exit fullscreen mode

Before testing this feature what is expected ?

  • A new ArgoCD Application is created when a pull request is created with a "deploy" label
  • In the template of the Application we can use metadata of the pull request: ID, title, description, labels, source and target branch name, commit ref, …
  • A comment is added to the PR when the Application is deployed and Synced with the available URLs

Now we will see how to implement this ;-)

Workflow before Implementation

Source Code Repository

Let's start with a simple application repository: git@github.com:camptocamp/frontend.git
Let's consider that this repository has a github action that builds a container image when a pull request is opened. The image is tagged with the short commit hash and the concatenation of the branch name and the short commit hash. For example, if the feature branch is name update_lib with the last commit: 4a9b29e, the following tags will be generated:

  • 4a9b29e
  • update_lib-4a9b29e

Deployment Repository

There is another git repository: git@github.com:camptocamp/argocd-project-foo-apps.git to describe what needs to be deployed in each kubernetes cluster (dev, int, …). In this repository, we have one folder per environment:

apps
├── dev
│   ├── backend
│   └── frontend
├── int
│   ├── backend
│   └── frontend
└── prod
    ├── backend
    └── frontend
Enter fullscreen mode Exit fullscreen mode

We are using an ApplicationSet to deploy every component defined in this git repository using the directory generator. For example, for "dev" env:

---
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: foo-dev
  namespace: argocd
spec:
  generators:
  - git:
      directories:
      - path: apps/dev/*
      repoURL: git@github.com:camptocamp/argocd-project-foo-apps.git
      revision: main
  template:
    metadata:
      name: foo-dev-{{path.basename}} # sub folder name
    spec:
      source:
        path: '{{path}}' # full path
        repoURL: git@github.com:camptocamp/argocd-project-foo-apps.git
        targetRevision: main
      project: default
      destination:
        namespace: foo-dev
        server: https://kubernetes.default.svc

Enter fullscreen mode Exit fullscreen mode

This ApplicationSet will create one ArgoCD Application per folder in apps/dev/. Imagine that we have the following structure in git :

apps
└── dev
    ├── backend
    │   ├── Chart.yaml
    │   └── values.yaml
    ├── database
    │   ├── Chart.yaml
    │   └── values.yaml
    └── frontend
        ├── Chart.yaml
        └── values.yaml
Enter fullscreen mode Exit fullscreen mode

This will generate 3 Argocd Applications :

  • foo-dev-database
  • foo-dev-backend
  • foo-dev-frontend

Review App Workflow

When a pull request is opened for a specific application, for example the frontend, we want to deploy a new instance of this specific component. We will monitor pull requests on the frontend repository.
So we want to create an additional ApplicationSet to deploy the frontend if a pull request is created with the label deploy in the frontend git repository.

Implementation

Create a token to access GitHub API

First step is to create a token to access the frontend repository.

Then we need to deploy this token as a kubernetes secret in the cluster :

export GITHUB_TOKEN=ghp_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
kubectl create secret generic github-token \
  --from-literal=token=$GITHUB_TOKEN \
  -o yaml --dry-run=client > github-token-secret.yaml
Enter fullscreen mode Exit fullscreen mode

If you follow the GitOps principles to deploy manifests in the cluster, you can commit this file.

Create a webhook

For a better user experience, we can setup a webhook that will notify ArgoCD when something changes on Github.
This webhook needs to be defined in the source code repository, where pull requests are created.
Go to the repository "Settings" and then "Webhooks". Click on the "Add webhook" button.

  • The Payload URL is the URL to access ArgoCD with the path /api/webhook.
  • The Content Type should be set to application/json.
  • It's a good idea to set a "Secret", just use a random string, we will use this random string in the next step.
  • Regarding events, we need to individually selects events and choose "Pull requests" events.

Deploy the new ApplicationSet

This new ApplicationSet will use the "Pull request" generator, this "generator" will monitor pull requests on the source code repository. Just create and commit a file with the following ApplicationSet manifest and deploy this new manifest.

---
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: foo-dev-review-frontend
  namespace: argocd
spec:
  generators:
  - pullRequest:
      github:
        owner: camptocamp
        repo: frontend # This is the application source code repo
        tokenRef:
          secretName: github-token
          key: token
        labels:
        - deploy # label on PR that trigger review app
  template:
    metadata:
      name: 'foo-dev-frontend-{{branch}}-{{number}}'
    spec:
      source:
        repoURL: git@github.com:camptocamp/argocd-project-foo-apps.git
        targetRevision: main
        path: apps/dev/frontend
        helm:
          parameters:
          - name: "image.tag"
            value: "{{branch}}-{{head_sha}}" # override of the image tag
          - name: "ingress.prefix"
            value: "{{branch}}" # add a prefix to the URL 
      project: default
      destination:
        server: https://kubernetes.default.svc
        namespace: foo-dev
Enter fullscreen mode Exit fullscreen mode

This ApplicationSet will deploy a new instance of the frontend for each pull request with the deploy label. The image tag will be overridden with the branch name and the short commit hash and a unique prefix will be added to the URL to avoid conflicts with other instances. Finally, the name of the release is also unique as it's the same as the Application name: foo-dev-frontend-{{branch}}-{{number}}, this should also avoid conflicts on object names.

Configure ArgoCD to use secret for webhook

The last step is to protect the ArgoCD webhook with a password. The ArgoCD Helm chart allows setting a secret for the github webhook endpoint : configs.secret.githubSecret.

Testing

Now it's time to test. For this step, you just need to make a modification in the source repository and create a pull request for this. Please wait until the container image is built. Then by adding the deploy label a new ArgoCD app should be created :-)

Conclusion

This new ArgoCD feature is very interesting. Maybe it can help to have feedback on the pull requests to see the status of the review app. It can also be interesting to have the list of URLs available. ArgoCD already shows this information in the webUI. So maybe just a link to the ArgocD application is enough.

Camptocamp will participate in the KubeCon at Amsterdam from 18 to 21 april. Maybe we can meet there and discuss development workflows that really help developers.

Top comments (3)

Collapse
 
chrislin22 profile image
Chris Lin

One key thing is to use dynamic namespace (probably based on the name of repo and branch name) for the deployment. In scenarios multiple PR's on the same repo.
Can you shown in your helm chart example how to pass in like the{{ .Release.Namespace }} for each PR? Thanks

Collapse
 
joshuabaird profile image
Josh Baird

How did you handle posting the comment on the PR letting the user know the app was deployed?

Collapse
 
vampouille profile image
Julien Acroute

Unfortunately it's not implemented in argocd. Argocd has rights to inspect le PR and it should be able to post comment. From my point of view it can be a nice improvement.