Skip to content

Commit

Permalink
feat: Allow stampable repotags for oci_tarball (#185)
Browse files Browse the repository at this point in the history
Co-authored-by: Alex Eagle <[email protected]>
  • Loading branch information
josephglanville and alexeagle authored Apr 26, 2023
1 parent 14499d5 commit 82d5b6a
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 13 deletions.
2 changes: 1 addition & 1 deletion docs/tarball.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,6 @@ Passing anything other than oci_image to the image attribute will lead to build
| :------------- | :------------- | :------------- | :------------- | :------------- |
| <a id="oci_tarball-name"></a>name | A unique name for this target. | <a href="https://bazel.build/docs/build-ref.html#name">Name</a> | required | |
| <a id="oci_tarball-image"></a>image | Label of a directory containing an OCI layout, typically <code>oci_image</code> | <a href="https://bazel.build/docs/build-ref.html#labels">Label</a> | required | |
| <a id="oci_tarball-repotags"></a>repotags | List of repository+tags to apply to the loaded image | List of strings | required | |
| <a id="oci_tarball-repotags"></a>repotags | a file containing repotags, one per line. | <a href="https://bazel.build/docs/build-ref.html#labels">Label</a> | optional | None |


30 changes: 29 additions & 1 deletion oci/defs.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ load("//oci/private:structure_test.bzl", _structure_test = "structure_test")
load("@bazel_skylib//lib:types.bzl", "types")
load("@bazel_skylib//rules:write_file.bzl", "write_file")

oci_tarball = _oci_tarball
oci_tarball_rule = _oci_tarball
oci_image_rule = _oci_image
oci_image_index = _oci_image_index
oci_push_rule = _oci_push
Expand Down Expand Up @@ -82,3 +82,31 @@ def oci_push(name, repotags = None, **kwargs):
repotags = repotags,
**kwargs
)

def oci_tarball(name, repotags = None, **kwargs):
"""Macro wrapper around [oci_tarball_rule](#oci_tarball_rule).
Allows the repotags attribute to be a list of strings in addition to a text file.
Args:
name: name of resulting oci_tarball_rule
repotags: a list of repository:tag to specify when loading the image,
or a label of a file containing tags one-per-line.
See [stamped_tags](https://github.com/bazel-contrib/rules_oci/blob/main/examples/push/stamp_tags.bzl)
as one example of a way to produce such a file.
**kwargs: other named arguments to [oci_tarball_rule](#oci_tarball_rule).
"""
if types.is_list(repotags):
tags_label = "_{}_write_tags".format(name)
write_file(
name = tags_label,
out = "_{}.tags.txt".format(name),
content = repotags,
)
repotags = tags_label

oci_tarball_rule(
name = name,
repotags = repotags,
**kwargs
)
28 changes: 19 additions & 9 deletions oci/private/tarball.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,12 @@ Passing anything other than oci_image to the image attribute will lead to build

attrs = {
"image": attr.label(mandatory = True, allow_single_file = True, doc = "Label of a directory containing an OCI layout, typically `oci_image`"),
"repotags": attr.string_list(mandatory = True, doc = "List of repository+tags to apply to the loaded image"),
"repotags": attr.label(
doc = """\
a file containing repotags, one per line.
""",
allow_single_file = [".txt"],
),
"_tarball_sh": attr.label(allow_single_file = True, default = "//oci/private:tarball.sh.tpl"),
"_build_tar": attr.label(
default = Label("@rules_pkg//pkg/private/tar:build_tar"),
Expand Down Expand Up @@ -75,22 +80,27 @@ def _tarball_impl(ctx):

yq_bin = ctx.toolchains["@aspect_bazel_lib//lib:yq_toolchain_type"].yqinfo.bin
executable = ctx.actions.declare_file("{}/tarball.sh".format(ctx.label.name))

substitutions = {
"{{yq}}": yq_bin.path,
"{{image_dir}}": image.path,
"{{blobs_dir}}": blobs.path,
"{{manifest_path}}": manifest.path,
}

if ctx.attr.repotags:
substitutions["{{tags}}"] = ctx.file.repotags.path

ctx.actions.expand_template(
template = ctx.file._tarball_sh,
output = executable,
is_executable = True,
substitutions = {
"{{yq}}": yq_bin.path,
"{{image_dir}}": image.path,
"{{blobs_dir}}": blobs.path,
"{{manifest_path}}": manifest.path,
"{{repotags}}": json.encode(ctx.attr.repotags),
},
substitutions = substitutions,
)

ctx.actions.run(
executable = executable,
inputs = [image],
inputs = [image, ctx.file.repotags],
outputs = [manifest, blobs],
tools = [yq_bin],
mnemonic = "OCITarball",
Expand Down
9 changes: 7 additions & 2 deletions oci/private/tarball.sh.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,14 @@ set -o pipefail -o errexit -o nounset
readonly YQ="{{yq}}"
readonly IMAGE_DIR="{{image_dir}}"
readonly BLOBS_DIR="{{blobs_dir}}"
readonly REPOTAGS='{{repotags}}'
readonly TAGS_FILE="{{tags}}"
readonly TARBALL_MANIFEST_PATH="{{manifest_path}}"

REPOTAGS=()
# read repotags file as array and prepend it to REPOTAGS array.
IFS=$'\n' REPOTAGSFILE=($(cat "$TAGS_FILE"))
REPOTAGS=(${REPOTAGSFILE[@]+"${REPOTAGSFILE[@]}"} ${REPOTAGS[@]+"${REPOTAGS[@]}"})

MANIFEST_DIGEST=$(${YQ} eval '.manifests[0].digest | sub(":"; "/")' "${IMAGE_DIR}/index.json")
MANIFEST_BLOB_PATH="${IMAGE_DIR}/blobs/${MANIFEST_DIGEST}"

Expand All @@ -23,7 +28,7 @@ for LAYER in $(${YQ} ".[]" <<< $LAYERS); do
done

config="blobs/${CONFIG_DIGEST}" \
repotags="${REPOTAGS}" \
repotags="${REPOTAGS:-[]}" \
layers="${LAYERS}" \
"${YQ}" eval \
--null-input '.[0] = {"Config": env(config), "RepoTags": env(repotags), "Layers": env(layers) | map( "blobs/" + . + ".tar.gz") }' \
Expand Down

0 comments on commit 82d5b6a

Please sign in to comment.