Pull Request Generator

The Pull Request generator uses the API of an SCMaaS provider (GitHub, Gitea, or Bitbucket Server) to automatically discover open pull requests within a repository. This fits well with the style of building a test environment when you create a pull request.

  1. apiVersion: argoproj.io/v1alpha1
  2. kind: ApplicationSet
  3. metadata:
  4. name: myapps
  5. spec:
  6. goTemplate: true
  7. goTemplateOptions: ["missingkey=error"]
  8. generators:
  9. - pullRequest:
  10. # When using a Pull Request generator, the ApplicationSet controller polls every `requeueAfterSeconds` interval (defaulting to every 30 minutes) to detect changes.
  11. requeueAfterSeconds: 1800
  12. # See below for provider specific options.
  13. github:
  14. # ...

Note

Know the security implications of PR generators in ApplicationSets. Only admins may create ApplicationSets to avoid leaking Secrets, and only admins may create PRs if the project field of an ApplicationSet with a PR generator is templated, to avoid granting management of out-of-bounds resources.

GitHub

Specify the repository from which to fetch the GitHub Pull requests.

  1. apiVersion: argoproj.io/v1alpha1
  2. kind: ApplicationSet
  3. metadata:
  4. name: myapps
  5. spec:
  6. goTemplate: true
  7. goTemplateOptions: ["missingkey=error"]
  8. generators:
  9. - pullRequest:
  10. github:
  11. # The GitHub organization or user.
  12. owner: myorg
  13. # The Github repository
  14. repo: myrepository
  15. # For GitHub Enterprise (optional)
  16. api: https://git.example.com/
  17. # Reference to a Secret containing an access token. (optional)
  18. tokenRef:
  19. secretName: github-token
  20. key: token
  21. # (optional) use a GitHub App to access the API instead of a PAT.
  22. appSecretName: github-app-repo-creds
  23. # Labels is used to filter the PRs that you want to target. (optional)
  24. labels:
  25. - preview
  26. requeueAfterSeconds: 1800
  27. template:
  28. # ...
  • owner: Required name of the GitHub organization or user.
  • repo: Required name of the GitHub repository.
  • api: If using GitHub Enterprise, the URL to access it. (Optional)
  • tokenRef: A Secret name and key containing the GitHub access token to use for requests. If not specified, will make anonymous requests which have a lower rate limit and can only see public repositories. (Optional)
  • labels: Filter the PRs to those containing all of the labels listed. (Optional)
  • appSecretName: A Secret name containing a GitHub App secret in repo-creds format.

GitLab

Specify the project from which to fetch the GitLab merge requests.

  1. apiVersion: argoproj.io/v1alpha1
  2. kind: ApplicationSet
  3. metadata:
  4. name: myapps
  5. spec:
  6. goTemplate: true
  7. goTemplateOptions: ["missingkey=error"]
  8. generators:
  9. - pullRequest:
  10. gitlab:
  11. # The GitLab project.
  12. project: myproject
  13. # For self-hosted GitLab (optional)
  14. api: https://git.example.com/
  15. # Reference to a Secret containing an access token. (optional)
  16. tokenRef:
  17. secretName: gitlab-token
  18. key: token
  19. # Labels is used to filter the MRs that you want to target. (optional)
  20. labels:
  21. - preview
  22. # MR state is used to filter MRs only with a certain state. (optional)
  23. pullRequestState: opened
  24. # If true, skips validating the SCM provider's TLS certificate - useful for self-signed certificates.
  25. insecure: false
  26. requeueAfterSeconds: 1800
  27. template:
  28. # ...
  • project: Required name of the GitLab project.
  • api: If using self-hosted GitLab, the URL to access it. (Optional)
  • tokenRef: A Secret name and key containing the GitLab access token to use for requests. If not specified, will make anonymous requests which have a lower rate limit and can only see public repositories. (Optional)
  • labels: Labels is used to filter the MRs that you want to target. (Optional)
  • pullRequestState: PullRequestState is an additional MRs filter to get only those with a certain state. Default: “” (all states)
  • insecure: By default (false) - Skip checking the validity of the SCM’s certificate - useful for self-signed TLS certificates.

As a preferable alternative to setting insecure to true, you can configure self-signed TLS certificates for Gitlab by mounting self-signed certificate to the applicationset controller.

