ArgoCD: Create Applications based on Pull Requests

argocd kubernetes ApplicationSet pull request github

4 min read | by Jordi Prats

One of the key features of ArgoCD is the ApplicationSet, which provides a way to group multiple applications together and deploy them as a single unit. This allows you to manage and deploy multiple applications as a single entity, making it easier to coordinate deployments across multiple teams and applications.

We have several ways of generating Applications using and ApplicationSet, one of them is using the repositories Pull Requests.

The PR generator is a convenient way to implement a GitOps workflow, where changes to infrastructure are made through pull requests, ensuring that all changes are reviewed and approved before they are deployed.

It supports several SCMaaS providers such as GitHub, GitLab, Gitea, and Bitbucket Server. For this example we are going to use GitHub, but the changes to use any other provider are minimal.

First, we'll have to store the credentials in a secret, got GitHub it's going to be a PAT:

apiVersion: v1
kind: Secret
metadata:
  name: github-token
data:
  token: Z2hwXzEyMzQ1Njc4OTBwdXRhNDU2Nzg5ZXNwYW55YTg5MDEyMzQ1Ng==

Once this secret is available we just need to create the ApplicationSet, using the spec.template field to configure how the actual Applications are going to be generated. To be able to create them, we'll have some variables available:

  • number: The ID number of the pull request.
  • branch: The name of the branch of the pull request head. You can use it's slug using branch_slug.
  • head_sha: This is the SHA of the head of the pull request, being able to use the short version as well: head_short_sha.
  • labels: The array of pull request labels.

With these values we can create applications using the PR the repo like this:

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: pr-versions
  namespace: argocd
spec:
  generators:
  - pullRequest:
      github:
        owner: pet2cattle
        repo: demo-app
        tokenRef:
          secretName: github-token
          key: token
      requeueAfterSeconds: 600
  template:
    metadata:
      name: "demo-app-pr{{ number }}"
      namespace: argocd
    spec:
      project: default
      destination:
        namespace: demo-app
        server: 'https://kubernetes.default.svc'
      source:
        repoURL: git@github.com:pet2cattle/demo-app.git
        path: manifests
        targetRevision: "{{ head_sha }}"
        kustomize:
          namePrefix: "pr{{ number }}-"
          commonLabels:
            app-instance: "pr{{ number }}"
          commonAnnotations:
            domain: "pr{{ number }}.127.0.0.1.nip.io"
          images:
          - "jordiprats/demoapp=jordiprats/demoapp:pr{{ number }}"
      syncPolicy:
        automated:
          selfHeal: true
          prune: true
        syncOptions:
          - CreateNamespace=true

If when we create the ApplicationSet there are no pull requests, we'll get an error condition as follows:

$ kubectl describe applicationset pr-versions
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
(...)
Status:
  Conditions:
    Last Transition Time:  2023-01-02T14:05:50Z
    Message:               error listing repos: error listing pull requests for pet2cattle/demo-app: GET https://api.github.com/repos/pet2cattle/demo-app/pulls?per_page=100: 404 Not Found []
    Reason:                ApplicationGenerationFromParamsError
    Status:                True
    Type:                  ErrorOccurred
    Last Transition Time:  2023-01-02T14:05:50Z
    Message:               error listing repos: error listing pull requests for pet2cattle/demo-app: GET https://api.github.com/repos/pet2cattle/demo-app/pulls?per_page=100: 404 Not Found []
    Reason:                ErrorOccurred
    Status:                False
    Type:                  ParametersGenerated
    Last Transition Time:  2023-01-02T14:05:50Z
    Message:               error listing repos: error listing pull requests for pet2cattle/demo-app: GET https://api.github.com/repos/pet2cattle/demo-app/pulls?per_page=100: 404 Not Found []
    Reason:                ApplicationGenerationFromParamsError
    Status:                False
    Type:                  ResourcesUpToDate
Events:                    <none>

As soon as we create the first PR, the error will go away:

$ kubectl get applicationset pr-versions -o yaml
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
(...)
status:
  conditions:
  - lastTransitionTime: "2023-01-03T08:45:53Z"
    message: Successfully generated parameters for all Applications
    reason: ApplicationSetUpToDate
    status: "False"
    type: ErrorOccurred
  - lastTransitionTime: "2023-01-03T08:45:53Z"
    message: Successfully generated parameters for all Applications
    reason: ParametersGenerated
    status: "True"
    type: ParametersGenerated
  - lastTransitionTime: "2023-01-03T08:45:53Z"
    message: ApplicationSet up to date
    reason: ApplicationSetUpToDate
    status: "True"
    type: ResourcesUpToDate

Posted on 22/02/2023