<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Dag Andersen</title>
    <description>The latest articles on DEV Community by Dag Andersen (@dag-andersen).</description>
    <link>https://dev.to/dag-andersen</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1409654%2F91dfa29d-aa23-47fa-817f-ee85b5b4595a.jpg</url>
      <title>DEV Community: Dag Andersen</title>
      <link>https://dev.to/dag-andersen</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dag-andersen"/>
    <language>en</language>
    <item>
      <title>Argo CD: Previewing Pull Request changes in SECONDS! 🥵⚡️⏰</title>
      <dc:creator>Dag Andersen</dc:creator>
      <pubDate>Thu, 16 Oct 2025 15:05:49 +0000</pubDate>
      <link>https://dev.to/dag-andersen/argo-cd-previewing-pull-requests-changes-in-seconds-241g</link>
      <guid>https://dev.to/dag-andersen/argo-cd-previewing-pull-requests-changes-in-seconds-241g</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;: You can now render previews of your PRs by using a cluster with Argo CD pre-installed instead of spinning up a new one each run. This results in very short preview times while maintaining accuracy. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is a continuation of my first blog post: &lt;a href="https://dev.to/dag-andersen/rendering-the-true-argo-cd-diff-on-your-prs-10bk"&gt;Rendering the TRUE Argo CD diff on your PRs&lt;/a&gt;. That article addresses a critical challenge in GitOps workflows: visualizing the actual impact of configuration changes when using templating tools like Helm and Kustomize.&lt;/p&gt;

&lt;p&gt;The article shows how you can render changes to your manifests/Argo CD configuration directly on your pull requests using &lt;a href="https://github.com/dag-andersen/argocd-diff-preview" rel="noopener noreferrer"&gt;&lt;code&gt;argocd-diff-preview&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In short, it shows how you can transform a pull request like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5uj1woylw7979u1s50t9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5uj1woylw7979u1s50t9.png" alt="" width="800" height="460"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;and turn it into a preview like this: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx2ia44gwlsogt1s5vgjn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx2ia44gwlsogt1s5vgjn.png" alt="" width="800" height="970"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Here are some examples:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3 Example Pull Requests:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/dag-andersen/argocd-diff-preview/pull/16" rel="noopener noreferrer"&gt;Helm Example | Internal Chart&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/dag-andersen/argocd-diff-preview/pull/15" rel="noopener noreferrer"&gt;Helm example | External Chart: Nginx&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/dag-andersen/argocd-diff-preview/pull/12" rel="noopener noreferrer"&gt;Kustomize Example&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Three Approaches to Preview Generation
&lt;/h2&gt;

&lt;p&gt;Since its introduction in 2024, the tool now supports more ways of running it, so you can optimize it for your use case!&lt;/p&gt;

&lt;p&gt;All three approaches are perfectly valid and you can choose the one that best fits your needs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Approach 1: Ephemeral Clusters (Original)
&lt;/h3&gt;

&lt;p&gt;This is the simplest solution, but also the slowest...&lt;/p&gt;

&lt;p&gt;The original solution spins up ephemeral Kubernetes clusters inside your CI/CD pipeline, letting Argo CD itself render the manifests. This ensures maximum accuracy since the same engine that will deploy your changes generates the preview.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffg16gqjm0488hxl4x8ov.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffg16gqjm0488hxl4x8ov.png" alt="" width="800" height="245"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create an ephemeral Kubernetes cluster (kind, k3d, or minikube)&lt;/li&gt;
&lt;li&gt;Install Argo CD from scratch&lt;/li&gt;
&lt;li&gt;Apply your applications (without syncing them)&lt;/li&gt;
&lt;li&gt;Wait for Argo CD to render the Applications in memory&lt;/li&gt;
&lt;li&gt;Extract the manifests from the cluster&lt;/li&gt;
&lt;li&gt;Generate the diff between the two sets of rendered manifests&lt;/li&gt;
&lt;li&gt;Post the diff to the pull request&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is the approach described in detail in the &lt;a href="https://dev.to/dag-andersen/rendering-the-true-argo-cd-diff-on-your-prs-10bk"&gt;first blog post&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why this approach is superior to alternative tools:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;True accuracy&lt;/strong&gt;: Uses Argo CD itself rather than tools that try to mimic its rendering logic&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No infrastructure access required&lt;/strong&gt;: Can work without credentials for your production Argo CD instance&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complete isolation&lt;/strong&gt;: Can run in complete isolation from your production systems&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, this approach has one significant limitation: &lt;strong&gt;Speed&lt;/strong&gt;. Creating a cluster and installing Argo CD takes ~60 seconds every time, making even simple configuration changes take 80+ seconds to preview.&lt;/p&gt;

