From 8c8fe9e04b86bf7780b6d3b78a29d3373cf46ab4 Mon Sep 17 00:00:00 2001 From: Javier Maestro Date: Fri, 13 Sep 2024 20:16:06 +0100 Subject: [PATCH] refactor: centralize all of the deb_import functionality in deb_import.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 "index repo" (`apt/private/index.bzl`) and the "package repos" (`apt/private/deb_import.bzl`). --- apt/extensions.bzl | 4 +- apt/index.bzl | 6 +- apt/private/BUILD.bazel | 2 +- apt/private/deb_import.bzl | 64 +++++++++++++++- apt/private/index.bzl | 76 +++++-------------- ...age.BUILD.tmpl => package_arch.BUILD.tmpl} | 8 +- docs/apt.md | 4 +- 7 files changed, 93 insertions(+), 71 deletions(-) rename apt/private/{package.BUILD.tmpl => package_arch.BUILD.tmpl} (80%) diff --git a/apt/extensions.bzl b/apt/extensions.bzl index 225893f..e4a8456 100644 --- a/apt/extensions.bzl +++ b/apt/extensions.bzl @@ -48,7 +48,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: @@ -74,7 +74,7 @@ install = tag_class(attrs = { doc = """Whether dependencies of dependencies should be resolved and added to the lockfile.""", default = True, ), - "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."), }) apt = module_extension( diff --git a/apt/index.bzl b/apt/index.bzl index e8fe772..150bbc6 100644 --- a/apt/index.bzl +++ b/apt/index.bzl @@ -8,7 +8,7 @@ def deb_index( manifest, lock = None, nolock = False, - package_template = None, + package_arch_build_template = None, resolve_transitive = True): """A convience repository macro for apt rules. @@ -81,7 +81,7 @@ def deb_index( manifest: label to a `manifest.yaml` 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. + package_arch_build_template: (EXPERIMENTAL!) a template file for the generated package BUILD files per architecture. 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. """ @@ -100,5 +100,5 @@ def deb_index( _deb_package_index( name = name, lock = lock if lock else "@" + name + "_resolve//:lock.json", - package_template = package_template, + package_arch_build_template = package_arch_build_template, ) diff --git a/apt/private/BUILD.bazel b/apt/private/BUILD.bazel index 287c316..f930b43 100644 --- a/apt/private/BUILD.bazel +++ b/apt/private/BUILD.bazel @@ -4,7 +4,7 @@ exports_files([ "dpkg_statusd.sh", "dpkg_status.sh", "copy.sh.tmpl", - "package.BUILD.tmpl", + "package_arch.BUILD.tmpl", ]) bzl_library( diff --git a/apt/private/deb_import.bzl b/apt/private/deb_import.bzl index d05ba49..01b1db9 100644 --- a/apt/private/deb_import.bzl +++ b/apt/private/deb_import.bzl @@ -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", @@ -62,8 +61,67 @@ def make_deb_import_key(repo_name, package): util.sanitize(package.version), ) -def deb_import(**kwargs): +def deb_import(name, url, sha256): 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), ) diff --git a/apt/private/index.bzl b/apt/private/index.bzl index 18b1bf8..f68f829 100644 --- a/apt/private/index.bzl +++ b/apt/private/index.bzl @@ -1,26 +1,8 @@ "apt-get" -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'])) @@ -31,52 +13,33 @@ alias( """ def _deb_package_index_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 architectures in lockf.packages.values(): for package in architectures.values(): - 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_package_index = repository_rule( @@ -85,5 +48,6 @@ deb_package_index = repository_rule( "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"), }, ) diff --git a/apt/private/package.BUILD.tmpl b/apt/private/package_arch.BUILD.tmpl similarity index 80% rename from apt/private/package.BUILD.tmpl rename to apt/private/package_arch.BUILD.tmpl index b5d074a..974ce8d 100644 --- a/apt/private/package.BUILD.tmpl +++ b/apt/private/package_arch.BUILD.tmpl @@ -1,3 +1,5 @@ +"""Generated by rules_distroless. DO NOT EDIT.""" + alias( name = "data", actual = "@{repo_name}//:data", @@ -12,8 +14,6 @@ alias( filegroup( name = "{target_name}", + srcs = {deps} visibility = ["//visibility:public"], - srcs = [ - {deps} - ] + [":data"] -) \ No newline at end of file +) diff --git a/docs/apt.md b/docs/apt.md index c879469..13268d8 100644 --- a/docs/apt.md +++ b/docs/apt.md @@ -7,7 +7,7 @@ apt-get ## deb_index
-deb_index(name, manifest, lock, nolock, package_template, resolve_transitive)
+deb_index(name, manifest, lock, nolock, package_arch_build_template, resolve_transitive)
 
A convience repository macro for apt rules. @@ -86,7 +86,7 @@ An example of this can be found at [/examples/ubuntu_snapshot](/examples/ubuntu_ | manifest | label to a manifest.yaml | none | | lock | label to a lock.json | None | | nolock | bool, set to True if you explicitly want to run without a lock and avoid the DEBUG messages. | False | -| package_template | (EXPERIMENTAL!) a template file for generated BUILD files. Available template replacement keys are: {target_name}, {deps}, {urls}, {name}, {arch}, {sha256}, {repo_name} | None | +| package_arch_build_template | (EXPERIMENTAL!) a template file for the generated package BUILD files per architecture. Available template replacement keys are: {target_name}, {deps}, {urls}, {name}, {arch}, {sha256}, {repo_name} | None | | resolve_transitive | whether dependencies of dependencies should be resolved and added to the lockfile. | True |