Gitea

Specify the repository from which to fetch the Gitea Pull requests.

  1. apiVersion: argoproj.io/v1alpha1
  2. kind: ApplicationSet
  3. metadata:
  4. name: myapps
  5. spec:
  6. goTemplate: true
  7. goTemplateOptions: ["missingkey=error"]
  8. generators:
  9. - pullRequest:
  10. gitea:
  11. # The Gitea organization or user.
  12. owner: myorg
  13. # The Gitea repository
  14. repo: myrepository
  15. # The Gitea url to use
  16. api: https://gitea.mydomain.com/
  17. # Reference to a Secret containing an access token. (optional)
  18. tokenRef:
  19. secretName: gitea-token
  20. key: token
  21. # many gitea deployments use TLS, but many are self-hosted and self-signed certificates
  22. insecure: true
  23. requeueAfterSeconds: 1800
  24. template:
  25. # ...
  • owner: Required name of the Gitea organization or user.
  • repo: Required name of the Gitea repository.
  • api: The url of the Gitea instance.
  • tokenRef: A Secret name and key containing the Gitea access token to use for requests. If not specified, will make anonymous requests which have a lower rate limit and can only see public repositories. (Optional)
  • insecure: Allow for self-signed certificates, primarily for testing.

Bitbucket Server

Fetch pull requests from a repo hosted on a Bitbucket Server (not the same as Bitbucket Cloud).

  1. apiVersion: argoproj.io/v1alpha1
  2. kind: ApplicationSet
  3. metadata:
  4. name: myapps
  5. spec:
  6. goTemplate: true
  7. goTemplateOptions: ["missingkey=error"]
  8. generators:
  9. - pullRequest:
  10. bitbucketServer:
  11. project: myproject
  12. repo: myrepository
  13. # URL of the Bitbucket Server. Required.
  14. api: https://mycompany.bitbucket.org
  15. # Credentials for Basic authentication. Required for private repositories.
  16. basicAuth:
  17. # The username to authenticate with
  18. username: myuser
  19. # Reference to a Secret containing the password or personal access token.
  20. passwordRef:
  21. secretName: mypassword
  22. key: password
  23. # Labels are not supported by Bitbucket Server, so filtering by label is not possible.
  24. # Filter PRs using the source branch name. (optional)
  25. filters:
  26. - branchMatch: ".*-argocd"
  27. template:
  28. # ...
  • project: Required name of the Bitbucket project
  • repo: Required name of the Bitbucket repository.
  • api: Required URL to access the Bitbucket REST API. For the example above, an API request would be made to https://mycompany.bitbucket.org/rest/api/1.0/projects/myproject/repos/myrepository/pull-requests
  • branchMatch: Optional regexp filter which should match the source branch name. This is an alternative to labels which are not supported by Bitbucket server.

If you want to access a private repository, you must also provide the credentials for Basic auth (this is the only auth supported currently): * username: The username to authenticate with. It only needs read access to the relevant repo. * passwordRef: A Secret name and key containing the password or personal access token to use for requests.

Bitbucket Cloud

Fetch pull requests from a repo hosted on a Bitbucket Cloud.

  1. apiVersion: argoproj.io/v1alpha1
  2. kind: ApplicationSet
  3. metadata:
  4. name: myapps
  5. spec:
  6. goTemplate: true
  7. goTemplateOptions: ["missingkey=error"]
  8. generators:
  9. - pullRequest:
  10. bitbucket:
  11. # Workspace name where the repoistory is stored under. Required.
  12. owner: myproject
  13. # Repository slug. Required.
  14. repo: myrepository
  15. # URL of the Bitbucket Server. (optional) Will default to 'https://api.bitbucket.org/2.0'.
  16. api: https://api.bitbucket.org/2.0
  17. # Credentials for Basic authentication (App Password). Either basicAuth or bearerToken
  18. # authentication is required to access private repositories
  19. basicAuth:
  20. # The username to authenticate with
  21. username: myuser
  22. # Reference to a Secret containing the password or personal access token.
  23. passwordRef:
  24. secretName: mypassword
  25. key: password
  26. # Credentials for Bearer Token (App Token) authentication. Either basicAuth or bearerToken
  27. # authentication is required to access private repositories
  28. bearerToken:
  29. tokenRef:
  30. secretName: repotoken
  31. key: token
  32. # Labels are not supported by Bitbucket Cloud, so filtering by label is not possible.
  33. # Filter PRs using the source branch name. (optional)
  34. filters:
  35. - branchMatch: ".*-argocd"
  36. template:
  37. # ...
  • owner: Required name of the Bitbucket workspace
  • repo: Required name of the Bitbucket repository.
  • api: Optional URL to access the Bitbucket REST API. For the example above, an API request would be made to https://api.bitbucket.org/2.0/repositories/{workspace}/{repo_slug}/pullrequests. If not set, defaults to https://api.bitbucket.org/2.0
  • branchMatch: Optional regexp filter which should match the source branch name. This is an alternative to labels which are not supported by Bitbucket server.

