Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions LICENSE-3rdparty.csv
Original file line number Diff line number Diff line change
Expand Up @@ -2506,6 +2506,7 @@ core,github.com/twmb/franz-go/pkg/sasl,BSD-3-Clause,"Copyright 2020, Travis Bisc
core,github.com/twmb/murmur3,BSD-3-Clause,"Copyright 2013, Sébastien Paolacci | Copyright 2018, Travis Bischel"
core,github.com/ua-parser/uap-go/uaparser,MIT,Copyright (c) 2013 Yihuan Zhou | Copyright 2009 Google Inc
core,github.com/ugorji/go/codec,MIT,Copyright (c) 2012-2020 Ugorji Nwoke
core,github.com/ulikunitz/xz,BSD-3-Clause,Copyright (c) 2014-2022 Ulrich Kunitz
core,github.com/ulikunitz/xz/internal/hash,BSD-3-Clause,Copyright (c) 2014-2022 Ulrich Kunitz
core,github.com/ulikunitz/xz/internal/xlog,BSD-3-Clause,Copyright (c) 2014-2022 Ulrich Kunitz
core,github.com/ulikunitz/xz/lzma,BSD-3-Clause,Copyright (c) 2014-2022 Ulrich Kunitz
Expand Down
8 changes: 7 additions & 1 deletion MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,16 @@ git_override(
remote = "https://github.com/bazel-contrib/rules_go.git",
)

# Temporary until rules_pkg > 1.2.0 is in BCR
# Temporary until rules_pkg > 1.2.0 is released. Then switch to http_override.
git_override(
module_name = "rules_pkg",
commit = "401969d4367c42dcbb45d33a637eae87788d025e", # main as of April 22, 2026
patch_strip = 1,
patches = [
# Replaces the Python build_tar tool with dd_tar_writer (Go) so that
# pkg_tar emits a .md5sums sidecar via OutputGroupInfo(md5sums=...).
"//third_party/rules_pkg/patches:tar_bzl.patch",
],
remote = "https://github.com/bazelbuild/rules_pkg.git",
)

Expand Down
255 changes: 255 additions & 0 deletions bazel/rules/dd_tar_writer/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,255 @@
load("@rules_go//go:def.bzl", "go_binary", "go_library", "go_test")
load("@rules_pkg//pkg:mappings.bzl", "pkg_files", "pkg_mkdirs")
load("@rules_pkg//pkg:pkg.bzl", "pkg_tar")
load("@rules_pkg//pkg:verify_archive.bzl", "verify_archive_test")

go_library(
name = "dd_tar_writer_lib",
srcs = ["main.go"],
importpath = "github.com/DataDog/datadog-agent/bazel/rules/dd_tar_writer",
visibility = ["//visibility:private"],
deps = [
"@com_github_ulikunitz_xz//:xz",
],
)

go_binary(
name = "dd_tar_writer",
embed = [":dd_tar_writer_lib"],
visibility = ["//visibility:public"],
)

go_test(
name = "dd_tar_writer_test",
srcs = ["main_test.go"],
embed = [":dd_tar_writer_lib"],
gotags = ["test"],
deps = [
"@com_github_stretchr_testify//assert",
"@com_github_stretchr_testify//require",
],
)

# ——————————————————————————————————————————
# Declarative archive-structure tests
#
# These verify that pkg_tar (which uses dd_tar_writer as its back-end) places
# files, directories, and symlinks at the expected paths inside the archive.
# Compression auto-detection is handled by verify_archive_test.
#
# Unit-level tests for md5sums content, file modes, and entry ordering remain
# in main_test.go where they need to inspect the binary's output directly.
# ——————————————————————————————————————————

# Shared test-data files.
# strip_prefix = "." in pkg_tar strips the Bazel package path from each source
# file, leaving only the filename as the archive entry name.
genrule(
name = "_td_agent",
testonly = True,
outs = ["td_agent"],
cmd = "echo -n binary > $@",
)

genrule(
name = "_td_data",
testonly = True,
outs = ["td_data.txt"],
cmd = "echo -n data > $@",
)

genrule(
name = "_td_local",
testonly = True,
outs = ["td_local.txt"],
cmd = "echo -n local > $@",
)

genrule(
name = "_td_merged",
testonly = True,
outs = ["td_merged.txt"],
cmd = "echo -n merged > $@",
)

