10482.1.8
by Tim Penhey
Make review requests a job. |
1 |
# Copyright 2009, 2010 Canonical Ltd. This software is licensed under the
|
8687.15.22
by Karl Fogel
Add the copyright header block to the remaining .py files. |
2 |
# GNU Affero General Public License version 3 (see the file LICENSE).
|
8590.1.2
by Tim Penhey
Break out the jobs from the merge proposal module. |
3 |
|
10427.13.1
by Aaron Bentley
Improve oops messages |
4 |
|
8590.1.2
by Tim Penhey
Break out the jobs from the merge proposal module. |
5 |
"""Job classes related to BranchMergeProposals are in here.
|
6 |
||
7 |
This includes both jobs for the proposals themselves, or jobs that are
|
|
8 |
creating proposals, or diffs relating to the proposals.
|
|
9 |
"""
|
|
10 |
||
10427.13.1
by Aaron Bentley
Improve oops messages |
11 |
|
8590.1.2
by Tim Penhey
Break out the jobs from the merge proposal module. |
12 |
__metaclass__ = type |
10427.13.1
by Aaron Bentley
Improve oops messages |
13 |
|
14 |
||
8590.1.2
by Tim Penhey
Break out the jobs from the merge proposal module. |
15 |
__all__ = [ |
16 |
'BranchMergeProposalJob', |
|
7675.624.75
by Tim Penhey
Logic changed slightly for next_preview_diff_job. |
17 |
'BranchMergeProposalJobFactory', |
7675.624.18
by Tim Penhey
Make one job source for all merge proposal jobs. |
18 |
'BranchMergeProposalJobSource', |
7675.624.75
by Tim Penhey
Logic changed slightly for next_preview_diff_job. |
19 |
'BranchMergeProposalJobType', |
10482.1.2
by Tim Penhey
Add the job type to the enum. |
20 |
'CodeReviewCommentEmailJob', |
8590.1.2
by Tim Penhey
Break out the jobs from the merge proposal module. |
21 |
'CreateMergeProposalJob', |
11486.4.19
by Aaron Bentley
Create GenerateIncrementalDiff jobs missing incremental diffs on tip change. |
22 |
'GenerateIncrementalDiffJob', |
8590.1.2
by Tim Penhey
Break out the jobs from the merge proposal module. |
23 |
'MergeProposalCreatedJob', |
11733.1.1
by Tim Penhey
Rename the MergeProposalCreatedJob to be MergeProposalReviewRequestedEmailJob. |
24 |
'MergeProposalNeedsReviewEmailJob', |
7675.624.18
by Tim Penhey
Make one job source for all merge proposal jobs. |
25 |
'MergeProposalUpdatedEmailJob', |
10482.1.8
by Tim Penhey
Make review requests a job. |
26 |
'ReviewRequestedEmailJob', |
10100.1.25
by Jonathan Lange
Fix the last of them |
27 |
'UpdatePreviewDiffJob', |
8590.1.2
by Tim Penhey
Break out the jobs from the merge proposal module. |
28 |
]
|
29 |
||
9826.11.26
by Aaron Bentley
Provide job running context in a ContextManager. |
30 |
import contextlib |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
31 |
from datetime import ( |
32 |
datetime, |
|
33 |
timedelta, |
|
34 |
)
|
|
10054.23.6
by Aaron Bentley
Fix test name. |
35 |
from email.utils import parseaddr |
8590.1.2
by Tim Penhey
Break out the jobs from the merge proposal module. |
36 |
|
37 |
from lazr.delegates import delegates |
|
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
38 |
from lazr.enum import ( |
39 |
DBEnumeratedType, |
|
40 |
DBItem, |
|
41 |
)
|
|
7675.624.49
by Tim Penhey
Not yet passing, but getting close. |
42 |
import pytz |
8590.1.2
by Tim Penhey
Break out the jobs from the merge proposal module. |
43 |
import simplejson |
44 |
from sqlobject import SQLObjectNotFound |
|
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
45 |
from storm.expr import ( |
46 |
And, |
|
47 |
Desc, |
|
48 |
Or, |
|
49 |
)
|
|
7675.624.18
by Tim Penhey
Make one job source for all merge proposal jobs. |
50 |
from storm.info import ClassAlias |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
51 |
from storm.locals import ( |
52 |
Int, |
|
53 |
Reference, |
|
54 |
Unicode, |
|
55 |
)
|
|
8590.1.2
by Tim Penhey
Break out the jobs from the merge proposal module. |
56 |
from storm.store import Store |
57 |
from zope.component import getUtility |
|
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
58 |
from zope.interface import ( |
59 |
classProvides, |
|
60 |
implements, |
|
61 |
)
|
|
8590.1.2
by Tim Penhey
Break out the jobs from the merge proposal module. |
62 |
|
10482.1.31
by Tim Penhey
Updates while on skype with reviewer. |
63 |
from canonical.config import config |
8590.1.2
by Tim Penhey
Break out the jobs from the merge proposal module. |
64 |
from canonical.database.enumcol import EnumCol |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
65 |
from canonical.launchpad.database.message import ( |
66 |
MessageJob, |
|
67 |
MessageJobAction, |
|
68 |
)
|
|
8590.1.2
by Tim Penhey
Break out the jobs from the merge proposal module. |
69 |
from canonical.launchpad.interfaces.message import IMessageJob |
9826.11.21
by Aaron Bentley
Ensure oopses are handled correctly. |
70 |
from canonical.launchpad.webapp import errorlog |
8590.1.2
by Tim Penhey
Break out the jobs from the merge proposal module. |
71 |
from canonical.launchpad.webapp.interaction import setupInteraction |
72 |
from canonical.launchpad.webapp.interfaces import ( |
|
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
73 |
DEFAULT_FLAVOR, |
74 |
IPlacelessAuthUtility, |
|
75 |
IStoreSelector, |
|
76 |
MAIN_STORE, |
|
77 |
MASTER_FLAVOR, |
|
78 |
)
|
|
8590.1.2
by Tim Penhey
Break out the jobs from the merge proposal module. |
79 |
from lp.code.enums import BranchType |
8590.1.3
by Tim Penhey
Fix the imports and naming. |
80 |
from lp.code.interfaces.branchmergeproposal import ( |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
81 |
IBranchMergeProposalJob, |
82 |
IBranchMergeProposalJobSource, |
|
83 |
ICodeReviewCommentEmailJob, |
|
84 |
ICodeReviewCommentEmailJobSource, |
|
85 |
ICreateMergeProposalJob, |
|
86 |
ICreateMergeProposalJobSource, |
|
11486.4.4
by Aaron Bentley
Fake merge of job removal. |
87 |
IGenerateIncrementalDiffJob, |
88 |
IGenerateIncrementalDiffJobSource, |
|
11733.1.1
by Tim Penhey
Rename the MergeProposalCreatedJob to be MergeProposalReviewRequestedEmailJob. |
89 |
IMergeProposalNeedsReviewEmailJob, |
90 |
IMergeProposalNeedsReviewEmailJobSource, |
|
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
91 |
IMergeProposalUpdatedEmailJob, |
92 |
IMergeProposalUpdatedEmailJobSource, |
|
93 |
IReviewRequestedEmailJob, |
|
94 |
IReviewRequestedEmailJobSource, |
|
95 |
IUpdatePreviewDiffJob, |
|
96 |
IUpdatePreviewDiffJobSource, |
|
9222.1.31
by Aaron Bentley
Add and test script for running preview diff update jobs. |
97 |
)
|
11486.4.15
by Aaron Bentley
Get job tests passing. |
98 |
from lp.code.interfaces.revision import IRevisionSet |
10482.1.8
by Tim Penhey
Make review requests a job. |
99 |
from lp.code.mail.branch import RecipientReason |
8590.1.2
by Tim Penhey
Break out the jobs from the merge proposal module. |
100 |
from lp.code.mail.branchmergeproposal import BMPMailer |
7675.624.3
by Tim Penhey
Make the code review comment email sent by a job. |
101 |
from lp.code.mail.codereviewcomment import CodeReviewCommentMailer |
8590.1.2
by Tim Penhey
Break out the jobs from the merge proposal module. |
102 |
from lp.code.model.branchmergeproposal import BranchMergeProposal |
11486.4.15
by Aaron Bentley
Get job tests passing. |
103 |
from lp.code.model.diff import PreviewDiff |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
104 |
from lp.codehosting.vfs import ( |
105 |
get_ro_server, |
|
106 |
get_rw_server, |
|
107 |
)
|
|
10482.1.8
by Tim Penhey
Make review requests a job. |
108 |
from lp.registry.interfaces.person import IPersonSet |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
109 |
from lp.services.job.interfaces.job import JobStatus |
8590.1.2
by Tim Penhey
Break out the jobs from the merge proposal module. |
110 |
from lp.services.job.model.job import Job |
10137.6.14
by Aaron Bentley
Fix lint errors. |
111 |
from lp.services.job.runner import BaseRunnableJob |
7675.624.51
by Tim Penhey
Test passes now. |
112 |
from lp.services.mail.sendmail import format_address_for_person |
12243.4.3
by j.c.sackett
Moved lp.services.stormbase to lp.services.database.stormbase |
113 |
from lp.services.database.stormbase import StormBase |
8590.1.2
by Tim Penhey
Break out the jobs from the merge proposal module. |
114 |
|
115 |
||
116 |
class BranchMergeProposalJobType(DBEnumeratedType): |
|
117 |
"""Values that ICodeImportJob.state can take."""
|
|
118 |
||
11733.1.2
by Tim Penhey
Update the job type enum to make more sense. |
119 |
MERGE_PROPOSAL_NEEDS_REVIEW = DBItem(0, """ |
120 |
Merge proposal needs review
|
|
8590.1.2
by Tim Penhey
Break out the jobs from the merge proposal module. |
121 |
|
11733.1.2
by Tim Penhey
Update the job type enum to make more sense. |
122 |
This job sends mail to all interested parties about the proposal.
|
8590.1.2
by Tim Penhey
Break out the jobs from the merge proposal module. |
123 |
""") |
124 |
||
9222.1.24
by Aaron Bentley
Implement UpdatePreviewDiffJob |
125 |
UPDATE_PREVIEW_DIFF = DBItem(1, """ |
126 |
Update the preview diff for the BranchMergeProposal.
|
|
127 |
||
128 |
This job generates the preview diff for a BranchMergeProposal.
|
|
129 |
""") |
|
130 |
||
10482.1.2
by Tim Penhey
Add the job type to the enum. |
131 |
CODE_REVIEW_COMMENT_EMAIL = DBItem(2, """ |
132 |
Send the code review comment to the subscribers.
|
|
10482.1.3
by Tim Penhey
Test the running of the job and creation on commenting. |
133 |
|
134 |
This job sends the email to the merge proposal subscribers and
|
|
135 |
reviewers.
|
|
10482.1.2
by Tim Penhey
Add the job type to the enum. |
136 |
""") |
137 |
||
10482.1.8
by Tim Penhey
Make review requests a job. |
138 |
REVIEW_REQUEST_EMAIL = DBItem(3, """ |
139 |
Send the review request email to the requested reviewer.
|
|
140 |
||
141 |
This job sends an email to the requested reviewer, or members of the
|
|
142 |
requested reviewer team asking them to review the proposal.
|
|
143 |
""") |
|
144 |
||
10482.1.14
by Tim Penhey
Start the job process. |
145 |
MERGE_PROPOSAL_UPDATED = DBItem(4, """ |
146 |
Merge proposal updated
|
|
147 |
||
148 |
This job sends an email to the subscribers informing them of fields
|
|
149 |
that have been changed on the merge proposal itself.
|
|
150 |
""") |
|
151 |
||
11486.4.4
by Aaron Bentley
Fake merge of job removal. |
152 |
GENERATE_INCREMENTAL_DIFF = DBItem(5, """ |
153 |
Generate incremental diff
|
|
154 |
||
155 |
This job generates an incremental diff for a merge proposal.""") |
|
156 |
||
8590.1.2
by Tim Penhey
Break out the jobs from the merge proposal module. |
157 |
|
12243.4.2
by j.c.sackett
Updated all uses of storm.base.Storm with lp.services.stormbase.StormBase |
158 |
class BranchMergeProposalJob(StormBase): |
8590.1.2
by Tim Penhey
Break out the jobs from the merge proposal module. |
159 |
"""Base class for jobs related to branch merge proposals."""
|
160 |
||
161 |
implements(IBranchMergeProposalJob) |
|
162 |
||
163 |
__storm_table__ = 'BranchMergeProposalJob' |
|
164 |
||
165 |
id = Int(primary=True) |
|
166 |
||
167 |
jobID = Int('job') |
|
168 |
job = Reference(jobID, Job.id) |
|
169 |
||
170 |
branch_merge_proposalID = Int('branch_merge_proposal', allow_none=False) |
|
171 |
branch_merge_proposal = Reference( |
|
172 |
branch_merge_proposalID, BranchMergeProposal.id) |
|
173 |
||
174 |
job_type = EnumCol(enum=BranchMergeProposalJobType, notNull=True) |
|
175 |
||
176 |
_json_data = Unicode('json_data') |
|
177 |
||
178 |
@property
|
|
179 |
def metadata(self): |
|
180 |
return simplejson.loads(self._json_data) |
|
181 |
||
182 |
def __init__(self, branch_merge_proposal, job_type, metadata): |
|
183 |
"""Constructor.
|
|
184 |
||
185 |
:param branch_merge_proposal: The proposal this job relates to.
|
|
186 |
:param job_type: The BranchMergeProposalJobType of this job.
|
|
187 |
:param metadata: The type-specific variables, as a JSON-compatible
|
|
188 |
dict.
|
|
189 |
"""
|
|
12243.4.5
by j.c.sackett
Improved subclassing on branchmergeproposaljob. |
190 |
super(BranchMergeProposalJob, self).__init__() |
8590.1.2
by Tim Penhey
Break out the jobs from the merge proposal module. |
191 |
json_data = simplejson.dumps(metadata) |
192 |
self.job = Job() |
|
193 |
self.branch_merge_proposal = branch_merge_proposal |
|
194 |
self.job_type = job_type |
|
195 |
# XXX AaronBentley 2009-01-29 bug=322819: This should be a bytestring,
|
|
196 |
# but the DB representation is unicode.
|
|
197 |
self._json_data = json_data.decode('utf-8') |
|
198 |
||
199 |
def sync(self): |
|
200 |
store = Store.of(self) |
|
201 |
store.flush() |
|
202 |
store.autoreload(self) |
|
203 |
||
204 |
def destroySelf(self): |
|
205 |
Store.of(self).remove(self) |
|
206 |
||
207 |
@classmethod
|
|
208 |
def selectBy(klass, **kwargs): |
|
209 |
"""Return selected instances of this class.
|
|
210 |
||
211 |
At least one pair of keyword arguments must be supplied.
|
|
212 |
foo=bar is interpreted as 'select all instances of
|
|
213 |
BranchMergeProposalJob whose property "foo" is equal to "bar"'.
|
|
214 |
"""
|
|
215 |
assert len(kwargs) > 0 |
|
216 |
store = getUtility(IStoreSelector).get(MAIN_STORE, DEFAULT_FLAVOR) |
|
217 |
return store.find(klass, **kwargs) |
|
218 |
||
219 |
@classmethod
|
|
220 |
def get(klass, key): |
|
221 |
"""Return the instance of this class whose key is supplied.
|
|
222 |
||
223 |
:raises: SQLObjectNotFound
|
|
224 |
"""
|
|
225 |
store = getUtility(IStoreSelector).get(MAIN_STORE, DEFAULT_FLAVOR) |
|
226 |
instance = store.get(klass, key) |
|
227 |
if instance is None: |
|
228 |
raise SQLObjectNotFound( |
|
229 |
'No occurrence of %s has key %s' % (klass.__name__, key)) |
|
230 |
return instance |
|
231 |
||
232 |
||
8963.10.6
by Aaron Bentley
Refactor job running in terms of IRunnableJob. |
233 |
class BranchMergeProposalJobDerived(BaseRunnableJob): |
8590.1.2
by Tim Penhey
Break out the jobs from the merge proposal module. |
234 |
|
235 |
"""Intermediate class for deriving from BranchMergeProposalJob."""
|
|
236 |
delegates(IBranchMergeProposalJob) |
|
237 |
||
238 |
def __init__(self, job): |
|
239 |
self.context = job |
|
240 |
||
7675.624.52
by Tim Penhey
Lots of logging and a better producer. |
241 |
def __repr__(self): |
242 |
bmp = self.branch_merge_proposal |
|
243 |
return '<%(job_type)s job for merge %(merge_id)s on %(branch)s>' % { |
|
244 |
'job_type': self.context.job_type.name, |
|
245 |
'merge_id': bmp.id, |
|
246 |
'branch': bmp.source_branch.unique_name, |
|
247 |
}
|
|
248 |
||
8590.1.2
by Tim Penhey
Break out the jobs from the merge proposal module. |
249 |
@classmethod
|
9222.1.44
by Aaron Bentley
Updates from review. |
250 |
def create(cls, bmp): |
9222.1.24
by Aaron Bentley
Implement UpdatePreviewDiffJob |
251 |
"""See `IMergeProposalCreationJob`."""
|
252 |
job = BranchMergeProposalJob( |
|
9222.1.44
by Aaron Bentley
Updates from review. |
253 |
bmp, cls.class_job_type, {}) |
254 |
return cls(job) |
|
9222.1.24
by Aaron Bentley
Implement UpdatePreviewDiffJob |
255 |
|
256 |
@classmethod
|
|
9826.11.15
by Aaron Bentley
Start trying to use the ampoule process pool. |
257 |
def get(cls, job_id): |
9963.7.7
by Aaron Bentley
cleanup. |
258 |
"""Get a job by id.
|
259 |
||
260 |
:return: the BranchMergeProposalJob with the specified id, as the
|
|
261 |
current BranchMergeProposalJobDereived subclass.
|
|
262 |
:raises: SQLObjectNotFound if there is no job with the specified id,
|
|
263 |
or its job_type does not match the desired subclass.
|
|
264 |
"""
|
|
9826.11.15
by Aaron Bentley
Start trying to use the ampoule process pool. |
265 |
job = BranchMergeProposalJob.get(job_id) |
9963.7.2
by Aaron Bentley
Allow BranchMergeProposal jobs to be retrieved by their id. |
266 |
if job.job_type != cls.class_job_type: |
267 |
raise SQLObjectNotFound( |
|
268 |
'No object found with id %d and type %s' % (job_id, |
|
269 |
cls.class_job_type.title)) |
|
9826.11.15
by Aaron Bentley
Start trying to use the ampoule process pool. |
270 |
return cls(job) |
271 |
||
272 |
@classmethod
|
|
8590.1.2
by Tim Penhey
Break out the jobs from the merge proposal module. |
273 |
def iterReady(klass): |
274 |
"""Iterate through all ready BranchMergeProposalJobs."""
|
|
275 |
from lp.code.model.branch import Branch |
|
276 |
store = getUtility(IStoreSelector).get(MAIN_STORE, MASTER_FLAVOR) |
|
277 |
jobs = store.find( |
|
278 |
(BranchMergeProposalJob), |
|
279 |
And(BranchMergeProposalJob.job_type == klass.class_job_type, |
|
280 |
BranchMergeProposalJob.job == Job.id, |
|
281 |
Job.id.is_in(Job.ready_jobs), |
|
9826.2.1
by Michael Hudson
test and fix |
282 |
BranchMergeProposalJob.branch_merge_proposal |
283 |
== BranchMergeProposal.id, |
|
8590.1.2
by Tim Penhey
Break out the jobs from the merge proposal module. |
284 |
BranchMergeProposal.source_branch == Branch.id, |
285 |
# A proposal isn't considered ready if it has no revisions,
|
|
286 |
# or if it is hosted but pending a mirror.
|
|
287 |
Branch.revision_count > 0, |
|
288 |
Or(Branch.next_mirror_time == None, |
|
12243.4.9
by j.c.sackett
Lint fixes. |
289 |
Branch.branch_type != BranchType.HOSTED))) |
8590.1.2
by Tim Penhey
Break out the jobs from the merge proposal module. |
290 |
return (klass(job) for job in jobs) |
291 |
||
9314.1.1
by Aaron Bentley
Add oops var handling to the Job infrastructure |
292 |
def getOopsVars(self): |
9314.2.3
by Aaron Bentley
Update documentation |
293 |
"""See `IRunnableJob`."""
|
11486.4.13
by Aaron Bentley
Lint fixes. |
294 |
vars = BaseRunnableJob.getOopsVars(self) |
9314.1.1
by Aaron Bentley
Add oops var handling to the Job infrastructure |
295 |
bmp = self.context.branch_merge_proposal |
296 |
vars.extend([ |
|
297 |
('branchmergeproposal_job_id', self.context.id), |
|
298 |
('branchmergeproposal_job_type', self.context.job_type.title), |
|
299 |
('source_branch', bmp.source_branch.unique_name), |
|
300 |
('target_branch', bmp.target_branch.unique_name)]) |
|
301 |
return vars |
|
8590.1.2
by Tim Penhey
Break out the jobs from the merge proposal module. |
302 |
|
7675.624.3
by Tim Penhey
Make the code review comment email sent by a job. |
303 |
|
11733.1.1
by Tim Penhey
Rename the MergeProposalCreatedJob to be MergeProposalReviewRequestedEmailJob. |
304 |
class MergeProposalNeedsReviewEmailJob(BranchMergeProposalJobDerived): |
305 |
"""See `IMergeProposalNeedsReviewEmailJob`."""
|
|
306 |
||
307 |
implements(IMergeProposalNeedsReviewEmailJob) |
|
308 |
||
309 |
classProvides(IMergeProposalNeedsReviewEmailJobSource) |
|
10482.1.7
by Tim Penhey
Update the branch merge proposal job source interfaces to inherit from IJobSource. |
310 |
|
11733.1.2
by Tim Penhey
Update the job type enum to make more sense. |
311 |
class_job_type = BranchMergeProposalJobType.MERGE_PROPOSAL_NEEDS_REVIEW |
8590.1.2
by Tim Penhey
Break out the jobs from the merge proposal module. |
312 |
|
7675.624.21
by Tim Penhey
The merge proposal created job no longer generates the diff. |
313 |
def run(self): |
11733.1.1
by Tim Penhey
Rename the MergeProposalCreatedJob to be MergeProposalReviewRequestedEmailJob. |
314 |
"""See `IMergeProposalNeedsReviewEmailJob`."""
|
8590.1.2
by Tim Penhey
Break out the jobs from the merge proposal module. |
315 |
mailer = BMPMailer.forCreation( |
316 |
self.branch_merge_proposal, self.branch_merge_proposal.registrant) |
|
317 |
mailer.sendAll() |
|
318 |
||
8963.10.3
by Aaron Bentley
Provide notifications for BranchMergeProposal jobs. |
319 |
def getOopsRecipients(self): |
320 |
return [self.branch_merge_proposal.registrant.preferredemail.email] |
|
321 |
||
322 |
def getOperationDescription(self): |
|
323 |
return ('notifying people about the proposal to merge %s into %s' % |
|
324 |
(self.branch_merge_proposal.source_branch.bzr_identity, |
|
325 |
self.branch_merge_proposal.target_branch.bzr_identity)) |
|
326 |
||
327 |
||
7675.624.49
by Tim Penhey
Not yet passing, but getting close. |
328 |
class UpdatePreviewDiffNotReady(Exception): |
329 |
"""Raised if the the preview diff is not ready to run."""
|
|
330 |
||
331 |
||
9222.1.24
by Aaron Bentley
Implement UpdatePreviewDiffJob |
332 |
class UpdatePreviewDiffJob(BranchMergeProposalJobDerived): |
9222.1.44
by Aaron Bentley
Updates from review. |
333 |
"""A job to update the preview diff for a branch merge proposal.
|
334 |
||
335 |
Provides class methods to create and retrieve such jobs.
|
|
336 |
"""
|
|
9222.1.24
by Aaron Bentley
Implement UpdatePreviewDiffJob |
337 |
|
7675.624.49
by Tim Penhey
Not yet passing, but getting close. |
338 |
implements(IUpdatePreviewDiffJob) |
9222.1.29
by Aaron Bentley
Switch test to JobRunner. |
339 |
|
9222.1.31
by Aaron Bentley
Add and test script for running preview diff update jobs. |
340 |
classProvides(IUpdatePreviewDiffJobSource) |
341 |
||
9222.1.24
by Aaron Bentley
Implement UpdatePreviewDiffJob |
342 |
class_job_type = BranchMergeProposalJobType.UPDATE_PREVIEW_DIFF |
343 |
||
7675.624.51
by Tim Penhey
Test passes now. |
344 |
user_error_types = (UpdatePreviewDiffNotReady, ) |
345 |
||
346 |
def checkReady(self): |
|
7675.624.49
by Tim Penhey
Not yet passing, but getting close. |
347 |
"""Is this job ready to run?"""
|
348 |
bmp = self.branch_merge_proposal |
|
349 |
if bmp.source_branch.last_scanned_id is None: |
|
350 |
raise UpdatePreviewDiffNotReady( |
|
351 |
'The source branch has no revisions.') |
|
352 |
if bmp.target_branch.last_scanned_id is None: |
|
353 |
raise UpdatePreviewDiffNotReady( |
|
354 |
'The target branch has no revisions.') |
|
355 |
if bmp.source_branch.pending_writes: |
|
356 |
raise UpdatePreviewDiffNotReady( |
|
357 |
'The source branch has pending writes.') |
|
358 |
||
9826.11.20
by Aaron Bentley
Avoid repeating setup and teardown. |
359 |
@staticmethod
|
9826.11.26
by Aaron Bentley
Provide job running context in a ContextManager. |
360 |
@contextlib.contextmanager |
361 |
def contextManager(): |
|
9826.13.9
by Aaron Bentley
Update for review. |
362 |
"""See `IUpdatePreviewDiffJobSource`."""
|
9826.11.21
by Aaron Bentley
Ensure oopses are handled correctly. |
363 |
errorlog.globalErrorUtility.configure('update_preview_diffs') |
9590.1.112
by Michael Hudson
server fixes, fixes the scanner script tests |
364 |
server = get_ro_server() |
10197.5.13
by Michael Hudson
misc. fixes |
365 |
server.start_server() |
9826.11.26
by Aaron Bentley
Provide job running context in a ContextManager. |
366 |
yield
|
10197.5.13
by Michael Hudson
misc. fixes |
367 |
server.stop_server() |
9826.11.20
by Aaron Bentley
Avoid repeating setup and teardown. |
368 |
|
7675.580.1
by Aaron Bentley
Increase the timeout for UpdatePreviewDiff jobs to 10 minutes. |
369 |
def acquireLease(self, duration=600): |
370 |
return self.job.acquireLease(duration) |
|
371 |
||
9222.1.24
by Aaron Bentley
Implement UpdatePreviewDiffJob |
372 |
def run(self): |
10482.1.5
by Tim Penhey
Updates from code review comments. |
373 |
"""See `IRunnableJob`."""
|
7675.624.51
by Tim Penhey
Test passes now. |
374 |
self.checkReady() |
9222.1.24
by Aaron Bentley
Implement UpdatePreviewDiffJob |
375 |
preview = PreviewDiff.fromBranchMergeProposal( |
376 |
self.branch_merge_proposal) |
|
377 |
self.branch_merge_proposal.preview_diff = preview |
|
378 |
||
7675.624.51
by Tim Penhey
Test passes now. |
379 |
def getOperationDescription(self): |
380 |
return ('generating the diff for a merge proposal') |
|
381 |
||
382 |
def getErrorRecipients(self): |
|
383 |
"""Return a list of email-ids to notify about user errors."""
|
|
384 |
registrant = self.branch_merge_proposal.registrant |
|
385 |
return format_address_for_person(registrant) |
|
386 |
||
9222.1.24
by Aaron Bentley
Implement UpdatePreviewDiffJob |
387 |
|
8963.10.6
by Aaron Bentley
Refactor job running in terms of IRunnableJob. |
388 |
class CreateMergeProposalJob(BaseRunnableJob): |
8590.1.2
by Tim Penhey
Break out the jobs from the merge proposal module. |
389 |
"""See `ICreateMergeProposalJob` and `ICreateMergeProposalJobSource`."""
|
390 |
||
391 |
classProvides(ICreateMergeProposalJobSource) |
|
392 |
||
393 |
delegates(IMessageJob) |
|
394 |
||
395 |
class_action = MessageJobAction.CREATE_MERGE_PROPOSAL |
|
396 |
||
397 |
implements(ICreateMergeProposalJob) |
|
398 |
||
399 |
def __init__(self, context): |
|
400 |
"""Create an instance of CreateMergeProposalJob.
|
|
401 |
||
402 |
:param context: a MessageJob.
|
|
403 |
"""
|
|
404 |
self.context = context |
|
405 |
||
406 |
def __eq__(self, other): |
|
407 |
return (self.__class__ == other.__class__ and |
|
408 |
self.context == other.context) |
|
409 |
||
410 |
@classmethod
|
|
411 |
def create(klass, message_bytes): |
|
412 |
"""See `ICreateMergeProposalJobSource`."""
|
|
413 |
context = MessageJob( |
|
414 |
message_bytes, MessageJobAction.CREATE_MERGE_PROPOSAL) |
|
415 |
return klass(context) |
|
416 |
||
417 |
@classmethod
|
|
418 |
def iterReady(klass): |
|
419 |
"""Iterate through all ready BranchMergeProposalJobs."""
|
|
420 |
store = getUtility(IStoreSelector).get(MAIN_STORE, MASTER_FLAVOR) |
|
421 |
jobs = store.find( |
|
422 |
(MessageJob), |
|
423 |
And(MessageJob.action == klass.class_action, |
|
424 |
MessageJob.job == Job.id, |
|
425 |
Job.id.is_in(Job.ready_jobs))) |
|
426 |
return (klass(job) for job in jobs) |
|
427 |
||
428 |
def run(self): |
|
429 |
"""See `ICreateMergeProposalJob`."""
|
|
430 |
# Avoid circular import
|
|
431 |
from lp.code.mail.codehandler import CodeHandler |
|
10427.13.1
by Aaron Bentley
Improve oops messages |
432 |
url = self.context.message_bytes.getURL() |
433 |
with errorlog.globalErrorUtility.oopsMessage('Mail url: %r' % url): |
|
434 |
message = self.getMessage() |
|
435 |
# Since the message was checked as signed before it was saved in
|
|
436 |
# the Librarian, just create the principal from the sender and set
|
|
437 |
# up the interaction.
|
|
438 |
name, email_addr = parseaddr(message['From']) |
|
439 |
authutil = getUtility(IPlacelessAuthUtility) |
|
440 |
principal = authutil.getPrincipalByLogin(email_addr) |
|
441 |
if principal is None: |
|
442 |
raise AssertionError('No principal found for %s' % email_addr) |
|
443 |
setupInteraction(principal, email_addr) |
|
8590.1.2
by Tim Penhey
Break out the jobs from the merge proposal module. |
444 |
|
9590.1.112
by Michael Hudson
server fixes, fixes the scanner script tests |
445 |
server = get_rw_server() |
10427.13.1
by Aaron Bentley
Improve oops messages |
446 |
server.start_server() |
447 |
try: |
|
448 |
return CodeHandler().processMergeProposal(message) |
|
449 |
finally: |
|
450 |
server.stop_server() |
|
8963.10.3
by Aaron Bentley
Provide notifications for BranchMergeProposal jobs. |
451 |
|
452 |
def getOopsRecipients(self): |
|
453 |
message = self.getMessage() |
|
8963.10.10
by Aaron Bentley
Fix test failures, do more interface inheritance. |
454 |
from_ = message['From'] |
455 |
if from_ is None: |
|
456 |
return [] |
|
457 |
return [from_] |
|
8963.10.3
by Aaron Bentley
Provide notifications for BranchMergeProposal jobs. |
458 |
|
459 |
def getOperationDescription(self): |
|
460 |
message = self.getMessage() |
|
461 |
return ('creating a merge proposal from message with subject %s' % |
|
462 |
message['Subject']) |
|
7675.624.3
by Tim Penhey
Make the code review comment email sent by a job. |
463 |
|
464 |
||
465 |
class CodeReviewCommentEmailJob(BranchMergeProposalJobDerived): |
|
466 |
"""A job to send a code review comment.
|
|
467 |
||
468 |
Provides class methods to create and retrieve such jobs.
|
|
469 |
"""
|
|
470 |
||
471 |
implements(ICodeReviewCommentEmailJob) |
|
10482.1.5
by Tim Penhey
Updates from code review comments. |
472 |
|
7675.624.3
by Tim Penhey
Make the code review comment email sent by a job. |
473 |
classProvides(ICodeReviewCommentEmailJobSource) |
474 |
||
475 |
class_job_type = BranchMergeProposalJobType.CODE_REVIEW_COMMENT_EMAIL |
|
476 |
||
477 |
def run(self): |
|
10482.1.5
by Tim Penhey
Updates from code review comments. |
478 |
"""See `IRunnableJob`."""
|
479 |
mailer = CodeReviewCommentMailer.forCreation(self.code_review_comment) |
|
7675.624.3
by Tim Penhey
Make the code review comment email sent by a job. |
480 |
mailer.sendAll() |
481 |
||
482 |
@classmethod
|
|
483 |
def create(cls, code_review_comment): |
|
10482.1.5
by Tim Penhey
Updates from code review comments. |
484 |
"""See `ICodeReviewCommentEmailJobSource`."""
|
7675.624.3
by Tim Penhey
Make the code review comment email sent by a job. |
485 |
metadata = cls.getMetadata(code_review_comment) |
486 |
bmp = code_review_comment.branch_merge_proposal |
|
487 |
job = BranchMergeProposalJob(bmp, cls.class_job_type, metadata) |
|
488 |
return cls(job) |
|
489 |
||
490 |
@staticmethod
|
|
491 |
def getMetadata(code_review_comment): |
|
492 |
return {'code_review_comment': code_review_comment.id} |
|
493 |
||
10482.1.5
by Tim Penhey
Updates from code review comments. |
494 |
@property
|
7675.624.3
by Tim Penhey
Make the code review comment email sent by a job. |
495 |
def code_review_comment(self): |
10482.1.5
by Tim Penhey
Updates from code review comments. |
496 |
"""Get the code review comment."""
|
10482.1.3
by Tim Penhey
Test the running of the job and creation on commenting. |
497 |
return self.branch_merge_proposal.getComment( |
498 |
self.metadata['code_review_comment']) |
|
10482.1.1
by Tim Penhey
Make the code review comment email sent by a job. |
499 |
|
10482.1.7
by Tim Penhey
Update the branch merge proposal job source interfaces to inherit from IJobSource. |
500 |
def getOopsVars(self): |
501 |
"""See `IRunnableJob`."""
|
|
11486.4.13
by Aaron Bentley
Lint fixes. |
502 |
vars = BranchMergeProposalJobDerived.getOopsVars(self) |
10482.1.7
by Tim Penhey
Update the branch merge proposal job source interfaces to inherit from IJobSource. |
503 |
vars.extend([ |
504 |
('code_review_comment', self.metadata['code_review_comment']), |
|
505 |
])
|
|
506 |
return vars |
|
507 |
||
508 |
def getErrorRecipients(self): |
|
509 |
"""Return a list of email-ids to notify about user errors."""
|
|
510 |
commenter = self.code_review_comment.message.owner |
|
10482.1.22
by Tim Penhey
Format the email address for the error recipients properly. |
511 |
return [format_address_for_person(commenter)] |
10482.1.8
by Tim Penhey
Make review requests a job. |
512 |
|
7675.659.1
by Tim Penhey
Test and add more operation descriptions. |
513 |
def getOperationDescription(self): |
514 |
return 'emailing a code review comment' |
|
515 |
||
10482.1.8
by Tim Penhey
Make review requests a job. |
516 |
|
517 |
class ReviewRequestedEmailJob(BranchMergeProposalJobDerived): |
|
518 |
"""Send email to the reviewer telling them to review the proposal.
|
|
519 |
||
520 |
Provides class methods to create and retrieve such jobs.
|
|
521 |
"""
|
|
522 |
||
523 |
implements(IReviewRequestedEmailJob) |
|
524 |
||
525 |
classProvides(IReviewRequestedEmailJobSource) |
|
526 |
||
527 |
class_job_type = BranchMergeProposalJobType.REVIEW_REQUEST_EMAIL |
|
528 |
||
529 |
def run(self): |
|
530 |
"""See `IRunnableJob`."""
|
|
531 |
reason = RecipientReason.forReviewer( |
|
532 |
self.branch_merge_proposal, True, self.reviewer) |
|
533 |
mailer = BMPMailer.forReviewRequest( |
|
534 |
reason, self.branch_merge_proposal, self.requester) |
|
535 |
mailer.sendAll() |
|
536 |
||
537 |
@classmethod
|
|
538 |
def create(cls, review_request): |
|
539 |
"""See `IReviewRequestedEmailJobSource`."""
|
|
540 |
metadata = cls.getMetadata(review_request) |
|
541 |
bmp = review_request.branch_merge_proposal |
|
542 |
job = BranchMergeProposalJob(bmp, cls.class_job_type, metadata) |
|
543 |
return cls(job) |
|
544 |
||
545 |
@staticmethod
|
|
546 |
def getMetadata(review_request): |
|
547 |
return { |
|
548 |
'reviewer': review_request.reviewer.name, |
|
549 |
'requester': review_request.registrant.name, |
|
550 |
}
|
|
551 |
||
552 |
@property
|
|
553 |
def reviewer(self): |
|
554 |
"""The person or team who has been asked to review."""
|
|
555 |
return getUtility(IPersonSet).getByName(self.metadata['reviewer']) |
|
556 |
||
557 |
@property
|
|
558 |
def requester(self): |
|
559 |
"""The person who requested the review to be done."""
|
|
560 |
return getUtility(IPersonSet).getByName(self.metadata['requester']) |
|
561 |
||
562 |
def getOopsVars(self): |
|
563 |
"""See `IRunnableJob`."""
|
|
11486.4.13
by Aaron Bentley
Lint fixes. |
564 |
vars = BranchMergeProposalJobDerived.getOopsVars(self) |
10482.1.8
by Tim Penhey
Make review requests a job. |
565 |
vars.extend([ |
566 |
('reviewer', self.metadata['reviewer']), |
|
567 |
('requester', self.metadata['requester']), |
|
568 |
])
|
|
569 |
return vars |
|
570 |
||
571 |
def getErrorRecipients(self): |
|
572 |
"""Return a list of email-ids to notify about user errors."""
|
|
573 |
recipients = [] |
|
574 |
if self.requester is not None: |
|
7675.624.51
by Tim Penhey
Test passes now. |
575 |
recipients.append(format_address_for_person(self.requester)) |
10482.1.8
by Tim Penhey
Make review requests a job. |
576 |
return recipients |
10482.1.14
by Tim Penhey
Start the job process. |
577 |
|
7675.659.1
by Tim Penhey
Test and add more operation descriptions. |
578 |
def getOperationDescription(self): |
579 |
return 'emailing a reviewer requesting a review' |
|
580 |
||
10482.1.14
by Tim Penhey
Start the job process. |
581 |
|
10482.1.16
by Tim Penhey
Register the global utilities. |
582 |
class MergeProposalUpdatedEmailJob(BranchMergeProposalJobDerived): |
10482.1.14
by Tim Penhey
Start the job process. |
583 |
"""Send email to the subscribers informing them of updated fields.
|
584 |
||
585 |
When attributes of the merge proposal are edited, we inform the
|
|
586 |
subscribers.
|
|
587 |
"""
|
|
588 |
||
10482.1.16
by Tim Penhey
Register the global utilities. |
589 |
implements(IMergeProposalUpdatedEmailJob) |
10482.1.14
by Tim Penhey
Start the job process. |
590 |
|
10482.1.16
by Tim Penhey
Register the global utilities. |
591 |
classProvides(IMergeProposalUpdatedEmailJobSource) |
10482.1.14
by Tim Penhey
Start the job process. |
592 |
|
593 |
class_job_type = BranchMergeProposalJobType.MERGE_PROPOSAL_UPDATED |
|
594 |
||
595 |
def run(self): |
|
596 |
"""See `IRunnableJob`."""
|
|
10482.1.18
by Tim Penhey
Emails describing merge proposal updates now jobified. |
597 |
mailer = BMPMailer.forModification( |
598 |
self.branch_merge_proposal, self.delta_text, self.editor) |
|
599 |
mailer.sendAll() |
|
10482.1.14
by Tim Penhey
Start the job process. |
600 |
|
601 |
@classmethod
|
|
10482.1.18
by Tim Penhey
Emails describing merge proposal updates now jobified. |
602 |
def create(cls, merge_proposal, delta_text, editor): |
10482.1.14
by Tim Penhey
Start the job process. |
603 |
"""See `IReviewRequestedEmailJobSource`."""
|
10482.1.18
by Tim Penhey
Emails describing merge proposal updates now jobified. |
604 |
metadata = cls.getMetadata(delta_text, editor) |
605 |
job = BranchMergeProposalJob( |
|
606 |
merge_proposal, cls.class_job_type, metadata) |
|
10482.1.14
by Tim Penhey
Start the job process. |
607 |
return cls(job) |
608 |
||
609 |
@staticmethod
|
|
10482.1.18
by Tim Penhey
Emails describing merge proposal updates now jobified. |
610 |
def getMetadata(delta_text, editor): |
611 |
metadata = {'delta_text': delta_text} |
|
612 |
if editor is not None: |
|
11486.4.13
by Aaron Bentley
Lint fixes. |
613 |
metadata['editor'] = editor.name |
10482.1.18
by Tim Penhey
Emails describing merge proposal updates now jobified. |
614 |
return metadata |
615 |
||
616 |
@property
|
|
617 |
def editor(self): |
|
618 |
"""The person who updated the merge proposal."""
|
|
619 |
editor_name = self.metadata.get('editor') |
|
620 |
if editor_name is None: |
|
621 |
return None |
|
622 |
else: |
|
623 |
return getUtility(IPersonSet).getByName(editor_name) |
|
624 |
||
625 |
@property
|
|
626 |
def delta_text(self): |
|
627 |
"""The changes that were made to the merge proposal."""
|
|
628 |
return self.metadata['delta_text'] |
|
10482.1.14
by Tim Penhey
Start the job process. |
629 |
|
630 |
def getOopsVars(self): |
|
631 |
"""See `IRunnableJob`."""
|
|
11486.4.13
by Aaron Bentley
Lint fixes. |
632 |
vars = BranchMergeProposalJobDerived.getOopsVars(self) |
10482.1.14
by Tim Penhey
Start the job process. |
633 |
vars.extend([ |
10482.1.18
by Tim Penhey
Emails describing merge proposal updates now jobified. |
634 |
('editor', self.metadata.get('editor', '(not set)')), |
635 |
('delta_text', self.metadata['delta_text']), |
|
10482.1.14
by Tim Penhey
Start the job process. |
636 |
])
|
637 |
return vars |
|
638 |
||
639 |
def getErrorRecipients(self): |
|
640 |
"""Return a list of email-ids to notify about user errors."""
|
|
641 |
recipients = [] |
|
10482.1.18
by Tim Penhey
Emails describing merge proposal updates now jobified. |
642 |
if self.editor is not None: |
7675.624.51
by Tim Penhey
Test passes now. |
643 |
recipients.append(format_address_for_person(self.editor)) |
10482.1.14
by Tim Penhey
Start the job process. |
644 |
return recipients |
7675.624.18
by Tim Penhey
Make one job source for all merge proposal jobs. |
645 |
|
7675.659.1
by Tim Penhey
Test and add more operation descriptions. |
646 |
def getOperationDescription(self): |
647 |
return 'emailing subscribers about merge proposal changes' |
|
648 |
||
7675.624.18
by Tim Penhey
Make one job source for all merge proposal jobs. |
649 |
|
11486.4.4
by Aaron Bentley
Fake merge of job removal. |
650 |
class GenerateIncrementalDiffJob(BranchMergeProposalJobDerived): |
651 |
"""A job to generate an incremental diff for a branch merge proposal.
|
|
652 |
||
653 |
Provides class methods to create and retrieve such jobs.
|
|
654 |
"""
|
|
655 |
||
656 |
implements(IGenerateIncrementalDiffJob) |
|
657 |
||
658 |
classProvides(IGenerateIncrementalDiffJobSource) |
|
659 |
||
660 |
class_job_type = BranchMergeProposalJobType.GENERATE_INCREMENTAL_DIFF |
|
661 |
||
11486.4.15
by Aaron Bentley
Get job tests passing. |
662 |
def acquireLease(self, duration=600): |
663 |
return self.job.acquireLease(duration) |
|
664 |
||
11486.4.4
by Aaron Bentley
Fake merge of job removal. |
665 |
def run(self): |
11486.4.15
by Aaron Bentley
Get job tests passing. |
666 |
revision_set = getUtility(IRevisionSet) |
667 |
old_revision = revision_set.getByRevisionId(self.old_revision_id) |
|
668 |
new_revision = revision_set.getByRevisionId(self.new_revision_id) |
|
669 |
diff = self.branch_merge_proposal.generateIncrementalDiff( |
|
670 |
old_revision, new_revision) |
|
11486.4.4
by Aaron Bentley
Fake merge of job removal. |
671 |
|
672 |
@classmethod
|
|
673 |
def create(cls, merge_proposal, old_revision_id, new_revision_id): |
|
674 |
metadata = cls.getMetadata(old_revision_id, new_revision_id) |
|
675 |
job = BranchMergeProposalJob( |
|
676 |
merge_proposal, cls.class_job_type, metadata) |
|
677 |
return cls(job) |
|
678 |
||
679 |
@staticmethod
|
|
680 |
def getMetadata(old_revision_id, new_revision_id): |
|
681 |
return { |
|
682 |
'old_revision_id': old_revision_id, |
|
683 |
'new_revision_id': new_revision_id, |
|
684 |
}
|
|
685 |
||
686 |
@property
|
|
687 |
def old_revision_id(self): |
|
688 |
"""The old revision id for the diff."""
|
|
689 |
return self.metadata['old_revision_id'] |
|
690 |
||
691 |
@property
|
|
692 |
def new_revision_id(self): |
|
693 |
"""The new revision id for the diff."""
|
|
694 |
return self.metadata['new_revision_id'] |
|
695 |
||
696 |
def getOopsVars(self): |
|
697 |
"""See `IRunnableJob`."""
|
|
11486.4.13
by Aaron Bentley
Lint fixes. |
698 |
vars = BranchMergeProposalJobDerived.getOopsVars(self) |
11486.4.4
by Aaron Bentley
Fake merge of job removal. |
699 |
vars.extend([ |
700 |
('old_revision_id', self.metadata['old_revision_id']), |
|
701 |
('new_revision_id', self.metadata['new_revision_id']), |
|
702 |
])
|
|
703 |
return vars |
|
704 |
||
705 |
def getOperationDescription(self): |
|
706 |
return ('generating an incremental diff for a merge proposal') |
|
707 |
||
708 |
def getErrorRecipients(self): |
|
709 |
"""Return a list of email-ids to notify about user errors."""
|
|
710 |
registrant = self.branch_merge_proposal.registrant |
|
711 |
return format_address_for_person(registrant) |
|
712 |
||
713 |
||
7675.624.18
by Tim Penhey
Make one job source for all merge proposal jobs. |
714 |
class BranchMergeProposalJobFactory: |
715 |
"""Construct a derived merge proposal job for a BranchMergeProposalJob."""
|
|
716 |
||
717 |
job_classes = { |
|
11733.1.2
by Tim Penhey
Update the job type enum to make more sense. |
718 |
BranchMergeProposalJobType.MERGE_PROPOSAL_NEEDS_REVIEW: |
11733.1.1
by Tim Penhey
Rename the MergeProposalCreatedJob to be MergeProposalReviewRequestedEmailJob. |
719 |
MergeProposalNeedsReviewEmailJob, |
7675.624.18
by Tim Penhey
Make one job source for all merge proposal jobs. |
720 |
BranchMergeProposalJobType.UPDATE_PREVIEW_DIFF: |
721 |
UpdatePreviewDiffJob, |
|
722 |
BranchMergeProposalJobType.CODE_REVIEW_COMMENT_EMAIL: |
|
723 |
CodeReviewCommentEmailJob, |
|
724 |
BranchMergeProposalJobType.REVIEW_REQUEST_EMAIL: |
|
725 |
ReviewRequestedEmailJob, |
|
726 |
BranchMergeProposalJobType.MERGE_PROPOSAL_UPDATED: |
|
727 |
MergeProposalUpdatedEmailJob, |
|
11486.4.4
by Aaron Bentley
Fake merge of job removal. |
728 |
BranchMergeProposalJobType.GENERATE_INCREMENTAL_DIFF: |
729 |
GenerateIncrementalDiffJob, |
|
7675.624.18
by Tim Penhey
Make one job source for all merge proposal jobs. |
730 |
}
|
731 |
||
732 |
@classmethod
|
|
733 |
def create(cls, bmp_job): |
|
734 |
"""Create the derived job for the bmp_job's job type."""
|
|
735 |
job_class = cls.job_classes[bmp_job.job_type] |
|
736 |
return job_class(bmp_job) |
|
737 |
||
738 |
||
739 |
class BranchMergeProposalJobSource: |
|
740 |
"""Provide a job source for all merge proposal jobs.
|
|
741 |
||
742 |
Only one job for any particular merge proposal is returned.
|
|
743 |
"""
|
|
744 |
||
745 |
classProvides(IBranchMergeProposalJobSource) |
|
746 |
||
747 |
@staticmethod
|
|
748 |
@contextlib.contextmanager |
|
749 |
def contextManager(): |
|
750 |
"""See `IJobSource`."""
|
|
751 |
errorlog.globalErrorUtility.configure('merge_proposal_jobs') |
|
9590.14.1
by Michael Hudson
merge db-devel via lower pipes, fixing conflicts |
752 |
server = get_ro_server() |
7675.624.18
by Tim Penhey
Make one job source for all merge proposal jobs. |
753 |
server.start_server() |
754 |
yield
|
|
755 |
server.stop_server() |
|
756 |
||
757 |
@staticmethod
|
|
758 |
def get(job_id): |
|
759 |
"""Get a job by id.
|
|
760 |
||
761 |
:return: the BranchMergeProposalJob with the specified id, as the
|
|
762 |
current BranchMergeProposalJobDereived subclass.
|
|
763 |
:raises: SQLObjectNotFound if there is no job with the specified id,
|
|
764 |
or its job_type does not match the desired subclass.
|
|
765 |
"""
|
|
766 |
job = BranchMergeProposalJob.get(job_id) |
|
767 |
return BranchMergeProposalJobFactory.create(job) |
|
768 |
||
769 |
@staticmethod
|
|
11486.4.19
by Aaron Bentley
Create GenerateIncrementalDiff jobs missing incremental diffs on tip change. |
770 |
def iterReady(job_type=None): |
7675.624.18
by Tim Penhey
Make one job source for all merge proposal jobs. |
771 |
from lp.code.model.branch import Branch |
772 |
store = getUtility(IStoreSelector).get(MAIN_STORE, MASTER_FLAVOR) |
|
773 |
SourceBranch = ClassAlias(Branch) |
|
774 |
TargetBranch = ClassAlias(Branch) |
|
11486.4.36
by Aaron Bentley
Updates from review. |
775 |
clauses = [ |
776 |
BranchMergeProposalJob.job == Job.id, |
|
777 |
Job._status.is_in([JobStatus.WAITING, JobStatus.RUNNING]), |
|
778 |
BranchMergeProposalJob.branch_merge_proposal == |
|
779 |
BranchMergeProposal.id, BranchMergeProposal.source_branch == |
|
780 |
SourceBranch.id, BranchMergeProposal.target_branch == |
|
781 |
TargetBranch.id, |
|
782 |
]
|
|
11486.4.19
by Aaron Bentley
Create GenerateIncrementalDiff jobs missing incremental diffs on tip change. |
783 |
if job_type is not None: |
784 |
clauses.append(BranchMergeProposalJob.job_type == job_type) |
|
785 |
jobs = store.find( |
|
786 |
(BranchMergeProposalJob, Job, BranchMergeProposal, |
|
787 |
SourceBranch, TargetBranch), And(*clauses)) |
|
10482.1.31
by Tim Penhey
Updates while on skype with reviewer. |
788 |
# Order by the job status first (to get running before waiting), then
|
789 |
# the date_created, then job type. This should give us all creation
|
|
790 |
# jobs before comment jobs.
|
|
7675.624.18
by Tim Penhey
Make one job source for all merge proposal jobs. |
791 |
jobs = jobs.order_by( |
7675.624.25
by Tim Penhey
If there is a job running for a merge proposal, don't run any extra jobs. |
792 |
Desc(Job._status), Job.date_created, |
793 |
Desc(BranchMergeProposalJob.job_type)) |
|
7675.624.18
by Tim Penhey
Make one job source for all merge proposal jobs. |
794 |
# Now only return one job for any given merge proposal.
|
795 |
ready_jobs = [] |
|
796 |
seen_merge_proposals = set() |
|
797 |
for bmp_job, job, bmp, source, target in jobs: |
|
798 |
# If we've seen this merge proposal already, skip this job.
|
|
799 |
if bmp.id in seen_merge_proposals: |
|
800 |
continue
|
|
7675.624.25
by Tim Penhey
If there is a job running for a merge proposal, don't run any extra jobs. |
801 |
# We have now seen this merge proposal.
|
802 |
seen_merge_proposals.add(bmp.id) |
|
803 |
# If the job is running, then skip it
|
|
804 |
if job.status == JobStatus.RUNNING: |
|
805 |
continue
|
|
7675.624.18
by Tim Penhey
Make one job source for all merge proposal jobs. |
806 |
derived_job = BranchMergeProposalJobFactory.create(bmp_job) |
7675.624.49
by Tim Penhey
Not yet passing, but getting close. |
807 |
# If the job is an update preview diff, then check that it is
|
808 |
# ready.
|
|
809 |
if IUpdatePreviewDiffJob.providedBy(derived_job): |
|
810 |
try: |
|
7675.624.51
by Tim Penhey
Test passes now. |
811 |
derived_job.checkReady() |
7675.624.49
by Tim Penhey
Not yet passing, but getting close. |
812 |
except UpdatePreviewDiffNotReady: |
813 |
# If the job was created under 15 minutes ago wait a bit.
|
|
10482.1.31
by Tim Penhey
Updates while on skype with reviewer. |
814 |
minutes = ( |
815 |
config.codehosting.update_preview_diff_ready_timeout) |
|
816 |
cut_off_time = ( |
|
817 |
datetime.now(pytz.UTC) - timedelta(minutes=minutes)) |
|
7675.624.49
by Tim Penhey
Not yet passing, but getting close. |
818 |
if job.date_created > cut_off_time: |
819 |
continue
|
|
7675.624.18
by Tim Penhey
Make one job source for all merge proposal jobs. |
820 |
ready_jobs.append(derived_job) |
821 |
return ready_jobs |