&lt;p&gt;This leads us to the next approach to running &lt;code&gt;argocd-diff-preview&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Trade-offs:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Zero setup&lt;/li&gt;
&lt;li&gt;✅ Complete isolation&lt;/li&gt;
&lt;li&gt;✅ Works with any CI/CD (even works on your local machine)&lt;/li&gt;
&lt;li&gt;❌ Slow (~60 second overhead per run)&lt;/li&gt;
&lt;li&gt;❌ Resource-intensive (creates a new cluster for each run)&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Approach 2: Cluster with Argo CD pre-installed
&lt;/h3&gt;

&lt;p&gt;Instead of creating a new ephemeral cluster each time, &lt;code&gt;argocd-diff-preview&lt;/code&gt; can now connect to a cluster with Argo CD already installed. This reduces preview times from minutes to seconds! 🤯&lt;/p&gt;

&lt;p&gt;See it as a cluster with Argo CD pre-installed that is on standby and ready to render your manifests. Remember, the cluster only runs Argo CD and not the resources generated by the Applications. So it is fairly lightweight.&lt;/p&gt;

&lt;p&gt;We do not recommend using your &lt;em&gt;normal&lt;/em&gt; Argo CD instance for this. Instead, create a dedicated cluster or Argo CD instance for diff previews.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzhyupnhw2ese3iz8mmcb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzhyupnhw2ese3iz8mmcb.png" alt="" width="800" height="243"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Connect to the cluster&lt;/li&gt;
&lt;li&gt;Apply your applications (without syncing them)&lt;/li&gt;
&lt;li&gt;Wait for Argo CD to render the Applications in memory.&lt;/li&gt;
&lt;li&gt;Extract the manifests from the cluster&lt;/li&gt;
&lt;li&gt;Generate the diff between the two sets of rendered manifests&lt;/li&gt;
&lt;li&gt;Post the diff to the pull request&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Quick Demo:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create cluster and install Argo CD (one-time setup)&lt;/span&gt;
kind create cluster
helm repo add argo https://argoproj.github.io/argo-helm
helm &lt;span class="nb"&gt;install &lt;/span&gt;argo-cd argo/argo-cd &lt;span class="nt"&gt;--version&lt;/span&gt; 8.0.3 &lt;span class="nt"&gt;--create-namespace&lt;/span&gt; &lt;span class="nt"&gt;--namespace&lt;/span&gt; argocd-diff-preview

&lt;span class="c"&gt;# Wait for Argo CD to be ready&lt;/span&gt;
kubectl &lt;span class="nb"&gt;wait&lt;/span&gt; &lt;span class="nt"&gt;--for&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;condition&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ready pod &lt;span class="nt"&gt;-l&lt;/span&gt; app.kubernetes.io/name&lt;span class="o"&gt;=&lt;/span&gt;argocd-server &lt;span class="nt"&gt;-n&lt;/span&gt; argocd-diff-preview

&lt;span class="c"&gt;# Clone each branch from the PR into subfolders&lt;/span&gt;
git clone https://github.com/dag-andersen/argocd-diff-preview base-branch &lt;span class="nt"&gt;--depth&lt;/span&gt; 1 &lt;span class="nt"&gt;-q&lt;/span&gt; 
git clone https://github.com/dag-andersen/argocd-diff-preview target-branch &lt;span class="nt"&gt;--depth&lt;/span&gt; 1 &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="nt"&gt;-b&lt;/span&gt; helm-example-3

&lt;span class="c"&gt;# Run the tool (connects to the kind cluster)&lt;/span&gt;
docker run &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--network&lt;/span&gt; host &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; ~/.kube:/root/.kube &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; /var/run/docker.sock:/var/run/docker.sock &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;/output:/output &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;/base-branch:/base-branch &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;/target-branch:/target-branch &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;TARGET_BRANCH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;helm-example-3 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;REPO&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;dag-andersen/argocd-diff-preview &lt;span class="se"&gt;\&lt;/span&gt;
  dagandersen/argocd-diff-preview:v0.1.18 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--argocd-namespace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;argocd-diff-preview &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--create-cluster&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Concurrent Runs: Multiple PRs, No Conflicts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Each run uses a unique identifier, so multiple PRs can run without collisions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Network &amp;amp; Security:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The main downside here is that you need access to the Kubernetes API from your GitHub/GitLab hosted pipeline. Some organizations will see this as a no-go... which leads us to the next way of running &lt;code&gt;argocd-diff-preview&lt;/code&gt;... &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Trade-offs:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Fast execution (eliminates ~60s overhead)&lt;/li&gt;