If you want to access a private repository, Argo CD will need credentials to access repository in Bitbucket Cloud. You can use Bitbucket App Password (generated per user, with access to whole workspace), or Bitbucket App Token (generated per repository, with access limited to repository scope only). If both App Password and App Token are defined, App Token will be used.

To use Bitbucket App Password, use basicAuth section. - username: The username to authenticate with. It only needs read access to the relevant repo. - passwordRef: A Secret name and key containing the password or personal access token to use for requests.

In case of Bitbucket App Token, go with bearerToken section. - tokenRef: A Secret name and key containing the app token to use for requests.

Azure DevOps

Specify the organization, project and repository from which you want to fetch pull requests.

  1. apiVersion: argoproj.io/v1alpha1
  2. kind: ApplicationSet
  3. metadata:
  4. name: myapps
  5. spec:
  6. goTemplate: true
  7. goTemplateOptions: ["missingkey=error"]
  8. generators:
  9. - pullRequest:
  10. azuredevops:
  11. # Azure DevOps org to scan. Required.
  12. organization: myorg
  13. # Azure DevOps project name to scan. Required.
  14. project: myproject
  15. # Azure DevOps repo name to scan. Required.
  16. repo: myrepository
  17. # The Azure DevOps API URL to talk to. If blank, use https://dev.azure.com/.
  18. api: https://dev.azure.com/
  19. # Reference to a Secret containing an access token. (optional)
  20. tokenRef:
  21. secretName: azure-devops-token
  22. key: token
  23. # Labels is used to filter the PRs that you want to target. (optional)
  24. labels:
  25. - preview
  26. requeueAfterSeconds: 1800
  27. template:
  28. # ...
  • organization: Required name of the Azure DevOps organization.
  • project: Required name of the Azure DevOps project.
  • repo: Required name of the Azure DevOps repository.
  • api: If using self-hosted Azure DevOps Repos, the URL to access it. (Optional)
  • tokenRef: A Secret name and key containing the Azure DevOps access token to use for requests. If not specified, will make anonymous requests which have a lower rate limit and can only see public repositories. (Optional)
  • labels: Filter the PRs to those containing all of the labels listed. (Optional)

Filters

Filters allow selecting which pull requests to generate for. Each filter can declare one or more conditions, all of which must pass. If multiple filters are present, any can match for a repository to be included. If no filters are specified, all pull requests will be processed. Currently, only a subset of filters is available when comparing with SCM provider filters.

  1. apiVersion: argoproj.io/v1alpha1
  2. kind: ApplicationSet
  3. metadata:
  4. name: myapps
  5. spec:
  6. goTemplate: true
  7. goTemplateOptions: ["missingkey=error"]
  8. generators:
  9. - pullRequest:
  10. # ...
  11. # Include any pull request ending with "argocd". (optional)
  12. filters:
  13. - branchMatch: ".*-argocd"
  14. template:
  15. # ...
  • branchMatch: A regexp matched against source branch names.
  • targetBranchMatch: A regexp matched against target branch names.

GitHub and GitLab also support a labels filter.

Template

As with all generators, several keys are available for replacement in the generated application.

