Merge lp:~jml/launchpad/process-upload-checks into lp:launchpad/db-devel
- process-upload-checks
- Merge into db-devel
Status: | Merged |
---|---|
Approved by: | Julian Edwards |
Approved revision: | no longer in the source branch. |
Merged at revision: | not available |
Proposed branch: | lp:~jml/launchpad/process-upload-checks |
Merge into: | lp:launchpad/db-devel |
Prerequisite: | lp:~jml/launchpad/wellington |
Diff against target: |
843 lines (+283/-100) 20 files modified
configs/development/launchpad-lazr.conf (+1/-1) configs/testrunner/launchpad-lazr.conf (+1/-1) database/schema/security.cfg (+8/-0) lib/lp/archiveuploader/nascentupload.py (+4/-4) lib/lp/archiveuploader/uploadpolicy.py (+37/-2) lib/lp/archiveuploader/uploadprocessor.py (+4/-1) lib/lp/buildmaster/interfaces/buildbase.py (+18/-2) lib/lp/buildmaster/interfaces/buildfarmjob.py (+3/-3) lib/lp/buildmaster/model/buildbase.py (+50/-23) lib/lp/buildmaster/model/builder.py (+1/-2) lib/lp/buildmaster/model/buildfarmjob.py (+1/-1) lib/lp/buildmaster/tests/test_buildbase.py (+82/-0) lib/lp/soyuz/configure.zcml (+34/-29) lib/lp/soyuz/interfaces/sourcepackagerecipebuild.py (+1/-0) lib/lp/soyuz/model/build.py (+8/-2) lib/lp/soyuz/model/buildpackagejob.py (+2/-2) lib/lp/soyuz/model/recipebuilder.py (+5/-4) lib/lp/soyuz/model/sourcepackagerecipebuild.py (+7/-5) lib/lp/soyuz/model/sourcepackagerecipedata.py (+2/-2) lib/lp/soyuz/tests/test_recipebuilder.py (+14/-16) |
To merge this branch: | bzr merge lp:~jml/launchpad/process-upload-checks |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Julian Edwards (community) | Approve | ||
Canonical Launchpad Engineering | Pending | ||
Review via email:
|
Commit message
Allow uploads from recipe jobs. Upload policies are now specified explicitly by Build objects, rather than in configuration files.
Description of the change
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Jonathan Lange (jml) wrote : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Jonathan Lange (jml) wrote : | # |
I should note also that this has been tested, sort of, on wgrant's laptop, and that the config changes are somewhat in lock-step with the code changes. I'll submit a branch to change the production configs.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Jonathan Lange (jml) wrote : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Julian Edwards (julian-edwards) wrote : | # |
The diff below has got conflict markers in it. Also, when I diffed locally, it's 8000 lines against devel, or 17000 against db-devel. WTF!
So, I'm backing off reviewing this for now. Can you grab me ASAP so we can get this done.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Jonathan Lange (jml) wrote : | # |
Hi Julian,
I've fixed a whole bunch of conflicts as well as all of the failing tests from my last "fix all the conflicts and run the tests" run. I'm running the tests now, and will no doubt have fixed all of the errors by the time you wake.
jml
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Jonathan Lange (jml) wrote : | # |
The tests do pass.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Julian Edwards (julian-edwards) wrote : | # |
Thanks for fixing things! Here's my review:
> + # XXX: JonathanLange 2010-01-15: This shouldn't instantiate policy
> + # types. They should instead have names as class variables.
The XXX should reference a bug :) Or better still, fix it, it's an easy change.
> + # XXX: JonathanLange 2010-01-15: This has to be exactly the same
> + # string as the one in SourcePackageRe
> + # out a shared constant.
Same here.
> class SourcePackageRe
Did you double check the inherited policy options for this? I think it looks sane but I have to ask ...
> + # XXX: JonathanLange 2010-01-15: We should not be re-using magical
> + # string literals. Zombie Dijkstra will come and kill us in our sleep.
bug number *cough* :)
> - buildqueue_record = Attribute(
> + buildqueue_record = Attribute(
I know you're just fixing the text, but we can surely do better than "Attribute".
> + policy_name = Attribute(
> + "The upload policy to use for handling these builds.")
And here!
> + uploader_argv = list(config.
Can you rename this variable to something like "uploader_command". The "argv" bit made me look twice since I was expecting only parameters to the command but it's actually the base command from the config.
> + # XXX: Duplicated from getUploaderCommand
> uploader_
Why not turn it into a property on the class then?
> - classProvides(
> + classProvides(
Why did you remove that? I note that it's there in db-devel but not devel.
> + # XXX: BuildBase is supposed to implement IBuildBase, but doesn't atm.
> + # Since it's not the focus of the branch, we'll postpone the work.
From the code I just looked at, it does! If there's a genuine problem then we need a bug please - tag wellington of course. This is becoming known as the Wellington project I think!
FWIW, I think all classes should have basic doctests, I really don't like this unit testing for their basic features.
What layer is TestBuildBase going to run in if it's not explicitly specified?
> +class TestBuildBaseHa
Crappy name alert! Perhaps "TestBuildBaseW
Or maybe, s/TestBuildBase
> + <adapter factory=
> + permission=
You can fill a gap in my knowledge here, what does this do when declared without the "provides" and "for" ?
> + build_log_url = exported(
Why is this moved from BuildBase to Build?
> + # JRV 2010-01-15: The database table really should have a pocket
> + # column, although this is not a big problem at the moment as recipe
> + # builds only happen for PPA's (so far). (bug 507307)
Can you XXX this in the usual format please.
I guess I should tell Jelmer how this works too :)
> + distroseries.n...
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Jonathan Lange (jml) wrote : | # |
On Fri, Jan 22, 2010 at 3:11 AM, Julian Edwards
<email address hidden> wrote:
> Review: Needs Information code
> Thanks for fixing things! Here's my review:
>
Hey Julian,
Thanks for the review.
As a meta-comment, I'd really appreciate it if you could leave the
filenames from the diff in your reply. It makes it much, much faster
to find the relevant code in my editor.
>> + # XXX: JonathanLange 2010-01-15: This shouldn't instantiate policy
>> + # types. They should instead have names as class variables.
>
> The XXX should reference a bug :) Or better still, fix it, it's an easy change.
>
Bug filed. It's an easy change, but the branch is big enough as-is.
I'll make the change in a separate branch.
>> + # XXX: JonathanLange 2010-01-15: This has to be exactly the same
>> + # string as the one in SourcePackageRe
>> + # out a shared constant.
>
> Same here.
>
And same reply.
>> class SourcePackageRe
>
> Did you double check the inherited policy options for this? I think it looks sane but I have to ask ...
>
I don't know if those bits are good. Your call.
>> + # XXX: JonathanLange 2010-01-15: We should not be re-using magical
>> + # string literals. Zombie Dijkstra will come and kill us in our sleep.
>
> bug number *cough* :)
>
Added.
>> - buildqueue_record = Attribute(
>> + buildqueue_record = Attribute(
>
> I know you're just fixing the text, but we can surely do better than "Attribute".
>
Changed to Object(...)
>> + policy_name = Attribute(
>> + "The upload policy to use for handling these builds.")
>
> And here!
>
Changed to TextLine(...)
>> + uploader_argv = list(config.
>
> Can you rename this variable to something like "uploader_command". The "argv" bit made me look twice since I was expecting only parameters to the command but it's actually the base command from the config.
Ahh ok. FWIW, I used "argv" specifically because it corresponds to
argv arrays in C convention by including the argument.
Changed to uploader_command.
>
>> + # XXX: Duplicated from getUploaderCommand
>> uploader_
>
> Why not turn it into a property on the class then?
>
Because it's parametrized -- it depends on upload_leaf. I've made it
an argument to getUploaderCommand.
>> - classProvides(
>> + classProvides(
>
> Why did you remove that? I note that it's there in db-devel but not devel.
>
_Probably_ a bad merge. Restored.
>> + # XXX: BuildBase is supposed to implement IBuildBase, but doesn't atm.
>> + # Since it's not the focus of the branch, we'll postpone the work.
>
>
>From the code I just looked at, it does! If there's a genuine problem then we need a bug please - tag wellington of course. This is becoming known as the Wellington project I think!
It didn't when I su...
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Julian Edwards (julian-edwards) wrote : | # |
review approve
merge approve
> As a meta-comment, I'd really appreciate it if you could leave the
> filenames from the diff in your reply. It makes it much, much faster
> to find the relevant code in my editor.
Right, sorry, I hate that too.
> Bug filed. It's an easy change, but the branch is big enough as-is.
> I'll make the change in a separate branch.
Cool, thank you.
> self.unsigned_
> self.unsigned_
> self.can_
> self.can_
>
> I don't know if those bits are good. Your call.
That looks fine, thanks for checking (again).
> >> - buildqueue_record = Attribute(
> >> + buildqueue_record = Attribute(
> >
> > I know you're just fixing the text, but we can surely do better than
> > "Attribute".
>
> Changed to Object(...)
Isn't it a Reference() ?
> Ahh ok. FWIW, I used "argv" specifically because it corresponds to
> argv arrays in C convention by including the argument.
>
> Changed to uploader_command.
True. I always hated that :)
>
> >> + # XXX: Duplicated from getUploaderCommand
> >> uploader_
> >
> > Why not turn it into a property on the class then?
>
> Because it's parametrized -- it depends on upload_leaf. I've made it
> an argument to getUploaderCommand.
D'oh, right.
> >> - classProvides(
> >> ISpecificBuildF
> >
> > Why did you remove that? I note that it's there in db-devel but not
> > devel.
>
> _Probably_ a bad merge. Restored.
Phew, thanks ;)
Since it didn't break anything, this indicates a missing test :/
> It didn't when I submitted this branch last week, and when I
> re-enabled the test, it failed. The problem is genuine, so I've filed
> a bug and added it to the comment.
Argh, ok, thanks. I was just looking at the "implements" rather than actually
looking to see what it was implementing!
> > FWIW, I think all classes should have basic doctests, I really don't like
> > this unit testing for their basic features.
>
> OK. I haven't added any doctests in this branch.
Yeah, it's a matter of policy I'll raise in a reviewers' meeting I think.
> > What layer is TestBuildBase going to run in if it's not explicitly
> > specified?
>
> No layer at all. It doesn't need to be run in a layer. We want more
> tests like this, because they are fast :)
Ah! Ok, that's cool. We need more of this! You should totally email the
list about that.
> I forwarded you an email on the subject from the Canonical thread.
> http://
Right, I remember it now, thanks for the pointer.
> >> + build_log_url = exported(
> >
> > Why is this moved from BuildBase to Build?
>
> When I was trying to get the assertProvides(
> thing to pass, it turned out that BuildBase didn't implement this, so
> I moved the declaration.
Righto.
> I look forward to hearing back from you.
Land it!
Cheers,
J.
Preview Diff
1 | === modified file 'configs/development/launchpad-lazr.conf' |
2 | --- configs/development/launchpad-lazr.conf 2010-01-19 12:49:35 +0000 |
3 | +++ configs/development/launchpad-lazr.conf 2010-01-29 17:17:19 +0000 |
4 | @@ -15,7 +15,7 @@ |
5 | |
6 | [builddmaster] |
7 | root: /var/tmp/builddmaster/ |
8 | -uploader: scripts/process-upload.py -Mvv --context buildd |
9 | +uploader: scripts/process-upload.py -Mvv |
10 | |
11 | [buildsequencer] |
12 | mailproblemsto: root |
13 | |
14 | === modified file 'configs/testrunner/launchpad-lazr.conf' |
15 | --- configs/testrunner/launchpad-lazr.conf 2010-01-22 04:59:09 +0000 |
16 | +++ configs/testrunner/launchpad-lazr.conf 2010-01-29 17:17:19 +0000 |
17 | @@ -17,7 +17,7 @@ |
18 | |
19 | [builddmaster] |
20 | socket_timeout: 10 |
21 | -uploader: scripts/process-upload.py -Mvv --context buildd |
22 | +uploader: scripts/process-upload.py -Mvv |
23 | |
24 | [buildsequencer] |
25 | mailproblemsto: - |
26 | |
27 | === modified file 'database/schema/security.cfg' |
28 | --- database/schema/security.cfg 2010-01-26 02:05:23 +0000 |
29 | +++ database/schema/security.cfg 2010-01-29 17:17:19 +0000 |
30 | @@ -835,6 +835,7 @@ |
31 | public.archive = SELECT, UPDATE |
32 | public.archivearch = SELECT, UPDATE |
33 | public.archivedependency = SELECT |
34 | +public.branch = SELECT |
35 | public.buildqueue = SELECT, INSERT, UPDATE, DELETE |
36 | public.job = SELECT, INSERT, UPDATE, DELETE |
37 | public.buildpackagejob = SELECT, INSERT, UPDATE, DELETE |
38 | @@ -858,8 +859,15 @@ |
39 | public.processor = SELECT |
40 | public.processorfamily = SELECT |
41 | public.pocketchroot = SELECT, INSERT, UPDATE |
42 | +public.product = SELECT |
43 | +public.productseries = SELECT |
44 | public.component = SELECT |
45 | public.section = SELECT |
46 | +public.sourcepackagerecipe = SELECT |
47 | +public.sourcepackagerecipebuild = SELECT, UPDATE |
48 | +public.sourcepackagerecipebuildjob = SELECT, INSERT, UPDATE, DELETE |
49 | +public.sourcepackagerecipedata = SELECT |
50 | +public.sourcepackagerecipedatainstruction = SELECT |
51 | public.publishedpackage = SELECT |
52 | public.person = SELECT |
53 | public.emailaddress = SELECT |
54 | |
55 | === modified file 'lib/lp/archiveuploader/nascentupload.py' |
56 | --- lib/lp/archiveuploader/nascentupload.py 2009-11-24 23:12:23 +0000 |
57 | +++ lib/lp/archiveuploader/nascentupload.py 2010-01-29 17:17:19 +0000 |
58 | @@ -477,11 +477,12 @@ |
59 | return |
60 | |
61 | # Set up some convenient shortcut variables. |
62 | - signer = self.changes.signer |
63 | + |
64 | + uploader = self.policy.getUploader(self.changes) |
65 | archive = self.policy.archive |
66 | |
67 | # If we have no signer, there's no ACL we can apply. |
68 | - if signer is None: |
69 | + if uploader is None: |
70 | self.logger.debug("No signer, therefore ACL not processed") |
71 | return |
72 | |
73 | @@ -489,7 +490,7 @@ |
74 | ISourcePackageNameSet).queryByName(self.changes.dsc.package) |
75 | |
76 | rejection_reason = check_upload_to_archive( |
77 | - signer, self.policy.distroseries, source_name, archive, |
78 | + uploader, self.policy.distroseries, source_name, archive, |
79 | self.changes.dsc.component, self.policy.pocket, not self.is_new) |
80 | |
81 | if rejection_reason is not None: |
82 | @@ -894,7 +895,6 @@ |
83 | # Queue entries are created in the NEW state by default; at the |
84 | # end of this method we cope with uploads that aren't new. |
85 | self.logger.debug("Creating queue entry") |
86 | - distroseries = self.policy.distroseries |
87 | self.queue_root = self._createQueueEntry() |
88 | |
89 | # When binaryful and sourceful, we have a mixed-mode upload. |
90 | |
91 | === modified file 'lib/lp/archiveuploader/uploadpolicy.py' |
92 | --- lib/lp/archiveuploader/uploadpolicy.py 2009-12-14 00:04:19 +0000 |
93 | +++ lib/lp/archiveuploader/uploadpolicy.py 2010-01-29 17:17:19 +0000 |
94 | @@ -5,7 +5,11 @@ |
95 | |
96 | __metaclass__ = type |
97 | |
98 | -__all__ = ["findPolicyByName", "findPolicyByOptions", "UploadPolicyError"] |
99 | +__all__ = [ |
100 | + "findPolicyByName", |
101 | + "findPolicyByOptions", |
102 | + "UploadPolicyError", |
103 | + ] |
104 | |
105 | from zope.component import getUtility |
106 | |
107 | @@ -13,6 +17,8 @@ |
108 | from lp.registry.interfaces.distribution import IDistributionSet |
109 | from lp.registry.interfaces.series import SeriesStatus |
110 | from lp.registry.interfaces.pocket import PackagePublishingPocket |
111 | +from lp.soyuz.interfaces.sourcepackagerecipebuild import ( |
112 | + ISourcePackageRecipeBuildSource) |
113 | |
114 | |
115 | # Number of seconds in an hour (used later) |
116 | @@ -85,6 +91,10 @@ |
117 | # The earliest year we accept in a deb's file's mtime |
118 | self.earliest_year = 1984 |
119 | |
120 | + def getUploader(self, changes): |
121 | + """Get the person who is doing the uploading.""" |
122 | + return changes.signer |
123 | + |
124 | def setOptions(self, options): |
125 | """Store the options for later.""" |
126 | self.options = options |
127 | @@ -167,6 +177,8 @@ |
128 | @classmethod |
129 | def _registerPolicy(cls, policy_type): |
130 | """Register the given policy type as belonging to its given name.""" |
131 | + # XXX: JonathanLange 2010-01-15 bug=510892: This shouldn't instantiate |
132 | + # policy types. They should instead have names as class variables. |
133 | policy_name = policy_type().name |
134 | cls.policies[policy_name] = policy_type |
135 | |
136 | @@ -188,6 +200,7 @@ |
137 | findPolicyByName = AbstractUploadPolicy.findPolicyByName |
138 | findPolicyByOptions = AbstractUploadPolicy.findPolicyByOptions |
139 | |
140 | + |
141 | class InsecureUploadPolicy(AbstractUploadPolicy): |
142 | """The insecure upload policy is used by the poppy interface.""" |
143 | |
144 | @@ -306,7 +319,7 @@ |
145 | """The build daemon upload policy is invoked by the slave scanner.""" |
146 | |
147 | def __init__(self): |
148 | - AbstractUploadPolicy.__init__(self) |
149 | + super(BuildDaemonUploadPolicy, self).__init__() |
150 | self.name = 'buildd' |
151 | # We permit unsigned uploads because we trust our build daemons |
152 | self.unsigned_changes_ok = True |
153 | @@ -334,6 +347,28 @@ |
154 | AbstractUploadPolicy._registerPolicy(BuildDaemonUploadPolicy) |
155 | |
156 | |
157 | +class SourcePackageRecipeUploadPolicy(BuildDaemonUploadPolicy): |
158 | + """Policy for uploading the results of a source package recipe build.""" |
159 | + |
160 | + def __init__(self): |
161 | + super(SourcePackageRecipeUploadPolicy, self).__init__() |
162 | + # XXX: JonathanLange 2010-01-15 bug=510894: This has to be exactly the |
163 | + # same string as the one in SourcePackageRecipeBuild.policy_name. |
164 | + # Factor out a shared constant. |
165 | + self.name = 'recipe' |
166 | + self.can_upload_source = True |
167 | + self.can_upload_binaries = False |
168 | + |
169 | + def getUploader(self, changes): |
170 | + """Return the person doing the upload.""" |
171 | + build_id = int(getattr(self.options, 'buildid')) |
172 | + sprb = getUtility(ISourcePackageRecipeBuildSource).getById(build_id) |
173 | + return sprb.requester |
174 | + |
175 | + |
176 | +AbstractUploadPolicy._registerPolicy(SourcePackageRecipeUploadPolicy) |
177 | + |
178 | + |
179 | class SyncUploadPolicy(AbstractUploadPolicy): |
180 | """This policy is invoked when processing sync uploads.""" |
181 | |
182 | |
183 | === modified file 'lib/lp/archiveuploader/uploadprocessor.py' |
184 | --- lib/lp/archiveuploader/uploadprocessor.py 2009-06-24 23:33:29 +0000 |
185 | +++ lib/lp/archiveuploader/uploadprocessor.py 2010-01-29 17:17:19 +0000 |
186 | @@ -339,7 +339,10 @@ |
187 | |
188 | # Reject source upload to buildd upload paths. |
189 | first_path = relative_path.split(os.path.sep)[0] |
190 | - if first_path.isdigit() and policy.name != 'buildd': |
191 | + # XXX: JonathanLange 2010-01-15 bug=510894: We should not be re-using |
192 | + # magical string literals. Zombie Dijkstra will come and kill us in |
193 | + # our sleep. |
194 | + if first_path.isdigit() and policy.name not in ('buildd', 'recipe'): |
195 | error_message = ( |
196 | "Invalid upload path (%s) for this policy (%s)" % |
197 | (relative_path, policy.name)) |
198 | |
199 | === modified file 'lib/lp/buildmaster/interfaces/buildbase.py' |
200 | --- lib/lp/buildmaster/interfaces/buildbase.py 2010-01-20 02:02:02 +0000 |
201 | +++ lib/lp/buildmaster/interfaces/buildbase.py 2010-01-29 17:17:19 +0000 |
202 | @@ -19,11 +19,14 @@ |
203 | from lp.registry.interfaces.distribution import IDistribution |
204 | from lp.registry.interfaces.pocket import PackagePublishingPocket |
205 | from lp.soyuz.interfaces.archive import IArchive |
206 | +from lp.soyuz.interfaces.buildqueue import IBuildQueue |
207 | from canonical.launchpad.interfaces.librarian import ILibraryFileAlias |
208 | from canonical.launchpad import _ |
209 | |
210 | + |
211 | class IBuildBase(Interface): |
212 | """Common interface shared by farm jobs that build a package.""" |
213 | + |
214 | # XXX: wgrant 2010-01-20 bug=507712: Most of these attribute names |
215 | # are bad. |
216 | datecreated = exported( |
217 | @@ -68,10 +71,16 @@ |
218 | description=_("A URL for the build log. None if there is no " |
219 | "log available."))) |
220 | |
221 | - buildqueue_record = Attribute("Corespondent BuildQueue record") |
222 | + buildqueue_record = Object( |
223 | + schema=IBuildQueue, required=True, |
224 | + title=_("Corresponding BuildQueue record")) |
225 | |
226 | is_private = Attribute("Whether the build should be treated as private.") |
227 | |
228 | + policy_name = TextLine( |
229 | + title=_("Policy name"), required=True, |
230 | + description=_("The upload policy to use for handling these builds.")) |
231 | + |
232 | archive = exported( |
233 | Reference( |
234 | title=_("Archive"), schema=IArchive, |
235 | @@ -100,7 +109,14 @@ |
236 | title=_("Distribution"), required=True, |
237 | description=_("Shortcut for its distribution."))) |
238 | |
239 | - def handleStatus(status, queueItem, librarian, slave_status): |
240 | + def getUploaderCommand(upload_leaf): |
241 | + """Get the command to run as the uploader. |
242 | + |
243 | + :return: A list of command line arguments, beginning with the |
244 | + executable. |
245 | + """ |
246 | + |
247 | + def handleStatus(status, librarian, slave_status): |
248 | """Handle a finished build status from a slave. |
249 | |
250 | :param status: Slave build status string with 'BuildStatus.' stripped. |
251 | |
252 | === modified file 'lib/lp/buildmaster/interfaces/buildfarmjob.py' |
253 | --- lib/lp/buildmaster/interfaces/buildfarmjob.py 2010-01-18 22:01:19 +0000 |
254 | +++ lib/lp/buildmaster/interfaces/buildfarmjob.py 2010-01-29 17:17:19 +0000 |
255 | @@ -158,7 +158,7 @@ |
256 | |
257 | class IBuildFarmCandidateJobSelection(Interface): |
258 | """Operations for refining candidate job selection (optional). |
259 | - |
260 | + |
261 | Job type classes that do *not* need to refine candidate job selection may |
262 | be derived from `BuildFarmJob` which provides a base implementation of |
263 | this interface. |
264 | @@ -178,7 +178,7 @@ |
265 | SELECT TRUE |
266 | FROM Archive, Build, BuildPackageJob, DistroArchSeries |
267 | WHERE |
268 | - BuildPackageJob.job = Job.id AND |
269 | + BuildPackageJob.job = Job.id AND |
270 | .. |
271 | |
272 | :param processor: the type of processor that the candidate jobs are |
273 | @@ -192,7 +192,7 @@ |
274 | def postprocessCandidate(job, logger): |
275 | """True if the candidate job is fine and should be dispatched |
276 | to a builder, False otherwise. |
277 | - |
278 | + |
279 | :param job: The `BuildQueue` instance to be scrutinized. |
280 | :param logger: The logger to use. |
281 | |
282 | |
283 | === modified file 'lib/lp/buildmaster/model/buildbase.py' |
284 | --- lib/lp/buildmaster/model/buildbase.py 2010-01-20 01:24:01 +0000 |
285 | +++ lib/lp/buildmaster/model/buildbase.py 2010-01-29 17:17:19 +0000 |
286 | @@ -14,9 +14,9 @@ |
287 | import os |
288 | import pytz |
289 | import subprocess |
290 | -import time |
291 | |
292 | from storm.store import Store |
293 | +from zope.interface import implements |
294 | from zope.security.proxy import removeSecurityProxy |
295 | |
296 | from canonical.config import config |
297 | @@ -24,12 +24,54 @@ |
298 | from canonical.database.sqlbase import ( |
299 | clear_current_connection_cache, cursor, flush_database_updates) |
300 | from canonical.librarian.utils import copy_and_close |
301 | +from lp.buildmaster.interfaces.buildbase import IBuildBase |
302 | from lp.registry.interfaces.pocket import pocketsuffix |
303 | from lp.soyuz.interfaces.build import BuildStatus |
304 | from lp.soyuz.model.buildqueue import BuildQueue |
305 | |
306 | |
307 | class BuildBase: |
308 | + |
309 | + implements(IBuildBase) |
310 | + |
311 | + policy_name = 'buildd' |
312 | + |
313 | + def getUploadLeaf(self, build_id, now=None): |
314 | + """Return a directory name to store build things in. |
315 | + |
316 | + :param build_id: The id as returned by the slave, normally |
317 | + $BUILD_ID-$BUILDQUEUE_ID |
318 | + :param now: The `datetime` to use. If not provided, defaults to now. |
319 | + """ |
320 | + # UPLOAD_LEAF: <TIMESTAMP>-<BUILD_ID>-<BUILDQUEUE_ID> |
321 | + if now is None: |
322 | + now = datetime.datetime.now() |
323 | + return '%s-%s' % (now.strftime("%Y%m%d-%H%M%S"), build_id) |
324 | + |
325 | + def getUploadDir(self, upload_leaf): |
326 | + """Return the directory that things will be stored in.""" |
327 | + return os.path.join(config.builddmaster.root, 'incoming', upload_leaf) |
328 | + |
329 | + def getUploaderCommand(self, upload_leaf, uploader_logfilename): |
330 | + """See `IBuildBase`.""" |
331 | + root = os.path.abspath(config.builddmaster.root) |
332 | + uploader_command = list(config.builddmaster.uploader.split()) |
333 | + |
334 | + # add extra arguments for processing a binary upload |
335 | + extra_args = [ |
336 | + "--log-file", "%s" % uploader_logfilename, |
337 | + "-d", "%s" % self.distribution.name, |
338 | + "-s", "%s" % (self.distroseries.name + |
339 | + pocketsuffix[self.pocket]), |
340 | + "-b", "%s" % self.id, |
341 | + "-J", "%s" % upload_leaf, |
342 | + '--context=%s' % self.policy_name, |
343 | + "%s" % root, |
344 | + ] |
345 | + |
346 | + uploader_command.extend(extra_args) |
347 | + return uploader_command |
348 | + |
349 | def _getProxiedFileURL(self, library_file): |
350 | """Return the 'http_url' of a `ProxiedLibraryFileAlias`.""" |
351 | # Avoiding circular imports. |
352 | @@ -81,12 +123,10 @@ |
353 | # ensure we have the correct build root as: |
354 | # <BUILDMASTER_ROOT>/incoming/<UPLOAD_LEAF>/<TARGET_PATH>/[FILES] |
355 | root = os.path.abspath(config.builddmaster.root) |
356 | - incoming = os.path.join(root, 'incoming') |
357 | |
358 | # create a single directory to store build result files |
359 | - # UPLOAD_LEAF: <TIMESTAMP>-<BUILD_ID>-<BUILDQUEUE_ID> |
360 | - upload_leaf = "%s-%s" % (time.strftime("%Y%m%d-%H%M%S"), buildid) |
361 | - upload_dir = os.path.join(incoming, upload_leaf) |
362 | + upload_leaf = self.getUploadLeaf(buildid) |
363 | + upload_dir = self.getUploadDir(upload_leaf) |
364 | logger.debug("Storing build result at '%s'" % upload_dir) |
365 | |
366 | # Build the right UPLOAD_PATH so the distribution and archive |
367 | @@ -106,29 +146,16 @@ |
368 | out_file = open(out_file_name, "wb") |
369 | copy_and_close(slave_file, out_file) |
370 | |
371 | - uploader_argv = list(config.builddmaster.uploader.split()) |
372 | uploader_logfilename = os.path.join(upload_dir, 'uploader.log') |
373 | - logger.debug("Saving uploader log at '%s'" |
374 | - % uploader_logfilename) |
375 | - |
376 | - # add extra arguments for processing a binary upload |
377 | - extra_args = [ |
378 | - "--log-file", "%s" % uploader_logfilename, |
379 | - "-d", "%s" % self.distribution.name, |
380 | - "-s", "%s" % (self.distroseries.name + |
381 | - pocketsuffix[self.pocket]), |
382 | - "-b", "%s" % self.id, |
383 | - "-J", "%s" % upload_leaf, |
384 | - "%s" % root, |
385 | - ] |
386 | - |
387 | - uploader_argv.extend(extra_args) |
388 | + uploader_command = self.getUploaderCommand( |
389 | + upload_leaf, uploader_logfilename) |
390 | + logger.debug("Saving uploader log at '%s'" % uploader_logfilename) |
391 | |
392 | logger.debug("Invoking uploader on %s" % root) |
393 | - logger.debug("%s" % uploader_argv) |
394 | + logger.debug("%s" % uploader_command) |
395 | |
396 | uploader_process = subprocess.Popen( |
397 | - uploader_argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
398 | + uploader_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
399 | |
400 | # Nothing should be written to the stdout/stderr. |
401 | upload_stdout, upload_stderr = uploader_process.communicate() |
402 | |
403 | === modified file 'lib/lp/buildmaster/model/builder.py' |
404 | --- lib/lp/buildmaster/model/builder.py 2010-01-21 10:48:25 +0000 |
405 | +++ lib/lp/buildmaster/model/builder.py 2010-01-29 17:17:18 +0000 |
406 | @@ -457,7 +457,7 @@ |
407 | AND ( |
408 | -- The processor values either match or the candidate |
409 | -- job is processor-independent. |
410 | - buildqueue.processor = %s OR |
411 | + buildqueue.processor = %s OR |
412 | buildqueue.processor IS NULL) |
413 | AND ( |
414 | -- The virtualized values either match or the candidate |
415 | @@ -473,7 +473,6 @@ |
416 | self.virtualized) |
417 | order_clause = " ORDER BY buildqueue.lastscore DESC, buildqueue.id" |
418 | |
419 | - extra_tables = set() |
420 | extra_queries = [] |
421 | job_classes = specific_job_classes() |
422 | for job_type, job_class in job_classes.iteritems(): |
423 | |
424 | === modified file 'lib/lp/buildmaster/model/buildfarmjob.py' |
425 | --- lib/lp/buildmaster/model/buildfarmjob.py 2010-01-20 04:04:15 +0000 |
426 | +++ lib/lp/buildmaster/model/buildfarmjob.py 2010-01-29 17:17:19 +0000 |
427 | @@ -19,7 +19,7 @@ |
428 | class BuildFarmJob: |
429 | """Mix-in class for `IBuildFarmJob` implementations.""" |
430 | implements(IBuildFarmJob) |
431 | - classProvides(IBuildFarmCandidateJobSelection, ISpecificBuildFarmJobClass) |
432 | + classProvides(ISpecificBuildFarmJobClass, IBuildFarmCandidateJobSelection) |
433 | |
434 | def score(self): |
435 | """See `IBuildFarmJob`.""" |
436 | |
437 | === added file 'lib/lp/buildmaster/tests/test_buildbase.py' |
438 | --- lib/lp/buildmaster/tests/test_buildbase.py 1970-01-01 00:00:00 +0000 |
439 | +++ lib/lp/buildmaster/tests/test_buildbase.py 2010-01-29 17:17:19 +0000 |
440 | @@ -0,0 +1,82 @@ |
441 | +# Copyright 2010 Canonical Ltd. This software is licensed under the |
442 | +# GNU Affero General Public License version 3 (see the file LICENSE). |
443 | + |
444 | +"""Tests for `IBuildBase`.""" |
445 | + |
446 | +__metaclass__ = type |
447 | + |
448 | +from datetime import datetime |
449 | +import os |
450 | +import unittest |
451 | + |
452 | +from canonical.config import config |
453 | +from canonical.testing.layers import DatabaseFunctionalLayer |
454 | +from lp.buildmaster.interfaces.buildbase import IBuildBase |
455 | +from lp.buildmaster.model.buildbase import BuildBase |
456 | +from lp.registry.interfaces.pocket import pocketsuffix |
457 | +from lp.testing import TestCase, TestCaseWithFactory |
458 | + |
459 | + |
460 | +class TestBuildBase(TestCase): |
461 | + """Tests for `IBuildBase`.""" |
462 | + |
463 | + def disabled_test_build_base_provides_interface(self): |
464 | + # XXX: JonathanLange 2010-01-22 bug=510919: BuildBase is supposed to |
465 | + # implement IBuildBase, but doesn't atm. Since it's not the focus of |
466 | + # the branch, we'll postpone the work. |
467 | + build_base = BuildBase() |
468 | + self.assertProvides(build_base, IBuildBase) |
469 | + |
470 | + def test_getUploadLeaf(self): |
471 | + # getUploadLeaf returns the current time, followed by the build id. |
472 | + build_base = BuildBase() |
473 | + now = datetime.now() |
474 | + build_id = self.factory.getUniqueInteger() |
475 | + upload_leaf = build_base.getUploadLeaf(build_id, now=now) |
476 | + self.assertEqual( |
477 | + '%s-%s' % (now.strftime("%Y%m%d-%H%M%S"), build_id), upload_leaf) |
478 | + |
479 | + def test_getUploadDir(self): |
480 | + # getUploadDir is the absolute path to the directory in which things |
481 | + # are uploaded to. |
482 | + build_base = BuildBase() |
483 | + build_id = self.factory.getUniqueInteger() |
484 | + upload_leaf = build_base.getUploadLeaf(build_id) |
485 | + upload_dir = build_base.getUploadDir(upload_leaf) |
486 | + self.assertEqual( |
487 | + os.path.join(config.builddmaster.root, 'incoming', upload_leaf), |
488 | + upload_dir) |
489 | + |
490 | + |
491 | +class TestBuildBaseWithDatabase(TestCaseWithFactory): |
492 | + """Tests for `IBuildBase` that need objects from the rest of Launchpad.""" |
493 | + |
494 | + layer = DatabaseFunctionalLayer |
495 | + |
496 | + def test_getUploaderCommand(self): |
497 | + build_base = BuildBase() |
498 | + upload_leaf = self.factory.getUniqueString('upload-leaf') |
499 | + build_base.distroseries = self.factory.makeDistroSeries() |
500 | + build_base.distribution = build_base.distroseries.distribution |
501 | + build_base.pocket = self.factory.getAnyPocket() |
502 | + build_base.id = self.factory.getUniqueInteger() |
503 | + build_base.policy_name = self.factory.getUniqueString('policy-name') |
504 | + config_args = list(config.builddmaster.uploader.split()) |
505 | + log_file = self.factory.getUniqueString('logfile') |
506 | + config_args.extend( |
507 | + ['--log-file', log_file, |
508 | + '-d', build_base.distribution.name, |
509 | + '-s', (build_base.distroseries.name |
510 | + + pocketsuffix[build_base.pocket]), |
511 | + '-b', str(build_base.id), |
512 | + '-J', upload_leaf, |
513 | + '--context=%s' % build_base.policy_name, |
514 | + os.path.abspath(config.builddmaster.root), |
515 | + ]) |
516 | + uploader_command = build_base.getUploaderCommand( |
517 | + upload_leaf, log_file) |
518 | + self.assertEqual(config_args, uploader_command) |
519 | + |
520 | + |
521 | +def test_suite(): |
522 | + return unittest.TestLoader().loadTestsFromName(__name__) |
523 | |
524 | === modified file 'lib/lp/soyuz/configure.zcml' |
525 | --- lib/lp/soyuz/configure.zcml 2010-01-20 07:47:53 +0000 |
526 | +++ lib/lp/soyuz/configure.zcml 2010-01-29 17:17:19 +0000 |
527 | @@ -930,6 +930,39 @@ |
528 | permission="zope.Public" /> |
529 | |
530 | <!-- SourcePackageRecipe --> |
531 | + |
532 | + <securedutility |
533 | + component="lp.soyuz.model.sourcepackagerecipe.SourcePackageRecipe" |
534 | + provides="lp.soyuz.interfaces.sourcepackagerecipe.ISourcePackageRecipeSource"> |
535 | + <allow interface="lp.soyuz.interfaces.sourcepackagerecipe.ISourcePackageRecipeSource"/> |
536 | + </securedutility> |
537 | + |
538 | + <class |
539 | + class="lp.soyuz.model.sourcepackagerecipebuild.SourcePackageRecipeBuild"> |
540 | + <allow interface="lp.soyuz.interfaces.sourcepackagerecipebuild.ISourcePackageRecipeBuild"/> |
541 | + </class> |
542 | + |
543 | + <securedutility |
544 | + component="lp.soyuz.model.sourcepackagerecipebuild.SourcePackageRecipeBuild" |
545 | + provides="lp.soyuz.interfaces.sourcepackagerecipebuild.ISourcePackageRecipeBuildSource"> |
546 | + <allow interface="lp.soyuz.interfaces.sourcepackagerecipebuild.ISourcePackageRecipeBuildSource"/> |
547 | + </securedutility> |
548 | + |
549 | + <class |
550 | + class="lp.soyuz.model.sourcepackagerecipebuild.SourcePackageRecipeBuildJob"> |
551 | + <allow interface="lp.soyuz.interfaces.sourcepackagerecipebuild.ISourcePackageRecipeBuildJob"/> |
552 | + </class> |
553 | + |
554 | + <securedutility |
555 | + component="lp.soyuz.model.sourcepackagerecipebuild.SourcePackageRecipeBuildJob" |
556 | + provides="lp.soyuz.interfaces.sourcepackagerecipebuild.ISourcePackageRecipeBuildJobSource"> |
557 | + <allow interface="lp.soyuz.interfaces.sourcepackagerecipebuild.ISourcePackageRecipeBuildJobSource"/> |
558 | + </securedutility> |
559 | + |
560 | + <adapter factory="lp.soyuz.model.recipebuilder.RecipeBuildBehavior" |
561 | + permission="zope.Public" /> |
562 | + |
563 | + <!-- SourcePackageRecipe --> |
564 | <class |
565 | class="lp.soyuz.model.sourcepackagerecipe.SourcePackageRecipe"> |
566 | <allow interface="lp.soyuz.interfaces.sourcepackagerecipe.ISourcePackageRecipe"/> |
567 | @@ -953,37 +986,9 @@ |
568 | class="bzrlib.plugins.builder.recipe.NestInstruction"> |
569 | <allow attributes="as_tuple recipe_branch nest_path" /> |
570 | </class> |
571 | - <securedutility |
572 | - component="lp.soyuz.model.sourcepackagerecipe.SourcePackageRecipe" |
573 | - provides="lp.soyuz.interfaces.sourcepackagerecipe.ISourcePackageRecipeSource"> |
574 | - <allow interface="lp.soyuz.interfaces.sourcepackagerecipe.ISourcePackageRecipeSource"/> |
575 | - </securedutility> |
576 | - |
577 | - <class |
578 | - class="lp.soyuz.model.sourcepackagerecipebuild.SourcePackageRecipeBuild"> |
579 | - <allow interface="lp.soyuz.interfaces.sourcepackagerecipebuild.ISourcePackageRecipeBuild"/> |
580 | - </class> |
581 | - |
582 | - <securedutility |
583 | - component="lp.soyuz.model.sourcepackagerecipebuild.SourcePackageRecipeBuild" |
584 | - provides="lp.soyuz.interfaces.sourcepackagerecipebuild.ISourcePackageRecipeBuildSource"> |
585 | - <allow interface="lp.soyuz.interfaces.sourcepackagerecipebuild.ISourcePackageRecipeBuildSource"/> |
586 | - </securedutility> |
587 | - |
588 | - <class |
589 | - class="lp.soyuz.model.sourcepackagerecipebuild.SourcePackageRecipeBuildJob"> |
590 | - <allow interface="lp.soyuz.interfaces.sourcepackagerecipebuild.ISourcePackageRecipeBuildJob"/> |
591 | - </class> |
592 | + |
593 | <utility component="lp.soyuz.model.sourcepackagerecipebuild.SourcePackageRecipeBuildJob" |
594 | name="RECIPEBRANCHBUILD" |
595 | provides="lp.buildmaster.interfaces.buildfarmjob.IBuildFarmJob"/> |
596 | |
597 | - <securedutility |
598 | - component="lp.soyuz.model.sourcepackagerecipebuild.SourcePackageRecipeBuildJob" |
599 | - provides="lp.soyuz.interfaces.sourcepackagerecipebuild.ISourcePackageRecipeBuildJobSource"> |
600 | - <allow interface="lp.soyuz.interfaces.sourcepackagerecipebuild.ISourcePackageRecipeBuildJobSource"/> |
601 | - </securedutility> |
602 | - |
603 | - <adapter factory="lp.soyuz.model.recipebuilder.RecipeBuildBehavior"/> |
604 | - |
605 | </configure> |
606 | |
607 | === modified file 'lib/lp/soyuz/interfaces/sourcepackagerecipebuild.py' |
608 | --- lib/lp/soyuz/interfaces/sourcepackagerecipebuild.py 2010-01-18 09:38:12 +0000 |
609 | +++ lib/lp/soyuz/interfaces/sourcepackagerecipebuild.py 2010-01-29 17:17:19 +0000 |
610 | @@ -49,6 +49,7 @@ |
611 | schema=ISourcePackageRecipe, required=True, |
612 | title=_("The recipe being built.")) |
613 | |
614 | + |
615 | class ISourcePackageRecipeBuildSource(Interface): |
616 | """A utility of this interface be used to create source package builds.""" |
617 | |
618 | |
619 | === modified file 'lib/lp/soyuz/model/build.py' |
620 | --- lib/lp/soyuz/model/build.py 2010-01-20 01:24:01 +0000 |
621 | +++ lib/lp/soyuz/model/build.py 2010-01-29 17:17:19 +0000 |
622 | @@ -11,6 +11,9 @@ |
623 | import datetime |
624 | import logging |
625 | import operator |
626 | +import os |
627 | +import subprocess |
628 | +import time |
629 | |
630 | from zope.interface import implements |
631 | from zope.component import getUtility |
632 | @@ -27,7 +30,8 @@ |
633 | from canonical.database.datetimecol import UtcDateTimeCol |
634 | from canonical.database.enumcol import EnumCol |
635 | from canonical.database.sqlbase import ( |
636 | - cursor, quote_like, SQLBase, sqlvalues) |
637 | + clear_current_connection_cache, flush_database_updates, cursor, |
638 | + quote_like, SQLBase, sqlvalues) |
639 | from canonical.launchpad.components.decoratedresultset import ( |
640 | DecoratedResultSet) |
641 | from canonical.launchpad.database.librarian import ( |
642 | @@ -43,10 +47,12 @@ |
643 | from canonical.launchpad.webapp.interfaces import ( |
644 | IStoreSelector, MAIN_STORE, DEFAULT_FLAVOR) |
645 | from canonical.launchpad.webapp.tales import DurationFormatterAPI |
646 | +from canonical.librarian.utils import copy_and_close |
647 | from lp.archivepublisher.utils import get_ppa_reference |
648 | from lp.buildmaster.interfaces.buildfarmjob import BuildFarmJobType |
649 | from lp.buildmaster.model.buildbase import BuildBase |
650 | -from lp.registry.interfaces.pocket import PackagePublishingPocket |
651 | +from lp.registry.interfaces.pocket import (PackagePublishingPocket, |
652 | + pocketsuffix) |
653 | from lp.services.job.model.job import Job |
654 | from lp.soyuz.adapters.archivedependencies import get_components_for_building |
655 | from lp.soyuz.interfaces.archive import ArchivePurpose |
656 | |
657 | === modified file 'lib/lp/soyuz/model/buildpackagejob.py' |
658 | --- lib/lp/soyuz/model/buildpackagejob.py 2010-01-20 04:14:23 +0000 |
659 | +++ lib/lp/soyuz/model/buildpackagejob.py 2010-01-29 17:17:19 +0000 |
660 | @@ -213,8 +213,8 @@ |
661 | sub_query = """ |
662 | SELECT TRUE FROM Archive, Build, BuildPackageJob, DistroArchSeries |
663 | WHERE |
664 | - BuildPackageJob.job = Job.id AND |
665 | - BuildPackageJob.build = Build.id AND |
666 | + BuildPackageJob.job = Job.id AND |
667 | + BuildPackageJob.build = Build.id AND |
668 | Build.distroarchseries = DistroArchSeries.id AND |
669 | Build.archive = Archive.id AND |
670 | ((Archive.private IS TRUE AND |
671 | |
672 | === modified file 'lib/lp/soyuz/model/recipebuilder.py' |
673 | --- lib/lp/soyuz/model/recipebuilder.py 2010-01-18 09:38:12 +0000 |
674 | +++ lib/lp/soyuz/model/recipebuilder.py 2010-01-29 17:17:19 +0000 |
675 | @@ -68,7 +68,7 @@ |
676 | args["ogrecomponent"] = get_primary_current_component( |
677 | self.build.archive, self.build.distroseries, |
678 | self.build.sourcepackagename.name) |
679 | - args['archives'] = get_sources_list_for_building(self.build, |
680 | + args['archives'] = get_sources_list_for_building(self.build, |
681 | distroarchseries, self.build.sourcepackagename.name) |
682 | return args |
683 | |
684 | @@ -87,7 +87,7 @@ |
685 | |
686 | chroot = distroarchseries.getChroot() |
687 | if chroot is None: |
688 | - raise CannotBuild("Unable to find a chroot for %s" % |
689 | + raise CannotBuild("Unable to find a chroot for %s" % |
690 | distroarchseries.displayname) |
691 | self._builder.slave.cacheFile(logger, chroot) |
692 | |
693 | @@ -131,10 +131,11 @@ |
694 | |
695 | # This should already have been checked earlier, but just check again |
696 | # here in case of programmer errors. |
697 | - reason = check_upload_to_pocket(build.archive, build.distroseries, build.pocket) |
698 | + reason = check_upload_to_pocket( |
699 | + build.archive, build.distroseries, build.pocket) |
700 | assert reason is None, ( |
701 | "%s (%s) can not be built for pocket %s: invalid pocket due " |
702 | - "to the series status of %s." % |
703 | + "to the series status of %s." % |
704 | (build.title, build.id, build.pocket.name, |
705 | build.distroseries.name)) |
706 | |
707 | |
708 | === modified file 'lib/lp/soyuz/model/sourcepackagerecipebuild.py' |
709 | --- lib/lp/soyuz/model/sourcepackagerecipebuild.py 2010-01-20 04:14:23 +0000 |
710 | +++ lib/lp/soyuz/model/sourcepackagerecipebuild.py 2010-01-29 17:17:19 +0000 |
711 | @@ -39,6 +39,8 @@ |
712 | class SourcePackageRecipeBuild(BuildBase, Storm): |
713 | __storm_table__ = 'SourcePackageRecipeBuild' |
714 | |
715 | + policy_name = 'recipe' |
716 | + |
717 | implements(ISourcePackageRecipeBuild) |
718 | classProvides(ISourcePackageRecipeBuildSource) |
719 | |
720 | @@ -87,9 +89,9 @@ |
721 | |
722 | @property |
723 | def pocket(self): |
724 | - # JRV 2010-01-15: The database table really should have a pocket |
725 | - # column, although this is not a big problem at the moment |
726 | - # as recipe builds only happen for PPA's (so far). (bug 507307) |
727 | + # XXX: JRV 2010-01-15 bug=507307: The database table really should |
728 | + # have a pocket column, although this is not a big problem at the |
729 | + # moment as recipe builds only happen for PPA's (so far). |
730 | return PackagePublishingPocket.RELEASE |
731 | |
732 | recipe_id = Int(name='recipe', allow_none=False) |
733 | @@ -129,8 +131,8 @@ |
734 | self.sourcepackagename = sourcepackagename |
735 | |
736 | @classmethod |
737 | - def new( |
738 | - cls, sourcepackage, recipe, requester, archive, date_created=None): |
739 | + def new(cls, sourcepackage, recipe, requester, archive, |
740 | + date_created=None): |
741 | """See `ISourcePackageRecipeBuildSource`.""" |
742 | store = IMasterStore(SourcePackageRecipeBuild) |
743 | if date_created is None: |
744 | |
745 | === modified file 'lib/lp/soyuz/model/sourcepackagerecipedata.py' |
746 | --- lib/lp/soyuz/model/sourcepackagerecipedata.py 2010-01-13 02:59:33 +0000 |
747 | +++ lib/lp/soyuz/model/sourcepackagerecipedata.py 2010-01-29 17:17:19 +0000 |
748 | @@ -127,8 +127,8 @@ |
749 | |
750 | sourcepackage_recipe_build_id = Int( |
751 | name='sourcepackage_recipe_build', allow_none=True) |
752 | - #sourcepackage_recipe_build = Reference( |
753 | - # sourcepackage_recipe_build_id, 'SourcePackageRecipeBuild.id') |
754 | + sourcepackage_recipe_build = Reference( |
755 | + sourcepackage_recipe_build_id, 'SourcePackageRecipeBuild.id') |
756 | |
757 | def getRecipe(self): |
758 | """The BaseRecipeBranch version of the recipe.""" |
759 | |
760 | === modified file 'lib/lp/soyuz/tests/test_recipebuilder.py' |
761 | --- lib/lp/soyuz/tests/test_recipebuilder.py 2010-01-21 04:34:44 +0000 |
762 | +++ lib/lp/soyuz/tests/test_recipebuilder.py 2010-01-29 17:17:19 +0000 |
763 | @@ -16,8 +16,8 @@ |
764 | IBuildFarmJobBehavior) |
765 | from lp.buildmaster.manager import RecordingSlave |
766 | from lp.soyuz.adapters.archivedependencies import get_sources_list_for_building |
767 | +from lp.soyuz.model.processor import ProcessorFamilySet |
768 | from lp.soyuz.model.recipebuilder import RecipeBuildBehavior |
769 | -from lp.soyuz.model.processor import ProcessorFamilySet |
770 | from lp.soyuz.model.sourcepackagerecipebuild import ( |
771 | SourcePackageRecipeBuild) |
772 | from lp.soyuz.tests.soyuzbuilddhelpers import (MockBuilder, |
773 | @@ -48,21 +48,20 @@ |
774 | """Create a sample `ISourcePackageRecipeBuildJob`.""" |
775 | spn = self.factory.makeSourcePackageName("apackage") |
776 | distro = self.factory.makeDistribution(name="distro") |
777 | - distroseries = self.factory.makeDistroSeries(name="mydistro", |
778 | + distroseries = self.factory.makeDistroSeries(name="mydistro", |
779 | distribution=distro) |
780 | - processorfamily = ProcessorFamilySet().getByName('x86') |
781 | - distroarchseries = self.factory.makeDistroArchSeries( |
782 | - distroseries=distroseries, architecturetag='i386', |
783 | - processorfamily=processorfamily) |
784 | + processorfamily = ProcessorFamilySet().getByProcessorName('386') |
785 | + distroseries.newArch( |
786 | + 'i386', processorfamily, True, self.factory.makePerson()) |
787 | sourcepackage = self.factory.makeSourcePackage(spn, distroseries) |
788 | requester = self.factory.makePerson(email="requester@ubuntu.com", |
789 | name="joe", displayname="Joe User") |
790 | - somebranch = self.factory.makeBranch(owner=requester, name="pkg", |
791 | + somebranch = self.factory.makeBranch(owner=requester, name="pkg", |
792 | product=self.factory.makeProduct("someapp")) |
793 | - recipe = self.factory.makeSourcePackageRecipe(requester, requester, |
794 | + recipe = self.factory.makeSourcePackageRecipe(requester, requester, |
795 | distroseries, spn, u"recept", somebranch) |
796 | - spb = self.factory.makeSourcePackageRecipeBuild(sourcepackage=sourcepackage, |
797 | - recipe=recipe, requester=requester) |
798 | + spb = self.factory.makeSourcePackageRecipeBuild( |
799 | + sourcepackage=sourcepackage, recipe=recipe, requester=requester) |
800 | job = spb.makeJob() |
801 | job = IBuildFarmJobBehavior(job) |
802 | return job |
803 | @@ -95,8 +94,7 @@ |
804 | # _extraBuildArgs will return a sane set of additional arguments |
805 | job = self.makeJob() |
806 | distroarchseries = job.build.distroseries.architectures[0] |
807 | - distroname = job.build.archive.distribution.name |
808 | - self.assertEquals({ |
809 | + self.assertEqual({ |
810 | 'author_email': u'requester@ubuntu.com', |
811 | 'suite': u'mydistro', |
812 | 'author_name': u'Joe User', |
813 | @@ -105,7 +103,7 @@ |
814 | 'ogrecomponent': 'universe', |
815 | 'recipe_text': '# bzr-builder format 0.2 deb-version 1.0\n' |
816 | 'lp://dev/~joe/someapp/pkg\n', |
817 | - 'archives': get_sources_list_for_building(job.build, |
818 | + 'archives': get_sources_list_for_building(job.build, |
819 | distroarchseries, job.build.sourcepackagename.name) |
820 | }, job._extraBuildArgs(distroarchseries)) |
821 | |
822 | @@ -132,10 +130,10 @@ |
823 | self.assertEquals(build_args[1], "sourcepackagerecipe") |
824 | self.assertEquals(build_args[3], {}) |
825 | distroarchseries = job.build.distroseries.architectures[0] |
826 | - self.assertEquals(build_args[4], job._extraBuildArgs(distroarchseries)) |
827 | + self.assertEqual(build_args[4], job._extraBuildArgs(distroarchseries)) |
828 | |
829 | def test_dispatchBuildToSlave_nochroot(self): |
830 | - # dispatchBuildToSlave will fail when there is not chroot tarball |
831 | + # dispatchBuildToSlave will fail when there is not chroot tarball |
832 | # available for the distroseries to build for. |
833 | job = self.makeJob() |
834 | builder = MockBuilder("bob-de-bouwer", SaneBuildingSlave()) |
835 | @@ -143,7 +141,7 @@ |
836 | builder.processor = processorfamily.processors[0] |
837 | job.setBuilder(builder) |
838 | logger = BufferLogger() |
839 | - self.assertRaises(CannotBuild, job.dispatchBuildToSlave, |
840 | + self.assertRaises(CannotBuild, job.dispatchBuildToSlave, |
841 | "someid", logger) |
842 | |
843 | def test_getById(self): |
This branch changes the Soyuz uploader to allow uploads from the recipe job.
It has a few stages of work:
1. Tweaks to BuilderBase to be more readily testable and()
- Lots of new getUploaderFoo methods. The one that's actually used externally is getUploaderComm
2. A new upload policy for recipes
3. Changes to the nascentupload process so that it delegates decisions
4. Change the Build and SourcePackageRe cipeBuild objects to specify their upload policy explicitly
5. Change the BuilderBase to use those policies when spawning the upload processor.
6. Change the configs so that policies are not specified in the configs.