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

Proposed by Alberto Aguirre
Status: Merged
Merged at revision: 132
Proposed branch: lp:~albaguirre/jenkins-launchpad-plugin/support-lp-trigger-for-git-mps
Merge into: lp:jenkins-launchpad-plugin
Prerequisite: lp:~albaguirre/jenkins-launchpad-plugin/support-voting-on-git-mps
Diff against target: 338 lines (+174/-20)
5 files modified
jlp/commands/launchpadTrigger.py (+11/-7)
jlp/jenkinsutils.py (+12/-4)
jlp/launchpadutils.py (+42/-5)
tests/test_launchpadTrigger.py (+36/-2)
tests/test_launchpadutils.py (+73/-2)
To merge this branch: bzr merge lp:~albaguirre/jenkins-launchpad-plugin/support-lp-trigger-for-git-mps
Reviewer Review Type Date Requested Status
Alexandros Frantzis (community) Approve
Review via email: mp+302868@code.launchpad.net

Commit message

launchPadTrigger: Add support for git projects

To post a comment you must log in.
Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

Looks good.

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 2016-08-13 18:04:14 +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='bazaar'):
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,9 @@
53 default='launchpadTrigger',
54 help='''Name of the lock and launchpadlib cache
55 to be used''')
56+ parser.add_argument('-r', '--repo-type',
57+ default='bazaar',
58+ help='''What type of branches to trigger jobs for [git or bazaar]''')
59
60 args = vars(parser.parse_args())
61
62
63=== modified file 'jlp/jenkinsutils.py'
64--- jlp/jenkinsutils.py 2016-02-05 13:20:38 +0000
65+++ jlp/jenkinsutils.py 2016-08-13 18:04:14 +0000
66@@ -670,6 +670,16 @@
67 params['hooks'] = get_parameter(jenkins, job_url, 'dput_hooks', '')
68 params['test_result'] = "PASSED"
69
70+def get_jenkins_params(mp):
71+ params = {
72+ 'landing_candidate': launchpadutils.get_source_repo(mp),
73+ 'merge_proposal': mp.web_link,
74+ 'candidate_revision': launchpadutils.get_latest_revision(mp)}
75+
76+ if '+git' in mp.web_link:
77+ params['landing_candidate_branch'] = launchpadutils.get_source_branch(mp)
78+
79+ return params
80
81 def start_jenkins_job(lp_handle, launchpaduser, jenkins_url, jenkins_job, mp,
82 fasttrack_merge=False):
83@@ -686,10 +696,8 @@
84 """
85 j = jenkins.Jenkins(jenkins_url, get_config_option('jenkins_user'),
86 get_config_option('jenkins_password'))
87- jenkins_params = {
88- 'landing_candidate': mp.source_branch.bzr_identity,
89- 'merge_proposal': mp.web_link,
90- 'candidate_revision': mp.source_branch.revision_count}
91+
92+ jenkins_params = get_jenkins_params(mp)
93
94 job_info = j.get_job_info(jenkins_job)
95 if not job_info['buildable']:
96
97=== modified file 'jlp/launchpadutils.py'
98--- jlp/launchpadutils.py 2016-08-13 18:04:14 +0000
99+++ jlp/launchpadutils.py 2016-08-13 18:04:14 +0000
100@@ -9,6 +9,23 @@
101 DISAPPROVE = 'Disapprove'
102 NEEDS_FIXING = 'Needs Fixing'
103
104+def get_source_repo(mp):
105+ if '+git' in mp.web_link:
106+ return mp.source_git_repository.git_identity
107+ else:
108+ return mp.target_branch.bzr_identity
109+
110+def get_source_branch(mp):
111+ if '+git' in mp.web_link:
112+ return mp.source_git_path.replace('refs/heads/', '')
113+ else:
114+ return mp.source_branch.bzr_identity
115+
116+def get_target_branch(mp):
117+ if '+git' in mp.web_link:
118+ return mp.target_git_path.replace('refs/heads/', '')
119+ else:
120+ return mp.target_branch.bzr_identity
121
122 def get_vote_subject(mp):
123 """Given a mp handle return a subject for the vote message
124@@ -271,6 +288,11 @@
125 return True
126 return False
127
128+def get_review_revision_regex(mp):
129+ if '+git' in mp.web_link:
130+ return '^(PASSED|FAILED): Continuous integration, rev:([0-9a-f]+)'
131+ else:
132+ return '^(PASSED|FAILED): Continuous integration, rev:(\d+)'
133
134 def get_latest_review(launchpad_user, mp):
135 """Return the latest revision reviewed by the given launchpad_user.
136@@ -287,12 +309,25 @@
137 if comment.author.name == launchpad_user.name:
138 if comment.vote_tag == launchpad_review_type:
139 m = re.search(
140- '^(PASSED|FAILED): Continuous integration, rev:(\d+)',
141+ get_review_revision_regex(mp),
142 comment.message_body)
143- if m and (int(m.group(2)) > revision):
144- revision = int(m.group(2))
145+ if m:
146+ revision = m.group(2)
147 return revision
148
149+def get_latest_revision(mp):
150+ """Return the latest revision of the given merge proposal.
151+
152+ :param mp: handle to merge proposal
153+ """
154+ if '+git' in mp.web_link:
155+ for ref in mp.source_git_repository.refs_collection:
156+ if ref.path == mp.source_git_path:
157+ return ref.commit_sha1
158+ return str(0)
159+ else:
160+ return mp.source_branch.revision_count
161+
162
163 def latest_candidate_validated(launchpad_user, mp):
164 """Return if the latest candidate revision of the merge proposal is
165@@ -305,9 +340,11 @@
166
167 latest_review = get_latest_review(launchpad_user, mp)
168 logger.debug('Latest_review is revision: ' + str(latest_review))
169- if latest_review >= mp.source_branch.revision_count:
170+ latest_revision = get_latest_revision(mp)
171+ logger.debug('Latest revision is: ' + str(latest_revision))
172+ if latest_review == latest_revision:
173 logger.debug('Skipping this MP. Current revision: ' +
174- str(mp.source_branch.revision_count))
175+ str(latest_revision))
176 return True
177 return False
178
179
180=== modified file 'tests/test_launchpadTrigger.py'
181--- tests/test_launchpadTrigger.py 2013-05-10 14:10:52 +0000
182+++ tests/test_launchpadTrigger.py 2016-08-13 18:04:14 +0000
183@@ -142,6 +142,27 @@
184 'http://localhost:8080/')
185
186
187+ def test_trigger_git_ci(self):
188+ """Trigger CI got a git repo."""
189+
190+ sys_argv = ["launchpadTrigger.py",
191+ "--branch=lp:faux-dbus-test-runner",
192+ "--trigger-ci",
193+ "--job=faux-dbus-test-runner",
194+ "--repo-type=git"]
195+ with patch('sys.argv', sys_argv), \
196+ patch('jlp.commands.launchpadTrigger.get_merge_proposals') as \
197+ get_merge_proposals, \
198+ patch('jlp.commands.launchpadTrigger.jenkinsutils.' +
199+ 'trigger_ci_build') as trigger_ci_build:
200+ get_merge_proposals.return_value = [self.merge_proposal]
201+ launchpadTrigger()
202+ get_merge_proposals.assert_called_with(self.launchpad,
203+ 'lp:faux-dbus-test-runner',
204+ ['Needs review'],
205+ 'git')
206+
207+
208 class TestLockNames(PatchedLaunchpadTriggerTest):
209
210 sys_argv = ["launchpadTrigger.py",
211@@ -192,7 +213,7 @@
212 lock_name=self.lock_name)
213 trigger_ci_build.assert_called_with(
214 None, None, get_config_option('jenkins_url'),
215- self.expected_cache_dir)
216+ self.expected_cache_dir, 'bazaar')
217
218 def test_lock_name_autolanding(self):
219 """test trigger_jenkins method for correct use of lock_name param"""
220@@ -204,4 +225,17 @@
221 lock_name=self.lock_name)
222 trigger_al_build.assert_called_with(
223 None, None, get_config_option('jenkins_url'),
224- False, self.expected_cache_dir)
225+ False, self.expected_cache_dir, 'bazaar')
226+
227+ def test_repo_type_is_propagated(self):
228+ """test trigger_jenkins method for correct use of lock_name param"""
229+
230+ with patch('jlp.commands.launchpadTrigger.trigger_al_build') \
231+ as trigger_al_build:
232+ trigger_jenkins(branch=None,
233+ autoland=True,
234+ lock_name=self.lock_name,
235+ repo_type='git')
236+ trigger_al_build.assert_called_with(
237+ None, None, get_config_option('jenkins_url'),
238+ False, self.expected_cache_dir, 'git')
239
240=== modified file 'tests/test_launchpadutils.py'
241--- tests/test_launchpadutils.py 2016-08-13 18:04:14 +0000
242+++ tests/test_launchpadutils.py 2016-08-13 18:04:14 +0000
243@@ -411,7 +411,7 @@
244 "URL:..."
245 mp.all_comments = [comment]
246 self.assertEqual(
247- launchpadutils.get_latest_review(self.launchpad_user, mp), 47)
248+ launchpadutils.get_latest_review(self.launchpad_user, mp), '47')
249
250 def test_get_latest_review_which_failed(self):
251 mp = MagicMock()
252@@ -422,7 +422,7 @@
253 "URL:..."
254 mp.all_comments = [comment]
255 self.assertEqual(
256- launchpadutils.get_latest_review(self.launchpad_user, mp), 47)
257+ launchpadutils.get_latest_review(self.launchpad_user, mp), '47')
258
259 @patch('jlp.launchpadutils.get_latest_review', new=lambda x, y: 60)
260 def test_new_mp_candidate_revision_in_queue(self):
261@@ -448,6 +448,77 @@
262 self.launchpad_user, mp)
263 self.assertTrue(ret)
264
265+class TestLatestReviewForGitMPs(unittest.TestCase):
266+ def setUp(self):
267+ self.launchpad_user = MagicMock()
268+ self.jenkinsUserName = 'name'
269+ self.launchpad_user.name = self.jenkinsUserName
270+
271+ def create_mp(self):
272+ mp = MagicMock()
273+ mp.web_link = 'https://code.launchpad.net/~user/project/+git/project/+merge/777'
274+ return mp
275+
276+ def create_mp_with_revision(self, revision):
277+ mp = self.create_mp()
278+ path = "refs/heads/nice"
279+ ref = MagicMock()
280+ ref.path = path
281+ ref.commit_sha1 = revision
282+ mp.source_git_path = path
283+ mp.source_git_repository.refs_collection = [ref]
284+ return mp
285+
286+ def test_get_latest_review_no_comments(self):
287+ mp = self.create_mp()
288+ mp.all_comments = []
289+ self.assertEqual(
290+ launchpadutils.get_latest_review(self.launchpad_user, mp), 0)
291+
292+ def test_get_latest_review_unrelated_comment(self):
293+ mp = self.create_mp()
294+ comment = MagicMock()
295+ comment.vote_tag = get_config_option('launchpad_review_type')
296+ comment.message_body = 'unrelated comment'
297+ mp.all_comments = [comment]
298+ self.assertEqual(
299+ launchpadutils.get_latest_review(self.launchpad_user, mp), 0)
300+
301+ def test_get_latest_review_which_passed(self):
302+ mp = self.create_mp()
303+ comment = MagicMock()
304+ comment.author.name = self.jenkinsUserName
305+ comment.vote_tag = get_config_option('launchpad_review_type')
306+ comment.message_body = "PASSED: Continuous integration, rev:2fd4e1c67a2d28fced849ee1bb76e7391b93eb12\n" + \
307+ "URL:..."
308+ mp.all_comments = [comment]
309+ self.assertEqual(
310+ launchpadutils.get_latest_review(self.launchpad_user, mp), '2fd4e1c67a2d28fced849ee1bb76e7391b93eb12')
311+
312+ def test_get_latest_review_which_failed(self):
313+ mp = self.create_mp()
314+ comment = MagicMock()
315+ comment.author.name = self.jenkinsUserName
316+ comment.vote_tag = get_config_option('launchpad_review_type')
317+ comment.message_body = "FAILED: Continuous integration, rev:2fd4e1c67a2d28fced849ee1bb76e7391b93eb12\n" + \
318+ "URL:..."
319+ mp.all_comments = [comment]
320+ self.assertEqual(
321+ launchpadutils.get_latest_review(self.launchpad_user, mp), '2fd4e1c67a2d28fced849ee1bb76e7391b93eb12')
322+
323+ @patch('jlp.launchpadutils.get_latest_review', new=lambda x, y: '2fd4e1c67a2d28fced849ee1bb76e7391b93eb12')
324+ def test_new_mp_candidate_revision_in_queue(self):
325+ mp = self.create_mp_with_revision('de9f2c7fd25e1b3afad3e85a0bd17d9b100db4b3')
326+ ret = launchpadutils.latest_candidate_validated(
327+ self.launchpad_user, mp)
328+ self.assertFalse(ret)
329+
330+ @patch('jlp.launchpadutils.get_latest_review', new=lambda x, y: '2fd4e1c67a2d28fced849ee1bb76e7391b93eb12')
331+ def test_mp_already_validated(self):
332+ mp = self.create_mp_with_revision('2fd4e1c67a2d28fced849ee1bb76e7391b93eb12')
333+ ret = launchpadutils.latest_candidate_validated(
334+ self.launchpad_user, mp)
335+ self.assertTrue(ret)
336
337 class TestApproveAndDisapprove(unittest.TestCase):
338 jenkinsUserName = 'jenkins-user'

Subscribers

People subscribed via source and target branches