← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] ~pelpsi/launchpad:upload-jars-produced-by-maven into launchpad:master

 

Simone Pelosi has proposed merging ~pelpsi/launchpad:upload-jars-produced-by-maven into launchpad:master.

Commit message:
Maven can produce multiple .jar

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~pelpsi/launchpad/+git/launchpad/+merge/493954
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~pelpsi/launchpad:upload-jars-produced-by-maven into launchpad:master.
diff --git a/lib/lp/archiveuploader/craftrecipeupload.py b/lib/lp/archiveuploader/craftrecipeupload.py
index 298878d..8acfdb8 100644
--- a/lib/lp/archiveuploader/craftrecipeupload.py
+++ b/lib/lp/archiveuploader/craftrecipeupload.py
@@ -104,12 +104,6 @@ class CraftRecipeUpload:
                         "Only one .crate file is allowed per build."
                     )
 
-                if len(jar_files) > 1:
-                    raise UploadError(
-                        "Archive contains multiple JAR files. "
-                        "Only one .jar file is allowed per build."
-                    )
-
                 if len(pom_files) > 1:
                     raise UploadError(
                         "Archive contains multiple pom.xml files. "
@@ -168,17 +162,20 @@ class CraftRecipeUpload:
                             "Failed to parse metadata.yaml: %s", e
                         )
 
-                    # Upload the JAR file
-                    jar_path = jar_files[0]
-                    with open(jar_path, "rb") as file:
-                        libraryfile = self.librarian.create(
-                            os.path.basename(str(jar_path)),
-                            os.stat(jar_path).st_size,
-                            file,
-                            filenameToContentType(str(jar_path)),
-                            restricted=build.is_private,
-                        )
-                    build.addFile(libraryfile)
+                    # Upload all JAR files
+                    self.logger.debug(
+                        "Uploading %d JAR file(s)", len(jar_files)
+                    )
+                    for jar_path in sorted(jar_files):
+                        with open(jar_path, "rb") as file:
+                            libraryfile = self.librarian.create(
+                                os.path.basename(str(jar_path)),
+                                os.stat(jar_path).st_size,
+                                file,
+                                filenameToContentType(str(jar_path)),
+                                restricted=build.is_private,
+                            )
+                        build.addFile(libraryfile)
 
                     # Upload the POM file
                     pom_path = pom_files[0]
diff --git a/lib/lp/archiveuploader/tests/test_craftrecipeupload.py b/lib/lp/archiveuploader/tests/test_craftrecipeupload.py
index 7f95291..dba37c6 100644
--- a/lib/lp/archiveuploader/tests/test_craftrecipeupload.py
+++ b/lib/lp/archiveuploader/tests/test_craftrecipeupload.py
@@ -349,9 +349,9 @@ class TestCraftRecipeUploads(TestUploadProcessorBase):
         }
         self.assertEqual(expected_files, filenames)
 
-    def test_errors_on_multiple_artifact_types(self):
-        """Test that an error is raised when both crate and Maven artifacts
-        are present in the same archive."""
+    def test_processes_on_multiple_jars(self):
+        """Test that multiple JARs and POM files are properly extracted and processed
+        from archives."""
         upload_dir = os.path.join(
             self.incoming_folder, "test", str(self.build.id)
         )
@@ -368,17 +368,16 @@ class TestCraftRecipeUploads(TestUploadProcessorBase):
             with open(metadata_path, "w") as f:
                 yaml.safe_dump(metadata, f)
 
-            # Create dummy crate file
-            crate_path = os.path.join(tmpdir, "test-artifact-0.1.0.crate")
-            with open(crate_path, "wb") as f:
-                f.write(b"dummy crate contents")
-
-            # Create dummy JAR file
-            jar_path = os.path.join(tmpdir, "test-artifact-0.1.0.jar")
-            with open(jar_path, "wb") as f:
+            # Create multiple JAR files
+            jar_path1 = os.path.join(tmpdir, "test-artifact-0.1.0.jar")
+            with open(jar_path1, "wb") as f:
                 f.write(b"dummy jar contents")
 