&lt;li&gt;✅ Utilizes Argo CD caching from previous runs&lt;/li&gt;
&lt;li&gt;❌ Infrastructure setup required (set up a cluster with Argo CD beforehand) &lt;/li&gt;
&lt;li&gt;❌ Cluster credentials in CI/CD pipeline&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Approach 3: Cluster with Argo CD pre-installed + Self-Hosted Runner
&lt;/h3&gt;

&lt;p&gt;Running &lt;code&gt;argocd-diff-preview&lt;/code&gt; on a self-hosted runner inside a cluster that has Argo CD pre-installed combines maximum performance with enhanced security. This approach eliminates both cluster creation overhead and the need to store cluster credentials in your CI/CD pipeline.&lt;/p&gt;

&lt;p&gt;Instead of creating a temporary cluster for each diff preview, your self-hosted GitHub Actions runner connects directly to a dedicated Argo CD instance running in the same cluster as the hosted runners. This offers fast execution (no cluster creation overhead) and enhanced network and credential security.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6nomrkuvrogliedld30d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6nomrkuvrogliedld30d.png" alt="" width="800" height="471"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Setup Guide:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Install Action Runner Controller (ARC)&lt;/strong&gt; in your cluster alongside the dedicated Argo CD instance in the namespace &lt;code&gt;argocd-diff-preview&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The runner uses a service account&lt;/strong&gt; to connect to the host cluster and access the Argo CD instance&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The tool runs exactly as before&lt;/strong&gt;, but without any credential management complexity and without creating an ephemeral cluster&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: This setup is more complex than the previous two approaches. For complete setup instructions, see the &lt;a href="https://dag-andersen.github.io/argocd-diff-preview/reusing-clusters/self-hosted-gh-runner/" rel="noopener noreferrer"&gt;self-hosted runner guide&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Trade-offs:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Fast execution (eliminates ~60s overhead)&lt;/li&gt;
&lt;li&gt;✅ Network isolation (No need to expose your cluster to the internet)&lt;/li&gt;
&lt;li&gt;✅ No cluster credentials in CI/CD pipeline because you are using a service account from within the cluster and Argo CD already has all the credentials it needs&lt;/li&gt;
&lt;li&gt;❌ Most complex setup (requires self-hosted runners + dedicated Argo CD)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Optimizing for Large Repositories
&lt;/h2&gt;

&lt;p&gt;Even when using a cluster with Argo CD pre-installed, repositories with hundreds of applications can take 1+ minutes to render. The solution is selective rendering using annotations.&lt;/p&gt;

&lt;p&gt;The most powerful optimization is the &lt;code&gt;argocd-diff-preview/watch-pattern&lt;/code&gt; annotation. This tells the tool exactly which files each application cares about. An application will only be rendered if its watch patterns match any of the changed files in the PR.&lt;/p&gt;

&lt;h3&gt;
  
  
  Smart Application Selection
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Setup Guide:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add the &lt;code&gt;argocd-diff-preview/watch-pattern&lt;/code&gt; annotation to your Applications and ApplicationSets&lt;/li&gt;
&lt;li&gt;Enable automatic file change detection. Use the following flags:

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;--auto-detect-files-changed=true&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;&lt;code&gt;--watch-if-no-watch-pattern-found=true&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use the &lt;code&gt;argocd-diff-preview/watch-pattern&lt;/code&gt; annotation to tell the tool exactly which files each application cares about:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;argoproj.io/v1alpha1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Application&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-app&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;argocd&lt;/span&gt;
  &lt;span class="na"&gt;annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;argocd-diff-preview/watch-pattern&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;apps/my-app/.*,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;shared/values.yaml"&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/my-app&lt;/span&gt;
    &lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This application will only render if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Any file in the &lt;code&gt;apps/my-app/&lt;/code&gt; directory changes&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;shared/values.yaml&lt;/code&gt; file changes&lt;/li&gt;
&lt;li&gt;The application's own manifest file changes (automatic)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More information about the &lt;code&gt;watch-pattern&lt;/code&gt; annotation can be found in the &lt;a href="https://dag-andersen.github.io/argocd-diff-preview/application-selection/" rel="noopener noreferrer"&gt;application-selection&lt;/a&gt; documentation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Other application selection methods:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ignore applications&lt;/strong&gt;: &lt;code&gt;argocd-diff-preview/ignore: "true"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Filter by labels&lt;/strong&gt;: &lt;code&gt;--selector "team=frontend"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Filter by path&lt;/strong&gt;: &lt;code&gt;--file-regex="/team-a/"&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Performance impact&lt;/strong&gt;: Instead of rendering 100+ applications (60+ seconds), render only 6-10 relevant applications (~10 seconds).&lt;/p&gt;

