Merge ~mthaddon/jenkins-launchpad-plugin/+git/jenkins-launchpad-plugin:comment-if-nominate-fails into jenkins-launchpad-plugin:master

Proposed by Tom Haddon
Status: Merged
Approved by: Paride Legovini
Approved revision: 16d08ec3a49ddee753281a647bca5bd08c92f99a
Merged at revision: 16d08ec3a49ddee753281a647bca5bd08c92f99a
Proposed branch: ~mthaddon/jenkins-launchpad-plugin/+git/jenkins-launchpad-plugin:comment-if-nominate-fails
Merge into: jenkins-launchpad-plugin:master
Diff against target: 146 lines (+68/-12)
3 files modified
.gitignore (+1/-0)
jlp/jenkinsutils.py (+26/-9)
tests/test_jenkinsutils.py (+41/-3)
Reviewer Review Type Date Requested Status
Paride Legovini Approve
Review via email: mp+398966@code.launchpad.net

Commit message

Add a comment as a fallback if nominateReviewer fails in start_jenkins_job

Description of the change

Add a comment as a fallback if nominateReviewer fails in start_jenkins_job.

Per lp#1917331 allow jenkins-launchpad-plugin to work with less permissions to the project in question.

To post a comment you must log in.
Revision history for this message
Paride Legovini (paride) wrote :

The change LGTM, I'd just add an info or warning message printed by launchpadTrigger to inform the CI maintainer about the fallback to a comment because the bot user doesn't have permissions. I can see myself being confused by the fact that some jobs add the commend, and others do not.

Revision history for this message
Tom Haddon (mthaddon) wrote :
Revision history for this message
Alvaro Uria (aluria) wrote :

I've also tested it in 3 different MPs and worked as expected.

See one of the tests [1].

1. https://code.launchpad.net/~aluria/juju-verify/+git/juju-verify/+merge/399084

Revision history for this message
Paride Legovini (paride) wrote :

