← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] ~pappacena/launchpad:ui-manage-ocirecipe-for-projects into launchpad:master

 

Thiago F. Pappacena has proposed merging ~pappacena/launchpad:ui-manage-ocirecipe-for-projects into launchpad:master with ~pappacena/launchpad:ui-create-ociproject-for-projects as a prerequisite.

Commit message:
Adjustments to make OCIRecipe work also with OCIProjects based on project, rather then distributions.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~pappacena/launchpad/+git/launchpad/+merge/384755
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~pappacena/launchpad:ui-manage-ocirecipe-for-projects into launchpad:master.
diff --git a/lib/lp/oci/browser/tests/test_ocirecipe.py b/lib/lp/oci/browser/tests/test_ocirecipe.py
index 6633966..e25d463 100644
--- a/lib/lp/oci/browser/tests/test_ocirecipe.py
+++ b/lib/lp/oci/browser/tests/test_ocirecipe.py
@@ -91,8 +91,22 @@ class TestOCIRecipeNavigation(TestCaseWithFactory):
             "http://launchpad.test/~person/distro/+oci/oci-project/";
             "+recipe/recipe", canonical_url(recipe))
 
-    def test_recipe(self):
-        recipe = self.factory.makeOCIRecipe()
+    def test_recipe_traverse_distribution(self):
+        # Make sure we can reach recipe of distro-based OCI projects.
+        distro = self.factory.makeDistribution()
+        oci_project = self.factory.makeOCIProject(pillar=distro)
+        recipe = self.factory.makeOCIRecipe(oci_project=oci_project)
+        obj, _, _ = test_traverse(
+            "http://launchpad.test/~%s/%s/+oci/%s/+recipe/%s"; % (
+                recipe.owner.name, recipe.oci_project.pillar.name,
+                recipe.oci_project.name, recipe.name))
+        self.assertEqual(recipe, obj)
+
+    def test_recipe_traverse_project(self):
+        # Make sure we can reach recipe of project-based OCI projects.
+        project = self.factory.makeProduct()
+        oci_project = self.factory.makeOCIProject(pillar=project)
+        recipe = self.factory.makeOCIRecipe(oci_project=oci_project)
         obj, _, _ = test_traverse(
             "http://launchpad.test/~%s/%s/+oci/%s/+recipe/%s"; % (
                 recipe.owner.name, recipe.oci_project.pillar.name,
diff --git a/lib/lp/oci/model/ocirecipe.py b/lib/lp/oci/model/ocirecipe.py
index 8562778..245e730 100644
--- a/lib/lp/oci/model/ocirecipe.py
+++ b/lib/lp/oci/model/ocirecipe.py
@@ -36,6 +36,7 @@ from zope.interface import implementer
 from zope.security.interfaces import Unauthorized
 from zope.security.proxy import removeSecurityProxy
 
+from lp.app.interfaces.launchpad import ILaunchpadCelebrities
 from lp.app.interfaces.security import IAuthorization
 from lp.buildmaster.enums import BuildStatus
 from lp.buildmaster.interfaces.buildqueue import IBuildQueueSet
@@ -216,9 +217,12 @@ class OCIRecipe(Storm, WebhookTargetMixin):
 
     @property
     def distribution(self):
-        # XXX twom 2019-12-05 This may need to change when an OCIProject
-        # pillar isn't just a distribution
-        return self.oci_project.distribution
+        if self.oci_project.distribution:
+            return self.oci_project.distribution
+        # XXX pappacena 2020-05-28: If the related OCIProject is not
+        # based on distribution, maybe we should get the default distro from
+        # a feature flag, instead of hardcoding Ubuntu.
+        return getUtility(ILaunchpadCelebrities).ubuntu
 
     @property
     def distro_series(self):
@@ -237,9 +241,10 @@ class OCIRecipe(Storm, WebhookTargetMixin):
         """See `IOCIRecipe`."""
         clauses = [Processor.id == DistroArchSeries.processor_id]
         if self.distro_series is not None:
+            enabled_archs_resultset = removeSecurityProxy(
+                self.distro_series.enabled_architectures)
             clauses.append(DistroArchSeries.id.is_in(
-                self.distro_series.enabled_architectures.get_select_expr(
-                    DistroArchSeries.id)))
+                enabled_archs_resultset.get_select_expr(DistroArchSeries.id)))
         else:
             # We might not know the series if the OCI project's distribution
             # has no series at all, which can happen in tests.  Fall back to
diff --git a/lib/lp/registry/browser/personproduct.py b/lib/lp/registry/browser/personproduct.py
index 90f8b55..a249b27 100644
--- a/lib/lp/registry/browser/personproduct.py
+++ b/lib/lp/registry/browser/personproduct.py
@@ -1,4 +1,4 @@
-# Copyright 2009 Canonical Ltd.  This software is licensed under the
+# Copyright 2009-2020 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 """Views, menus and traversal related to PersonProducts."""
@@ -10,19 +10,23 @@ __all__ = [
     'PersonProductNavigation',
     ]
 
-
-from zope.component import queryAdapter
+from zope.component import (
+    getUtility,
+    queryAdapter,
+    )
 from zope.interface import implementer
 from zope.traversing.interfaces import IPathAdapter
 
 from lp.app.errors import NotFoundError
 from lp.code.browser.vcslisting import PersonTargetDefaultVCSNavigationMixin
 from lp.code.interfaces.branchnamespace import get_branch_namespace
+from lp.registry.interfaces.personociproject import IPersonOCIProjectFactory
 from lp.registry.interfaces.personproduct import IPersonProduct
 from lp.services.webapp import (
     canonical_url,
     Navigation,
     StandardLaunchpadFacets,
+    stepthrough,
     )
 from lp.services.webapp.breadcrumb import Breadcrumb
 from lp.services.webapp.interfaces import IMultiFacetedBreadcrumb
@@ -33,6 +37,12 @@ class PersonProductNavigation(PersonTargetDefaultVCSNavigationMixin,
     """Navigation to branches for this person/product."""
     usedfor = IPersonProduct
 
+    @stepthrough('+oci')
+    def traverse_oci(self, name):
+        oci_project = self.context.product.getOCIProject(name)
+        return getUtility(IPersonOCIProjectFactory).create(
+            self.context.person, oci_project)
+
     def traverse(self, branch_name):
         """Look for a branch in the person/product namespace."""
         namespace = get_branch_namespace(

Follow ups