Skip to content

Use helm pull for downloading charts#197

Open
zachburg wants to merge 11 commits intoperiareon:mainfrom
zachburg:helm_pull
Open

Use helm pull for downloading charts#197
zachburg wants to merge 11 commits intoperiareon:mainfrom
zachburg:helm_pull

Conversation

@zachburg
Copy link
Copy Markdown
Collaborator

@zachburg zachburg commented Aug 27, 2025

Since helm is already available, use it for downloading charts using helm pull instead of attempting to duplicate helm.

This will ensure any use cases handled by helm can be handled by rules_helm.

Downloaded charts are cached in the workspace by Bazel since the repository rule isn't always re-executed (https://bazel.build/external/repo#when_is_the_implementation_function_executed)

A potential separate feature to add is pinning charts by their SHA-256 checksum, similar to https://github.com/bazel-contrib/rules_jvm_external?tab=readme-ov-file#pinning-artifacts-and-integration-with-bazels-downloader. But I think most Helm charts are small enough that I'm not concerned if the same chart has be downloaded in multiple workspaces instead of coming from the repository cache.

@zachburg zachburg requested a review from abrisco August 27, 2025 00:29
Copy link
Copy Markdown
Collaborator

@abrisco abrisco left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Won't this just be slower as the Bazel repository cache won't be used?

@zachburg
Copy link
Copy Markdown
Collaborator Author

helm is being cached and charts are only being downloaded if an attribute of the build rule changes. Rebuilding //tests/with_chart_deps doesn't show the repository rule is always being executed.

@zachburg
Copy link
Copy Markdown
Collaborator Author

zachburg commented Aug 27, 2025

Actually, we can return a repo_metadata object to indicate if the rule is reproducible.

Unfortunately, we can't determine the exact attributes required for reproducibility unless we parsed the output from YAML output which is returned via stderr:

$ helm show chart oci://registry-1.docker.io/bitnamicharts/grafana 2> /dev/null
annotations:
  category: Analytics
  images: |
    - name: grafana
      image: docker.io/bitnami/grafana:12.1.1-debian-12-r1
    - name: os-shell
      image: docker.io/bitnami/os-shell:12-debian-12-r50
  licenses: Apache-2.0
  tanzuCategory: application
apiVersion: v2
appVersion: 12.1.1
dependencies:
- name: common
  repository: oci://registry-1.docker.io/bitnamicharts
  tags:
  - bitnami-common
  version: 2.x.x
description: Grafana is an open source metric analytics and visualization suite for
  visualizing time series data that supports various types of data sources.
home: https://bitnami.com
icon: https://dyltqmyl993wv.cloudfront.net/assets/stacks/grafana/img/grafana-stack-220x234.png
keywords:
- analytics
- monitoring
- metrics
- logs
maintainers:
- name: Broadcom, Inc. All Rights Reserved.
  url: https://github.com/bitnami/charts
name: grafana
sources:
- https://github.com/bitnami/charts/tree/main/bitnami/grafana
version: 12.1.8

I filed helm/helm#31205 for having helm pull print the pulled version, but that will require waiting for Helm v4 and I don't think would be backported to v3.

@zachburg zachburg requested a review from abrisco August 27, 2025 22:36
Copy link
Copy Markdown
Collaborator

@abrisco abrisco left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

helm is being cached and charts are only being downloaded if an attribute of the build rule changes. Rebuilding //tests/with_chart_deps doesn't show the repository rule is always being executed.

That's not what I'm referring to. https://blog.engflow.com/2024/05/13/the-many-caches-of-bazel/#repository-cache

The rule won't run but any time it does Bazel will have to rely on whatever caching mechanism helm has to maybe skip downloading something or ensure the same thing from a previous point in time was downloaded. I've experienced massive issues with this in the earlier pip_parse rules from rules_python where developers would have volatile items in their pip cache that would make their way into builds and make everything slow. If pull is capable of fetching metadata, then I would be down for that but I ultimately want Bazel (via repository_ctx.download) to fetch and verify external dependencies.

@zachburg
Copy link
Copy Markdown
Collaborator Author

What about maintaining two options? helm_pull to allow using helm and it's resolver logic to download a chart, which wouldn't be cacheable, and helm_import_url to download a specific chart using the Bazel downloader.

@abrisco
Copy link
Copy Markdown
Collaborator

abrisco commented Aug 30, 2025

What about maintaining two options? helm_pull to allow using helm and it's resolver logic to download a chart, which wouldn't be cacheable, and helm_import_url to download a specific chart using the Bazel downloader.

If there is something that's just not possible with just repository_ctx then I would be in favor of another rule that does that. However, I don't think there should be overlap in functionality. I would want to do something that discourages the use of a helm invocation if there's a repository_ctx way to do the same thing.

@zachburg
Copy link
Copy Markdown
Collaborator Author

zachburg commented Sep 4, 2025