genrule(
name = "_td_tree_a",
testonly = True,
outs = ["td_tree_a.txt"],
cmd = "echo -n aaa > $@",
)

genrule(
name = "_td_tree_b",
testonly = True,
outs = ["td_tree_b.txt"],
cmd = "echo -n bbb > $@",
)

# — TestDirectoryPrefix: package_dir places a file at the correct archive path.
pkg_tar(
name = "test_directory_prefix_tar",
testonly = True,
srcs = [":_td_agent"],
package_dir = "opt/datadog-agent/bin",
strip_prefix = ".",
)

verify_archive_test(
name = "test_directory_prefix",
testonly = True,
must_contain = ["opt/datadog-agent/bin/td_agent"],
target = ":test_directory_prefix_tar",
)

# — TestCreateParents: auto-created parent directories precede their children.
pkg_tar(
name = "test_create_parents_tar",
testonly = True,
srcs = [":_td_agent"],
package_dir = "opt/agent/bin",
strip_prefix = ".",
)

verify_archive_test(
name = "test_create_parents",
testonly = True,
# Python's tarfile strips trailing slashes when reading, so directory
# entries appear without them even though the tar header has the slash.
must_contain = [
"opt",
"opt/agent",
"opt/agent/bin",
"opt/agent/bin/td_agent",
],
target = ":test_create_parents_tar",
)

# — TestSymlinkStructure: symlink entry is present with the correct target.
pkg_tar(
name = "test_symlink_tar",
testonly = True,
symlinks = {"opt/agent/current": "/opt/agent/7.0.0"},
)

verify_archive_test(
name = "test_symlink_structure",
testonly = True,
target = ":test_symlink_tar",
verify_links = {"opt/agent/current": "/opt/agent/7.0.0"},
)

# — TestDirStructure: explicit directory entry appears with a trailing slash.
pkg_mkdirs(
name = "_dir_logs",
testonly = True,
dirs = ["opt/agent/logs"],
)

pkg_tar(
name = "test_dir_tar",
testonly = True,
srcs = [":_dir_logs"],
)

verify_archive_test(
name = "test_dir_structure",
testonly = True,
# Python's tarfile strips trailing slashes when reading.
must_contain = ["opt/agent/logs"],
target = ":test_dir_tar",
)

# — TestGzipCompression: gzip-compressed archive is readable, contains the file.
pkg_tar(
name = "test_gzip_tar",
testonly = True,
srcs = [":_td_data"],
extension = "tar.gz",
strip_prefix = ".",
)

verify_archive_test(
name = "test_gzip_compression",
testonly = True,
must_contain = ["td_data.txt"],
target = ":test_gzip_tar",
)

# — TestXzCompression: xz-compressed archive is readable, contains the file.
pkg_tar(
name = "test_xz_tar",
testonly = True,
srcs = [":_td_data"],
extension = "tar.xz",
strip_prefix = ".",
)

verify_archive_test(
name = "test_xz_compression",
testonly = True,
must_contain = ["td_data.txt"],
target = ":test_xz_tar",
)

# — TestMergeTarStructure: merging tars via deps produces an archive with all files.
pkg_tar(
name = "_merge_dep_tar",
testonly = True,
srcs = [":_td_merged"],
package_dir = "merged",
strip_prefix = ".",
)

pkg_tar(
name = "test_merge_tar",
testonly = True,
srcs = [":_td_local"],
strip_prefix = ".",
deps = [":_merge_dep_tar"],
)

verify_archive_test(
name = "test_merge_tar_structure",
testonly = True,
must_contain = [
"td_local.txt",
"merged/td_merged.txt",
],
target = ":test_merge_tar",
)

# — TestAddTree: files at different paths, assembled via pkg_files.
# pkg_files places each source at prefix/<basename> without needing strip_prefix.
pkg_files(
name = "_tree_root_files",
testonly = True,
srcs = [":_td_tree_a"],
prefix = "opt/agent",
)

pkg_files(
name = "_tree_sub_files",
testonly = True,
srcs = [":_td_tree_b"],
prefix = "opt/agent/sub",
)

pkg_tar(
name = "test_add_tree_tar",
testonly = True,
srcs = [
":_tree_root_files",
":_tree_sub_files",
],
)

verify_archive_test(
name = "test_add_tree",
testonly = True,
must_contain = [
"opt/agent/td_tree_a.txt",
"opt/agent/sub/td_tree_b.txt",
],
target = ":test_add_tree_tar",
)
Loading
Loading