Skip to content

Commit

Permalink
tar: make all gzip compression hermetic (#75)
Browse files Browse the repository at this point in the history
We weren't passing the flag to make gzip hermetic. Without the flag to
ignore timestamp, the shasum will differ based on the system time.

Also, DEFAULT_ARGS contained "--options=gzip:...", which is invalid when
using any other compression scheme. Therefore, remove that option from
DEFAULT_ARGS and provide an alternate function called
`add_default_compression_args` to add per-compression type default
arguments which can do things like make the compression more hermetic.
  • Loading branch information
DolceTriade authored Oct 28, 2024
1 parent 30c3960 commit 7853bcd
Show file tree
Hide file tree
Showing 7 changed files with 22 additions and 9 deletions.
2 changes: 2 additions & 0 deletions distroless/private/flatten.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ def _flatten_impl(ctx):
output = ctx.actions.declare_file(ctx.attr.name + ext)

args = ctx.actions.args()
args.add_all(tar_lib.DEFAULT_ARGS)
args.add("--create")
tar_lib.common.add_compression_args(ctx.attr.compress, args)
tar_lib.add_default_compression_args(ctx.attr.compress, args)
args.add("--file", output)
args.add_all(ctx.files.tars, format_each = "@%s")

Expand Down
2 changes: 1 addition & 1 deletion distroless/private/group.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def group(name, entries, time = "0.0", mode = "0644", **kwargs):
name = name,
srcs = [":%s_content" % name],
mtree = mtree.content(),
args = tar_lib.DEFAULT_ARGS,
args = tar_lib.DEFAULT_ARGS + tar_lib.DEFAULT_COMPRESSION_ARGS["gzip"],
compress = "gzip",
**common_kwargs
)
2 changes: 1 addition & 1 deletion distroless/private/home.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def home(name, dirs, **kwargs):
tar(
name = name,
mtree = mtree.content(),
args = tar_lib.DEFAULT_ARGS,
args = tar_lib.DEFAULT_ARGS + tar_lib.DEFAULT_COMPRESSION_ARGS["gzip"],
compress = "gzip",
**kwargs
)
4 changes: 2 additions & 2 deletions distroless/private/locale.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ shift 4
# TODO: there must be a better way to manipulate tars!
# "$bsdtar" -cf $out --posix --no-same-owner --options="" $@ "@$package_path"
# "$bsdtar" -cf to.mtree $@ --format=mtree --options '!gname,!uname,!sha1,!nlink' "@$package_path"
# "$bsdtar" --older "0" -Uf $out @to.mtree
# "$bsdtar" --older "0" -Uf $out @to.mtree

tmp=$(mktemp -d)
"$bsdtar" -xf "$package_path" $@ -C "$tmp"
"$bsdtar" -cf - $@ --format=mtree --options '!gname,!uname,!sha1,!nlink,!time' "@$package_path" | sed 's/$/ time=0.0/' | "$bsdtar" --gzip -cf "$out" -C "$tmp/" @-
"$bsdtar" -cf - $@ --format=mtree --options '!gname,!uname,!sha1,!nlink,!time' "@$package_path" | sed 's/$/ time=0.0/' | "$bsdtar" --gzip --options 'gzip:!timestamp' -cf "$out" -C "$tmp/" @-
2 changes: 1 addition & 1 deletion distroless/private/os_release.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def os_release(
name = name,
srcs = [":%s_content" % name],
mtree = mtree.content(),
args = tar_lib.DEFAULT_ARGS,
args = tar_lib.DEFAULT_ARGS + tar_lib.DEFAULT_COMPRESSION_ARGS["gzip"],
compress = "gzip",
**common_kwargs
)
2 changes: 1 addition & 1 deletion distroless/private/passwd.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def passwd(name, entries, mode = "0644", time = "0.0", **kwargs):
name = name,
srcs = [":%s_content" % name],
mtree = mtree.content(),
args = tar_lib.DEFAULT_ARGS,
args = tar_lib.DEFAULT_ARGS + tar_lib.DEFAULT_COMPRESSION_ARGS["gzip"],
compress = "gzip",
**common_kwargs
)
17 changes: 14 additions & 3 deletions distroless/private/tar.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,15 @@ DEFAULT_ARGS = [
# TODO: distroless uses gnu archives
"--format",
"gnutar",
# Gzip timestamps are source of non-hermeticity. disable them
"--options=gzip:!timestamp",
]

DEFAULT_COMPRESSION_ARGS = {
"gzip": [
# Gzip timestamps are source of non-hermeticity. disable them
"--options=gzip:!timestamp",
],
}

def _mtree_line(dest, type, content = None, uid = DEFAULT_UID, gid = DEFAULT_GID, time = DEFAULT_TIME, mode = DEFAULT_MODE):
# mtree expects paths to start with ./ so normalize paths that starts with
# `/` or relative path (without / and ./)
Expand Down Expand Up @@ -56,7 +61,8 @@ def _build_tar(ctx, mtree, output, inputs = [], compression = "gzip", mnemonic =
args = ctx.actions.args()
args.add_all(DEFAULT_ARGS)
args.add("--create")
args.add(compression, format = "--%s")
tar.common.add_compression_args(compression, args)
_add_default_compression_args(compression, args)
args.add("--file", output)
args.add(mtree, format = "@%s")

Expand Down Expand Up @@ -100,9 +106,14 @@ def _create_mtree(ctx = None):
content = lambda: content.to_list() + ["#end"],
)

def _add_default_compression_args(compression, args):
args.add_all(DEFAULT_COMPRESSION_ARGS.get(compression, []))

tar_lib = struct(
TOOLCHAIN_TYPE = tar.toolchain_type,
DEFAULT_ARGS = DEFAULT_ARGS,
DEFAULT_COMPRESSION_ARGS = DEFAULT_COMPRESSION_ARGS,
add_default_compression_args = _add_default_compression_args,
create_mtree = _create_mtree,
common = tar.common,
)

0 comments on commit 7853bcd

Please sign in to comment.