Skip to content

Commit ceda6ca

Browse files
committed
feat: validate actions for merged-usr violations
1 parent cd52563 commit ceda6ca

File tree

4 files changed

+95
-5
lines changed

4 files changed

+95
-5
lines changed

.bazelrc

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
# Take care to document any settings that you expect users to apply.
33
# Settings that apply only to CI are in .github/workflows/ci.bazelrc
44

5-
# Allow DOCKER_HOST env to leak into test actions.
5+
# Allow DOCKER_HOST env to leak into test actions.
66
test --test_env=DOCKER_HOST
77

8-
# Stamp
8+
# Stamp
99
build:release --workspace_status_command=./private/stamp.bash --stamp
1010
run:release --workspace_status_command=./private/stamp.bash --stamp
1111
test:release --workspace_status_command=./private/stamp.bash --stamp
@@ -25,6 +25,11 @@ build --java_runtime_version=remotejdk_11
2525
# https://github.com/GoogleContainerTools/rules_distroless/actions/runs/7118944984/job/19382981899?pr=9#step:8:51
2626
common:linux --sandbox_tmpfs_path=/tmp
2727

28+
29+
# Attach validation actions to layers that end up in the final oci_image targets
30+
# to catch potential merged-usr errors.
31+
common --aspects=//private/util:validate_usr_symlinks.bzl%validate_usr_symlinks
32+
2833
# Load any settings specific to the current user.
2934
# .bazelrc.user should appear in .gitignore so that settings are not shared with team members
3035
# This needs to be last statement in this

MODULE.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ bazel_dep(name = "rules_oci", version = "1.8.0")
1414
bazel_dep(name = "rules_distroless", version = "0.5.3")
1515
bazel_dep(name = "rules_python", version = "1.5.3")
1616
bazel_dep(name = "rules_cc", version = "0.2.0")
17+
bazel_dep(name = "gawk", version = "5.3.2.bcr.3")
1718

1819
### OCI ###
1920
oci = use_extension("@rules_oci//oci:extensions.bzl", "oci")

MODULE.bazel.lock

Lines changed: 6 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
"a utility that extracts files from tar"
2+
3+
load("@aspect_bazel_lib//lib:tar.bzl", "tar_lib")
4+
5+
# https://wiki.gentoo.org/wiki/Merge-usr
6+
# https://salsa.debian.org/md/usrmerge/raw/master/debian/README.Debian
7+
# https://www.freedesktop.org/wiki/Software/systemd/TheCaseForTheUsrMerge/
8+
# Mapping taken from https://github.com/floppym/merge-usr/blob/15dd02207bdee7ca6720d7024e8c0ffdc166ed23/merge-usr#L17-L25
9+
# https://salsa.debian.org/md/usrmerge/-/tree/master/debian?ref_type=heads
10+
_VALIDATE_SYMLINKS = """\
11+
BEGIN {
12+
prefixes = "./bin|./sbin|./usr/sbin|./lib|./lib32|./lib64|./libx32"
13+
}
14+
{
15+
if ($0 ~ "^(" prefixes ")" && $0 !~ /type=link/) {
16+
VIOLATIONS[$0] = $1
17+
next
18+
}
19+
}
20+
END {
21+
for (violation in VIOLATIONS) {
22+
print "VIOLATION: " VIOLATIONS[violation] " violates usr-merge convention."
23+
print violation
24+
}
25+
if (length(VIOLATIONS) > 0) {
26+
exit 1
27+
}
28+
print "" > "{validation_output}"
29+
}
30+
31+
"""
32+
33+
def _validate_usr_symlink_impl(target, ctx):
34+
if target.label.name.find("debian13") == -1:
35+
return []
36+
37+
if not hasattr(ctx.rule.files, "tars"):
38+
return []
39+
bsdtar = ctx.toolchains[tar_lib.toolchain_type]
40+
41+
output = ctx.actions.declare_file(target.label.name + ".mtree")
42+
43+
args = ctx.actions.args()
44+
args.add("--create")
45+
args.add("--file", output)
46+
args.add("--format=mtree")
47+
args.add_all(ctx.rule.files.tars, format_each = "@%s")
48+
49+
ctx.actions.run(
50+
executable = bsdtar.tarinfo.binary,
51+
inputs = ctx.rule.files.tars,
52+
outputs = [output],
53+
tools = bsdtar.default.files,
54+
arguments = [args],
55+
mnemonic = "PackageListing",
56+
)
57+
58+
validation_output = ctx.actions.declare_file(target.label.name + ".validation")
59+
ctx.actions.run(
60+
executable = ctx.executable._awk,
61+
inputs = [output],
62+
outputs = [validation_output],
63+
arguments = [
64+
_VALIDATE_SYMLINKS.replace("{validation_output}", validation_output.path),
65+
output.path,
66+
],
67+
mnemonic = "ValidateUsrSymlinks",
68+
)
69+
70+
return [
71+
OutputGroupInfo(_validation = depset([validation_output])),
72+
]
73+
74+
validate_usr_symlinks = aspect(
75+
implementation = _validate_usr_symlink_impl,
76+
attrs = {
77+
"_awk": attr.label(default = "@gawk//:gawk", cfg = "exec", executable = True),
78+
},
79+
attr_aspects = ["tars"],
80+
toolchains = [tar_lib.toolchain_type],
81+
)

0 commit comments

Comments
 (0)