Merge lp:~thumper/launchpad/recipe-binary-builds into lp:launchpad

Proposed by Tim Penhey
Status: Merged
Approved by: Aaron Bentley
Approved revision: no longer in the source branch.
Merged at revision: 12000
Proposed branch: lp:~thumper/launchpad/recipe-binary-builds
Merge into: lp:launchpad
Diff against target: 435 lines (+189/-17)
8 files modified
lib/canonical/launchpad/doc/hierarchical-menu.txt (+6/-0)
lib/lp/code/browser/sourcepackagerecipebuild.py (+4/-3)
lib/lp/code/browser/tests/test_sourcepackagerecipe.py (+84/-5)
lib/lp/code/templates/sourcepackagerecipe-index.pt (+49/-4)
lib/lp/soyuz/browser/build.py (+33/-0)
lib/lp/soyuz/model/processor.py (+6/-0)
lib/lp/soyuz/templates/build-index.pt (+1/-2)
lib/lp/testing/factory.py (+6/-3)
To merge this branch: bzr merge lp:~thumper/launchpad/recipe-binary-builds
Reviewer Review Type Date Requested Status
Aaron Bentley (community) Approve
Paul Hummer (community) ui Approve
Review via email: mp+40686@code.launchpad.net

Commit message

[r=abentley][ui=rockstar][bug=602508] Show related binary builds on the recipe index page.

Description of the change

Adds binary build information to the latest builds section on the recipe index page.

http://people.canonical.com/~tim/recipe-latest-builds.png shows an example of how it looks.

I made some of the properties of the view that were accessed multiple times
cached properties. This required a few tweaks in the tests too.

The binary builds for the successful recipe builds are indented slightly and
show underneath the recipe build that they relate to.

During interactive hacking, I found that I wanted some nicer repr methods
for the processors.

A drive-by fix on the soyuz build-index.pt to just specify the content as
buildlog instead of using tal:content="string: buildlog"

To post a comment you must log in.
Revision history for this message
Paul Hummer (rockstar) wrote :

This looks really excellent!

review: Approve (ui)
Revision history for this message
Aaron Bentley (abentley) wrote :

You are showing the start time for binary builds, while the source package recipe builds show the end time. The time values in this column should have a consistent meaning.

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

Aaron, I've gone with the expected completed time, and added the same properties to the BuildView. I feel that we should use a common mixin, but I can't think where to actually put the code.

My first thought was actually something like lp.shared.browser or lp.app.browser.shared...

Not sure.

Revision history for this message
Aaron Bentley (abentley) wrote :

Looks good. At some point, we might want to collapse eta and date into a single method call that returns a tuple.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/canonical/launchpad/doc/hierarchical-menu.txt'
--- lib/canonical/launchpad/doc/hierarchical-menu.txt 2010-10-18 22:24:59 +0000
+++ lib/canonical/launchpad/doc/hierarchical-menu.txt 2010-11-30 01:38:20 +0000
@@ -90,6 +90,7 @@
90 # have to create fake views and other stuff to test breadcrumbs here. The90 # have to create fake views and other stuff to test breadcrumbs here. The
91 # functionality provided by that method is tested in91 # functionality provided by that method is tested in
92 # webapp/tests/test_breadcrumbs.py.92 # webapp/tests/test_breadcrumbs.py.
93 >>> make_breadcrumb_func = Hierarchy.makeBreadcrumbForRequestedPage
93 >>> Hierarchy.makeBreadcrumbForRequestedPage = lambda self: None94 >>> Hierarchy.makeBreadcrumbForRequestedPage = lambda self: None
9495
95 # Note that the Hierarchy assigns the breadcrumb's URL, but we need to96 # Note that the Hierarchy assigns the breadcrumb's URL, but we need to
@@ -269,3 +270,8 @@
269270
270 >>> homepage_hierarchy.render().strip()271 >>> homepage_hierarchy.render().strip()
271 u''272 u''
273
274
275Put the monkey patched method back.
276
277 >>> Hierarchy.makeBreadcrumbForRequestedPage = make_breadcrumb_func
272278
=== modified file 'lib/lp/code/browser/sourcepackagerecipebuild.py'
--- lib/lp/code/browser/sourcepackagerecipebuild.py 2010-11-23 23:22:27 +0000
+++ lib/lp/code/browser/sourcepackagerecipebuild.py 2010-11-30 01:38:20 +0000
@@ -34,6 +34,7 @@
34 ISourcePackageRecipeBuild,34 ISourcePackageRecipeBuild,
35 )35 )
36from lp.services.job.interfaces.job import JobStatus36from lp.services.job.interfaces.job import JobStatus
37from lp.services.propertycache import cachedproperty
3738
3839
39UNEDITABLE_BUILD_STATES = (40UNEDITABLE_BUILD_STATES = (
@@ -95,7 +96,7 @@
95 BuildStatus.FAILEDTOUPLOAD: 'Could not be uploaded correctly',96 BuildStatus.FAILEDTOUPLOAD: 'Could not be uploaded correctly',
96 }.get(self.context.status, self.context.status.title)97 }.get(self.context.status, self.context.status.title)
9798
98 @property99 @cachedproperty
99 def eta(self):100 def eta(self):
100 """The datetime when the build job is estimated to complete.101 """The datetime when the build job is estimated to complete.
101102
@@ -114,14 +115,14 @@
114 duration = queue_record.estimated_duration115 duration = queue_record.estimated_duration
115 return start_time + duration116 return start_time + duration
116117
117 @property118 @cachedproperty
118 def date(self):119 def date(self):
119 """The date when the build completed or is estimated to complete."""120 """The date when the build completed or is estimated to complete."""
120 if self.estimate:121 if self.estimate:
121 return self.eta122 return self.eta
122 return self.context.date_finished123 return self.context.date_finished
123124
124 @property125 @cachedproperty
125 def estimate(self):126 def estimate(self):
126 """If true, the date value is an estimate."""127 """If true, the date value is an estimate."""
127 if self.context.date_finished is not None:128 if self.context.date_finished is not None:
128129
=== modified file 'lib/lp/code/browser/tests/test_sourcepackagerecipe.py'
--- lib/lp/code/browser/tests/test_sourcepackagerecipe.py 2010-11-24 18:40:48 +0000
+++ lib/lp/code/browser/tests/test_sourcepackagerecipe.py 2010-11-30 01:38:20 +0000
@@ -42,6 +42,7 @@
42from lp.code.interfaces.sourcepackagerecipe import MINIMAL_RECIPE_TEXT42from lp.code.interfaces.sourcepackagerecipe import MINIMAL_RECIPE_TEXT
43from lp.code.tests.helpers import recipe_parser_newest_version43from lp.code.tests.helpers import recipe_parser_newest_version
44from lp.registry.interfaces.pocket import PackagePublishingPocket44from lp.registry.interfaces.pocket import PackagePublishingPocket
45from lp.services.propertycache import clear_property_cache
45from lp.soyuz.model.processor import ProcessorFamily46from lp.soyuz.model.processor import ProcessorFamily
46from lp.testing import (47from lp.testing import (
47 ANONYMOUS,48 ANONYMOUS,
@@ -691,7 +692,7 @@
691692
692class TestSourcePackageRecipeView(TestCaseForRecipe):693class TestSourcePackageRecipeView(TestCaseForRecipe):
693694
694 layer = DatabaseFunctionalLayer695 layer = LaunchpadFunctionalLayer
695696
696 def test_index(self):697 def test_index(self):
697 recipe = self.makeRecipe()698 recipe = self.makeRecipe()
@@ -716,7 +717,7 @@
716 Distribution series: Secret Squirrel717 Distribution series: Secret Squirrel
717718
718 Latest builds719 Latest builds
719 Status Time Distribution series Archive720 Status When complete Distribution series Archive
720 Successful build on 2010-03-16 Secret Squirrel Secret PPA721 Successful build on 2010-03-16 Secret Squirrel Secret PPA
721 Request build\(s\)722 Request build\(s\)
722723
@@ -724,12 +725,86 @@
724 # bzr-builder format 0.2 deb-version {debupstream}-0~{revno}725 # bzr-builder format 0.2 deb-version {debupstream}-0~{revno}
725 lp://dev/~chef/chocolate/cake""", self.getMainText(recipe))726 lp://dev/~chef/chocolate/cake""", self.getMainText(recipe))
726727
728 def test_index_success_with_buildlog(self):
729 # The buildlog is shown if it is there.
730 recipe = self.makeRecipe()
731 build = removeSecurityProxy(self.factory.makeSourcePackageRecipeBuild(
732 recipe=recipe, distroseries=self.squirrel, archive=self.ppa))
733 build.status = BuildStatus.FULLYBUILT
734 build.date_started = datetime(2010, 03, 16, tzinfo=utc)
735 build.date_finished = datetime(2010, 03, 16, tzinfo=utc)
736 build.log = self.factory.makeLibraryFileAlias()
737
738 self.assertTextMatchesExpressionIgnoreWhitespace("""\
739 Latest builds
740 Status .* Archive
741 Successful build on 2010-03-16 buildlog \(.*\) Secret Squirrel Secret PPA
742 Request build\(s\)""", self.getMainText(recipe))
743
744 def test_index_success_with_binary_builds(self):
745 # Binary builds are shown after the recipe builds if there are any.
746 recipe = self.makeRecipe()
747 build = removeSecurityProxy(self.factory.makeSourcePackageRecipeBuild(
748 recipe=recipe, distroseries=self.squirrel, archive=self.ppa))
749 build.status = BuildStatus.FULLYBUILT
750 build.date_started = datetime(2010, 03, 16, tzinfo=utc)
751 build.date_finished = datetime(2010, 03, 16, tzinfo=utc)
752 build.log = self.factory.makeLibraryFileAlias()
753 package_name = self.factory.getOrMakeSourcePackageName('chocolate')
754 source_package_release = self.factory.makeSourcePackageRelease(
755 archive=self.ppa, sourcepackagename=package_name, distroseries=self.squirrel,
756 source_package_recipe_build=build, version='0+r42')
757 builder = self.factory.makeBuilder()
758 binary_build = self.factory.makeBinaryPackageBuild(
759 source_package_release=source_package_release,
760 distroarchseries=self.squirrel.nominatedarchindep,
761 processor=builder.processor)
762 binary_build.queueBuild()
763
764 self.assertTextMatchesExpressionIgnoreWhitespace("""\
765 Latest builds
766 Status .* Archive
767 Successful build on 2010-03-16 buildlog \(.*\) Secret Squirrel Secret PPA
768 chocolate - 0\+r42 in .* \(estimated\) i386
769 Request build\(s\)""", self.getMainText(recipe))
770
771 def test_index_success_with_completed_binary_build(self):
772 # Binary builds show their buildlog too.
773 recipe = self.makeRecipe()
774 build = removeSecurityProxy(self.factory.makeSourcePackageRecipeBuild(
775 recipe=recipe, distroseries=self.squirrel, archive=self.ppa))
776 build.status = BuildStatus.FULLYBUILT
777 build.date_started = datetime(2010, 03, 16, tzinfo=utc)
778 build.date_finished = datetime(2010, 03, 16, tzinfo=utc)
779 build.log = self.factory.makeLibraryFileAlias()
780 package_name = self.factory.getOrMakeSourcePackageName('chocolate')
781 source_package_release = self.factory.makeSourcePackageRelease(
782 archive=self.ppa, sourcepackagename=package_name, distroseries=self.squirrel,
783 source_package_recipe_build=build, version='0+r42')
784 builder = self.factory.makeBuilder()
785 binary_build = removeSecurityProxy(self.factory.makeBinaryPackageBuild(
786 source_package_release=source_package_release,
787 distroarchseries=self.squirrel.nominatedarchindep,
788 processor=builder.processor))
789 binary_build.queueBuild()
790 binary_build.status = BuildStatus.FULLYBUILT
791 binary_build.date_started = datetime(2010, 04, 16, tzinfo=utc)
792 binary_build.date_finished = datetime(2010, 04, 16, tzinfo=utc)
793 binary_build.log = self.factory.makeLibraryFileAlias()
794
795 self.assertTextMatchesExpressionIgnoreWhitespace("""\
796 Latest builds
797 Status .* Archive
798 Successful build on 2010-03-16 buildlog \(.*\) Secret Squirrel Secret PPA
799 chocolate - 0\+r42 on 2010-04-16 buildlog \(.*\) i386
800 Request build\(s\)""", self.getMainText(recipe))
801
727 def test_index_no_builds(self):802 def test_index_no_builds(self):
728 """A message should be shown when there are no builds."""803 """A message should be shown when there are no builds."""
729 recipe = self.makeRecipe()804 recipe = self.makeRecipe()
730 self.assertTextMatchesExpressionIgnoreWhitespace("""\805 self.assertTextMatchesExpressionIgnoreWhitespace("""\
731 Latest builds806 Latest builds
732 Status Time Distribution series Archive807 Status .* Archive
733 This recipe has not been built yet.""", self.getMainText(recipe))808 This recipe has not been built yet.""", self.getMainText(recipe))
734809
735 def test_index_no_suitable_builders(self):810 def test_index_no_suitable_builders(self):
@@ -738,7 +813,7 @@
738 recipe=recipe, distroseries=self.squirrel, archive=self.ppa))813 recipe=recipe, distroseries=self.squirrel, archive=self.ppa))
739 self.assertTextMatchesExpressionIgnoreWhitespace("""814 self.assertTextMatchesExpressionIgnoreWhitespace("""
740 Latest builds815 Latest builds
741 Status Time Distribution series Archive816 Status .* Archive
742 No suitable builders Secret Squirrel Secret PPA817 No suitable builders Secret Squirrel Secret PPA
743 Request build\(s\)""", self.getMainText(recipe))818 Request build\(s\)""", self.getMainText(recipe))
744819
@@ -756,7 +831,7 @@
756 self.factory.makeBuilder()831 self.factory.makeBuilder()
757 pattern = """\832 pattern = """\
758 Latest builds833 Latest builds
759 Status Time Distribution series Archive834 Status .* Archive
760 Pending build in .* \(estimated\) Secret Squirrel Secret PPA835 Pending build in .* \(estimated\) Secret Squirrel Secret PPA
761 Request build\(s\)836 Request build\(s\)
762837
@@ -946,8 +1021,10 @@
946 view = self.makeBuildView()1021 view = self.makeBuildView()
947 self.assertTrue(view.estimate)1022 self.assertTrue(view.estimate)
948 view.context.buildqueue_record.job.start()1023 view.context.buildqueue_record.job.start()
1024 clear_property_cache(view)
949 self.assertTrue(view.estimate)1025 self.assertTrue(view.estimate)
950 removeSecurityProxy(view.context).date_finished = datetime.now(utc)1026 removeSecurityProxy(view.context).date_finished = datetime.now(utc)
1027 clear_property_cache(view)
951 self.assertFalse(view.estimate)1028 self.assertFalse(view.estimate)
9521029
953 def test_eta(self):1030 def test_eta(self):
@@ -966,11 +1043,13 @@
966 recipe_build=build)1043 recipe_build=build)
967 queue_entry._now = lambda: datetime(1970, 1, 1, 0, 0, 0, 0, utc)1044 queue_entry._now = lambda: datetime(1970, 1, 1, 0, 0, 0, 0, utc)
968 self.factory.makeBuilder()1045 self.factory.makeBuilder()
1046 clear_property_cache(view)
969 self.assertIsNot(None, view.eta)1047 self.assertIsNot(None, view.eta)
970 self.assertEqual(1048 self.assertEqual(
971 queue_entry.getEstimatedJobStartTime() +1049 queue_entry.getEstimatedJobStartTime() +
972 queue_entry.estimated_duration, view.eta)1050 queue_entry.estimated_duration, view.eta)
973 queue_entry.job.start()1051 queue_entry.job.start()
1052 clear_property_cache(view)
974 self.assertEqual(1053 self.assertEqual(
975 queue_entry.job.date_started + queue_entry.estimated_duration,1054 queue_entry.job.date_started + queue_entry.estimated_duration,
976 view.eta)1055 view.eta)
9771056
=== modified file 'lib/lp/code/templates/sourcepackagerecipe-index.pt'
--- lib/lp/code/templates/sourcepackagerecipe-index.pt 2010-11-09 04:24:09 +0000
+++ lib/lp/code/templates/sourcepackagerecipe-index.pt 2010-11-30 01:38:20 +0000
@@ -7,6 +7,13 @@
7 i18n:domain="launchpad"7 i18n:domain="launchpad"
8>8>
99
10<metal:block fill-slot="head_epilogue">
11 <style type="text/css">
12 .binary-build .indent {
13 padding-left: 2em;
14 }
15 </style>
16</metal:block>
1017
11<body>18<body>
1219
@@ -86,14 +93,15 @@
86 <thead>93 <thead>
87 <tr>94 <tr>
88 <th>Status</th>95 <th>Status</th>
89 <th>Time</th>96 <th>When complete</th>
90 <th>Distribution series</th>97 <th>Distribution series</th>
91 <th>Archive</th>98 <th>Archive</th>
92 </tr>99 </tr>
93 </thead>100 </thead>
94 <tbody>101 <tbody>
95 <tr tal:repeat="build view/builds">102 <tal:recipe-builds repeat="build view/builds">
96 <tal:build-view define="buildview nocall:build/@@+index">103 <tal:build-view define="buildview nocall:build/@@+index">
104 <tr>
97 <td>105 <td>
98 <span tal:replace="structure build/image:icon" />106 <span tal:replace="structure build/image:icon" />
99 <a tal:content="buildview/status"107 <a tal:content="buildview/status"
@@ -102,8 +110,15 @@
102 <td>110 <td>
103 <tal:date replace="buildview/date/fmt:displaydate" />111 <tal:date replace="buildview/date/fmt:displaydate" />
104 <tal:estimate condition="buildview/estimate">112 <tal:estimate condition="buildview/estimate">
105 (estimated)113 (estimated)
106 </tal:estimate>114 </tal:estimate>
115
116 <tal:build-log define="file build/log"
117 tal:condition="file">
118 <a class="sprite download"
119 tal:attributes="href build/log_url">buildlog</a>
120 (<span tal:replace="file/content/filesize/fmt:bytes" />)
121 </tal:build-log>
107 </td>122 </td>
108 <td>123 <td>
109 <tal:distro124 <tal:distro
@@ -112,8 +127,38 @@
112 <td>127 <td>
113 <tal:archive replace="structure build/archive/fmt:link"/>128 <tal:archive replace="structure build/archive/fmt:link"/>
114 </td>129 </td>
115 </tal:build-view>
116 </tr>130 </tr>
131 <tal:binary-builds repeat="binary buildview/binary_builds">
132 <tr tal:define="binaryview nocall:binary/@@+index"
133 class="binary-build">
134 <td class="indent">
135 <span tal:replace="structure binary/image:icon"/>
136 <a tal:content="binary/source_package_release/title"
137 tal:attributes="href binary/fmt:url">package - version</a>
138 </td>
139 <td>
140 <tal:date replace="binaryview/date/fmt:displaydate" />
141 <tal:estimate condition="binaryview/estimate">
142 (estimated)
143 </tal:estimate>
144
145 <tal:build-log define="file binary/log"
146 tal:condition="file">
147 <a class="sprite download"
148 tal:attributes="href binary/log_url">buildlog</a>
149 (<span tal:replace="file/content/filesize/fmt:bytes" />)
150 </tal:build-log>
151 </td>
152 <td class="indent">
153 <a class="sprite distribution"
154 tal:define="archseries binary/distro_arch_series"
155 tal:attributes="href archseries/fmt:url"
156 tal:content="archseries/architecturetag">i386</a>
157 </td>
158 </tr>
159 </tal:binary-builds>
160 </tal:build-view>
161 </tal:recipe-builds>
117 </tbody>162 </tbody>
118 </table>163 </table>
119 <p tal:condition="not: view/builds">164 <p tal:condition="not: view/builds">
120165
=== modified file 'lib/lp/soyuz/browser/build.py'
--- lib/lp/soyuz/browser/build.py 2010-11-23 23:22:27 +0000
+++ lib/lp/soyuz/browser/build.py 2010-11-30 01:38:20 +0000
@@ -242,6 +242,39 @@
242 self.context.status == BuildStatus.NEEDSBUILD and242 self.context.status == BuildStatus.NEEDSBUILD and
243 self.context.buildqueue_record.job.status == JobStatus.WAITING)243 self.context.buildqueue_record.job.status == JobStatus.WAITING)
244244
245 @cachedproperty
246 def eta(self):
247 """The datetime when the build job is estimated to complete.
248
249 This is the BuildQueue.estimated_duration plus the
250 Job.date_started or BuildQueue.getEstimatedJobStartTime.
251 """
252 if self.context.buildqueue_record is None:
253 return None
254 queue_record = self.context.buildqueue_record
255 if queue_record.job.status == JobStatus.WAITING:
256 start_time = queue_record.getEstimatedJobStartTime()
257 if start_time is None:
258 return None
259 else:
260 start_time = queue_record.job.date_started
261 duration = queue_record.estimated_duration
262 return start_time + duration
263
264 @cachedproperty
265 def date(self):
266 """The date when the build completed or is estimated to complete."""
267 if self.estimate:
268 return self.eta
269 return self.context.date_finished
270
271 @cachedproperty
272 def estimate(self):
273 """If true, the date value is an estimate."""
274 if self.context.date_finished is not None:
275 return False
276 return self.eta is not None
277
245278
246class BuildRetryView(BuildView):279class BuildRetryView(BuildView):
247 """View class for retrying `IBinaryPackageBuild`s"""280 """View class for retrying `IBinaryPackageBuild`s"""
248281
=== modified file 'lib/lp/soyuz/model/processor.py'
--- lib/lp/soyuz/model/processor.py 2010-08-20 20:31:18 +0000
+++ lib/lp/soyuz/model/processor.py 2010-11-30 01:38:20 +0000
@@ -38,6 +38,9 @@
38 title = StringCol(dbName='title', notNull=True)38 title = StringCol(dbName='title', notNull=True)
39 description = StringCol(dbName='description', notNull=True)39 description = StringCol(dbName='description', notNull=True)
4040
41 def __repr__(self):
42 return "<Processor %r>" % self.title
43
4144
42class ProcessorFamily(SQLBase):45class ProcessorFamily(SQLBase):
43 implements(IProcessorFamily)46 implements(IProcessorFamily)
@@ -55,6 +58,9 @@
55 return Processor(family=self, name=name, title=title,58 return Processor(family=self, name=name, title=title,
56 description=description)59 description=description)
5760
61 def __repr__(self):
62 return "<ProcessorFamily %r>" % self.title
63
5864
59class ProcessorFamilySet:65class ProcessorFamilySet:
60 implements(IProcessorFamilySet)66 implements(IProcessorFamilySet)
6167
=== modified file 'lib/lp/soyuz/templates/build-index.pt'
--- lib/lp/soyuz/templates/build-index.pt 2010-08-06 16:01:38 +0000
+++ lib/lp/soyuz/templates/build-index.pt 2010-11-30 01:38:20 +0000
@@ -190,8 +190,7 @@
190 <li tal:define="file context/log"190 <li tal:define="file context/log"
191 tal:condition="file">191 tal:condition="file">
192 <a class="sprite download"192 <a class="sprite download"
193 tal:attributes="href context/log_url"193 tal:attributes="href context/log_url">buildlog</a>
194 tal:content="string: buildlog">BUILDLOG</a>
195 (<span tal:replace="file/content/filesize/fmt:bytes" />)194 (<span tal:replace="file/content/filesize/fmt:bytes" />)
196 </li>195 </li>
197 <li tal:define="file context/upload_log"196 <li tal:define="file context/upload_log"
198197
=== modified file 'lib/lp/testing/factory.py'
--- lib/lp/testing/factory.py 2010-11-25 17:24:59 +0000
+++ lib/lp/testing/factory.py 2010-11-30 01:38:20 +0000
@@ -2771,7 +2771,7 @@
27712771
2772 def makeBinaryPackageBuild(self, source_package_release=None,2772 def makeBinaryPackageBuild(self, source_package_release=None,
2773 distroarchseries=None, archive=None, builder=None,2773 distroarchseries=None, archive=None, builder=None,
2774 status=None, pocket=None):2774 status=None, pocket=None, date_created=None, processor=None):
2775 """Create a BinaryPackageBuild.2775 """Create a BinaryPackageBuild.
27762776
2777 If archive is not supplied, the source_package_release is used2777 If archive is not supplied, the source_package_release is used
@@ -2795,7 +2795,8 @@
2795 self.makeSourcePackagePublishingHistory(2795 self.makeSourcePackagePublishingHistory(
2796 distroseries=source_package_release.upload_distroseries,2796 distroseries=source_package_release.upload_distroseries,
2797 archive=archive, sourcepackagerelease=source_package_release)2797 archive=archive, sourcepackagerelease=source_package_release)
2798 processor = self.makeProcessor()2798 if processor is None:
2799 processor = self.makeProcessor()
2799 if distroarchseries is None:2800 if distroarchseries is None:
2800 distroarchseries = self.makeDistroArchSeries(2801 distroarchseries = self.makeDistroArchSeries(
2801 distroseries=source_package_release.upload_distroseries,2802 distroseries=source_package_release.upload_distroseries,
@@ -2804,6 +2805,8 @@
2804 status = BuildStatus.NEEDSBUILD2805 status = BuildStatus.NEEDSBUILD
2805 if pocket is None:2806 if pocket is None:
2806 pocket = PackagePublishingPocket.RELEASE2807 pocket = PackagePublishingPocket.RELEASE
2808 if date_created is None:
2809 date_created = self.getUniqueDate()
2807 binary_package_build = getUtility(IBinaryPackageBuildSet).new(2810 binary_package_build = getUtility(IBinaryPackageBuildSet).new(
2808 source_package_release=source_package_release,2811 source_package_release=source_package_release,
2809 processor=processor,2812 processor=processor,
@@ -2811,7 +2814,7 @@
2811 status=status,2814 status=status,
2812 archive=archive,2815 archive=archive,
2813 pocket=pocket,2816 pocket=pocket,
2814 date_created=self.getUniqueDate())2817 date_created=date_created)
2815 naked_build = removeSecurityProxy(binary_package_build)2818 naked_build = removeSecurityProxy(binary_package_build)
2816 naked_build.builder = builder2819 naked_build.builder = builder
2817 return binary_package_build2820 return binary_package_build