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
1=== modified file 'jlp/commands/launchpadTrigger.py'
2--- jlp/commands/launchpadTrigger.py 2013-05-10 14:10:52 +0000
3+++ jlp/commands/launchpadTrigger.py 2017-02-24 14:36:30 +0000
4@@ -8,20 +8,20 @@
5 LAUNCHPADLIB_DIR_PREFIX = os.path.expanduser('~/.launchpadlib')
6
7
8-def trigger_ci_build(branch, job, jenkins_url, launchpadlib_dir):
9+def trigger_ci_build(branch, job, jenkins_url, launchpadlib_dir, repo_type):
10 """Trigger a CI build."""
11
12 launchpad = get_launchpad(launchpadlib_dir)
13- mps = get_merge_proposals(launchpad, branch, ['Needs review'])
14+ mps = get_merge_proposals(launchpad, branch, ['Needs review'], repo_type)
15 jenkinsutils.trigger_ci_build(launchpad, mps, job, jenkins_url)
16
17
18 def trigger_al_build(branch, job, jenkins_url, fasttrack_merge,
19- launchpadlib_dir):
20+ launchpadlib_dir, repo_type):
21 """Trigger an autolanding build."""
22
23 launchpad = get_launchpad(launchpadlib_dir)
24- mps = get_merge_proposals(launchpad, branch, ['Approved'])
25+ mps = get_merge_proposals(launchpad, branch, ['Approved'], repo_type)
26 jenkinsutils.trigger_al_build(launchpad, mps, job, jenkins_url,
27 fasttrack_merge)
28
29@@ -32,7 +32,8 @@
30 job=None,
31 jenkins_url=None,
32 fasttrack_merge=False,
33- lock_name=''):
34+ lock_name='',
35+ repo_type='auto'):
36 """Trigger a Jenkins build."""
37
38 if jenkins_url is None:
39@@ -43,10 +44,10 @@
40 launchpadlib_dir))
41
42 if trigger_ci:
43- trigger_ci_build(branch, job, jenkins_url, launchpadlib_dir)
44+ trigger_ci_build(branch, job, jenkins_url, launchpadlib_dir, repo_type)
45 elif autoland:
46 trigger_al_build(branch, job, jenkins_url, fasttrack_merge,
47- launchpadlib_dir)
48+ launchpadlib_dir, repo_type)
49 return 1
50
51
52@@ -75,6 +76,8 @@
53 default='launchpadTrigger',
54 help='''Name of the lock and launchpadlib cache
55 to be used''')
56+ parser.add_argument("-r", "--repo_type", default="auto",
57+ help="Repository type [bazaar, git, or auto]")
58
59 args = vars(parser.parse_args())
60
61
62=== modified file 'jlp/jenkinsutils.py'
63--- jlp/jenkinsutils.py 2016-02-05 13:20:38 +0000
64+++ jlp/jenkinsutils.py 2017-02-24 14:36:30 +0000
65@@ -670,6 +670,16 @@
66 params['hooks'] = get_parameter(jenkins, job_url, 'dput_hooks', '')
67 params['test_result'] = "PASSED"
68
69+def get_jenkins_params(mp):
70+ params = {
71+ 'landing_candidate': launchpadutils.get_source_repo(mp),
72+ 'merge_proposal': mp.web_link,
73+ 'candidate_revision': launchpadutils.get_latest_revision(mp)}
74+
75+ if '+git' in mp.web_link:
76+ params['landing_candidate_branch'] = launchpadutils.get_source_branch(mp)
77+
78+ return params
79
80 def start_jenkins_job(lp_handle, launchpaduser, jenkins_url, jenkins_job, mp,
81 fasttrack_merge=False):
82@@ -686,10 +696,8 @@
83 """
84 j = jenkins.Jenkins(jenkins_url, get_config_option('jenkins_user'),
85 get_config_option('jenkins_password'))
86- jenkins_params = {
87- 'landing_candidate': mp.source_branch.bzr_identity,
88- 'merge_proposal': mp.web_link,
89- 'candidate_revision': mp.source_branch.revision_count}
90+
91+ jenkins_params = get_jenkins_params(mp)
92
93 job_info = j.get_job_info(jenkins_job)
94 if not job_info['buildable']:
95
96=== modified file 'jlp/launchpadutils.py'
97--- jlp/launchpadutils.py 2017-02-16 21:32:04 +0000
98+++ jlp/launchpadutils.py 2017-02-24 14:36:30 +0000
99@@ -9,6 +9,23 @@
100 DISAPPROVE = 'Disapprove'
101 NEEDS_FIXING = 'Needs Fixing'
102
103+def get_source_repo(mp):
104+ if '+git' in mp.web_link:
105+ return mp.source_git_repository.git_identity
106+ else:
107+ return mp.target_branch.bzr_identity
108+
109+def get_source_branch(mp):
110+ if '+git' in mp.web_link:
111+ return mp.source_git_path.replace('refs/heads/', '')
112+ else:
113+ return mp.source_branch.bzr_identity
114+
115+def get_target_branch(mp):
116+ if '+git' in mp.web_link:
117+ return mp.target_git_path.replace('refs/heads/', '')
118+ else:
119+ return mp.target_branch.bzr_identity
120
121 def get_vote_subject(mp):
122 """Given a mp handle return a subject for the vote message
123@@ -20,10 +37,19 @@
124 This returns what seems to be the launchpad way of doing subjects.
125 :param mp: launchpad merge proposal handle
126 """
127+ if '+git' in mp.web_link:
128+ source = mp.source_git_repository.display_name.replace('lp:', '') + \
129+ ':' + \
130+ mp.source_git_path.replace('refs/heads/', '')
131+ target = mp.target_git_repository.display_name.replace('lp:', '') + \
132+ ':' + \
133+ mp.target_git_path.replace('refs/heads/', '')
134
135- return 'Re: [Merge] {} into {}'.format(
136- mp.source_branch.display_name,
137- mp.target_branch.display_name)
138+ return 'Re: [Merge] {} into {}'.format(source, target)
139+ else:
140+ return 'Re: [Merge] {} into {}'.format(
141+ mp.source_branch.display_name,
142+ mp.target_branch.display_name)
143
144
145 def get_branch_from_mp(merge_proposal):
146@@ -262,6 +288,11 @@
147 return True
148 return False
149
150+def get_review_revision_regex(mp):
151+ if '+git' in mp.web_link:
152+ return '^(PASSED|FAILED): Continuous integration, rev:([0-9a-f]+)'
153+ else:
154+ return '^(PASSED|FAILED): Continuous integration, rev:(\d+)'
155
156 def get_latest_review(launchpad_user, mp):
157 """Return the latest revision reviewed by the given launchpad_user.
158@@ -278,12 +309,25 @@
159 if comment.author.name == launchpad_user.name:
160 if comment.vote_tag == launchpad_review_type:
161 m = re.search(
162- '^(PASSED|FAILED): Continuous integration, rev:(\d+)',
163+ get_review_revision_regex(mp),
164 comment.message_body)
165- if m and (int(m.group(2)) > revision):
166- revision = int(m.group(2))
167+ if m:
168+ revision = m.group(2)
169 return revision
170
171+def get_latest_revision(mp):
172+ """Return the latest revision of the given merge proposal.
173+
174+ :param mp: handle to merge proposal
175+ """
176+ if '+git' in mp.web_link:
177+ for ref in mp.source_git_repository.refs_collection:
178+ if ref.path == mp.source_git_path:
179+ return ref.commit_sha1
180+ return str(0)
181+ else:
182+ return mp.source_branch.revision_count
183+
184
185 def latest_candidate_validated(launchpad_user, mp):
186 """Return if the latest candidate revision of the merge proposal is
187@@ -296,9 +340,11 @@
188
189 latest_review = get_latest_review(launchpad_user, mp)
190 logger.debug('Latest_review is revision: ' + str(latest_review))
191- if latest_review >= mp.source_branch.revision_count:
192+ latest_revision = get_latest_revision(mp)
193+ logger.debug('Latest revision is: ' + str(latest_revision))
194+ if latest_review == latest_revision:
195 logger.debug('Skipping this MP. Current revision: ' +
196- str(mp.source_branch.revision_count))
197+ str(latest_revision))
198 return True
199 return False
200
201@@ -306,7 +352,7 @@
202 def approve_mp(mp, revision, build_url):
203 """Approve a given merge proposal a revision.
204
205- :params mp: launchapd handle to the respective merge proposal
206+ :params mp: launchpad handle to the respective merge proposal
207 :params revision: revision that should be approved
208 :params build_url: jenkins build url with the details. This job is used to
209 generate the message with all the links to test runs as
210@@ -324,7 +370,7 @@
211 def disapprove_mp(mp, revision, build_url, reason=None):
212 """Disapprove a given merge proposal a revision (vote Needs Fixing).
213
214- :params mp: launchapd handle to the respective merge proposal
215+ :params mp: launchpad handle to the respective merge proposal
216 :params revision: revision that should be fixed
217 :params build_url: jenkins build url with the details. This job is used to
218 generate the message with all the links to test runs as
219@@ -462,6 +508,26 @@
220 mps.append(mp)
221 return mps
222
223+def get_branch_handle_from_url(lp_handle, url):
224+ """ Return a branch/repo handle for the given url.
225+
226+ Returns a launchpad branch or git repository handle for the given url.
227+ :param lp_handle: launchpad API handle/instance
228+ :param url: url of the branch or git repository
229+ """
230+ if '+git' in url:
231+ name = url.replace('https://code.launchpad.net/', '')
232+ logger.debug('fetching repo: ' + name)
233+ try:
234+ return lp_handle.git_repositories.getByPath(path=name)
235+ except AttributeError:
236+ logger.debug('git_repositories.getByPath was not found. You may need to set lp_version=devel in the config')
237+ return None
238+ else:
239+ name = url.replace('https://code.launchpad.net/', 'lp:')
240+ name = name.replace('https://code.staging.launchpad.net/', 'lp://staging/')
241+ logger.debug('fetching branch: ' + name)
242+ return lp_handle.branches.getByUrl(url=name)
243
244 def get_mp_handle_from_url(lp_handle, merge_proposal_link):
245 """ Get launchpad handle for merge proposal given a merge proposal URL.
246@@ -474,11 +540,7 @@
247 logger.error('Unable to get branch link from merge proposal link.')
248 return None
249
250- branch_link = branch_link.replace('https://code.launchpad.net/', 'lp:')
251- branch_link = branch_link.replace('https://code.staging.launchpad.net/',
252- 'lp://staging/')
253- logger.debug('fetching branch: ' + branch_link)
254- branch = lp_handle.branches.getByUrl(url=branch_link)
255+ branch = get_branch_handle_from_url(lp_handle, branch_link)
256 if not branch:
257 logger.debug('Branch {} does not exist'.format(branch_link))
258 return None
259
260=== modified file 'tests/test_launchpadTrigger.py'
261--- tests/test_launchpadTrigger.py 2017-02-18 13:28:31 +0000
262+++ tests/test_launchpadTrigger.py 2017-02-24 14:36:30 +0000
263@@ -142,6 +142,27 @@
264 'http://localhost:8080/')
265
266
267+ def test_trigger_git_ci(self):
268+ """Trigger CI got a git repo."""
269+
270+ sys_argv = ["launchpadTrigger.py",
271+ "--branch=lp:faux-dbus-test-runner",
272+ "--trigger-ci",
273+ "--job=faux-dbus-test-runner",
274+ "--repo_type=git"]
275+ with patch('sys.argv', sys_argv), \
276+ patch('jlp.commands.launchpadTrigger.get_merge_proposals') as \
277+ get_merge_proposals, \
278+ patch('jlp.commands.launchpadTrigger.jenkinsutils.' +
279+ 'trigger_ci_build') as trigger_ci_build:
280+ get_merge_proposals.return_value = [self.merge_proposal]
281+ launchpadTrigger()
282+ get_merge_proposals.assert_called_with(self.launchpad,
283+ 'lp:faux-dbus-test-runner',
284+ ['Needs review'],
285+ 'git')
286+
287+
288 class TestLockNames(PatchedLaunchpadTriggerTest):
289
290 sys_argv = ["launchpadTrigger.py",
291@@ -196,7 +217,7 @@
292 lock_name=self.lock_name)
293 trigger_ci_build.assert_called_with(
294 None, None, get_config_option('jenkins_url'),
295- self.expected_cache_dir)
296+ self.expected_cache_dir, 'auto')
297
298 def test_lock_name_autolanding(self):
299 """test trigger_jenkins method for correct use of lock_name param"""
300@@ -208,4 +229,17 @@
301 lock_name=self.lock_name)
302 trigger_al_build.assert_called_with(
303 None, None, get_config_option('jenkins_url'),
304- False, self.expected_cache_dir)
305+ False, self.expected_cache_dir, 'auto')
306+
307+ def test_repo_type_is_propagated(self):
308+ """test trigger_jenkins method for correct use of lock_name param"""
309+
310+ with patch('jlp.commands.launchpadTrigger.trigger_al_build') \
311+ as trigger_al_build:
312+ trigger_jenkins(branch=None,
313+ autoland=True,
314+ lock_name=self.lock_name,
315+ repo_type='git')
316+ trigger_al_build.assert_called_with(
317+ None, None, get_config_option('jenkins_url'),
318+ False, self.expected_cache_dir, 'git')
319
320=== modified file 'tests/test_launchpadutils.py'
321--- tests/test_launchpadutils.py 2017-02-19 03:05:45 +0000
322+++ tests/test_launchpadutils.py 2017-02-24 14:36:30 +0000
323@@ -411,7 +411,7 @@
324 "URL:..."
325 mp.all_comments = [comment]
326 self.assertEqual(
327- launchpadutils.get_latest_review(self.launchpad_user, mp), 47)
328+ launchpadutils.get_latest_review(self.launchpad_user, mp), '47')
329
330 def test_get_latest_review_which_failed(self):
331 mp = MagicMock()
332@@ -422,7 +422,7 @@
333 "URL:..."
334 mp.all_comments = [comment]
335 self.assertEqual(
336- launchpadutils.get_latest_review(self.launchpad_user, mp), 47)
337+ launchpadutils.get_latest_review(self.launchpad_user, mp), '47')
338
339 @patch('jlp.launchpadutils.get_latest_review', new=lambda x, y: 60)
340 def test_new_mp_candidate_revision_in_queue(self):
341@@ -448,6 +448,77 @@
342 self.launchpad_user, mp)
343 self.assertTrue(ret)
344
345+class TestLatestReviewForGitMPs(unittest.TestCase):
346+ def setUp(self):
347+ self.launchpad_user = MagicMock()
348+ self.jenkinsUserName = 'name'
349+ self.launchpad_user.name = self.jenkinsUserName
350+
351+ def create_mp(self):
352+ mp = MagicMock()
353+ mp.web_link = 'https://code.launchpad.net/~user/project/+git/project/+merge/777'
354+ return mp
355+
356+ def create_mp_with_revision(self, revision):
357+ mp = self.create_mp()
358+ path = "refs/heads/nice"
359+ ref = MagicMock()
360+ ref.path = path
361+ ref.commit_sha1 = revision
362+ mp.source_git_path = path
363+ mp.source_git_repository.refs_collection = [ref]
364+ return mp
365+
366+ def test_get_latest_review_no_comments(self):
367+ mp = self.create_mp()
368+ mp.all_comments = []
369+ self.assertEqual(
370+ launchpadutils.get_latest_review(self.launchpad_user, mp), 0)
371+
372+ def test_get_latest_review_unrelated_comment(self):
373+ mp = self.create_mp()
374+ comment = MagicMock()
375+ comment.vote_tag = get_config_option('launchpad_review_type')
376+ comment.message_body = 'unrelated comment'
377+ mp.all_comments = [comment]
378+ self.assertEqual(
379+ launchpadutils.get_latest_review(self.launchpad_user, mp), 0)
380+
381+ def test_get_latest_review_which_passed(self):
382+ mp = self.create_mp()
383+ comment = MagicMock()
384+ comment.author.name = self.jenkinsUserName
385+ comment.vote_tag = get_config_option('launchpad_review_type')
386+ comment.message_body = "PASSED: Continuous integration, rev:2fd4e1c67a2d28fced849ee1bb76e7391b93eb12\n" + \
387+ "URL:..."
388+ mp.all_comments = [comment]
389+ self.assertEqual(
390+ launchpadutils.get_latest_review(self.launchpad_user, mp), '2fd4e1c67a2d28fced849ee1bb76e7391b93eb12')
391+
392+ def test_get_latest_review_which_failed(self):
393+ mp = self.create_mp()
394+ comment = MagicMock()
395+ comment.author.name = self.jenkinsUserName
396+ comment.vote_tag = get_config_option('launchpad_review_type')
397+ comment.message_body = "FAILED: Continuous integration, rev:2fd4e1c67a2d28fced849ee1bb76e7391b93eb12\n" + \
398+ "URL:..."
399+ mp.all_comments = [comment]
400+ self.assertEqual(
401+ launchpadutils.get_latest_review(self.launchpad_user, mp), '2fd4e1c67a2d28fced849ee1bb76e7391b93eb12')
402+
403+ @patch('jlp.launchpadutils.get_latest_review', new=lambda x, y: '2fd4e1c67a2d28fced849ee1bb76e7391b93eb12')
404+ def test_new_mp_candidate_revision_in_queue(self):
405+ mp = self.create_mp_with_revision('de9f2c7fd25e1b3afad3e85a0bd17d9b100db4b3')
406+ ret = launchpadutils.latest_candidate_validated(
407+ self.launchpad_user, mp)
408+ self.assertFalse(ret)
409+
410+ @patch('jlp.launchpadutils.get_latest_review', new=lambda x, y: '2fd4e1c67a2d28fced849ee1bb76e7391b93eb12')
411+ def test_mp_already_validated(self):
412+ mp = self.create_mp_with_revision('2fd4e1c67a2d28fced849ee1bb76e7391b93eb12')
413+ ret = launchpadutils.latest_candidate_validated(
414+ self.launchpad_user, mp)
415+ self.assertTrue(ret)
416
417 class TestApproveAndDisapprove(unittest.TestCase):
418 jenkinsUserName = 'jenkins-user'
419@@ -459,10 +530,29 @@
420 mp.source_branch.display_name = 'lp:~ps-jenkins/unity/fix'
421 return mp
422
423+ def _get_git_mp(self):
424+ mp = MagicMock()
425+ mp.web_link = 'https://code.launchpad.net/~dummy/agitproject/+git/gitproject/+merge/778899'
426+ mp.target_git_repository.display_name = 'lp:agitproject'
427+ mp.source_git_repository.display_name = 'lp:~auser/gitrepo'
428+ mp.source_git_path = 'refs/heads/abranch'
429+ mp.target_git_path = 'refs/heads/master'
430+ return mp
431+
432 def _get_subject(self, mp):
433 return 'Re: [Merge] {} into {}'.format(
434 mp.source_branch.display_name, mp.target_branch.display_name)
435
436+ def _expected_git_mp_subject(self, mp):
437+ source = mp.source_git_repository.display_name.replace('lp:', '') + \
438+ ':' + \
439+ mp.source_git_path.replace('refs/heads/', '')
440+ target = mp.target_git_repository.display_name.replace('lp:', '') + \
441+ ':' + \
442+ mp.target_git_path.replace('refs/heads/', '')
443+
444+ return 'Re: [Merge] {} into {}'.format(source, target)
445+
446 def setUp(self):
447 user = MagicMock()
448 user.name = self.jenkinsUserName
449@@ -531,6 +621,40 @@
450 subject=subject,
451 content=content)
452
453+ def test_approve_git_mp(self):
454+ mp = self._get_git_mp()
455+ subject = self._expected_git_mp_subject(mp)
456+ launchpadutils.approve_mp(mp, '1', 'http://url')
457+ content = dedent('''\
458+ PASSED: Continuous integration, rev:1
459+ http://url
460+
461+ Click here to trigger a rebuild:
462+ http://url/rebuild
463+ ''')
464+ mp.createComment.assert_called_once_with(
465+ review_type=get_config_option('launchpad_review_type'),
466+ vote=launchpadutils.LaunchpadVote.APPROVE,
467+ subject=subject,
468+ content=content)
469+
470+ def test_dissaprove_git_mp(self):
471+ mp = self._get_git_mp()
472+ subject = self._expected_git_mp_subject(mp)
473+ launchpadutils.disapprove_mp(mp, '1', 'http://url')
474+ content = dedent('''\
475+ FAILED: Continuous integration, rev:1
476+ http://url
477+
478+ Click here to trigger a rebuild:
479+ http://url/rebuild
480+ ''')
481+ mp.createComment.assert_called_once_with(
482+ review_type=get_config_option('launchpad_review_type'),
483+ vote=launchpadutils.LaunchpadVote.NEEDS_FIXING,
484+ subject=subject,
485+ content=content)
486+
487
488 class TestGetMergeProposalsWithInvalidBranch(unittest.TestCase):
489 branch_with_mps = None
490@@ -649,6 +773,21 @@
491 ret = launchpadutils.get_mp_handle_from_url(launchpad, mp_url)
492 self.assertEquals(ret, mp)
493
494+ def test_call_git_api_for_git_url(self):
495+ """If there is a merge proposal for the given merge proposal URL then
496+ get_mp_handle_from_url must return the respective merge proposal
497+ handle"""
498+
499+ mp_url = 'https://code.launchpad.net/~dummy/agitproject/+git/gitproject/+merge/778899'
500+ launchpad = MagicMock()
501+ git_repo = MagicMock
502+ mp = MagicMock()
503+ mp.web_link = mp_url
504+ git_repo.landing_targets = [mp]
505+ launchpad.git_repositories.getByPath = lambda path: git_repo
506+ ret = launchpadutils.get_mp_handle_from_url(launchpad, mp_url)
507+ self.assertEquals(ret, mp)
508+
509 class TestGetBranchHandle(unittest.TestCase):
510 def setUp(self):
511 '''Setup an empty launchpad.'''
512@@ -775,4 +914,3 @@
513 with self.assertRaises(RuntimeError):
514 launchpadutils.get_branch_handle_for(self.launchpad, name,
515 'auto');
516-

Subscribers

People subscribed via source and target branches

to all changes: