Merge lp:~powersj/jenkins-launchpad-plugin/support-lp-trigger-for-git-mps into lp:jenkins-launchpad-plugin

Proposed by Joshua Powers
Status: Merged
Approved by: Francis Ginther
Approved revision: 135
Merged at revision: 132
Proposed branch: lp:~powersj/jenkins-launchpad-plugin/support-lp-trigger-for-git-mps
Merge into: lp:jenkins-launchpad-plugin
Diff against target: 516 lines (+276/-31)
5 files modified
jlp/commands/launchpadTrigger.py (+10/-7)
jlp/jenkinsutils.py (+12/-4)
jlp/launchpadutils.py (+77/-15)
tests/test_launchpadTrigger.py (+36/-2)
tests/test_launchpadutils.py (+141/-3)
To merge this branch: bzr merge lp:~powersj/jenkins-launchpad-plugin/support-lp-trigger-for-git-mps
Reviewer Review Type Date Requested Status
Francis Ginther Approve
Joshua Powers (community) Needs Resubmitting
Review via email: mp+318151@code.launchpad.net

Description of the change

Merge master and ~albaguirre's proposal for triggering git reviews, as well as voting on them, and modified to not require a repo_type be passed in, but optionally added

Ran included tests:

Ran 298 tests in 0.638s
OK

Command tested with:

./launchpadTrigger.py --lock-name='my_lock' --job='my_ci_job' --branch=lp:cloud-init --trigger-ci
DEBUG: Going to acquire launchpad lock "launchpad-trigger-lock-my_lock" for launchpadTrigger
DEBUG: Lock acquired for launchpadTrigger
DEBUG: Using "/home/powersj/.launchpadlib-my_lock" as launchpadlib cache directory.
DEBUG: Provided branch name: lp:cloud-init
DEBUG: Using repo_type: auto
DEBUG: git repo: https://api.launchpad.net/devel/~cloud-init-dev/cloud-init/+git/cloud-init
DEBUG: Users "raharper" not allowed to trigger jobs
DEBUG: Users "slystopad" not allowed to trigger jobs

./launchpadTrigger.py --lock-name='my_lock' --job='my_ci_job' --branch=lp:curtin --trigger-ci
DEBUG: Going to acquire launchpad lock "launchpad-trigger-lock-my_lock" for launchpadTrigger
DEBUG: Lock acquired for launchpadTrigger
DEBUG: Using "/home/powersj/.launchpadlib-my_lock" as launchpadlib cache directory.
DEBUG: Provided branch name: lp:curtin
DEBUG: Using repo_type: auto
DEBUG: bazaar repo: https://api.launchpad.net/devel/~curtin-dev/curtin/trunk
DEBUG: Users "raharper" not allowed to trigger jobs
DEBUG: Users "pwlars" not allowed to trigger jobs

Voting tested with:
./voteOnMergeProposal.py -s "PASSED" -u "https://jenkins.ubuntu.com/server" -r "8d9f243dc678698f9aea16b3e43dcdf75176ee0b" -b "~powersj/cloud-init:jlp" -p "https://code.launchpad.net/~powersj/cloud-init/+git/cloud-init/+merge/318152"
DEBUG: fetching repo: ~powersj/cloud-init/+git/cloud-init/
DEBUG: mp_link: https://code.launchpad.net/~powersj/cloud-init/+git/cloud-init/+merge/318152.
DEBUG: mp.web_link: https://code.launchpad.net/~powersj/cloud-init/+git/cloud-init/+merge/318152
DEBUG: Unable to get job name from build_url.Skipping check for empty commit message
DEBUG: PASSED: Continuous integration, rev:8d9f243dc678698f9aea16b3e43dcdf75176ee0b

