Argo CD: Fixing Helm Chart Deployment With Digest Issue

Alex Johnson
-
Argo CD: Fixing Helm Chart Deployment With Digest Issue

In today's cloud-native world, deploying applications efficiently and reliably is paramount. Helm charts have become a cornerstone for managing Kubernetes applications, simplifying the process of packaging, deploying, and managing applications. At the same time, Argo CD, a declarative GitOps continuous delivery tool for Kubernetes, automates the deployment of applications to a Kubernetes cluster. However, integrating Helm charts with Argo CD can sometimes present challenges, especially when using digests to point to specific chart versions.

This article aims to explore and address a common issue encountered when deploying applications with Helm charts in Argo CD, specifically when the chart is referenced using its digest. We'll delve into the technical details of the problem, understand its root cause, and provide a step-by-step guide to resolving it. Whether you're a seasoned DevOps engineer or just starting with Kubernetes and Argo CD, this article will equip you with the knowledge to overcome this hurdle and ensure smooth application deployments.

We'll cover the following topics:

  1. Detailed explanation of the issue: the error message, logs, and screenshots.
  2. Step-by-step instructions on how to reproduce the bug.
  3. Root cause analysis: why the issue occurs and what are the underlying problems.
  4. Proposed solution: how to fix the issue by modifying the Argo CD configuration.
  5. Best practices: how to avoid the issue in the future and ensure smooth deployments.
  6. Additional resources: links to the Helm and Argo CD documentation, as well as the GitHub issues and pull requests related to the topic.

By the end of this article, you'll have a comprehensive understanding of how to deploy applications with Helm charts and Argo CD, even when using digests.

The Problem: Deploying Helm Charts with Digests in Argo CD

When deploying applications using Helm charts stored in an OCI registry, referencing the chart by its digest ensures that you're using a specific, immutable version. However, this approach can lead to deployment failures in Argo CD due to how Argo CD constructs Helm commands. The core issue arises because Argo CD incorrectly includes the --version flag when pulling Helm charts by digest. The Helm CLI interprets the digest as a semver version when the --version flag is used, leading to an error.

To illustrate, consider the following scenario. Your organization packages Helm charts into an OCI repository and references them using digests, like this:

helm install example-registry-quay-openshift-operators.apps.quay-gori.cp.example.com/piotr/charts/test-nginx-chart/nginx@sha256:4b5007efa6ea560d18fb7cb7d4f268e180ef8f8e577861abeb8db38ad39a49eb

When deploying this chart through Argo CD, the process fails. This failure occurs because Argo CD's internal commands add the --version flag, which is incompatible with digest references. This issue is a known follow-up from a previous discussion, highlighting the ongoing challenges in managing Helm OCI repositories with Argo CD.

The error manifests as Argo CD attempting to parse the digest (e.g., sha256:4b5007efa6ea560d18fb7cb7d4f268e180ef8f8e577861abeb8db38ad39a49eb) as a semantic version. Since a digest is not a semver-compliant string, Helm CLI throws an error, and the deployment fails. This behavior contradicts the expected outcome, where specifying a digest should uniquely identify the chart version without needing the --version flag.

Reproducing the Bug: Step-by-Step Guide

To reproduce this bug, follow these steps:

  1. Create a Helm OCI repository:

    First, you need to set up a Helm OCI repository. This involves configuring Argo CD to connect to your OCI registry. Here’s an example configuration:

    - connectionState:
        attemptedAt: "2025-10-15T12:26:59Z"
        message: ""
        status: Successful
      enableOCI: true
      name: quay-oci-repo
      repo: example-registry-quay-openshift-operators.apps.quay-gori.cp.example.com/piotr/charts
      type: helm
    

    This configuration snippet tells Argo CD how to connect to your OCI repository, including enabling OCI support and specifying the repository URL.

  2. Create an Argo CD Application:

    Next, define an Argo CD Application that points to a Helm chart in your OCI repository using a digest. Here’s an example Application manifest:

    project: default
    source:
      repoURL: >-
        example-registry-quay-openshift-operators.apps.quay-gori.cp.example.com/piotr/charts
      chart: test-nginx-chart/nginx
      targetRevision: sha256:4b5007efa6ea560d18fb7cb7d4f268e180ef8f8e577861abeb8db38ad39a49eb
    destination:
      server: https://kubernetes.default.svc/
      namespace: nginx-demo
    syncPolicy:
      automated:
        prune: true
        selfHeal: true
    

    In this manifest, targetRevision specifies the chart version using a SHA256 digest. This is where the problem arises, as Argo CD's handling of this digest causes the deployment to fail.

  3. Observe the Error:

    When you apply this Application in Argo CD, you will encounter an error similar to the one below:

    Unable to save changes: application spec for nginx-oci-app is invalid:
    InvalidSpecError: Unable to generate manifests in : 
    rpc error: code = Unknown desc = invalid revision:
    failed to determine semver constraint: improper constraint: 
    sha256:4b5007efa6ea560d18fb7cb7d4f268e180ef8f8e577861abeb8db38ad39a49eb
    

    This error message indicates that Argo CD is unable to interpret the digest as a semver constraint, which is the root of the problem.

  4. Examine the Helm CLI Command:

    Argo CD generates a Helm CLI command that includes the --version flag with the digest, which causes Helm to misinterpret the digest. The command looks something like this:

    helm pull oci://example-registry-quay-openshift-operators.apps.quay-gori.cp.example.com/piotr/charts/test-nginx-chart/nginx --version sha256:4b5007efa6ea560d18fb7cb7d4f268e180ef8f8e577861abeb8db38ad39a49eb --destination /tmp/8ecd5c56-695d-426b-82c0-5a6201e137b2 --insecure-skip-tls-verify
    Error: improper constraint: sha256:4b5007efa6ea560d18fb7cb7d4f268e180ef8f8e577861abeb8db38ad39a49eb
    

    This command fails because Helm expects --version to be a semver-compatible string, not a digest.

By following these steps, you can reproduce the bug and confirm that Argo CD's handling of Helm charts with digests is problematic.

Root Cause Analysis: Why Argo CD Fails with Digests

The root cause of the issue lies in how Argo CD constructs Helm CLI commands when dealing with OCI repositories and digests. Specifically, Argo CD erroneously adds the --version flag to the helm pull command when the chart is referenced by its digest. This behavior is incorrect because Helm does not require the --version flag when a digest is provided; in fact, including it causes Helm to misinterpret the digest as a semantic version, leading to a failure.

To understand this better, let’s break down the Helm CLI command generated by Argo CD:

helm pull oci://<repository>/<chart> --version <digest> --destination <temp_dir> --insecure-skip-tls-verify

Here, the --version flag is followed by the digest, which Helm attempts to parse as a semver string. Since a digest is a SHA256 hash and not a semantic version, Helm throws an improper constraint error.

The Helm community has extensively discussed how digests should be handled in Helm CLI. The consensus is that when a digest is used, the --version flag should be omitted. This is because the digest uniquely identifies the chart version, making the --version flag redundant and potentially conflicting.

For instance, running the helm pull command manually without the --version flag works perfectly:

helm pull oci://example-registry-quay-openshift-operators.apps.quay-gori.cp.example.com/piotr/charts/test-nginx-chart/nginx@sha256:4b5007efa6ea560d18fb7cb7d4f268e180ef8f8e577861abeb8db38ad39a49eb --destination /tmp/8ecd5c56-695d-426b-82c0-5a6201e137b2 --insecure-skip-tls-verify

This command succeeds because it adheres to the Helm best practice of excluding the --version flag when using digests.

In summary, Argo CD's incorrect inclusion of the --version flag when pulling Helm charts by digest is the primary reason for the deployment failures. This issue stems from a misunderstanding of how Helm CLI handles digests and the redundancy of the --version flag in such cases.

Proposed Solution: Modifying Argo CD to Handle Digests Correctly

The proposed solution to this issue involves modifying Argo CD's behavior to conditionally include the --version flag in Helm CLI commands. Specifically, the --version flag should only be added when the targetRevision does not contain a digest. This ensures that when a chart is referenced by its digest, Argo CD generates the correct Helm command without the problematic --version flag.