&lt;p&gt;For complete details, see the &lt;a href="https://dag-andersen.github.io/argocd-diff-preview/application-selection/" rel="noopener noreferrer"&gt;application-selection documentation&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Comparison: Which Approach to Choose?
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Approach&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;th&gt;Pros&lt;/th&gt;
&lt;th&gt;Cons&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ephemeral&lt;br&gt;clusters&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Getting started, Full isolation&lt;/td&gt;
&lt;td&gt;• Simple setup&lt;br&gt;• Complete isolation&lt;/td&gt;
&lt;td&gt;• Slow (~60s overhead)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cluster with&lt;br&gt;Argo CD&lt;br&gt;pre-installed&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Teams prioritizing speed&lt;/td&gt;
&lt;td&gt;• Fast&lt;br&gt;• Leverages Argo CD caching&lt;/td&gt;
&lt;td&gt;• Requires dedicated Argo CD setup&lt;br&gt;• Need cluster credentials in CI/CD&lt;br&gt;• Infrastructure maintenance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cluster with&lt;br&gt;Argo CD&lt;br&gt;pre-installed + self-hosted runner&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Teams prioritizing speed AND network security&lt;/td&gt;
&lt;td&gt;• Fast + secure&lt;br&gt;• Leverages Argo CD caching&lt;br&gt;• No credentials in CI/CD&lt;/td&gt;
&lt;td&gt;• Most complex setup&lt;br&gt; • Requires dedicated Argo CD and self-hosted runner setup&lt;br&gt;• Infrastructure maintenance&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Real-World Results
&lt;/h2&gt;

&lt;p&gt;At &lt;a href="https://www.egmont.com" rel="noopener noreferrer"&gt;Egmont&lt;/a&gt;, we use the "&lt;em&gt;Cluster with Argo CD pre-installed + self-hosted runner&lt;/em&gt;" approach with a repository containing 600+ applications. Combined with smart application selection, we achieve preview times under 10 seconds - a 20x improvement over the original "&lt;em&gt;ephemeral cluster&lt;/em&gt;" approach.&lt;/p&gt;

&lt;p&gt;Each pull request preview includes a &lt;code&gt;stats&lt;/code&gt; section at the bottom.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm4hn4g2pmykx4bmu5vda.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm4hn4g2pmykx4bmu5vda.png" alt="stats section in preview" width="800" height="363"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The key is combining two optimizations:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Use a cluster with Argo CD pre-installed&lt;/strong&gt; to eliminate cluster creation overhead&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Select only affected applications&lt;/strong&gt; using watch patterns to minimize rendering scope&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This approach maintains the accuracy that makes &lt;code&gt;argocd-diff-preview&lt;/code&gt; superior to alternatives while delivering the preview in seconds.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The evolution of &lt;code&gt;argocd-diff-preview&lt;/code&gt; proves you don't have to choose between accuracy and speed. What started as an accurate - but slow - solution has matured into a flexible tool that adapts to your team's needs - whether you prioritize &lt;em&gt;simplicity&lt;/em&gt;, &lt;em&gt;speed&lt;/em&gt;, or &lt;em&gt;security&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Throughout this journey, one principle has remained constant: &lt;strong&gt;use Argo CD itself to render manifests&lt;/strong&gt;. This ensures your previews perfectly match what will actually deploy. What's new is the speed at which this happens. By using a cluster with Argo CD pre-installed and intelligently selecting applications, we've lower preview times from minutes to seconds! ⏰⚡️&lt;/p&gt;

&lt;p&gt;Each approach presented in this blog post has its own pros and cons. You should choose the one that best fits your needs.&lt;/p&gt;

&lt;p&gt;I suggest that you begin with the "&lt;em&gt;ephemeral cluster&lt;/em&gt;" approach to get familiar with the tool. As your confidence grows and speed becomes a priority, you can consider if you should switch to a faster setup using a cluster with Argo CD pre-installed. Combine this with well-placed &lt;code&gt;argocd-diff-preview/watch-pattern&lt;/code&gt; annotations and you can achieve preview times under 10 seconds while maintaining the same accuracy you started with, even at scale.&lt;/p&gt;

&lt;p&gt;The result? Preview rendering in under 10 seconds 🎉&lt;/p&gt;