./voteOnMergeProposal.py -s "FAILED" -u "https://jenkins.ubuntu.com/server" -r "8d9f243dc678698f9aea16b3e43dcdf75176ee0b" -b "~powersj/cloud-init:jlp" -p "https://code.launchpad.net/~powersj/cloud-init/+git/cloud-init/+merge/318152"
DEBUG: fetching repo: ~powersj/cloud-init/+git/cloud-init/
DEBUG: mp_link: https://code.launchpad.net/~powersj/cloud-init/+git/cloud-init/+merge/318152.
DEBUG: mp.web_link: https://code.launchpad.net/~powersj/cloud-init/+git/cloud-init/+merge/318152
DEBUG: Unable to get job name from build_url.Skipping check for empty commit message
DEBUG: FAILED: Continuous integration, rev:8d9f243dc678698f9aea16b3e43dcdf75176ee0b

The result of the voting can be seen on this cloud-init git MP:
https://code.launchpad.net/~powersj/cloud-init/+git/cloud-init/+merge/318152

To post a comment you must log in.
Revision history for this message
Francis Ginther (fginther) wrote :

Looks really good. Just one default parameter value I'd like to see changed.

Thanks again for working on these changes.

review: Needs Fixing
135. By Joshua Powers

Updating default arg to auto and updating tests to match change

Revision history for this message
Joshua Powers (powersj) wrote :

Good catch on the default parameter. Updated that to auto and the tests.

review: Needs Resubmitting
Revision history for this message
Francis Ginther (fginther) wrote :

Thanks for the update, approve.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'jlp/commands/launchpadTrigger.py'
--- jlp/commands/launchpadTrigger.py 2013-05-10 14:10:52 +0000
+++ jlp/commands/launchpadTrigger.py 2017-02-24 14:36:30 +0000
@@ -8,20 +8,20 @@
8LAUNCHPADLIB_DIR_PREFIX = os.path.expanduser('~/.launchpadlib')8LAUNCHPADLIB_DIR_PREFIX = os.path.expanduser('~/.launchpadlib')
99
1010
11def trigger_ci_build(branch, job, jenkins_url, launchpadlib_dir):11def trigger_ci_build(branch, job, jenkins_url, launchpadlib_dir, repo_type):
12 """Trigger a CI build."""12 """Trigger a CI build."""
1313
14 launchpad = get_launchpad(launchpadlib_dir)14 launchpad = get_launchpad(launchpadlib_dir)
15 mps = get_merge_proposals(launchpad, branch, ['Needs review'])15 mps = get_merge_proposals(launchpad, branch, ['Needs review'], repo_type)
16 jenkinsutils.trigger_ci_build(launchpad, mps, job, jenkins_url)16 jenkinsutils.trigger_ci_build(launchpad, mps, job, jenkins_url)
1717
1818
19def trigger_al_build(branch, job, jenkins_url, fasttrack_merge,19def trigger_al_build(branch, job, jenkins_url, fasttrack_merge,
20 launchpadlib_dir):20 launchpadlib_dir, repo_type):
21 """Trigger an autolanding build."""21 """Trigger an autolanding build."""
2222
23 launchpad = get_launchpad(launchpadlib_dir)23 launchpad = get_launchpad(launchpadlib_dir)
24 mps = get_merge_proposals(launchpad, branch, ['Approved'])24 mps = get_merge_proposals(launchpad, branch, ['Approved'], repo_type)
25 jenkinsutils.trigger_al_build(launchpad, mps, job, jenkins_url,25 jenkinsutils.trigger_al_build(launchpad, mps, job, jenkins_url,
26 fasttrack_merge)26 fasttrack_merge)
2727
@@ -32,7 +32,8 @@
32 job=None,32 job=None,
33 jenkins_url=None,33 jenkins_url=None,
34 fasttrack_merge=False,34 fasttrack_merge=False,
35 lock_name=''):35 lock_name='',
36 repo_type='auto'):
36 """Trigger a Jenkins build."""37 """Trigger a Jenkins build."""
3738
38 if jenkins_url is None:39 if jenkins_url is None:
@@ -43,10 +44,10 @@
43 launchpadlib_dir))44 launchpadlib_dir))
4445
45 if trigger_ci:46 if trigger_ci:
46 trigger_ci_build(branch, job, jenkins_url, launchpadlib_dir)47 trigger_ci_build(branch, job, jenkins_url, launchpadlib_dir, repo_type)
47 elif autoland:48 elif autoland:
48 trigger_al_build(branch, job, jenkins_url, fasttrack_merge,49 trigger_al_build(branch, job, jenkins_url, fasttrack_merge,
49 launchpadlib_dir)50 launchpadlib_dir, repo_type)
50 return 151 return 1
5152
5253
@@ -75,6 +76,8 @@
75 default='launchpadTrigger',76 default='launchpadTrigger',
76 help='''Name of the lock and launchpadlib cache77 help='''Name of the lock and launchpadlib cache
77 to be used''')78 to be used''')
79 parser.add_argument("-r", "--repo_type", default="auto",
80 help="Repository type [bazaar, git, or auto]")
7881
79 args = vars(parser.parse_args())82 args = vars(parser.parse_args())
8083
8184
=== modified file 'jlp/jenkinsutils.py'
--- jlp/jenkinsutils.py 2016-02-05 13:20:38 +0000
+++ jlp/jenkinsutils.py 2017-02-24 14:36:30 +0000
@@ -670,6 +670,16 @@
670 params['hooks'] = get_parameter(jenkins, job_url, 'dput_hooks', '')670 params['hooks'] = get_parameter(jenkins, job_url, 'dput_hooks', '')
671 params['test_result'] = "PASSED"671 params['test_result'] = "PASSED"
672672
673def get_jenkins_params(mp):
674 params = {
675 'landing_candidate': launchpadutils.get_source_repo(mp),
676 'merge_proposal': mp.web_link,
677 'candidate_revision': launchpadutils.get_latest_revision(mp)}
678
679 if '+git' in mp.web_link:
680 params['landing_candidate_branch'] = launchpadutils.get_source_branch(mp)
681
682 return params
673683
674def start_jenkins_job(lp_handle, launchpaduser, jenkins_url, jenkins_job, mp,684def start_jenkins_job(lp_handle, launchpaduser, jenkins_url, jenkins_job, mp,
675 fasttrack_merge=False):685 fasttrack_merge=False):
@@ -686,10 +696,8 @@
686 """696 """
687 j = jenkins.Jenkins(jenkins_url, get_config_option('jenkins_user'),697 j = jenkins.Jenkins(jenkins_url, get_config_option('jenkins_user'),
688 get_config_option('jenkins_password'))698 get_config_option('jenkins_password'))
689 jenkins_params = {699
690 'landing_candidate': mp.source_branch.bzr_identity,700 jenkins_params = get_jenkins_params(mp)
691 'merge_proposal': mp.web_link,
692 'candidate_revision': mp.source_branch.revision_count}
693701
694 job_info = j.get_job_info(jenkins_job)702 job_info = j.get_job_info(jenkins_job)
695 if not job_info['buildable']:703 if not job_info['buildable']:
696704
=== modified file 'jlp/launchpadutils.py'
--- jlp/launchpadutils.py 2017-02-16 21:32:04 +0000
+++ jlp/launchpadutils.py 2017-02-24 14:36:30 +0000
@@ -9,6 +9,23 @@
9 DISAPPROVE = 'Disapprove'9 DISAPPROVE = 'Disapprove'
10 NEEDS_FIXING = 'Needs Fixing'10 NEEDS_FIXING = 'Needs Fixing'
1111
12def get_source_repo(mp):
13 if '+git' in mp.web_link:
14 return mp.source_git_repository.git_identity
15 else:
16 return mp.target_branch.bzr_identity
17
18def get_source_branch(mp):
19 if '+git' in mp.web_link:
20 return mp.source_git_path.replace('refs/heads/', '')
21 else:
22 return mp.source_branch.bzr_identity
23
24def get_target_branch(mp):
25 if '+git' in mp.web_link:
26 return mp.target_git_path.replace('refs/heads/', '')
27 else:
28 return mp.target_branch.bzr_identity
1229
13def get_vote_subject(mp):30def get_vote_subject(mp):
14 """Given a mp handle return a subject for the vote message31 """Given a mp handle return a subject for the vote message
@@ -20,10 +37,19 @@
20 This returns what seems to be the launchpad way of doing subjects.37 This returns what seems to be the launchpad way of doing subjects.
21 :param mp: launchpad merge proposal handle38 :param mp: launchpad merge proposal handle
22 """39 """
40 if '+git' in mp.web_link:
41 source = mp.source_git_repository.display_name.replace('lp:', '') + \
42 ':' + \
43 mp.source_git_path.replace('refs/heads/', '')
44 target = mp.target_git_repository.display_name.replace('lp:', '') + \
45 ':' + \
46 mp.target_git_path.replace('refs/heads/', '')
2347
24 return 'Re: [Merge] {} into {}'.format(48 return 'Re: [Merge] {} into {}'.format(source, target)
25 mp.source_branch.display_name,49 else:
26 mp.target_branch.display_name)50 return 'Re: [Merge] {} into {}'.format(
51 mp.source_branch.display_name,
52 mp.target_branch.display_name)
2753
2854
29def get_branch_from_mp(merge_proposal):55def get_branch_from_mp(merge_proposal):
@@ -262,6 +288,11 @@
262 return True288 return True
263 return False289 return False
264290
291def get_review_revision_regex(mp):
292 if '+git' in mp.web_link:
293 return '^(PASSED|FAILED): Continuous integration, rev:([0-9a-f]+)'
294 else:
295 return '^(PASSED|FAILED): Continuous integration, rev:(\d+)'
265296
266def get_latest_review(launchpad_user, mp):297def get_latest_review(launchpad_user, mp):
267 """Return the latest revision reviewed by the given launchpad_user.298 """Return the latest revision reviewed by the given launchpad_user.
@@ -278,12 +309,25 @@
278 if comment.author.name == launchpad_user.name:309 if comment.author.name == launchpad_user.name:
279 if comment.vote_tag == launchpad_review_type:310 if comment.vote_tag == launchpad_review_type:
280 m = re.search(311 m = re.search(
281 '^(PASSED|FAILED): Continuous integration, rev:(\d+)',312 get_review_revision_regex(mp),
282 comment.message_body)313 comment.message_body)
283 if m and (int(m.group(2)) > revision):314 if m:
284 revision = int(m.group(2))315 revision = m.group(2)
285 return revision316 return revision
286317
318def get_latest_revision(mp):
319 """Return the latest revision of the given merge proposal.
320
321 :param mp: handle to merge proposal
322 """
323 if '+git' in mp.web_link:
324 for ref in mp.source_git_repository.refs_collection:
325 if ref.path == mp.source_git_path:
326 return ref.commit_sha1
327 return str(0)
328 else:
329 return mp.source_branch.revision_count
330
287331
288def latest_candidate_validated(launchpad_user, mp):332def latest_candidate_validated(launchpad_user, mp):
289 """Return if the latest candidate revision of the merge proposal is333 """Return if the latest candidate revision of the merge proposal is
@@ -296,9 +340,11 @@
296340
297 latest_review = get_latest_review(launchpad_user, mp)341 latest_review = get_latest_review(launchpad_user, mp)
298 logger.debug('Latest_review is revision: ' + str(latest_review))342 logger.debug('Latest_review is revision: ' + str(latest_review))
299 if latest_review >= mp.source_branch.revision_count:343 latest_revision = get_latest_revision(mp)
344 logger.debug('Latest revision is: ' + str(latest_revision))
345 if latest_review == latest_revision:
300 logger.debug('Skipping this MP. Current revision: ' +346 logger.debug('Skipping this MP. Current revision: ' +
301 str(mp.source_branch.revision_count))347 str(latest_revision))
302 return True348 return True
303 return False349 return False
304350
@@ -306,7 +352,7 @@
306def approve_mp(mp, revision, build_url):352def approve_mp(mp, revision, build_url):
307 """Approve a given merge proposal a revision.353 """Approve a given merge proposal a revision.
308354
309 :params mp: launchapd handle to the respective merge proposal355 :params mp: launchpad handle to the respective merge proposal
310 :params revision: revision that should be approved356 :params revision: revision that should be approved
311 :params build_url: jenkins build url with the details. This job is used to357 :params build_url: jenkins build url with the details. This job is used to
312 generate the message with all the links to test runs as358 generate the message with all the links to test runs as
@@ -324,7 +370,7 @@
324def disapprove_mp(mp, revision, build_url, reason=None):370def disapprove_mp(mp, revision, build_url, reason=None):
325 """Disapprove a given merge proposal a revision (vote Needs Fixing).371 """Disapprove a given merge proposal a revision (vote Needs Fixing).
326372
327 :params mp: launchapd handle to the respective merge proposal373 :params mp: launchpad handle to the respective merge proposal
328 :params revision: revision that should be fixed374 :params revision: revision that should be fixed
329 :params build_url: jenkins build url with the details. This job is used to375 :params build_url: jenkins build url with the details. This job is used to
330 generate the message with all the links to test runs as376 generate the message with all the links to test runs as
@@ -462,6 +508,26 @@
462 mps.append(mp)508 mps.append(mp)
463 return mps509 return mps
464510
511def get_branch_handle_from_url(lp_handle, url):
512 """ Return a branch/repo handle for the given url.
513
514 Returns a launchpad branch or git repository handle for the given url.
515 :param lp_handle: launchpad API handle/instance
516 :param url: url of the branch or git repository
517 """
518 if '+git' in url:
519 name = url.replace('https://code.launchpad.net/', '')
520 logger.debug('fetching repo: ' + name)
521 try:
522 return lp_handle.git_repositories.getByPath(path=name)
523 except AttributeError:
524 logger.debug('git_repositories.getByPath was not found. You may need to set lp_version=devel in the config')
525 return None
526 else:
527 name = url.replace('https://code.launchpad.net/', 'lp:')
528 name = name.replace('https://code.staging.launchpad.net/', 'lp://staging/')
529 logger.debug('fetching branch: ' + name)
530 return lp_handle.branches.getByUrl(url=name)
465531
466def get_mp_handle_from_url(lp_handle, merge_proposal_link):532def get_mp_handle_from_url(lp_handle, merge_proposal_link):
467 """ Get launchpad handle for merge proposal given a merge proposal URL.533 """ Get launchpad handle for merge proposal given a merge proposal URL.
@@ -474,11 +540,7 @@
474 logger.error('Unable to get branch link from merge proposal link.')540 logger.error('Unable to get branch link from merge proposal link.')
475 return None541 return None
476542
477 branch_link = branch_link.replace('https://code.launchpad.net/', 'lp:')543 branch = get_branch_handle_from_url(lp_handle, branch_link)
478 branch_link = branch_link.replace('https://code.staging.launchpad.net/',
479 'lp://staging/')
480 logger.debug('fetching branch: ' + branch_link)
481 branch = lp_handle.branches.getByUrl(url=branch_link)
482 if not branch:544 if not branch:
483 logger.debug('Branch {} does not exist'.format(branch_link))545 logger.debug('Branch {} does not exist'.format(branch_link))
484 return None546 return None
485547
=== modified file 'tests/test_launchpadTrigger.py'
--- tests/test_launchpadTrigger.py 2017-02-18 13:28:31 +0000
+++ tests/test_launchpadTrigger.py 2017-02-24 14:36:30 +0000
@@ -142,6 +142,27 @@
142 'http://localhost:8080/')142 'http://localhost:8080/')
143143
144144
145 def test_trigger_git_ci(self):
146 """Trigger CI got a git repo."""
147
148 sys_argv = ["launchpadTrigger.py",
149 "--branch=lp:faux-dbus-test-runner",
150 "--trigger-ci",
151 "--job=faux-dbus-test-runner",
152 "--repo_type=git"]
153 with patch('sys.argv', sys_argv), \
154 patch('jlp.commands.launchpadTrigger.get_merge_proposals') as \
155 get_merge_proposals, \
156 patch('jlp.commands.launchpadTrigger.jenkinsutils.' +
157 'trigger_ci_build') as trigger_ci_build:
158 get_merge_proposals.return_value = [self.merge_proposal]
159 launchpadTrigger()
160 get_merge_proposals.assert_called_with(self.launchpad,
161 'lp:faux-dbus-test-runner',
162 ['Needs review'],
163 'git')
164
165
145class TestLockNames(PatchedLaunchpadTriggerTest):166class TestLockNames(PatchedLaunchpadTriggerTest):
146167
147 sys_argv = ["launchpadTrigger.py",168 sys_argv = ["launchpadTrigger.py",
@@ -196,7 +217,7 @@
196 lock_name=self.lock_name)217 lock_name=self.lock_name)
197 trigger_ci_build.assert_called_with(218 trigger_ci_build.assert_called_with(
198 None, None, get_config_option('jenkins_url'),219 None, None, get_config_option('jenkins_url'),
199 self.expected_cache_dir)220 self.expected_cache_dir, 'auto')
200221
201 def test_lock_name_autolanding(self):222 def test_lock_name_autolanding(self):
202 """test trigger_jenkins method for correct use of lock_name param"""223 """test trigger_jenkins method for correct use of lock_name param"""
@@ -208,4 +229,17 @@
208 lock_name=self.lock_name)229 lock_name=self.lock_name)
209 trigger_al_build.assert_called_with(230 trigger_al_build.assert_called_with(
210 None, None, get_config_option('jenkins_url'),231 None, None, get_config_option('jenkins_url'),
211 False, self.expected_cache_dir)232 False, self.expected_cache_dir, 'auto')
233
234 def test_repo_type_is_propagated(self):
235 """test trigger_jenkins method for correct use of lock_name param"""
236
237 with patch('jlp.commands.launchpadTrigger.trigger_al_build') \
238 as trigger_al_build:
239 trigger_jenkins(branch=None,
240 autoland=True,
241 lock_name=self.lock_name,
242 repo_type='git')
243 trigger_al_build.assert_called_with(
244 None, None, get_config_option('jenkins_url'),
245 False, self.expected_cache_dir, 'git')
212246
=== modified file 'tests/test_launchpadutils.py'
--- tests/test_launchpadutils.py 2017-02-19 03:05:45 +0000
+++ tests/test_launchpadutils.py 2017-02-24 14:36:30 +0000
@@ -411,7 +411,7 @@
411 "URL:..."411 "URL:..."
412 mp.all_comments = [comment]412 mp.all_comments = [comment]
413 self.assertEqual(413 self.assertEqual(
414 launchpadutils.get_latest_review(self.launchpad_user, mp), 47)414 launchpadutils.get_latest_review(self.launchpad_user, mp), '47')
415415
416 def test_get_latest_review_which_failed(self):416 def test_get_latest_review_which_failed(self):
417 mp = MagicMock()417 mp = MagicMock()
@@ -422,7 +422,7 @@
422 "URL:..."422 "URL:..."
423 mp.all_comments = [comment]423 mp.all_comments = [comment]
424 self.assertEqual(424 self.assertEqual(
425 launchpadutils.get_latest_review(self.launchpad_user, mp), 47)425 launchpadutils.get_latest_review(self.launchpad_user, mp), '47')
426426
427 @patch('jlp.launchpadutils.get_latest_review', new=lambda x, y: 60)427 @patch('jlp.launchpadutils.get_latest_review', new=lambda x, y: 60)
428 def test_new_mp_candidate_revision_in_queue(self):428 def test_new_mp_candidate_revision_in_queue(self):
@@ -448,6 +448,77 @@
448 self.launchpad_user, mp)448 self.launchpad_user, mp)
449 self.assertTrue(ret)449 self.assertTrue(ret)
450450
451class TestLatestReviewForGitMPs(unittest.TestCase):
452 def setUp(self):
453 self.launchpad_user = MagicMock()
454 self.jenkinsUserName = 'name'
455 self.launchpad_user.name = self.jenkinsUserName
456
457 def create_mp(self):
458 mp = MagicMock()
459 mp.web_link = 'https://code.launchpad.net/~user/project/+git/project/+merge/777'
460 return mp
461
462 def create_mp_with_revision(self, revision):
463 mp = self.create_mp()
464 path = "refs/heads/nice"
465 ref = MagicMock()
466 ref.path = path
467 ref.commit_sha1 = revision
468 mp.source_git_path = path
469 mp.source_git_repository.refs_collection = [ref]
470 return mp
471
472 def test_get_latest_review_no_comments(self):
473 mp = self.create_mp()
474 mp.all_comments = []
475 self.assertEqual(
476 launchpadutils.get_latest_review(self.launchpad_user, mp), 0)
477
478 def test_get_latest_review_unrelated_comment(self):
479 mp = self.create_mp()
480 comment = MagicMock()
481 comment.vote_tag = get_config_option('launchpad_review_type')
482 comment.message_body = 'unrelated comment'
483 mp.all_comments = [comment]
484 self.assertEqual(
485 launchpadutils.get_latest_review(self.launchpad_user, mp), 0)
486
487 def test_get_latest_review_which_passed(self):
488 mp = self.create_mp()
489 comment = MagicMock()
490 comment.author.name = self.jenkinsUserName
491 comment.vote_tag = get_config_option('launchpad_review_type')
492 comment.message_body = "PASSED: Continuous integration, rev:2fd4e1c67a2d28fced849ee1bb76e7391b93eb12\n" + \
493 "URL:..."
494 mp.all_comments = [comment]
495 self.assertEqual(
496 launchpadutils.get_latest_review(self.launchpad_user, mp), '2fd4e1c67a2d28fced849ee1bb76e7391b93eb12')
497
498 def test_get_latest_review_which_failed(self):
499 mp = self.create_mp()
500 comment = MagicMock()
501 comment.author.name = self.jenkinsUserName
502 comment.vote_tag = get_config_option('launchpad_review_type')
503 comment.message_body = "FAILED: Continuous integration, rev:2fd4e1c67a2d28fced849ee1bb76e7391b93eb12\n" + \
504 "URL:..."
505 mp.all_comments = [comment]
506 self.assertEqual(
507 launchpadutils.get_latest_review(self.launchpad_user, mp), '2fd4e1c67a2d28fced849ee1bb76e7391b93eb12')
508
509 @patch('jlp.launchpadutils.get_latest_review', new=lambda x, y: '2fd4e1c67a2d28fced849ee1bb76e7391b93eb12')
510 def test_new_mp_candidate_revision_in_queue(self):
511 mp = self.create_mp_with_revision('de9f2c7fd25e1b3afad3e85a0bd17d9b100db4b3')
512 ret = launchpadutils.latest_candidate_validated(
513 self.launchpad_user, mp)
514 self.assertFalse(ret)
515
516 @patch('jlp.launchpadutils.get_latest_review', new=lambda x, y: '2fd4e1c67a2d28fced849ee1bb76e7391b93eb12')
517 def test_mp_already_validated(self):
518 mp = self.create_mp_with_revision('2fd4e1c67a2d28fced849ee1bb76e7391b93eb12')
519 ret = launchpadutils.latest_candidate_validated(
520 self.launchpad_user, mp)
521 self.assertTrue(ret)
451522
452class TestApproveAndDisapprove(unittest.TestCase):523class TestApproveAndDisapprove(unittest.TestCase):
453 jenkinsUserName = 'jenkins-user'524 jenkinsUserName = 'jenkins-user'
@@ -459,10 +530,29 @@
459 mp.source_branch.display_name = 'lp:~ps-jenkins/unity/fix'530 mp.source_branch.display_name = 'lp:~ps-jenkins/unity/fix'
460 return mp531 return mp
461532
533 def _get_git_mp(self):
534 mp = MagicMock()
535 mp.web_link = 'https://code.launchpad.net/~dummy/agitproject/+git/gitproject/+merge/778899'
536 mp.target_git_repository.display_name = 'lp:agitproject'
537 mp.source_git_repository.display_name = 'lp:~auser/gitrepo'
538 mp.source_git_path = 'refs/heads/abranch'
539 mp.target_git_path = 'refs/heads/master'
540 return mp
541
462 def _get_subject(self, mp):542 def _get_subject(self, mp):
463 return 'Re: [Merge] {} into {}'.format(543 return 'Re: [Merge] {} into {}'.format(
464 mp.source_branch.display_name, mp.target_branch.display_name)544 mp.source_branch.display_name, mp.target_branch.display_name)
465545
546 def _expected_git_mp_subject(self, mp):
547 source = mp.source_git_repository.display_name.replace('lp:', '') + \
548 ':' + \
549 mp.source_git_path.replace('refs/heads/', '')
550 target = mp.target_git_repository.display_name.replace('lp:', '') + \
551 ':' + \
552 mp.target_git_path.replace('refs/heads/', '')
553
554 return 'Re: [Merge] {} into {}'.format(source, target)
555
466 def setUp(self):556 def setUp(self):
467 user = MagicMock()557 user = MagicMock()
468 user.name = self.jenkinsUserName558 user.name = self.jenkinsUserName
@@ -531,6 +621,40 @@
531 subject=subject,621 subject=subject,
532 content=content)622 content=content)
533623
624 def test_approve_git_mp(self):
625 mp = self._get_git_mp()
626 subject = self._expected_git_mp_subject(mp)
627 launchpadutils.approve_mp(mp, '1', 'http://url')
628 content = dedent('''\
629 PASSED: Continuous integration, rev:1
630 http://url
631
632 Click here to trigger a rebuild:
633 http://url/rebuild
634 ''')
635 mp.createComment.assert_called_once_with(
636 review_type=get_config_option('launchpad_review_type'),
637 vote=launchpadutils.LaunchpadVote.APPROVE,
638 subject=subject,
639 content=content)
640
641 def test_dissaprove_git_mp(self):
642 mp = self._get_git_mp()
643 subject = self._expected_git_mp_subject(mp)
644 launchpadutils.disapprove_mp(mp, '1', 'http://url')
645 content = dedent('''\
646 FAILED: Continuous integration, rev:1
647 http://url
648
649 Click here to trigger a rebuild:
650 http://url/rebuild
651 ''')
652 mp.createComment.assert_called_once_with(
653 review_type=get_config_option('launchpad_review_type'),
654 vote=launchpadutils.LaunchpadVote.NEEDS_FIXING,
655 subject=subject,
656 content=content)
657
534658
535class TestGetMergeProposalsWithInvalidBranch(unittest.TestCase):659class TestGetMergeProposalsWithInvalidBranch(unittest.TestCase):
536 branch_with_mps = None660 branch_with_mps = None
@@ -649,6 +773,21 @@
649 ret = launchpadutils.get_mp_handle_from_url(launchpad, mp_url)773 ret = launchpadutils.get_mp_handle_from_url(launchpad, mp_url)
650 self.assertEquals(ret, mp)774 self.assertEquals(ret, mp)
651775
776 def test_call_git_api_for_git_url(self):
777 """If there is a merge proposal for the given merge proposal URL then
778 get_mp_handle_from_url must return the respective merge proposal
779 handle"""
780
781 mp_url = 'https://code.launchpad.net/~dummy/agitproject/+git/gitproject/+merge/778899'
782 launchpad = MagicMock()
783 git_repo = MagicMock
784 mp = MagicMock()
785 mp.web_link = mp_url
786 git_repo.landing_targets = [mp]
787 launchpad.git_repositories.getByPath = lambda path: git_repo
788 ret = launchpadutils.get_mp_handle_from_url(launchpad, mp_url)
789 self.assertEquals(ret, mp)
790
652class TestGetBranchHandle(unittest.TestCase):791class TestGetBranchHandle(unittest.TestCase):
653 def setUp(self):792 def setUp(self):
654 '''Setup an empty launchpad.'''793 '''Setup an empty launchpad.'''
@@ -775,4 +914,3 @@
775 with self.assertRaises(RuntimeError):914 with self.assertRaises(RuntimeError):
776 launchpadutils.get_branch_handle_for(self.launchpad, name,915 launchpadutils.get_branch_handle_for(self.launchpad, name,
777 'auto');916 'auto');
778

Subscribers

People subscribed via source and target branches

to all changes: