load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") def _helm_import_impl(ctx): if ctx.attr.url.startswith("oci://"): # Use the python script to pull output_file = "chart.tgz" # We need a python interpreter. We'll assume 'python3' is in the path for now. # In a strict build, we should probably use the python toolchain, but that's hard in a repo rule. # Locate the helper script. # Since this is a repo rule, we can't easily access the source tree files unless we use `exports_files` and `ctx.path`. # But `tools/helm_pull.py` is in the main repo. # We can copy the content of the script into the rule or the repo. # Let's assume the script content is passed or available. # Actually, reading it from the label is cleaner if possible. script_path = ctx.path(Label("//tools:helm_pull.py")) cmd = [ "python3", script_path, "--url", ctx.attr.url, "--version", ctx.attr.version, "--output", output_file, ] if ctx.attr.sha256: cmd.extend(["--digest", ctx.attr.sha256]) result = ctx.execute(cmd) if result.return_code != 0: fail("Failed to pull OCI chart: \n%s\n%s" % (result.stdout, result.stderr)) # Extract ctx.extract(output_file, stripPrefix = ctx.attr.strip_prefix) ctx.delete(output_file) else: # HTTP fallback (simulating http_archive logic partially) ctx.download_and_extract( url = ctx.attr.url, sha256 = ctx.attr.sha256, stripPrefix = ctx.attr.strip_prefix, ) # Build file ctx.file("BUILD.bazel", ctx.attr.build_file_content) helm_import = repository_rule( implementation = _helm_import_impl, attrs = { "url": attr.string(mandatory = True), "version": attr.string(), "sha256": attr.string(), "strip_prefix": attr.string(), "build_file_content": attr.string(), }, ) def _helm_deps_impl(ctx): # 1. Read the lockfile lockfile_content = ctx.read(ctx.path(Label("//third_party/helm:chartfile.lock.json"))) lock = json.decode(lockfile_content) # 2. Iterate over charts for name, info in lock.get("charts", {}).items(): # name is like "grafana/grafana" # repo_name will be "helm_grafana_grafana" repo_name = "helm_" + name.replace("/", "_").replace("-", "_") chart_name = name.split("/")[1] helm_import( name = repo_name, url = info["url"], version = info.get("version", ""), # Version needed for OCI sha256 = info["digest"], strip_prefix = chart_name, build_file_content = """ filegroup( name = "chart", srcs = glob(["**"]), visibility = ["//visibility:public"], ) """, ) helm_deps = module_extension( implementation = _helm_deps_impl, )