From 8a69a8fb096a8ca0597cf9bb2b50a0d6aa086109 Mon Sep 17 00:00:00 2001 From: "Worker Pants (Pantsbuild GitHub Automation Bot)" <133242086+WorkerPants@users.noreply.github.com> Date: Tue, 6 Aug 2024 15:04:53 -0400 Subject: [PATCH] jvm resources action is not reproducible (Cherry-pick of #21259) (#21267) While we are trying to zip the file without extra data and same creation date, we noticed in CI that the action can produce different digests. This commit adds another strip jar action after zipping the resources. It would be great if this can be cherry-picked to 2.20.X and above Co-authored-by: Doron Somech --- src/python/pants/jvm/resources.py | 4 ++ src/python/pants/jvm/resources_test.py | 51 ++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/src/python/pants/jvm/resources.py b/src/python/pants/jvm/resources.py index 1dbb84e831f..03d0ae1a11d 100644 --- a/src/python/pants/jvm/resources.py +++ b/src/python/pants/jvm/resources.py @@ -28,6 +28,7 @@ FallibleClasspathEntries, FallibleClasspathEntry, ) +from pants.jvm.strip_jar.strip_jar import StripJarRequest from pants.jvm.subsystems import JvmSubsystem from pants.util.logging import LogLevel @@ -119,6 +120,9 @@ async def assemble_resources_jar( ) output_digest = resources_jar_result.output_digest + if jvm.reproducible_jars: + output_digest = await Get(Digest, StripJarRequest(output_digest, tuple(output_files))) + cpe = ClasspathEntry(output_digest, output_files, []) merged_cpe_digest = await Get( diff --git a/src/python/pants/jvm/resources_test.py b/src/python/pants/jvm/resources_test.py index 3a10cd7187e..7f379558bbc 100644 --- a/src/python/pants/jvm/resources_test.py +++ b/src/python/pants/jvm/resources_test.py @@ -129,3 +129,54 @@ def test_resources_jar_is_deterministic(rule_runner: RuleRunner) -> None: z = ZipFile(BytesIO(contents[0].content)) for info in z.infolist(): assert info.date_time == (1980, 1, 1, 0, 0, 0) + + +@maybe_skip_jdk_test +def test_resources_reproducible_jars(rule_runner: RuleRunner) -> None: + rule_runner.set_options(["--jvm-reproducible-jars"]) + rule_runner.write_files( + { + "BUILD": "resources(name='root', sources=['**/*.txt'])", + "one.txt": "", + "two.txt": "", + "three/four.txt": "", + "three/five.txt": "", + "three/six/seven/eight.txt": "", + "3rdparty/jvm/default.lock": EMPTY_JVM_LOCKFILE, + } + ) + + # Building the generator target should exclude the individual files and result in a single jar + # for the generator. + classpath = rule_runner.request( + Classpath, [Addresses([Address(spec_path="", target_name="root")])] + ) + + contents = rule_runner.request(DigestContents, list(classpath.digests())) + assert contents[0].path == ".root.resources.jar" + resources_filenames = set(filenames_from_zip(contents[0])) + expected = { + "one.txt", + "two.txt", + "three/", + "three/four.txt", + "three/five.txt", + "three/six/", + "three/six/seven/", + "three/six/seven/eight.txt", + } + + assert resources_filenames == expected + + # But requesting a single file should individually package it. + classpath = rule_runner.request( + Classpath, + [Addresses([Address(spec_path="", target_name="root", relative_file_path="one.txt")])], + ) + contents = rule_runner.request(DigestContents, list(classpath.digests())) + assert contents[0].path == ".one.txt.root.resources.jar" + assert filenames_from_zip(contents[0]) == ["one.txt"] + + z = ZipFile(BytesIO(contents[0].content)) + for info in z.infolist(): + assert info.date_time == (2000, 1, 1, 0, 0, 0)