Skip to content

Commit

Permalink
refactor: centralize all of the deb_import functionality in deb_impor…
Browse files Browse the repository at this point in the history
…t.bzl

Refactor the package repo templates into their own methods and massively
cleanup the `for`-loop in `_deb_package_index_impl`.

IMHO overall now there's a much better and clear separation of concerns
between the "deb_translate_lock" repo and the "package repos"
(`apt/private/deb_import.bzl`).
  • Loading branch information
jjmaestro committed Nov 24, 2024
1 parent d0fa7fc commit 652ca76
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 78 deletions.
13 changes: 7 additions & 6 deletions apt/apt.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def _apt_install(
manifest,
lock = None,
nolock = False,
package_template = None,
package_arch_build_template = None,
resolve_transitive = True):
"""Repository macro to create Debian repositories.
Expand Down Expand Up @@ -112,10 +112,11 @@ def _apt_install(
lock: label to a `lock.json`
nolock: bool, set to True if you explicitly want to run without a lock
and avoid the DEBUG messages.
package_template: (EXPERIMENTAL!) a template file for generated BUILD
files. Available template replacement keys are:
`{target_name}`, `{deps}`, `{urls}`, `{name}`,
`{arch}`, `{sha256}`, `{repo_name}`
package_arch_build_template: (EXPERIMENTAL!) a template file for
generated BUILD files. Available template
replacement keys are: `{target_name}`,
`{deps}`, `{urls}`, `{name}`, `{arch}`,
`{sha256}`, `{repo_name}`
resolve_transitive: whether dependencies of dependencies should be
resolved and added to the lockfile.
"""
Expand All @@ -134,7 +135,7 @@ def _apt_install(
_deb_translate_lock(
name = name,
lock = lock if lock else "@" + name + "_resolve//:lock.json",
package_template = package_template,
package_arch_build_template = package_arch_build_template,
)

apt = struct(
Expand Down
8 changes: 4 additions & 4 deletions apt/extensions.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def _distroless_extension(module_ctx):
name = install.name,
lock = install.lock,
lock_content = lockf.as_json(),
package_template = install.package_template,
package_arch_build_template = install.package_arch_build_template,
)

if mod.is_root:
Expand Down Expand Up @@ -166,9 +166,9 @@ install = tag_class(
"to `True` to avoid the DEBUG messages.",
default = False,
),
"package_template": attr.label(
doc = "(EXPERIMENTAL!) a template file for generated BUILD " +
"files.",
"package_arch_build_template": attr.label(
doc = "(EXPERIMENTAL!) a template file for the generated " +
"package BUILD files per architecture.",
),
"resolve_transitive": attr.bool(
doc = "Whether dependencies of dependencies should be " +
Expand Down
2 changes: 1 addition & 1 deletion apt/private/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ exports_files([
"dpkg_statusd.sh",
"dpkg_status.sh",
"copy.sh.tmpl",
"package.BUILD.tmpl",
"package_arch.BUILD.tmpl",
])

bzl_library(
Expand Down
63 changes: 61 additions & 2 deletions apt/private/deb_import.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
load(":util.bzl", "util")

# BUILD.bazel template
_DEB_IMPORT_BUILD_TMPL = '''
genrule(
name = "data",
Expand Down Expand Up @@ -62,8 +61,68 @@ def make_deb_import_key(repo_name, package):
util.sanitize(package.version),
)

def deb_import(**kwargs):
def deb_import(name, url, sha256, **kwargs):
http_archive(
name = name,
url = url,
sha256 = sha256,
build_file_content = _DEB_IMPORT_BUILD_TMPL,
**kwargs
)

def _deb_import_tmpl(repo_name, package):
deb_import_key = make_deb_import_key(repo_name, package)

return '''\
deb_import(
name = "{name}",
url = "{url}",
sha256 = "{sha256}",
)
'''.format(name = deb_import_key, url = package.url, sha256 = package.sha256)

def deb_packages(repo_name, packages):
deb_imports = [
_deb_import_tmpl(repo_name, package)
for architectures in packages.values()
for package in architectures.values()
]

return '''\
"""Generated by rules_distroless. DO NOT EDIT."""
load("@rules_distroless//apt/private:deb_import.bzl", "deb_import")
# buildifier: disable=function-docstring
def {repo_name}_packages():
{deb_imports}
'''.format(
repo_name = repo_name,
deb_imports = "\n".join(deb_imports) if deb_imports else " pass",
)

def package_arch_build(package, repo_prefix, repo_name, arch_template):
def deps_str(dependencies, arch, depth):
return ("\n" + " " * depth).join([
'"//%s/%s",' % (dep.name, arch)
for dep in dependencies
])

deb_import_key = make_deb_import_key(repo_name, package)

deps = '[":data"]'
if package.dependencies:
deps += """ + [
{deps}
]""".format(deps = deps_str(package.dependencies, package.arch, 8))
deps += ","

return arch_template.format(
target_name = package.arch,
src = '"@%s%s//:data"' % (repo_prefix, deb_import_key),
deps = deps,
urls = [package.url],
name = package.name,
arch = package.arch,
sha256 = package.sha256,
repo_name = "%s%s" % (repo_prefix, deb_import_key),
)
77 changes: 20 additions & 57 deletions apt/private/deb_translate_lock.bzl
Original file line number Diff line number Diff line change
@@ -1,26 +1,8 @@
"repository rule for generating a dependency graph from a lockfile."

load(":deb_import.bzl", "make_deb_import_key")
load(":deb_import.bzl", "deb_packages", "package_arch_build")
load(":lockfile.bzl", "lockfile")

# header template for packages.bzl file
_DEB_IMPORT_HEADER_TMPL = '''\
"""Generated by rules_distroless. DO NOT EDIT."""
load("@rules_distroless//apt/private:deb_import.bzl", "deb_import")
# buildifier: disable=function-docstring
def {}_packages():
'''

# deb_import template for packages.bzl file
_DEB_IMPORT_TMPL = '''\
deb_import(
name = "{name}",
urls = {urls},
sha256 = "{sha256}",
)
'''

_BUILD_TMPL = """\
exports_files(glob(['packages.bzl']))
Expand All @@ -31,58 +13,39 @@ alias(
"""

def _deb_translate_lock_impl(rctx):
lock_content = rctx.attr.lock_content
package_template = rctx.read(rctx.attr.package_template)
lockf = lockfile.from_json(rctx, lock_content if lock_content else rctx.read(rctx.attr.lock))

package_defs = []

if not lock_content:
package_defs = [_DEB_IMPORT_HEADER_TMPL.format(rctx.attr.name)]
lockf = lockfile.from_json(
rctx,
rctx.attr.lock_content or rctx.read(rctx.attr.lock),
)
lockf.write("lock.json")

if not lockf.packages:
package_defs.append(" pass")
repo_prefix = "@" if rctx.attr.lock_content else ""
repo_name = rctx.attr.name

for package in lockf.packages():
deb_import_key = make_deb_import_key(rctx.attr.name, package)

if not lock_content:
package_defs.append(
_DEB_IMPORT_TMPL.format(
name = deb_import_key,
package_name = package.name,
urls = [package.url],
sha256 = package.sha256,
),
)

repo_name = "%s%s" % ("@" if lock_content else "", deb_import_key)

rctx.file(
"%s/%s/BUILD.bazel" % (package.name, package.arch),
package_template.format(
target_name = package.arch,
src = '"@%s//:data"' % repo_name,
deps = ",\n ".join([
'"//%s/%s"' % (dep.name, package.arch)
for dep in package.dependencies
]),
urls = [package.url],
name = package.name,
arch = package.arch,
sha256 = package.sha256,
repo_name = "%s" % repo_name,
package_arch_build(
package,
repo_prefix,
repo_name,
rctx.read(rctx.attr.package_arch_build_template),
),
)

rctx.file("packages.bzl", "\n".join(package_defs))
if rctx.attr.lock_content:
packages_bzl = ""
else:
packages_bzl = deb_packages(repo_name, lockf.packages)

rctx.file("packages.bzl", packages_bzl)
rctx.file("BUILD.bazel", _BUILD_TMPL.format(rctx.attr.name.split("~")[-1]))

deb_translate_lock = repository_rule(
implementation = _deb_translate_lock_impl,
attrs = {
"lock": attr.label(),
"lock_content": attr.string(doc = "INTERNAL: DO NOT USE"),
"package_template": attr.label(default = "//apt/private:package.BUILD.tmpl"),
"package_arch_build_template": attr.label(default = "//apt/private:package_arch.BUILD.tmpl"),
},
)
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"""Generated by rules_distroless. DO NOT EDIT."""

alias(
name = "data",
actual = "@{repo_name}//:data",
Expand All @@ -12,8 +14,6 @@ alias(

filegroup(
name = "{target_name}",
srcs = {deps}
visibility = ["//visibility:public"],
srcs = [
{deps}
] + [":data"]
)
)
4 changes: 2 additions & 2 deletions docs/apt.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions docs/apt_macro.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 652ca76

Please sign in to comment.