&lt;p&gt;For detailed setup instructions, check out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dag-andersen.github.io/argocd-diff-preview/reusing-clusters/connecting/" rel="noopener noreferrer"&gt;Connecting to an already running cluster&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dag-andersen.github.io/argocd-diff-preview/getting-started/self-hosted-gh-runner/" rel="noopener noreferrer"&gt;Self-Hosted GitHub Actions Runners on Kubernetes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dag-andersen.github.io/argocd-diff-preview/application-selection/" rel="noopener noreferrer"&gt;Application Selection&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>kubernetes</category>
      <category>devops</category>
      <category>git</category>
      <category>argocd</category>
    </item>
    <item>
      <title>Rendering the TRUE Argo CD diff on your PRs</title>
      <dc:creator>Dag Andersen</dc:creator>
      <pubDate>Thu, 23 May 2024 10:33:41 +0000</pubDate>
      <link>https://dev.to/dag-andersen/rendering-the-true-argo-cd-diff-on-your-prs-10bk</link>
      <guid>https://dev.to/dag-andersen/rendering-the-true-argo-cd-diff-on-your-prs-10bk</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;TL;DR — The safest way to make changes to your Helm Charts and Kustomize Overlays is to let Argo CD render them for you. This can be done by spinning up an ephemeral cluster in your automated pipelines. This article presents a tool (&lt;a href="https://github.com/dag-andersen/argocd-diff-preview" rel="noopener noreferrer"&gt;&lt;code&gt;argocd-diff-preview&lt;/code&gt;&lt;/a&gt;) for rendering manifest changes on pull requests. The rendered output is similar to what Atlantis creates for Terraform.&lt;/p&gt;

&lt;p&gt;There’s now a &lt;em&gt;PART 2&lt;/em&gt; of this article with more advanced use cases: &lt;a href="https://dev.to/dag-andersen/argo-cd-previewing-pull-requests-changes-in-seconds-241g"&gt;Argo CD: Previewing Pull Request changes in SECONDS! 🥵⚡️⏰&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Problem
&lt;/h2&gt;

&lt;p&gt;In the Kubernetes world, we often use templating tools like Kustomize and Helm to generate our Kubernetes manifests. These tools make maintaining and streamlining configuration easier across applications and environments. However, they also make it harder to visualize the application's actual configuration in the cluster.&lt;/p&gt;

&lt;p&gt;Mentally parsing Helm templates and Kustomize patches is hard without rendering the actual output. Thus, making mistakes while modifying an application's configuration is relatively easy.&lt;/p&gt;

&lt;p&gt;In the field of GitOps and infrastructure as code, all configurations are checked into Git and modified through PRs. The code changes in the PR are reviewed by a human, who needs to understand the changes made to the configuration. This is hard when the configuration is generated through templating tools like Kustomize and Helm.&lt;/p&gt;

&lt;p&gt;If you are interested in a more detailed walkthrough for this problem, I recommend watching &lt;a href="https://www.linkedin.com/in/nicholas-morey/" rel="noopener noreferrer"&gt;&lt;em&gt;Nicholas Morey&lt;/em&gt;&lt;/a&gt;'s talk at KubeCon 2024: &lt;a href="https://www.youtube.com/watch?v=TonN-369Qfo&amp;amp;ab_channel=CNCF%5BCloudNativeComputingFoundation%5D" rel="noopener noreferrer"&gt;"The Rendered Manifests Pattern: Reveal Your True Desired State"&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This article introduces the tool &lt;a href="https://github.com/dag-andersen/argocd-diff-preview" rel="noopener noreferrer"&gt;&lt;code&gt;argocd-diff-preview&lt;/code&gt;&lt;/a&gt; that solves this problem by rendering manifest changes directly on pull requests.&lt;/p&gt;

&lt;p&gt;... but first, let's go through two simple examples where not rendering manifests can result in misconfiguration:&lt;/p&gt;

&lt;h4&gt;
  
  
  Helm misconfiguration example
&lt;/h4&gt;

&lt;p&gt;Here we see an example of a developer trying to override the replica count on an Argo CD application:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flu0215gbohowgvl4jeo6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flu0215gbohowgvl4jeo6.png" alt="helm misconfiguration example" width="800" height="506"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This PR may look correct, but as a reviewer, you do not know if the value specified in the Helm Chart is named &lt;code&gt;replicas:&lt;/code&gt; or &lt;code&gt;replicaCount:&lt;/code&gt;. The code change has no effect if the value name is incorrect. Without rendering the Helm templates, the likelihood of these errors going to production is high.&lt;/p&gt;

&lt;h4&gt;
  
  
  Kustomize misconfiguration example
&lt;/h4&gt;

