← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~thumper/launchpad/fix-recipe-build-oops into lp:launchpad

 

Tim Penhey has proposed merging lp:~thumper/launchpad/fix-recipe-build-oops into lp:launchpad.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)
Related bugs:
  #692814 Sourcepacakgerecipebuild tales formatting fails with deleted recipes
  https://bugs.launchpad.net/bugs/692814

For more details, see:
https://code.launchpad.net/~thumper/launchpad/fix-recipe-build-oops/+merge/45319

This change updates the canonical_url for a source package recipe build.  Prior to this change
the build lived under the recipe itself.  However to maintain some traceability of builds
we now allow the builds to exist for deleted recipes.  This made them very hard to traverse
to.  The solution is to move the builds under the archive, just like the binary package builds.

However to have them co-exist, I needed to change the integral identifier at the end of the +build
to be the build farm job id, rather than the build id itself.
-- 
https://code.launchpad.net/~thumper/launchpad/fix-recipe-build-oops/+merge/45319
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~thumper/launchpad/fix-recipe-build-oops into lp:launchpad.
=== modified file 'lib/canonical/launchpad/doc/canonical_url_examples.txt'
--- lib/canonical/launchpad/doc/canonical_url_examples.txt	2010-10-19 18:44:31 +0000
+++ lib/canonical/launchpad/doc/canonical_url_examples.txt	2011-01-06 07:21:24 +0000
@@ -391,4 +391,4 @@
 
     >>> build = factory.makeSourcePackageRecipeBuild(recipe=recipe)
     >>> canonical_url(build)
-    u'http://code.launchpad.dev/~person-name.../+recipe/generic-string.../+build/...'
+    u'http://code.launchpad.dev/~person-name.../+archive/generic-string.../+build/...'

=== modified file 'lib/lp/app/browser/tales.py'
--- lib/lp/app/browser/tales.py	2010-11-03 08:17:36 +0000
+++ lib/lp/app/browser/tales.py	2011-01-06 07:21:24 +0000
@@ -1645,10 +1645,15 @@
 class SourcePackageRecipeBuildFormatterAPI(CustomizableFormatter):
     """Adapter providing fmt support for ISourcePackageRecipe objects."""
 
-    _link_summary_template = '%(name)s recipe build [%(owner)s/%(archive)s]'
+    _link_summary_template = '%(name)s [%(owner)s/%(archive)s]'
 
     def _link_summary_values(self):
