From 31acd5efde626c7926a22cc0e7b237840e1e5607 Mon Sep 17 00:00:00 2001 From: thesayyn Date: Tue, 7 May 2024 11:48:12 -0700 Subject: [PATCH] feat: implement tars symlinks --- MODULE.bazel | 1 + oci/dependencies.bzl | 7 +++++++ oci/private/image.bzl | 14 +++++++++++++- oci/private/image.sh | 8 +++++++- oci/repositories.bzl | 2 ++ 5 files changed, 30 insertions(+), 2 deletions(-) diff --git a/MODULE.bazel b/MODULE.bazel index 56a53157..02253580 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -9,6 +9,7 @@ module( bazel_dep(name = "aspect_bazel_lib", version = "2.7.2") bazel_dep(name = "bazel_skylib", version = "1.5.0") bazel_dep(name = "platforms", version = "0.0.8") +bazel_dep(name = "bazel_features", version = "1.10.0") oci = use_extension("//oci:extensions.bzl", "oci") oci.toolchains() diff --git a/oci/dependencies.bzl b/oci/dependencies.bzl index 28208cf7..c929428a 100644 --- a/oci/dependencies.bzl +++ b/oci/dependencies.bzl @@ -26,3 +26,10 @@ def rules_oci_dependencies(): strip_prefix = "bazel-lib-2.7.2", url = "https://github.com/aspect-build/bazel-lib/releases/download/v2.7.2/bazel-lib-v2.7.2.tar.gz", ) + + http_archive( + name = "bazel_features", + sha256 = "95fb3cfd11466b4cad6565e3647a76f89886d875556a4b827c021525cb2482bb", + strip_prefix = "bazel_features-1.10.0", + url = "https://github.com/bazel-contrib/bazel_features/releases/download/v1.10.0/bazel_features-v1.10.0.tar.gz", + ) diff --git a/oci/private/image.bzl b/oci/private/image.bzl index 6ec0b72e..867d5153 100644 --- a/oci/private/image.bzl +++ b/oci/private/image.bzl @@ -1,5 +1,6 @@ "Implementation details for image rule" +load("@bazel_features//:features.bzl", "bazel_features") load("//oci/private:util.bzl", "util") _ACCEPTED_TAR_EXTENSIONS = [ @@ -139,6 +140,8 @@ def _oci_image_impl(ctx): output = ctx.actions.declare_directory(ctx.label.name) + use_symlinks = bazel_features.rules.permits_treeartifact_uplevel_symlinks + # create the image builder builder = ctx.actions.declare_file("image_%s.sh" % ctx.label.name) ctx.actions.expand_template( @@ -150,10 +153,12 @@ def _oci_image_impl(ctx): "{{jq_path}}": jq.jqinfo.bin.dirname, "{{coreutils_path}}": coreutils.coreutils_info.bin.dirname, "{{output}}": output.path, + "{{treeartifact_symlinks}}": str(int(use_symlinks)), }, ) - inputs = [builder] + ctx.files.tars + inputs = [builder] + transitive_inputs = [] args = ctx.actions.args() @@ -165,6 +170,12 @@ def _oci_image_impl(ctx): # create a scratch base image with given os/arch[/variant] args.add(_platform_str(ctx.attr.os, ctx.attr.architecture, ctx.attr.variant), format = "--scratch=%s") + # If tree artifact symlinks are supported just add tars into runfiles. + if use_symlinks: + transitive_inputs = transitive_inputs + ctx.files.tars + else: + inputs = inputs + ctx.files.tars + # add layers for (i, layer) in enumerate(ctx.files.tars): descriptor = _calculate_descriptor(ctx, i, layer, zstd, jq, coreutils, regctl) @@ -233,6 +244,7 @@ def _oci_image_impl(ctx): return [ DefaultInfo( files = depset([output]), + runfiles = ctx.runfiles(transitive_inputs), ), ] diff --git a/oci/private/image.sh b/oci/private/image.sh index e5e4e6b8..87823a7e 100644 --- a/oci/private/image.sh +++ b/oci/private/image.sh @@ -7,6 +7,7 @@ PATH="{{regctl_path}}:$PATH" PATH="{{coreutils_path}}:$PATH" # Constants +readonly USE_TREEARTIFACT_SYMLINKS="{{treeartifact_symlinks}}" readonly OUTPUT="{{output}}" readonly REF="ocidir://$OUTPUT:intermediate" # shellcheck disable=SC2016 @@ -96,7 +97,12 @@ function add_layer() { local digest_path= digest_path="$(jq -r '.digest | sub(":"; "/")' <<< "$desc")" - coreutils cat "$path" > "$OUTPUT/blobs/$digest_path" + if [[ "$USE_TREEARTIFACT_SYMLINKS" == "1" ]]; then + relative=$(coreutils realpath --relative-to="$OUTPUT/blobs/sha256" "$path" --no-symlinks) + coreutils ln -s "$relative" "$OUTPUT/blobs/$digest_path" + else + coreutils cat "$path" > "$OUTPUT/blobs/$digest_path" + fi } CONFIG="{}" diff --git a/oci/repositories.bzl b/oci/repositories.bzl index e0c7ff45..658db259 100644 --- a/oci/repositories.bzl +++ b/oci/repositories.bzl @@ -8,6 +8,7 @@ load( "register_tar_toolchains", "register_zstd_toolchains", ) +load("@bazel_features//:deps.bzl", "bazel_features_deps") load("//oci/private:toolchains_repo.bzl", "PLATFORMS", "toolchains_repo") load("//oci/private:versions.bzl", "CRANE_VERSIONS", "REGCTL_VERSIONS") @@ -100,6 +101,7 @@ def oci_register_toolchains(name, register = True): register: whether to call through to native.register_toolchains. Should be True for WORKSPACE users, but false when used under bzlmod extension """ + bazel_features_deps() register_jq_toolchains(register = register) register_tar_toolchains(register = register) register_coreutils_toolchains(register = register)