&lt;p&gt;Here we see an example of a developer trying to set the replica count for both staging and production: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9i715pktjvpgh66rtzzi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9i715pktjvpgh66rtzzi.png" alt="kustomize misconfiguration example" width="800" height="576"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Again, this PR may look correct because the change happens in a base folder, so the change applies to all overlays (production and staging). But as a reviewer, you do not know if this value is overridden later down the chain of overlays.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;~/someApp&lt;/span&gt;
&lt;span class="s"&gt;├── base&lt;/span&gt;
&lt;span class="s"&gt;│   ├── deployment.yaml        ⬅️ File changed in Pull Request&lt;/span&gt;
&lt;span class="s"&gt;│   ├── kustomization.yaml&lt;/span&gt;
&lt;span class="s"&gt;│   └── service.yaml&lt;/span&gt;
&lt;span class="s"&gt;└── overlays&lt;/span&gt;
    &lt;span class="s"&gt;├── staging&lt;/span&gt;
    &lt;span class="s"&gt;│   ├── cpu_count.yaml&lt;/span&gt;
    &lt;span class="s"&gt;│   ├── kustomization.yaml&lt;/span&gt;
    &lt;span class="s"&gt;└── production&lt;/span&gt;
        &lt;span class="s"&gt;├── cpu_count.yaml&lt;/span&gt;
        &lt;span class="s"&gt;├── kustomization.yaml&lt;/span&gt;
        &lt;span class="s"&gt;└── replica_count.yaml ⬅️ replicaCount overwritten here&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This unintended result might not have been caught without rendering the final output for staging and production.&lt;/p&gt;

&lt;h3&gt;
  
  
  Other solutions to the problem
&lt;/h3&gt;

&lt;p&gt;This problem has been pointed out many times in articles and tech talks about GitOps and infrastructure as code.&lt;/p&gt;

&lt;p&gt;If you are interested in different approaches to solving the problem and their limitations, check out &lt;a href="https://www.linkedin.com/in/kostiskapelonis/" rel="noopener noreferrer"&gt;&lt;em&gt;Kostis Kapelonis&lt;/em&gt;&lt;/a&gt;'s &lt;a href="https://codefresh.io/blog/argo-cd-preview-diff/" rel="noopener noreferrer"&gt;article&lt;/a&gt; on the topic.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;argocd-diff-preview&lt;/code&gt; is not the first tool that tries to tackle this problem. Other open-source repos include &lt;a href="https://github.com/quizlet/argocd-diff-action" rel="noopener noreferrer"&gt;quizlet/argocd-diff-action&lt;/a&gt; and &lt;a href="https://github.com/zapier/kubechecks" rel="noopener noreferrer"&gt;zapier/kubechecks&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/quizlet/argocd-diff-action" rel="noopener noreferrer"&gt;quizlet/argocd-diff-action&lt;/a&gt; generates an Argo CD diff between the current PR and the current state of the cluster using the &lt;code&gt;argocd app diff&lt;/code&gt; command. Thus, this tool needs the Argo CD applications to already be in sync with Git to be helpful. Applications that are out-of-sync on the Argo CD instance will be rendered as a diff on every PR. Additionally, you need to provide your CI pipeline with credentials to your Argo CD server, which may not be possible or desirable. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/zapier/kubechecks" rel="noopener noreferrer"&gt;zapier/kubechecks&lt;/a&gt; is a system that you install on your cluster, which may not be desirable for organizations with strict security restrictions. The tool is complex but has many interesting features. Again, this tool requires access to your running Argo CD instance, which may not be possible or desirable. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;argocd-diff-preview&lt;/code&gt; was created to avoid installing a tool directly on a cluster or providing it with credentials to your live Argo CD instance.&lt;/p&gt;




&lt;h2&gt;
  
  
  New solution: &lt;code&gt;argocd-diff-preview&lt;/code&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Goal
&lt;/h3&gt;

&lt;p&gt;Create a tool that works like Atlantis for Terraform but for Argo CD. The tool should render a reliable diff of the configuration changes directly on the PR. Additionally, it should work without needing access to your existing infrastructure. &lt;/p&gt;

&lt;p&gt;Instead of creating some scripts that try to mimic how Argo CD would render the manifests, why not let Argo CD render the manifests itself? This would ensure that the rendered manifests are exactly how Argo CD would render the manifests.&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;argocd-diff-preview&lt;/code&gt; spins up a local cluster, installs Argo CD, applies the manifests to the cluster, extracts the rendered manifests from Argo CD, and compares it to the main branch.&lt;/p&gt;

&lt;p&gt;This tool runs an ephemeral local cluster inside Docker, so it does not need access to your infrastructure. It only needs read access to the Git repository and your Helm Charts (either stored in Git or a registry) &lt;/p&gt;

