diff --git a/docs/docs.md b/docs/docs.md
index 959693b..3a177b2 100644
--- a/docs/docs.md
+++ b/docs/docs.md
@@ -102,7 +102,7 @@ oci_pull(name, digest
-oci_push(name, headers, manifest, registry, repository, tag, x_meta_headers)
+oci_push(name, headers, manifest, registry, repository, stamp, tag, x_meta_headers)
@@ -119,7 +119,8 @@ oci_push(name, headers<
| manifest | A manifest to push to a registry. If an OCILayout index, then push all artifacts with a 'org.opencontainers.image.ref.name' annotation. | Label | optional | None |
| registry | A registry host to push to, if not present consult the toolchain. | String | optional | "" |
| repository | A repository to push to, if not present consult the toolchain. | String | optional | "" |
-| tag | (optional) A tag to include in the target reference. This will not be included on child images." | String | optional | "" |
+| stamp | Whether to encode build information into the output. Possible values:
- stamp = 1
: Always stamp the build information into the output, even in [--nostamp](https://docs.bazel.build/versions/main/user-manual.html#flag--stamp) builds. This setting should be avoided, since it is non-deterministic. It potentially causes remote cache misses for the target and any downstream actions that depend on the result. - stamp = 0
: Never stamp, instead replace build information by constant values. This gives good build result caching. - stamp = -1
: Embedding of build information is controlled by the [--[no]stamp](https://docs.bazel.build/versions/main/user-manual.html#flag--stamp) flag. Stamped targets are not rebuilt unless their dependencies change. | Integer | optional | -1 |
+| tag | (optional) A tag to include in the target reference. This will not be included on child images.
Subject to [$(location)](https://bazel.build/reference/be/make-variables#predefined_label_variables) and ["Make variable"](https://bazel.build/reference/be/make-variabmes) substitution.
**Stamping**
You can use values produced by the workspace status command in your tag. To do this write a script that prints key-value pairs separated by spaces, e.g.
sh #!/usr/bin/env bash echo "STABLE_KEY1 VALUE1" echo "STABLE_KEY2 VALUE2"
tag
using curly braces,python oci_push( name = "push", tag = "v1.0-{STABLE_KEY1}", )
| String | optional | "" |
| x_meta_headers | (optional) A list of key/values to to be sent to the registry as headers with an X-Meta- prefix. | Dictionary: String -> String | optional | {} |
diff --git a/oci/BUILD.bazel b/oci/BUILD.bazel
index 4268ab9..6443160 100755
--- a/oci/BUILD.bazel
+++ b/oci/BUILD.bazel
@@ -69,6 +69,7 @@ bzl_library(
srcs = ["push.bzl"],
visibility = ["//visibility:public"],
deps = [
+ "@aspect_bazel_lib//lib:stamping",
"@com_github_datadog_rules_oci//oci:debug_flag",
"@com_github_datadog_rules_oci//oci:providers",
],
diff --git a/oci/providers.bzl b/oci/providers.bzl
index 4854416..8057d9a 100755
--- a/oci/providers.bzl
+++ b/oci/providers.bzl
@@ -4,6 +4,7 @@ OCIReferenceInfo = provider(
"registry": "the URI where the artifact is stored",
"repository": "a namespace for an artifact",
"tag": "a organizational reference within a repository",
+ "tag_file": "a file containing the organizational reference within a repository",
"digest": "a file containing the digest of the artifact",
},
)
diff --git a/oci/push.bzl b/oci/push.bzl
index 9bd933b..78844e5 100755
--- a/oci/push.bzl
+++ b/oci/push.bzl
@@ -1,3 +1,4 @@
+load("@aspect_bazel_lib//lib:stamping.bzl", "STAMP_ATTRS", "maybe_stamp")
load("@com_github_datadog_rules_oci//oci:providers.bzl", "OCIDescriptor", "OCILayout", "OCIReferenceInfo")
load("@com_github_datadog_rules_oci//oci:debug_flag.bzl", "DebugInfo")
@@ -11,7 +12,54 @@ def _oci_push_impl(ctx):
repository = ctx.attr.repository,
)
- tag = ctx.expand_make_variables("tag", ctx.attr.tag, {})
+ tag_file = ctx.actions.declare_file("{name}.tag".format(name = ctx.label.name))
+ ctx.actions.write(
+ output = tag_file,
+ content = ctx.expand_make_variables("tag", ctx.attr.tag, {}),
+ )
+
+ stamp = maybe_stamp(ctx)
+ if stamp:
+ unstamped_tag_file = tag_file
+ tag_file = ctx.actions.declare_file("{name}.stamped.tag".format(name = ctx.label.name))
+
+ args = ctx.actions.args()
+ args.add_all([
+ unstamped_tag_file,
+ tag_file,
+ stamp.stable_status_file,
+ stamp.volatile_status_file,
+ ])
+
+ ctx.actions.run_shell(
+ inputs = [
+ unstamped_tag_file,
+ stamp.stable_status_file,
+ stamp.volatile_status_file,
+ ],
+ outputs = [
+ tag_file,
+ ],
+ arguments = [args],
+ command = """#!/usr/bin/env bash
+scratch=$(cat $1)
+shift
+
+out=$1
+shift
+
+for file in $@
+do
+ while read -r key value
+ do
+ # Replace the keys with their corresponding values in the scratch output
+ scratch=${scratch//\\{$key\\}/$value}
+ done <$file
+done
+
+>$out echo -n "$scratch"
+""",
+ )
digest_file = ctx.actions.declare_file("{name}.digest".format(name = ctx.label.name))
ctx.actions.run(
@@ -47,7 +95,7 @@ def _oci_push_impl(ctx):
--layout-relative {root} \\
--desc {desc} \\
--target-ref {ref} \\
- --parent-tag \"{tag}\" \\
+ --parent-tag \"$(cat {tag})\" \\
{headers} \\
{xheaders} \\
@@ -59,12 +107,12 @@ def _oci_push_impl(ctx):
layout = layout.blob_index.short_path,
desc = ctx.attr.manifest[OCIDescriptor].descriptor_file.short_path,
ref = ref,
- tag = tag,
debug = str(ctx.attr._debug[DebugInfo].debug),
headers = headers,
xheaders = xheaders,
post_scripts = "\n".join(["./" + hook.short_path for hook in toolchain.post_push_hooks]),
digest = digest_file.short_path,
+ tag = tag_file.short_path,
),
output = ctx.outputs.executable,
is_executable = True,
@@ -73,14 +121,15 @@ def _oci_push_impl(ctx):
return [
DefaultInfo(
runfiles = ctx.runfiles(
- files = layout.files.to_list() +
- [toolchain.sdk.ocitool, ctx.attr.manifest[OCIDescriptor].descriptor_file, layout.blob_index, digest_file] + toolchain.post_push_hooks,
+ files = layout.files.to_list() + toolchain.post_push_hooks +
+ [toolchain.sdk.ocitool, ctx.attr.manifest[OCIDescriptor].descriptor_file, layout.blob_index, digest_file, tag_file],
),
),
OCIReferenceInfo(
registry = ctx.attr.registry,
repository = ctx.attr.repository,
digest = digest_file,
+ tag_file = tag_file,
),
]
@@ -90,7 +139,7 @@ oci_push = rule(
""",
implementation = _oci_push_impl,
executable = True,
- attrs = {
+ attrs = dict({
"manifest": attr.label(
doc = """
A manifest to push to a registry. If an OCILayout index, then
@@ -111,7 +160,28 @@ oci_push = rule(
),
"tag": attr.string(
doc = """
- (optional) A tag to include in the target reference. This will not be included on child images."
+ (optional) A tag to include in the target reference. This will not be included on child images.
+
+ Subject to [$(location)](https://bazel.build/reference/be/make-variables#predefined_label_variables) and ["Make variable"](https://bazel.build/reference/be/make-variabmes) substitution.
+
+ **Stamping**
+
+ You can use values produced by the workspace status command in your tag. To do this write a script that prints key-value pairs separated by spaces, e.g.
+
+ ```sh
+ #!/usr/bin/env bash
+ echo "STABLE_KEY1 VALUE1"
+ echo "STABLE_KEY2 VALUE2"
+ ```
+
+ You can reference these keys in `tag` using curly braces,
+
+ ```python
+ oci_push(
+ name = "push",
+ tag = "v1.0-{STABLE_KEY1}",
+ )
+ ```
""",
),
"headers": attr.string_dict(
@@ -128,7 +198,7 @@ oci_push = rule(
default = "//oci:debug",
providers = [DebugInfo],
),
- },
+ }, **STAMP_ATTRS),
provides = [
OCIReferenceInfo,
],