From 71bf89a5888040c7a80a3fcf97da8f43b1ad7d09 Mon Sep 17 00:00:00 2001 From: Richard Clark Date: Tue, 10 Nov 2026 12:10:25 +0000 Subject: [PATCH] Move `helm_oci_manifest` into a separate `rules_helm_img` module Bazel has no optional `bazel_dep`, and a dev dependency is invisible to dependents. While `helm/rules_img.bzl` was in `rules_helm`, every consumer resolved `rules_img`, `hermetic_launcher` and the `img_toolchain` hub repo, including those that never use `helm_oci_manifest`. `helm_oci_manifest` now lives in `modules/rules_helm_img`, a second module that is released from the same tag and has the same version. `rules_helm` has `rules_img` as a dev dependency only. A consumer adds `bazel_dep(name = "rules_helm_img")` and loads from `@rules_helm_img//:defs.bzl`. - The new module loads the private `helm_oci_parts` rule. `HELM_OCI_PARTS_API` in `oci_parts.bzl` makes a `rules_helm_img` that is paired with a different `rules_helm` fail with a clear message. - `.bazelignore` keeps the module out of `//...`, because Bazel does not skip a directory that has its own `MODULE.bazel`. The root uses the module through a dev dependency and `local_path_override`. - `.bcr/config.yml` lists both module roots. The new module reuses the `rules_helm` release archive with `strip_prefix = "modules/rules_helm_img"`. - `tests/bzl_version` also compares the new module's version and its `rules_helm` dependency with `version.bzl`, so a release that misses a bump fails on the pull request. `release_prep.sh` checks the same values as a backstop. - `rules_helm_img_smoke_build_test` builds the module's smoke target from the root. `//...` does not reach it, and a missing `bazel_dep(platforms)` in the module passed the root tests and failed a standalone build on Bazel 9. --- .bazelignore | 1 + .bcr/config.yml | 1 + .../rules_helm_img/metadata.template.json | 17 +++++++ .bcr/modules/rules_helm_img/presubmit.yml | 14 ++++++ .../rules_helm_img/source.template.json | 5 ++ .github/release_notes.template | 4 ++ .github/workflows/release_prep.sh | 15 ++++++ .gitignore | 4 ++ MODULE.bazel | 10 +++- docs/BUILD.bazel | 4 +- docs/src/index.md | 14 ++++++ helm/BUILD.bazel | 13 ------ helm/private/BUILD.bazel | 8 ++++ helm/private/oci_parts.bzl | 6 +++ modules/rules_helm_img/BUILD.bazel | 21 +++++++++ modules/rules_helm_img/MODULE.bazel | 15 ++++++ .../rules_helm_img/defs.bzl | 22 +++++++-- modules/rules_helm_img/smoke/BUILD.bazel | 32 +++++++++++++ tests/bzl_version/BUILD.bazel | 5 +- tests/bzl_version/bzl_version_test.go | 46 ++++++++++++++++--- tests/helm_oci_manifest/BUILD.bazel | 12 ++++- version.bzl | 3 ++ 22 files changed, 244 insertions(+), 28 deletions(-) create mode 100644 .bcr/modules/rules_helm_img/metadata.template.json create mode 100644 .bcr/modules/rules_helm_img/presubmit.yml create mode 100644 .bcr/modules/rules_helm_img/source.template.json create mode 100644 modules/rules_helm_img/BUILD.bazel create mode 100644 modules/rules_helm_img/MODULE.bazel rename helm/rules_img.bzl => modules/rules_helm_img/defs.bzl (81%) create mode 100644 modules/rules_helm_img/smoke/BUILD.bazel diff --git a/.bazelignore b/.bazelignore index a954dea3..9d195237 100644 --- a/.bazelignore +++ b/.bazelignore @@ -2,3 +2,4 @@ bazel-out bazel-bin bazel-rules_helm bazel-testlogs +modules/rules_helm_img diff --git a/.bcr/config.yml b/.bcr/config.yml index e69de29b..6a3e227a 100644 --- a/.bcr/config.yml +++ b/.bcr/config.yml @@ -0,0 +1 @@ +moduleRoots: [".", "modules/rules_helm_img"] diff --git a/.bcr/modules/rules_helm_img/metadata.template.json b/.bcr/modules/rules_helm_img/metadata.template.json new file mode 100644 index 00000000..657b9a71 --- /dev/null +++ b/.bcr/modules/rules_helm_img/metadata.template.json @@ -0,0 +1,17 @@ +{ + "homepage": "https://github.com/periareon/rules_helm", + "maintainers": [ + { + "name": "Andre Brisco", + "email": "91817010+abrisco@users.noreply.github.com", + "github": "abrisco", + "github_user_id": 91817010 + } + ], + "repository": [ + "github:abrisco/rules_helm", + "github:periareon/rules_helm" + ], + "versions": [], + "yanked_versions": {} +} diff --git a/.bcr/modules/rules_helm_img/presubmit.yml b/.bcr/modules/rules_helm_img/presubmit.yml new file mode 100644 index 00000000..05dc77e3 --- /dev/null +++ b/.bcr/modules/rules_helm_img/presubmit.yml @@ -0,0 +1,14 @@ +--- +bcr_test_module: + module_path: "." + matrix: + # rules_img's image_manifest is not built on Windows by this repository's tests. + platform: ["macos_arm64", "ubuntu2004"] + bazel: ["7.x", "8.x"] + tasks: + run_tests: + name: "Build the module and its smoke target" + platform: ${{ platform }} + bazel: ${{ bazel }} + build_targets: + - "//..." diff --git a/.bcr/modules/rules_helm_img/source.template.json b/.bcr/modules/rules_helm_img/source.template.json new file mode 100644 index 00000000..dfc8b354 --- /dev/null +++ b/.bcr/modules/rules_helm_img/source.template.json @@ -0,0 +1,5 @@ +{ + "integrity": "", + "strip_prefix": "modules/rules_helm_img", + "url": "https://github.com/{OWNER}/{REPO}/releases/download/{VERSION}/rules_helm-v{VERSION}.tar.gz" +} diff --git a/.github/release_notes.template b/.github/release_notes.template index db297156..18bf85e1 100644 --- a/.github/release_notes.template +++ b/.github/release_notes.template @@ -9,4 +9,8 @@ http_archive( ) ``` +`rules_helm_img`, which adds `helm_oci_manifest` for `rules_img`, is an optional module in this archive for +Bzlmod only. Use the same version as `rules_helm`. With `archive_override`, set +`strip_prefix = "modules/rules_helm_img"`. + Additional documentation can be found at: https://github.com/periareon/rules_helm diff --git a/.github/workflows/release_prep.sh b/.github/workflows/release_prep.sh index b4a3f622..3e1aa6ab 100755 --- a/.github/workflows/release_prep.sh +++ b/.github/workflows/release_prep.sh @@ -34,6 +34,21 @@ if [[ "${ON_DISK_VERSION}" != "${TAG}" ]]; then exit 1 fi +# modules/rules_helm_img is published from this archive with the same version. +# Fail if its own version, or its pin of rules_helm, is not the tag: the +# published module would otherwise depend on a different rules_helm. +IMG_MODULE_FILE="${WORKSPACE}/modules/rules_helm_img/MODULE.bazel" +IMG_MODULE_VERSION="$(tr -d '\r' < "${IMG_MODULE_FILE}" | sed -n '/^module(/,/^)/s/^ *version = "\([^"]*\)".*$/\1/p')" +IMG_MODULE_PIN="$(tr -d '\r' < "${IMG_MODULE_FILE}" | sed -n 's/^bazel_dep(name = "rules_helm", version = "\([^"]*\)".*$/\1/p')" +if [[ -z "${IMG_MODULE_VERSION}" || -z "${IMG_MODULE_PIN}" ]]; then + echo "ERROR: could not read the module version ('${IMG_MODULE_VERSION}') or the rules_helm dependency version ('${IMG_MODULE_PIN}') from ${IMG_MODULE_FILE}" + exit 1 +fi +if [[ "${IMG_MODULE_VERSION}" != "${TAG}" || "${IMG_MODULE_PIN}" != "${TAG}" ]]; then + echo "ERROR: ${IMG_MODULE_FILE} has version='${IMG_MODULE_VERSION}' and rules_helm pin='${IMG_MODULE_PIN}', expected both to be ${TAG}" + exit 1 +fi + # Build the source archive. Exclude .git (history isn't needed by # consumers), .github (release infrastructure isn't part of the # ruleset), examples (kept out to reduce archive size — matches diff --git a/.gitignore b/.gitignore index 9f3bc62e..8fc655a3 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,10 @@ /bazel-* user.bazelrc +# Building a module in `modules/` as its own root writes these there. +/modules/*/bazel-* +/modules/*/MODULE.bazel.lock + # Helm # Dependency charts are not checked in and are instead handled by Bazel. **/charts/** diff --git a/MODULE.bazel b/MODULE.bazel index 38f4ca68..52537bc6 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -11,15 +11,23 @@ bazel_dep(name = "bazel_skylib", version = "1.9.2") bazel_dep(name = "rules_go", version = "0.63.0") bazel_dep(name = "gazelle", version = "0.53.0") bazel_dep(name = "bazel_lib", version = "3.0.0") -bazel_dep(name = "rules_img", version = "0.3.24") bazel_dep(name = "rules_oci", version = "2.3.0", dev_dependency = True) +bazel_dep(name = "rules_img", version = "0.3.24", dev_dependency = True) +bazel_dep(name = "rules_helm_img", version = "0.34.0", dev_dependency = True) bazel_dep(name = "stardoc", version = "0.8.1", dev_dependency = True) bazel_dep(name = "rules_rust_mdbook", version = "0.69.0", dev_dependency = True) bazel_dep(name = "rules_shell", version = "0.6.1", dev_dependency = True) bazel_dep(name = "buildifier_prebuilt", version = "8.5.1", dev_dependency = True) bazel_dep(name = "rules_cc", version = "0.2.17", dev_dependency = True) +# `rules_helm_img` is in this repository. The override is for the tests and docs +# here and does not apply to dependents. +local_path_override( + module_name = "rules_helm_img", + path = "modules/rules_helm_img", +) + # This override can be dropped when https://github.com/bazel-contrib/rules_oci/pull/891 is released. single_version_override( module_name = "rules_oci", diff --git a/docs/BUILD.bazel b/docs/BUILD.bazel index 6e3e5a32..5eea8274 100644 --- a/docs/BUILD.bazel +++ b/docs/BUILD.bazel @@ -148,10 +148,10 @@ stardoc( stardoc( name = "rules_img", out = "src/rules_img.md", - input = "//helm:rules_img.bzl", + input = "@rules_helm_img//:defs.bzl", table_of_contents_template = "@stardoc//stardoc:templates/markdown_tables/table_of_contents.vm", tags = ["manual"], - deps = ["//helm:rules_img_bzl"], + deps = ["@rules_helm_img//:defs_bzl"], ) stardoc( diff --git a/docs/src/index.md b/docs/src/index.md index 8709393c..5fd35c21 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -13,6 +13,20 @@ Bazel rules for producing [helm charts][helm] bazel_dep(name = "rules_helm", version = "{version}") ``` +### Optional module: `rules_helm_img` + +[`helm_oci_manifest`](./rules_img.md) lets the `multi_deploy` rule of +[rules_img](https://github.com/bazel-contrib/rules_img) push a chart. It is in a separate module, so +`rules_helm` does not depend on `rules_img`. Add the module only if you use it, with the same version +as `rules_helm`: + +```python +bazel_dep(name = "rules_helm_img", version = "{version}") +``` + +`rules_helm_img` supports Bzlmod only. To use it from the release archive with `archive_override`, +set `strip_prefix = "modules/rules_helm_img"`. + ## Run as a tool ```bash diff --git a/helm/BUILD.bazel b/helm/BUILD.bazel index 712e665f..c0df1890 100644 --- a/helm/BUILD.bazel +++ b/helm/BUILD.bazel @@ -18,7 +18,6 @@ exports_files( "helm_push.bzl", "helm_template.bzl", "helm_toolchain.bzl", - "rules_img.bzl", ], visibility = ["//visibility:public"], ) @@ -163,15 +162,3 @@ bzl_library( visibility = ["//visibility:public"], deps = ["//helm/private:bzl_lib"], ) - -bzl_library( - name = "rules_img_bzl", - srcs = ["rules_img.bzl"], - visibility = ["//visibility:public"], - deps = [ - "//helm/private:bzl_lib", - "@rules_img//img:image", - "@rules_img//img:layer", - "@rules_img//img:push", - ], -) diff --git a/helm/private/BUILD.bazel b/helm/private/BUILD.bazel index 680bd285..24a548d3 100644 --- a/helm/private/BUILD.bazel +++ b/helm/private/BUILD.bazel @@ -22,3 +22,11 @@ bzl_library( "@bazel_skylib//rules:common_settings", ], ) + +# Used by `rules_helm_img`, a separate module. +bzl_library( + name = "oci_parts_bzl", + srcs = ["oci_parts.bzl"], + visibility = ["//visibility:public"], + deps = [":bzl_lib"], +) diff --git a/helm/private/oci_parts.bzl b/helm/private/oci_parts.bzl index 5b55477e..4f31c857 100644 --- a/helm/private/oci_parts.bzl +++ b/helm/private/oci_parts.bzl @@ -2,6 +2,12 @@ load(":providers.bzl", "HelmPackageInfo") +# The interface of `helm_oci_parts` that `helm_oci_manifest` in the separate +# `rules_helm_img` module relies on: its attributes and outputs. A change that +# would break that macro must increase this number, so that an older +# `rules_helm_img` fails with a clear message. +HELM_OCI_PARTS_API = 1 + def _helm_oci_parts_impl(ctx): if ctx.attr.registry_url and ctx.attr.registry_url_file: fail("`registry_url` and `registry_url_file` are mutually exclusive. Only one may be specified for target `{}`.".format(ctx.label)) diff --git a/modules/rules_helm_img/BUILD.bazel b/modules/rules_helm_img/BUILD.bazel new file mode 100644 index 00000000..acf69071 --- /dev/null +++ b/modules/rules_helm_img/BUILD.bazel @@ -0,0 +1,21 @@ +load("@bazel_skylib//:bzl_library.bzl", "bzl_library") + +exports_files( + [ + "MODULE.bazel", + "defs.bzl", + ], + visibility = ["//visibility:public"], +) + +bzl_library( + name = "defs_bzl", + srcs = ["defs.bzl"], + visibility = ["//visibility:public"], + deps = [ + "@rules_helm//helm/private:oci_parts_bzl", + "@rules_img//img:image", + "@rules_img//img:layer", + "@rules_img//img:push", + ], +) diff --git a/modules/rules_helm_img/MODULE.bazel b/modules/rules_helm_img/MODULE.bazel new file mode 100644 index 00000000..566425f2 --- /dev/null +++ b/modules/rules_helm_img/MODULE.bazel @@ -0,0 +1,15 @@ +"""rules_helm_img: rules that build on both rules_helm and rules_img. + +This is a separate module so that `rules_helm` does not depend on `rules_img`. +It is released from the same tag as `rules_helm` with the same version. +""" + +module( + name = "rules_helm_img", + version = "0.34.0", +) + +bazel_dep(name = "bazel_skylib", version = "1.9.2") +bazel_dep(name = "platforms", version = "1.0.0") +bazel_dep(name = "rules_helm", version = "0.34.0") +bazel_dep(name = "rules_img", version = "0.3.24") diff --git a/helm/rules_img.bzl b/modules/rules_helm_img/defs.bzl similarity index 81% rename from helm/rules_img.bzl rename to modules/rules_helm_img/defs.bzl index 7fcad130..2198ed62 100644 --- a/helm/rules_img.bzl +++ b/modules/rules_helm_img/defs.bzl @@ -1,12 +1,25 @@ """# rules_img integration. -Rules that build on [rules_img](https://github.com/bazel-contrib/rules_img). +Rules that build on [rules_img](https://github.com/bazel-contrib/rules_img). They are in the +`rules_helm_img` module, so a workspace that does not use them does not depend on `rules_img`. + +```python +bazel_dep(name = "rules_helm", version = "{version}") +bazel_dep(name = "rules_helm_img", version = "{version}") +``` + +Use the same version of both modules, because `rules_helm_img` uses a private rule of `rules_helm`. """ +# Private to `rules_helm`, but released with this module. `helm_oci_manifest` checks `HELM_OCI_PARTS_API`. +# buildifier: disable=bzl-visibility +load("@rules_helm//helm/private:oci_parts.bzl", "HELM_OCI_PARTS_API", "helm_oci_parts") load("@rules_img//img:image.bzl", "image_manifest") load("@rules_img//img:layer.bzl", "layer_from_file") load("@rules_img//img:push.bzl", "image_push_spec") -load("//helm/private:oci_parts.bzl", "helm_oci_parts") + +# The version of `helm_oci_parts` that this file is written for. +_HELM_OCI_PARTS_API = 1 _HELM_CHART_MEDIA_TYPE = "application/vnd.cncf.helm.chart.content.v1.tar+gzip" _HELM_CONFIG_MEDIA_TYPE = "application/vnd.cncf.helm.config.v1+json" @@ -27,7 +40,7 @@ def helm_oci_manifest( `helm push` would. Only the chart is pushed; push its images with their own targets. ```python - load("@rules_helm//helm:rules_img.bzl", "helm_oci_manifest") + load("@rules_helm_img//:defs.bzl", "helm_oci_manifest") load("@rules_img//img:multi_deploy.bzl", "multi_deploy") helm_oci_manifest( @@ -73,6 +86,9 @@ def helm_oci_manifest( **kwargs (dict): Common attributes such as `tags`, `target_compatible_with` and `testonly`, applied to every target. """ + if HELM_OCI_PARTS_API != _HELM_OCI_PARTS_API: + fail("This `rules_helm_img` uses version {} of the `helm_oci_parts` interface of `rules_helm`, but the `rules_helm` in use has version {}. Use the same version of `rules_helm` and `rules_helm_img`.".format(_HELM_OCI_PARTS_API, HELM_OCI_PARTS_API)) + helm_oci_parts( name = name + ".oci_parts", chart = chart, diff --git a/modules/rules_helm_img/smoke/BUILD.bazel b/modules/rules_helm_img/smoke/BUILD.bazel new file mode 100644 index 00000000..7a62208c --- /dev/null +++ b/modules/rules_helm_img/smoke/BUILD.bazel @@ -0,0 +1,32 @@ +load("@rules_helm//helm:defs.bzl", "helm_chart") +load("//:defs.bzl", "helm_oci_manifest") + +# Built by the BCR presubmit, so that a published `rules_helm_img` is loaded and +# analysed against the published `rules_helm` and `rules_img`, and by +# `//tests/helm_oci_manifest:rules_helm_img_smoke_build_test` in `rules_helm`. The +# tests that check the pushed bytes are in that package. + +helm_chart( + name = "chart", + chart_json = json.encode({ + "apiVersion": "v2", + "name": "smoke", + "version": "0.1.0", + }), + # The chart has no templates, which Helm 4 lint rejects. + tags = ["no-helm-lint"], + values_json = json.encode({}), +) + +helm_oci_manifest( + name = "chart_oci_manifest", + chart = ":chart", + registry_url = "oci://registry.example.com/charts", + target_compatible_with = select({ + # As in //tests/helm_oci_manifest in rules_helm. + "@platforms//os:windows": ["@platforms//:incompatible"], + "//conditions:default": [], + }), + # Public for that build test. + visibility = ["//visibility:public"], +) diff --git a/tests/bzl_version/BUILD.bazel b/tests/bzl_version/BUILD.bazel index 81d9d55e..638733bf 100644 --- a/tests/bzl_version/BUILD.bazel +++ b/tests/bzl_version/BUILD.bazel @@ -4,7 +4,10 @@ load("//:version.bzl", "VERSION") go_test( name = "bzl_version_test", srcs = ["bzl_version_test.go"], - data = ["//:MODULE.bazel"], + data = [ + "//:MODULE.bazel", + "@rules_helm_img//:MODULE.bazel", + ], env = {"VERSION": VERSION}, deps = ["@rules_go//go/runfiles"], ) diff --git a/tests/bzl_version/bzl_version_test.go b/tests/bzl_version/bzl_version_test.go index 45505ea5..1d8c0711 100644 --- a/tests/bzl_version/bzl_version_test.go +++ b/tests/bzl_version/bzl_version_test.go @@ -3,15 +3,15 @@ package main import ( "errors" "os" - "reflect" + "regexp" "strings" "testing" "github.com/bazelbuild/rules_go/go/runfiles" ) -func parseModuleBazel() (string, error) { - path, err := runfiles.Rlocation("rules_helm/MODULE.bazel") +func readRunfile(rlocation string) (string, error) { + path, err := runfiles.Rlocation(rlocation) if err != nil { return "", err } @@ -20,9 +20,13 @@ func parseModuleBazel() (string, error) { if err != nil { return "", err } + return string(content), nil +} +// parseModuleVersion returns the version in the `module()` call of a MODULE.bazel file. +func parseModuleVersion(content string) (string, error) { var moduleFound bool = false - for _, line := range strings.Split(string(content), "\n") { + for _, line := range strings.Split(content, "\n") { text := strings.TrimRight(line, "\r") if moduleFound { if strings.HasSuffix(text, ")") { @@ -45,18 +49,46 @@ func parseModuleBazel() (string, error) { return "", errors.New("Failed to parse version from MODULE.bazel") } +// parseBazelDepVersion returns the version of a `bazel_dep()` call on a single line. +func parseBazelDepVersion(content string, name string) (string, error) { + re := regexp.MustCompile(`(?m)^bazel_dep\(name = "` + regexp.QuoteMeta(name) + `", version = "([^"]*)"`) + match := re.FindStringSubmatch(content) + if match == nil { + return "", errors.New("Failed to find a bazel_dep on " + name) + } + return match[1], nil +} + func TestVersionFiles(t *testing.T) { version, found := os.LookupEnv("VERSION") if !found { t.Fatal("Couldn't parse VERSION from environment.") } - module_bazel, err := parseModuleBazel() + rulesHelm, err := readRunfile("rules_helm/MODULE.bazel") if err != nil { t.Fatalf("Error reading file MODULE.bazel: %v", err) } + // `rules_helm_img` is released from the same tag, so it has the same version + // and requires exactly this version of `rules_helm`. + rulesHelmImg, err := readRunfile("rules_helm_img/MODULE.bazel") + if err != nil { + t.Fatalf("Error reading file modules/rules_helm_img/MODULE.bazel: %v", err) + } - if !reflect.DeepEqual(version, module_bazel) { - t.Fatalf("version.bzl (%s) != MODULE.bazel (%s)", version, module_bazel) + for _, check := range []struct { + description string + parse func() (string, error) + }{ + {"MODULE.bazel", func() (string, error) { return parseModuleVersion(rulesHelm) }}, + {"modules/rules_helm_img/MODULE.bazel", func() (string, error) { return parseModuleVersion(rulesHelmImg) }}, + {"the rules_helm dependency of modules/rules_helm_img/MODULE.bazel", func() (string, error) { return parseBazelDepVersion(rulesHelmImg, "rules_helm") }}, + } { + got, err := check.parse() + if err != nil { + t.Errorf("Error reading the version of %s: %v", check.description, err) + } else if got != version { + t.Errorf("version.bzl (%s) != %s (%s)", version, check.description, got) + } } } diff --git a/tests/helm_oci_manifest/BUILD.bazel b/tests/helm_oci_manifest/BUILD.bazel index 4d28a694..63c9fffc 100644 --- a/tests/helm_oci_manifest/BUILD.bazel +++ b/tests/helm_oci_manifest/BUILD.bazel @@ -1,8 +1,9 @@ +load("@bazel_skylib//rules:build_test.bzl", "build_test") load("@bazel_skylib//rules:write_file.bzl", "write_file") load("@rules_go//go:def.bzl", "go_test") +load("@rules_helm_img//:defs.bzl", "helm_oci_manifest") load("@rules_img//img:multi_deploy.bzl", "multi_deploy") load("//helm:defs.bzl", "helm_chart") -load("//helm:rules_img.bzl", "helm_oci_manifest") EXCLUDE_WINDOWS = select({ # As in //tests/with_image_deps_img. @@ -118,6 +119,15 @@ multi_deploy( target_compatible_with = EXCLUDE_WINDOWS, ) +# `//...` does not include `rules_helm_img`'s own packages, so this builds the +# target that its BCR presubmit builds, using only the dependencies that the +# module declares. +build_test( + name = "rules_helm_img_smoke_build_test", + target_compatible_with = EXCLUDE_WINDOWS, + targets = ["@rules_helm_img//smoke:chart_oci_manifest"], +) + # The `simple.helm_push_*.golden` files are what a real `helm push` of # `:simple` sends. To regenerate them after `:simple`'s .tgz changes, run # `crane registry serve --address localhost:5051`, set the .tgz mtime to the diff --git a/version.bzl b/version.bzl index 41922173..fd52a600 100644 --- a/version.bzl +++ b/version.bzl @@ -1,3 +1,6 @@ """ Version info for the `rules_helm` repository """ +# A release also sets this version in `MODULE.bazel` and in +# `modules/rules_helm_img/MODULE.bazel` (its `module()` version and its +# `rules_helm` dependency). `//tests/bzl_version` checks them. VERSION = "0.34.0"