How it works🔗
This page describes how argocd-diff-preview works under the hood.

The tool follows a simple but powerful approach: spin up a real Argo CD instance, let it render your manifests, and compare the results between branches. This ensures the diff is 100% accurate - exactly what Argo CD would produce in your real cluster.
When you run the tool, it follows these steps:
Step 1: Fetch Applications🔗
The tool collects all resources from the base-branch and target-branch folders for all YAML files containing:
kind: Applicationkind: ApplicationSet
Step 2: Select/Filter Applications🔗
Before processing, the tool filters which applications to render. By default, all applications are rendered, but you can limit this using several strategies:
| Strategy | How it works |
|---|---|
| Watch patterns | Add argocd-diff-preview/watch-pattern annotation to only render apps when specific files change |
| Ignore annotation | Add argocd-diff-preview/ignore: "true" to skip specific applications entirely |
| Label selectors | Use --selector "team=platform" to filter by Kubernetes labels |
| File path regex | Use --file-regex="team-a/" to filter by the application's file location |
This is especially useful in large monorepos where rendering all applications on every PR would be slow.
→ Full documentation on application selection
Early exit if no applications selected
If no applications are selected after filtering, the tool stops here and outputs an empty diff. This avoids spinning up a cluster unnecessarily.
Step 3: Patch Applications🔗
For each Application or ApplicationSet found, it applies the following modifications:
| Modification | Why |
|---|---|
Set metadata.namespace to argocd-diff-preview |
So Argo CD can find and manage the applications |
Remove spec.syncPolicy |
Prevents Argo CD from actually syncing resources to the cluster |
Set spec.project to default |
The ephemeral Argo CD only has the default project configured |
Set spec.destination.server to https://kubernetes.default.svc |
Points to the local cluster (the actual destination doesn't matter since we're only rendering, not syncing) |
Set spec.source.targetRevision to the branch name |
So Argo CD renders manifests from the correct branch |
Set spec.sources[*].targetRevision to the branch name |
Same as above, but for multi-source applications |
Set spec.generators[*].git.revision to the branch name |
For ApplicationSets using Git generators (including nested Matrix/Merge generators) |
Steps 4-6 are skipped if --create-cluster false is provided
Step 4: Start local cluster🔗
The tool creates a local ephemeral Kubernetes cluster using one of the supported local cluster tools:
- Kind (default)
- Minikube
- k3d
argocd-diff-preview practically just runs:
Step 5: Install Argo CD🔗
Argo CD is installed using the official Argo CD Helm Chart. By default, the latest version is installed, but you can specify a version with --argocd-chart-version.
You can customize the installation by mounting a values.yaml file. This is useful for:
- Enabling Config Management Plugins (CMPs)
- Configuring Kustomize build options
- Any other Argo CD Helm chart customization
See Custom Argo CD Installation for details.
argocd-diff-preview practically just runs:
Step 6: Apply credentials🔗
If your repository is private, you need to provide the tool with the necessary credentials.
You can do this by mounting a /secrets folder:
Example: GitHub Actions workflow with secrets
- name: Prepare secrets
run: |
mkdir secrets
cat > secrets/secret.yaml << "EOF"
apiVersion: v1
kind: Secret
metadata:
name: private-repo
namespace: argocd
labels:
argocd.argoproj.io/secret-type: repo-creds
stringData:
url: https://github.com/${{ github.repository }}
password: ${{ secrets.GITHUB_TOKEN }} ⬅️ Short-lived GitHub Token
username: not-used
EOF
- name: Generate Diff
run: |
docker run \
--network=host \
-v /var/run/docker.sock:/var/run/docker.sock \
-v $(pwd)/main:/base-branch \
-v $(pwd)/pull-request:/target-branch \
-v $(pwd)/output:/output \
-v $(pwd)/secrets:/secrets \ ⬅️ Mount the secrets folder
-e TARGET_BRANCH=refs/pull/${{ github.event.number }}/merge \
-e REPO=${{ github.repository }} \
dagandersen/argocd-diff-preview:v0.1.20
All resources in the /secrets folder are applied to the cluster. The relevant secrets are typically included in the /secrets folder:
- Repository credentials - For accessing private Git repositories
- Helm chart credentials - For private Helm registries (including OCI)
- Cluster secrets - For ApplicationSets using the Cluster generator
These secrets use the standard Argo CD secret format.
argocd-diff-preview practically just runs:
Step 7: Generate Applications from ApplicationSets🔗
For each ApplicationSet found, it generates the applications using the Argo CD CLI:
This returns a list of applications.
The newly generated applications also go through Step 2 and Step 3 (filtering and patching).
Step 8: Apply applications to the cluster🔗
The patched applications are applied to the cluster.
argocd-diff-preview practically just runs:
At this point, Argo CD starts processing each application - rendering the applications.
Step 9: Wait for Argo CD to render🔗
The tool will repeatedly check the status of each application and extract the rendered manifests as they become ready.
The tool will poll the applications until they're ready or the timeout is reached (default: 180 seconds).
It practically just waits for the Application to look like this:
Step 10: Extract rendered manifests🔗
Once applications are ready, the tool extracts the rendered manifests using the Argo CD CLI:
This returns the exact YAML generated by the applications - fully rendered with all Helm values substituted and Kustomize patches applied.
Step 11: Generate the diff🔗
The tool compares the two sets of manifests and generates a diff. The comparison is done per-application, showing:
- Added applications - New in target branch
- Removed applications - Deleted in target branch
- Modified applications - Changed between branches
- Unchanged applications - No differences (not shown in output)
The diff respects the --diff-ignore option to filter out noisy changes. Documentation: Ignore specific lines in the diff preview
Step 12: Output the results🔗
The tool writes several files to the output folder (./output/ by default):
| File | Description |
|---|---|
./output/diff.md |
Markdown diff - ready to post as a PR comment |
./output/diff.html |
HTML diff - visual side-by-side comparison |
./output/base-branch.yaml |
Single manifest with all rendered resources from base branch |
./output/target-branch.yaml |
Single manifest with all rendered resources from target branch |
./output/base/<app-name>.yaml |
Individual manifests for each app rendered from base branch |
./output/target/<app-name>.yaml |
Individual manifests for each app rendered from target branch |
The Markdown output is designed to be posted directly to your pull request using gh pr comment or equivalent.