LGTM, thanks!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/.gitignore b/.gitignore
2index cffb0d6..b2c77d6 100644
3--- a/.gitignore
4+++ b/.gitignore
5@@ -8,5 +8,6 @@ docs/_build/*
6 /man
7 __pycache__
8 *.pyc
9+*.swp
10 build
11 dist
12diff --git a/jlp/jenkinsutils.py b/jlp/jenkinsutils.py
13index 8b94b1b..9c8a839 100644
14--- a/jlp/jenkinsutils.py
15+++ b/jlp/jenkinsutils.py
16@@ -737,18 +737,34 @@ def start_jenkins_job(lp_handle, launchpaduser, jenkins_url, jenkins_job, mp,
17 logger.debug('Job is not buildable (probably disabled)')
18 return False
19
20+ review_type = get_config_option('launchpad_review_type')
21+ subject = launchpadutils.get_vote_subject(mp)
22+
23 try:
24 mp.nominateReviewer(
25 reviewer=launchpaduser,
26- review_type=get_config_option('launchpad_review_type'))
27+ review_type=review_type)
28 except Unauthorized:
29+ # If we fail to nominate a review it could be because we don't have
30+ # the required permissions, but we may still be able to comment on
31+ # the merge propsal, so try that before failing.
32 try:
33- username = lp_handle.me.name
34+ message = ("A CI job is currently in progress. A follow up "
35+ "comment will be added when it completes.")
36+ mp.createComment(
37+ content=message,
38+ review_type=review_type,
39+ subject=subject)
40+ logger.info("Missing permissions to nominate a review, so added "
41+ "a comment instead.")
42 except Unauthorized:
43- username = '<anonymous>'
44- logger.info('You (' + username + ') are not authorized to review '
45- 'this merge proposal. CI process will now be stopped.')
46- return False
47+ try:
48+ username = lp_handle.me.name
49+ except Unauthorized:
50+ username = '<anonymous>'
51+ logger.error('You (' + username + ') are not authorized to review '
52+ 'this merge proposal. CI process will now be stopped.')
53+ return False
54
55 try:
56 is_merge_only = launchpadutils.is_merge_only(mp)
57@@ -778,9 +794,10 @@ def start_jenkins_job(lp_handle, launchpaduser, jenkins_url, jenkins_job, mp,
58 logger.debug('Starting a job failed')
59 message = "ERROR: failed to start a jenkins job"
60 mp.createComment(
61- review_type=get_config_option('launchpad_review_type'),
62- vote='Disapprove', subject=launchpadutils.get_vote_subject(mp),
63- content=message)
64+ content=message,
65+ review_type=review_type,
66+ subject=subject,
67+ vote='Disapprove')
68
69
70 def trigger_ci_build(lp_handle, mps, jenkins_job, jenkins_url):
71diff --git a/tests/test_jenkinsutils.py b/tests/test_jenkinsutils.py
72index 8c7bd85..e0565d2 100644
73--- a/tests/test_jenkinsutils.py
74+++ b/tests/test_jenkinsutils.py
75@@ -1,4 +1,4 @@
76-from unittest.mock import MagicMock, patch
77+from unittest.mock import MagicMock, call, patch
78 from jlp import jenkinsutils, launchpadutils, _config
79 import unittest
80 from tests import JenkinsJSONData
81@@ -954,6 +954,14 @@ class TestStartJenkinsJob(unittest.TestCase):
82 'url', 'jenkins_job', mp)
83 self.assertEqual(j.build_job.call_count, 1)
84 self.assertEqual(mp.nominateReviewer.call_count, 1)
85+ expected_call_args_list = [
86+ call(reviewer=self.launchpad_user,
87+ review_type='continuous-integration')]
88+ self.assertEqual(mp.nominateReviewer.call_args_list,
89+ expected_call_args_list)
90+ # We have no failure to nominateReviewer, so there is
91+ # no need to add a comment.
92+ self.assertEqual(mp.createComment.call_count, 0)
93
94 def test_start_jenkins_job_while_diff_is_not_yet_generated(self):
95 mp = MagicMock()
96@@ -985,10 +993,12 @@ class TestStartJenkinsJob(unittest.TestCase):
97 'url', 'jenkins_job', mp)
98 self.assertEqual(mp.createComment.call_count, 1)
99
100- def test_start_jenkins_job_and_raise_unauthorized(self):
101+ def test_start_jenkins_job_nominate_unauthorized(self):
102 mp = MagicMock()
103 mp.web_link = 'http://my-example-url.com'
104 mp.nominateReviewer.side_effect = Unauthorized("unauthorized", '')
105+ mp.source_branch.display_name = "source_branch"
106+ mp.target_branch.display_name = "target_branch"
107 j = MagicMock()
108 j.get_job_info = MagicMock(return_value={'buildable': True})
109 jenkinsInstance = MagicMock()
110@@ -997,7 +1007,35 @@ class TestStartJenkinsJob(unittest.TestCase):
111 ret = jenkinsutils.start_jenkins_job(self.lp_handle,
112 self.launchpad_user, 'url',
113 'jenkins_job', mp)
114- self.assertEqual(mp.createComment.call_count, 0)
115+ self.assertEqual(mp.nominateReviewer.call_count, 1)
116+ # nominateReviewer is raising an exception, but createComment
117+ # can complete without problems.
118+ self.assertEqual(mp.createComment.call_count, 1)
119+ expected_content = ("A CI job is currently in progress. A follow "
120+ "up comment will be added when it completes.")
121+ expected_subject = "Re: [Merge] source_branch into target_branch"
122+ expected_call_args_list = [
123+ call(content=expected_content,
124+ review_type='continuous-integration',
125+ subject=expected_subject)]
126+ self.assertEqual(mp.createComment.call_args_list,
127+ expected_call_args_list)
128+
129+ def test_start_jenkins_job_nominate_and_comment_unauthorized(self):
130+ mp = MagicMock()
131+ mp.web_link = 'http://my-example-url.com'
132+ mp.nominateReviewer.side_effect = Unauthorized("unauthorized", '')
133+ mp.createComment.side_effect = Unauthorized("unauthorized", '')
134+ j = MagicMock()
135+ j.get_job_info = MagicMock(return_value={'buildable': True})
136+ jenkinsInstance = MagicMock()
137+ jenkinsInstance.Jenkins = MagicMock(return_value=j)
138+ with patch('jlp.jenkinsutils.jenkins', new=jenkinsInstance):
139+ ret = jenkinsutils.start_jenkins_job(self.lp_handle,
140+ self.launchpad_user, 'url',
141+ 'jenkins_job', mp)
142+ self.assertEqual(mp.nominateReviewer.call_count, 1)
143+ self.assertEqual(mp.createComment.call_count, 1)
144 self.assertEqual(ret, False)
145
146 def test_start_nonbuildable_jenkins_job(self):

Subscribers

People subscribed via source and target branches

to all changes: