From 5fe55005a1bed9b6013d5d7e8797bf3adb8fc56c Mon Sep 17 00:00:00 2001 From: Sahin Yort Date: Thu, 18 Apr 2024 10:17:44 -0700 Subject: [PATCH] fix: always install highest version (#35) --- WORKSPACE.bazel | 11 +++++++++++ apt/private/package_resolution.bzl | 25 +++++++++++++++++-------- apt/private/resolve.bzl | 1 + apt/private/version.bzl | 14 ++++++++++++++ apt/tests/BUILD.bazel | 4 +++- apt/tests/version_test.bzl | 8 ++++++++ examples/apt_security/BUILD.bazel | 17 +++++++++++++++++ examples/apt_security/security.yaml | 15 +++++++++++++++ 8 files changed, 86 insertions(+), 9 deletions(-) create mode 100644 examples/apt_security/BUILD.bazel create mode 100644 examples/apt_security/security.yaml diff --git a/WORKSPACE.bazel b/WORKSPACE.bazel index 2acd9a8..8ac33a1 100644 --- a/WORKSPACE.bazel +++ b/WORKSPACE.bazel @@ -35,3 +35,14 @@ deb_index( load("@bullseye//:packages.bzl", "bullseye_packages") bullseye_packages() + +# bazel run @apt_security//:lock +deb_index( + name = "apt_security", + # lock = "//examples/apt_security:security.lock.json", + manifest = "//examples/apt_security:security.yaml", +) + +load("@apt_security//:packages.bzl", "apt_security_packages") + +apt_security_packages() diff --git a/apt/private/package_resolution.bzl b/apt/private/package_resolution.bzl index 09ab165..1c9c0ea 100644 --- a/apt/private/package_resolution.bzl +++ b/apt/private/package_resolution.bzl @@ -1,6 +1,6 @@ "package resolution" -load(":version.bzl", "version") +load(":version.bzl", version_lib = "version") def _parse_dep(raw): raw = raw.strip() # remove leading & trailing whitespace @@ -49,28 +49,37 @@ def _parse_depends(depends_raw): def _version_relop(va, vb, op): if op == "<<": - return version.lt(va, vb) + return version_lib.lt(va, vb) elif op == ">>": - return version.gt(va, vb) + return version_lib.gt(va, vb) elif op == "<=": - return version.lte(va, vb) + return version_lib.lte(va, vb) elif op == ">=": - return version.gte(va, vb) + return version_lib.gte(va, vb) elif op == "=": - return version.eq(va, vb) + return version_lib.eq(va, vb) fail("unknown op %s" % op) def _resolve_package(state, name, version, arch): + # Get available versions of the package versions = state.index.package_versions(name = name, arch = arch) + + # Order packages by highest to lowest + versions = version_lib.sort(versions, reverse = True) package = None if version: for av in versions: if _version_relop(av, version[1], version[0]): package = state.index.package(name = name, version = av, arch = arch) + + # Since versions are ordered by hight to low, the first satisfied version will be + # the highest version and rules_distroless ignores Priority field so it's safe. + # TODO: rethink this `break` with https://github.com/GoogleContainerTools/rules_distroless/issues/34 break elif len(versions) > 0: - # TODO: what do we do when there is no version constraint? - package = state.index.package(name = name, version = versions[0], arch = arch) + # First element in the versions list is the latest version. + version = versions[0] + package = state.index.package(name = name, version = version, arch = arch) return package def _resolve_all(state, name, version, arch, in_lock, include_transitive): diff --git a/apt/private/resolve.bzl b/apt/private/resolve.bzl index ace041b..ccab42f 100644 --- a/apt/private/resolve.bzl +++ b/apt/private/resolve.bzl @@ -120,6 +120,7 @@ filegroup( name = "lockfile", srcs = ["lock.json"], tags = ["manual"], + visibility = ["//visibility:public"] ) sh_binary( name = "lock", diff --git a/apt/private/version.bzl b/apt/private/version.bzl index aaee1e3..12e9bf0 100644 --- a/apt/private/version.bzl +++ b/apt/private/version.bzl @@ -131,6 +131,19 @@ def _compare_version(va, vb): # compare debian revision return _version_cmp_part(vap[2] or "0", vbp[2] or "0") +def _sort(versions, reverse = False): + vr = versions + for i in range(len(vr)): + for j in range(i + 1, len(vr)): + # if vr[i] is greater than vr[i+1] then swap their indices. + if _compare_version(vr[i], vr[j]) == 1: + vri = vr[i] + vr[i] = vr[j] + vr[j] = vri + if reverse: + vr = reversed(vr) + return vr + version = struct( parse = _parse_version, gt = lambda va, vb: _compare_version(va, vb) == 1, @@ -138,4 +151,5 @@ version = struct( lt = lambda va, vb: _compare_version(va, vb) == -1, lte = lambda va, vb: _compare_version(va, vb) <= 0, eq = lambda va, vb: _compare_version(va, vb) == 0, + sort = lambda versions, reverse = False: _sort(versions, reverse = reverse), ) diff --git a/apt/tests/BUILD.bazel b/apt/tests/BUILD.bazel index b4afaef..1520b02 100644 --- a/apt/tests/BUILD.bazel +++ b/apt/tests/BUILD.bazel @@ -1,8 +1,10 @@ load(":package_resolution_test.bzl", "version_depends_test") -load(":version_test.bzl", "version_compare_test", "version_parse_test") +load(":version_test.bzl", "version_compare_test", "version_parse_test", "version_sort_test") version_compare_test(name = "version_compare_test") version_parse_test(name = "version_parse_test") version_depends_test(name = "version_depends") + +version_sort_test(name = "version_sort_test") diff --git a/apt/tests/version_test.bzl b/apt/tests/version_test.bzl index fdcbdbc..4316206 100644 --- a/apt/tests/version_test.bzl +++ b/apt/tests/version_test.bzl @@ -53,3 +53,11 @@ def _version_compare_test(ctx): return unittest.end(env) version_compare_test = unittest.make(_version_compare_test) + +def _version_sort_test(ctx): + env = unittest.begin(ctx) + asserts.equals(env, version.sort(["1.5~rc2", "1.0.4-2", "1.5~rc1"]), ["1.0.4-2", "1.5~rc1", "1.5~rc2"]) + asserts.equals(env, version.sort(["1.0a7-2", "1.0final-5sarge1", "1.0final-5"], reverse = True), ["1.0final-5sarge1", "1.0final-5", "1.0a7-2"]) + return unittest.end(env) + +version_sort_test = unittest.make(_version_sort_test) diff --git a/examples/apt_security/BUILD.bazel b/examples/apt_security/BUILD.bazel new file mode 100644 index 0000000..18e1d4a --- /dev/null +++ b/examples/apt_security/BUILD.bazel @@ -0,0 +1,17 @@ +load("@aspect_bazel_lib//lib:jq.bzl", "jq") +load("@aspect_bazel_lib//lib:testing.bzl", "assert_contains") + +jq( + name = "pick_libuuid_version", + srcs = [ + "@apt_security_resolution//:lockfile", + ], + args = ["-rj"], + filter = '.packages | map(select(.name == "libuuid1")) | .[0].version', +) + +assert_contains( + name = "test_libuuid_version", + actual = ":pick_libuuid_version", + expected = "2.38.1-5+deb12u1", +) diff --git a/examples/apt_security/security.yaml b/examples/apt_security/security.yaml new file mode 100644 index 0000000..3e2b267 --- /dev/null +++ b/examples/apt_security/security.yaml @@ -0,0 +1,15 @@ +version: 1 + +sources: + - channel: bookworm main + url: https://snapshot-cloudflare.debian.org/archive/debian/20240401T030239Z + - channel: bookworm-updates main + url: https://snapshot-cloudflare.debian.org/archive/debian/20240401T030239Z + - channel: bookworm-security main + url: https://snapshot-cloudflare.debian.org/archive/debian-security/20240401T030239Z + +archs: + - amd64 + +packages: + - libuuid1