A couple benefits from using real helm pull for pulling charts:

  • Allows helm to handle authentication instead of reimplementing it in Bazel rules (which is already done for OCI registries, I don't know how to handle it for HTTP repositories)
  • Pull by version constraint instead of a specific version. This wouldn't be reproducible, but could log the pulled version and warn to specify a specific version
  • Allow verifying the provenance file (I don't have a use-case for this but maybe some other users do)

But even using repository_ctx.download doesn't always mean the result will be reproducible or cacheable. If pulling a chart from a repository or via a OCI version tag, multiple HTTP calls are required before pulling the chart package.

For example, rules_oci does allow specifying a version tag (1.2.3) instead of a digest but warns on that case.

@zachburg
Copy link
Copy Markdown
Collaborator Author

zachburg commented Sep 4, 2025

One more issue I thought of for OCI URLs: URLs that use a version digest (@sha123..) have the SHA256 sum of the entire container, but we only care about chart blob which has its own digest that's not known until pulling the manifest (either by tag or digest)

Little demo of helm pull:

$ helm pull oci://registry-1.docker.io/bitnamicharts/grafana@sha256:93158fcd5ca9f61687bee4f4bd5e9867af4285860f794696e7771b403f46149d
Pulled: registry-1.docker.io/bitnamicharts/grafana@sha256:93158fcd5ca9f61687bee4f4bd5e9867af4285860f794696e7771b403f46149d
Digest: sha256:93158fcd5ca9f61687bee4f4bd5e9867af4285860f794696e7771b403f46149d
zachburg:/tmp/tmp.dV1XrHuMga
$ ls
grafana@sha256-93158fcd5ca9f61687bee4f4bd5e9867af4285860f794696e7771b403f46149d.tgz
zachburg:/tmp/tmp.dV1XrHuMga
$ sha256sum grafana@sha256-93158fcd5ca9f61687bee4f4bd5e9867af4285860f794696e7771b403f46149d.tgz 
e7227a3b9e77777fed9d781745dafdc384982f2326d859605101396611e928ed  grafana@sha256-93158fcd5ca9f61687bee4f4bd5e9867af4285860f794696e7771b403f46149d.tgz
zachburg:/tmp/tmp.dV1XrHuMga

The SHA256 sum of the chart is not related to the OCI URL.

@zachburg zachburg requested a review from abrisco September 18, 2025 21:59
@zachburg
Copy link
Copy Markdown
Collaborator Author

zachburg commented Oct 1, 2025

@abrisco, thoughts on #197 (comment)?

Looking at https://github.com/bazel-contrib/rules_jvm_external and https://github.com/bazel-contrib/rules_python, they use coursier and pip respectively, with optional support to write a file for downloading dependencies via the Bazel downloader. I think the possible equivalent here is to intercept the logs from helm pull/helm show and write a file of chart deps that could be downloaded via Bazel, if desired.

@abrisco
Copy link
Copy Markdown
Collaborator

abrisco commented Oct 14, 2025

@abrisco, thoughts on #197 (comment)?

Looking at https://github.com/bazel-contrib/rules_jvm_external and https://github.com/bazel-contrib/rules_python, they use coursier and pip respectively, with optional support to write a file for downloading dependencies via the Bazel downloader. I think the possible equivalent here is to intercept the logs from helm pull/helm show and write a file of chart deps that could be downloaded via Bazel, if desired.

Hey! Sorry for the radio silence here. Things have been hectic 😓

I'm extremely familiar with rules_python and it's use of pip and that exact implementation is what solidified my stance that repository rules should ideally use repository_ctx to download and not rely on any external tools or caching mechanism. The middle ground I've found to be palatable is if an external tool was used to query the data needed to use the Bazel downloader (which is similar to the original implementation).

If there were to be a helm pull backed repository rule, my current thought is that it should always say it's not reproducible and should recommend using the pure Bazel rule.

Though maybe this is something we could better discuss on slack at this point. I don't mean to be halting progress here.

@zachburg
Copy link
Copy Markdown
Collaborator Author

I don't have easy access to Slack, but email zachburg@google.com instead.

@bcsgh
Copy link
Copy Markdown
Contributor

bcsgh commented Jan 5, 2026

A bit out of scope, but I wonder if this sort of case would support Bazel acting as an HTTP/HTTPS/etc. proxy? Tools like helm/mpm/npm/etc generally already need a way to redirect them to a proxy (e.g. to protect builds from supply chain attacks and to allow air-gaped builds) so a way to make their invocation proxy thought the existing bazel caching would offer an effective way to both integrate high fidelity caching as well as avoid re-implementing the native tool's logic in .bzl libraries.

@nate-england
Copy link
Copy Markdown
Contributor

Using the bazel downloader is preferable in scenarios where users want to redirect through custom proxies and especially those that need credentials. https://blog.aspect.build/configuring-bazels-downloader gives a good overview and bazel's credential_helper support is already very nice for automatically injecting credentials instead of relying on helm login.

@abrisco
Copy link
Copy Markdown
Collaborator

abrisco commented Mar 9, 2026

I think it was rude of me to let this linger for as long as it has and I'm sorry for that. My feelings are that I'm against directly adding a mode that uses helm and doesn't use the bazel downloader since I've had many headaches from other tools that do similar things. But I do understand the convenience of it. Is there a path forward to ensuring there is a stable enough interface within these rules to allow these rules to live in a separate repo? I just don't have enough bandwidth or context to deal with any issues that come from invoking helm in a repository rule.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants