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

Proposed by Tim Penhey
Status: Merged
Approved by: Tim Penhey
Approved revision: no longer in the source branch.
Merged at revision: 12204
Proposed branch: lp:~thumper/launchpad/fix-recipe-build-oops
Merge into: lp:launchpad
Diff against target: 1205 lines (+255/-160)
32 files modified
lib/canonical/launchpad/doc/canonical_url_examples.txt (+0/-12)
lib/canonical/launchpad/pagetests/basics/notfound-traversals.txt (+0/-1)
lib/lp/app/browser/tales.py (+7/-2)
lib/lp/buildmaster/interfaces/packagebuild.py (+4/-0)
lib/lp/buildmaster/model/packagebuild.py (+4/-0)
lib/lp/code/browser/configure.zcml (+4/-10)
lib/lp/code/browser/sourcepackagerecipe.py (+0/-11)
lib/lp/code/browser/sourcepackagerecipebuild.py (+1/-0)
lib/lp/code/browser/tests/test_sourcepackagerecipe.py (+16/-4)
lib/lp/code/browser/tests/test_sourcepackagerecipebuild.py (+16/-0)
lib/lp/code/browser/tests/test_tales.py (+37/-0)
lib/lp/code/mail/tests/test_sourcepackagerecipebuild.py (+5/-4)
lib/lp/registry/browser/tests/test_person_view.py (+4/-4)
lib/lp/soyuz/browser/archive.py (+7/-17)
lib/lp/soyuz/browser/build.py (+37/-2)
lib/lp/soyuz/browser/builder.py (+11/-15)
lib/lp/soyuz/browser/distributionsourcepackagerelease.py (+3/-17)
lib/lp/soyuz/browser/tests/build-views.txt (+3/-3)
lib/lp/soyuz/browser/tests/test_builder.py (+38/-0)
lib/lp/soyuz/doc/binarypackagebuild.txt (+3/-3)
lib/lp/soyuz/doc/build-failedtoupload-workflow.txt (+3/-3)
lib/lp/soyuz/doc/build-notification.txt (+8/-8)
lib/lp/soyuz/stories/ppa/xx-ppa-files.txt (+6/-6)
lib/lp/soyuz/stories/soyuz/xx-binarypackagerelease-index.txt (+2/-2)
lib/lp/soyuz/stories/soyuz/xx-build-record.txt (+14/-14)
lib/lp/soyuz/stories/soyuz/xx-build-redirect.txt (+1/-3)
lib/lp/soyuz/stories/soyuz/xx-buildfarm-index.txt (+1/-1)
lib/lp/soyuz/stories/soyuz/xx-distributionsourcepackagerelease-pages.txt (+1/-1)
lib/lp/soyuz/stories/soyuz/xx-private-builds.txt (+9/-9)
lib/lp/soyuz/stories/webservice/xx-builds.txt (+6/-6)
lib/lp/soyuz/tests/test_binarypackagebuild.py (+2/-2)
lib/lp/testing/factory.py (+2/-0)
To merge this branch: bzr merge lp:~thumper/launchpad/fix-recipe-build-oops
Reviewer Review Type Date Requested Status
Julian Edwards (community) code Approve
Michael Hudson-Doyle Approve
Steve Kowalik (community) code* Approve
Review via email: mp+45319@code.launchpad.net

Commit message

[r=julian-edwards,mwhudson,stevenk][ui=none][bug=692814] Make recipe builds live under the archive, not the recipe.

Description of the change

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.

To post a comment you must log in.
Revision history for this message
Steve Kowalik (stevenk) wrote :

This looks like a good change, thanks.

review: Approve (code*)
Revision history for this message
Michael Hudson-Doyle (mwhudson) wrote :

The code seems perfectly fine.

The only issue is the changing of the urls of all builds, it seems to be an open question about whether that's important so I'll leave it up to you :-)

review: Approve
Revision history for this message
Tim Penhey (thumper) wrote :

Code has been updated to use +buildjob for the new urls and adding redirects for the old +build urls.

Revision history for this message
Julian Edwards (julian-edwards) wrote :

Looking pretty good, thanks for the change Tim. There's just a couple of comments I have:

1. Can you change /builders/buildjob/NNNN to /builders/+buildjob/NNNNN so that it's consistent with /builders/+build/NNNNN

Sorry, you can blame me for getting this wrong since I missed the "+" in the email.

2. The stepthrough('+buildjob') code looks like it can be refactored somewhere, the same code is in three different places.

Cheers
J

review: Needs Fixing (code)
Revision history for this message
Tim Penhey (thumper) wrote :

Done.

Also fixed a bunch of test failures that referred to the old urls.

Revision history for this message
Julian Edwards (julian-edwards) wrote :

Looks good!

Can you add the + to buildjob on lines 657 and 668 of the diff and you're good to land.

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/canonical/launchpad/doc/canonical_url_examples.txt'
2--- lib/canonical/launchpad/doc/canonical_url_examples.txt 2010-10-19 18:44:31 +0000
3+++ lib/canonical/launchpad/doc/canonical_url_examples.txt 2011-01-14 10:09:39 +0000
4@@ -380,15 +380,3 @@
5
6 >>> canonical_url(celebs.ubuntu.getSpecification('media-integrity-check'))
7 u'http://blueprints.launchpad.dev/ubuntu/+spec/media-integrity-check'
8-
9-
10-SourcePackageRecipes
11-====================
12-
13- >>> recipe = factory.makeSourcePackageRecipe()
14- >>> canonical_url(recipe)
15- u'http://code.launchpad.dev/~person-name.../+recipe/generic-string...'
16-
17- >>> build = factory.makeSourcePackageRecipeBuild(recipe=recipe)
18- >>> canonical_url(build)
19- u'http://code.launchpad.dev/~person-name.../+recipe/generic-string.../+build/...'
20
21=== modified file 'lib/canonical/launchpad/pagetests/basics/notfound-traversals.txt'
22--- lib/canonical/launchpad/pagetests/basics/notfound-traversals.txt 2011-01-04 16:08:57 +0000
23+++ lib/canonical/launchpad/pagetests/basics/notfound-traversals.txt 2011-01-14 10:09:39 +0000
24@@ -404,7 +404,6 @@
25 >>> check("/builders")
26 >>> check("/builders/bob/")
27 >>> check_redirect("/+builds", status=301)
28->>> check("/ubuntu/+source/pmount/0.1-1/+build/7/")
29
30 >>> check_redirect("/support/", status=301)
31
32
33=== modified file 'lib/lp/app/browser/tales.py'
34--- lib/lp/app/browser/tales.py 2011-01-11 01:09:43 +0000
35+++ lib/lp/app/browser/tales.py 2011-01-14 10:09:39 +0000
36@@ -1651,10 +1651,15 @@
37 class SourcePackageRecipeBuildFormatterAPI(CustomizableFormatter):
38 """Adapter providing fmt support for ISourcePackageRecipe objects."""
39
40- _link_summary_template = '%(name)s recipe build [%(owner)s/%(archive)s]'
41+ _link_summary_template = '%(name)s [%(owner)s/%(archive)s]'
42
43 def _link_summary_values(self):
44- return {'name': self._context.recipe.base_branch.unique_name,
45+ if self._context.recipe is None:
46+ name = 'build for deleted recipe'
47+ else:
48+ branch_name = self._context.recipe.base_branch.unique_name
49+ name = '%s recipe build' % branch_name
50+ return {'name': name,
51 'owner': self._context.archive.owner.name,
52 'archive': self._context.archive.name}
53
54
55=== modified file 'lib/lp/buildmaster/interfaces/packagebuild.py'
56--- lib/lp/buildmaster/interfaces/packagebuild.py 2010-11-16 10:55:23 +0000
57+++ lib/lp/buildmaster/interfaces/packagebuild.py 2011-01-14 10:09:39 +0000
58@@ -37,6 +37,10 @@
59
60 id = Attribute('The package build ID.')
61
62+ url_id = Attribute(
63+ 'A unique identifier for accessing the builds. '
64+ 'Used for the canonical_url generation.')
65+
66 archive = exported(
67 Reference(
68 title=_('Archive'), schema=IArchive,
69
70=== modified file 'lib/lp/buildmaster/model/packagebuild.py'
71--- lib/lp/buildmaster/model/packagebuild.py 2011-01-07 00:23:44 +0000
72+++ lib/lp/buildmaster/model/packagebuild.py 2011-01-14 10:09:39 +0000
73@@ -94,6 +94,10 @@
74 build_farm_job_id = Int(name='build_farm_job', allow_none=False)
75 build_farm_job = Reference(build_farm_job_id, 'BuildFarmJob.id')
76
77+ @property
78+ def url_id(self):
79+ return self.build_farm_job_id
80+
81 # The following two properties are part of the IPackageBuild
82 # interface, but need to be provided by derived classes.
83 distribution = None
84
85=== modified file 'lib/lp/code/browser/configure.zcml'
86--- lib/lp/code/browser/configure.zcml 2010-12-15 06:47:38 +0000
87+++ lib/lp/code/browser/configure.zcml 2011-01-14 10:09:39 +0000
88@@ -1195,17 +1195,14 @@
89 rootsite="code" />
90 <browser:url
91 for="lp.code.interfaces.sourcepackagerecipebuild.ISourcePackageRecipeBuild"
92- attribute_to_parent="recipe"
93- path_expression="string:+build/${id}"
94- rootsite="code" />
95+ attribute_to_parent="archive"
96+ path_expression="string:+buildjob/${url_id}"
97+ />
98 <browser:menus
99 classes="SourcePackageRecipeBuildContextMenu"
100 module="lp.code.browser.sourcepackagerecipebuild"/>
101
102 <browser:navigation
103- module="lp.code.browser.sourcepackagerecipe"
104- classes="SourcePackageRecipeNavigation" />
105- <browser:navigation
106 module="lp.code.browser.sourcepackagerecipebuild"
107 classes="SourcePackageRecipeBuildNavigation" />
108
109@@ -1234,24 +1231,21 @@
110 <browser:defaultView
111 for="lp.code.interfaces.sourcepackagerecipebuild.ISourcePackageRecipeBuild"
112 name="+index"
113- layer="lp.code.publisher.CodeLayer"/>
114+ />
115 <browser:page
116 for="lp.code.interfaces.sourcepackagerecipebuild.ISourcePackageRecipeBuild"
117- layer="lp.code.publisher.CodeLayer"
118 class="lp.code.browser.sourcepackagerecipebuild.SourcePackageRecipeBuildView"
119 name="+index"
120 template="../templates/sourcepackagerecipebuild-index.pt"
121 permission="launchpad.View"/>
122 <browser:page
123 for="lp.code.interfaces.sourcepackagerecipebuild.ISourcePackageRecipeBuild"
124- layer="lp.code.publisher.CodeLayer"
125 class="lp.code.browser.sourcepackagerecipebuild.SourcePackageRecipeBuildCancelView"
126 name="+cancel"
127 template="../../app/templates/generic-edit.pt"
128 permission="launchpad.Admin"/>
129 <browser:page
130 for="lp.code.interfaces.sourcepackagerecipebuild.ISourcePackageRecipeBuild"
131- layer="lp.code.publisher.CodeLayer"
132 class="lp.code.browser.sourcepackagerecipebuild.SourcePackageRecipeBuildRescoreView"
133 name="+rescore"
134 template="../../app/templates/generic-edit.pt"
135
136=== modified file 'lib/lp/code/browser/sourcepackagerecipe.py'
137--- lib/lp/code/browser/sourcepackagerecipe.py 2011-01-14 05:46:14 +0000
138+++ lib/lp/code/browser/sourcepackagerecipe.py 2011-01-14 10:09:39 +0000
139@@ -144,17 +144,6 @@
140 yield item
141
142
143-class SourcePackageRecipeNavigation(Navigation):
144- """Navigation from the SourcePackageRecipe."""
145-
146- usedfor = ISourcePackageRecipe
147-
148- @stepthrough('+build')
149- def traverse_build(self, id):
150- """Traverse to this recipe's builds."""
151- return getUtility(ISourcePackageRecipeBuildSource).getById(int(id))
152-
153-
154 class SourcePackageRecipeNavigationMenu(NavigationMenu):
155 """Navigation menu for sourcepackage recipes."""
156
157
158=== modified file 'lib/lp/code/browser/sourcepackagerecipebuild.py'
159--- lib/lp/code/browser/sourcepackagerecipebuild.py 2010-11-26 00:29:09 +0000
160+++ lib/lp/code/browser/sourcepackagerecipebuild.py 2011-01-14 10:09:39 +0000
161@@ -43,6 +43,7 @@
162 BuildStatus.SUPERSEDED,
163 BuildStatus.FAILEDTOUPLOAD,)
164
165+
166 class SourcePackageRecipeBuildNavigation(Navigation, FileNavigationMixin):
167
168 usedfor = ISourcePackageRecipeBuild
169
170=== modified file 'lib/lp/code/browser/tests/test_sourcepackagerecipe.py'
171--- lib/lp/code/browser/tests/test_sourcepackagerecipe.py 2011-01-14 05:46:14 +0000
172+++ lib/lp/code/browser/tests/test_sourcepackagerecipe.py 2011-01-14 10:09:39 +0000
173@@ -52,12 +52,26 @@
174 BrowserTestCase,
175 login,
176 person_logged_in,
177+ TestCaseWithFactory,
178 time_counter,
179 )
180 from lp.testing.factory import remove_security_proxy_and_shout_at_engineer
181 from lp.testing.views import create_initialized_view
182
183
184+class TestCanonicalUrlForRecipe(TestCaseWithFactory):
185+
186+ layer = DatabaseFunctionalLayer
187+
188+ def test_canonical_url(self):
189+ owner = self.factory.makePerson(name='recipe-owner')
190+ recipe = self.factory.makeSourcePackageRecipe(
191+ owner=owner, name=u'recipe-name')
192+ self.assertEqual(
193+ 'http://code.launchpad.dev/~recipe-owner/+recipe/recipe-name',
194+ canonical_url(recipe))
195+
196+
197 class TestCaseForRecipe(BrowserTestCase):
198 """Create some sample data for recipe tests."""
199
200@@ -1237,8 +1251,7 @@
201 """Test the basic index page."""
202 main_text = self.getMainText(self.makeBuild(), '+index')
203 self.assertTextMatchesExpressionIgnoreWhitespace("""\
204- Code
205- my-recipe
206+ Owner PPA named build for Owner
207 created .*
208 Build status
209 Needs building
210@@ -1268,8 +1281,7 @@
211 main_text = self.getMainText(
212 release.source_package_recipe_build, '+index')
213 self.assertTextMatchesExpressionIgnoreWhitespace("""\
214- Code
215- my-recipe
216+ Owner PPA named build for Owner
217 created .*
218 Build status
219 Successfully built
220
221=== modified file 'lib/lp/code/browser/tests/test_sourcepackagerecipebuild.py'
222--- lib/lp/code/browser/tests/test_sourcepackagerecipebuild.py 2010-10-04 19:50:45 +0000
223+++ lib/lp/code/browser/tests/test_sourcepackagerecipebuild.py 2011-01-14 10:09:39 +0000
224@@ -8,6 +8,7 @@
225
226 from mechanize import LinkNotFoundError
227 from storm.locals import Store
228+from testtools.matchers import StartsWith
229 import transaction
230 from zope.component import getUtility
231 from zope.security.interfaces import Unauthorized
232@@ -28,9 +29,24 @@
233 BrowserTestCase,
234 login,
235 logout,
236+ TestCaseWithFactory,
237 )
238
239
240+class TestCanonicalUrlForRecipeBuild(TestCaseWithFactory):
241+
242+ layer = DatabaseFunctionalLayer
243+
244+ def test_canonical_url(self):
245+ owner = self.factory.makePerson(name='ppa-owner')
246+ ppa = self.factory.makeArchive(owner=owner, name='ppa')
247+ build = self.factory.makeSourcePackageRecipeBuild(archive=ppa)
248+ self.assertThat(
249+ canonical_url(build),
250+ StartsWith(
251+ 'http://launchpad.dev/~ppa-owner/+archive/ppa/+buildjob/'))
252+
253+
254 class TestSourcePackageRecipeBuild(BrowserTestCase):
255 """Create some sample data for recipe tests."""
256
257
258=== modified file 'lib/lp/code/browser/tests/test_tales.py'
259--- lib/lp/code/browser/tests/test_tales.py 2010-10-04 19:50:45 +0000
260+++ lib/lp/code/browser/tests/test_tales.py 2011-01-14 10:09:39 +0000
261@@ -9,12 +9,16 @@
262 import unittest
263
264 from storm.store import Store
265+from testtools.matchers import Equals
266+from zope.component import queryAdapter
267 from zope.security.proxy import removeSecurityProxy
268+from zope.traversing.interfaces import IPathAdapter
269
270 from canonical.launchpad.webapp.publisher import canonical_url
271 from canonical.testing.layers import LaunchpadFunctionalLayer
272 from lp.testing import (
273 login,
274+ person_logged_in,
275 test_tales,
276 TestCaseWithFactory,
277 )
278@@ -174,6 +178,39 @@
279 diff.diff_text.getURL(), test_tales('diff/fmt:url', diff=diff))
280
281
282+class TestSourcePackageRecipeBuild(TestCaseWithFactory):
283+ """Test the formatter for SourcePackageRecipeBuilds."""
284+
285+ layer = LaunchpadFunctionalLayer
286+
287+ def test_link(self):
288+ eric = self.factory.makePerson(name='eric')
289+ ppa = self.factory.makeArchive(owner=eric, name='ppa')
290+ build = self.factory.makeSourcePackageRecipeBuild(
291+ archive=ppa)
292+ adapter = queryAdapter(build, IPathAdapter, 'fmt')
293+ self.assertThat(
294+ adapter.link(None),
295+ Equals(
296+ '<a href="%s">%s recipe build [eric/ppa]</a>'
297+ % (canonical_url(build, path_only_if_possible=True),
298+ build.recipe.base_branch.unique_name)))
299+
300+ def test_link_no_recipe(self):
301+ eric = self.factory.makePerson(name='eric')
302+ ppa = self.factory.makeArchive(owner=eric, name='ppa')
303+ build = self.factory.makeSourcePackageRecipeBuild(
304+ archive=ppa)
305+ with person_logged_in(build.recipe.owner):
306+ build.recipe.destroySelf()
307+ adapter = queryAdapter(build, IPathAdapter, 'fmt')
308+ self.assertThat(
309+ adapter.link(None),
310+ Equals(
311+ '<a href="%s">build for deleted recipe [eric/ppa]</a>'
312+ % (canonical_url(build, path_only_if_possible=True), )))
313+
314+
315 def test_suite():
316 return unittest.TestLoader().loadTestsFromName(__name__)
317
318
319=== modified file 'lib/lp/code/mail/tests/test_sourcepackagerecipebuild.py'
320--- lib/lp/code/mail/tests/test_sourcepackagerecipebuild.py 2010-12-08 17:22:23 +0000
321+++ lib/lp/code/mail/tests/test_sourcepackagerecipebuild.py 2011-01-14 10:09:39 +0000
322@@ -12,6 +12,7 @@
323 from zope.security.proxy import removeSecurityProxy
324
325 from canonical.config import config
326+from canonical.launchpad.webapp import canonical_url
327 from canonical.testing.layers import LaunchpadFunctionalLayer
328 from lp.buildmaster.enums import BuildStatus
329 from lp.code.mail.sourcepackagerecipebuild import (
330@@ -73,9 +74,9 @@
331 body, footer = ctrl.body.split('\n-- \n')
332 self.assertEqual(
333 expected_body % build.log.getURL(), body)
334+ build_url = canonical_url(build)
335 self.assertEqual(
336- 'http://code.launchpad.dev/~person/+recipe/recipe/+build/1\n'
337- 'You are the requester of the build.\n', footer)
338+ '%s\nYou are the requester of the build.\n' % build_url, footer)
339 self.assertEqual(
340 config.canonical.noreply_from_address, ctrl.from_addr)
341 self.assertEqual(
342@@ -104,9 +105,9 @@
343 'Build for superseded Source' % (build.id), ctrl.subject)
344 body, footer = ctrl.body.split('\n-- \n')
345 self.assertEqual(superseded_body, body)
346+ build_url = canonical_url(build)
347 self.assertEqual(
348- 'http://code.launchpad.dev/~person/+recipe/recipe/+build/1\n'
349- 'You are the requester of the build.\n', footer)
350+ '%s\nYou are the requester of the build.\n' % build_url, footer)
351 self.assertEqual(
352 config.canonical.noreply_from_address, ctrl.from_addr)
353 self.assertEqual(
354
355=== modified file 'lib/lp/registry/browser/tests/test_person_view.py'
356--- lib/lp/registry/browser/tests/test_person_view.py 2010-11-23 11:54:09 +0000
357+++ lib/lp/registry/browser/tests/test_person_view.py 2011-01-14 10:09:39 +0000
358@@ -663,16 +663,16 @@
359 self.view = create_view(self.user, name='+related-software')
360 html = self.view()
361 self.assertTrue(
362- '<a href="/ubuntutest/+source/foo/666/+build/%d">i386</a>' % (
363- self.build.id) in html)
364+ '<a href="/ubuntutest/+source/foo/666/+buildjob/%d">i386</a>' % (
365+ self.build.url_id) in html)
366
367 def test_related_ppa_packages_with_failed_build(self):
368 # The link to the failed build is displayed.
369 self.view = create_view(self.user, name='+ppa-packages')
370 html = self.view()
371 self.assertTrue(
372- '<a href="/ubuntutest/+source/foo/666/+build/%d">i386</a>' % (
373- self.build.id) in html)
374+ '<a href="/ubuntutest/+source/foo/666/+buildjob/%d">i386</a>' % (
375+ self.build.url_id) in html)
376
377
378 class TestPersonDeactivateAccountView(TestCaseWithFactory):
379
380=== modified file 'lib/lp/soyuz/browser/archive.py'
381--- lib/lp/soyuz/browser/archive.py 2011-01-13 17:23:57 +0000
382+++ lib/lp/soyuz/browser/archive.py 2011-01-14 10:09:39 +0000
383@@ -117,7 +117,10 @@
384 from lp.soyuz.adapters.archivesourcepublication import (
385 ArchiveSourcePublications,
386 )
387-from lp.soyuz.browser.build import BuildRecordsView
388+from lp.soyuz.browser.build import (
389+ BuildNavigationMixin,
390+ BuildRecordsView,
391+ )
392 from lp.soyuz.browser.sourceslist import (
393 SourcesListEntries,
394 SourcesListEntriesView,
395@@ -137,10 +140,7 @@
396 )
397 from lp.soyuz.interfaces.archivepermission import IArchivePermissionSet
398 from lp.soyuz.interfaces.archivesubscriber import IArchiveSubscriberSet
399-from lp.soyuz.interfaces.binarypackagebuild import (
400- BuildSetStatus,
401- IBinaryPackageBuildSet,
402- )
403+from lp.soyuz.interfaces.binarypackagebuild import BuildSetStatus
404 from lp.soyuz.interfaces.binarypackagename import IBinaryPackageNameSet
405 from lp.soyuz.interfaces.component import IComponentSet
406 from lp.soyuz.interfaces.packagecopyrequest import IPackageCopyRequestSet
407@@ -220,22 +220,12 @@
408 return u"+archive/%s" % self.context.name
409
410
411-class ArchiveNavigation(Navigation, FileNavigationMixin):
412+class ArchiveNavigation(Navigation, FileNavigationMixin,
413+ BuildNavigationMixin):
414 """Navigation methods for IArchive."""
415
416 usedfor = IArchive
417
418- @stepthrough('+build')
419- def traverse_build(self, name):
420- try:
421- build_id = int(name)
422- except ValueError:
423- return None
424- try:
425- return getUtility(IBinaryPackageBuildSet).getByBuildID(build_id)
426- except NotFoundError:
427- return None
428-
429 @stepthrough('+sourcepub')
430 def traverse_sourcepub(self, name):
431 return self._traverse_publication(name, source=True)
432
433=== modified file 'lib/lp/soyuz/browser/build.py'
434--- lib/lp/soyuz/browser/build.py 2011-01-12 13:15:28 +0000
435+++ lib/lp/soyuz/browser/build.py 2011-01-14 10:09:39 +0000
436@@ -9,6 +9,7 @@
437 'BuildBreadcrumb',
438 'BuildContextMenu',
439 'BuildNavigation',
440+ 'BuildNavigationMixin',
441 'BuildRecordsView',
442 'BuildRescoringView',
443 'BuildUrl',
444@@ -32,6 +33,7 @@
445 LaunchpadView,
446 Link,
447 StandardLaunchpadFacets,
448+ stepthrough,
449 )
450 from canonical.launchpad.webapp.authorization import check_permission
451 from canonical.launchpad.webapp.batching import BatchNavigator
452@@ -42,8 +44,12 @@
453 action,
454 LaunchpadFormView,
455 )
456-from lp.app.errors import UnexpectedFormData
457+from lp.app.errors import (
458+ NotFoundError,
459+ UnexpectedFormData,
460+ )
461 from lp.buildmaster.enums import BuildStatus
462+from lp.buildmaster.interfaces.buildfarmjob import IBuildFarmJobSet
463 from lp.services.job.interfaces.job import JobStatus
464 from lp.services.propertycache import cachedproperty
465 from lp.soyuz.enums import PackageUploadStatus
466@@ -84,13 +90,42 @@
467
468 @property
469 def path(self):
470- return u"+build/%d" % self.context.id
471+ return u"+buildjob/%d" % self.context.url_id
472
473
474 class BuildNavigation(GetitemNavigation, FileNavigationMixin):
475 usedfor = IBinaryPackageBuild
476
477
478+class BuildNavigationMixin:
479+ """Provide a simple way to traverse to builds."""
480+
481+ @stepthrough('+build')
482+ def traverse_build(self, name):
483+ try:
484+ build_id = int(name)
485+ except ValueError:
486+ return None
487+ try:
488+ build = getUtility(IBinaryPackageBuildSet).getByBuildID(build_id)
489+ except NotFoundError:
490+ return None
491+ else:
492+ return self.redirectSubTree(canonical_url(build))
493+
494+ @stepthrough('+buildjob')
495+ def traverse_buildjob(self, name):
496+ try:
497+ job_id = int(name)
498+ except ValueError:
499+ return None
500+ try:
501+ build_job = getUtility(IBuildFarmJobSet).getByID(job_id)
502+ return build_job.getSpecificJob()
503+ except NotFoundError:
504+ return None
505+
506+
507 class BuildFacets(StandardLaunchpadFacets):
508 """The links that will appear in the facet menu for an
509 IBinaryPackageBuild."""
510
511=== modified file 'lib/lp/soyuz/browser/builder.py'
512--- lib/lp/soyuz/browser/builder.py 2010-11-23 23:22:27 +0000
513+++ lib/lp/soyuz/browser/builder.py 2011-01-14 10:09:39 +0000
514@@ -49,29 +49,25 @@
515 LaunchpadEditFormView,
516 LaunchpadFormView,
517 )
518-from lp.app.errors import NotFoundError
519 from lp.buildmaster.interfaces.builder import (
520 IBuilder,
521 IBuilderSet,
522 )
523 from lp.services.propertycache import cachedproperty
524-from lp.soyuz.browser.build import BuildRecordsView
525-from lp.soyuz.interfaces.binarypackagebuild import IBinaryPackageBuildSet
526-
527-
528-class BuilderSetNavigation(GetitemNavigation):
529+from lp.soyuz.browser.build import (
530+ BuildNavigationMixin,
531+ BuildRecordsView,
532+ )
533+
534+
535+class BuilderSetNavigation(GetitemNavigation, BuildNavigationMixin):
536 """Navigation methods for IBuilderSet."""
537 usedfor = IBuilderSet
538
539- @stepthrough('+build')
540- def traverse_build(self, name):
541- try:
542- build_id = int(name)
543- except ValueError:
544- return None
545- try:
546- build = getUtility(IBinaryPackageBuildSet).getByBuildID(build_id)
547- except NotFoundError:
548+ @stepthrough('+buildjob')
549+ def traverse_buildjob(self, name):
550+ build = super(BuilderSetNavigation, self).traverse_buildjob(name)
551+ if build is None:
552 return None
553 else:
554 return self.redirectSubTree(canonical_url(build))
555
556=== modified file 'lib/lp/soyuz/browser/distributionsourcepackagerelease.py'
557--- lib/lp/soyuz/browser/distributionsourcepackagerelease.py 2010-08-31 11:31:04 +0000
558+++ lib/lp/soyuz/browser/distributionsourcepackagerelease.py 2011-01-14 10:09:39 +0000
559@@ -12,21 +12,17 @@
560
561 import operator
562
563-from zope.component import getUtility
564-
565 from canonical.launchpad.browser.librarian import ProxiedLibraryFileAlias
566 from canonical.launchpad.webapp import (
567 LaunchpadView,
568 Navigation,
569- stepthrough,
570 )
571 from canonical.launchpad.webapp.breadcrumb import Breadcrumb
572 from canonical.lazr.utils import smartquote
573-from lp.app.errors import NotFoundError
574 from lp.archivepublisher.debversion import Version
575 from lp.services.propertycache import cachedproperty
576+from lp.soyuz.browser.build import BuildNavigationMixin
577 from lp.soyuz.enums import PackagePublishingStatus
578-from lp.soyuz.interfaces.binarypackagebuild import IBinaryPackageBuildSet
579 from lp.soyuz.interfaces.distributionsourcepackagerelease import (
580 IDistributionSourcePackageRelease,
581 )
582@@ -40,20 +36,10 @@
583 return self.context.version
584
585
586-class DistributionSourcePackageReleaseNavigation(Navigation):
587+class DistributionSourcePackageReleaseNavigation(Navigation,
588+ BuildNavigationMixin):
589 usedfor = IDistributionSourcePackageRelease
590
591- @stepthrough('+build')
592- def traverse_build(self, name):
593- try:
594- build_id = int(name)
595- except ValueError:
596- return None
597- try:
598- return getUtility(IBinaryPackageBuildSet).getByBuildID(build_id)
599- except NotFoundError:
600- return None
601-
602
603 class DistributionSourcePackageReleaseView(LaunchpadView):
604 """View logic for `DistributionSourcePackageRelease` objects. """
605
606=== modified file 'lib/lp/soyuz/browser/tests/build-views.txt'
607--- lib/lp/soyuz/browser/tests/build-views.txt 2010-10-18 22:24:59 +0000
608+++ lib/lp/soyuz/browser/tests/build-views.txt 2011-01-14 10:09:39 +0000
609@@ -300,7 +300,7 @@
610 >>> view.request.response.getStatus()
611 302
612 >>> print view.request.response.getHeader('Location')
613- http://launchpad.dev/~cprov/+archive/ppa/+build/26
614+ http://launchpad.dev/~cprov/+archive/ppa/+buildjob/26
615
616 Canceled 'Rescore' form redirects users back to the Build page.
617
618@@ -312,7 +312,7 @@
619 ... pending_build, name="+rescore")
620
621 >>> print view.cancel_url
622- http://launchpad.dev/ubuntu/+source/alsa-utils/1.0.9a-4ubuntu1/+build/11
623+ http://launchpad.dev/ubuntu/+source/alsa-utils/1.0.9a-4ubuntu1/+buildjob/11
624
625 The 'priority' field only accepts long integer values.
626
627@@ -351,7 +351,7 @@
628 >>> view.request.response.getStatus()
629 302
630 >>> print view.request.response.getHeader('Location')
631- http://launchpad.dev/ubuntu/+source/alsa-utils/1.0.9a-4ubuntu1/+build/11
632+ http://launchpad.dev/ubuntu/+source/alsa-utils/1.0.9a-4ubuntu1/+buildjob/11
633
634 >>> for notification in view.request.response.notifications:
635 ... print notification.message
636
637=== added file 'lib/lp/soyuz/browser/tests/test_builder.py'
638--- lib/lp/soyuz/browser/tests/test_builder.py 1970-01-01 00:00:00 +0000
639+++ lib/lp/soyuz/browser/tests/test_builder.py 2011-01-14 10:09:39 +0000
640@@ -0,0 +1,38 @@
641+# Copyright 2010 Canonical Ltd. This software is licensed under the
642+# GNU Affero General Public License version 3 (see the file LICENSE).
643+
644+"""Tests for the lp.soyuz.browser.builder module."""
645+
646+__metaclass__ = type
647+
648+from canonical.launchpad.webapp import canonical_url
649+from canonical.testing.layers import DatabaseFunctionalLayer
650+from lp.testing import TestCaseWithFactory
651+from lp.testing.publication import test_traverse
652+
653+
654+class TestBuildersNavigation(TestCaseWithFactory):
655+
656+ layer = DatabaseFunctionalLayer
657+
658+ def test_buildjob_redirects_for_recipe_build(self):
659+ # /builders/+buildjob/<job id> redirects to the build page.
660+ build = self.factory.makeSourcePackageRecipeBuild()
661+ url = 'http://launchpad.dev/builders/+buildjob/%s' % build.url_id
662+ context, view, request = test_traverse(url)
663+ view()
664+ self.assertEqual(301, request.response.getStatus())
665+ self.assertEqual(
666+ canonical_url(build),
667+ request.response.getHeader('location'))
668+
669+ def test_buildjob_redirects_for_binary_build(self):
670+ # /builders/+buildjob/<job id> redirects to the build page.
671+ build = self.factory.makeBinaryPackageBuild()
672+ url = 'http://launchpad.dev/builders/+buildjob/%s' % build.url_id
673+ context, view, request = test_traverse(url)
674+ view()
675+ self.assertEqual(301, request.response.getStatus())
676+ self.assertEqual(
677+ canonical_url(build),
678+ request.response.getHeader('location'))
679
680=== modified file 'lib/lp/soyuz/doc/binarypackagebuild.txt'
681--- lib/lp/soyuz/doc/binarypackagebuild.txt 2010-10-18 22:24:59 +0000
682+++ lib/lp/soyuz/doc/binarypackagebuild.txt 2011-01-14 10:09:39 +0000
683@@ -85,13 +85,13 @@
684 buildlog_ubuntutest-breezy-autotest-i386.mozilla-firefox_0.9_FULLYBUILT.txt.gz
685
686 >>> print firefox_build.log_url
687- http://launchpad.dev/ubuntutest/+source/mozilla-firefox/0.9/+build/.../+files/buildlog_ubuntutest-breezy-autotest-i386.mozilla-firefox_0.9_FULLYBUILT.txt.gz
688+ http://launchpad.dev/ubuntutest/+source/mozilla-firefox/0.9/+buildjob/.../+files/buildlog_ubuntutest-breezy-autotest-i386.mozilla-firefox_0.9_FULLYBUILT.txt.gz
689
690 >>> print firefox_build.upload_changesfile.filename
691 firefox_0.9_i386.changes
692
693 >>> print firefox_build.changesfile_url
694- http://launchpad.dev/ubuntutest/+source/mozilla-firefox/0.9/+build/.../+files/firefox_0.9_i386.changes
695+ http://launchpad.dev/ubuntutest/+source/mozilla-firefox/0.9/+buildjob/.../+files/firefox_0.9_i386.changes
696
697 The 'firefox_build' is already finished and requesting the estimated build
698 start time makes no sense. Hence an exception is raised.
699@@ -202,7 +202,7 @@
700 upload_9_log.txt
701
702 >>> print active_build.upload_log_url
703- http://launchpad.dev/ubuntu/+source/pmount/0.1-1/+build/9/+files/upload_9_log.txt
704+ http://launchpad.dev/ubuntu/+source/pmount/0.1-1/+buildjob/9/+files/upload_9_log.txt
705
706 Once the transaction is committed, the file is available in the
707 librarian, and we can retrieve its contents.
708
709=== modified file 'lib/lp/soyuz/doc/build-failedtoupload-workflow.txt'
710--- lib/lp/soyuz/doc/build-failedtoupload-workflow.txt 2010-12-22 01:08:48 +0000
711+++ lib/lp/soyuz/doc/build-failedtoupload-workflow.txt 2011-01-14 10:09:39 +0000
712@@ -88,8 +88,8 @@
713 * Component: main
714 * State: Failed to upload
715 * Duration: a minute
716- * Build Log: http://launchpad.dev/ubuntu/+source/cdrkit/1.0/+build/22/+fil=
717- es/netapplet-1.0.0.tar.gz
718+ * Build Log: http://launchpad.dev/ubuntu/+source/cdrkit/1.0/+buildjob/22/+=
719+ files/netapplet-1.0.0.tar.gz
720 * Builder: http://launchpad.dev/builders/bob
721 * Source: http://launchpad.dev/ubuntu/+source/cdrkit/1.0
722 <BLANKLINE>
723@@ -101,7 +101,7 @@
724 <BLANKLINE>
725 --
726 i386 build of cdrkit 1.0 in ubuntu breezy-autotest RELEASE
727- http://launchpad.dev/ubuntu/+source/cdrkit/1.0/+build/22
728+ http://launchpad.dev/ubuntu/+source/cdrkit/1.0/+buildjob/22
729 <BLANKLINE>
730
731
732
733=== modified file 'lib/lp/soyuz/doc/build-notification.txt'
734--- lib/lp/soyuz/doc/build-notification.txt 2010-10-03 15:30:06 +0000
735+++ lib/lp/soyuz/doc/build-notification.txt 2011-01-14 10:09:39 +0000
736@@ -114,7 +114,7 @@
737 * Component: main
738 * State: Failed to build
739 * Duration: three minutes
740- * Build Log: http://launchpad.dev/ubuntu/+source/pmount/0.1-1/+build/9/+files/netapplet-1.0.0.tar.gz
741+ * Build Log: http://launchpad.dev/ubuntu/+source/pmount/0.1-1/+buildjob/9/+files/netapplet-1.0.0.tar.gz
742 * Builder: http://launchpad.dev/builders/bob
743 * Source: http://launchpad.dev/ubuntu/+source/pmount/0.1-1
744 <BLANKLINE>
745@@ -125,7 +125,7 @@
746 <BLANKLINE>
747 --
748 i386 build of pmount 0.1-1 in ubuntu warty RELEASE
749- http://launchpad.dev/ubuntu/+source/pmount/0.1-1/+build/9
750+ http://launchpad.dev/ubuntu/+source/pmount/0.1-1/+buildjob/9
751 <BLANKLINE>
752
753 Notification for a pending (NEEDSBUILD) build record:
754@@ -193,7 +193,7 @@
755 <BLANKLINE>
756 --
757 i386 build of alsa-utils 1.0.9a-4ubuntu1 in ubuntu hoary RELEASE
758- http://launchpad.dev/ubuntu/+source/alsa-utils/1.0.9a-4ubuntu1/+build/11
759+ http://launchpad.dev/ubuntu/+source/alsa-utils/1.0.9a-4ubuntu1/+buildjob/11
760 <BLANKLINE>
761
762 Notification for a BUILDING build record:
763@@ -261,7 +261,7 @@
764 <BLANKLINE>
765 --
766 i386 build of mozilla-firefox 0.9 in ubuntu hoary RELEASE
767- http://launchpad.dev/ubuntu/+source/mozilla-firefox/0.9/+build/8
768+ http://launchpad.dev/ubuntu/+source/mozilla-firefox/0.9/+buildjob/8
769 <BLANKLINE>
770
771 Notification for a SUPERSEDED build record:
772@@ -329,7 +329,7 @@
773 <BLANKLINE>
774 --
775 i386 build of at 0.00 in ubuntu warty RELEASE
776- http://launchpad.dev/ubuntu/+source/at/0.00/+build/15
777+ http://launchpad.dev/ubuntu/+source/at/0.00/+buildjob/15
778 <BLANKLINE>
779
780 Check if the 'build_notification' configuration option really suppress
781@@ -451,7 +451,7 @@
782 * Component: main
783 * State: Failed to build
784 * Duration: a minute
785- * Build Log: http://launchpad.dev/~cprov/+archive/ppa/+build/26/+files/netapplet-1.0.0.tar.gz
786+ * Build Log: http://launchpad.dev/~cprov/+archive/ppa/+buildjob/26/+files/netapplet-1.0.0.tar.gz
787 * Builder: http://launchpad.dev/builders/bob
788 * Source: not available
789 ...
790@@ -614,7 +614,7 @@
791 * Component: main
792 * State: Failed to build
793 * Duration: a minute
794- * Build Log: http://launchpad.dev/~cprov/+archive/testing/+build/26/+files/netapplet-1.0.0.tar.gz
795+ * Build Log: http://launchpad.dev/~cprov/+archive/testing/+buildjob/26/+files/netapplet-1.0.0.tar.gz
796 * Builder: http://launchpad.dev/builders/bob
797 * Source: not available
798 <BLANKLINE>
799@@ -625,5 +625,5 @@
800 <BLANKLINE>
801 --
802 i386 build of cdrkit 1.0 in ubuntu breezy-autotest RELEASE
803- http://launchpad.dev/~cprov/+archive/testing/+build/26
804+ http://launchpad.dev/~cprov/+archive/testing/+buildjob/26
805 <BLANKLINE>
806
807=== modified file 'lib/lp/soyuz/stories/ppa/xx-ppa-files.txt'
808--- lib/lp/soyuz/stories/ppa/xx-ppa-files.txt 2010-12-10 00:08:39 +0000
809+++ lib/lp/soyuz/stories/ppa/xx-ppa-files.txt 2011-01-14 10:09:39 +0000
810@@ -181,7 +181,7 @@
811 >>> no_priv_browser.getControl("Filter").click()
812
813 >>> check_urls(no_priv_browser, builds_links,
814- ... 'http://launchpad.dev/~no-priv/+archive/p3a/+build/31')
815+ ... 'http://launchpad.dev/~no-priv/+archive/p3a/+buildjob/31')
816 buildlog_ubuntu-breezy-autotest-i386.test-pkg_1.0_FULLYBUILT.txt.gz: OK
817
818 >>> no_priv_browser.open(
819@@ -208,7 +208,7 @@
820 i386 build of test-pkg 1.0 : PPA named p3a for No Privileges Person : No Privileges Person
821
822 >>> check_urls(no_priv_browser, build_links,
823- ... 'http://launchpad.dev/~no-priv/+archive/p3a/+build/31')
824+ ... 'http://launchpad.dev/~no-priv/+archive/p3a/+buildjob/31')
825 test-bin_1.0_i386.changes: OK
826 buildlog_...txt.gz: OK
827 upload_..._log.txt: OK
828@@ -276,7 +276,7 @@
829 >>> buildlog_content = buildlog.read()
830 >>> buildlog_size = str(buildlog.content.filesize)
831 >>> buildlog_lp_url = str(
832- ... 'http://launchpad.dev/~no-priv/+archive/p3a/+build/%d/+files/%s' %
833+ ... 'http://launchpad.dev/~no-priv/+archive/p3a/+buildjob/%d/+files/%s' %
834 ... (build.id, buildlog.filename))
835
836 >>> diff_content = package_diff.diff_content.read()
837@@ -380,12 +380,12 @@
838 Location: http://localhost/~no-priv/+archive/ppa/+files/test-pkg_1.0.dsc
839 ...
840
841-The same redirection happens for +archive/+build/blah urls:
842+The same redirection happens for +archive/+buildjob/blah urls:
843
844 >>> buildlog_lp_url_without_ppa_name = buildlog_lp_url.replace(
845 ... '/p3a', '')
846 >>> print buildlog_lp_url_without_ppa_name
847- http://.../~no-priv/+archive/+build/31/+files/...
848+ http://.../~no-priv/+archive/+buildjob/31/+files/...
849
850 >>> print http(r"""
851 ... GET %s HTTP/1.1
852@@ -393,7 +393,7 @@
853 ... 'http://launchpad.dev', ''))
854 HTTP/1.1 301 Moved Permanently
855 ...
856- Location: http://.../~no-priv/+archive/ppa/+build/31/+files/...
857+ Location: http://.../~no-priv/+archive/ppa/+buildjob/31/+files/...
858 ...
859
860
861
862=== modified file 'lib/lp/soyuz/stories/soyuz/xx-binarypackagerelease-index.txt'
863--- lib/lp/soyuz/stories/soyuz/xx-binarypackagerelease-index.txt 2010-05-17 15:03:59 +0000
864+++ lib/lp/soyuz/stories/soyuz/xx-binarypackagerelease-index.txt 2011-01-14 10:09:39 +0000
865@@ -14,7 +14,7 @@
866 ... 'i386 build of mozilla-firefox 0.9 in ubuntu '
867 ... 'warty RELEASE')
868 >>> build_link.url
869- 'http://launchpad.dev/ubuntu/+source/mozilla-firefox/0.9/+build/2'
870+ 'http://launchpad.dev/ubuntu/+source/mozilla-firefox/0.9/+buildjob/2'
871
872 Next, we'll manually create a suitable package upload record for our
873 build:
874@@ -40,7 +40,7 @@
875
876 >>> build_link.click()
877 >>> browser.url
878- 'http://launchpad.dev/ubuntu/+source/mozilla-firefox/0.9/+build/2'
879+ 'http://launchpad.dev/ubuntu/+source/mozilla-firefox/0.9/+buildjob/2'
880
881 This build produced one BinaryPackage, called 'mozilla-firefox 0.9',
882 which is presented in the right portlet, called 'Resulting Binaries'.
883
884=== modified file 'lib/lp/soyuz/stories/soyuz/xx-build-record.txt'
885--- lib/lp/soyuz/stories/soyuz/xx-build-record.txt 2010-12-16 12:48:14 +0000
886+++ lib/lp/soyuz/stories/soyuz/xx-build-record.txt 2011-01-14 10:09:39 +0000
887@@ -39,7 +39,7 @@
888 individual `Build`, and they can be accessed via the build-farm URL
889 shortcut.
890
891- >>> build_url = "http://launchpad.dev/builders/+build/%d" % build_id
892+ >>> build_url = "http://launchpad.dev/builders/+buildjob/%d" % build_id
893
894 Using the short-cut URL any user can promptly access the build
895 page. It's title briefly describes the build.
896@@ -226,10 +226,10 @@
897 http://launchpad.dev/builders/bob
898
899 >>> print anon_browser.getLink('buildlog').url
900- http://.../+build/31/+files/fake-buildlog
901+ http://.../+buildjob/31/+files/fake-buildlog
902
903 >>> print anon_browser.getLink('uploadlog').url
904- http://.../+build/31/+files/fake-uploadlog
905+ http://.../+buildjob/31/+files/fake-uploadlog
906
907 Note that the links to the logs points to their `ProxiedLibrarianFile`
908 entry points, so users with permission can reach the files even if
909@@ -249,7 +249,7 @@
910 uploadlog (7 bytes)
911
912 >>> print admin_browser.getLink('Retry this build').url
913- http://launchpad.dev/ubuntutest/+source/testing/1.0/+build/31/+retry
914+ http://launchpad.dev/ubuntutest/+source/testing/1.0/+buildjob/31/+retry
915
916 By clicking on the 'Retry this build' link, administrators are informed of
917 the consequences of this action.
918@@ -337,7 +337,7 @@
919 testing_1.0_all.changes (15 bytes)
920
921 >>> print anon_browser.getLink('testing_1.0_all.changes').url
922- http://.../+build/31/+files/testing_1.0_all.changes
923+ http://.../+buildjob/31/+files/testing_1.0_all.changes
924
925 >>> print extract_text(
926 ... find_tag_by_id(anon_browser.contents, 'binaries'))
927@@ -364,7 +364,7 @@
928 already have access to them.
929
930 >>> print anon_browser.getLink('testing-bin_1.0_all.deb').url
931- http://.../+build/31/+files/testing-bin_1.0_all.deb
932+ http://.../+buildjob/31/+files/testing-bin_1.0_all.deb
933
934 Again, note that the files are `ProxiedLibrarianFile` objects as well.
935
936@@ -389,7 +389,7 @@
937 LinkNotFoundError
938
939 >>> print anon_browser.getLink('testing-bin_1.0_all.deb').url
940- http://.../+build/31/+files/testing-bin_1.0_all.deb
941+ http://.../+buildjob/31/+files/testing-bin_1.0_all.deb
942
943 When new binaries are accepted by an archive administrator (See
944 xx-queue-pages.txt) this condition is presented in the build page.
945@@ -413,7 +413,7 @@
946 LinkNotFoundError
947
948 >>> print anon_browser.getLink('testing-bin_1.0_all.deb').url
949- http://.../+build/31/+files/testing-bin_1.0_all.deb
950+ http://.../+buildjob/31/+files/testing-bin_1.0_all.deb
951
952 Once the accepted binary upload is processed by the backend, the
953 binary reference finally becomes a link to its corresponding page.
954@@ -455,7 +455,7 @@
955 >>> [ppa_build] = ppa_source.getBuilds()
956 >>> ppa_build.builder = bob_builder
957 >>> ppa_build_url = (
958- ... "http://launchpad.dev/builders/+build/%d" % ppa_build.id)
959+ ... "http://launchpad.dev/builders/+buildjob/%d" % ppa_build.id)
960 >>> logout()
961
962 >>> anon_browser.open(ppa_build_url)
963@@ -478,10 +478,10 @@
964 http://launchpad.dev/builders/bob
965
966 >>> print anon_browser.getLink('buildlog').url
967- http://launchpad.dev/~cprov/+archive/ppa/+build/.../+files/buildlog_...
968+ http://launchpad.dev/~cprov/+archive/ppa/+buildjob/.../+files/buildlog_...
969
970 >>> print anon_browser.getLink('ppa-test-bin_1.0_i386.changes').url
971- http://.../+build/.../+files/ppa-test-bin_1.0_i386.changes
972+ http://.../+buildjob/.../+files/ppa-test-bin_1.0_i386.changes
973
974 'Build details', as mentioned above, doesn't link to the PPA source
975 packages, since they do not exist.
976@@ -543,7 +543,7 @@
977 ...
978
979 >>> print anon_browser.getLink('~cprov/product/mybranch recipe build').url
980- http://code.launchpad.dev/~cprov/+recipe/myrecipe/+build/1
981+ http://launchpad.dev/~cprov/+archive/ppa/+buildjob/...
982
983 Finally, the 'Build files' section is identical for PPA builds.
984
985@@ -554,7 +554,7 @@
986 ppa-test-bin_1.0_all.deb (18 bytes)
987
988 >>> print anon_browser.getLink('ppa-test-bin_1.0_all.deb').url
989- http://.../+build/.../+files/ppa-test-bin_1.0_all.deb
990+ http://.../+buildjob/.../+files/ppa-test-bin_1.0_all.deb
991
992
993 Imported binaries builds
994@@ -574,7 +574,7 @@
995 None
996
997 >>> imported_build_url = (
998- ... "http://launchpad.dev/builders/+build/%d" % imported_build.id)
999+ ... "http://launchpad.dev/builders/+buildjob/%d" % imported_build.url_id)
1000
1001 >>> logout()
1002
1003
1004=== modified file 'lib/lp/soyuz/stories/soyuz/xx-build-redirect.txt'
1005--- lib/lp/soyuz/stories/soyuz/xx-build-redirect.txt 2007-06-12 12:23:15 +0000
1006+++ lib/lp/soyuz/stories/soyuz/xx-build-redirect.txt 2011-01-14 10:09:39 +0000
1007@@ -5,6 +5,4 @@
1008
1009 >>> anon_browser.open("http://launchpad.dev/+builds/+build/18")
1010 >>> anon_browser.url
1011- 'http://launchpad.dev/ubuntu/+source/mozilla-firefox/0.9/+build/18'
1012-
1013-
1014+ 'http://launchpad.dev/ubuntu/+source/mozilla-firefox/0.9/+buildjob/18'
1015
1016=== modified file 'lib/lp/soyuz/stories/soyuz/xx-buildfarm-index.txt'
1017--- lib/lp/soyuz/stories/soyuz/xx-buildfarm-index.txt 2010-09-13 09:45:58 +0000
1018+++ lib/lp/soyuz/stories/soyuz/xx-buildfarm-index.txt 2011-01-14 10:09:39 +0000
1019@@ -32,7 +32,7 @@
1020
1021 >>> print anon_browser.getLink(
1022 ... 'i386 build of mozilla-firefox 0.9').url
1023- http://launchpad.dev/ubuntu/+source/mozilla-firefox/0.9/+build/8
1024+ http://launchpad.dev/ubuntu/+source/mozilla-firefox/0.9/+buildjob/8
1025
1026 The build status portlets contain the number of builds waiting
1027 in queue and the sum of their 'estimated_duration' for each
1028
1029=== modified file 'lib/lp/soyuz/stories/soyuz/xx-distributionsourcepackagerelease-pages.txt'
1030--- lib/lp/soyuz/stories/soyuz/xx-distributionsourcepackagerelease-pages.txt 2010-12-20 06:46:09 +0000
1031+++ lib/lp/soyuz/stories/soyuz/xx-distributionsourcepackagerelease-pages.txt 2011-01-14 10:09:39 +0000
1032@@ -188,7 +188,7 @@
1033 Breezy Badger Autotest: i386
1034
1035 >>> print anon_browser.getLink('i386').url
1036- http://launchpad.dev/ubuntutest/+source/testing-dspr/1.0/+build/...
1037+ http://launchpad.dev/ubuntutest/+source/testing-dspr/1.0/+buildjob/...
1038
1039 The 'Downloads' section lists and links to the files for this
1040 source. Each file links to its normalized download path based on the
1041
1042=== modified file 'lib/lp/soyuz/stories/soyuz/xx-private-builds.txt'
1043--- lib/lp/soyuz/stories/soyuz/xx-private-builds.txt 2010-10-18 22:24:59 +0000
1044+++ lib/lp/soyuz/stories/soyuz/xx-private-builds.txt 2011-01-14 10:09:39 +0000
1045@@ -109,7 +109,7 @@
1046 users:
1047
1048 >>> anon_browser.open(
1049- ... "http://launchpad.dev/~cprov/+archive/p3a/+build/%s" %
1050+ ... "http://launchpad.dev/~cprov/+archive/p3a/+buildjob/%s" %
1051 ... private_build_id)
1052 Traceback (most recent call last):
1053 ...
1054@@ -118,10 +118,10 @@
1055 But it is fine for authorised users:
1056
1057 >>> cprov_browser.open(
1058- ... "http://launchpad.dev/~cprov/+archive/p3a/+build/%s" %
1059+ ... "http://launchpad.dev/~cprov/+archive/p3a/+buildjob/%s" %
1060 ... private_build_id)
1061 >>> print cprov_browser.url
1062- http://launchpad.dev/~cprov/+archive/p3a/+build/...
1063+ http://launchpad.dev/~cprov/+archive/p3a/+buildjob/...
1064
1065
1066 == Builder history page ==
1067@@ -253,7 +253,7 @@
1068 >>> from zope.security.interfaces import Unauthorized
1069 >>> try:
1070 ... anon_browser.open(
1071- ... "http://launchpad.dev/~cprov/+archive/p3a/+build/%s" %
1072+ ... "http://launchpad.dev/~cprov/+archive/p3a/+buildjob/%s" %
1073 ... private_build_id)
1074 ... except Unauthorized:
1075 ... print "Got expected exception"
1076@@ -264,7 +264,7 @@
1077 >>> browser = setupBrowser(auth="Basic no-priv@canonical.com:test")
1078 >>> try:
1079 ... browser.open(
1080- ... "http://launchpad.dev/~cprov/+archive/p3a/+build/%s" %
1081+ ... "http://launchpad.dev/~cprov/+archive/p3a/+buildjob/%s" %
1082 ... private_build_id)
1083 ... except Unauthorized:
1084 ... print "Got expected exception"
1085@@ -319,13 +319,13 @@
1086 Accessing the build page will now also work:
1087
1088 >>> anon_browser.open(
1089- ... "http://launchpad.dev/~cprov/+archive/p3a/+build/%s" %
1090+ ... "http://launchpad.dev/~cprov/+archive/p3a/+buildjob/%s" %
1091 ... private_build_id)
1092 >>> print anon_browser.title
1093 i386 build of privacy-test 666 : PPA named p3a for Celso Providelo : Celso Providelo
1094
1095 >>> browser.open(
1096- ... "http://launchpad.dev/~cprov/+archive/p3a/+build/%s" %
1097+ ... "http://launchpad.dev/~cprov/+archive/p3a/+buildjob/%s" %
1098 ... private_build_id)
1099 >>> print browser.title
1100 i386 build of privacy-test 666 : PPA named p3a for Celso Providelo : Celso Providelo
1101@@ -342,7 +342,7 @@
1102 breezy-autotest i386 Successfully built
1103
1104 >>> print browser.getLink('i386').url
1105- http://launchpad.dev/~cprov/+archive/p3a/+build/...
1106+ http://launchpad.dev/~cprov/+archive/p3a/+buildjob/...
1107
1108 Similarly, when accessing the distribution source package release page,
1109 the main content will display a link to the newly unembargoed build:
1110@@ -355,4 +355,4 @@
1111 Breezy Badger Autotest: i386
1112
1113 >>> print browser.getLink('i386').url
1114- http://launchpad.dev/~cprov/+archive/p3a/+build/...
1115+ http://launchpad.dev/~cprov/+archive/p3a/+buildjob/...
1116
1117=== modified file 'lib/lp/soyuz/stories/webservice/xx-builds.txt'
1118--- lib/lp/soyuz/stories/webservice/xx-builds.txt 2010-10-18 22:24:59 +0000
1119+++ lib/lp/soyuz/stories/webservice/xx-builds.txt 2011-01-14 10:09:39 +0000
1120@@ -51,10 +51,10 @@
1121 date_first_dispatched: None
1122 dependencies: None
1123 distribution_link: u'http://.../beta/ubuntu'
1124- log_url: u'http://.../~cprov/+archive/ppa/+build/26/+files/netapplet-1.0.0.tar.gz'
1125+ log_url: u'http://.../~cprov/+archive/ppa/+buildjob/26/+files/netapplet-1.0.0.tar.gz'
1126 pocket: u'Release'
1127 resource_type_link: u'http://api.launchpad.dev/beta/#build'
1128- self_link: u'http://api.launchpad.dev/beta/~cprov/+archive/ppa/+build/26'
1129+ self_link: u'http://api.launchpad.dev/beta/~cprov/+archive/ppa/+buildjob/26'
1130 status: u'Failed to build'
1131 title: u'i386 build of cdrkit 1.0 in ubuntu breezy-autotest RELEASE'
1132 upload_log_url: None
1133@@ -67,7 +67,7 @@
1134 >>> pprint_entry(builds_1_0['entries'][0])
1135 arch_tag: u'i386'
1136 archive_link: u'http://.../~cprov/+archive/ppa'
1137- build_log_url: u'http://.../~cprov/+archive/ppa/+build/26/+files/netapplet-1.0.0.tar.gz'
1138+ build_log_url: u'http://.../~cprov/+archive/ppa/+buildjob/26/+files/netapplet-1.0.0.tar.gz'
1139 buildstate: u'Failed to build'
1140 can_be_rescored: False
1141 can_be_retried: True
1142@@ -80,7 +80,7 @@
1143 distribution_link: u'http://.../ubuntu'
1144 pocket: u'Release'
1145 resource_type_link: u'http://.../#build'
1146- self_link: u'http://.../~cprov/+archive/ppa/+build/26'
1147+ self_link: u'http://.../~cprov/+archive/ppa/+buildjob/26'
1148 title: u'i386 build of cdrkit 1.0 in ubuntu breezy-autotest RELEASE'
1149 upload_log_url: None
1150
1151@@ -108,10 +108,10 @@
1152 ... source_pub['self_link'], 'getBuilds').jsonBody()
1153
1154 >>> print builds['entries'][0]['log_url']
1155- http://launchpad.dev/~cprov/+archive/ppa/+build/26/+files/...
1156+ http://launchpad.dev/~cprov/+archive/ppa/+buildjob/26/+files/...
1157
1158 >>> print builds['entries'][0]['upload_log_url']
1159- http://launchpad.dev/~cprov/+archive/ppa/+build/26/+files/...
1160+ http://launchpad.dev/~cprov/+archive/ppa/+buildjob/26/+files/...
1161
1162
1163 Re-trying builds
1164
1165=== modified file 'lib/lp/soyuz/tests/test_binarypackagebuild.py'
1166--- lib/lp/soyuz/tests/test_binarypackagebuild.py 2011-01-13 11:42:44 +0000
1167+++ lib/lp/soyuz/tests/test_binarypackagebuild.py 2011-01-14 10:09:39 +0000
1168@@ -102,7 +102,7 @@
1169 self.addFakeBuildLog()
1170 self.failUnlessEqual(
1171 'http://launchpad.dev/ubuntutest/+source/'
1172- 'gedit/666/+build/%d/+files/mybuildlog.txt' % (
1173+ 'gedit/666/+buildjob/%d/+files/mybuildlog.txt' % (
1174 self.build.package_build.build_farm_job.id),
1175 self.build.log_url)
1176
1177@@ -115,7 +115,7 @@
1178 owner=ppa_owner, name="myppa")
1179 self.failUnlessEqual(
1180 'http://launchpad.dev/~joe/'
1181- '+archive/myppa/+build/%d/+files/mybuildlog.txt' % (
1182+ '+archive/myppa/+buildjob/%d/+files/mybuildlog.txt' % (
1183 self.build.build_farm_job.id),
1184 self.build.log_url)
1185
1186
1187=== modified file 'lib/lp/testing/factory.py'
1188--- lib/lp/testing/factory.py 2011-01-06 16:42:50 +0000
1189+++ lib/lp/testing/factory.py 2011-01-14 10:09:39 +0000
1190@@ -2312,6 +2312,7 @@
1191 if naked_sprb.date_started is None:
1192 naked_sprb.date_started = spr_build.date_created
1193 naked_sprb.date_finished = naked_sprb.date_started + duration
1194+ IStore(spr_build).flush()
1195 return spr_build
1196
1197 def makeSourcePackageRecipeBuildJob(
1198@@ -3101,6 +3102,7 @@
1199 date_created=date_created)
1200 naked_build = removeSecurityProxy(binary_package_build)
1201 naked_build.builder = builder
1202+ IStore(binary_package_build).flush()
1203 return binary_package_build
1204
1205 def makeSourcePackagePublishingHistory(self, sourcepackagename=None,