blob: f2a6e5b266e2900395da4267ad2d96949ad038fc [file] [log] [blame]
Gregory Haynes4fc12542015-04-22 20:38:06 -07001# Copyright 2015 GoodData
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
15import logging
Jan Hrubane252a732017-01-03 15:03:09 +010016import re
17from testtools.matchers import MatchesRegex
Jan Hruban324ca5b2015-11-05 19:28:54 +010018import time
Gregory Haynes4fc12542015-04-22 20:38:06 -070019
Wayne1a78c612015-06-11 17:14:13 -070020from tests.base import ZuulTestCase, simple_layout, random_sha1
Gregory Haynes4fc12542015-04-22 20:38:06 -070021
22logging.basicConfig(level=logging.DEBUG,
23 format='%(asctime)s %(name)-32s '
24 '%(levelname)-8s %(message)s')
25
26
27class TestGithubDriver(ZuulTestCase):
28 config_file = 'zuul-github-driver.conf'
29
30 @simple_layout('layouts/basic-github.yaml', driver='github')
31 def test_pull_event(self):
32 self.executor_server.hold_jobs_in_build = True
33
Jan Hruban37615e52015-11-19 14:30:49 +010034 A = self.fake_github.openFakePullRequest('org/project', 'master', 'A')
35 self.fake_github.emitEvent(A.getPullRequestOpenedEvent())
Gregory Haynes4fc12542015-04-22 20:38:06 -070036 self.waitUntilSettled()
37
38 build_params = self.builds[0].parameters
39 self.assertEqual('master', build_params['ZUUL_BRANCH'])
Jan Hruban37615e52015-11-19 14:30:49 +010040 self.assertEqual(str(A.number), build_params['ZUUL_CHANGE'])
41 self.assertEqual(A.head_sha, build_params['ZUUL_PATCHSET'])
Gregory Haynes4fc12542015-04-22 20:38:06 -070042
43 self.executor_server.hold_jobs_in_build = False
44 self.executor_server.release()
45 self.waitUntilSettled()
46
47 self.assertEqual('SUCCESS',
48 self.getJobFromHistory('project-test1').result)
49 self.assertEqual('SUCCESS',
50 self.getJobFromHistory('project-test2').result)
51
52 job = self.getJobFromHistory('project-test2')
53 zuulvars = job.parameters['vars']['zuul']
Jan Hruban37615e52015-11-19 14:30:49 +010054 self.assertEqual(A.number, zuulvars['change'])
55 self.assertEqual(A.head_sha, zuulvars['patchset'])
56 self.assertEqual(1, len(A.comments))
Jan Hruband4edee82015-12-16 12:49:51 +010057 self.assertEqual(2, len(self.history))
58
59 # test_pull_unmatched_branch_event(self):
60 self.create_branch('org/project', 'unmatched_branch')
61 B = self.fake_github.openFakePullRequest(
62 'org/project', 'unmatched_branch', 'B')
63 self.fake_github.emitEvent(B.getPullRequestOpenedEvent())
64 self.waitUntilSettled()
65
66 self.assertEqual(2, len(self.history))
Wayne1a78c612015-06-11 17:14:13 -070067
Jan Hruban570d01c2016-03-10 21:51:32 +010068 @simple_layout('layouts/files-github.yaml', driver='github')
69 def test_pull_matched_file_event(self):
70 A = self.fake_github.openFakePullRequest(
71 'org/project', 'master', 'A',
72 files=['random.txt', 'build-requires'])
73 self.fake_github.emitEvent(A.getPullRequestOpenedEvent())
74 self.waitUntilSettled()
75 self.assertEqual(1, len(self.history))
76
77 # test_pull_unmatched_file_event
78 B = self.fake_github.openFakePullRequest('org/project', 'master', 'B',
79 files=['random.txt'])
80 self.fake_github.emitEvent(B.getPullRequestOpenedEvent())
81 self.waitUntilSettled()
82 self.assertEqual(1, len(self.history))
83
Jan Hrubanc7ab1602015-10-14 15:29:33 +020084 @simple_layout('layouts/basic-github.yaml', driver='github')
85 def test_comment_event(self):
Jan Hruban37615e52015-11-19 14:30:49 +010086 A = self.fake_github.openFakePullRequest('org/project', 'master', 'A')
87 self.fake_github.emitEvent(A.getCommentAddedEvent('test me'))
Jan Hrubanc7ab1602015-10-14 15:29:33 +020088 self.waitUntilSettled()
89 self.assertEqual(2, len(self.history))
90
91 # Test an unmatched comment, history should remain the same
Jan Hruban37615e52015-11-19 14:30:49 +010092 B = self.fake_github.openFakePullRequest('org/project', 'master', 'B')
93 self.fake_github.emitEvent(B.getCommentAddedEvent('casual comment'))
Jan Hrubanc7ab1602015-10-14 15:29:33 +020094 self.waitUntilSettled()
95 self.assertEqual(2, len(self.history))
96
Wayne1a78c612015-06-11 17:14:13 -070097 @simple_layout('layouts/push-tag-github.yaml', driver='github')
98 def test_tag_event(self):
99 self.executor_server.hold_jobs_in_build = True
100
101 sha = random_sha1()
102 self.fake_github.emitEvent(
103 self.fake_github.getPushEvent('org/project', 'refs/tags/newtag',
104 new_rev=sha))
105 self.waitUntilSettled()
106
107 build_params = self.builds[0].parameters
108 self.assertEqual('refs/tags/newtag', build_params['ZUUL_REF'])
109 self.assertEqual('00000000000000000000000000000000',
110 build_params['ZUUL_OLDREV'])
111 self.assertEqual(sha, build_params['ZUUL_NEWREV'])
112
113 self.executor_server.hold_jobs_in_build = False
114 self.executor_server.release()
115 self.waitUntilSettled()
116
117 self.assertEqual('SUCCESS',
118 self.getJobFromHistory('project-tag').result)
119
120 @simple_layout('layouts/push-tag-github.yaml', driver='github')
121 def test_push_event(self):
122 self.executor_server.hold_jobs_in_build = True
123
124 old_sha = random_sha1()
125 new_sha = random_sha1()
126 self.fake_github.emitEvent(
127 self.fake_github.getPushEvent('org/project', 'refs/heads/master',
128 old_sha, new_sha))
129 self.waitUntilSettled()
130
131 build_params = self.builds[0].parameters
132 self.assertEqual('refs/heads/master', build_params['ZUUL_REF'])
133 self.assertEqual(old_sha, build_params['ZUUL_OLDREV'])
134 self.assertEqual(new_sha, build_params['ZUUL_NEWREV'])
135
136 self.executor_server.hold_jobs_in_build = False
137 self.executor_server.release()
138 self.waitUntilSettled()
139
140 self.assertEqual('SUCCESS',
141 self.getJobFromHistory('project-post').result)
Jan Hruband4edee82015-12-16 12:49:51 +0100142 self.assertEqual(1, len(self.history))
143
144 # test unmatched push event
145 old_sha = random_sha1()
146 new_sha = random_sha1()
147 self.fake_github.emitEvent(
148 self.fake_github.getPushEvent('org/project',
149 'refs/heads/unmatched_branch',
150 old_sha, new_sha))
151 self.waitUntilSettled()
152
153 self.assertEqual(1, len(self.history))
Jan Hruban6d53c5e2015-10-24 03:03:34 +0200154
Jan Hruban16ad31f2015-11-07 14:39:07 +0100155 @simple_layout('layouts/labeling-github.yaml', driver='github')
156 def test_labels(self):
Jan Hruban37615e52015-11-19 14:30:49 +0100157 A = self.fake_github.openFakePullRequest('org/project', 'master', 'A')
Jan Hruban16ad31f2015-11-07 14:39:07 +0100158 self.fake_github.emitEvent(A.addLabel('test'))
159 self.waitUntilSettled()
160 self.assertEqual(1, len(self.history))
161 self.assertEqual('project-labels', self.history[0].name)
162 self.assertEqual(['tests passed'], A.labels)
163
164 # test label removed
Jan Hruban37615e52015-11-19 14:30:49 +0100165 B = self.fake_github.openFakePullRequest('org/project', 'master', 'B')
Jan Hruban16ad31f2015-11-07 14:39:07 +0100166 B.addLabel('do not test')
167 self.fake_github.emitEvent(B.removeLabel('do not test'))
168 self.waitUntilSettled()
169 self.assertEqual(2, len(self.history))
170 self.assertEqual('project-labels', self.history[1].name)
171 self.assertEqual(['tests passed'], B.labels)
172
173 # test unmatched label
Jan Hruban37615e52015-11-19 14:30:49 +0100174 C = self.fake_github.openFakePullRequest('org/project', 'master', 'C')
Jan Hruban16ad31f2015-11-07 14:39:07 +0100175 self.fake_github.emitEvent(C.addLabel('other label'))
176 self.waitUntilSettled()
177 self.assertEqual(2, len(self.history))
178 self.assertEqual(['other label'], C.labels)
179
Jesse Keating5c05a9f2017-01-12 14:44:58 -0800180 @simple_layout('layouts/reviews-github.yaml', driver='github')
181 def test_review_event(self):
182 A = self.fake_github.openFakePullRequest('org/project', 'master', 'A')
183 self.fake_github.emitEvent(A.getReviewAddedEvent('approve'))
184 self.waitUntilSettled()
185 self.assertEqual(1, len(self.history))
186 self.assertEqual('project-reviews', self.history[0].name)
187 self.assertEqual(['tests passed'], A.labels)
188
189 # test_review_unmatched_event
190 B = self.fake_github.openFakePullRequest('org/project', 'master', 'B')
191 self.fake_github.emitEvent(B.getReviewAddedEvent('comment'))
192 self.waitUntilSettled()
193 self.assertEqual(1, len(self.history))
194
Jan Hruban324ca5b2015-11-05 19:28:54 +0100195 @simple_layout('layouts/dequeue-github.yaml', driver='github')
196 def test_dequeue_pull_synchronized(self):
197 self.executor_server.hold_jobs_in_build = True
198
Jan Hruban37615e52015-11-19 14:30:49 +0100199 A = self.fake_github.openFakePullRequest(
200 'org/one-job-project', 'master', 'A')
201 self.fake_github.emitEvent(A.getPullRequestOpenedEvent())
Jan Hruban324ca5b2015-11-05 19:28:54 +0100202 self.waitUntilSettled()
203
204 # event update stamp has resolution one second, wait so the latter
205 # one has newer timestamp
206 time.sleep(1)
Jan Hruban37615e52015-11-19 14:30:49 +0100207 A.addCommit()
208 self.fake_github.emitEvent(A.getPullRequestSynchronizeEvent())
Jan Hruban324ca5b2015-11-05 19:28:54 +0100209 self.waitUntilSettled()
210
211 self.executor_server.hold_jobs_in_build = False
212 self.executor_server.release()
213 self.waitUntilSettled()
214
215 self.assertEqual(2, len(self.history))
216 self.assertEqual(1, self.countJobResults(self.history, 'ABORTED'))
217
218 @simple_layout('layouts/dequeue-github.yaml', driver='github')
219 def test_dequeue_pull_abandoned(self):
220 self.executor_server.hold_jobs_in_build = True
221
Jan Hruban37615e52015-11-19 14:30:49 +0100222 A = self.fake_github.openFakePullRequest(
223 'org/one-job-project', 'master', 'A')
224 self.fake_github.emitEvent(A.getPullRequestOpenedEvent())
Jan Hruban324ca5b2015-11-05 19:28:54 +0100225 self.waitUntilSettled()
Jan Hruban37615e52015-11-19 14:30:49 +0100226 self.fake_github.emitEvent(A.getPullRequestClosedEvent())
Jan Hruban324ca5b2015-11-05 19:28:54 +0100227 self.waitUntilSettled()
228
229 self.executor_server.hold_jobs_in_build = False
230 self.executor_server.release()
231 self.waitUntilSettled()
232
233 self.assertEqual(1, len(self.history))
234 self.assertEqual(1, self.countJobResults(self.history, 'ABORTED'))
235
Jan Hruban6d53c5e2015-10-24 03:03:34 +0200236 @simple_layout('layouts/basic-github.yaml', driver='github')
237 def test_git_https_url(self):
238 """Test that git_ssh option gives git url with ssh"""
239 url = self.fake_github.real_getGitUrl('org/project')
240 self.assertEqual('https://github.com/org/project', url)
241
242 @simple_layout('layouts/basic-github.yaml', driver='github')
243 def test_git_ssh_url(self):
244 """Test that git_ssh option gives git url with ssh"""
245 url = self.fake_github_ssh.real_getGitUrl('org/project')
246 self.assertEqual('ssh://git@github.com/org/project.git', url)
Jan Hrubane252a732017-01-03 15:03:09 +0100247
Jesse Keatingbe4ef8a2016-12-06 11:29:13 -0800248 @simple_layout('layouts/basic-github.yaml', driver='github')
249 def test_git_enterprise_url(self):
250 """Test that git_url option gives git url with proper host"""
251 url = self.fake_github_ent.real_getGitUrl('org/project')
252 self.assertEqual('ssh://git@github.enterprise.io/org/project.git', url)
253
Jan Hrubane252a732017-01-03 15:03:09 +0100254 @simple_layout('layouts/reporting-github.yaml', driver='github')
255 def test_reporting(self):
256 # pipeline reports pull status both on start and success
257 self.executor_server.hold_jobs_in_build = True
Jan Hruban37615e52015-11-19 14:30:49 +0100258 A = self.fake_github.openFakePullRequest('org/project', 'master', 'A')
259 self.fake_github.emitEvent(A.getPullRequestOpenedEvent())
Jan Hrubane252a732017-01-03 15:03:09 +0100260 self.waitUntilSettled()
Jan Hruban37615e52015-11-19 14:30:49 +0100261 self.assertIn('check', A.statuses)
262 check_status = A.statuses['check']
Jan Hrubanddeb95a2017-01-03 15:12:41 +0100263 check_url = ('http://zuul.example.com/status/#%s,%s' %
264 (A.number, A.head_sha))
Jan Hrubane252a732017-01-03 15:03:09 +0100265 self.assertEqual('Standard check', check_status['description'])
266 self.assertEqual('pending', check_status['state'])
Jan Hrubanddeb95a2017-01-03 15:12:41 +0100267 self.assertEqual(check_url, check_status['url'])
Jan Hruban37615e52015-11-19 14:30:49 +0100268 self.assertEqual(0, len(A.comments))
Jan Hrubane252a732017-01-03 15:03:09 +0100269
270 self.executor_server.hold_jobs_in_build = False
271 self.executor_server.release()
272 self.waitUntilSettled()
Jan Hruban37615e52015-11-19 14:30:49 +0100273 check_status = A.statuses['check']
Jan Hrubane252a732017-01-03 15:03:09 +0100274 self.assertEqual('Standard check', check_status['description'])
275 self.assertEqual('success', check_status['state'])
Jan Hrubanddeb95a2017-01-03 15:12:41 +0100276 self.assertEqual(check_url, check_status['url'])
Jan Hruban37615e52015-11-19 14:30:49 +0100277 self.assertEqual(1, len(A.comments))
278 self.assertThat(A.comments[0],
Jan Hrubane252a732017-01-03 15:03:09 +0100279 MatchesRegex('.*Build succeeded.*', re.DOTALL))
280
281 # pipeline does not report any status but does comment
282 self.executor_server.hold_jobs_in_build = True
283 self.fake_github.emitEvent(
Jan Hruban37615e52015-11-19 14:30:49 +0100284 A.getCommentAddedEvent('reporting check'))
Jan Hrubane252a732017-01-03 15:03:09 +0100285 self.waitUntilSettled()
Jan Hruban37615e52015-11-19 14:30:49 +0100286 self.assertNotIn('reporting', A.statuses)
Jan Hrubane252a732017-01-03 15:03:09 +0100287 # comments increased by one for the start message
Jan Hruban37615e52015-11-19 14:30:49 +0100288 self.assertEqual(2, len(A.comments))
289 self.assertThat(A.comments[1],
Jan Hrubane252a732017-01-03 15:03:09 +0100290 MatchesRegex('.*Starting reporting jobs.*', re.DOTALL))
291 self.executor_server.hold_jobs_in_build = False
292 self.executor_server.release()
293 self.waitUntilSettled()
Jan Hruban37615e52015-11-19 14:30:49 +0100294 self.assertNotIn('reporting', A.statuses)
295 self.assertEqual(2, len(A.comments))
Jan Hruban49bff072015-11-03 11:45:46 +0100296
297 @simple_layout('layouts/merging-github.yaml', driver='github')
298 def test_report_pull_merge(self):
299 # pipeline merges the pull request on success
Jan Hruban3b415922016-02-03 13:10:22 +0100300 A = self.fake_github.openFakePullRequest('org/project', 'master',
301 'PR title')
Jan Hruban49bff072015-11-03 11:45:46 +0100302 self.fake_github.emitEvent(A.getCommentAddedEvent('merge me'))
303 self.waitUntilSettled()
304 self.assertTrue(A.is_merged)
Jan Hruban3b415922016-02-03 13:10:22 +0100305 self.assertThat(A.merge_message,
306 MatchesRegex('.*PR title.*Reviewed-by.*', re.DOTALL))
Jan Hruban49bff072015-11-03 11:45:46 +0100307
308 # pipeline merges the pull request on success after failure
309 self.fake_github.merge_failure = True
Jan Hruban37615e52015-11-19 14:30:49 +0100310 B = self.fake_github.openFakePullRequest('org/project', 'master', 'B')
Jan Hruban49bff072015-11-03 11:45:46 +0100311 self.fake_github.emitEvent(B.getCommentAddedEvent('merge me'))
312 self.waitUntilSettled()
313 self.assertFalse(B.is_merged)
314 self.fake_github.merge_failure = False
315
316 # pipeline merges the pull request on second run of merge
317 # first merge failed on 405 Method Not Allowed error
318 self.fake_github.merge_not_allowed_count = 1
Jan Hruban37615e52015-11-19 14:30:49 +0100319 C = self.fake_github.openFakePullRequest('org/project', 'master', 'C')
Jan Hruban49bff072015-11-03 11:45:46 +0100320 self.fake_github.emitEvent(C.getCommentAddedEvent('merge me'))
321 self.waitUntilSettled()
322 self.assertTrue(C.is_merged)
323
324 # pipeline does not merge the pull request
325 # merge failed on 405 Method Not Allowed error - twice
326 self.fake_github.merge_not_allowed_count = 2
Jan Hruban37615e52015-11-19 14:30:49 +0100327 D = self.fake_github.openFakePullRequest('org/project', 'master', 'D')
Jan Hruban49bff072015-11-03 11:45:46 +0100328 self.fake_github.emitEvent(D.getCommentAddedEvent('merge me'))
329 self.waitUntilSettled()
330 self.assertFalse(D.is_merged)
Jan Hruban37615e52015-11-19 14:30:49 +0100331
332 @simple_layout('layouts/dependent-github.yaml', driver='github')
333 def test_parallel_changes(self):
334 "Test that changes are tested in parallel and merged in series"
335
336 self.executor_server.hold_jobs_in_build = True
337 A = self.fake_github.openFakePullRequest('org/project', 'master', 'A')
338 B = self.fake_github.openFakePullRequest('org/project', 'master', 'B')
339 C = self.fake_github.openFakePullRequest('org/project', 'master', 'C')
340
341 self.fake_github.emitEvent(A.addLabel('merge'))
342 self.fake_github.emitEvent(B.addLabel('merge'))
343 self.fake_github.emitEvent(C.addLabel('merge'))
344
345 self.waitUntilSettled()
346 self.assertEqual(len(self.builds), 1)
347 self.assertEqual(self.builds[0].name, 'project-merge')
348 self.assertTrue(self.builds[0].hasChanges(A))
349
350 self.executor_server.release('.*-merge')
351 self.waitUntilSettled()
352 self.assertEqual(len(self.builds), 3)
353 self.assertEqual(self.builds[0].name, 'project-test1')
354 self.assertTrue(self.builds[0].hasChanges(A))
355 self.assertEqual(self.builds[1].name, 'project-test2')
356 self.assertTrue(self.builds[1].hasChanges(A))
357 self.assertEqual(self.builds[2].name, 'project-merge')
358 self.assertTrue(self.builds[2].hasChanges(A, B))
359
360 self.executor_server.release('.*-merge')
361 self.waitUntilSettled()
362 self.assertEqual(len(self.builds), 5)
363 self.assertEqual(self.builds[0].name, 'project-test1')
364 self.assertTrue(self.builds[0].hasChanges(A))
365 self.assertEqual(self.builds[1].name, 'project-test2')
366 self.assertTrue(self.builds[1].hasChanges(A))
367
368 self.assertEqual(self.builds[2].name, 'project-test1')
369 self.assertTrue(self.builds[2].hasChanges(A))
370 self.assertEqual(self.builds[3].name, 'project-test2')
371 self.assertTrue(self.builds[3].hasChanges(A, B))
372
373 self.assertEqual(self.builds[4].name, 'project-merge')
374 self.assertTrue(self.builds[4].hasChanges(A, B, C))
375
376 self.executor_server.release('.*-merge')
377 self.waitUntilSettled()
378 self.assertEqual(len(self.builds), 6)
379 self.assertEqual(self.builds[0].name, 'project-test1')
380 self.assertTrue(self.builds[0].hasChanges(A))
381 self.assertEqual(self.builds[1].name, 'project-test2')
382 self.assertTrue(self.builds[1].hasChanges(A))
383
384 self.assertEqual(self.builds[2].name, 'project-test1')
385 self.assertTrue(self.builds[2].hasChanges(A, B))
386 self.assertEqual(self.builds[3].name, 'project-test2')
387 self.assertTrue(self.builds[3].hasChanges(A, B))
388
389 self.assertEqual(self.builds[4].name, 'project-test1')
390 self.assertTrue(self.builds[4].hasChanges(A, B, C))
391 self.assertEqual(self.builds[5].name, 'project-test2')
392 self.assertTrue(self.builds[5].hasChanges(A, B, C))
393
394 all_builds = self.builds[:]
395 self.release(all_builds[2])
396 self.release(all_builds[3])
397 self.waitUntilSettled()
398 self.assertFalse(A.is_merged)
399 self.assertFalse(B.is_merged)
400 self.assertFalse(C.is_merged)
401
402 self.release(all_builds[0])
403 self.release(all_builds[1])
404 self.waitUntilSettled()
405 self.assertTrue(A.is_merged)
406 self.assertTrue(B.is_merged)
407 self.assertFalse(C.is_merged)
408
409 self.executor_server.hold_jobs_in_build = False
410 self.executor_server.release()
411 self.waitUntilSettled()
412 self.assertEqual(len(self.builds), 0)
413 self.assertEqual(len(self.history), 9)
414 self.assertTrue(C.is_merged)
415
416 self.assertNotIn('merge', A.labels)
417 self.assertNotIn('merge', B.labels)
418 self.assertNotIn('merge', C.labels)
419
420 @simple_layout('layouts/dependent-github.yaml', driver='github')
421 def test_failed_changes(self):
422 "Test that a change behind a failed change is retested"
423 self.executor_server.hold_jobs_in_build = True
424
425 A = self.fake_github.openFakePullRequest('org/project', 'master', 'A')
426 B = self.fake_github.openFakePullRequest('org/project', 'master', 'B')
427
428 self.executor_server.failJob('project-test1', A)
429
430 self.fake_github.emitEvent(A.addLabel('merge'))
431 self.fake_github.emitEvent(B.addLabel('merge'))
432 self.waitUntilSettled()
433
434 self.executor_server.release('.*-merge')
435 self.waitUntilSettled()
436
437 self.executor_server.hold_jobs_in_build = False
438 self.executor_server.release()
439
440 self.waitUntilSettled()
441 # It's certain that the merge job for change 2 will run, but
442 # the test1 and test2 jobs may or may not run.
443 self.assertTrue(len(self.history) > 6)
444 self.assertFalse(A.is_merged)
445 self.assertTrue(B.is_merged)
446 self.assertNotIn('merge', A.labels)
447 self.assertNotIn('merge', B.labels)
448
449 @simple_layout('layouts/dependent-github.yaml', driver='github')
450 def test_failed_change_at_head(self):
451 "Test that if a change at the head fails, jobs behind it are canceled"
452
453 self.executor_server.hold_jobs_in_build = True
454 A = self.fake_github.openFakePullRequest('org/project', 'master', 'A')
455 B = self.fake_github.openFakePullRequest('org/project', 'master', 'B')
456 C = self.fake_github.openFakePullRequest('org/project', 'master', 'C')
457
458 self.executor_server.failJob('project-test1', A)
459
460 self.fake_github.emitEvent(A.addLabel('merge'))
461 self.fake_github.emitEvent(B.addLabel('merge'))
462 self.fake_github.emitEvent(C.addLabel('merge'))
463
464 self.waitUntilSettled()
465
466 self.assertEqual(len(self.builds), 1)
467 self.assertEqual(self.builds[0].name, 'project-merge')
468 self.assertTrue(self.builds[0].hasChanges(A))
469
470 self.executor_server.release('.*-merge')
471 self.waitUntilSettled()
472 self.executor_server.release('.*-merge')
473 self.waitUntilSettled()
474 self.executor_server.release('.*-merge')
475 self.waitUntilSettled()
476
477 self.assertEqual(len(self.builds), 6)
478 self.assertEqual(self.builds[0].name, 'project-test1')
479 self.assertEqual(self.builds[1].name, 'project-test2')
480 self.assertEqual(self.builds[2].name, 'project-test1')
481 self.assertEqual(self.builds[3].name, 'project-test2')
482 self.assertEqual(self.builds[4].name, 'project-test1')
483 self.assertEqual(self.builds[5].name, 'project-test2')
484
485 self.release(self.builds[0])
486 self.waitUntilSettled()
487
488 # project-test2, project-merge for B
489 self.assertEqual(len(self.builds), 2)
490 self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 4)
491
492 self.executor_server.hold_jobs_in_build = False
493 self.executor_server.release()
494 self.waitUntilSettled()
495
496 self.assertEqual(len(self.builds), 0)
497 self.assertEqual(len(self.history), 15)
498 self.assertFalse(A.is_merged)
499 self.assertTrue(B.is_merged)
500 self.assertTrue(C.is_merged)
501 self.assertNotIn('merge', A.labels)
502 self.assertNotIn('merge', B.labels)
503 self.assertNotIn('merge', C.labels)