How the Argo CD Pull Request generator creates a preview environment for each open pull request
The Argo CD Pull Request generator creates one Application for each open pull request in a Git repository, so reviewers can open a running copy of a change before it merges. The generator sits inside an ApplicationSet, which the ApplicationSet controller reads to produce and maintain those Applications. Teams need this when a code change is hard to judge from a diff alone, such as a web front end, an API contract change or a Helm chart edit that only shows its effect once rendered and deployed. Each generated Application points at the pull request's head branch and deploys into a cluster you already run, so the preview workloads, their images and their logs stay inside your own infrastructure.
The ApplicationSet controller runs in the Argo CD installation and polls the Git provider through the generator's configuration. On each pass it queries the provider for open pull requests, filters them, and renders an Application template for every match, filling in values such as the branch name, pull request number and head SHA. Those parameters are what make each preview unique, for example a namespace or hostname derived from the pull request number. Before you rely on this, confirm the generator supports your Git host (GitHub, GitLab, Gitea, Bitbucket Server, Bitbucket Cloud and Azure DevOps are listed in the Argo CD Pull Request generator guide), and confirm how label filters and branch matching behave on that host, since the filtering options differ by provider.
The access the generator needs is the part to plan first. The controller needs a token or app credential that can list pull requests and read their metadata, and that credential is stored in the cluster where Argo CD runs, not in the repository. Scope it to the repositories that should get previews, and keep preview targets in a dedicated cluster or namespace where a bad preview cannot reach production workloads. Decide before rollout whether previews should be created for every pull request or only for those carrying a label, because that choice controls both cluster load and the number of Applications your reviewers will see. Ask your Git provider's administrator which token type fits your policy and what rate limits apply to it.
Generator options and when each one fits
This table compares the Pull Request generator choices that shape a preview setup: which Git provider you use, how pull requests are filtered, how often the generator polls, and whether a webhook server is worth its own Ingress. Read each row against your Git host, then confirm the exact field names in the generator guide before you write the ApplicationSet. The main takeaway is that label filtering is not available everywhere, so your provider often decides the filter design.
| Option | What it does | Choose it when | Confirm before building |
|---|---|---|---|
| GitHub | Generates one Application per open pull request; supports label filters | Your code review and CI already run on GitHub, and you want labels to mark which pull requests get a preview | Token scope, label filter syntax and webhook setup in the generator guide |
| GitLab | Generates per pull request (merge request); supports label filters and webhooks | Your repositories and merge requests live in GitLab, including self-managed instances | Merge request field names and webhook secret handling for your version |
| Azure DevOps | Generates per pull request; supports label filters | Your Git repositories and pipelines are in Azure DevOps Repos | Authentication method and label filter fields against the guide |
| Bitbucket Cloud or Bitbucket Server | Generates per pull request; uses branch matching, not label filters | Your pull requests are on Bitbucket and you filter previews by source branch name | Branch match pattern and whether your Bitbucket edition supports the polling interval you need |
| Gitea | Generates per pull request; listed as supported in the generator guide | Your Git host is Gitea and you accept its provider-specific settings | Filter options and API token requirements for your Gitea version |
| Label filters | Only pull requests carrying a named label produce an environment | You want reviewers to opt in to a preview, which limits cluster spend on routine changes | Label names and whether label changes trigger generation promptly on your provider |
| Branch matching | Pull requests whose source branch matches a pattern produce an environment | Your provider has no label filter, or branch naming already marks work that needs previews | Pattern syntax and how renamed or forked branches are handled |
| requeueAfterSeconds | Sets how often the generator polls the provider; the documented default is 30 minutes | Polling alone is acceptable, for example for low-change repositories where a delay is tolerable | The value you set, and whether shorter intervals raise API request use against your provider's rate limits |
| Webhook server | Lets GitHub or GitLab notify Argo CD so generation runs sooner than the next poll; needs its own Ingress | Reviewers expect a preview to appear within minutes of opening a pull request | Ingress exposure, webhook secret configuration and network path from the Git host |
Setting up the generator in a cluster you control
This sequence takes a cluster from a working Argo CD install to one where every open pull request gets its own Application, and where closing the pull request removes it. Each step ends with a check so the team can confirm the generator behaves before anyone relies on it.
Confirm the Argo CD and ApplicationSet controller versions
Your platform engineer checks which Argo CD release is running in the cluster and confirms that the ApplicationSet controller is deployed alongside the application controller. Confirm the version against the upgrade and release notes for your Argo CD line before you write any manifests, since the generator behavior you rely on should match the release you run. Check that the ApplicationSet custom resource is registered with
kubectl get crd applicationsets.argoproj.io. The step is done when the CRD exists and the controller pod is running in the Argo CD namespace.Create the Git provider credential as a Secret
Your platform engineer creates a Kubernetes Secret in the Argo CD namespace that holds a token with read access to pull requests and repository contents for the target repository. Use a token scoped to the minimum repositories and permissions your provider allows, and confirm with your Git host which permissions its pull request API requires. Store the token only in the Secret, not in the ApplicationSet manifest or in Git. The check is that the Secret exists and that a test call with the token lists open pull requests for the repository.
Write the ApplicationSet with the pull request generator
Your platform engineer writes an ApplicationSet that uses the pullRequest generator, pointing at the Git provider, the repository and the Secret from the previous step. The template sets a generated namespace per pull request, usually built from the pull request number, and sets the target revision to the pull request head branch. Add a label filter where your provider supports it so that only pull requests with the agreed label produce environments. The check is that
kubectl applysucceeds and the controller logs show the generator polling the repository without authentication errors.Set the polling interval and webhook trigger
Decide whether the generator waits for its default requeue interval or whether your Git host sends webhooks. The default requeueAfterSeconds value is 30 minutes, so a team that expects environments to appear quickly will need webhooks for GitHub or GitLab. If you use webhooks, your platform engineer configures the ApplicationSet webhook server and exposes it through its own Ingress with TLS, then registers the webhook on the repository with a shared secret. The check is that the webhook delivery in the Git host shows a successful response code.
Confirm the webhook Ingress and access controls
Your network or platform team confirms that the webhook endpoint is reachable from the Git host and nowhere else that does not need it. Confirm that the shared secret is set on both sides and that requests without a valid signature are rejected. Review which network path the Ingress uses, since the webhook is an inbound route into a cluster that deploys code. The check is that a request with a bad signature is refused and a delivery with a valid signature is accepted.
Open a test pull request and confirm the Application
Your engineering team opens a test pull request in a non-production repository, or in a branch set aside for the test. Within the polling interval, or immediately if webhooks are configured, the generator should create an Application named after the pull request and deploy its target revision into the generated namespace. Check the Application status in the Argo CD UI or with
argocd app list, and confirm that the workload reaches a healthy state. The step is complete when the Application exists and syncs from the pull request branch.Close the test pull request and confirm removal
Your engineering team closes or merges the test pull request. The generator should stop producing that Application, and Argo CD should delete it along with its resources if the finalizer and prune behavior are configured as your team intends. Confirm that the Application and the generated namespace are gone, and that no orphaned resources remain in the cluster. Record the result so that the cleanup behavior is documented before the generator is used for real teams. The step is done when a clean list of Applications matches the set of open pull requests.
Polling versus webhooks: how fast previews appear and what it costs to run
The Pull Request generator checks the Git host on a timer by default. The requeueAfterSeconds setting defaults to 30 minutes, so a new pull request can wait up to half an hour before its preview Application appears. For many teams that delay is acceptable, and polling has the advantage of needing no inbound network path from the Git host into the cluster. If a reviewer expects the preview to exist within a few minutes of opening a pull request, the default will feel slow, and you will need to choose a faster trigger or shorten the interval. Shortening the interval raises the number of API calls the generator makes, so the two settings must be decided together.
For GitHub and GitLab, a webhook can make the generator run as soon as the Git host sends an event. That requires the ApplicationSet webhook server, which needs its own Ingress. This is the main cost of the faster path. You expose one more HTTP endpoint to the Git host, you must terminate TLS for it, and you must configure the shared secret that lets the server reject forged requests. Each of these is ongoing work for the platform team, not a one-time task, because certificates rotate, ingress controllers change, and the secret must be updated on both sides. Webhooks also reduce polling traffic, but they do not remove it entirely, and every webhook delivery still causes a generation run. Review the webhook server's exposure in the same way you review any other publicly reachable control plane component, and confirm the current configuration steps in the Pull Request generator guide before you build it.
Before choosing, answer four questions with your platform and security owners. How long can a reviewer wait for a preview? Which Git host do you use, and does it support webhook-triggered generation for your plan and version? How many open pull requests and repositories will each polling cycle scan, and how does that compare with the rate limits your Git provider enforces for the token the generator uses (for GitHub, GitHub's Actions limits documentation lists the hourly figures)? Who will rotate the webhook secret and maintain the Ingress? If the answers point to a short wait, a shared token with headroom, and a team that already runs internet-facing endpoints, webhooks are worth the added surface. Otherwise, a longer polling interval is the simpler and lower-risk choice.
Security risks when every pull request can deploy code into your cluster
A preview environment is a deployment triggered by someone who may not be trusted, so every pull request becomes an input to your cluster. The cards below cover the places where that input reaches Argo CD's repo-server, its credentials, its webhook endpoint and the privileges of the Applications it generates.
Untrusted code in the repo-server
The Argo CD security documentation notes that the repo-server runs Helm and Kustomize on repository content. A pull request from an untrusted fork can change chart values, Kustomize transformers or templates, so rendering runs attacker-influenced input inside Argo CD. Decide which repositories and branches may generate previews, and require review before a fork's pull request is rendered.
Out-of-tree file access
Helm and Kustomize can read files outside the application path if the manifests reference them, and that access is the risk the security documentation calls out. A preview branch could point at files that hold other teams' values or secrets in the same checkout. Confirm that each generated preview reads only its own path and that the repo-server cannot reach unrelated repositories.
Scope of the Git provider token
The Pull Request generator polls the Git provider with a token, and that token decides which pull requests Argo CD can see and comment on. A token with write access to every repository lets a preview reach beyond the intended project. Use a credential limited to the repositories that need previews, store it as a Kubernetes Secret, and rotate it on a schedule you set.
Webhook authentication
GitHub and GitLab webhooks can trigger generation sooner than polling, through an ApplicationSet webhook server exposed by its own Ingress. An unauthenticated or loosely checked endpoint lets outsiders force generation runs. Configure the provider's webhook secret, restrict the Ingress to the provider's source addresses where your network allows it, and test that a forged request is rejected.
Cluster privileges on generated Applications
Each preview becomes a generated Application that deploys into a destination cluster with whatever rights its project grants. If the project allows broad destinations or cluster-scoped resources, a pull request can create objects you never intended. Restrict preview projects to named namespaces, deny cluster-scoped resources, and review the project's destination and resource allow lists before enabling the generator.
Credential redaction in logs
Argo CD redacts cluster, Git and OAuth2 credentials from API responses and logs, according to its security documentation. That protection covers what Argo CD prints, not what a preview's own pods or scripts print. Ask teams not to echo secrets in preview hooks or manifests, and check controller and repo-server logs after a test run to confirm no token values appear.
Questions teams ask before building pull request previews
What drives the cost of building pull request previews with Argo CD?
The cost is mostly the engineering time to design the generator, register clusters, wire DNS and TLS, and test cleanup, plus the compute that each preview consumes. Argo CD itself is open source under the Apache License 2.0 with no paid edition from the project, so license cost is not the driver. The main cost factors are how many repositories and Git providers are involved, whether previews need their own namespace or cluster, how much data each preview needs, and how many pull requests are open at once. Ask for a quote that lists each of these as a separate line so you can see what is one-time setup and what recurs in operation.
How long does a working pull request preview setup take?
The duration depends on the scope agreed in writing before work starts, not on a fixed number. Timing is shaped by how many applications need previews, whether the Git host is GitHub, GitLab, Gitea, Bitbucket or Azure DevOps, whether webhooks are needed, and how much of the environment already exists, such as an Argo CD installation, an ingress controller and a wildcard DNS record. Ask the vendor or DeployOpen for a written timeline tied to the agreed deliverables, and confirm which of your existing systems the plan assumes are ready.
What access and infrastructure does the client need to provide?
Plan to provide four things before work starts:
- Git administrator rights or an app or token with permission to read pull requests and set up webhooks on the repositories in scope
- Cluster access for the Argo CD instance and the target clusters where previews will run
- DNS and TLS for preview hostnames, usually a wildcard record and certificate that you control
- An Ingress for the ApplicationSet webhook server if you want GitHub or GitLab events to trigger generation sooner than the default polling interval
Confirm who owns each item and how changes to DNS and certificates are approved in your organization.
Can an internal platform team build pull request previews without outside help?
Yes, a team with working knowledge of Kubernetes, Argo CD and their Git host can build this internally, and many do. The work that tends to take longer is less the generator syntax than the surrounding decisions: deciding which pull requests get previews, how label filters map to your branch and label conventions, how previews reach their hostnames, and how secrets and data for each preview are handled. If your team has not run ApplicationSets before, budget time to learn the generator model. A partner can be useful for a fixed-scope build and handover, and the written scope will show which parts your team would own afterward.
How does cleanup work when a pull request closes?
The Pull Request generator polls the Git host on a schedule and regenerates the set of Applications from the open pull requests that match your filters. When a pull request closes or stops matching, its Application is no longer generated, and the ApplicationSet removes it according to the policy you configured. Confirm how your ApplicationSet handles deletion, including whether the preview's namespace, persistent volumes and external resources are removed too, because Argo CD only deletes what it manages. Test the close path in a non-production cluster before relying on it.
Which Git provider limits matter for preview environments?
Check three things with your provider before designing the polling and webhook setup. First, the Pull Request generator supports GitHub, GitLab, Gitea, Bitbucket Server, Bitbucket Cloud and Azure DevOps, but label filters are documented only for GitHub, GitLab and Azure DevOps, while Bitbucket uses branch matching. Second, the default requeue interval is 30 minutes, and webhooks for GitHub and GitLab can trigger generation sooner. Third, GitHub publishes its REST API rate limits, which are 5,000 requests per hour for personal access tokens and 15,000 per hour for GitHub Enterprise Cloud apps, so a busy repository with frequent polling should be checked against the limit that applies to your token type. Confirm your own plan and limits, since pricing for GitHub is $4 per user per month for Team and $21 for Enterprise according to GitHub's pricing page, and GitLab Premium is listed at $29 per user per month billed annually, but your negotiated rates may differ.
Do pull request previews expose data or secrets, and how is that controlled?
Previews can expose risk because they run code from pull requests, which may come from contributors you do not fully trust, and Argo CD's repo-server runs Helm and Kustomize on repository content. Limit which pull requests trigger previews, keep previews in isolated namespaces with restricted permissions, and avoid loading production secrets into them. Argo CD authenticates API requests with JSON Web Tokens and redacts credentials from responses and logs, but it does not decide what a preview may access. Review your project boundaries, cluster privileges and the webhook endpoint exposure with your security team before enabling previews on repositories that handle sensitive data.
Limits to confirm in your environment before you rely on previews
The Pull Request generator works well only when your Git provider, plan, label behavior, cluster topology and cluster capacity match what the guide assumes. Each card below names one limit to check and what to ask your team or your provider before previews become part of your review process.
Git provider version and plan
The generator supports GitHub, GitLab, Gitea, Bitbucket Server, Bitbucket Cloud and Azure DevOps, but the exact API behavior depends on the version and plan you run. Confirm the provider edition for each repository, whether it is cloud or self-managed, and whether your API token scopes allow reading pull requests. Ask who owns token rotation, because a revoked token silently stops preview creation.
Label filter behavior by provider
Label filters are documented for GitHub, GitLab and Azure DevOps, so a label that works on one host may not behave the same on another. Test the filter on a pull request you control before you rely on it to limit which pull requests get environments. Confirm that your labels are applied consistently by reviewers, since a missing label means no preview is created.
Bitbucket branch matching constraints
Bitbucket does not use label filters in the same way, so previews on Bitbucket Server or Bitbucket Cloud depend on branch matching. Write down which source branch patterns create previews, and check that teams do not reuse branch names across repositories. Ask whether your branch naming standard can express the filter you need without catching unrelated work.
IPv6-only cluster exclusion
The Argo CD high availability documentation states that IPv6-only clusters are not supported. If your preview target is an IPv6-only cluster, the generated Applications may not deploy as expected even though the generator runs. Confirm the address family of every destination cluster before you pick it for previews, and treat a dual-stack or IPv4 cluster as a prerequisite rather than an assumption.
Quota and namespace limits per preview
Each open pull request can create its own namespace, workloads and services, so the total load grows with the number of open pull requests. Set a ResourceQuota and LimitRange per preview namespace, and confirm how many concurrent previews your cluster can hold. Ask your platform team who approves the ceiling and what happens when a team opens more pull requests than the cluster can carry.
Data handling for preview databases
A preview that connects to a database may copy production data, retain it after the pull request closes, or expose it to people who can open a pull request. Decide whether previews use seeded or synthetic data, who can reach preview endpoints, and how long any database or volume lives after cleanup. Confirm this with your data owner and security team before enabling previews on any system that handles regulated data.
What changes for developers, reviewers and platform owners
Developers get a running link for every pull request. Once the ApplicationSet Pull Request generator is in place, opening a pull request produces an Argo CD Application that deploys that branch to its own namespace or cluster, so the developer no longer has to wait for a shared staging environment to be free. The developer's main new responsibility is keeping the change self-contained: the preview must start from the branch alone, which means any database seed data, feature flags and external endpoints the branch needs have to be declared in the repository or in the template rather than assumed to exist in a shared environment. Ask the team which preview dependencies are still manual today, because those are the first things that will fail in a generated environment.
Reviewers test a running build instead of reading a diff. The reviewer opens the preview link, exercises the change and checks it against the pull request description, which is only useful if the preview is reachable by the people who need it. Reviewers outside the corporate network, such as external contractors or auditors, will need an access path that your ingress and identity setup allows, and that decision belongs with the SSO and project boundary design rather than with the generator. Confirm with your security team who may open a preview, and whether preview URLs are public, behind login or limited to a network segment, before the first pull request is opened.
Platform owners carry the ApplicationSet, the template guardrails and the cleanup. The platform team owns the generator configuration, the Application template, the label filter that decides which pull requests qualify, and the polling or webhook setup that controls how quickly new previews appear. They also own the rule that removes a preview when its pull request closes, and they decide what quota or cluster capacity a preview may consume. Each of these choices depends on how clusters are registered and which Argo CD projects and RBAC roles can create Applications, so settle those multi-cluster and access decisions first and treat the preview design as one consumer of them.
How DeployOpen scopes, delivers and supports Argo CD preview environments
DeployOpen scopes preview environments per pull request as a fixed-scope piece of work inside your own clusters and Git host. We agree the provider, label rules, cleanup behavior and handover in writing before any build starts, then support the result as a retainer if you want it.
How we scope
- Confirm which Git provider hosts your repositories, since the generator supports GitHub, GitLab, Gitea, Bitbucket Server, Bitbucket Cloud and Azure DevOps.
- Define label filters for GitHub, GitLab or Azure DevOps, or the branch matching rules that apply to Bitbucket.
- Agree in writing which clusters, namespaces, hostnames and data sets preview environments may use, and what each one costs to run.
How we build
- Configure the ApplicationSet with the Pull Request generator and set the polling interval, which defaults to 30 minutes, against your team's needs.
- Where webhooks are in scope, deploy the ApplicationSet webhook server with its own Ingress and test that pull request events trigger generation.
- Build and test cleanup so environments are removed when the pull request closes, and verify that no orphaned Applications or namespaces remain.
How we hand over
- Deliver the ApplicationSet manifests, RBAC settings and webhook configuration as code in a repository your team owns.
- Document the generator settings, label conventions, cleanup checks and the steps to rotate Git provider tokens.
- Walk your platform and development leads through a test pull request end to end and record the results in the handover pack.
How we support
- Offer ongoing support, upgrades and monitoring of preview environments as a retainer, with the scope confirmed in writing.
- Plan Argo CD upgrades around the supported minor release cadence and the patch releases your version receives.
- Review generator behavior, API rate limits and cleanup failures with your team at agreed intervals, and adjust the configuration as needed.