The fix requires changes in Argo CD's codebase where Helm CLI commands are constructed. The logic should be updated to check if the targetRevision is a digest (e.g., starts with sha256:). If it is, the --version flag should be omitted; otherwise, the flag should be included with the appropriate version value.

Here’s a high-level overview of the steps to implement this fix:

  1. Identify the Code Location:

    Locate the section of Argo CD's code responsible for generating Helm CLI commands, particularly the helm pull command.

  2. Implement Conditional Logic:

    Add a conditional check to determine if the targetRevision is a digest. This can be done by checking if the targetRevision string starts with sha256:.

  3. Modify Command Construction:

    If the targetRevision is a digest, construct the helm pull command without the --version flag. If it is not a digest, include the --version flag with the targetRevision value.

  4. Test the Changes:

    Implement thorough testing to ensure the fix works as expected. This should include tests for both digest and version-based chart references.

By implementing this solution, Argo CD will correctly handle Helm charts referenced by digests, allowing for seamless deployments from OCI registries. This fix aligns with Helm's best practices and resolves the improper constraint error caused by the incorrect use of the --version flag.

Best Practices: Ensuring Smooth Deployments with Helm and Argo CD

To ensure smooth deployments with Helm and Argo CD, especially when using OCI registries and digests, consider the following best practices:

  1. Always Use Digests for Production Deployments:

    Referencing Helm charts by their digests in production environments ensures immutability and reproducibility. Digests uniquely identify a specific chart version, eliminating the risk of unexpected changes due to tag updates.

  2. Validate Charts Before Pushing to the OCI Registry:

    Before pushing a chart to your OCI registry, validate it thoroughly. This includes linting, testing, and ensuring that the chart adheres to your organization's standards and best practices. This proactive approach can prevent deployment issues and ensure the stability of your applications.

  3. Regularly Update Argo CD:

    Keep your Argo CD installation up to date to benefit from the latest bug fixes, features, and performance improvements. Newer versions of Argo CD may include enhancements that address issues related to Helm OCI repositories and digest handling.

  4. Monitor Argo CD Logs:

    Regularly monitor Argo CD logs to identify and address any deployment issues promptly. Logs can provide valuable insights into the root cause of failures and help you troubleshoot problems more effectively.

  5. Test Deployments in a Staging Environment:

    Before deploying changes to production, always test them in a staging environment. This allows you to identify and resolve any issues before they impact your production applications.

  6. Use Semantic Versioning for Chart Releases:

    Adopt semantic versioning (SemVer) for your Helm chart releases. SemVer provides a clear and consistent way to manage chart versions and helps prevent compatibility issues between different releases.

  7. Document Your Deployment Process:

    Document your deployment process, including the steps for building, pushing, and deploying Helm charts. This documentation will help ensure consistency and make it easier for team members to collaborate and troubleshoot issues.

  8. Automate Your Deployment Pipeline:

    Automate your deployment pipeline using CI/CD tools. This reduces the risk of human error and ensures that deployments are performed consistently and reliably.

By following these best practices, you can significantly improve the reliability and efficiency of your Helm and Argo CD deployments, ensuring that your applications are always running smoothly.

Conclusion

In conclusion, deploying Helm charts with digests in Argo CD requires careful attention to how Argo CD constructs Helm CLI commands. The issue of Argo CD incorrectly including the --version flag when pulling charts by digest can lead to deployment failures and frustrate DevOps teams. However, by understanding the root cause of this problem and implementing the proposed solution—modifying Argo CD to conditionally include the --version flag—you can overcome this hurdle and ensure seamless deployments.

Moreover, adhering to best practices such as using digests for production deployments, validating charts before pushing them to the OCI registry, and regularly updating Argo CD can further enhance the reliability and efficiency of your deployment process. By adopting these strategies, you can leverage the full potential of Helm and Argo CD to manage your Kubernetes applications effectively.

Remember, the cloud-native landscape is constantly evolving, and staying informed about the latest tools and techniques is crucial for success. We hope this article has provided you with valuable insights and practical guidance for deploying Helm charts with Argo CD. For additional information and resources, be sure to explore the official Argo CD documentation and the Helm documentation. Happy deploying!

You may also like