&lt;h4&gt;
  
  
  In other words, it follows these 10 steps:
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Start a local cluster&lt;/li&gt;
&lt;li&gt;Install Argo CD&lt;/li&gt;
&lt;li&gt;Add the required credentials (Git credentials, image pull secrets, etc.)&lt;/li&gt;
&lt;li&gt;Fetch all Argo CD application files on your PR branch

&lt;ul&gt;
&lt;li&gt;Point their &lt;code&gt;targetRevision&lt;/code&gt; to the Pull Request branch&lt;/li&gt;
&lt;li&gt;Remove the &lt;code&gt;syncPolicy&lt;/code&gt; from the application (to avoid the application to sync locally)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Apply the modified applications to the cluster&lt;/li&gt;
&lt;li&gt;Let Argo CD do its magic&lt;/li&gt;
&lt;li&gt;Extract the rendered manifests from the Argo CD server&lt;/li&gt;
&lt;li&gt;Repeat steps 4–7 for the base branch (main branch)&lt;/li&gt;
&lt;li&gt;Create a diff between the manifests rendered from each branch&lt;/li&gt;
&lt;li&gt;Display the diff in the PR&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;The flow visualized:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx5cergp1nzexsuxrwwfm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx5cergp1nzexsuxrwwfm.png" alt="the flow visualized" width="800" height="255"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;If you are asked for a review on a PR that looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fisem8ehiagmfpjtnpwmu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fisem8ehiagmfpjtnpwmu.png" alt="pull request example" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then you can verify that it is configured correctly by checking the output generated by &lt;code&gt;argocd-diff-preview&lt;/code&gt;. The output would look similar to this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fike2g0merao6bxedrzx4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fike2g0merao6bxedrzx4.png" alt="tool output example" width="800" height="1073"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Always renders the correct difference between branches because it is rendered by Argo CD itself. &lt;/li&gt;
&lt;li&gt;Fully ephemeral cluster.&lt;/li&gt;
&lt;li&gt;Does not access any of your existing infrastructure. It only requires read access to the Git repository and your Helm Charts. &lt;/li&gt;
&lt;li&gt;Can be run locally before you open the pull request.&lt;/li&gt;
&lt;li&gt;Supports multi-source applications&lt;/li&gt;
&lt;li&gt;Supports Argo CD Config Management Plugins (CMP)&lt;/li&gt;
&lt;li&gt;Renders changes in resources from external sources (e.g., Helm Charts). For example, when you update the Helm Chart version of &lt;code&gt;nginx&lt;/code&gt;, you can see what exactly changed - &lt;a href="https://github.com/dag-andersen/argocd-diff-preview/pull/15" rel="noopener noreferrer"&gt;PR example&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;It is slow. Spinning up a cluster and installing Argo CD takes a few minutes each run (see table below)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Comparing desired states - Not actual state
&lt;/h3&gt;

&lt;p&gt;An important point to understand is that, unlike Atlantis or the &lt;code&gt;argocd diff&lt;/code&gt; CLI command, this approach doesn't compare the desired state in Git with the actual state in Kubernetes. Instead, it compares the desired state of the two branches stored in Git. I would argue that this is better than comparing Git with the actual state in Kubernetes because the state can change, resulting in non-deterministic output. The actual state in Kubernetes can temporarily go out-of-sync with Git, and we don't want this to be highlighted in our diff preview. Developers who work with Altanis experience this a lot - each time you run &lt;code&gt;atlantis plan&lt;/code&gt;, it may produce a different result if the infrastructure changes often.&lt;/p&gt;
&lt;h3&gt;
  
  
  How to use it in GitHub Actions
&lt;/h3&gt;

&lt;p&gt;Here is an example of how you would trigger &lt;code&gt;argocd-diff-preview&lt;/code&gt; on your pull requests in GitHub Actions&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Argo CD Diff Preview&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;render-diff&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;contents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;read&lt;/span&gt;
      &lt;span class="na"&gt;pull-requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pull-request&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;
          &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Generate Diff&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;docker run \&lt;/span&gt;
            &lt;span class="s"&gt;--network=host \&lt;/span&gt;
            &lt;span class="s"&gt;-v /var/run/docker.sock:/var/run/docker.sock \&lt;/span&gt;
            &lt;span class="s"&gt;-v $(pwd)/main:/base-branch \&lt;/span&gt;
            &lt;span class="s"&gt;-v $(pwd)/pull-request:/target-branch \&lt;/span&gt;
            &lt;span class="s"&gt;-v $(pwd)/output:/output \&lt;/span&gt;
            &lt;span class="s"&gt;-e TARGET_BRANCH=${{ github.head_ref }} \&lt;/span&gt;
            &lt;span class="s"&gt;-e REPO=${{ github.repository }} \&lt;/span&gt;
            &lt;span class="s"&gt;dagandersen/argocd-diff-preview:v0.0.23&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Post diff as comment&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;gh pr comment ${{ github.event.number }} --repo ${{ github.repository }} --body-file output/diff.md --edit-last || \&lt;/span&gt;
          &lt;span class="s"&gt;gh pr comment ${{ github.event.number }} --repo ${{ github.repository }} --body-file output/diff.md&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;GITHUB_TOKEN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Handling credentials
