Skip to content

Commit

Permalink
feat: stamp the "tag" attribute for oci_push (#59)
Browse files Browse the repository at this point in the history
  • Loading branch information
nguyening authored Jun 3, 2024
1 parent 18cb69e commit 461b15b
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 10 deletions.
5 changes: 3 additions & 2 deletions docs/docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ oci_pull(<a href="#oci_pull-name">name</a>, <a href="#oci_pull-digest">digest</a
## oci_push

<pre>
oci_push(<a href="#oci_push-name">name</a>, <a href="#oci_push-headers">headers</a>, <a href="#oci_push-manifest">manifest</a>, <a href="#oci_push-registry">registry</a>, <a href="#oci_push-repository">repository</a>, <a href="#oci_push-tag">tag</a>, <a href="#oci_push-x_meta_headers">x_meta_headers</a>)
oci_push(<a href="#oci_push-name">name</a>, <a href="#oci_push-headers">headers</a>, <a href="#oci_push-manifest">manifest</a>, <a href="#oci_push-registry">registry</a>, <a href="#oci_push-repository">repository</a>, <a href="#oci_push-stamp">stamp</a>, <a href="#oci_push-tag">tag</a>, <a href="#oci_push-x_meta_headers">x_meta_headers</a>)
</pre>


Expand All @@ -119,7 +119,8 @@ oci_push(<a href="#oci_push-name">name</a>, <a href="#oci_push-headers">headers<
| <a id="oci_push-manifest"></a>manifest | A manifest to push to a registry. If an OCILayout index, then push all artifacts with a 'org.opencontainers.image.ref.name' annotation. | <a href="https://bazel.build/docs/build-ref.html#labels">Label</a> | optional | None |
| <a id="oci_push-registry"></a>registry | A registry host to push to, if not present consult the toolchain. | String | optional | "" |
| <a id="oci_push-repository"></a>repository | A repository to push to, if not present consult the toolchain. | String | optional | "" |
| <a id="oci_push-tag"></a>tag | (optional) A tag to include in the target reference. This will not be included on child images." | String | optional | "" |
| <a id="oci_push-stamp"></a>stamp | Whether to encode build information into the output. Possible values:<br><br> - <code>stamp = 1</code>: 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. - <code>stamp = 0</code>: Never stamp, instead replace build information by constant values. This gives good build result caching. - <code>stamp = -1</code>: 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 |
| <a id="oci_push-tag"></a>tag | (optional) A tag to include in the target reference. This will not be included on child images.<br><br> Subject to [$(location)](https://bazel.build/reference/be/make-variables#predefined_label_variables) and ["Make variable"](https://bazel.build/reference/be/make-variabmes) substitution.<br><br> **Stamping**<br><br> 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.<br><br> <pre><code>sh #!/usr/bin/env bash echo "STABLE_KEY1 VALUE1" echo "STABLE_KEY2 VALUE2" </code></pre><br><br> You can reference these keys in <code>tag</code> using curly braces,<br><br> <pre><code>python oci_push( name = "push", tag = "v1.0-{STABLE_KEY1}", ) </code></pre> | String | optional | "" |
| <a id="oci_push-x_meta_headers"></a>x_meta_headers | (optional) A list of key/values to to be sent to the registry as headers with an X-Meta- prefix. | <a href="https://bazel.build/docs/skylark/lib/dict.html">Dictionary: String -> String</a> | optional | {} |


1 change: 1 addition & 0 deletions oci/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -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",
],
Expand Down
1 change: 1 addition & 0 deletions oci/providers.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -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",
},
)
Expand Down
86 changes: 78 additions & 8 deletions oci/push.bzl
Original file line number Diff line number Diff line change
@@ -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")

Expand All @@ -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(
Expand Down Expand Up @@ -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} \\
Expand All @@ -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,
Expand All @@ -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,
),
]

Expand All @@ -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
Expand All @@ -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(
Expand All @@ -128,7 +198,7 @@ oci_push = rule(
default = "//oci:debug",
providers = [DebugInfo],
),
},
}, **STAMP_ATTRS),
provides = [
OCIReferenceInfo,
],
Expand Down

0 comments on commit 461b15b

Please sign in to comment.