-        return {'name': self._context.recipe.base_branch.unique_name,
+        if self._context.recipe is None:
+            name = 'build for deleted recipe'
+        else:
+            branch_name = self._context.recipe.base_branch.unique_name
+            name = '%s recipe build' % branch_name
+        return {'name': name,
                 'owner': self._context.archive.owner.name,
                 'archive': self._context.archive.name}
 

=== modified file 'lib/lp/buildmaster/interfaces/packagebuild.py'
--- lib/lp/buildmaster/interfaces/packagebuild.py	2010-11-16 10:55:23 +0000
+++ lib/lp/buildmaster/interfaces/packagebuild.py	2011-01-06 07:21:24 +0000
@@ -37,6 +37,10 @@
 
     id = Attribute('The package build ID.')
 
+    url_id = Attribute(
+        'A unique identifier for accessing the builds. '
+        'Used for the canonical_url generation.')
+
     archive = exported(
         Reference(
             title=_('Archive'), schema=IArchive,

=== modified file 'lib/lp/buildmaster/model/packagebuild.py'
--- lib/lp/buildmaster/model/packagebuild.py	2010-12-15 22:30:35 +0000
+++ lib/lp/buildmaster/model/packagebuild.py	2011-01-06 07:21:24 +0000
@@ -94,6 +94,10 @@
     build_farm_job_id = Int(name='build_farm_job', allow_none=False)
     build_farm_job = Reference(build_farm_job_id, 'BuildFarmJob.id')
 
+    @property
+    def url_id(self):
+        return self.build_farm_job_id
+
     # The following two properties are part of the IPackageBuild
     # interface, but need to be provided by derived classes.
     distribution = None

=== modified file 'lib/lp/code/browser/configure.zcml'
--- lib/lp/code/browser/configure.zcml	2010-12-15 06:47:38 +0000
+++ lib/lp/code/browser/configure.zcml	2011-01-06 07:21:24 +0000
@@ -1195,8 +1195,8 @@
         rootsite="code" />
     <browser:url
         for="lp.code.interfaces.sourcepackagerecipebuild.ISourcePackageRecipeBuild"
-        attribute_to_parent="recipe"
-        path_expression="string:+build/${id}"
+        attribute_to_parent="archive"
+        path_expression="string:+build/${url_id}"
         rootsite="code" />
     <browser:menus
         classes="SourcePackageRecipeBuildContextMenu"

=== modified file 'lib/lp/code/browser/tests/test_sourcepackagerecipe.py'
--- lib/lp/code/browser/tests/test_sourcepackagerecipe.py	2010-12-22 02:01:36 +0000
+++ lib/lp/code/browser/tests/test_sourcepackagerecipe.py	2011-01-06 07:21:24 +0000
@@ -1192,8 +1192,7 @@
         """Test the basic index page."""
         main_text = self.getMainText(self.makeBuild(), '+index')
         self.assertTextMatchesExpressionIgnoreWhitespace("""\
-            Code
-            my-recipe
+            Owner Code PPA named build for Owner
             created .*
             Build status
             Needs building
@@ -1223,8 +1222,7 @@
         main_text = self.getMainText(
             release.source_package_recipe_build, '+index')
         self.assertTextMatchesExpressionIgnoreWhitespace("""\
-            Code
-            my-recipe
+            Owner Code PPA named build for Owner
             created .*
             Build status
             Successfully built

=== modified file 'lib/lp/code/browser/tests/test_tales.py'
--- lib/lp/code/browser/tests/test_tales.py	2010-10-04 19:50:45 +0000
+++ lib/lp/code/browser/tests/test_tales.py	2011-01-06 07:21:24 +0000
@@ -9,12 +9,14 @@
 import unittest
 
 from storm.store import Store
+from testtools.matchers import Equals
 from zope.security.proxy import removeSecurityProxy
 
 from canonical.launchpad.webapp.publisher import canonical_url
 from canonical.testing.layers import LaunchpadFunctionalLayer
 from lp.testing import (
     login,
+    person_logged_in,
     test_tales,
     TestCaseWithFactory,
     )
@@ -174,6 +176,38 @@
             diff.diff_text.getURL(), test_tales('diff/fmt:url', diff=diff))
 
 
+class TestSourcePackageRecipeBuild(TestCaseWithFactory):
+    """Test the formatter for SourcePackageRecipeBuilds."""
+
+    layer = LaunchpadFunctionalLayer
+
+    def test_link(self):
+        eric = self.factory.makePerson(name='eric')
+        ppa = self.factory.makeArchive(owner=eric, name='ppa')
+        build = self.factory.makeSourcePackageRecipeBuild(
+            archive=ppa)
+        self.assertThat(
+            test_tales('build/fmt:link', build=build),
+            Equals(
+                '<a href="http://code.launchpad.dev/~eric/+archive/ppa/'
+                '+build/%s">%s recipe build [eric/ppa]</a>'
+                % (build.url_id, build.recipe.base_branch.unique_name)))
+
+    def test_link_no_recipe(self):
+        eric = self.factory.makePerson(name='eric')
+        ppa = self.factory.makeArchive(owner=eric, name='ppa')
+        build = self.factory.makeSourcePackageRecipeBuild(
+            archive=ppa)
+        with person_logged_in(build.recipe.owner):
+            build.recipe.destroySelf()
+        self.assertThat(
+            test_tales('build/fmt:link', build=build),
+            Equals(
+                '<a href="http://code.launchpad.dev/~eric/+archive/ppa/'
+                '+build/%s">build for deleted recipe [eric/ppa]</a>'
+                % (build.url_id, )))
+
+
 def test_suite():
     return unittest.TestLoader().loadTestsFromName(__name__)
 

=== modified file 'lib/lp/code/mail/tests/test_sourcepackagerecipebuild.py'
--- lib/lp/code/mail/tests/test_sourcepackagerecipebuild.py	2010-12-08 17:22:23 +0000
+++ lib/lp/code/mail/tests/test_sourcepackagerecipebuild.py	2011-01-06 07:21:24 +0000
@@ -12,6 +12,7 @@
 from zope.security.proxy import removeSecurityProxy
 
 from canonical.config import config
+from canonical.launchpad.webapp import canonical_url
 from canonical.testing.layers import LaunchpadFunctionalLayer
 from lp.buildmaster.enums import BuildStatus
 from lp.code.mail.sourcepackagerecipebuild import (
@@ -73,9 +74,9 @@
         body, footer = ctrl.body.split('\n-- \n')
         self.assertEqual(
             expected_body % build.log.getURL(), body)
+        build_url = canonical_url(build)
         self.assertEqual(
-            'http://code.launchpad.dev/~person/+recipe/recipe/+build/1\n'
-            'You are the requester of the build.\n', footer)
+            '%s\nYou are the requester of the build.\n' % build_url, footer)
         self.assertEqual(
             config.canonical.noreply_from_address, ctrl.from_addr)
         self.assertEqual(
@@ -104,9 +105,9 @@
             'Build for superseded Source' % (build.id), ctrl.subject)
         body, footer = ctrl.body.split('\n-- \n')
         self.assertEqual(superseded_body, body)
+        build_url = canonical_url(build)
         self.assertEqual(
-            'http://code.launchpad.dev/~person/+recipe/recipe/+build/1\n'
-            'You are the requester of the build.\n', footer)
+            '%s\nYou are the requester of the build.\n' % build_url, footer)
         self.assertEqual(
             config.canonical.noreply_from_address, ctrl.from_addr)
         self.assertEqual(

=== modified file 'lib/lp/soyuz/browser/archive.py'
--- lib/lp/soyuz/browser/archive.py	2010-12-20 05:46:40 +0000
+++ lib/lp/soyuz/browser/archive.py	2011-01-06 07:21:24 +0000
@@ -100,6 +100,7 @@
 from lp.app.browser.stringformatter import FormattersAPI
 from lp.app.errors import NotFoundError
 from lp.buildmaster.enums import BuildStatus
+from lp.buildmaster.interfaces.buildfarmjob import IBuildFarmJobSet
 from lp.registry.interfaces.person import (
     IPersonSet,
     PersonVisibility,
@@ -137,10 +138,7 @@
     )
 from lp.soyuz.interfaces.archivepermission import IArchivePermissionSet
 from lp.soyuz.interfaces.archivesubscriber import IArchiveSubscriberSet
-from lp.soyuz.interfaces.binarypackagebuild import (
-    BuildSetStatus,
-    IBinaryPackageBuildSet,
-    )
+from lp.soyuz.interfaces.binarypackagebuild import BuildSetStatus
 from lp.soyuz.interfaces.binarypackagename import IBinaryPackageNameSet
 from lp.soyuz.interfaces.component import IComponentSet
 from lp.soyuz.interfaces.packagecopyrequest import IPackageCopyRequestSet
@@ -232,7 +230,8 @@
         except ValueError:
             return None
         try:
-            return getUtility(IBinaryPackageBuildSet).getByBuildID(build_id)
+            build_job = getUtility(IBuildFarmJobSet).getByID(build_id)
+            return build_job.getSpecificJob()
         except NotFoundError:
             return None
 

=== modified file 'lib/lp/soyuz/browser/build.py'
--- lib/lp/soyuz/browser/build.py	2010-12-16 12:48:14 +0000
+++ lib/lp/soyuz/browser/build.py	2011-01-06 07:21:24 +0000
@@ -84,7 +84,7 @@
 
     @property
     def path(self):
-        return u"+build/%d" % self.context.id
+        return u"+build/%d" % self.context.url_id
 
 
 class BuildNavigation(GetitemNavigation, FileNavigationMixin):

=== modified file 'lib/lp/soyuz/browser/distributionsourcepackagerelease.py'
--- lib/lp/soyuz/browser/distributionsourcepackagerelease.py	2010-08-31 11:31:04 +0000
+++ lib/lp/soyuz/browser/distributionsourcepackagerelease.py	2011-01-06 07:21:24 +0000
@@ -24,9 +24,9 @@
 from canonical.lazr.utils import smartquote
 from lp.app.errors import NotFoundError
 from lp.archivepublisher.debversion import Version
+from lp.buildmaster.interfaces.buildfarmjob import IBuildFarmJobSet
 from lp.services.propertycache import cachedproperty
 from lp.soyuz.enums import PackagePublishingStatus
-from lp.soyuz.interfaces.binarypackagebuild import IBinaryPackageBuildSet
 from lp.soyuz.interfaces.distributionsourcepackagerelease import (
     IDistributionSourcePackageRelease,
     )
@@ -50,7 +50,8 @@
         except ValueError:
             return None
         try:
-            return getUtility(IBinaryPackageBuildSet).getByBuildID(build_id)
+            build_job = getUtility(IBuildFarmJobSet).getByID(build_id)
+            return build_job.getSpecificJob()
         except NotFoundError:
             return None
 

=== modified file 'lib/lp/soyuz/stories/soyuz/xx-build-record.txt'
--- lib/lp/soyuz/stories/soyuz/xx-build-record.txt	2010-12-16 12:48:14 +0000
+++ lib/lp/soyuz/stories/soyuz/xx-build-record.txt	2011-01-06 07:21:24 +0000
@@ -543,7 +543,7 @@
     ...
 
     >>> print anon_browser.getLink('~cprov/product/mybranch recipe build').url
-    http://code.launchpad.dev/~cprov/+recipe/myrecipe/+build/1
+    http://code.launchpad.dev/~cprov/+archive/ppa/+build/...
 
 Finally, the 'Build files' section is identical for PPA builds.