&lt;/h3&gt;

&lt;p&gt;In the simple code example above, I do not provide &lt;code&gt;argocd-diff-preview&lt;/code&gt; with any credentials, which only works if the Helm Chart registry and the Git repository are public. If you want to use this tool in a private repository, you need to provide the tool with the required credentials. More details on this can be seen in the &lt;a href="https://github.com/dag-andersen/argocd-diff-preview#handling-credentials" rel="noopener noreferrer"&gt;GitHub Repository&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Output
&lt;/h3&gt;

&lt;p&gt;On a successful run, the tool prints the following output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✨ Running with:
✨ - base-branch: main
✨ - target-branch: helm-example-3
✨ - repo: dag-andersen/argocd-diff-preview
✨ - timeout: 180
🚀 Creating cluster...
🚀 Cluster created successfully
🦑 Installing Argo CD...
...
🤖 Patching applications for branch: main
🤖 Patching applications for branch: helm-example-3
🌚 Getting resources for base-branch
🌚 Getting resources for target-branch
...
🔮 Generating diff between main and helm-example-3
🙏 Please check the ./output/diff.md file for differences
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If something is wrong with your configuration, it prints the Argo CD Application error message:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
🤖 Patching 4 Argo CD Application[Sets] for branch: helm-example-3
🌚 Getting resources for target-branch
⏳ Waiting for 4 out of 4 applications to become 'OutOfSync'. Retrying in 5 seconds. Timeout in 180 seconds...
❌ Failed to process application, my-app, with error:
    Failed to load target state: failed to generate manifest for source 2 of 2: rpc error: code = Unknown desc = authentication required
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Speed
&lt;/h3&gt;

&lt;p&gt;The table below shows how the number of applications correlates with the time it takes to render them all:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Number of applications&lt;/th&gt;
&lt;th&gt;1&lt;/th&gt;
&lt;th&gt;50&lt;/th&gt;
&lt;th&gt;250&lt;/th&gt;
&lt;th&gt;500&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Seconds**&lt;/td&gt;
&lt;td&gt;80&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;210&lt;/td&gt;
&lt;td&gt;330&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj1tlx6wwqvwgdsczs0tk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj1tlx6wwqvwgdsczs0tk.png" alt="graph showing how the number of applications correlates with the time it takes to render them" width="800" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Creating a cluster and installing Argo CD on it takes around 1 minute, which is why rendering a single application takes over a minute. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;**The speed can vary depending on the distribution between applications used with Kustomize, Helm, and raw manifests. This test's result is based on a codebase mainly filled with Helm Charts.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Speeding up the rendering process
&lt;/h4&gt;

&lt;p&gt;Rendering the manifests generated by all applications in the repository for each pull request can be slow. The tool offers various options to limit the number of applications rendered on each PR. You can choose applications based on label selectors, file paths, or by tracking specific file changes For more information: &lt;a href="https://dag-andersen.github.io/argocd-diff-preview/application-selection/" rel="noopener noreferrer"&gt;[docs]&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In conclusion, tackling the challenge of accurately visualizing Kubernetes configuration changes within GitOps workflows is essential for ensuring smooth operations and minimizing errors.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;argocd-diff-preview&lt;/code&gt; works like Atlantis for Terraform. The tool lets you render the diff on PRs, making it easier to review the changes made to the configuration. Since the diff is rendered by Argo CD itself, it is as accurate as possible.&lt;/p&gt;

&lt;p&gt;In contrast to other existing solutions, &lt;code&gt;argocd-diff-preview&lt;/code&gt;  works without direct access to your infrastructure, which can be desirable for organizations with strict security requirements.&lt;/p&gt;

&lt;p&gt;If you experience any issues with the tool, please open an issue on the &lt;a href="https://github.com/dag-andersen/argocd-diff-preview" rel="noopener noreferrer"&gt;repository&lt;/a&gt;&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>devops</category>
      <category>git</category>
      <category>argocd</category>
    </item>
  </channel>
</rss>