-            # Create dummy POM file
+            jar_path2 = os.path.join(tmpdir, "another-jar-0.2.0.jar")
+            with open(jar_path2, "wb") as f:
+                f.write(b"another jar contents")
+
+            # Create POM file
             pom_path = os.path.join(tmpdir, "pom.xml")
             with open(pom_path, "w") as f:
                 f.write("<project></project>")
@@ -387,8 +386,8 @@ class TestCraftRecipeUploads(TestUploadProcessorBase):
             archive_path = os.path.join(upload_dir, "output.tar.xz")
             with tarfile.open(archive_path, "w:xz") as tar:
                 tar.add(metadata_path, arcname="metadata.yaml")
-                tar.add(crate_path, arcname=os.path.basename(crate_path))
-                tar.add(jar_path, arcname=os.path.basename(jar_path))
+                tar.add(jar_path1, arcname=os.path.basename(jar_path1))
+                tar.add(jar_path2, arcname=os.path.basename(jar_path2))
                 tar.add(pom_path, arcname="pom.xml")
 
         handler = UploadHandler.forProcessor(
@@ -396,16 +395,32 @@ class TestCraftRecipeUploads(TestUploadProcessorBase):
         )
         result = handler.processCraftRecipe(self.log)
 
-        # Verify upload was rejected
-        self.assertEqual(UploadStatusEnum.REJECTED, result)
+        # Verify upload succeeded
+        self.assertEqual(UploadStatusEnum.ACCEPTED, result)
+        self.assertEqual(BuildStatus.FULLYBUILT, self.build.status)
+
         self.assertIn(
-            "ERROR Archive contains both Rust and Java artifacts",
+            "Uploading 2 JAR file(s)",
             self.log.getLogBuffer(),
         )
-        self.assertFalse(self.build.verifySuccessfulUpload())
 
-    def test_errors_on_multiple_crates(self):
-        """Test that an error is raised when multiple crates are present."""
+        # Verify JARs, POM, and metadata were stored (not the archive)
+        build = removeSecurityProxy(self.build)
+        files = list(build.getFiles())
+        self.assertEqual(4, len(files))
+
+        filenames = {f[1].filename for f in files}
+        expected_files = {
+            "test-artifact-0.1.0.jar",
+            "another-jar-0.2.0.jar",
+            "pom.xml",
+            "metadata.yaml",
+        }
+        self.assertEqual(expected_files, filenames)
+
+    def test_errors_on_multiple_artifact_types(self):
+        """Test that an error is raised when both crate and Maven artifacts
+        are present in the same archive."""
         upload_dir = os.path.join(
             self.incoming_folder, "test", str(self.build.id)
         )
@@ -422,21 +437,28 @@ class TestCraftRecipeUploads(TestUploadProcessorBase):
             with open(metadata_path, "w") as f:
                 yaml.safe_dump(metadata, f)
 
-            # Create multiple crate files
-            crate_path1 = os.path.join(tmpdir, "test-artifact-0.1.0.crate")
-            with open(crate_path1, "wb") as f:
+            # Create dummy crate file
+            crate_path = os.path.join(tmpdir, "test-artifact-0.1.0.crate")
+            with open(crate_path, "wb") as f:
                 f.write(b"dummy crate contents")
 
-            crate_path2 = os.path.join(tmpdir, "another-crate-0.2.0.crate")
-            with open(crate_path2, "wb") as f:
-                f.write(b"another crate contents")
+            # Create dummy JAR file
+            jar_path = os.path.join(tmpdir, "test-artifact-0.1.0.jar")
+            with open(jar_path, "wb") as f:
+                f.write(b"dummy jar contents")
+
+            # Create dummy POM file
+            pom_path = os.path.join(tmpdir, "pom.xml")
+            with open(pom_path, "w") as f:
+                f.write("<project></project>")
 
             # Create tar.xz archive
             archive_path = os.path.join(upload_dir, "output.tar.xz")
             with tarfile.open(archive_path, "w:xz") as tar:
                 tar.add(metadata_path, arcname="metadata.yaml")
