← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] ~cjwatson/launchpad:oci-recipe-request-builds-link into launchpad:master

 

Colin Watson has proposed merging ~cjwatson/launchpad:oci-recipe-request-builds-link into launchpad:master.

Commit message:
Add a "Request builds" link to OCIRecipe:+index

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

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

This makes https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/381910 slightly more useful.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:oci-recipe-request-builds-link into launchpad:master.
diff --git a/lib/lp/oci/browser/configure.zcml b/lib/lp/oci/browser/configure.zcml
index 548a725..941cccc 100644
--- a/lib/lp/oci/browser/configure.zcml
+++ b/lib/lp/oci/browser/configure.zcml
@@ -14,7 +14,9 @@
             attribute_to_parent="owner" />
         <browser:menus
             module="lp.oci.browser.ocirecipe"
-            classes="OCIRecipeNavigationMenu" />
+            classes="
+                OCIRecipeNavigationMenu
+                OCIRecipeContextMenu" />
         <browser:navigation
             module="lp.oci.browser.ocirecipe"
             classes="OCIRecipeNavigation" />
diff --git a/lib/lp/oci/browser/ocirecipe.py b/lib/lp/oci/browser/ocirecipe.py
index 9eafed3..42a32a7 100644
--- a/lib/lp/oci/browser/ocirecipe.py
+++ b/lib/lp/oci/browser/ocirecipe.py
@@ -9,6 +9,7 @@ __metaclass__ = type
 __all__ = [
     'OCIRecipeAddView',
     'OCIRecipeAdminView',
+    'OCIRecipeContextMenu',
     'OCIRecipeDeleteView',
     'OCIRecipeEditView',
     'OCIRecipeNavigation',
@@ -53,6 +54,7 @@ from lp.services.helpers import english_list
 from lp.services.propertycache import cachedproperty
 from lp.services.webapp import (
     canonical_url,
+    ContextMenu,
     enabled_with_permission,
     LaunchpadView,
     Link,
@@ -114,6 +116,20 @@ class OCIRecipeNavigationMenu(NavigationMenu):
         return Link("+delete", "Delete OCI recipe", icon="trash-icon")
 
 
+class OCIRecipeContextMenu(ContextMenu):
+    """Context menu for OCI recipes."""
+
+    usedfor = IOCIRecipe
+
+    facet = 'overview'
+
+    links = ('request_builds',)
+
+    @enabled_with_permission('launchpad.Edit')
+    def request_builds(self):
+        return Link('+request-builds', 'Request builds', icon='add')
+
+
 class OCIRecipeView(LaunchpadView):
     """Default view of an OCI recipe."""
 
diff --git a/lib/lp/oci/browser/tests/test_ocirecipe.py b/lib/lp/oci/browser/tests/test_ocirecipe.py
index a956071..1dfb3df 100644
--- a/lib/lp/oci/browser/tests/test_ocirecipe.py
+++ b/lib/lp/oci/browser/tests/test_ocirecipe.py
@@ -670,6 +670,33 @@ class TestOCIRecipeView(BaseTestOCIRecipeView):
             Needs building in .* \(estimated\) 386
             """, self.getMainText(build.recipe))
 
+    def test_index_request_builds_link(self):
+        # Recipe owners get a link to allow requesting builds.
+        owner = self.factory.makePerson()
+        distroseries = self.factory.makeDistroSeries()
+        oci_project = self.factory.makeOCIProject(
+            pillar=distroseries.distribution)
+        recipe = self.factory.makeOCIRecipe(
+            registrant=owner, owner=owner, oci_project=oci_project)
+        recipe_name = recipe.name
+        browser = self.getViewBrowser(recipe, user=owner)
+        browser.getLink("Request builds").click()
+        self.assertIn("Request builds for %s" % recipe_name, browser.contents)
+
+    def test_index_request_builds_link_unauthorized(self):
+        # People who cannot edit the recipe do not get a link to allow
+        # requesting builds.
+        distroseries = self.factory.makeDistroSeries()
+        oci_project = self.factory.makeOCIProject(
+            pillar=distroseries.distribution)
+        recipe = self.factory.makeOCIRecipe(oci_project=oci_project)
+        recipe_url = canonical_url(recipe)
+        browser = self.getViewBrowser(recipe, user=self.person)
+        self.assertRaises(LinkNotFoundError, browser.getLink, "Request builds")
+        self.assertRaises(
+            Unauthorized, self.getUserBrowser, recipe_url + "/+request-builds",
+            user=self.person)
+
     def setStatus(self, build, status):
         build.updateStatus(
             BuildStatus.BUILDING, date_started=build.date_created)
diff --git a/lib/lp/oci/templates/ocirecipe-index.pt b/lib/lp/oci/templates/ocirecipe-index.pt
index fc75d75..f7df628 100644
--- a/lib/lp/oci/templates/ocirecipe-index.pt
+++ b/lib/lp/oci/templates/ocirecipe-index.pt
@@ -112,6 +112,10 @@
     <p tal:condition="not: view/builds">
       This OCI recipe has not been built yet.
     </p>
+    <div tal:define="link context/menu:context/request_builds"
+         tal:condition="link/enabled">
+      <tal:request-builds replace="structure link/fmt:link"/>
+    </div>
   </div>
 
 </body>