Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions helm/defs.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ load(
":helm_package.bzl",
_helm_package = "helm_package",
)
load(
":helm_package_info.bzl",
_HelmPackageInfo = "HelmPackageInfo",
)
load(
":helm_plugin.bzl",
_helm_plugin = "helm_plugin",
Expand All @@ -48,10 +52,6 @@ load(
":helm_toolchain.bzl",
_helm_toolchain = "helm_toolchain",
)
load(
":providers.bzl",
_HelmPackageInfo = "HelmPackageInfo",
)

chart_content = _chart_content
chart_file = _chart_file
Expand Down
8 changes: 8 additions & 0 deletions helm/helm_package_info.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
"""# HelmPackageInfo provider"""

load(
"//helm/private:providers.bzl",
_HelmPackageInfo = "HelmPackageInfo",
)

HelmPackageInfo = _HelmPackageInfo
2 changes: 1 addition & 1 deletion helm/private/helm_import.bzl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""Helm rules for managing external dependencies"""

load("//helm:providers.bzl", "HelmPackageInfo")
load(":helm_import_authn.bzl", "authn")
load(":providers.bzl", "HelmPackageInfo")

def _helm_import_impl(ctx):
metadata_output = ctx.actions.declare_file(ctx.label.name + ".metadata.json")
Expand Down
2 changes: 1 addition & 1 deletion helm/private/helm_install.bzl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""Helm rules"""

load("//helm:providers.bzl", "HelmPackageInfo")
load(":helm_utils.bzl", "is_stamping_enabled", "rlocationpath", "symlink")
load(":providers.bzl", "HelmPackageInfo")

HelmInstallInfo = provider(
doc = "Info about a helm installer.",
Expand Down
2 changes: 1 addition & 1 deletion helm/private/helm_lint.bzl
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
"""Helm rules"""

load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")
load("//helm:providers.bzl", "HelmPackageInfo")
load(":helm_utils.bzl", "rlocationpath", "symlink")
load(":providers.bzl", "HelmPackageInfo")

def _helm_lint_aspect_impl(target, ctx):
if HelmPackageInfo not in target:
Expand Down
133 changes: 16 additions & 117 deletions helm/private/helm_package.bzl
Original file line number Diff line number Diff line change
@@ -1,110 +1,9 @@
"""Helm rules"""

load("//helm:providers.bzl", "HelmPackageInfo")
load("//helm/private:helm_utils.bzl", "is_stamping_enabled")
load("//helm/private:json_to_yaml.bzl", "json_to_yaml")

OciPushRepositoryInfo = provider(
doc = "Repository and image information for a given oci_push or image_push target",
fields = {
"manifest_file": "File (optional): The manifest JSON file for rules_img images",
"oci_layout": "File (optional): The OCI layout directory for rules_oci images (contains index.json)",
"remote_tags_file": "File (optional): The file containing remote tags (one per line) used for the push target",
"repository_file": "File: The file containing the repository path for the push target",
},
)

def _oci_push_repository_aspect_impl(target, ctx):
# Handle rules_img image_push
if hasattr(ctx.rule.attr, "registry") and ctx.rule.attr.registry:
# rules_img uses registry + repository attributes
if hasattr(ctx.rule.attr, "repository") and ctx.rule.attr.repository:
# Combine registry and repository for full repository path
registry = ctx.rule.attr.registry
repo = ctx.rule.attr.repository

# Remove protocol from registry if present
registry_clean = registry.replace("https://", "").replace("http://", "")
full_repo = "{}/{}".format(registry_clean, repo)

output = ctx.actions.declare_file("{}.rules_helm.repository.txt".format(target.label.name))
ctx.actions.write(
output = output,
content = full_repo,
)
else:
fail("image_push target {} must have a `repository` attribute".format(target.label))

# rules_img image_push has 'image' attribute pointing to image_manifest
if not hasattr(ctx.rule.attr, "image") or not ctx.rule.attr.image:
fail("image_push target {} must have an `image` attribute".format(target.label))

# Get the image file from the image attribute
image_file = None
if hasattr(ctx.rule.files, "image") and ctx.rule.files.image:
image_file = ctx.rule.files.image[0]
elif hasattr(ctx.rule.file, "image") and ctx.rule.file.image:
image_file = ctx.rule.file.image
else:
fail("image_push target {} `image` attribute must provide files".format(target.label))

# rules_img uses tags attribute (list of strings) instead of remote_tags file
remote_tags_file = None
if hasattr(ctx.rule.attr, "tags") and ctx.rule.attr.tags:
# Write tags to a file for consistency with rules_oci
tags_output = ctx.actions.declare_file("{}.rules_helm.tags.txt".format(target.label.name))
ctx.actions.write(
output = tags_output,
content = "\n".join(ctx.rule.attr.tags),
)
remote_tags_file = tags_output

return [OciPushRepositoryInfo(
repository_file = output,
manifest_file = image_file,
oci_layout = None,
remote_tags_file = remote_tags_file,
)]

# Handle rules_oci oci_push
if hasattr(ctx.rule.attr, "repository") and ctx.rule.attr.repository:
output = ctx.actions.declare_file("{}.rules_helm.repository.txt".format(target.label.name))
ctx.actions.write(
output = output,
content = ctx.rule.attr.repository,
)
elif hasattr(ctx.rule.file, "repository_file") and ctx.rule.file.repository_file:
output = ctx.rule.file.repository_file
else:
fail("oci_push/image_push target {} must have a `repository` attribute or a `repository_file` file".format(
target.label,
))

if not hasattr(ctx.rule.file, "image"):
fail("oci_push/image_push target {} must have an `image` attribute".format(
target.label,
))

remote_tags_file = None
if hasattr(ctx.rule.file, "remote_tags") and ctx.rule.file.remote_tags:
remote_tags_file = ctx.rule.file.remote_tags

return [OciPushRepositoryInfo(
repository_file = output,
oci_layout = ctx.rule.file.image,
manifest_file = None,
remote_tags_file = remote_tags_file,
)]

# This aspect exists because rules_oci and rules_img don't provide a provider
# that cleanly publishes this information but for the helm rules, it's
# absolutely necessary that an image's repository and digest are knowable.
# If rules_oci/rules_img decide to define their own provider for this (which they should)
# then this should be deleted in favor of that.
_oci_push_repository_aspect = aspect(
doc = "Provides the repository and image_root for a given oci_push or image_push target",
implementation = _oci_push_repository_aspect_impl,
)
load(":image_utils.bzl", "ImagePushRepositoryInfo", "image_push_repository_aspect")
load(":providers.bzl", "HelmPackageInfo")

def _rlocationpath(file, workspace_name):
if file.short_path.startswith("../"):
Expand Down Expand Up @@ -206,31 +105,31 @@ def _helm_package_impl(ctx):
image_inputs = []
single_image_manifests = []
for image in ctx.attr.images:
image_inputs.append(image[OciPushRepositoryInfo].repository_file)
image_inputs.append(image[ImagePushRepositoryInfo].repository_file)

# Add the appropriate image file based on format
if image[OciPushRepositoryInfo].oci_layout:
image_inputs.append(image[OciPushRepositoryInfo].oci_layout)
elif image[OciPushRepositoryInfo].manifest_file:
image_inputs.append(image[OciPushRepositoryInfo].manifest_file)
if image[ImagePushRepositoryInfo].oci_layout:
image_inputs.append(image[ImagePushRepositoryInfo].oci_layout)
elif image[ImagePushRepositoryInfo].manifest_file:
image_inputs.append(image[ImagePushRepositoryInfo].manifest_file)
single_image_manifest = ctx.actions.declare_file("{}/{}".format(
ctx.label.name,
str(image.label).strip("@").replace("/", "_").replace(":", "_") + ".image_manifest",
))
push_info = image[DefaultInfo]

remote_tags_path = None
if image[OciPushRepositoryInfo].remote_tags_file:
remote_tags_path = image[OciPushRepositoryInfo].remote_tags_file.path
image_inputs.append(image[OciPushRepositoryInfo].remote_tags_file)
if image[ImagePushRepositoryInfo].remote_tags_file:
remote_tags_path = image[ImagePushRepositoryInfo].remote_tags_file.path
image_inputs.append(image[ImagePushRepositoryInfo].remote_tags_file)

# Set mutually exclusive fields based on image format
oci_layout_dir = None
manifest_file = None
if image[OciPushRepositoryInfo].oci_layout:
oci_layout_dir = image[OciPushRepositoryInfo].oci_layout.path
elif image[OciPushRepositoryInfo].manifest_file:
manifest_file = image[OciPushRepositoryInfo].manifest_file.path
if image[ImagePushRepositoryInfo].oci_layout:
oci_layout_dir = image[ImagePushRepositoryInfo].oci_layout.path
elif image[ImagePushRepositoryInfo].manifest_file:
manifest_file = image[ImagePushRepositoryInfo].manifest_file.path
else:
fail("Unable to determine repository info for {}".format(image.label))

Expand All @@ -239,7 +138,7 @@ def _helm_package_impl(ctx):
content = json.encode_indent(
struct(
label = str(image.label),
repository_path = image[OciPushRepositoryInfo].repository_file.path,
repository_path = image[ImagePushRepositoryInfo].repository_file.path,
oci_layout_dir = oci_layout_dir,
manifest_file = manifest_file,
remote_tags_path = remote_tags_path,
Expand Down Expand Up @@ -332,7 +231,7 @@ helm_package = rule(
[oci_push](https://github.com/bazel-contrib/rules_oci/blob/main/docs/push.md#oci_push_rule-remote_tags) or \
[image_push](https://github.com/bazel-contrib/rules_img) \
targets.""",
aspects = [_oci_push_repository_aspect],
aspects = [image_push_repository_aspect],
),
"schema": attr.label(
doc = "The `values.schema.json` file for the current package.",
Expand Down
2 changes: 1 addition & 1 deletion helm/private/helm_registry.bzl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""Helm rules"""

load("//helm:providers.bzl", "HelmPackageInfo")
load(":helm_utils.bzl", "rlocationpath", "symlink")
load(":providers.bzl", "HelmPackageInfo")

def _get_image_push_commands(ctx, pkg_info):
image_pushers = []
Expand Down
2 changes: 1 addition & 1 deletion helm/private/helm_template.bzl
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
"""Helm rules"""

load("//helm:providers.bzl", "HelmPackageInfo")
load(":helm_install.bzl", "HelmInstallInfo")
load(":helm_utils.bzl", "rlocationpath", "symlink")
load(":providers.bzl", "HelmPackageInfo")

def _helm_template_test_impl(ctx):
toolchain = ctx.toolchains[Label("//helm:toolchain_type")]
Expand Down
103 changes: 103 additions & 0 deletions helm/private/image_utils.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
"""Utilities for container images"""

ImagePushRepositoryInfo = provider(
doc = "Repository and image information for a given oci_push or image_push target",
fields = {
"manifest_file": "File (optional): The manifest JSON file for rules_img images",
"oci_layout": "File (optional): The OCI layout directory for rules_oci images (contains index.json)",
"remote_tags_file": "File (optional): The file containing remote tags (one per line) used for the push target",
"repository_file": "File: The file containing the repository path for the push target",
},
)

def _image_push_repository_aspect_impl(target, ctx):
# Handle rules_img image_push
if hasattr(ctx.rule.attr, "registry") and ctx.rule.attr.registry:
# rules_img uses registry + repository attributes
if hasattr(ctx.rule.attr, "repository") and ctx.rule.attr.repository:
# Combine registry and repository for full repository path
registry = ctx.rule.attr.registry
repo = ctx.rule.attr.repository

# Remove protocol from registry if present
registry_clean = registry.replace("https://", "").replace("http://", "")
full_repo = "{}/{}".format(registry_clean, repo)

output = ctx.actions.declare_file("{}.rules_helm.repository.txt".format(target.label.name))
ctx.actions.write(
output = output,
content = full_repo,
)
else:
fail("image_push target {} must have a `repository` attribute".format(target.label))

# rules_img image_push has 'image' attribute pointing to image_manifest
if not hasattr(ctx.rule.attr, "image") or not ctx.rule.attr.image:
fail("image_push target {} must have an `image` attribute".format(target.label))

# Get the image file from the image attribute
image_file = None
if hasattr(ctx.rule.files, "image") and ctx.rule.files.image:
image_file = ctx.rule.files.image[0]
elif hasattr(ctx.rule.file, "image") and ctx.rule.file.image:
image_file = ctx.rule.file.image
else:
fail("image_push target {} `image` attribute must provide files".format(target.label))

# rules_img uses tags attribute (list of strings) instead of remote_tags file
remote_tags_file = None
if hasattr(ctx.rule.attr, "tags") and ctx.rule.attr.tags:
# Write tags to a file for consistency with rules_oci
tags_output = ctx.actions.declare_file("{}.rules_helm.tags.txt".format(target.label.name))
ctx.actions.write(
output = tags_output,
content = "\n".join(ctx.rule.attr.tags),
)
remote_tags_file = tags_output

return [ImagePushRepositoryInfo(
repository_file = output,
manifest_file = image_file,
oci_layout = None,
remote_tags_file = remote_tags_file,
)]

# Handle rules_oci oci_push
if hasattr(ctx.rule.attr, "repository") and ctx.rule.attr.repository:
output = ctx.actions.declare_file("{}.rules_helm.repository.txt".format(target.label.name))
ctx.actions.write(
output = output,
content = ctx.rule.attr.repository,
)
elif hasattr(ctx.rule.file, "repository_file") and ctx.rule.file.repository_file:
output = ctx.rule.file.repository_file
else:
fail("oci_push/image_push target {} must have a `repository` attribute or a `repository_file` file".format(
target.label,
))

if not hasattr(ctx.rule.file, "image"):
fail("oci_push/image_push target {} must have an `image` attribute".format(
target.label,
))

remote_tags_file = None
if hasattr(ctx.rule.file, "remote_tags") and ctx.rule.file.remote_tags:
remote_tags_file = ctx.rule.file.remote_tags

return [ImagePushRepositoryInfo(
repository_file = output,
oci_layout = ctx.rule.file.image,
manifest_file = None,
remote_tags_file = remote_tags_file,
)]

# This aspect exists because rules_oci and rules_img don't provide a provider
# that cleanly publishes this information but for the helm rules, it's
# absolutely necessary that an image's repository and digest are knowable.
# If rules_oci/rules_img decide to define their own provider for this (which they should)
# then this should be deleted in favor of that.
image_push_repository_aspect = aspect(
doc = "Provides the repository and image_root for a given oci_push or image_push target",
implementation = _image_push_repository_aspect_impl,
)
File renamed without changes.
2 changes: 1 addition & 1 deletion helm/private/repositories.bzl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""Helm dependencies"""

_HELM_TOOLCHAIN_BUILD_CONTENT = """\
load("@rules_helm//helm:toolchain.bzl", "helm_toolchain")
load("@rules_helm//helm:helm_toolchain.bzl", "helm_toolchain")
package(default_visibility = ["//visibility:public"])
Expand Down
8 changes: 0 additions & 8 deletions helm/toolchain.bzl

This file was deleted.

2 changes: 1 addition & 1 deletion tests/test_defs.bzl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Test rules and utiltiies"""

load("//helm:providers.bzl", "HelmPackageInfo")
load("//helm:helm_package_info.bzl", "HelmPackageInfo")

def _rlocationpath(file, workspace_name):
if file.short_path.startswith("../"):
Expand Down
2 changes: 1 addition & 1 deletion tests/version_stamp/version_stamp_unit_test.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
load("@bazel_skylib//rules:diff_test.bzl", "diff_test")
load("@bazel_skylib//rules:write_file.bzl", "write_file")
load("//helm:defs.bzl", "helm_lint_test", "helm_package", "helm_template_test")
load("//helm:providers.bzl", "HelmPackageInfo")
load("//helm:helm_package_info.bzl", "HelmPackageInfo")

def _helm_pkg_metadata_impl(ctx):
return DefaultInfo(
Expand Down