← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] ~cjwatson/launchpad:ocirecipebuild-get-file-urls into launchpad:master

 

Colin Watson has proposed merging ~cjwatson/launchpad:ocirecipebuild-get-file-urls into launchpad:master.

Commit message:
Add and export OCIRecipeBuild.getFileUrls

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)
Related bugs:
  Bug #1969449 in Launchpad itself: "add a method to return URLs for all the files produced by a given OCI build"
  https://bugs.launchpad.net/launchpad/+bug/1969449

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/420299

This aligns with snap builds, and it's useful for processing the results of OCI recipe builds outside Launchpad.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:ocirecipebuild-get-file-urls into launchpad:master.
diff --git a/lib/lp/oci/interfaces/ocirecipebuild.py b/lib/lp/oci/interfaces/ocirecipebuild.py
index b366f87..763e1ed 100644
--- a/lib/lp/oci/interfaces/ocirecipebuild.py
+++ b/lib/lp/oci/interfaces/ocirecipebuild.py
@@ -21,6 +21,7 @@ from lazr.enum import (
     )
 from lazr.restful.declarations import (
     error_status,
+    export_read_operation,
     export_write_operation,
     exported,
     exported_as_webservice_entry,
@@ -196,6 +197,14 @@ class IOCIRecipeBuildView(IPackageBuildView, IPrivacy):
         :return: The corresponding `ILibraryFileAlias`.
         """
 
+    @export_read_operation()
+    @operation_for_version("devel")
+    def getFileUrls():
+        """URLs for all the files produced by this build.
+
+        :return: A collection of URLs for this build.
+        """
+
     def getLayerFileByDigest(layer_file_digest):
         """Retrieve a layer file by the digest.
 
diff --git a/lib/lp/oci/model/ocirecipebuild.py b/lib/lp/oci/model/ocirecipebuild.py
index 4ad0f4f..2dee003 100644
--- a/lib/lp/oci/model/ocirecipebuild.py
+++ b/lib/lp/oci/model/ocirecipebuild.py
@@ -67,6 +67,7 @@ from lp.services.database.interfaces import (
 from lp.services.database.stormbase import StormBase
 from lp.services.job.interfaces.job import JobStatus
 from lp.services.job.model.job import Job
+from lp.services.librarian.browser import ProxiedLibraryFileAlias
 from lp.services.librarian.model import (
     LibraryFileAlias,
     LibraryFileContent,
@@ -293,6 +294,15 @@ class OCIRecipeBuild(PackageBuildMixin, StormBase):
 
         raise NotFoundError(filename)
 
+    def lfaUrl(self, lfa):
+        """Return the URL for a LibraryFileAlias in this context."""
+        if lfa is None:
+            return None
+        return ProxiedLibraryFileAlias(lfa, self).http_url
+
+    def getFileUrls(self):
+        return [self.lfaUrl(lfa) for _, lfa, _ in self.getFiles()]
+
     @cachedproperty
     def eta(self):
         """The datetime when the build job is estimated to complete.
diff --git a/lib/lp/oci/tests/test_ocirecipebuild.py b/lib/lp/oci/tests/test_ocirecipebuild.py
index 1ec8718..8a9c33b 100644
--- a/lib/lp/oci/tests/test_ocirecipebuild.py
+++ b/lib/lp/oci/tests/test_ocirecipebuild.py
@@ -57,6 +57,7 @@ from lp.services.authserver.xmlrpc import AuthServerAPIView
 from lp.services.config import config
 from lp.services.features.testing import FeatureFixture
 from lp.services.job.interfaces.job import JobStatus
+from lp.services.librarian.browser import ProxiedLibraryFileAlias
 from lp.services.macaroons.interfaces import (
     BadMacaroonContext,
     IMacaroonIssuer,
@@ -846,6 +847,23 @@ class TestOCIRecipeBuildWebservice(OCIConfigHelperMixin, TestCaseWithFactory):
         self.assertIsNotNone(build["upload_log_url"])
         self.assertCanOpenRedirectedUrl(browser, build["upload_log_url"])
 
+    def test_getFileUrls(self):
+        # API clients can fetch files attached to builds.
+        db_build = self.factory.makeOCIRecipeBuild(requester=self.person)
+        db_files = [self.factory.makeOCIFile(build=db_build) for i in range(2)]
+        build_url = api_url(db_build)
+        file_urls = [
+            ProxiedLibraryFileAlias(file.library_file, db_build).http_url
+            for file in db_files]
+        logout()
+        response = self.webservice.named_get(build_url, "getFileUrls")
+        self.assertEqual(200, response.status)
+        self.assertContentEqual(file_urls, response.jsonBody())
+        browser = self.getNonRedirectingBrowser(user=self.person)
+        browser.raiseHttpErrors = False
+        for file_url in file_urls:
+            self.assertCanOpenRedirectedUrl(browser, file_url)
+
 
 class TestOCIRecipeBuildMacaroonIssuer(
     MacaroonTestMixin, OCIConfigHelperMixin, TestCaseWithFactory):