blob: 875a9d7d0adf35bd4e69555be096f6bc11e28dd7 [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
James E. Blair21037782017-07-19 11:56:55 -070015import os
Jan Hrubane252a732017-01-03 15:03:09 +010016import re
Jamie Lennox3f16de52017-05-09 14:24:11 +100017from testtools.matchers import MatchesRegex, StartsWith
Tristan Cacqueray2bafb1f2017-06-12 07:10:26 +000018import urllib
Jan Hruban324ca5b2015-11-05 19:28:54 +010019import time
Gregory Haynes4fc12542015-04-22 20:38:06 -070020
James E. Blair21037782017-07-19 11:56:55 -070021import git
22
Wayne1a78c612015-06-11 17:14:13 -070023from tests.base import ZuulTestCase, simple_layout, random_sha1
Gregory Haynes4fc12542015-04-22 20:38:06 -070024
Gregory Haynes4fc12542015-04-22 20:38:06 -070025
26class TestGithubDriver(ZuulTestCase):
27 config_file = 'zuul-github-driver.conf'
28
29 @simple_layout('layouts/basic-github.yaml', driver='github')
30 def test_pull_event(self):
31 self.executor_server.hold_jobs_in_build = True
32
Jan Hruban37615e52015-11-19 14:30:49 +010033 A = self.fake_github.openFakePullRequest('org/project', 'master', 'A')
34 self.fake_github.emitEvent(A.getPullRequestOpenedEvent())
Gregory Haynes4fc12542015-04-22 20:38:06 -070035 self.waitUntilSettled()
36
37 build_params = self.builds[0].parameters
38 self.assertEqual('master', build_params['ZUUL_BRANCH'])
Gregory Haynes4fc12542015-04-22 20:38:06 -070039
40 self.executor_server.hold_jobs_in_build = False
41 self.executor_server.release()
42 self.waitUntilSettled()
43
44 self.assertEqual('SUCCESS',
45 self.getJobFromHistory('project-test1').result)
46 self.assertEqual('SUCCESS',
47 self.getJobFromHistory('project-test2').result)
48
49 job = self.getJobFromHistory('project-test2')
Monty Taylord13bc362017-06-30 13:11:37 -050050 zuulvars = job.parameters['zuul']
James E. Blaire3db2952017-07-21 15:03:36 -070051 self.assertEqual(str(A.number), zuulvars['change'])
52 self.assertEqual(str(A.head_sha), zuulvars['patchset'])
Jan Hruban37615e52015-11-19 14:30:49 +010053 self.assertEqual(1, len(A.comments))
Jan Hruband4edee82015-12-16 12:49:51 +010054 self.assertEqual(2, len(self.history))
55
56 # test_pull_unmatched_branch_event(self):
57 self.create_branch('org/project', 'unmatched_branch')
58 B = self.fake_github.openFakePullRequest(
59 'org/project', 'unmatched_branch', 'B')
60 self.fake_github.emitEvent(B.getPullRequestOpenedEvent())
61 self.waitUntilSettled()
62
63 self.assertEqual(2, len(self.history))
Wayne1a78c612015-06-11 17:14:13 -070064
Jan Hruban570d01c2016-03-10 21:51:32 +010065 @simple_layout('layouts/files-github.yaml', driver='github')
66 def test_pull_matched_file_event(self):
67 A = self.fake_github.openFakePullRequest(
68 'org/project', 'master', 'A',
69 files=['random.txt', 'build-requires'])
70 self.fake_github.emitEvent(A.getPullRequestOpenedEvent())
71 self.waitUntilSettled()
72 self.assertEqual(1, len(self.history))
73
74 # test_pull_unmatched_file_event
75 B = self.fake_github.openFakePullRequest('org/project', 'master', 'B',
76 files=['random.txt'])
77 self.fake_github.emitEvent(B.getPullRequestOpenedEvent())
78 self.waitUntilSettled()
79 self.assertEqual(1, len(self.history))
80
Jan Hrubanc7ab1602015-10-14 15:29:33 +020081 @simple_layout('layouts/basic-github.yaml', driver='github')
82 def test_comment_event(self):
Jan Hruban37615e52015-11-19 14:30:49 +010083 A = self.fake_github.openFakePullRequest('org/project', 'master', 'A')
84 self.fake_github.emitEvent(A.getCommentAddedEvent('test me'))
Jan Hrubanc7ab1602015-10-14 15:29:33 +020085 self.waitUntilSettled()
86 self.assertEqual(2, len(self.history))
87
88 # Test an unmatched comment, history should remain the same
Jan Hruban37615e52015-11-19 14:30:49 +010089 B = self.fake_github.openFakePullRequest('org/project', 'master', 'B')
90 self.fake_github.emitEvent(B.getCommentAddedEvent('casual comment'))
Jan Hrubanc7ab1602015-10-14 15:29:33 +020091 self.waitUntilSettled()
92 self.assertEqual(2, len(self.history))
93
Wayne1a78c612015-06-11 17:14:13 -070094 @simple_layout('layouts/push-tag-github.yaml', driver='github')
95 def test_tag_event(self):
96 self.executor_server.hold_jobs_in_build = True
97
James E. Blair21037782017-07-19 11:56:55 -070098 self.create_branch('org/project', 'tagbranch')
99 files = {'README.txt': 'test'}
100 self.addCommitToRepo('org/project', 'test tag',
101 files, branch='tagbranch', tag='newtag')
102 path = os.path.join(self.upstream_root, 'org/project')
103 repo = git.Repo(path)
104 tag = repo.tags['newtag']
105 sha = tag.commit.hexsha
106 del repo
107
Wayne1a78c612015-06-11 17:14:13 -0700108 self.fake_github.emitEvent(
109 self.fake_github.getPushEvent('org/project', 'refs/tags/newtag',
110 new_rev=sha))
111 self.waitUntilSettled()
112
113 build_params = self.builds[0].parameters
James E. Blaira438c172017-07-21 14:54:42 -0700114 self.assertEqual('refs/tags/newtag', build_params['zuul']['ref'])
Wayne1a78c612015-06-11 17:14:13 -0700115 self.assertEqual('00000000000000000000000000000000',
James E. Blaired8b0012017-07-21 14:49:29 -0700116 build_params['zuul']['oldrev'])
117 self.assertEqual(sha, build_params['zuul']['newrev'])
Wayne1a78c612015-06-11 17:14:13 -0700118
119 self.executor_server.hold_jobs_in_build = False
120 self.executor_server.release()
121 self.waitUntilSettled()
122
123 self.assertEqual('SUCCESS',
124 self.getJobFromHistory('project-tag').result)
125
126 @simple_layout('layouts/push-tag-github.yaml', driver='github')
127 def test_push_event(self):
128 self.executor_server.hold_jobs_in_build = True
129
130 old_sha = random_sha1()
131 new_sha = random_sha1()
132 self.fake_github.emitEvent(
133 self.fake_github.getPushEvent('org/project', 'refs/heads/master',
134 old_sha, new_sha))
135 self.waitUntilSettled()
136
137 build_params = self.builds[0].parameters
James E. Blaira438c172017-07-21 14:54:42 -0700138 self.assertEqual('refs/heads/master', build_params['zuul']['ref'])
James E. Blaired8b0012017-07-21 14:49:29 -0700139 self.assertEqual(old_sha, build_params['zuul']['oldrev'])
140 self.assertEqual(new_sha, build_params['zuul']['newrev'])
Wayne1a78c612015-06-11 17:14:13 -0700141
142 self.executor_server.hold_jobs_in_build = False
143 self.executor_server.release()
144 self.waitUntilSettled()
145
146 self.assertEqual('SUCCESS',
147 self.getJobFromHistory('project-post').result)
Jan Hruband4edee82015-12-16 12:49:51 +0100148 self.assertEqual(1, len(self.history))
149
150 # test unmatched push event
151 old_sha = random_sha1()
152 new_sha = random_sha1()
153 self.fake_github.emitEvent(
154 self.fake_github.getPushEvent('org/project',
155 'refs/heads/unmatched_branch',
156 old_sha, new_sha))
157 self.waitUntilSettled()
158
159 self.assertEqual(1, len(self.history))
Jan Hruban6d53c5e2015-10-24 03:03:34 +0200160
Jan Hruban16ad31f2015-11-07 14:39:07 +0100161 @simple_layout('layouts/labeling-github.yaml', driver='github')
162 def test_labels(self):
Jan Hruban37615e52015-11-19 14:30:49 +0100163 A = self.fake_github.openFakePullRequest('org/project', 'master', 'A')
Jan Hruban16ad31f2015-11-07 14:39:07 +0100164 self.fake_github.emitEvent(A.addLabel('test'))
165 self.waitUntilSettled()
166 self.assertEqual(1, len(self.history))
167 self.assertEqual('project-labels', self.history[0].name)
168 self.assertEqual(['tests passed'], A.labels)
169
170 # test label removed
Jan Hruban37615e52015-11-19 14:30:49 +0100171 B = self.fake_github.openFakePullRequest('org/project', 'master', 'B')
Jan Hruban16ad31f2015-11-07 14:39:07 +0100172 B.addLabel('do not test')
173 self.fake_github.emitEvent(B.removeLabel('do not test'))
174 self.waitUntilSettled()
175 self.assertEqual(2, len(self.history))
176 self.assertEqual('project-labels', self.history[1].name)
177 self.assertEqual(['tests passed'], B.labels)
178
179 # test unmatched label
Jan Hruban37615e52015-11-19 14:30:49 +0100180 C = self.fake_github.openFakePullRequest('org/project', 'master', 'C')
Jan Hruban16ad31f2015-11-07 14:39:07 +0100181 self.fake_github.emitEvent(C.addLabel('other label'))
182 self.waitUntilSettled()
183 self.assertEqual(2, len(self.history))
184 self.assertEqual(['other label'], C.labels)
185
Jesse Keating5c05a9f2017-01-12 14:44:58 -0800186 @simple_layout('layouts/reviews-github.yaml', driver='github')
187 def test_review_event(self):
188 A = self.fake_github.openFakePullRequest('org/project', 'master', 'A')
189 self.fake_github.emitEvent(A.getReviewAddedEvent('approve'))
190 self.waitUntilSettled()
191 self.assertEqual(1, len(self.history))
192 self.assertEqual('project-reviews', self.history[0].name)
193 self.assertEqual(['tests passed'], A.labels)
194
195 # test_review_unmatched_event
196 B = self.fake_github.openFakePullRequest('org/project', 'master', 'B')
197 self.fake_github.emitEvent(B.getReviewAddedEvent('comment'))
198 self.waitUntilSettled()
199 self.assertEqual(1, len(self.history))
200
Jan Hruban324ca5b2015-11-05 19:28:54 +0100201 @simple_layout('layouts/dequeue-github.yaml', driver='github')
202 def test_dequeue_pull_synchronized(self):
203 self.executor_server.hold_jobs_in_build = True
204
Jan Hruban37615e52015-11-19 14:30:49 +0100205 A = self.fake_github.openFakePullRequest(
206 'org/one-job-project', 'master', 'A')
207 self.fake_github.emitEvent(A.getPullRequestOpenedEvent())
Jan Hruban324ca5b2015-11-05 19:28:54 +0100208 self.waitUntilSettled()
209
210 # event update stamp has resolution one second, wait so the latter
211 # one has newer timestamp
212 time.sleep(1)
Jan Hruban37615e52015-11-19 14:30:49 +0100213 A.addCommit()
214 self.fake_github.emitEvent(A.getPullRequestSynchronizeEvent())
Jan Hruban324ca5b2015-11-05 19:28:54 +0100215 self.waitUntilSettled()
216
217 self.executor_server.hold_jobs_in_build = False
218 self.executor_server.release()
219 self.waitUntilSettled()
220
221 self.assertEqual(2, len(self.history))
222 self.assertEqual(1, self.countJobResults(self.history, 'ABORTED'))
223
224 @simple_layout('layouts/dequeue-github.yaml', driver='github')
225 def test_dequeue_pull_abandoned(self):
226 self.executor_server.hold_jobs_in_build = True
227
Jan Hruban37615e52015-11-19 14:30:49 +0100228 A = self.fake_github.openFakePullRequest(
229 'org/one-job-project', 'master', 'A')
230 self.fake_github.emitEvent(A.getPullRequestOpenedEvent())
Jan Hruban324ca5b2015-11-05 19:28:54 +0100231 self.waitUntilSettled()
Jan Hruban37615e52015-11-19 14:30:49 +0100232 self.fake_github.emitEvent(A.getPullRequestClosedEvent())
Jan Hruban324ca5b2015-11-05 19:28:54 +0100233 self.waitUntilSettled()
234
235 self.executor_server.hold_jobs_in_build = False
236 self.executor_server.release()
237 self.waitUntilSettled()
238
239 self.assertEqual(1, len(self.history))
240 self.assertEqual(1, self.countJobResults(self.history, 'ABORTED'))
241
Jan Hruban6d53c5e2015-10-24 03:03:34 +0200242 @simple_layout('layouts/basic-github.yaml', driver='github')
243 def test_git_https_url(self):
244 """Test that git_ssh option gives git url with ssh"""
245 url = self.fake_github.real_getGitUrl('org/project')
246 self.assertEqual('https://github.com/org/project', url)
247
248 @simple_layout('layouts/basic-github.yaml', driver='github')
249 def test_git_ssh_url(self):
250 """Test that git_ssh option gives git url with ssh"""
251 url = self.fake_github_ssh.real_getGitUrl('org/project')
252 self.assertEqual('ssh://git@github.com/org/project.git', url)
Jan Hrubane252a732017-01-03 15:03:09 +0100253
Jesse Keatingbe4ef8a2016-12-06 11:29:13 -0800254 @simple_layout('layouts/basic-github.yaml', driver='github')
255 def test_git_enterprise_url(self):
256 """Test that git_url option gives git url with proper host"""
257 url = self.fake_github_ent.real_getGitUrl('org/project')
258 self.assertEqual('ssh://git@github.enterprise.io/org/project.git', url)
259
Jan Hrubane252a732017-01-03 15:03:09 +0100260 @simple_layout('layouts/reporting-github.yaml', driver='github')
261 def test_reporting(self):
Jesse Keating1f7ebe92017-06-12 17:21:00 -0700262 project = 'org/project'
Jan Hrubane252a732017-01-03 15:03:09 +0100263 # pipeline reports pull status both on start and success
264 self.executor_server.hold_jobs_in_build = True
Jesse Keating1f7ebe92017-06-12 17:21:00 -0700265 A = self.fake_github.openFakePullRequest(project, 'master', 'A')
Jan Hruban37615e52015-11-19 14:30:49 +0100266 self.fake_github.emitEvent(A.getPullRequestOpenedEvent())
Jan Hrubane252a732017-01-03 15:03:09 +0100267 self.waitUntilSettled()
Jesse Keatingd96e5882017-01-19 13:55:50 -0800268 # We should have a status container for the head sha
Jesse Keating1f7ebe92017-06-12 17:21:00 -0700269 statuses = self.fake_github.statuses[project][A.head_sha]
270 self.assertIn(A.head_sha, self.fake_github.statuses[project].keys())
Jesse Keatingd96e5882017-01-19 13:55:50 -0800271 # We should only have one status for the head sha
Jesse Keating1f7ebe92017-06-12 17:21:00 -0700272 self.assertEqual(1, len(statuses))
273 check_status = statuses[0]
Jan Hrubanddeb95a2017-01-03 15:12:41 +0100274 check_url = ('http://zuul.example.com/status/#%s,%s' %
275 (A.number, A.head_sha))
Jamie Lennox18bc7ed2017-05-10 10:37:55 +1000276 self.assertEqual('tenant-one/check', check_status['context'])
Jan Hrubane252a732017-01-03 15:03:09 +0100277 self.assertEqual('Standard check', check_status['description'])
278 self.assertEqual('pending', check_status['state'])
Jan Hrubanddeb95a2017-01-03 15:12:41 +0100279 self.assertEqual(check_url, check_status['url'])
Jan Hruban37615e52015-11-19 14:30:49 +0100280 self.assertEqual(0, len(A.comments))
Jan Hrubane252a732017-01-03 15:03:09 +0100281
282 self.executor_server.hold_jobs_in_build = False
283 self.executor_server.release()
284 self.waitUntilSettled()
Jesse Keatingd96e5882017-01-19 13:55:50 -0800285 # We should only have two statuses for the head sha
Jesse Keating1f7ebe92017-06-12 17:21:00 -0700286 statuses = self.fake_github.statuses[project][A.head_sha]
287 self.assertEqual(2, len(statuses))
288 check_status = statuses[0]
Jesse Keatingd96e5882017-01-19 13:55:50 -0800289 check_url = ('http://zuul.example.com/status/#%s,%s' %
290 (A.number, A.head_sha))
Jamie Lennox18bc7ed2017-05-10 10:37:55 +1000291 self.assertEqual('tenant-one/check', check_status['context'])
Jan Hrubane252a732017-01-03 15:03:09 +0100292 self.assertEqual('success', check_status['state'])
Jan Hrubanddeb95a2017-01-03 15:12:41 +0100293 self.assertEqual(check_url, check_status['url'])
Jan Hruban37615e52015-11-19 14:30:49 +0100294 self.assertEqual(1, len(A.comments))
295 self.assertThat(A.comments[0],
Jan Hrubane252a732017-01-03 15:03:09 +0100296 MatchesRegex('.*Build succeeded.*', re.DOTALL))
297
298 # pipeline does not report any status but does comment
299 self.executor_server.hold_jobs_in_build = True
300 self.fake_github.emitEvent(
Jan Hruban37615e52015-11-19 14:30:49 +0100301 A.getCommentAddedEvent('reporting check'))
Jan Hrubane252a732017-01-03 15:03:09 +0100302 self.waitUntilSettled()
Jesse Keating1f7ebe92017-06-12 17:21:00 -0700303 statuses = self.fake_github.statuses[project][A.head_sha]
304 self.assertEqual(2, len(statuses))
Jan Hrubane252a732017-01-03 15:03:09 +0100305 # comments increased by one for the start message
Jan Hruban37615e52015-11-19 14:30:49 +0100306 self.assertEqual(2, len(A.comments))
307 self.assertThat(A.comments[1],
Jan Hrubane252a732017-01-03 15:03:09 +0100308 MatchesRegex('.*Starting reporting jobs.*', re.DOTALL))
309 self.executor_server.hold_jobs_in_build = False
310 self.executor_server.release()
311 self.waitUntilSettled()
Jesse Keatingd96e5882017-01-19 13:55:50 -0800312 # pipeline reports success status
Jesse Keating1f7ebe92017-06-12 17:21:00 -0700313 statuses = self.fake_github.statuses[project][A.head_sha]
314 self.assertEqual(3, len(statuses))
315 report_status = statuses[0]
Jamie Lennox18bc7ed2017-05-10 10:37:55 +1000316 self.assertEqual('tenant-one/reporting', report_status['context'])
Jesse Keatingd96e5882017-01-19 13:55:50 -0800317 self.assertEqual('success', report_status['state'])
Jan Hruban37615e52015-11-19 14:30:49 +0100318 self.assertEqual(2, len(A.comments))
Jamie Lennox3f16de52017-05-09 14:24:11 +1000319
320 base = 'http://logs.example.com/tenant-one/reporting/%s/%s/' % (
321 A.project, A.number)
322
323 # Deconstructing the URL because we don't save the BuildSet UUID
324 # anywhere to do a direct comparison and doing regexp matches on a full
325 # URL is painful.
326
327 # The first part of the URL matches the easy base string
328 self.assertThat(report_status['url'], StartsWith(base))
329
330 # The rest of the URL is a UUID and a trailing slash.
331 self.assertThat(report_status['url'][len(base):],
332 MatchesRegex('^[a-fA-F0-9]{32}\/$'))
Jan Hruban49bff072015-11-03 11:45:46 +0100333
Jesse Keating08dab8f2017-06-21 12:59:23 +0100334 @simple_layout('layouts/reporting-github.yaml', driver='github')
335 def test_push_reporting(self):
336 project = 'org/project2'
337 # pipeline reports pull status both on start and success
338 self.executor_server.hold_jobs_in_build = True
339 pevent = self.fake_github.getPushEvent(project=project,
340 ref='refs/heads/master')
341
342 self.fake_github.emitEvent(pevent)
343 self.waitUntilSettled()
344
345 # there should only be one report, a status
346 self.assertEqual(1, len(self.fake_github.reports))
347 # Verify the user/context/state of the status
348 status = ('zuul', 'tenant-one/push-reporting', 'pending')
349 self.assertEqual(status, self.fake_github.reports[0][-1])
350
351 # free the executor, allow the build to finish
352 self.executor_server.hold_jobs_in_build = False
353 self.executor_server.release()
354 self.waitUntilSettled()
355
356 # Now there should be a second report, the success of the build
357 self.assertEqual(2, len(self.fake_github.reports))
358 # Verify the user/context/state of the status
359 status = ('zuul', 'tenant-one/push-reporting', 'success')
360 self.assertEqual(status, self.fake_github.reports[-1][-1])
361
362 # now make a PR which should also comment
363 self.executor_server.hold_jobs_in_build = True
364 A = self.fake_github.openFakePullRequest(project, 'master', 'A')
365 self.fake_github.emitEvent(A.getPullRequestOpenedEvent())
366 self.waitUntilSettled()
367
368 # Now there should be a four reports, a new comment
369 # and status
370 self.assertEqual(4, len(self.fake_github.reports))
371 self.executor_server.release()
372 self.waitUntilSettled()
373
Jan Hruban49bff072015-11-03 11:45:46 +0100374 @simple_layout('layouts/merging-github.yaml', driver='github')
375 def test_report_pull_merge(self):
376 # pipeline merges the pull request on success
Jan Hruban3b415922016-02-03 13:10:22 +0100377 A = self.fake_github.openFakePullRequest('org/project', 'master',
378 'PR title')
Jan Hruban49bff072015-11-03 11:45:46 +0100379 self.fake_github.emitEvent(A.getCommentAddedEvent('merge me'))
380 self.waitUntilSettled()
381 self.assertTrue(A.is_merged)
Jan Hruban3b415922016-02-03 13:10:22 +0100382 self.assertThat(A.merge_message,
383 MatchesRegex('.*PR title.*Reviewed-by.*', re.DOTALL))
Jan Hruban49bff072015-11-03 11:45:46 +0100384
385 # pipeline merges the pull request on success after failure
386 self.fake_github.merge_failure = True
Jan Hruban37615e52015-11-19 14:30:49 +0100387 B = self.fake_github.openFakePullRequest('org/project', 'master', 'B')
Jan Hruban49bff072015-11-03 11:45:46 +0100388 self.fake_github.emitEvent(B.getCommentAddedEvent('merge me'))
389 self.waitUntilSettled()
390 self.assertFalse(B.is_merged)
391 self.fake_github.merge_failure = False
392
393 # pipeline merges the pull request on second run of merge
394 # first merge failed on 405 Method Not Allowed error
395 self.fake_github.merge_not_allowed_count = 1
Jan Hruban37615e52015-11-19 14:30:49 +0100396 C = self.fake_github.openFakePullRequest('org/project', 'master', 'C')
Jan Hruban49bff072015-11-03 11:45:46 +0100397 self.fake_github.emitEvent(C.getCommentAddedEvent('merge me'))
398 self.waitUntilSettled()
399 self.assertTrue(C.is_merged)
400
401 # pipeline does not merge the pull request
402 # merge failed on 405 Method Not Allowed error - twice
403 self.fake_github.merge_not_allowed_count = 2
Jan Hruban37615e52015-11-19 14:30:49 +0100404 D = self.fake_github.openFakePullRequest('org/project', 'master', 'D')
Jan Hruban49bff072015-11-03 11:45:46 +0100405 self.fake_github.emitEvent(D.getCommentAddedEvent('merge me'))
406 self.waitUntilSettled()
407 self.assertFalse(D.is_merged)
Adam Gandelman62198cb2017-02-14 16:11:02 -0800408 self.assertEqual(len(D.comments), 1)
409 self.assertEqual(D.comments[0], 'Merge failed')
Jan Hruban37615e52015-11-19 14:30:49 +0100410
411 @simple_layout('layouts/dependent-github.yaml', driver='github')
412 def test_parallel_changes(self):
413 "Test that changes are tested in parallel and merged in series"
414
415 self.executor_server.hold_jobs_in_build = True
416 A = self.fake_github.openFakePullRequest('org/project', 'master', 'A')
417 B = self.fake_github.openFakePullRequest('org/project', 'master', 'B')
418 C = self.fake_github.openFakePullRequest('org/project', 'master', 'C')
419
420 self.fake_github.emitEvent(A.addLabel('merge'))
421 self.fake_github.emitEvent(B.addLabel('merge'))
422 self.fake_github.emitEvent(C.addLabel('merge'))
423
424 self.waitUntilSettled()
425 self.assertEqual(len(self.builds), 1)
426 self.assertEqual(self.builds[0].name, 'project-merge')
427 self.assertTrue(self.builds[0].hasChanges(A))
428
429 self.executor_server.release('.*-merge')
430 self.waitUntilSettled()
431 self.assertEqual(len(self.builds), 3)
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 self.assertEqual(self.builds[2].name, 'project-merge')
437 self.assertTrue(self.builds[2].hasChanges(A, B))
438
439 self.executor_server.release('.*-merge')
440 self.waitUntilSettled()
441 self.assertEqual(len(self.builds), 5)
442 self.assertEqual(self.builds[0].name, 'project-test1')
443 self.assertTrue(self.builds[0].hasChanges(A))
444 self.assertEqual(self.builds[1].name, 'project-test2')
445 self.assertTrue(self.builds[1].hasChanges(A))
446
447 self.assertEqual(self.builds[2].name, 'project-test1')
448 self.assertTrue(self.builds[2].hasChanges(A))
449 self.assertEqual(self.builds[3].name, 'project-test2')
450 self.assertTrue(self.builds[3].hasChanges(A, B))
451
452 self.assertEqual(self.builds[4].name, 'project-merge')
453 self.assertTrue(self.builds[4].hasChanges(A, B, C))
454
455 self.executor_server.release('.*-merge')
456 self.waitUntilSettled()
457 self.assertEqual(len(self.builds), 6)
458 self.assertEqual(self.builds[0].name, 'project-test1')
459 self.assertTrue(self.builds[0].hasChanges(A))
460 self.assertEqual(self.builds[1].name, 'project-test2')
461 self.assertTrue(self.builds[1].hasChanges(A))
462
463 self.assertEqual(self.builds[2].name, 'project-test1')
464 self.assertTrue(self.builds[2].hasChanges(A, B))
465 self.assertEqual(self.builds[3].name, 'project-test2')
466 self.assertTrue(self.builds[3].hasChanges(A, B))
467
468 self.assertEqual(self.builds[4].name, 'project-test1')
469 self.assertTrue(self.builds[4].hasChanges(A, B, C))
470 self.assertEqual(self.builds[5].name, 'project-test2')
471 self.assertTrue(self.builds[5].hasChanges(A, B, C))
472
473 all_builds = self.builds[:]
474 self.release(all_builds[2])
475 self.release(all_builds[3])
476 self.waitUntilSettled()
477 self.assertFalse(A.is_merged)
478 self.assertFalse(B.is_merged)
479 self.assertFalse(C.is_merged)
480
481 self.release(all_builds[0])
482 self.release(all_builds[1])
483 self.waitUntilSettled()
484 self.assertTrue(A.is_merged)
485 self.assertTrue(B.is_merged)
486 self.assertFalse(C.is_merged)
487
488 self.executor_server.hold_jobs_in_build = False
489 self.executor_server.release()
490 self.waitUntilSettled()
491 self.assertEqual(len(self.builds), 0)
492 self.assertEqual(len(self.history), 9)
493 self.assertTrue(C.is_merged)
494
495 self.assertNotIn('merge', A.labels)
496 self.assertNotIn('merge', B.labels)
497 self.assertNotIn('merge', C.labels)
498
499 @simple_layout('layouts/dependent-github.yaml', driver='github')
500 def test_failed_changes(self):
501 "Test that a change behind a failed change is retested"
502 self.executor_server.hold_jobs_in_build = True
503
504 A = self.fake_github.openFakePullRequest('org/project', 'master', 'A')
505 B = self.fake_github.openFakePullRequest('org/project', 'master', 'B')
506
507 self.executor_server.failJob('project-test1', A)
508
509 self.fake_github.emitEvent(A.addLabel('merge'))
510 self.fake_github.emitEvent(B.addLabel('merge'))
511 self.waitUntilSettled()
512
513 self.executor_server.release('.*-merge')
514 self.waitUntilSettled()
515
516 self.executor_server.hold_jobs_in_build = False
517 self.executor_server.release()
518
519 self.waitUntilSettled()
520 # It's certain that the merge job for change 2 will run, but
521 # the test1 and test2 jobs may or may not run.
522 self.assertTrue(len(self.history) > 6)
523 self.assertFalse(A.is_merged)
524 self.assertTrue(B.is_merged)
525 self.assertNotIn('merge', A.labels)
526 self.assertNotIn('merge', B.labels)
527
528 @simple_layout('layouts/dependent-github.yaml', driver='github')
529 def test_failed_change_at_head(self):
530 "Test that if a change at the head fails, jobs behind it are canceled"
531
532 self.executor_server.hold_jobs_in_build = True
533 A = self.fake_github.openFakePullRequest('org/project', 'master', 'A')
534 B = self.fake_github.openFakePullRequest('org/project', 'master', 'B')
535 C = self.fake_github.openFakePullRequest('org/project', 'master', 'C')
536
537 self.executor_server.failJob('project-test1', A)
538
539 self.fake_github.emitEvent(A.addLabel('merge'))
540 self.fake_github.emitEvent(B.addLabel('merge'))
541 self.fake_github.emitEvent(C.addLabel('merge'))
542
543 self.waitUntilSettled()
544
545 self.assertEqual(len(self.builds), 1)
546 self.assertEqual(self.builds[0].name, 'project-merge')
547 self.assertTrue(self.builds[0].hasChanges(A))
548
549 self.executor_server.release('.*-merge')
550 self.waitUntilSettled()
551 self.executor_server.release('.*-merge')
552 self.waitUntilSettled()
553 self.executor_server.release('.*-merge')
554 self.waitUntilSettled()
555
556 self.assertEqual(len(self.builds), 6)
557 self.assertEqual(self.builds[0].name, 'project-test1')
558 self.assertEqual(self.builds[1].name, 'project-test2')
559 self.assertEqual(self.builds[2].name, 'project-test1')
560 self.assertEqual(self.builds[3].name, 'project-test2')
561 self.assertEqual(self.builds[4].name, 'project-test1')
562 self.assertEqual(self.builds[5].name, 'project-test2')
563
564 self.release(self.builds[0])
565 self.waitUntilSettled()
566
567 # project-test2, project-merge for B
568 self.assertEqual(len(self.builds), 2)
569 self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 4)
570
571 self.executor_server.hold_jobs_in_build = False
572 self.executor_server.release()
573 self.waitUntilSettled()
574
575 self.assertEqual(len(self.builds), 0)
576 self.assertEqual(len(self.history), 15)
577 self.assertFalse(A.is_merged)
578 self.assertTrue(B.is_merged)
579 self.assertTrue(C.is_merged)
580 self.assertNotIn('merge', A.labels)
581 self.assertNotIn('merge', B.labels)
582 self.assertNotIn('merge', C.labels)
Jesse Keating71a47ff2017-06-06 11:36:43 -0700583
584 @simple_layout('layouts/basic-github.yaml', driver='github')
585 def test_push_event_reconfigure(self):
586 pevent = self.fake_github.getPushEvent(project='common-config',
587 ref='refs/heads/master',
588 modified_files=['zuul.yaml'])
589
590 # record previous tenant reconfiguration time, which may not be set
591 old = self.sched.tenant_last_reconfigured.get('tenant-one', 0)
592 time.sleep(1)
593 self.fake_github.emitEvent(pevent)
594 self.waitUntilSettled()
595 new = self.sched.tenant_last_reconfigured.get('tenant-one', 0)
596 # New timestamp should be greater than the old timestamp
597 self.assertLess(old, new)
Tristan Cacqueray2bafb1f2017-06-12 07:10:26 +0000598
599 @simple_layout('layouts/basic-github.yaml', driver='github')
600 def test_ping_event(self):
601 # Test valid ping
602 pevent = {'repository': {'full_name': 'org/project'}}
603 req = self.fake_github.emitEvent(('ping', pevent))
604 self.assertEqual(req.status, 200, "Ping event didn't succeed")
605
606 # Test invalid ping
607 pevent = {'repository': {'full_name': 'unknown-project'}}
608 self.assertRaises(
609 urllib.error.HTTPError,
610 self.fake_github.emitEvent,
611 ('ping', pevent),
612 )