blob: 0cfe3dad4ad67ecfc783be95e7c43ed71b49850c [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
Jan Hrubane252a732017-01-03 15:03:09 +010015import re
Jamie Lennox3f16de52017-05-09 14:24:11 +100016from testtools.matchers import MatchesRegex, StartsWith
Tristan Cacqueray2bafb1f2017-06-12 07:10:26 +000017import urllib
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
Gregory Haynes4fc12542015-04-22 20:38:06 -070022
23class TestGithubDriver(ZuulTestCase):
24 config_file = 'zuul-github-driver.conf'
25
26 @simple_layout('layouts/basic-github.yaml', driver='github')
27 def test_pull_event(self):
28 self.executor_server.hold_jobs_in_build = True
29
Jan Hruban37615e52015-11-19 14:30:49 +010030 A = self.fake_github.openFakePullRequest('org/project', 'master', 'A')
31 self.fake_github.emitEvent(A.getPullRequestOpenedEvent())
Gregory Haynes4fc12542015-04-22 20:38:06 -070032 self.waitUntilSettled()
33
34 build_params = self.builds[0].parameters
35 self.assertEqual('master', build_params['ZUUL_BRANCH'])
Jan Hruban37615e52015-11-19 14:30:49 +010036 self.assertEqual(str(A.number), build_params['ZUUL_CHANGE'])
37 self.assertEqual(A.head_sha, build_params['ZUUL_PATCHSET'])
Gregory Haynes4fc12542015-04-22 20:38:06 -070038
39 self.executor_server.hold_jobs_in_build = False
40 self.executor_server.release()
41 self.waitUntilSettled()
42
43 self.assertEqual('SUCCESS',
44 self.getJobFromHistory('project-test1').result)
45 self.assertEqual('SUCCESS',
46 self.getJobFromHistory('project-test2').result)
47
48 job = self.getJobFromHistory('project-test2')
Monty Taylord13bc362017-06-30 13:11:37 -050049 zuulvars = job.parameters['zuul']
Jan Hruban37615e52015-11-19 14:30:49 +010050 self.assertEqual(A.number, zuulvars['change'])
51 self.assertEqual(A.head_sha, zuulvars['patchset'])
52 self.assertEqual(1, len(A.comments))
Jan Hruband4edee82015-12-16 12:49:51 +010053 self.assertEqual(2, len(self.history))
54
55 # test_pull_unmatched_branch_event(self):
56 self.create_branch('org/project', 'unmatched_branch')
57 B = self.fake_github.openFakePullRequest(
58 'org/project', 'unmatched_branch', 'B')
59 self.fake_github.emitEvent(B.getPullRequestOpenedEvent())
60 self.waitUntilSettled()
61
62 self.assertEqual(2, len(self.history))
Wayne1a78c612015-06-11 17:14:13 -070063
Jan Hruban570d01c2016-03-10 21:51:32 +010064 @simple_layout('layouts/files-github.yaml', driver='github')
65 def test_pull_matched_file_event(self):
66 A = self.fake_github.openFakePullRequest(
67 'org/project', 'master', 'A',
68 files=['random.txt', 'build-requires'])
69 self.fake_github.emitEvent(A.getPullRequestOpenedEvent())
70 self.waitUntilSettled()
71 self.assertEqual(1, len(self.history))
72
73 # test_pull_unmatched_file_event
74 B = self.fake_github.openFakePullRequest('org/project', 'master', 'B',
75 files=['random.txt'])
76 self.fake_github.emitEvent(B.getPullRequestOpenedEvent())
77 self.waitUntilSettled()
78 self.assertEqual(1, len(self.history))
79
Jan Hrubanc7ab1602015-10-14 15:29:33 +020080 @simple_layout('layouts/basic-github.yaml', driver='github')
81 def test_comment_event(self):
Jan Hruban37615e52015-11-19 14:30:49 +010082 A = self.fake_github.openFakePullRequest('org/project', 'master', 'A')
83 self.fake_github.emitEvent(A.getCommentAddedEvent('test me'))
Jan Hrubanc7ab1602015-10-14 15:29:33 +020084 self.waitUntilSettled()
85 self.assertEqual(2, len(self.history))
86
87 # Test an unmatched comment, history should remain the same
Jan Hruban37615e52015-11-19 14:30:49 +010088 B = self.fake_github.openFakePullRequest('org/project', 'master', 'B')
89 self.fake_github.emitEvent(B.getCommentAddedEvent('casual comment'))
Jan Hrubanc7ab1602015-10-14 15:29:33 +020090 self.waitUntilSettled()
91 self.assertEqual(2, len(self.history))
92
Wayne1a78c612015-06-11 17:14:13 -070093 @simple_layout('layouts/push-tag-github.yaml', driver='github')
94 def test_tag_event(self):
95 self.executor_server.hold_jobs_in_build = True
96
97 sha = random_sha1()
98 self.fake_github.emitEvent(
99 self.fake_github.getPushEvent('org/project', 'refs/tags/newtag',
100 new_rev=sha))
101 self.waitUntilSettled()
102
103 build_params = self.builds[0].parameters
104 self.assertEqual('refs/tags/newtag', build_params['ZUUL_REF'])
105 self.assertEqual('00000000000000000000000000000000',
106 build_params['ZUUL_OLDREV'])
107 self.assertEqual(sha, build_params['ZUUL_NEWREV'])
108
109 self.executor_server.hold_jobs_in_build = False
110 self.executor_server.release()
111 self.waitUntilSettled()
112
113 self.assertEqual('SUCCESS',
114 self.getJobFromHistory('project-tag').result)
115
116 @simple_layout('layouts/push-tag-github.yaml', driver='github')
117 def test_push_event(self):
118 self.executor_server.hold_jobs_in_build = True
119
120 old_sha = random_sha1()
121 new_sha = random_sha1()
122 self.fake_github.emitEvent(
123 self.fake_github.getPushEvent('org/project', 'refs/heads/master',
124 old_sha, new_sha))
125 self.waitUntilSettled()
126
127 build_params = self.builds[0].parameters
128 self.assertEqual('refs/heads/master', build_params['ZUUL_REF'])
129 self.assertEqual(old_sha, build_params['ZUUL_OLDREV'])
130 self.assertEqual(new_sha, build_params['ZUUL_NEWREV'])
131
132 self.executor_server.hold_jobs_in_build = False
133 self.executor_server.release()
134 self.waitUntilSettled()
135
136 self.assertEqual('SUCCESS',
137 self.getJobFromHistory('project-post').result)
Jan Hruband4edee82015-12-16 12:49:51 +0100138 self.assertEqual(1, len(self.history))
139
140 # test unmatched push event
141 old_sha = random_sha1()
142 new_sha = random_sha1()
143 self.fake_github.emitEvent(
144 self.fake_github.getPushEvent('org/project',
145 'refs/heads/unmatched_branch',
146 old_sha, new_sha))
147 self.waitUntilSettled()
148
149 self.assertEqual(1, len(self.history))
Jan Hruban6d53c5e2015-10-24 03:03:34 +0200150
Jan Hruban16ad31f2015-11-07 14:39:07 +0100151 @simple_layout('layouts/labeling-github.yaml', driver='github')
152 def test_labels(self):
Jan Hruban37615e52015-11-19 14:30:49 +0100153 A = self.fake_github.openFakePullRequest('org/project', 'master', 'A')
Jan Hruban16ad31f2015-11-07 14:39:07 +0100154 self.fake_github.emitEvent(A.addLabel('test'))
155 self.waitUntilSettled()
156 self.assertEqual(1, len(self.history))
157 self.assertEqual('project-labels', self.history[0].name)
158 self.assertEqual(['tests passed'], A.labels)
159
160 # test label removed
Jan Hruban37615e52015-11-19 14:30:49 +0100161 B = self.fake_github.openFakePullRequest('org/project', 'master', 'B')
Jan Hruban16ad31f2015-11-07 14:39:07 +0100162 B.addLabel('do not test')
163 self.fake_github.emitEvent(B.removeLabel('do not test'))
164 self.waitUntilSettled()
165 self.assertEqual(2, len(self.history))
166 self.assertEqual('project-labels', self.history[1].name)
167 self.assertEqual(['tests passed'], B.labels)
168
169 # test unmatched label
Jan Hruban37615e52015-11-19 14:30:49 +0100170 C = self.fake_github.openFakePullRequest('org/project', 'master', 'C')
Jan Hruban16ad31f2015-11-07 14:39:07 +0100171 self.fake_github.emitEvent(C.addLabel('other label'))
172 self.waitUntilSettled()
173 self.assertEqual(2, len(self.history))
174 self.assertEqual(['other label'], C.labels)
175
Jesse Keating5c05a9f2017-01-12 14:44:58 -0800176 @simple_layout('layouts/reviews-github.yaml', driver='github')
177 def test_review_event(self):
178 A = self.fake_github.openFakePullRequest('org/project', 'master', 'A')
179 self.fake_github.emitEvent(A.getReviewAddedEvent('approve'))
180 self.waitUntilSettled()
181 self.assertEqual(1, len(self.history))
182 self.assertEqual('project-reviews', self.history[0].name)
183 self.assertEqual(['tests passed'], A.labels)
184
185 # test_review_unmatched_event
186 B = self.fake_github.openFakePullRequest('org/project', 'master', 'B')
187 self.fake_github.emitEvent(B.getReviewAddedEvent('comment'))
188 self.waitUntilSettled()
189 self.assertEqual(1, len(self.history))
190
Jan Hruban324ca5b2015-11-05 19:28:54 +0100191 @simple_layout('layouts/dequeue-github.yaml', driver='github')
192 def test_dequeue_pull_synchronized(self):
193 self.executor_server.hold_jobs_in_build = True
194
Jan Hruban37615e52015-11-19 14:30:49 +0100195 A = self.fake_github.openFakePullRequest(
196 'org/one-job-project', 'master', 'A')
197 self.fake_github.emitEvent(A.getPullRequestOpenedEvent())
Jan Hruban324ca5b2015-11-05 19:28:54 +0100198 self.waitUntilSettled()
199
200 # event update stamp has resolution one second, wait so the latter
201 # one has newer timestamp
202 time.sleep(1)
Jan Hruban37615e52015-11-19 14:30:49 +0100203 A.addCommit()
204 self.fake_github.emitEvent(A.getPullRequestSynchronizeEvent())
Jan Hruban324ca5b2015-11-05 19:28:54 +0100205 self.waitUntilSettled()
206
207 self.executor_server.hold_jobs_in_build = False
208 self.executor_server.release()
209 self.waitUntilSettled()
210
211 self.assertEqual(2, len(self.history))
212 self.assertEqual(1, self.countJobResults(self.history, 'ABORTED'))
213
214 @simple_layout('layouts/dequeue-github.yaml', driver='github')
215 def test_dequeue_pull_abandoned(self):
216 self.executor_server.hold_jobs_in_build = True
217
Jan Hruban37615e52015-11-19 14:30:49 +0100218 A = self.fake_github.openFakePullRequest(
219 'org/one-job-project', 'master', 'A')
220 self.fake_github.emitEvent(A.getPullRequestOpenedEvent())
Jan Hruban324ca5b2015-11-05 19:28:54 +0100221 self.waitUntilSettled()
Jan Hruban37615e52015-11-19 14:30:49 +0100222 self.fake_github.emitEvent(A.getPullRequestClosedEvent())
Jan Hruban324ca5b2015-11-05 19:28:54 +0100223 self.waitUntilSettled()
224
225 self.executor_server.hold_jobs_in_build = False
226 self.executor_server.release()
227 self.waitUntilSettled()
228
229 self.assertEqual(1, len(self.history))
230 self.assertEqual(1, self.countJobResults(self.history, 'ABORTED'))
231
Jan Hruban6d53c5e2015-10-24 03:03:34 +0200232 @simple_layout('layouts/basic-github.yaml', driver='github')
233 def test_git_https_url(self):
234 """Test that git_ssh option gives git url with ssh"""
235 url = self.fake_github.real_getGitUrl('org/project')
236 self.assertEqual('https://github.com/org/project', url)
237
238 @simple_layout('layouts/basic-github.yaml', driver='github')
239 def test_git_ssh_url(self):
240 """Test that git_ssh option gives git url with ssh"""
241 url = self.fake_github_ssh.real_getGitUrl('org/project')
242 self.assertEqual('ssh://git@github.com/org/project.git', url)
Jan Hrubane252a732017-01-03 15:03:09 +0100243
Jesse Keatingbe4ef8a2016-12-06 11:29:13 -0800244 @simple_layout('layouts/basic-github.yaml', driver='github')
245 def test_git_enterprise_url(self):
246 """Test that git_url option gives git url with proper host"""
247 url = self.fake_github_ent.real_getGitUrl('org/project')
248 self.assertEqual('ssh://git@github.enterprise.io/org/project.git', url)
249
Jan Hrubane252a732017-01-03 15:03:09 +0100250 @simple_layout('layouts/reporting-github.yaml', driver='github')
251 def test_reporting(self):
Jesse Keating1f7ebe92017-06-12 17:21:00 -0700252 project = 'org/project'
Jan Hrubane252a732017-01-03 15:03:09 +0100253 # pipeline reports pull status both on start and success
254 self.executor_server.hold_jobs_in_build = True
Jesse Keating1f7ebe92017-06-12 17:21:00 -0700255 A = self.fake_github.openFakePullRequest(project, 'master', 'A')
Jan Hruban37615e52015-11-19 14:30:49 +0100256 self.fake_github.emitEvent(A.getPullRequestOpenedEvent())
Jan Hrubane252a732017-01-03 15:03:09 +0100257 self.waitUntilSettled()
Jesse Keatingd96e5882017-01-19 13:55:50 -0800258 # We should have a status container for the head sha
Jesse Keating1f7ebe92017-06-12 17:21:00 -0700259 statuses = self.fake_github.statuses[project][A.head_sha]
260 self.assertIn(A.head_sha, self.fake_github.statuses[project].keys())
Jesse Keatingd96e5882017-01-19 13:55:50 -0800261 # We should only have one status for the head sha
Jesse Keating1f7ebe92017-06-12 17:21:00 -0700262 self.assertEqual(1, len(statuses))
263 check_status = statuses[0]
Jan Hrubanddeb95a2017-01-03 15:12:41 +0100264 check_url = ('http://zuul.example.com/status/#%s,%s' %
265 (A.number, A.head_sha))
Jamie Lennox18bc7ed2017-05-10 10:37:55 +1000266 self.assertEqual('tenant-one/check', check_status['context'])
Jan Hrubane252a732017-01-03 15:03:09 +0100267 self.assertEqual('Standard check', check_status['description'])
268 self.assertEqual('pending', check_status['state'])
Jan Hrubanddeb95a2017-01-03 15:12:41 +0100269 self.assertEqual(check_url, check_status['url'])
Jan Hruban37615e52015-11-19 14:30:49 +0100270 self.assertEqual(0, len(A.comments))
Jan Hrubane252a732017-01-03 15:03:09 +0100271
272 self.executor_server.hold_jobs_in_build = False
273 self.executor_server.release()
274 self.waitUntilSettled()
Jesse Keatingd96e5882017-01-19 13:55:50 -0800275 # We should only have two statuses for the head sha
Jesse Keating1f7ebe92017-06-12 17:21:00 -0700276 statuses = self.fake_github.statuses[project][A.head_sha]
277 self.assertEqual(2, len(statuses))
278 check_status = statuses[0]
Jesse Keatingd96e5882017-01-19 13:55:50 -0800279 check_url = ('http://zuul.example.com/status/#%s,%s' %
280 (A.number, A.head_sha))
Jamie Lennox18bc7ed2017-05-10 10:37:55 +1000281 self.assertEqual('tenant-one/check', check_status['context'])
Jan Hrubane252a732017-01-03 15:03:09 +0100282 self.assertEqual('success', check_status['state'])
Jan Hrubanddeb95a2017-01-03 15:12:41 +0100283 self.assertEqual(check_url, check_status['url'])
Jan Hruban37615e52015-11-19 14:30:49 +0100284 self.assertEqual(1, len(A.comments))
285 self.assertThat(A.comments[0],
Jan Hrubane252a732017-01-03 15:03:09 +0100286 MatchesRegex('.*Build succeeded.*', re.DOTALL))
287
288 # pipeline does not report any status but does comment
289 self.executor_server.hold_jobs_in_build = True
290 self.fake_github.emitEvent(
Jan Hruban37615e52015-11-19 14:30:49 +0100291 A.getCommentAddedEvent('reporting check'))
Jan Hrubane252a732017-01-03 15:03:09 +0100292 self.waitUntilSettled()
Jesse Keating1f7ebe92017-06-12 17:21:00 -0700293 statuses = self.fake_github.statuses[project][A.head_sha]
294 self.assertEqual(2, len(statuses))
Jan Hrubane252a732017-01-03 15:03:09 +0100295 # comments increased by one for the start message
Jan Hruban37615e52015-11-19 14:30:49 +0100296 self.assertEqual(2, len(A.comments))
297 self.assertThat(A.comments[1],
Jan Hrubane252a732017-01-03 15:03:09 +0100298 MatchesRegex('.*Starting reporting jobs.*', re.DOTALL))
299 self.executor_server.hold_jobs_in_build = False
300 self.executor_server.release()
301 self.waitUntilSettled()
Jesse Keatingd96e5882017-01-19 13:55:50 -0800302 # pipeline reports success status
Jesse Keating1f7ebe92017-06-12 17:21:00 -0700303 statuses = self.fake_github.statuses[project][A.head_sha]
304 self.assertEqual(3, len(statuses))
305 report_status = statuses[0]
Jamie Lennox18bc7ed2017-05-10 10:37:55 +1000306 self.assertEqual('tenant-one/reporting', report_status['context'])
Jesse Keatingd96e5882017-01-19 13:55:50 -0800307 self.assertEqual('success', report_status['state'])
Jan Hruban37615e52015-11-19 14:30:49 +0100308 self.assertEqual(2, len(A.comments))
Jamie Lennox3f16de52017-05-09 14:24:11 +1000309
310 base = 'http://logs.example.com/tenant-one/reporting/%s/%s/' % (
311 A.project, A.number)
312
313 # Deconstructing the URL because we don't save the BuildSet UUID
314 # anywhere to do a direct comparison and doing regexp matches on a full
315 # URL is painful.
316
317 # The first part of the URL matches the easy base string
318 self.assertThat(report_status['url'], StartsWith(base))
319
320 # The rest of the URL is a UUID and a trailing slash.
321 self.assertThat(report_status['url'][len(base):],
322 MatchesRegex('^[a-fA-F0-9]{32}\/$'))
Jan Hruban49bff072015-11-03 11:45:46 +0100323
Jesse Keating08dab8f2017-06-21 12:59:23 +0100324 @simple_layout('layouts/reporting-github.yaml', driver='github')
325 def test_push_reporting(self):
326 project = 'org/project2'
327 # pipeline reports pull status both on start and success
328 self.executor_server.hold_jobs_in_build = True
329 pevent = self.fake_github.getPushEvent(project=project,
330 ref='refs/heads/master')
331
332 self.fake_github.emitEvent(pevent)
333 self.waitUntilSettled()
334
335 # there should only be one report, a status
336 self.assertEqual(1, len(self.fake_github.reports))
337 # Verify the user/context/state of the status
338 status = ('zuul', 'tenant-one/push-reporting', 'pending')
339 self.assertEqual(status, self.fake_github.reports[0][-1])
340
341 # free the executor, allow the build to finish
342 self.executor_server.hold_jobs_in_build = False
343 self.executor_server.release()
344 self.waitUntilSettled()
345
346 # Now there should be a second report, the success of the build
347 self.assertEqual(2, len(self.fake_github.reports))
348 # Verify the user/context/state of the status
349 status = ('zuul', 'tenant-one/push-reporting', 'success')
350 self.assertEqual(status, self.fake_github.reports[-1][-1])
351
352 # now make a PR which should also comment
353 self.executor_server.hold_jobs_in_build = True
354 A = self.fake_github.openFakePullRequest(project, 'master', 'A')
355 self.fake_github.emitEvent(A.getPullRequestOpenedEvent())
356 self.waitUntilSettled()
357
358 # Now there should be a four reports, a new comment
359 # and status
360 self.assertEqual(4, len(self.fake_github.reports))
361 self.executor_server.release()
362 self.waitUntilSettled()
363
Jan Hruban49bff072015-11-03 11:45:46 +0100364 @simple_layout('layouts/merging-github.yaml', driver='github')
365 def test_report_pull_merge(self):
366 # pipeline merges the pull request on success
Jan Hruban3b415922016-02-03 13:10:22 +0100367 A = self.fake_github.openFakePullRequest('org/project', 'master',
368 'PR title')
Jan Hruban49bff072015-11-03 11:45:46 +0100369 self.fake_github.emitEvent(A.getCommentAddedEvent('merge me'))
370 self.waitUntilSettled()
371 self.assertTrue(A.is_merged)
Jan Hruban3b415922016-02-03 13:10:22 +0100372 self.assertThat(A.merge_message,
373 MatchesRegex('.*PR title.*Reviewed-by.*', re.DOTALL))
Jan Hruban49bff072015-11-03 11:45:46 +0100374
375 # pipeline merges the pull request on success after failure
376 self.fake_github.merge_failure = True
Jan Hruban37615e52015-11-19 14:30:49 +0100377 B = self.fake_github.openFakePullRequest('org/project', 'master', 'B')
Jan Hruban49bff072015-11-03 11:45:46 +0100378 self.fake_github.emitEvent(B.getCommentAddedEvent('merge me'))
379 self.waitUntilSettled()
380 self.assertFalse(B.is_merged)
381 self.fake_github.merge_failure = False
382
383 # pipeline merges the pull request on second run of merge
384 # first merge failed on 405 Method Not Allowed error
385 self.fake_github.merge_not_allowed_count = 1
Jan Hruban37615e52015-11-19 14:30:49 +0100386 C = self.fake_github.openFakePullRequest('org/project', 'master', 'C')
Jan Hruban49bff072015-11-03 11:45:46 +0100387 self.fake_github.emitEvent(C.getCommentAddedEvent('merge me'))
388 self.waitUntilSettled()
389 self.assertTrue(C.is_merged)
390
391 # pipeline does not merge the pull request
392 # merge failed on 405 Method Not Allowed error - twice
393 self.fake_github.merge_not_allowed_count = 2
Jan Hruban37615e52015-11-19 14:30:49 +0100394 D = self.fake_github.openFakePullRequest('org/project', 'master', 'D')
Jan Hruban49bff072015-11-03 11:45:46 +0100395 self.fake_github.emitEvent(D.getCommentAddedEvent('merge me'))
396 self.waitUntilSettled()
397 self.assertFalse(D.is_merged)
Adam Gandelman62198cb2017-02-14 16:11:02 -0800398 self.assertEqual(len(D.comments), 1)
399 self.assertEqual(D.comments[0], 'Merge failed')
Jan Hruban37615e52015-11-19 14:30:49 +0100400
401 @simple_layout('layouts/dependent-github.yaml', driver='github')
402 def test_parallel_changes(self):
403 "Test that changes are tested in parallel and merged in series"
404
405 self.executor_server.hold_jobs_in_build = True
406 A = self.fake_github.openFakePullRequest('org/project', 'master', 'A')
407 B = self.fake_github.openFakePullRequest('org/project', 'master', 'B')
408 C = self.fake_github.openFakePullRequest('org/project', 'master', 'C')
409
410 self.fake_github.emitEvent(A.addLabel('merge'))
411 self.fake_github.emitEvent(B.addLabel('merge'))
412 self.fake_github.emitEvent(C.addLabel('merge'))
413
414 self.waitUntilSettled()
415 self.assertEqual(len(self.builds), 1)
416 self.assertEqual(self.builds[0].name, 'project-merge')
417 self.assertTrue(self.builds[0].hasChanges(A))
418
419 self.executor_server.release('.*-merge')
420 self.waitUntilSettled()
421 self.assertEqual(len(self.builds), 3)
422 self.assertEqual(self.builds[0].name, 'project-test1')
423 self.assertTrue(self.builds[0].hasChanges(A))
424 self.assertEqual(self.builds[1].name, 'project-test2')
425 self.assertTrue(self.builds[1].hasChanges(A))
426 self.assertEqual(self.builds[2].name, 'project-merge')
427 self.assertTrue(self.builds[2].hasChanges(A, B))
428
429 self.executor_server.release('.*-merge')
430 self.waitUntilSettled()
431 self.assertEqual(len(self.builds), 5)
432 self.assertEqual(self.builds[0].name, 'project-test1')
433 self.assertTrue(self.builds[0].hasChanges(A))
434 self.assertEqual(self.builds[1].name, 'project-test2')
435 self.assertTrue(self.builds[1].hasChanges(A))
436
437 self.assertEqual(self.builds[2].name, 'project-test1')
438 self.assertTrue(self.builds[2].hasChanges(A))
439 self.assertEqual(self.builds[3].name, 'project-test2')
440 self.assertTrue(self.builds[3].hasChanges(A, B))
441
442 self.assertEqual(self.builds[4].name, 'project-merge')
443 self.assertTrue(self.builds[4].hasChanges(A, B, C))
444
445 self.executor_server.release('.*-merge')
446 self.waitUntilSettled()
447 self.assertEqual(len(self.builds), 6)
448 self.assertEqual(self.builds[0].name, 'project-test1')
449 self.assertTrue(self.builds[0].hasChanges(A))
450 self.assertEqual(self.builds[1].name, 'project-test2')
451 self.assertTrue(self.builds[1].hasChanges(A))
452
453 self.assertEqual(self.builds[2].name, 'project-test1')
454 self.assertTrue(self.builds[2].hasChanges(A, B))
455 self.assertEqual(self.builds[3].name, 'project-test2')
456 self.assertTrue(self.builds[3].hasChanges(A, B))
457
458 self.assertEqual(self.builds[4].name, 'project-test1')
459 self.assertTrue(self.builds[4].hasChanges(A, B, C))
460 self.assertEqual(self.builds[5].name, 'project-test2')
461 self.assertTrue(self.builds[5].hasChanges(A, B, C))
462
463 all_builds = self.builds[:]
464 self.release(all_builds[2])
465 self.release(all_builds[3])
466 self.waitUntilSettled()
467 self.assertFalse(A.is_merged)
468 self.assertFalse(B.is_merged)
469 self.assertFalse(C.is_merged)
470
471 self.release(all_builds[0])
472 self.release(all_builds[1])
473 self.waitUntilSettled()
474 self.assertTrue(A.is_merged)
475 self.assertTrue(B.is_merged)
476 self.assertFalse(C.is_merged)
477
478 self.executor_server.hold_jobs_in_build = False
479 self.executor_server.release()
480 self.waitUntilSettled()
481 self.assertEqual(len(self.builds), 0)
482 self.assertEqual(len(self.history), 9)
483 self.assertTrue(C.is_merged)
484
485 self.assertNotIn('merge', A.labels)
486 self.assertNotIn('merge', B.labels)
487 self.assertNotIn('merge', C.labels)
488
489 @simple_layout('layouts/dependent-github.yaml', driver='github')
490 def test_failed_changes(self):
491 "Test that a change behind a failed change is retested"
492 self.executor_server.hold_jobs_in_build = True
493
494 A = self.fake_github.openFakePullRequest('org/project', 'master', 'A')
495 B = self.fake_github.openFakePullRequest('org/project', 'master', 'B')
496
497 self.executor_server.failJob('project-test1', A)
498
499 self.fake_github.emitEvent(A.addLabel('merge'))
500 self.fake_github.emitEvent(B.addLabel('merge'))
501 self.waitUntilSettled()
502
503 self.executor_server.release('.*-merge')
504 self.waitUntilSettled()
505
506 self.executor_server.hold_jobs_in_build = False
507 self.executor_server.release()
508
509 self.waitUntilSettled()
510 # It's certain that the merge job for change 2 will run, but
511 # the test1 and test2 jobs may or may not run.
512 self.assertTrue(len(self.history) > 6)
513 self.assertFalse(A.is_merged)
514 self.assertTrue(B.is_merged)
515 self.assertNotIn('merge', A.labels)
516 self.assertNotIn('merge', B.labels)
517
518 @simple_layout('layouts/dependent-github.yaml', driver='github')
519 def test_failed_change_at_head(self):
520 "Test that if a change at the head fails, jobs behind it are canceled"
521
522 self.executor_server.hold_jobs_in_build = True
523 A = self.fake_github.openFakePullRequest('org/project', 'master', 'A')
524 B = self.fake_github.openFakePullRequest('org/project', 'master', 'B')
525 C = self.fake_github.openFakePullRequest('org/project', 'master', 'C')
526
527 self.executor_server.failJob('project-test1', A)
528
529 self.fake_github.emitEvent(A.addLabel('merge'))
530 self.fake_github.emitEvent(B.addLabel('merge'))
531 self.fake_github.emitEvent(C.addLabel('merge'))
532
533 self.waitUntilSettled()
534
535 self.assertEqual(len(self.builds), 1)
536 self.assertEqual(self.builds[0].name, 'project-merge')
537 self.assertTrue(self.builds[0].hasChanges(A))
538
539 self.executor_server.release('.*-merge')
540 self.waitUntilSettled()
541 self.executor_server.release('.*-merge')
542 self.waitUntilSettled()
543 self.executor_server.release('.*-merge')
544 self.waitUntilSettled()
545
546 self.assertEqual(len(self.builds), 6)
547 self.assertEqual(self.builds[0].name, 'project-test1')
548 self.assertEqual(self.builds[1].name, 'project-test2')
549 self.assertEqual(self.builds[2].name, 'project-test1')
550 self.assertEqual(self.builds[3].name, 'project-test2')
551 self.assertEqual(self.builds[4].name, 'project-test1')
552 self.assertEqual(self.builds[5].name, 'project-test2')
553
554 self.release(self.builds[0])
555 self.waitUntilSettled()
556
557 # project-test2, project-merge for B
558 self.assertEqual(len(self.builds), 2)
559 self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 4)
560
561 self.executor_server.hold_jobs_in_build = False
562 self.executor_server.release()
563 self.waitUntilSettled()
564
565 self.assertEqual(len(self.builds), 0)
566 self.assertEqual(len(self.history), 15)
567 self.assertFalse(A.is_merged)
568 self.assertTrue(B.is_merged)
569 self.assertTrue(C.is_merged)
570 self.assertNotIn('merge', A.labels)
571 self.assertNotIn('merge', B.labels)
572 self.assertNotIn('merge', C.labels)
Jesse Keating71a47ff2017-06-06 11:36:43 -0700573
574 @simple_layout('layouts/basic-github.yaml', driver='github')
575 def test_push_event_reconfigure(self):
576 pevent = self.fake_github.getPushEvent(project='common-config',
577 ref='refs/heads/master',
578 modified_files=['zuul.yaml'])
579
580 # record previous tenant reconfiguration time, which may not be set
581 old = self.sched.tenant_last_reconfigured.get('tenant-one', 0)
582 time.sleep(1)
583 self.fake_github.emitEvent(pevent)
584 self.waitUntilSettled()
585 new = self.sched.tenant_last_reconfigured.get('tenant-one', 0)
586 # New timestamp should be greater than the old timestamp
587 self.assertLess(old, new)
Tristan Cacqueray2bafb1f2017-06-12 07:10:26 +0000588
589 @simple_layout('layouts/basic-github.yaml', driver='github')
590 def test_ping_event(self):
591 # Test valid ping
592 pevent = {'repository': {'full_name': 'org/project'}}
593 req = self.fake_github.emitEvent(('ping', pevent))
594 self.assertEqual(req.status, 200, "Ping event didn't succeed")
595
596 # Test invalid ping
597 pevent = {'repository': {'full_name': 'unknown-project'}}
598 self.assertRaises(
599 urllib.error.HTTPError,
600 self.fake_github.emitEvent,
601 ('ping', pevent),
602 )