Skip to content

Commit

Permalink
fix: locking with bzlmod (#73)
Browse files Browse the repository at this point in the history
  • Loading branch information
thesayyn authored Sep 5, 2024
1 parent 5f855ed commit 96d5a6f
Show file tree
Hide file tree
Showing 9 changed files with 242 additions and 232 deletions.
16 changes: 11 additions & 5 deletions apt/extensions.bzl
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
"apt extensions"

load("//apt/private:deb_import.bzl", "deb_import")
load("//apt/private:index.bzl", _deb_package_index = "deb_package_index")
load("//apt/private:index.bzl", "deb_package_index")
load("//apt/private:lockfile.bzl", "lockfile")
load("//apt/private:resolve.bzl", "internal_resolve")
load("//apt/private:resolve.bzl", "deb_resolve", "internal_resolve")

def _distroless_extension(module_ctx):
root_direct_deps = []
root_direct_dev_deps = []

for mod in module_ctx.modules:
for install in mod.tags.install:
lockf = None
Expand Down Expand Up @@ -37,12 +38,17 @@ def _distroless_extension(module_ctx):
sha256 = package["sha256"],
)

_deb_package_index(
deb_resolve(
name = install.name + "_resolve",
manifest = install.manifest,
resolve_transitive = install.resolve_transitive,
)

deb_package_index(
name = install.name,
lock = install.lock,
manifest = install.manifest,
package_template = install.package_template,
lock_content = lockf.as_json(),
package_template = install.package_template,
)

if mod.is_root:
Expand Down
5 changes: 2 additions & 3 deletions apt/index.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ def deb_index(
resolve_transitive: whether dependencies of dependencies should be resolved and added to the lockfile.
"""
_deb_resolve(
name = name + "_resolution",
name = name + "_resolve",
manifest = manifest,
resolve_transitive = resolve_transitive,
)
Expand All @@ -89,7 +89,6 @@ def deb_index(

_deb_package_index(
name = name,
manifest = manifest,
lock = lock if lock else "@" + name + "_resolution//:lock.json",
lock = lock if lock else "@" + name + "_resolve//:lock.json",
package_template = package_template,
)
72 changes: 5 additions & 67 deletions apt/private/index.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -23,56 +23,10 @@ _DEB_IMPORT_TMPL = '''\
_BUILD_TMPL = """\
exports_files(glob(['packages.bzl']))
sh_binary(
alias(
name = "lock",
srcs = ["copy.sh"],
data = ["lock.json"],
tags = ["manual"],
args = ["$(location :lock.json)"],
visibility = ["//visibility:public"]
)
"""

_COPY_SH_TMPL = """\
#!/usr/bin/env bash
set -o pipefail -o errexit -o nounset
lock=$(realpath $1)
cd $BUILD_WORKING_DIRECTORY
echo ''
echo 'Writing lockfile to {workspace_relative_path}'
cp $lock {workspace_relative_path}
# Detect which file we wish the user to edit
if [ -e $BUILD_WORKSPACE_DIRECTORY/WORKSPACE ]; then
wksp_file="WORKSPACE"
elif [ -e $BUILD_WORKSPACE_DIRECTORY/WORKSPACE.bazel ]; then
wksp_file="WORKSPACE.bazel"
else
echo>&2 "Error: neither WORKSPACE nor WORKSPACE.bazel file was found"
exit 1
fi
# Detect a vendored buildozer binary in canonical location (tools/buildozer)
if [ -e $BUILD_WORKSPACE_DIRECTORY/tools/buildozer ]; then
buildozer="tools/buildozer"
else
# Assume it's on the $PATH
buildozer="buildozer"
fi
if [[ "${{2:-}}" == "--autofix" ]]; then
echo ''
${{buildozer}} 'set lock \"{label}\"' ${{wksp_file}}:{name}
else
cat <<EOF
Run the following command to add the lockfile or pass --autofix flag to do it automatically.
${{buildozer}} 'set lock \"{label}\"' ${{wksp_file}}:{name}
EOF
fi
actual = "@{}_resolve//:lock"
)
"""

def _deb_package_index_impl(rctx):
Expand Down Expand Up @@ -124,30 +78,14 @@ def _deb_package_index_impl(rctx):
),
)

locklabel = rctx.attr.manifest.relative(rctx.attr.manifest.name.replace(".yaml", ".lock.json"))
rctx.file(
"copy.sh",
_COPY_SH_TMPL.format(
# TODO: don't assume the canonical -> apparent repo mapping character, as it might change
# https://bazelbuild.slack.com/archives/C014RARENH0/p1719237766005439
# https://github.com/bazelbuild/bazel/issues/22865
name = rctx.name.split("~")[-1],
label = locklabel,
workspace_relative_path = (("%s/" % locklabel.package) if locklabel.package else "") + locklabel.name,
),
executable = True,
)

lockf.write("lock.json")
rctx.file("packages.bzl", "\n".join(package_defs))
rctx.file("BUILD.bazel", _BUILD_TMPL)
rctx.file("BUILD.bazel", _BUILD_TMPL.format(rctx.attr.name.split("~")[-1]))

deb_package_index = repository_rule(
implementation = _deb_package_index_impl,
attrs = {
"manifest": attr.label(mandatory = True),
"lock": attr.label(),
"package_template": attr.label(default = "//apt/private:package.BUILD.tmpl"),
"lock_content": attr.string(doc = "INTERNAL: DO NOT USE"),
"package_template": attr.label(default = "//apt/private:package.BUILD.tmpl"),
},
)
2 changes: 1 addition & 1 deletion apt/private/package_index.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def _fetch_package_index(rctx, url, dist, comp, arch, integrity):
integrity = download.integrity
break

failed_attempts.append((url, download, decompress_r))
failed_attempts.append((dist_url, download, decompress_r))

if len(failed_attempts) == len(supported_extensions):
attempt_messages = []
Expand Down
80 changes: 73 additions & 7 deletions apt/private/resolve.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -85,19 +85,85 @@ def internal_resolve(rctx, yq_toolchain_prefix, manifest, include_transitive):
lockf.add_package_dependency(package, dep, arch)
return lockf

def _deb_resolve_impl(rctx):
lockf = internal_resolve(rctx, rctx.attr.yq_toolchain_prefix, rctx.attr.manifest, rctx.attr.resolve_transitive)

lockf.write("lock.json")

rctx.file("BUILD.bazel", """\
_COPY_SH_TMPL = """\
#!/usr/bin/env bash
set -o pipefail -o errexit -o nounset
lock=$(realpath $1)
cd $BUILD_WORKING_DIRECTORY
echo ''
echo 'Writing lockfile to {workspace_relative_path}'
cp $lock {workspace_relative_path}
# Detect which file we wish the user to edit
if [ -e $BUILD_WORKSPACE_DIRECTORY/WORKSPACE ]; then
wksp_file="WORKSPACE"
elif [ -e $BUILD_WORKSPACE_DIRECTORY/WORKSPACE.bazel ]; then
wksp_file="WORKSPACE.bazel"
else
echo>&2 "Error: neither WORKSPACE nor WORKSPACE.bazel file was found"
exit 1
fi
# Detect a vendored buildozer binary in canonical location (tools/buildozer)
if [ -e $BUILD_WORKSPACE_DIRECTORY/tools/buildozer ]; then
buildozer="tools/buildozer"
else
# Assume it's on the $PATH
buildozer="buildozer"
fi
if [[ "${{2:-}}" == "--autofix" ]]; then
echo ''
${{buildozer}} 'set lock \"{label}\"' ${{wksp_file}}:{name}
else
cat <<EOF
Run the following command to add the lockfile or pass --autofix flag to do it automatically.
${{buildozer}} 'set lock \"{label}\"' ${{wksp_file}}:{name}
EOF
fi
"""

_BUILD_TMPL = """
filegroup(
name = "lockfile",
srcs = ["lock.json"],
tags = ["manual"],
visibility = ["//visibility:public"]
)
""")
sh_binary(
name = "lock",
srcs = ["copy.sh"],
data = ["lock.json"],
tags = ["manual"],
args = ["$(location :lock.json)"],
visibility = ["//visibility:public"]
)
"""

def _deb_resolve_impl(rctx):
lockf = internal_resolve(rctx, rctx.attr.yq_toolchain_prefix, rctx.attr.manifest, rctx.attr.resolve_transitive)
lockf.write("lock.json")

locklabel = rctx.attr.manifest.relative(rctx.attr.manifest.name.replace(".yaml", ".lock.json"))
rctx.file(
"copy.sh",
_COPY_SH_TMPL.format(
# TODO: don't assume the canonical -> apparent repo mapping character, as it might change
# https://bazelbuild.slack.com/archives/C014RARENH0/p1719237766005439
# https://github.com/bazelbuild/bazel/issues/22865
name = rctx.name.split("~")[-1],
label = locklabel,
workspace_relative_path = (("%s/" % locklabel.package) if locklabel.package else "") + locklabel.name,
),
executable = True,
)

rctx.file("BUILD.bazel", _BUILD_TMPL)

deb_resolve = repository_rule(
implementation = _deb_resolve_impl,
Expand Down
3 changes: 2 additions & 1 deletion distroless/toolchains.bzl
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
"macro for registering toolchains required"

load("@aspect_bazel_lib//lib:repositories.bzl", "register_expand_template_toolchains", "register_tar_toolchains", "register_zstd_toolchains")
load("@aspect_bazel_lib//lib:repositories.bzl", "register_expand_template_toolchains", "register_tar_toolchains", "register_yq_toolchains", "register_zstd_toolchains")

def distroless_register_toolchains():
register_yq_toolchains()
register_zstd_toolchains()
register_tar_toolchains()
register_expand_template_toolchains()
Loading

0 comments on commit 96d5a6f

Please sign in to comment.