The following is a comprehensive Helm Application example;

  1. apiVersion: argoproj.io/v1alpha1
  2. kind: ApplicationSet
  3. metadata:
  4. name: myapps
  5. spec:
  6. goTemplate: true
  7. goTemplateOptions: ["missingkey=error"]
  8. generators:
  9. - pullRequest:
  10. # ...
  11. template:
  12. metadata:
  13. name: 'myapp-{{.branch}}-{{.number}}'
  14. spec:
  15. source:
  16. repoURL: 'https://github.com/myorg/myrepo.git'
  17. targetRevision: '{{.head_sha}}'
  18. path: kubernetes/
  19. helm:
  20. parameters:
  21. - name: "image.tag"
  22. value: "pull-{{.head_sha}}"
  23. project: "my-project"
  24. destination:
  25. server: https://kubernetes.default.svc
  26. namespace: default

And, here is a robust Kustomize example;

  1. apiVersion: argoproj.io/v1alpha1
  2. kind: ApplicationSet
  3. metadata:
  4. name: myapps
  5. spec:
  6. goTemplate: true
  7. goTemplateOptions: ["missingkey=error"]
  8. generators:
  9. - pullRequest:
  10. # ...
  11. template:
  12. metadata:
  13. name: 'myapp-{{.branch}}-{{.number}}'
  14. spec:
  15. source:
  16. repoURL: 'https://github.com/myorg/myrepo.git'
  17. targetRevision: '{{.head_sha}}'
  18. path: kubernetes/
  19. kustomize:
  20. nameSuffix: '{{.branch}}'
  21. commonLabels:
  22. app.kubernetes.io/instance: '{{.branch}}-{{.number}}'
  23. images:
  24. - 'ghcr.io/myorg/myrepo:{{.head_sha}}'
  25. project: "my-project"
  26. destination:
  27. server: https://kubernetes.default.svc
  28. namespace: default
  • number: The ID number of the pull request.
  • branch: The name of the branch of the pull request head.
  • branch_slug: The branch name will be cleaned to be conform to the DNS label standard as defined in RFC 1123, and truncated to 50 characters to give room to append/suffix-ing it with 13 more characters.
  • target_branch: The name of the target branch of the pull request.
  • target_branch_slug: The target branch name will be cleaned to be conform to the DNS label standard as defined in RFC 1123, and truncated to 50 characters to give room to append/suffix-ing it with 13 more characters.
  • head_sha: This is the SHA of the head of the pull request.
  • head_short_sha: This is the short SHA of the head of the pull request (8 characters long or the length of the head SHA if it’s shorter).
  • head_short_sha_7: This is the short SHA of the head of the pull request (7 characters long or the length of the head SHA if it’s shorter).
  • labels: The array of pull request labels. (Supported only for Go Template ApplicationSet manifests.)

Webhook Configuration

When using a Pull Request generator, the ApplicationSet controller polls every requeueAfterSeconds interval (defaulting to every 30 minutes) to detect changes. To eliminate this delay from polling, the ApplicationSet webhook server can be configured to receive webhook events, which will trigger Application generation by the Pull Request generator.

The configuration is almost the same as the one described in the Git generator, but there is one difference: if you want to use the Pull Request Generator as well, additionally configure the following settings.

Note

The ApplicationSet controller webhook does not use the same webhook as the API server as defined here. ApplicationSet exposes a webhook server as a service of type ClusterIP. An ApplicationSet specific Ingress resource needs to be created to expose this service to the webhook source.

Github webhook configuration

In section 1, “Create the webhook in the Git provider”, add an event so that a webhook request will be sent when a pull request is created, closed, or label changed.

Add Webhook URL with uri /api/webhook and select content-type as json Add Webhook URL

Select Let me select individual events and enable the checkbox for Pull requests.

Add Webhook

The Pull Request Generator will requeue when the next action occurs.

  • opened
  • closed
  • reopened
  • labeled
  • unlabeled
  • synchronized

For more information about each event, please refer to the official documentation.

Gitlab webhook configuration

Enable checkbox for “Merge request events” in triggers list.

Add Gitlab Webhook

The Pull Request Generator will requeue when the next action occurs.

  • open
  • close
  • reopen
  • update
  • merge

For more information about each event, please refer to the official documentation.

Lifecycle

An Application will be generated when a Pull Request is discovered when the configured criteria is met - i.e. for GitHub when a Pull Request matches the specified labels and/or pullRequestState. Application will be removed when a Pull Request no longer meets the specified criteria.