Repository navigation
Conversation
c286b80 to
ab3e11c
Compare
helm_deploy so rules_img's multi_deploy can push a charthelm_oci_manifest so rules_img's multi_deploy can push a chart
|
CI failures are 429's from ECR |
ab3e11c to
197c5e9
Compare
|
@abrisco I moved back into draft status - I think it would be better to wait on a rules_img release with rules_img#805 in, then we have byte-identical manifests from day 1. Will move back out of draft when that happens |
197c5e9 to
3d6e739
Compare
`helm_push` cannot provide `DeployInfo`, so a chart could not be one of a `multi_deploy`'s operations. `helm_oci_manifest` in the new helm/rules_img.bzl describes the chart as the OCI artifact `helm push` creates: an `image_manifest` with the Helm config media type, the chart .tgz as its only layer, the annotations `helm push` writes, and a push spec for `<registry_url>/<chart name>:<chart version>`. The manifest sets `omit_media_type`, because `helm push` writes no top-level `mediaType`. The pushed manifest is then byte-identical to the `helm push` one, and its digest is the one `helm_oci_digest` gives. Move the chart-reading and annotation code from oci_digest into a shared ociartifact package, add an oci_parts tool for the rules_img inputs, and make rules_img a non-dev dependency at 0.3.24, the first release with `omit_media_type`.
3d6e739 to
d289818
Compare
|
@abrisco rules_img made a release with our needed changes in to make the manifest byte-identical so moved back out of draft |
abrisco
left a comment
There was a problem hiding this comment.
Sorry for the delay here, I'll take a look this weekend!
| 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") |
There was a problem hiding this comment.
Is there a way to avoid this being a mandatory dependency?
There was a problem hiding this comment.
Not with the existing macro in this module. Bazel doesn't have any concept of optional deps.
Few options that I can think of:
- Separate
rules_helm_imgmodule in this repo (e.g inmodule/rules_helm_img). Needs a second BCR module and release workflow change. Looks likerules_imgpublishedimg_toollike this. - Have the caller pass the rules in. Should work but a bit clunky and a weird API
- Ship just
helm_oci_partsand then document 30 or so lines or rules_img wiring to copy. Also clunky.
If we really want to avoid this dep in the root module, I think 1. is probably the least worst option.
LMK what you think!
Closes #276.
multi_deploypushes many images from onebazel run(concurrently in later versions), but each chart still needs its ownbazel runofhelm_push.helm_pushcannot provideDeployInfo, becauseDeployInfodescribes an image push or load, not a command to run. This PR describes the chart as the OCI artifacthelm pushcreates, and letsrules_imgpush that.Digest
The pushed manifest is byte-identical to the one
helm pushcreates, so its digest is the onehelm_oci_digestgives. Fortests/helm_oci_manifest:simple,helm_oci_manifest,helm_oci_digestandhelm push(Helm 3.16.3 and 4.3.1) all givesha256:b6137ff1….rules_imgwrites a top-levelmediaTypethathelm pushdoes not, sohelm_oci_manifestsetsomit_media_type(rules_img#805, released in 0.3.24) to leave it out.Usage
The target is an
image_manifestwith the Helm config media type, the chart.tgzas its only layer, the annotationshelm pushwrites, and animage_push_specfor<registry_url>/<chart name>:<chart version>(+in the version becomes_, as Helm does). It is built fromrules_img's public rules only.helm_chartdoes not create it; it is opt-in through the newhelm/rules_img.bzl.Not supported, and documented in the macro:
push_cmdand plugins such ascm-push,HELM_REGISTRY_USERNAME/HELM_REGISTRY_PASSWORDlogin (credentials come fromrules_img's Docker config and credential helpers),include_images, and charts fromhelm_import(their metadata has nocreatedvalue).Two issues a user might otherwise hit:
rules_imgexpands Go templates in annotation values, so{{in chart metadata is escaped; and the manifest setssoci = "disabled", since a SOCI index would add an annotationhelm pushdoes not write.Dependency change
rules_imgis now a non-dev dependency at 0.3.24, the first release withomit_media_type. 0.3.14 is the first version that readsannotations_fileas a JSON object with values verbatim; earlier versions splitKEY=VALUElines and trim them. 0.3.18 addsmulti_deploy --sink, which the offline test uses.omit_platform(0.3.21) is not needed: it changes only the manifest descriptor, and the pushed bytes on 0.3.24 are identical with and without it.This has a cost for consumers who never load
helm/rules_img.bzl. In a throwaway consumer module with onehelm_chart, built from an empty repository cache, the change addedrules_img+(about 1.3 MB of source),hermetic_launcher+(164 KB) and theimg_toolchainhub repo (20 KB) to the fetched repositories, because both modules register toolchains. Noimgtool binaries were fetched. Module resolution also raisesrules_imgto at least 0.3.24,bazel_featuresto 1.47.0 andpackage_metadatato 0.0.10, and addshermetic_launcher0.0.17.Moving to 0.3.17 or later broke
tests/with_image_deps_imgon Linux, becauseimg_pullstarted making:imagean alias. #304 fixed that before this PR.Implementation
The chart-reading and annotation code moves out of
oci_digest.gointohelm/private/oci_digest/ociartifact, unchanged.oci_digestkeeps its output (thesimpleandcreateddigest goldens pass unchanged), and a newoci_partstool writes the config blob, annotations, tag and destination forrules_img.Testing
tests/helm_oci_manifestruns eachmulti_deploywith--sink oci:<dir>, offline, and checks the Helm config and layer media types, that the layer is the chart.tgz, that the config blob and manifest equal goldens from a realhelm push, that each manifest's digest equalshelm_oci_digest's, the reference for a trailing-slashregistry_urland forregistry_url_file, a{{description and a+version. It also passes with SOCI forced on, and fails on every chart's digest withomit_media_type = False.ociartifactandoci_parts.bazel test //...on macOS with Bazel 9.3.1 (with and without--config=strict) and with Bazel 7.7.2 and--config=strict, asci-min-bazelruns it: 68 pass, 3 skipped (the Linux-onlywith_image_deps_imgtests).bazel run //tests/helm_oci_manifest:deploy, and pushed the same.tgzfiles withhelm pushfrom Helm 3.16.3 and 4.3.1. Each chart got the same digest from all three pushes, equal to itshelm_oci_digestoutput.helm pull,helm show chartandhelm templateaccept the pushed charts with both Helm versions, and the pulled.tgzis byte-identical to the built one.