-                tar.add(crate_path1, arcname=os.path.basename(crate_path1))
-                tar.add(crate_path2, arcname=os.path.basename(crate_path2))
+                tar.add(crate_path, arcname=os.path.basename(crate_path))
+                tar.add(jar_path, arcname=os.path.basename(jar_path))
+                tar.add(pom_path, arcname="pom.xml")
 
         handler = UploadHandler.forProcessor(
             self.uploadprocessor, self.incoming_folder, "test", self.build
@@ -446,13 +468,13 @@ class TestCraftRecipeUploads(TestUploadProcessorBase):
         # Verify upload was rejected
         self.assertEqual(UploadStatusEnum.REJECTED, result)
         self.assertIn(
-            "ERROR Archive contains multiple Rust crate files",
+            "ERROR Archive contains both Rust and Java artifacts",
             self.log.getLogBuffer(),
         )
         self.assertFalse(self.build.verifySuccessfulUpload())
 
-    def test_errors_on_multiple_jars(self):
-        """Test that an error is raised when multiple jars are present."""
+    def test_errors_on_multiple_crates(self):
+        """Test that an error is raised when multiple crates are present."""
         upload_dir = os.path.join(
             self.incoming_folder, "test", str(self.build.id)
         )
@@ -469,27 +491,21 @@ class TestCraftRecipeUploads(TestUploadProcessorBase):
             with open(metadata_path, "w") as f:
                 yaml.safe_dump(metadata, f)
 
-            # Create multiple JAR files
-            jar_path1 = os.path.join(tmpdir, "test-artifact-0.1.0.jar")
-            with open(jar_path1, "wb") as f:
-                f.write(b"dummy jar contents")
-
-            jar_path2 = os.path.join(tmpdir, "another-jar-0.2.0.jar")
-            with open(jar_path2, "wb") as f:
-                f.write(b"another jar contents")
+            # Create multiple crate files
+            crate_path1 = os.path.join(tmpdir, "test-artifact-0.1.0.crate")
+            with open(crate_path1, "wb") as f:
+                f.write(b"dummy crate contents")
 
-            # Create POM file
-            pom_path = os.path.join(tmpdir, "pom.xml")
-            with open(pom_path, "w") as f:
-                f.write("<project></project>")
+            crate_path2 = os.path.join(tmpdir, "another-crate-0.2.0.crate")
+            with open(crate_path2, "wb") as f:
+                f.write(b"another crate contents")
 
             # Create tar.xz archive
             archive_path = os.path.join(upload_dir, "output.tar.xz")
             with tarfile.open(archive_path, "w:xz") as tar:
                 tar.add(metadata_path, arcname="metadata.yaml")
-                tar.add(jar_path1, arcname=os.path.basename(jar_path1))
-                tar.add(jar_path2, arcname=os.path.basename(jar_path2))
-                tar.add(pom_path, arcname="pom.xml")
+                tar.add(crate_path1, arcname=os.path.basename(crate_path1))
+                tar.add(crate_path2, arcname=os.path.basename(crate_path2))
 
         handler = UploadHandler.forProcessor(
             self.uploadprocessor, self.incoming_folder, "test", self.build
@@ -499,7 +515,7 @@ class TestCraftRecipeUploads(TestUploadProcessorBase):
         # Verify upload was rejected
         self.assertEqual(UploadStatusEnum.REJECTED, result)
         self.assertIn(
-            "ERROR Archive contains multiple JAR files",
+            "ERROR Archive contains multiple Rust crate files",
             self.log.getLogBuffer(),
         )
         self.assertFalse(self.build.verifySuccessfulUpload())