Merge lp:~asbalderson/jenkins-launchpad-plugin/templating into lp:jenkins-launchpad-plugin
- templating
- Merge into trunk
Proposed by
Alexander Balderson
Status: | Merged |
---|---|
Approved by: | Joshua Powers |
Approved revision: | 163 |
Merged at revision: | 146 |
Proposed branch: | lp:~asbalderson/jenkins-launchpad-plugin/templating |
Merge into: | lp:jenkins-launchpad-plugin |
Diff against target: |
1333 lines (+340/-551) 28 files modified
HACKING (+1/-1) MANIFEST.in (+1/-0) README (+33/-0) jlp/__init__.py (+12/-0) jlp/commands/autoland.py (+35/-23) jlp/commands/voteOnMergeProposal.py (+30/-15) jlp/jenkinsutils.py (+17/-130) jlp/launchpadutils.py (+56/-105) setup.py (+3/-0) templates/autoland_header.j2 (+1/-0) templates/ci_test.j2 (+4/-0) templates/commit_message_empty.j2 (+4/-0) templates/coverity.j2 (+4/-0) templates/executed_tests.j2 (+7/-0) templates/footer.j2 (+7/-0) templates/invalid_commit_message.j2 (+4/-0) templates/invalid_revid.j2 (+3/-0) templates/landing_failed.j2 (+3/-0) templates/merge_failed.j2 (+3/-0) templates/merged.j2 (+2/-0) templates/no_commit.j2 (+4/-0) templates/push_failed.j2 (+3/-0) templates/rebuild.j2 (+2/-0) templates/unapproved_changes.j2 (+3/-0) tests/test_autoland.py (+2/-2) tests/test_jenkinsutils.py (+8/-54) tests/test_launchpadutils.py (+48/-128) tests/test_voteOnMergeProposal.py (+40/-93) |
To merge this branch: | bzr merge lp:~asbalderson/jenkins-launchpad-plugin/templating |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Joshua Powers | Pending | ||
Review via email: mp+366484@code.launchpad.net |
Commit message
Adjust messaging to launchpad to use jinja2 templates.
Enable a user to customize the messages sent to launchpad based on results.
Adds the run requirement of Jinja2
Description of the change
Generally this change allowed for removing a big portion of code that was creating text and allowed for some simplification and reuse.
To post a comment you must log in.
- 162. By Alexander Balderson
-
add new lines to end of templates
add unit tests for voteOnMergeProposal - 163. By Alexander Balderson
-
fix unit tests, add readme
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'HACKING' | |||
2 | --- HACKING 2018-03-07 09:21:26 +0000 | |||
3 | +++ HACKING 2019-05-09 18:32:44 +0000 | |||
4 | @@ -4,7 +4,7 @@ | |||
5 | 4 | 4 | ||
6 | 5 | 5 | ||
7 | 6 | You need the following if you want to make changes/run this project: | 6 | You need the following if you want to make changes/run this project: |
9 | 7 | * sudo apt-get install -y python-launchpadlib python-bzrlib python-mock python-testtools python-jenkins python-lockfile python-testscenarios python-pyruntest python-yaml python-git | 7 | * sudo apt-get install -y python-launchpadlib python-bzrlib python-mock python-testtools python-jenkins python-lockfile python-testscenarios python-pyruntest python-yaml python-git python-jinja2 |
10 | 8 | * install tarmac: | 8 | * install tarmac: |
11 | 9 | bzr branch lp:tarmac | 9 | bzr branch lp:tarmac |
12 | 10 | cd tarmac | 10 | cd tarmac |
13 | 11 | 11 | ||
14 | === added file 'MANIFEST.in' | |||
15 | --- MANIFEST.in 1970-01-01 00:00:00 +0000 | |||
16 | +++ MANIFEST.in 2019-05-09 18:32:44 +0000 | |||
17 | @@ -0,0 +1,1 @@ | |||
18 | 1 | include templates/*.j2 | ||
19 | 0 | \ No newline at end of file | 2 | \ No newline at end of file |
20 | 1 | 3 | ||
21 | === modified file 'README' | |||
22 | --- README 2013-05-20 11:47:35 +0000 | |||
23 | +++ README 2019-05-09 18:32:44 +0000 | |||
24 | @@ -7,3 +7,36 @@ | |||
25 | 7 | 7 | ||
26 | 8 | See also /usr/share/doc/jenkins-launchpad-plugin/html/index.html for | 8 | See also /usr/share/doc/jenkins-launchpad-plugin/html/index.html for |
27 | 9 | more info. | 9 | more info. |
28 | 10 | |||
29 | 11 | # TEMPLATING | ||
30 | 12 | |||
31 | 13 | Jenkins Launchpad Plugin commands voteOnMergeProposal and autoland both | ||
32 | 14 | support using custom templates for the messages sent to launchpad. The | ||
33 | 15 | message templates imported using jinja2. See http://jinja.pocoo.org/docs/2.10/templates/ | ||
34 | 16 | for more information. | ||
35 | 17 | |||
36 | 18 | When using custom templating, the user only needs to update the | ||
37 | 19 | templates with messages they wish to change; the defaults will be | ||
38 | 20 | used in all other cases. | ||
39 | 21 | |||
40 | 22 | When working with custom templates, it's recommended that the user starts with | ||
41 | 23 | a default template and makes the changes they wish to see. | ||
42 | 24 | |||
43 | 25 | ## Arguments | ||
44 | 26 | |||
45 | 27 | The arguments are loaded into a dictionary called "args" so all calls need | ||
46 | 28 | to be prefixed with "args." | ||
47 | 29 | |||
48 | 30 | `result` defines the result from the tests, usually passed in as an argument | ||
49 | 31 | to the script, "PASSED" or "FAILED" | ||
50 | 32 | `revision` defines the git or bzr revision being reviewed. | ||
51 | 33 | `build_url` defines the URL for the build being run. it can be used to generate | ||
52 | 34 | the rebuild URL. | ||
53 | 35 | `merge_url` defines the URL to the merge request being reviewed. | ||
54 | 36 | `coverity_artifacts` defines artifcats built during tests run for this revision. | ||
55 | 37 | It is either None or a list of artificats. | ||
56 | 38 | `executed_tests` defines tests run against this propsal. It is a list of | ||
57 | 39 | dictionaries, where each dictionary defines 3 values: | ||
58 | 40 | `deb` defines list of jenkins urls for debs generated from the test. | ||
59 | 41 | `output` defines the jenkins url for the executed test. | ||
60 | 42 | `result` defines the result of that particular build job reported by jenkins. | ||
61 | 10 | 43 | ||
62 | === modified file 'jlp/__init__.py' | |||
63 | --- jlp/__init__.py 2015-12-14 04:36:05 +0000 | |||
64 | +++ jlp/__init__.py 2019-05-09 18:32:44 +0000 | |||
65 | @@ -11,6 +11,7 @@ | |||
66 | 11 | __version__ = '0.1' | 11 | __version__ = '0.1' |
67 | 12 | __author__ = 'Martin Mrazik' | 12 | __author__ = 'Martin Mrazik' |
68 | 13 | 13 | ||
69 | 14 | import jinja2 | ||
70 | 14 | import yaml | 15 | import yaml |
71 | 15 | import os | 16 | import os |
72 | 16 | import logging | 17 | import logging |
73 | @@ -85,6 +86,17 @@ | |||
74 | 85 | stdout_handler.setLevel(log_level) | 86 | stdout_handler.setLevel(log_level) |
75 | 86 | 87 | ||
76 | 87 | 88 | ||
77 | 89 | def get_jinja_environment(extra_dir=None): | ||
78 | 90 | default_templates = '/'.join(__file__.split('/')[0:-2]) + '/templates' | ||
79 | 91 | templates = [default_templates] | ||
80 | 92 | if extra_dir: | ||
81 | 93 | # we load the arg templates first | ||
82 | 94 | # then add in any missing templates from the defaults | ||
83 | 95 | templates.insert(0, extra_dir) | ||
84 | 96 | loader = jinja2.FileSystemLoader(templates) | ||
85 | 97 | env = jinja2.Environment(loader=loader) | ||
86 | 98 | return env | ||
87 | 99 | |||
88 | 88 | set_log_level(logger, stdout_handler) | 100 | set_log_level(logger, stdout_handler) |
89 | 89 | 101 | ||
90 | 90 | 102 | ||
91 | 91 | 103 | ||
92 | === modified file 'jlp/commands/autoland.py' | |||
93 | --- jlp/commands/autoland.py 2019-03-15 16:18:36 +0000 | |||
94 | +++ jlp/commands/autoland.py 2019-05-09 18:32:44 +0000 | |||
95 | @@ -3,12 +3,12 @@ | |||
96 | 3 | import argparse | 3 | import argparse |
97 | 4 | import atexit | 4 | import atexit |
98 | 5 | import git | 5 | import git |
100 | 6 | from jlp.launchpadutils import (build_state, LaunchpadVote, get_vote_subject, | 6 | from jlp.launchpadutils import (LaunchpadVote, get_vote_subject, |
101 | 7 | get_target_branch, get_source_branch, | 7 | get_target_branch, get_source_branch, |
102 | 8 | is_git_project) | 8 | is_git_project) |
103 | 9 | from jlp import (launchpadutils, Branch, | 9 | from jlp import (launchpadutils, Branch, |
104 | 10 | DputRunner, jenkinsutils, get_launchpad, | 10 | DputRunner, jenkinsutils, get_launchpad, |
106 | 11 | get_config_option, logger) | 11 | get_config_option, logger, get_jinja_environment) |
107 | 12 | from tarmac.exceptions import TarmacMergeError, BranchHasConflicts | 12 | from tarmac.exceptions import TarmacMergeError, BranchHasConflicts |
108 | 13 | from bzrlib.errors import LockFailed | 13 | from bzrlib.errors import LockFailed |
109 | 14 | import os | 14 | import os |
110 | @@ -74,23 +74,30 @@ | |||
111 | 74 | return formatted_message | 74 | return formatted_message |
112 | 75 | 75 | ||
113 | 76 | 76 | ||
118 | 77 | def change_mp_status(mp, reason, args, vote): | 77 | def change_mp_status(mp, template, args, vote): |
119 | 78 | args[reason] = True | 78 | if template != 'merged.j2': |
120 | 79 | mp_state, message = build_state(args) | 79 | args['test_result'] = 'FAILED' |
121 | 80 | message = jenkinsutils.format_message_for_mp_update( | 80 | env = get_jinja_environment(args['template_dir']) |
122 | 81 | real_template = env.get_template(template) | ||
123 | 82 | template_args = launchpadutils.get_template_args( | ||
124 | 83 | args['test_result'], | ||
125 | 84 | args['revision'], | ||
126 | 81 | args['build_job_url'], | 85 | args['build_job_url'], |
132 | 82 | message, | 86 | args['merge_proposal']) |
133 | 83 | include_rebuild_link=False) | 87 | msg = real_template.render(args=template_args) |
134 | 84 | launchpadutils.change_mp_status(mp, mp_state, message, args['revision'], | 88 | launchpadutils.report_to_launchpad( |
135 | 85 | vote) | 89 | mp, |
136 | 86 | 90 | msg, | |
137 | 91 | args['revision'], | ||
138 | 92 | vote=vote | ||
139 | 93 | ) | ||
140 | 87 | 94 | ||
141 | 88 | def merge_and_commit(mp, args, lp_handle): | 95 | def merge_and_commit(mp, args, lp_handle): |
142 | 89 | # if there is no reviewed_revid then something went wrong | 96 | # if there is no reviewed_revid then something went wrong |
143 | 90 | if not mp.reviewed_revid: | 97 | if not mp.reviewed_revid: |
144 | 91 | logger.debug('Approved revid is not set ' | 98 | logger.debug('Approved revid is not set ' |
145 | 92 | '(maybe a permission problem?). Failing autolanding.') | 99 | '(maybe a permission problem?). Failing autolanding.') |
147 | 93 | change_mp_status(mp, 'invalid_revid', | 100 | change_mp_status(mp, 'invalid_revid.j2', |
148 | 94 | args, LaunchpadVote.NEEDS_FIXING) | 101 | args, LaunchpadVote.NEEDS_FIXING) |
149 | 95 | return 1 | 102 | return 1 |
150 | 96 | 103 | ||
151 | @@ -196,7 +203,7 @@ | |||
152 | 196 | if source_revid != mp.reviewed_revid: | 203 | if source_revid != mp.reviewed_revid: |
153 | 197 | logger.debug('Unapproved changes made after approval. ' | 204 | logger.debug('Unapproved changes made after approval. ' |
154 | 198 | 'Failing autolanding.') | 205 | 'Failing autolanding.') |
156 | 199 | change_mp_status(mp, 'unapproved_changes', | 206 | change_mp_status(mp, 'unapproved_changes.j2', |
157 | 200 | args, LaunchpadVote.NEEDS_FIXING) | 207 | args, LaunchpadVote.NEEDS_FIXING) |
158 | 201 | return 1 | 208 | return 1 |
159 | 202 | 209 | ||
160 | @@ -223,11 +230,13 @@ | |||
161 | 223 | # Lint the commit message | 230 | # Lint the commit message |
162 | 224 | message, errors = lint_commit_message(message) | 231 | message, errors = lint_commit_message(message) |
163 | 225 | if errors: | 232 | if errors: |
166 | 226 | error_msg = 'Commit message lints:\n - ' + ' - '.join(errors) | 233 | env = get_jinja_environment(args['template_dir']) |
167 | 227 | logger.debug(error_msg) | 234 | real_template = env.get_template('invalid_commit_message.j2') |
168 | 235 | msg = real_template.render(errors=errors) | ||
169 | 236 | logger.debug(msg) | ||
170 | 228 | mp.createComment( | 237 | mp.createComment( |
171 | 229 | subject='Invalid Commit Message', | 238 | subject='Invalid Commit Message', |
173 | 230 | content=error_msg, | 239 | content=msg, |
174 | 231 | vote=LaunchpadVote.NEEDS_FIXING | 240 | vote=LaunchpadVote.NEEDS_FIXING |
175 | 232 | ) | 241 | ) |
176 | 233 | mp.setStatus(status='Needs review', revid=mp.reviewed_revid) | 242 | mp.setStatus(status='Needs review', revid=mp.reviewed_revid) |
177 | @@ -245,7 +254,6 @@ | |||
178 | 245 | target.git.push() | 254 | target.git.push() |
179 | 246 | 255 | ||
180 | 247 | logger.debug('New revision is: %s' % target.head.object.hexsha) | 256 | logger.debug('New revision is: %s' % target.head.object.hexsha) |
181 | 248 | |||
182 | 249 | mp.setStatus(status='Merged') | 257 | mp.setStatus(status='Merged') |
183 | 250 | 258 | ||
184 | 251 | logger.debug('Closing bugs') | 259 | logger.debug('Closing bugs') |
185 | @@ -271,7 +279,7 @@ | |||
186 | 271 | if source.bzr_branch.revno() > approved: | 279 | if source.bzr_branch.revno() > approved: |
187 | 272 | logger.debug('Unapproved changes made after approval. ' | 280 | logger.debug('Unapproved changes made after approval. ' |
188 | 273 | 'Failing autolanding.') | 281 | 'Failing autolanding.') |
190 | 274 | change_mp_status(mp, 'unapproved_changes', | 282 | change_mp_status(mp, 'unapproved_changes.j2', |
191 | 275 | args, LaunchpadVote.NEEDS_FIXING) | 283 | args, LaunchpadVote.NEEDS_FIXING) |
192 | 276 | return 1 | 284 | return 1 |
193 | 277 | 285 | ||
194 | @@ -322,18 +330,19 @@ | |||
195 | 322 | return 1 | 330 | return 1 |
196 | 323 | except BranchHasConflicts: | 331 | except BranchHasConflicts: |
197 | 324 | logger.info('Merging failed - branch has conflicts') | 332 | logger.info('Merging failed - branch has conflicts') |
199 | 325 | change_mp_status(mp, 'merge_failed', args, | 333 | |
200 | 334 | change_mp_status(mp, 'merge_failed.j2', args, | ||
201 | 326 | LaunchpadVote.NEEDS_FIXING) | 335 | LaunchpadVote.NEEDS_FIXING) |
202 | 327 | return 1 | 336 | return 1 |
203 | 328 | except TarmacMergeError: | 337 | except TarmacMergeError: |
204 | 329 | logger.info('Landing failed') | 338 | logger.info('Landing failed') |
206 | 330 | change_mp_status(mp, 'landing_failed', args, | 339 | change_mp_status(mp, 'landing_failed.j2', args, |
207 | 331 | LaunchpadVote.NEEDS_FIXING) | 340 | LaunchpadVote.NEEDS_FIXING) |
208 | 332 | return 1 | 341 | return 1 |
209 | 333 | except LockFailed: | 342 | except LockFailed: |
210 | 334 | logger.info('Bazaar error: LockFailed. Jenkins user is maybe not ' + | 343 | logger.info('Bazaar error: LockFailed. Jenkins user is maybe not ' + |
211 | 335 | 'allowed to push into target?') | 344 | 'allowed to push into target?') |
213 | 336 | change_mp_status(mp, 'landing_failed', args, | 345 | change_mp_status(mp, 'landing_failed.j2', args, |
214 | 337 | LaunchpadVote.NEEDS_FIXING) | 346 | LaunchpadVote.NEEDS_FIXING) |
215 | 338 | return 1 | 347 | return 1 |
216 | 339 | finally: | 348 | finally: |
217 | @@ -397,6 +406,9 @@ | |||
218 | 397 | "and don't modify the changlog in any other way") | 406 | "and don't modify the changlog in any other way") |
219 | 398 | parser.add_argument('--disable-squash', action='store_true', | 407 | parser.add_argument('--disable-squash', action='store_true', |
220 | 399 | help='Disable squashing during a merge') | 408 | help='Disable squashing during a merge') |
221 | 409 | parser.add_argument('-t', '--template-dir', | ||
222 | 410 | help='Optional directory of alternate jinja2 templates.', | ||
223 | 411 | default=None) | ||
224 | 400 | 412 | ||
225 | 401 | args = vars(parser.parse_args()) | 413 | args = vars(parser.parse_args()) |
226 | 402 | 414 | ||
227 | @@ -419,7 +431,7 @@ | |||
228 | 419 | #check for test_result and fail if previous testing failed | 431 | #check for test_result and fail if previous testing failed |
229 | 420 | if args['test_result'] == 'FAILED': | 432 | if args['test_result'] == 'FAILED': |
230 | 421 | logger.debug('Previous test failed. Failing autolanding.') | 433 | logger.debug('Previous test failed. Failing autolanding.') |
232 | 422 | change_mp_status(mp, 'landing_failed', args, | 434 | change_mp_status(mp, 'landing_failed.j2', args, |
233 | 423 | LaunchpadVote.NEEDS_FIXING) | 435 | LaunchpadVote.NEEDS_FIXING) |
234 | 424 | return 0 | 436 | return 0 |
235 | 425 | 437 | ||
236 | @@ -429,7 +441,7 @@ | |||
237 | 429 | if not (launchpadutils.get_commit_message( | 441 | if not (launchpadutils.get_commit_message( |
238 | 430 | mp, args['use_description_for_commit'])): | 442 | mp, args['use_description_for_commit'])): |
239 | 431 | logger.debug('Commit message empty. Failing autolanding.') | 443 | logger.debug('Commit message empty. Failing autolanding.') |
241 | 432 | change_mp_status(mp, 'commit_message_empty', | 444 | change_mp_status(mp, 'commit_message_empty.j2', |
242 | 433 | args, LaunchpadVote.NEEDS_FIXING) | 445 | args, LaunchpadVote.NEEDS_FIXING) |
243 | 434 | return 1 | 446 | return 1 |
244 | 435 | 447 | ||
245 | 436 | 448 | ||
246 | === modified file 'jlp/commands/voteOnMergeProposal.py' | |||
247 | --- jlp/commands/voteOnMergeProposal.py 2018-03-08 10:03:10 +0000 | |||
248 | +++ jlp/commands/voteOnMergeProposal.py 2019-05-09 18:32:44 +0000 | |||
249 | @@ -1,6 +1,7 @@ | |||
250 | 1 | from argparse import ArgumentParser | 1 | from argparse import ArgumentParser |
251 | 2 | import atexit | 2 | import atexit |
253 | 3 | from jlp import launchpadutils, get_launchpad, logger | 3 | import jinja2 |
254 | 4 | from jlp import launchpadutils, get_launchpad, logger, get_config_option, get_jinja_environment | ||
255 | 4 | import re | 5 | import re |
256 | 5 | import os | 6 | import os |
257 | 6 | from shutil import rmtree | 7 | from shutil import rmtree |
258 | @@ -19,6 +20,9 @@ | |||
259 | 19 | help="URL of the merge proposal to update") | 20 | help="URL of the merge proposal to update") |
260 | 20 | parser.add_argument('-i', '--skip-message', action='store_true', | 21 | parser.add_argument('-i', '--skip-message', action='store_true', |
261 | 21 | help="Skip checking if a commit message is set") | 22 | help="Skip checking if a commit message is set") |
262 | 23 | parser.add_argument('-t', '--template-dir', | ||
263 | 24 | help='Optional directory of alternate jinja2 templates.', | ||
264 | 25 | default=None) | ||
265 | 22 | args = vars(parser.parse_args()) | 26 | args = vars(parser.parse_args()) |
266 | 23 | 27 | ||
267 | 24 | # launchpadlib is not thread/process safe so we are creating launchpadlib | 28 | # launchpadlib is not thread/process safe so we are creating launchpadlib |
268 | @@ -41,11 +45,10 @@ | |||
269 | 41 | 45 | ||
270 | 42 | # this is the status from tests | 46 | # this is the status from tests |
271 | 43 | overal_status = args['status'] | 47 | overal_status = args['status'] |
272 | 44 | # by default reason is empty as it is usually just a failed build | ||
273 | 45 | reason = '' | ||
274 | 46 | 48 | ||
275 | 47 | #override the status to FAILED and set reason if no commit message is set | 49 | #override the status to FAILED and set reason if no commit message is set |
276 | 48 | match = re.match('^(.*)/job/([^/]*)/.*$', args['build_url']) | 50 | match = re.match('^(.*)/job/([^/]*)/.*$', args['build_url']) |
277 | 51 | template = 'ci_test.j2' | ||
278 | 49 | if args['skip_message']: | 52 | if args['skip_message']: |
279 | 50 | logger.debug('Skipping check for empty commit message') | 53 | logger.debug('Skipping check for empty commit message') |
280 | 51 | elif match: | 54 | elif match: |
281 | @@ -54,22 +57,34 @@ | |||
282 | 54 | if not launchpadutils.is_commit_message_set(mp, | 57 | if not launchpadutils.is_commit_message_set(mp, |
283 | 55 | jenkins_job, jenkins_url): | 58 | jenkins_job, jenkins_url): |
284 | 56 | overal_status = 'FAILED' | 59 | overal_status = 'FAILED' |
290 | 57 | reason = "No commit message was specified in the merge " + \ | 60 | template = 'no_commit.j2' |
286 | 58 | "proposal. Click on the following link and set the " + \ | ||
287 | 59 | "commit message (if you want a jenkins rebuild you " +\ | ||
288 | 60 | "need to trigger it yourself):\n" + \ | ||
289 | 61 | args['merge_proposal'] + "/+edit-commit-message\n" | ||
291 | 62 | logger.debug('Commit message not set. Failing CI.') | 61 | logger.debug('Commit message not set. Failing CI.') |
292 | 63 | else: | 62 | else: |
293 | 64 | logger.debug('Unable to get job name from build_url.' + | 63 | logger.debug('Unable to get job name from build_url.' + |
294 | 65 | 'Skipping check for empty commit message') | 64 | 'Skipping check for empty commit message') |
295 | 66 | 65 | ||
303 | 67 | if overal_status == 'PASSED': | 66 | template_args = launchpadutils.get_template_args( |
304 | 68 | launchpadutils.approve_mp(mp, args['revision'], args['build_url']) | 67 | overal_status, |
305 | 69 | else: # status == False corresponds to NOT 'PASSED' | 68 | args['revision'], |
306 | 70 | launchpadutils.disapprove_mp(mp, | 69 | args['build_url'], |
307 | 71 | args['revision'], | 70 | args['merge_proposal'] |
308 | 72 | args['build_url'], | 71 | ) |
309 | 73 | reason) | 72 | env = get_jinja_environment(args['template_dir']) |
310 | 73 | real_template = env.get_template(template) | ||
311 | 74 | msg = real_template.render(args=template_args) | ||
312 | 75 | if overal_status != 'PASSED': | ||
313 | 76 | launchpadutils.report_to_launchpad( | ||
314 | 77 | mp, | ||
315 | 78 | msg, | ||
316 | 79 | args['revision'], | ||
317 | 80 | vote=launchpadutils.LaunchpadVote.NEEDS_FIXING | ||
318 | 81 | ) | ||
319 | 82 | else: | ||
320 | 83 | launchpadutils.report_to_launchpad( | ||
321 | 84 | mp, | ||
322 | 85 | msg, | ||
323 | 86 | args['revision'], | ||
324 | 87 | vote=launchpadutils.LaunchpadVote.APPROVE | ||
325 | 88 | ) | ||
326 | 74 | 89 | ||
327 | 75 | return 0 | 90 | return 0 |
328 | 76 | 91 | ||
329 | === modified file 'jlp/jenkinsutils.py' | |||
330 | --- jlp/jenkinsutils.py 2018-06-28 19:31:20 +0000 | |||
331 | +++ jlp/jenkinsutils.py 2019-05-09 18:32:44 +0000 | |||
332 | @@ -8,7 +8,7 @@ | |||
333 | 8 | from textwrap import dedent | 8 | from textwrap import dedent |
334 | 9 | from . import get_json_jenkins | 9 | from . import get_json_jenkins |
335 | 10 | from lazr.restfulclient.errors import Unauthorized | 10 | from lazr.restfulclient.errors import Unauthorized |
337 | 11 | from jlp import logger, get_config_option | 11 | from jlp import logger, get_config_option, get_jinja_environment |
338 | 12 | 12 | ||
339 | 13 | 13 | ||
340 | 14 | def normalize_url(url): | 14 | def normalize_url(url): |
341 | @@ -492,7 +492,7 @@ | |||
342 | 492 | 'url': | 492 | 'url': |
343 | 493 | 'result': | 493 | 'result': |
344 | 494 | } | 494 | } |
346 | 495 | """ | 495 | """ |
347 | 496 | return_data = [] | 496 | return_data = [] |
348 | 497 | 497 | ||
349 | 498 | json_request = jenkins_url + job_name + '/' + str(build_number) +\ | 498 | json_request = jenkins_url + job_name + '/' + str(build_number) +\ |
350 | @@ -785,128 +785,6 @@ | |||
351 | 785 | content=message) | 785 | content=message) |
352 | 786 | 786 | ||
353 | 787 | 787 | ||
354 | 788 | def _get_result_line(result, url): | ||
355 | 789 | """Helper method for get_executed_test_runs_message. | ||
356 | 790 | |||
357 | 791 | Given a result and url it returns a string. | ||
358 | 792 | In case the result is failed it provides a link to console output: | ||
359 | 793 | FAILED: http://[...]/./distribution=quantal,flavor=amd64/267/console | ||
360 | 794 | |||
361 | 795 | In case the result is success or unstable (some tests failed) it provides | ||
362 | 796 | a link to the job: | ||
363 | 797 | SUCCESS: http://[...]/distribution=quantal,flavor=amd64/267 | ||
364 | 798 | |||
365 | 799 | :param result: one of SUCCESS, UNSTABLE or FAILURE (comes from jenkins) | ||
366 | 800 | :param url: url of the build or configuration in case of matrix job | ||
367 | 801 | """ | ||
368 | 802 | |||
369 | 803 | url = url.rstrip('/') | ||
370 | 804 | if result == 'SUCCESS' or result == 'UNSTABLE': | ||
371 | 805 | if url.endswith('console'): | ||
372 | 806 | # strip "/console" | ||
373 | 807 | url = url[:-8] | ||
374 | 808 | return "\n {result}: {output}".format( | ||
375 | 809 | result=result, | ||
376 | 810 | output=url) | ||
377 | 811 | |||
378 | 812 | |||
379 | 813 | def get_executed_test_runs_message(url): | ||
380 | 814 | """Return a string with executed runs for a given jenkins build url. | ||
381 | 815 | |||
382 | 816 | :param url: url with jenkins build | ||
383 | 817 | |||
384 | 818 | This is an example result of this function: | ||
385 | 819 | ----snip---- | ||
386 | 820 | Executed test runs: | ||
387 | 821 | FAILURE: http://[...]/./distribution=raring,flavor=amd64/3/console | ||
388 | 822 | FAILURE: http://[...]/./distribution=raring,flavor=i386/3/console | ||
389 | 823 | SUCCESS: http://[...]/job-freestyle/7 | ||
390 | 824 | deb: http://[...]/job-freestyle/7/artifact/work/output/*zip*/output.zip | ||
391 | 825 | UNSTABLE: http://jenkins/job/freestyle-downstream/12 | ||
392 | 826 | Coverity artifacts: | ||
393 | 827 | http://[...]/artifact/results/coverity/CID_10895.html | ||
394 | 828 | http://[...]/results/coverity/CID_10896.html | ||
395 | 829 | http://[...]/results/coverity/CID_10895.html | ||
396 | 830 | http://[...]/results/coverity/CID_10896.html | ||
397 | 831 | ----snip---- | ||
398 | 832 | """ | ||
399 | 833 | |||
400 | 834 | ret = "\nExecuted test runs:" | ||
401 | 835 | jenkins = get_json_jenkins() | ||
402 | 836 | builds = get_executed_builds(jenkins, url) | ||
403 | 837 | coverity_artifacts = [] | ||
404 | 838 | for build in builds: | ||
405 | 839 | ret += _get_result_line( | ||
406 | 840 | build['result'], | ||
407 | 841 | hide_jenkins_url(build['output'])) | ||
408 | 842 | if build['output'].endswith('console'): | ||
409 | 843 | build_url = build['output'][:-len('console')] | ||
410 | 844 | artifacts = get_coverity_artifacts(jenkins, build_url) | ||
411 | 845 | debs = get_deb_artifacts(jenkins, build_url) | ||
412 | 846 | if debs: | ||
413 | 847 | ret += "\n deb: {}".format(hide_jenkins_url(debs)) | ||
414 | 848 | coverity_artifacts += artifacts | ||
415 | 849 | if coverity_artifacts: | ||
416 | 850 | ret += "\nCoverity artifacts:" | ||
417 | 851 | for artifact in coverity_artifacts: | ||
418 | 852 | ret += "\n {}".format(hide_jenkins_url(artifact)) | ||
419 | 853 | |||
420 | 854 | return ret | ||
421 | 855 | |||
422 | 856 | |||
423 | 857 | def format_message_for_mp_update(build_url, message=None, | ||
424 | 858 | include_rebuild_link=True): | ||
425 | 859 | """Return a formatted message that is then posted as comment to the merge | ||
426 | 860 | proposal. | ||
427 | 861 | |||
428 | 862 | The message consists of: | ||
429 | 863 | * message | ||
430 | 864 | * executed test-runs (and links to artifacts such as deb files) | ||
431 | 865 | * rubuild link | ||
432 | 866 | |||
433 | 867 | :params build_url: jenkins url of the build in question | ||
434 | 868 | :params message: custom message (usually PASSED/FAILED) | ||
435 | 869 | :include_rebuild_link: boolean which affects the generation of rebuild link | ||
436 | 870 | |||
437 | 871 | Example: | ||
438 | 872 | ----snip---- | ||
439 | 873 | PASSED: Continuous integration, rev:114 | ||
440 | 874 | http://s-jenkins.ubuntu-ci:8080/job/jenkins-launchpad-plugin-ci/267/ | ||
441 | 875 | Executed test runs: | ||
442 | 876 | SUCCESS: http://[...]/distribution=quantal,flavor=amd64/267 | ||
443 | 877 | |||
444 | 878 | Click here to trigger a rebuild: | ||
445 | 879 | http://s-jenkins.ubuntu-ci:8080/job/jenkins-launchpad-plugin-ci/267/rebuild | ||
446 | 880 | ----snip---- | ||
447 | 881 | |||
448 | 882 | """ | ||
449 | 883 | formatted_message = dedent('''\ | ||
450 | 884 | {message}{build_url}{executed_test_runs} | ||
451 | 885 | ''') | ||
452 | 886 | if include_rebuild_link: | ||
453 | 887 | formatted_message = formatted_message + dedent('''\ | ||
454 | 888 | |||
455 | 889 | Click here to trigger a rebuild: | ||
456 | 890 | {rebuild_url} | ||
457 | 891 | ''') | ||
458 | 892 | if not message: | ||
459 | 893 | message = '' | ||
460 | 894 | if not build_url: | ||
461 | 895 | build_url = '' | ||
462 | 896 | executed_test_runs_message = '' | ||
463 | 897 | else: | ||
464 | 898 | executed_test_runs_message = \ | ||
465 | 899 | get_executed_test_runs_message(build_url) | ||
466 | 900 | |||
467 | 901 | rebuild_url = '{build_url}/rebuild'.format( | ||
468 | 902 | build_url=build_url.rstrip('/')) | ||
469 | 903 | return formatted_message.format( | ||
470 | 904 | message=message, | ||
471 | 905 | build_url=hide_jenkins_url(build_url), | ||
472 | 906 | rebuild_url=hide_jenkins_url(rebuild_url), | ||
473 | 907 | executed_test_runs=executed_test_runs_message) | ||
474 | 908 | |||
475 | 909 | |||
476 | 910 | def trigger_ci_build(lp_handle, mps, jenkins_job, jenkins_url): | 788 | def trigger_ci_build(lp_handle, mps, jenkins_job, jenkins_url): |
477 | 911 | result = True | 789 | result = True |
478 | 912 | launchpad_user = lp_handle.people(get_config_option('launchpad_login')) | 790 | launchpad_user = lp_handle.people(get_config_option('launchpad_login')) |
479 | @@ -952,13 +830,22 @@ | |||
480 | 952 | jenkins_url): | 830 | jenkins_url): |
481 | 953 | logger.debug('No commit message was set. Interrupting ' + | 831 | logger.debug('No commit message was set. Interrupting ' + |
482 | 954 | 'autolanding for "%s".' % (mp.web_link)) | 832 | 'autolanding for "%s".' % (mp.web_link)) |
488 | 955 | mp_state, message = launchpadutils.build_state({ | 833 | template_args = { |
489 | 956 | 'commit_message_empty': True, | 834 | 'result': 'FAILED', |
490 | 957 | 'merge_proposal': mp.web_link}) | 835 | 'revision': mp.source_branch.revision_count, |
491 | 958 | launchpadutils.change_mp_status( | 836 | 'build_url': None, |
492 | 959 | mp, mp_state, message, | 837 | 'merge_url': mp.web_link |
493 | 838 | } | ||
494 | 839 | env = get_jinja_environment() | ||
495 | 840 | real_template = env.get_template('commit_message_empty.j2') | ||
496 | 841 | msg = real_template.render(args=template_args) | ||
497 | 842 | launchpadutils.report_to_launchpad( | ||
498 | 843 | mp, | ||
499 | 844 | msg, | ||
500 | 960 | mp.source_branch.revision_count, | 845 | mp.source_branch.revision_count, |
502 | 961 | launchpadutils.LaunchpadVote.NEEDS_FIXING) | 846 | status='Needs Review', |
503 | 847 | vote=launchpadutils.LaunchpadVote.NEEDS_FIXING | ||
504 | 848 | ) | ||
505 | 962 | continue | 849 | continue |
506 | 963 | 850 | ||
507 | 964 | if launchpadutils.unapproved_prerequisite_exists(mp): | 851 | if launchpadutils.unapproved_prerequisite_exists(mp): |
508 | 965 | 852 | ||
509 | === modified file 'jlp/launchpadutils.py' | |||
510 | --- jlp/launchpadutils.py 2018-06-27 20:32:51 +0000 | |||
511 | +++ jlp/launchpadutils.py 2019-05-09 18:32:44 +0000 | |||
512 | @@ -1,4 +1,4 @@ | |||
514 | 1 | import re | 1 | import os, re |
515 | 2 | from jlp import logger, get_config_option | 2 | from jlp import logger, get_config_option |
516 | 3 | import jenkinsutils | 3 | import jenkinsutils |
517 | 4 | from . import get_json_jenkins | 4 | from . import get_json_jenkins |
518 | @@ -70,27 +70,6 @@ | |||
519 | 70 | return None | 70 | return None |
520 | 71 | 71 | ||
521 | 72 | 72 | ||
522 | 73 | def change_mp_status(mp, status, message, revision, vote=None): | ||
523 | 74 | """Change status (vote) of merge proposal. | ||
524 | 75 | |||
525 | 76 | :param status: merge proposal status (e.g. "Needs review") | ||
526 | 77 | :param message: message for the vote | ||
527 | 78 | :param revision: revision against which this message is valid | ||
528 | 79 | :param vote: None or something from LaunchpadVote | ||
529 | 80 | (e.g. LaunchpadVote.NEEDS_FIXING) | ||
530 | 81 | """ | ||
531 | 82 | mp.setStatus(status=status, revid=revision) | ||
532 | 83 | subject = get_vote_subject(mp) | ||
533 | 84 | if vote: | ||
534 | 85 | mp.createComment( | ||
535 | 86 | review_type=get_config_option('launchpad_review_type'), | ||
536 | 87 | subject=subject, content=message, vote=vote) | ||
537 | 88 | else: | ||
538 | 89 | mp.createComment( | ||
539 | 90 | review_type=get_config_option('launchpad_review_type'), | ||
540 | 91 | subject=subject, content=message) | ||
541 | 92 | |||
542 | 93 | |||
543 | 94 | def close_bugs(mp): | 73 | def close_bugs(mp): |
544 | 95 | """ Close bugs that are linked to this merge proposal. | 74 | """ Close bugs that are linked to this merge proposal. |
545 | 96 | 75 | ||
546 | @@ -390,95 +369,67 @@ | |||
547 | 390 | return False | 369 | return False |
548 | 391 | 370 | ||
549 | 392 | 371 | ||
590 | 393 | def approve_mp(mp, revision, build_url): | 372 | def report_to_launchpad(mp, message, revision, status=None, vote=None): |
591 | 394 | """Approve a given merge proposal a revision. | 373 | """Set the status and send a message to Launchpad for an merge proposal. |
592 | 395 | 374 | ||
593 | 396 | :params mp: launchpad handle to the respective merge proposal | 375 | :param mp: handle to merge proposal |
594 | 397 | :params revision: revision that should be approved | 376 | :param message: text message to post as a message |
595 | 398 | :params build_url: jenkins build url with the details. This job is used to | 377 | :param revision: revision number for the proposal |
596 | 399 | generate the message with all the links to test runs as | 378 | :param status: Launchpad status to set the propsal to |
597 | 400 | well as artifacts (coverity, deb files, etc) | 379 | :param vote: how the message should vote on the proposal |
598 | 401 | """ | 380 | """ |
599 | 402 | state = 'PASSED: Continuous integration, rev:' + str(revision) | 381 | if status: |
600 | 403 | logger.debug(state) | 382 | mp.setStatus(status=status, revid=revision) |
601 | 404 | content = jenkinsutils.format_message_for_mp_update(build_url, | 383 | if vote: |
602 | 405 | state + "\n") | 384 | mp.createComment( |
603 | 406 | mp.createComment(review_type=get_config_option('launchpad_review_type'), | 385 | review_type=get_config_option('launchpad_review_type'), |
604 | 407 | vote=LaunchpadVote.APPROVE, subject=get_vote_subject(mp), | 386 | vote=vote, |
605 | 408 | content=content) | 387 | subject=get_vote_subject(mp), |
606 | 409 | 388 | content=message) | |
607 | 410 | 389 | else: | |
608 | 411 | def disapprove_mp(mp, revision, build_url, reason=None): | 390 | mp.createComment( |
609 | 412 | """Disapprove a given merge proposal a revision (vote Needs Fixing). | 391 | review_type=get_config_option('launchpad_review_type'), |
610 | 413 | 392 | subject=get_vote_subject(mp), | |
611 | 414 | :params mp: launchpad handle to the respective merge proposal | 393 | content=message) |
612 | 415 | :params revision: revision that should be fixed | 394 | |
613 | 416 | :params build_url: jenkins build url with the details. This job is used to | 395 | |
614 | 417 | generate the message with all the links to test runs as | 396 | def get_template_args(result, revision, build_url, merge_url): |
615 | 418 | well as artifacts (coverity, deb files, etc) | 397 | """Collect a set of information for rendering templates |
616 | 419 | :params reason: optional string that is attached to the comment | 398 | |
617 | 420 | """ | 399 | :param result: Result of the tests, either PASSED or FAILED |
618 | 421 | state = "FAILED: Continuous integration, rev:{revision}".format( | 400 | :param revison: The revision number of the merge |
619 | 422 | revision=revision) | 401 | :param build_url: URL to the build triggered in jenkins |
620 | 423 | if reason: | 402 | :param merge_url: URL to the merge proposal |
621 | 424 | state = "{state}\n{reason}".format(state=state, reason=reason) | 403 | """ |
622 | 425 | 404 | jenkins = get_json_jenkins() | |
623 | 426 | logger.debug(state) | 405 | args = {} |
624 | 427 | content = jenkinsutils.format_message_for_mp_update( | 406 | args['result'] = result |
625 | 428 | build_url, state + "\n") | 407 | args['revision'] = revision |
626 | 429 | mp.createComment(review_type=get_config_option('launchpad_review_type'), | 408 | args['build_url'] = build_url |
627 | 430 | vote=LaunchpadVote.NEEDS_FIXING, | 409 | args['merge_url'] = merge_url |
628 | 431 | subject=get_vote_subject(mp), | 410 | build_urls = jenkinsutils.get_executed_builds(jenkins, build_url) |
629 | 432 | content=content) | 411 | args['coverity_artifacts'] = [] |
630 | 412 | args['executed_tests'] = [] | ||
631 | 413 | for build in build_urls: | ||
632 | 414 | if build['output'].endswith('console'): | ||
633 | 415 | build_url = build['output'][:-len('console')] | ||
634 | 416 | build['output'] = build_url | ||
635 | 417 | debs = jenkinsutils.get_deb_artifacts(jenkins, build_url) | ||
636 | 418 | if debs is None: | ||
637 | 419 | build['deb'] = [] | ||
638 | 420 | else: | ||
639 | 421 | build['deb'] = debs | ||
640 | 422 | args['coverity_artifacts'].extend( | ||
641 | 423 | jenkinsutils.get_coverity_artifacts(jenkins, build_url) | ||
642 | 424 | ) | ||
643 | 425 | args['executed_tests'].append(build) | ||
644 | 426 | return args | ||
645 | 433 | 427 | ||
646 | 434 | 428 | ||
647 | 435 | class UpdateMergeProposalException(Exception): | 429 | class UpdateMergeProposalException(Exception): |
648 | 436 | pass | 430 | pass |
649 | 437 | 431 | ||
650 | 438 | 432 | ||
651 | 439 | def build_state(args): | ||
652 | 440 | """Return a tuple containing merge proposal state, message, and | ||
653 | 441 | subject.""" | ||
654 | 442 | |||
655 | 443 | if 'merge_failed' in args and args['merge_failed']: | ||
656 | 444 | return ('Needs review', | ||
657 | 445 | "FAILED: Autolanding.\n" + | ||
658 | 446 | "Merging failed. More details in the following jenkins job:\n") | ||
659 | 447 | elif 'push_failed' in args and args['push_failed']: | ||
660 | 448 | return ('Needs review', | ||
661 | 449 | "FAILED: Autolanding.\n" + | ||
662 | 450 | "Pushing failed. More details in the following jenkins job:\n") | ||
663 | 451 | elif 'landing_failed' in args and args['landing_failed']: | ||
664 | 452 | return ('Needs review', | ||
665 | 453 | "FAILED: Autolanding.\n" + | ||
666 | 454 | "More details in the following jenkins job:\n") | ||
667 | 455 | elif 'merged' in args and args['merged']: | ||
668 | 456 | return ('Merged', | ||
669 | 457 | "PASSED: Autolanding.\nBranch merged.") | ||
670 | 458 | elif 'commit_message_empty' in args and args['commit_message_empty']: | ||
671 | 459 | return ('Needs review', | ||
672 | 460 | "FAILED: Autolanding.\n" + | ||
673 | 461 | "No commit message was specified in the merge proposal. " + | ||
674 | 462 | "Hit 'Add commit message' on the merge proposal web page " + | ||
675 | 463 | "or follow the link below. You can approve the merge " + | ||
676 | 464 | "proposal yourself to rerun.\n" + | ||
677 | 465 | args['merge_proposal'] + "/+edit-commit-message\n") | ||
678 | 466 | elif 'unapproved_changes' in args and args['unapproved_changes']: | ||
679 | 467 | return ('Needs review', | ||
680 | 468 | "FAILED: Autolanding.\n" + | ||
681 | 469 | "Unapproved changes made after approval.\n") | ||
682 | 470 | elif 'invalid_revid' in args and args['invalid_revid']: | ||
683 | 471 | return ('Needs review', | ||
684 | 472 | "FAILED: Autolanding.\n" + | ||
685 | 473 | "Approved revid is not set in launchpad. " + | ||
686 | 474 | "This is most likely a launchpad issue and re-approve " + | ||
687 | 475 | "should fix it. There is also a chance " + | ||
688 | 476 | "(although a very small one) this is a permission " + | ||
689 | 477 | "problem of the ps-jenkins bot." + | ||
690 | 478 | "\n") | ||
691 | 479 | else: | ||
692 | 480 | raise UpdateMergeProposalException("unrecognized parameters") | ||
693 | 481 | |||
694 | 482 | def get_branch_handle_for(lp_handle, name, repo_type='auto'): | 433 | def get_branch_handle_for(lp_handle, name, repo_type='auto'): |
695 | 483 | """ Return the branch type and repo handle for the given name. | 434 | """ Return the branch type and repo handle for the given name. |
696 | 484 | 435 | ||
697 | 485 | 436 | ||
698 | === modified file 'setup.py' | |||
699 | --- setup.py 2013-10-08 18:13:32 +0000 | |||
700 | +++ setup.py 2019-05-09 18:32:44 +0000 | |||
701 | @@ -1,10 +1,13 @@ | |||
702 | 1 | from distutils.core import setup | 1 | from distutils.core import setup |
703 | 2 | from setuptools import find_packages | 2 | from setuptools import find_packages |
704 | 3 | import glob | ||
705 | 3 | setup( | 4 | setup( |
706 | 4 | name='jenkins-launchpad-plugin', | 5 | name='jenkins-launchpad-plugin', |
707 | 5 | version='0.1', | 6 | version='0.1', |
708 | 6 | url='https://launchpad.net/jenkins-launchpad-plugin', | 7 | url='https://launchpad.net/jenkins-launchpad-plugin', |
709 | 7 | packages=find_packages(), | 8 | packages=find_packages(), |
710 | 9 | include_package_data=True, | ||
711 | 10 | data_files=[('templates', glob.glob('templates/*.j2'))], | ||
712 | 8 | test_suite='tests', | 11 | test_suite='tests', |
713 | 9 | entry_points="""\ | 12 | entry_points="""\ |
714 | 10 | [console_scripts] | 13 | [console_scripts] |
715 | 11 | 14 | ||
716 | === added directory 'templates' | |||
717 | === added file 'templates/autoland_header.j2' | |||
718 | --- templates/autoland_header.j2 1970-01-01 00:00:00 +0000 | |||
719 | +++ templates/autoland_header.j2 2019-05-09 18:32:44 +0000 | |||
720 | @@ -0,0 +1,1 @@ | |||
721 | 1 | Autolanding: {{ args.result }} | ||
722 | 0 | 2 | ||
723 | === added file 'templates/ci_test.j2' | |||
724 | --- templates/ci_test.j2 1970-01-01 00:00:00 +0000 | |||
725 | +++ templates/ci_test.j2 2019-05-09 18:32:44 +0000 | |||
726 | @@ -0,0 +1,4 @@ | |||
727 | 1 | {{ args.result }}: Continuous integration, rev:{{ args.revision }} | ||
728 | 2 | {% include 'footer.j2' %} | ||
729 | 3 | |||
730 | 4 | {% include 'rebuild.j2' -%} | ||
731 | 0 | 5 | ||
732 | === added file 'templates/commit_message_empty.j2' | |||
733 | --- templates/commit_message_empty.j2 1970-01-01 00:00:00 +0000 | |||
734 | +++ templates/commit_message_empty.j2 2019-05-09 18:32:44 +0000 | |||
735 | @@ -0,0 +1,4 @@ | |||
736 | 1 | {% include 'autoland_header.j2' %} | ||
737 | 2 | No commit message was specified in the merge proposal. Hit 'Add commit message' on the merge proposal web page or follow the link below. You can approve the merge proposal yourself to rerun. | ||
738 | 3 | {{ args.merge_url }}/+edit-commit-message | ||
739 | 4 | {% include 'footer.j2' -%} | ||
740 | 0 | 5 | ||
741 | === added file 'templates/coverity.j2' | |||
742 | --- templates/coverity.j2 1970-01-01 00:00:00 +0000 | |||
743 | +++ templates/coverity.j2 2019-05-09 18:32:44 +0000 | |||
744 | @@ -0,0 +1,4 @@ | |||
745 | 1 | Coverity artifacts: | ||
746 | 2 | {%- for cov in args.coverity_artifacts %} | ||
747 | 3 | {{ cov }} | ||
748 | 4 | {%- endfor -%} | ||
749 | 0 | 5 | ||
750 | === added file 'templates/executed_tests.j2' | |||
751 | --- templates/executed_tests.j2 1970-01-01 00:00:00 +0000 | |||
752 | +++ templates/executed_tests.j2 2019-05-09 18:32:44 +0000 | |||
753 | @@ -0,0 +1,7 @@ | |||
754 | 1 | Executed test runs: | ||
755 | 2 | {%- for build in args.executed_tests %} | ||
756 | 3 | {{ build.result }}: {{ build.output }} | ||
757 | 4 | {%- for deb in build.deb %} | ||
758 | 5 | deb: {{ deb }} | ||
759 | 6 | {%- endfor -%} | ||
760 | 7 | {% endfor -%} | ||
761 | 0 | 8 | ||
762 | === added file 'templates/footer.j2' | |||
763 | --- templates/footer.j2 1970-01-01 00:00:00 +0000 | |||
764 | +++ templates/footer.j2 2019-05-09 18:32:44 +0000 | |||
765 | @@ -0,0 +1,7 @@ | |||
766 | 1 | {%- if args.build_url -%} | ||
767 | 2 | {{ args.build_url }} | ||
768 | 3 | {% include 'executed_tests.j2' %} | ||
769 | 4 | {% if args.coverity_artifacts -%} | ||
770 | 5 | {% include 'coverity.j2' %} | ||
771 | 6 | {%- endif -%} | ||
772 | 7 | {%- endif -%} | ||
773 | 0 | 8 | ||
774 | === added file 'templates/invalid_commit_message.j2' | |||
775 | --- templates/invalid_commit_message.j2 1970-01-01 00:00:00 +0000 | |||
776 | +++ templates/invalid_commit_message.j2 2019-05-09 18:32:44 +0000 | |||
777 | @@ -0,0 +1,4 @@ | |||
778 | 1 | Commit message lints: | ||
779 | 2 | {% for error in errors -%} | ||
780 | 3 | - {{ error }} | ||
781 | 4 | {%- endfor -%} | ||
782 | 0 | 5 | ||
783 | === added file 'templates/invalid_revid.j2' | |||
784 | --- templates/invalid_revid.j2 1970-01-01 00:00:00 +0000 | |||
785 | +++ templates/invalid_revid.j2 2019-05-09 18:32:44 +0000 | |||
786 | @@ -0,0 +1,3 @@ | |||
787 | 1 | {% include 'autoland_header.j2' %} | ||
788 | 2 | Approved revid is not set in launchpad. This is most likely a launchpad issue and re-approve should fix it. There is also a chance (although a very small one) this is a permission problem of the ps-jenkins bot | ||
789 | 3 | {% include 'footer.j2' -%} | ||
790 | 0 | 4 | ||
791 | === added file 'templates/landing_failed.j2' | |||
792 | --- templates/landing_failed.j2 1970-01-01 00:00:00 +0000 | |||
793 | +++ templates/landing_failed.j2 2019-05-09 18:32:44 +0000 | |||
794 | @@ -0,0 +1,3 @@ | |||
795 | 1 | {% include 'autoland_header.j2' %} | ||
796 | 2 | More details in the following jenkins job: | ||
797 | 3 | {% include 'footer.j2' -%} | ||
798 | 0 | 4 | ||
799 | === added file 'templates/merge_failed.j2' | |||
800 | --- templates/merge_failed.j2 1970-01-01 00:00:00 +0000 | |||
801 | +++ templates/merge_failed.j2 2019-05-09 18:32:44 +0000 | |||
802 | @@ -0,0 +1,3 @@ | |||
803 | 1 | {% include 'autoland_header.j2' %} | ||
804 | 2 | Merging failed. More details in the following jenkins job: | ||
805 | 3 | {% include 'footer.j2' -%} | ||
806 | 0 | 4 | ||
807 | === added file 'templates/merged.j2' | |||
808 | --- templates/merged.j2 1970-01-01 00:00:00 +0000 | |||
809 | +++ templates/merged.j2 2019-05-09 18:32:44 +0000 | |||
810 | @@ -0,0 +1,2 @@ | |||
811 | 1 | PASSED: Autolanding. | ||
812 | 2 | Branch merged. | ||
813 | 0 | 3 | ||
814 | === added file 'templates/no_commit.j2' | |||
815 | --- templates/no_commit.j2 1970-01-01 00:00:00 +0000 | |||
816 | +++ templates/no_commit.j2 2019-05-09 18:32:44 +0000 | |||
817 | @@ -0,0 +1,4 @@ | |||
818 | 1 | No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want jenkins to rebuild you need to trigger it yourself): | ||
819 | 2 | {{ args.merge_url }}/+edit-commit-message | ||
820 | 3 | {% include 'footer.j2' %} | ||
821 | 4 | {% include 'rebuild.j2' -%} | ||
822 | 0 | 5 | ||
823 | === added file 'templates/push_failed.j2' | |||
824 | --- templates/push_failed.j2 1970-01-01 00:00:00 +0000 | |||
825 | +++ templates/push_failed.j2 2019-05-09 18:32:44 +0000 | |||
826 | @@ -0,0 +1,3 @@ | |||
827 | 1 | FAILED: Autolanding. | ||
828 | 2 | Pushing failed. More details in the following jenkins job: | ||
829 | 3 | {{ args.build_url }} | ||
830 | 0 | \ No newline at end of file | 4 | \ No newline at end of file |
831 | 1 | 5 | ||
832 | === added file 'templates/rebuild.j2' | |||
833 | --- templates/rebuild.j2 1970-01-01 00:00:00 +0000 | |||
834 | +++ templates/rebuild.j2 2019-05-09 18:32:44 +0000 | |||
835 | @@ -0,0 +1,2 @@ | |||
836 | 1 | Click here to trigger a rebuild: | ||
837 | 2 | {{ args.build_url }}/rebuild | ||
838 | 0 | 3 | ||
839 | === added file 'templates/unapproved_changes.j2' | |||
840 | --- templates/unapproved_changes.j2 1970-01-01 00:00:00 +0000 | |||
841 | +++ templates/unapproved_changes.j2 2019-05-09 18:32:44 +0000 | |||
842 | @@ -0,0 +1,3 @@ | |||
843 | 1 | {% include 'autoland_header.j2' %} | ||
844 | 2 | Unapproved changes made after approval. | ||
845 | 3 | {% include 'footer.j2' -%} | ||
846 | 0 | 4 | ||
847 | === modified file 'tests/test_autoland.py' | |||
848 | --- tests/test_autoland.py 2013-06-14 19:02:11 +0000 | |||
849 | +++ tests/test_autoland.py 2019-05-09 18:32:44 +0000 | |||
850 | @@ -154,7 +154,7 @@ | |||
851 | 154 | self.get_branch_from_mp = self.get_branch_from_mp_patch.start() | 154 | self.get_branch_from_mp = self.get_branch_from_mp_patch.start() |
852 | 155 | 155 | ||
853 | 156 | self.change_mp_status_patch = patch( | 156 | self.change_mp_status_patch = patch( |
855 | 157 | 'jlp.commands.autoland.launchpadutils.change_mp_status') | 157 | 'jlp.commands.autoland.change_mp_status') |
856 | 158 | self.change_mp_status = self.change_mp_status_patch.start() | 158 | self.change_mp_status = self.change_mp_status_patch.start() |
857 | 159 | 159 | ||
858 | 160 | def tearDown(self): | 160 | def tearDown(self): |
859 | @@ -493,7 +493,7 @@ | |||
860 | 493 | self.assertTrue("usage" in stderr.getvalue()) | 493 | self.assertTrue("usage" in stderr.getvalue()) |
861 | 494 | 494 | ||
862 | 495 | @patch('jlp.commands.autoland.launchpadutils.get_branch_from_mp') | 495 | @patch('jlp.commands.autoland.launchpadutils.get_branch_from_mp') |
864 | 496 | @patch('jlp.commands.autoland.launchpadutils.change_mp_status') | 496 | @patch('jlp.commands.autoland.change_mp_status') |
865 | 497 | def test_test_result_failed(self, change_mp_status_mock, get_branch_mock): | 497 | def test_test_result_failed(self, change_mp_status_mock, get_branch_mock): |
866 | 498 | """Fail autolanding because of failed testing""" | 498 | """Fail autolanding because of failed testing""" |
867 | 499 | 499 | ||
868 | 500 | 500 | ||
869 | === modified file 'tests/test_jenkinsutils.py' | |||
870 | --- tests/test_jenkinsutils.py 2018-01-25 22:13:52 +0000 | |||
871 | +++ tests/test_jenkinsutils.py 2019-05-09 18:32:44 +0000 | |||
872 | @@ -1119,9 +1119,7 @@ | |||
873 | 1119 | "\n None: http://10.0.0.1:8080/job/my-job/13/console"}), | 1119 | "\n None: http://10.0.0.1:8080/job/my-job/13/console"}), |
874 | 1120 | ] | 1120 | ] |
875 | 1121 | 1121 | ||
879 | 1122 | def test_get_result_line(self): | 1122 | # was get_result_line |
877 | 1123 | result = jenkinsutils._get_result_line(self.result, self.url) | ||
878 | 1124 | self.assertEqual(result, self.expected) | ||
880 | 1125 | 1123 | ||
881 | 1126 | 1124 | ||
882 | 1127 | class LaunchpadTriggerGetExecutedTestRuns(unittest.TestCase): | 1125 | class LaunchpadTriggerGetExecutedTestRuns(unittest.TestCase): |
883 | @@ -1163,54 +1161,10 @@ | |||
884 | 1163 | 1161 | ||
885 | 1164 | def tearDown(self): | 1162 | def tearDown(self): |
886 | 1165 | self.get_json_jenkins_patch.stop() | 1163 | self.get_json_jenkins_patch.stop() |
935 | 1166 | 1164 | ||
936 | 1167 | def test_get_executed_test_runs_message(self): | 1165 | # executed_test_runs_message |
937 | 1168 | ret = jenkinsutils.get_executed_test_runs_message(self.build_url) | 1166 | |
938 | 1169 | self.assertEqual(ret, | 1167 | # format message for MP update |
891 | 1170 | self._get_executed_test_runs_message('jenkins:8080')) | ||
892 | 1171 | |||
893 | 1172 | def test_format_message_for_mp_update(self): | ||
894 | 1173 | test_runs = self._get_executed_test_runs_message('jenkins:8080') | ||
895 | 1174 | expected = dedent("""\ | ||
896 | 1175 | mymessage | ||
897 | 1176 | http://jenkins:8080/job/my-job/3/{test_runs} | ||
898 | 1177 | |||
899 | 1178 | Click here to trigger a rebuild: | ||
900 | 1179 | http://jenkins:8080/job/my-job/3/rebuild | ||
901 | 1180 | """).format(test_runs=test_runs) | ||
902 | 1181 | actual = jenkinsutils.format_message_for_mp_update( | ||
903 | 1182 | self.build_url, | ||
904 | 1183 | "mymessage\n") | ||
905 | 1184 | self.assertEquals(actual, expected) | ||
906 | 1185 | |||
907 | 1186 | def test_format_message_with_empty_message(self): | ||
908 | 1187 | test_runs = self._get_executed_test_runs_message('jenkins:8080') | ||
909 | 1188 | expected = dedent("""\ | ||
910 | 1189 | http://jenkins:8080/job/my-job/3/{test_runs} | ||
911 | 1190 | |||
912 | 1191 | Click here to trigger a rebuild: | ||
913 | 1192 | http://jenkins:8080/job/my-job/3/rebuild | ||
914 | 1193 | """).format(test_runs=test_runs) | ||
915 | 1194 | |||
916 | 1195 | actual = jenkinsutils.format_message_for_mp_update( | ||
917 | 1196 | self.build_url) | ||
918 | 1197 | self.assertEquals(actual, expected) | ||
919 | 1198 | |||
920 | 1199 | def test_format_message_with_publishing_job(self): | ||
921 | 1200 | test_runs = self._get_executed_test_runs_message( | ||
922 | 1201 | 'jenkins.qa.ubuntu.com') | ||
923 | 1202 | expected = dedent("""\ | ||
924 | 1203 | http://jenkins.qa.ubuntu.com/job/my-job/3/{test_runs} | ||
925 | 1204 | |||
926 | 1205 | Click here to trigger a rebuild: | ||
927 | 1206 | http://jenkins:8080/job/my-job/3/rebuild | ||
928 | 1207 | """).format(test_runs=test_runs) | ||
929 | 1208 | |||
930 | 1209 | with patch("jlp.jenkinsutils.is_job_published", | ||
931 | 1210 | new=lambda x: True): | ||
932 | 1211 | actual = jenkinsutils.format_message_for_mp_update( | ||
933 | 1212 | self.build_url) | ||
934 | 1213 | self.assertEquals(actual, expected) | ||
939 | 1214 | 1168 | ||
940 | 1215 | 1169 | ||
941 | 1216 | class TestTriggerCi(unittest.TestCase): | 1170 | class TestTriggerCi(unittest.TestCase): |
942 | @@ -1294,10 +1248,10 @@ | |||
943 | 1294 | new=lambda x, y, z: False) | 1248 | new=lambda x, y, z: False) |
944 | 1295 | @patch('jlp.launchpadutils.users_allowed_to_trigger_jobs', | 1249 | @patch('jlp.launchpadutils.users_allowed_to_trigger_jobs', |
945 | 1296 | new=lambda x: True) | 1250 | new=lambda x: True) |
947 | 1297 | @patch('jlp.launchpadutils.change_mp_status') | 1251 | @patch('jlp.launchpadutils.report_to_launchpad') |
948 | 1298 | @patch('jlp.jenkinsutils.start_jenkins_job') | 1252 | @patch('jlp.jenkinsutils.start_jenkins_job') |
949 | 1299 | def test_trigger_al_with_no_commit_message(self, start_jenkins_job, | 1253 | def test_trigger_al_with_no_commit_message(self, start_jenkins_job, |
951 | 1300 | change_mp_status): | 1254 | report_to_launchpad): |
952 | 1301 | """If no commit message is set no jenkins job must be started and | 1255 | """If no commit message is set no jenkins job must be started and |
953 | 1302 | status of merge proposal must be changed to NEEDS_FIXING""" | 1256 | status of merge proposal must be changed to NEEDS_FIXING""" |
954 | 1303 | jenkinsutils.trigger_al_build(MagicMock(), | 1257 | jenkinsutils.trigger_al_build(MagicMock(), |
955 | @@ -1307,7 +1261,7 @@ | |||
956 | 1307 | # the new vote is the 5th argument in change_mp_status (and we count | 1261 | # the new vote is the 5th argument in change_mp_status (and we count |
957 | 1308 | # from 0) | 1262 | # from 0) |
958 | 1309 | new_vote_position = 4 | 1263 | new_vote_position = 4 |
960 | 1310 | self.assertEqual(change_mp_status.call_args[0][new_vote_position], | 1264 | self.assertEqual(report_to_launchpad.call_args[0][new_vote_position], |
961 | 1311 | launchpadutils.LaunchpadVote.NEEDS_FIXING) | 1265 | launchpadutils.LaunchpadVote.NEEDS_FIXING) |
962 | 1312 | 1266 | ||
963 | 1313 | @patch('jlp.launchpadutils.is_commit_message_set', | 1267 | @patch('jlp.launchpadutils.is_commit_message_set', |
964 | 1314 | 1268 | ||
965 | === modified file 'tests/test_launchpadutils.py' | |||
966 | --- tests/test_launchpadutils.py 2017-02-23 20:25:56 +0000 | |||
967 | +++ tests/test_launchpadutils.py 2019-05-09 18:32:44 +0000 | |||
968 | @@ -19,42 +19,53 @@ | |||
969 | 19 | 'https://copde.launchpad.net/~user/project/name/merge/12345') | 19 | 'https://copde.launchpad.net/~user/project/name/merge/12345') |
970 | 20 | self.assertEqual(branch, None) | 20 | self.assertEqual(branch, None) |
971 | 21 | 21 | ||
1008 | 22 | @patch('jlp.launchpadutils.get_vote_subject', | 22 | @patch('jlp.launchpadutils.get_config_option') |
1009 | 23 | new=lambda mp: 'Subject') | 23 | @patch('jlp.launchpadutils.get_vote_subject') |
1010 | 24 | def test_change_mp_status_with_no_vote(self): | 24 | def test_report_to_launchpad_status(self, gvs_mock, gco_mock): |
1011 | 25 | mp = MagicMock() | 25 | gvs_mock.return_value = 'vote subject' |
1012 | 26 | launchpadutils.change_mp_status(mp, 'Status', 'Message', revision=1) | 26 | gco_mock.return_value = 'vote type' |
1013 | 27 | mp.createComment.assert_called_once_with( | 27 | mp = MagicMock() |
1014 | 28 | review_type=get_config_option('launchpad_review_type'), | 28 | message = 'this is a test' |
1015 | 29 | subject='Subject', | 29 | revision = 'abc123' |
1016 | 30 | content='Message') | 30 | status = 'Approved' |
1017 | 31 | mp.setStatus.assert_called_once_with(status='Status', revid=1) | 31 | launchpadutils.report_to_launchpad(mp, message, revision, status) |
1018 | 32 | 32 | mp.setStatus.assert_called_once_with(revid='abc123', status='Approved') | |
1019 | 33 | @patch('jlp.launchpadutils.get_vote_subject', | 33 | mp.createComment.assert_called_once_with( |
1020 | 34 | new=lambda mp: 'Subject') | 34 | content='this is a test', |
1021 | 35 | def test_change_mp_status_with_approve(self): | 35 | review_type='vote type', |
1022 | 36 | mp = MagicMock() | 36 | subject='vote subject') |
1023 | 37 | mp.web_link = 'http://my-example-url.com' | 37 | |
1024 | 38 | launchpadutils.change_mp_status(mp, 'Status', 'Message', | 38 | @patch('jlp.launchpadutils.get_config_option') |
1025 | 39 | revision=1, vote='Approve') | 39 | @patch('jlp.launchpadutils.get_vote_subject') |
1026 | 40 | mp.createComment.assert_called_once_with( | 40 | def test_report_to_launchpad_vote(self, gvs_mock, gco_mock): |
1027 | 41 | review_type=get_config_option('launchpad_review_type'), | 41 | gvs_mock.return_value = 'vote subject' |
1028 | 42 | subject='Subject', | 42 | gco_mock.return_value = 'vote type' |
1029 | 43 | content='Message', vote='Approve') | 43 | mp = MagicMock() |
1030 | 44 | mp.setStatus.assert_called_once_with(status='Status', revid=1) | 44 | message = 'this is a test' |
1031 | 45 | 45 | revision = 'abc123' | |
1032 | 46 | @patch('jlp.launchpadutils.get_vote_subject', | 46 | launchpadutils.report_to_launchpad(mp, message, revision, 'approved') |
1033 | 47 | new=lambda mp: 'Subject') | 47 | mp.createComment.assert_called_once_with( |
1034 | 48 | def test_change_mp_status_with_disapprove(self): | 48 | content='this is a test', |
1035 | 49 | mp = MagicMock() | 49 | review_type='vote type', |
1036 | 50 | mp.web_link = 'http://my-example-url.com' | 50 | subject='vote subject') |
1037 | 51 | launchpadutils.change_mp_status(mp, 'Status', 'Message', | 51 | |
1038 | 52 | revision=1, vote='Disapprove') | 52 | @patch('jlp.launchpadutils.get_config_option') |
1039 | 53 | mp.createComment.assert_called_once_with( | 53 | @patch('jlp.launchpadutils.get_vote_subject') |
1040 | 54 | review_type=get_config_option('launchpad_review_type'), | 54 | def test_report_to_launchpad_status_and_vote(self, gvs_mock, gco_mock): |
1041 | 55 | subject='Subject', | 55 | gvs_mock.return_value = 'vote subject' |
1042 | 56 | content='Message', vote='Disapprove') | 56 | gco_mock.return_value = 'vote type' |
1043 | 57 | mp.setStatus.assert_called_once_with(status='Status', revid=1) | 57 | mp = MagicMock() |
1044 | 58 | message = 'this is a test' | ||
1045 | 59 | revision = 'abc123' | ||
1046 | 60 | status = 'Approved' | ||
1047 | 61 | launchpadutils.report_to_launchpad(mp, message, | ||
1048 | 62 | revision, status, 'approved') | ||
1049 | 63 | mp.setStatus.assert_called_once_with(revid='abc123', status='Approved') | ||
1050 | 64 | mp.createComment.assert_called_once_with( | ||
1051 | 65 | content='this is a test', | ||
1052 | 66 | review_type='vote type', | ||
1053 | 67 | subject='vote subject', | ||
1054 | 68 | vote='approved') | ||
1055 | 58 | 69 | ||
1056 | 59 | def test_close_bugs(self): | 70 | def test_close_bugs(self): |
1057 | 60 | mp = MagicMock() | 71 | mp = MagicMock() |
1058 | @@ -564,97 +575,6 @@ | |||
1059 | 564 | def tearDown(self): | 575 | def tearDown(self): |
1060 | 565 | self.get_executed_test_runs_message_patch.stop() | 576 | self.get_executed_test_runs_message_patch.stop() |
1061 | 566 | 577 | ||
1062 | 567 | def test_approve_mp(self): | ||
1063 | 568 | mp = self._get_mp() | ||
1064 | 569 | subject = self._get_subject(mp) | ||
1065 | 570 | launchpadutils.approve_mp(mp, '1', 'http://url') | ||
1066 | 571 | content = dedent('''\ | ||
1067 | 572 | PASSED: Continuous integration, rev:1 | ||
1068 | 573 | http://url | ||
1069 | 574 | |||
1070 | 575 | Click here to trigger a rebuild: | ||
1071 | 576 | http://url/rebuild | ||
1072 | 577 | ''') | ||
1073 | 578 | mp.createComment.assert_called_once_with( | ||
1074 | 579 | review_type=get_config_option('launchpad_review_type'), | ||
1075 | 580 | vote=launchpadutils.LaunchpadVote.APPROVE, | ||
1076 | 581 | subject=subject, | ||
1077 | 582 | content=content) | ||
1078 | 583 | |||
1079 | 584 | def test_disapprove_mp(self): | ||
1080 | 585 | mp = self._get_mp() | ||
1081 | 586 | subject = self._get_subject(mp) | ||
1082 | 587 | launchpadutils.disapprove_mp(mp, '1', 'http://url') | ||
1083 | 588 | content = dedent('''\ | ||
1084 | 589 | FAILED: Continuous integration, rev:1 | ||
1085 | 590 | http://url | ||
1086 | 591 | |||
1087 | 592 | Click here to trigger a rebuild: | ||
1088 | 593 | http://url/rebuild | ||
1089 | 594 | ''') | ||
1090 | 595 | mp.createComment.assert_called_once_with( | ||
1091 | 596 | review_type=get_config_option('launchpad_review_type'), | ||
1092 | 597 | vote=launchpadutils.LaunchpadVote.NEEDS_FIXING, | ||
1093 | 598 | subject=subject, | ||
1094 | 599 | content=content) | ||
1095 | 600 | |||
1096 | 601 | def test_disapprove_mp_with_reason(self): | ||
1097 | 602 | mp = self._get_mp() | ||
1098 | 603 | subject = self._get_subject(mp) | ||
1099 | 604 | reason = "No commit message set\nDo something\n" | ||
1100 | 605 | content = dedent('''\ | ||
1101 | 606 | FAILED: Continuous integration, rev:1 | ||
1102 | 607 | {reason} | ||
1103 | 608 | http://url | ||
1104 | 609 | |||
1105 | 610 | Click here to trigger a rebuild: | ||
1106 | 611 | http://url/rebuild | ||
1107 | 612 | ''').format(reason=reason) | ||
1108 | 613 | |||
1109 | 614 | launchpadutils.disapprove_mp(mp, | ||
1110 | 615 | '1', | ||
1111 | 616 | 'http://url', | ||
1112 | 617 | reason=reason) | ||
1113 | 618 | mp.createComment.assert_called_once_with( | ||
1114 | 619 | review_type=get_config_option('launchpad_review_type'), | ||
1115 | 620 | vote=launchpadutils.LaunchpadVote.NEEDS_FIXING, | ||
1116 | 621 | subject=subject, | ||
1117 | 622 | content=content) | ||
1118 | 623 | |||
1119 | 624 | def test_approve_git_mp(self): | ||
1120 | 625 | mp = self._get_git_mp() | ||
1121 | 626 | subject = self._expected_git_mp_subject(mp) | ||
1122 | 627 | launchpadutils.approve_mp(mp, '1', 'http://url') | ||
1123 | 628 | content = dedent('''\ | ||
1124 | 629 | PASSED: Continuous integration, rev:1 | ||
1125 | 630 | http://url | ||
1126 | 631 | |||
1127 | 632 | Click here to trigger a rebuild: | ||
1128 | 633 | http://url/rebuild | ||
1129 | 634 | ''') | ||
1130 | 635 | mp.createComment.assert_called_once_with( | ||
1131 | 636 | review_type=get_config_option('launchpad_review_type'), | ||
1132 | 637 | vote=launchpadutils.LaunchpadVote.APPROVE, | ||
1133 | 638 | subject=subject, | ||
1134 | 639 | content=content) | ||
1135 | 640 | |||
1136 | 641 | def test_dissaprove_git_mp(self): | ||
1137 | 642 | mp = self._get_git_mp() | ||
1138 | 643 | subject = self._expected_git_mp_subject(mp) | ||
1139 | 644 | launchpadutils.disapprove_mp(mp, '1', 'http://url') | ||
1140 | 645 | content = dedent('''\ | ||
1141 | 646 | FAILED: Continuous integration, rev:1 | ||
1142 | 647 | http://url | ||
1143 | 648 | |||
1144 | 649 | Click here to trigger a rebuild: | ||
1145 | 650 | http://url/rebuild | ||
1146 | 651 | ''') | ||
1147 | 652 | mp.createComment.assert_called_once_with( | ||
1148 | 653 | review_type=get_config_option('launchpad_review_type'), | ||
1149 | 654 | vote=launchpadutils.LaunchpadVote.NEEDS_FIXING, | ||
1150 | 655 | subject=subject, | ||
1151 | 656 | content=content) | ||
1152 | 657 | |||
1153 | 658 | 578 | ||
1154 | 659 | class TestGetMergeProposalsWithInvalidBranch(unittest.TestCase): | 579 | class TestGetMergeProposalsWithInvalidBranch(unittest.TestCase): |
1155 | 660 | branch_with_mps = None | 580 | branch_with_mps = None |
1156 | @@ -905,7 +825,7 @@ | |||
1157 | 905 | 825 | ||
1158 | 906 | self.assertEqual(result, ('git', repo)) | 826 | self.assertEqual(result, ('git', repo)) |
1159 | 907 | 827 | ||
1161 | 908 | def test_raises_for_no_mathc(self): | 828 | def test_raises_for_no_match(self): |
1162 | 909 | ''' | 829 | ''' |
1163 | 910 | Ensure that an exception is raised when there is no match. | 830 | Ensure that an exception is raised when there is no match. |
1164 | 911 | ''' | 831 | ''' |
1165 | 912 | 832 | ||
1166 | === modified file 'tests/test_voteOnMergeProposal.py' | |||
1167 | --- tests/test_voteOnMergeProposal.py 2013-11-19 00:11:18 +0000 | |||
1168 | +++ tests/test_voteOnMergeProposal.py 2019-05-09 18:32:44 +0000 | |||
1169 | @@ -12,9 +12,6 @@ | |||
1170 | 12 | 'jlp.commands.voteOnMergeProposal.get_launchpad', | 12 | 'jlp.commands.voteOnMergeProposal.get_launchpad', |
1171 | 13 | new=get_launchpad) | 13 | new=get_launchpad) |
1172 | 14 | self.get_launchpad_patch.start() | 14 | self.get_launchpad_patch.start() |
1173 | 15 | self.get_executed_test_runs_message_patch = patch( | ||
1174 | 16 | 'jlp.jenkinsutils.get_executed_test_runs_message') | ||
1175 | 17 | self.get_executed_test_runs_message_patch.start() | ||
1176 | 18 | self.is_commit_message_set_patch = patch( | 15 | self.is_commit_message_set_patch = patch( |
1177 | 19 | 'jlp.launchpadutils.is_commit_message_set') | 16 | 'jlp.launchpadutils.is_commit_message_set') |
1178 | 20 | self.is_commit_message_set_patch.start() | 17 | self.is_commit_message_set_patch.start() |
1179 | @@ -22,7 +19,6 @@ | |||
1180 | 22 | def tearDown(self): | 19 | def tearDown(self): |
1181 | 23 | self.get_launchpad_patch.stop() | 20 | self.get_launchpad_patch.stop() |
1182 | 24 | self.is_commit_message_set_patch.stop() | 21 | self.is_commit_message_set_patch.stop() |
1183 | 25 | self.get_executed_test_runs_message_patch.stop() | ||
1184 | 26 | 22 | ||
1185 | 27 | def test_gibberish(self): | 23 | def test_gibberish(self): |
1186 | 28 | """Gibberish on the command line produces usage message.""" | 24 | """Gibberish on the command line produces usage message.""" |
1187 | @@ -112,7 +108,12 @@ | |||
1188 | 112 | pass | 108 | pass |
1189 | 113 | self.assertTrue(error_message in stderr.getvalue()) | 109 | self.assertTrue(error_message in stderr.getvalue()) |
1190 | 114 | 110 | ||
1192 | 115 | def test_passed_vote(self): | 111 | @patch('sys.argv') |
1193 | 112 | @patch('jlp.commands.voteOnMergeProposal.launchpadutils.get_mp_handle_from_url') | ||
1194 | 113 | @patch('jlp.launchpadutils.report_to_launchpad') | ||
1195 | 114 | @patch('jlp.commands.voteOnMergeProposal.launchpadutils.get_template_args') | ||
1196 | 115 | @patch('jlp.commands.voteOnMergeProposal.get_jinja_environment') | ||
1197 | 116 | def test_passed_vote(self, gje, gta, rtl, gmphandle, sys_argv): | ||
1198 | 116 | """Vote on a proposal which passed.""" | 117 | """Vote on a proposal which passed.""" |
1199 | 117 | 118 | ||
1200 | 118 | sys_argv = ['voteOnMergeProposal.py', | 119 | sys_argv = ['voteOnMergeProposal.py', |
1201 | @@ -123,20 +124,27 @@ | |||
1202 | 123 | '--branch=lp:~mrazik/faux-dbus-test-runner/yar8', | 124 | '--branch=lp:~mrazik/faux-dbus-test-runner/yar8', |
1203 | 124 | '--merge-proposal=https://code.launchpad.net/~mrazik/' + | 125 | '--merge-proposal=https://code.launchpad.net/~mrazik/' + |
1204 | 125 | 'faux-dbus-test-runner/yar8/+merge/106113'] | 126 | 'faux-dbus-test-runner/yar8/+merge/106113'] |
1219 | 126 | with patch('sys.argv', sys_argv), \ | 127 | |
1220 | 127 | patch('jlp.commands.voteOnMergeProposal.launchpadutils.' + | 128 | gmphandle.return_value = 'Launchpad_mp' |
1221 | 128 | 'get_mp_handle_from_url') as get_mp_handle_from_url, \ | 129 | gta.return_value = { |
1222 | 129 | patch('jlp.launchpadutils.approve_mp') as approve_mp: | 130 | 'result': 'PASSED', |
1223 | 130 | get_mp_handle_from_url.return_value = 'Launchpad_mp' | 131 | 'revision': '66' |
1224 | 131 | ret = voteOnMergeProposal() | 132 | } |
1225 | 132 | self.assertEqual(ret, 0) | 133 | ret = voteOnMergeProposal() |
1226 | 133 | approve_mp.assert_called_with( | 134 | self.assertEqual(ret, 0) |
1227 | 134 | 'Launchpad_mp', | 135 | rtl.assert_called_once() |
1228 | 135 | '66', | 136 | gje.get_template.assert_called_with('ci_test.j2') |
1229 | 136 | 'http://s-jenkins.ubuntu-ci/job/faux-dbus-test-runner-ci/' + | 137 | |
1230 | 137 | 'configure') | 138 | |
1231 | 138 | 139 | @patch('sys.argv') | |
1232 | 139 | def test_no_commit_message_set(self): | 140 | @patch('jlp.commands.voteOnMergeProposal.launchpadutils.' +\ |
1233 | 141 | 'get_mp_handle_from_url') | ||
1234 | 142 | @patch('jlp.launchpadutils.report_to_launchpad') | ||
1235 | 143 | @patch('jlp.launchpadutils.is_commit_message_set') | ||
1236 | 144 | @patch('jlp.commands.voteOnMergeProposal.launchpadutils.get_template_args') | ||
1237 | 145 | @patch('jlp.commands.voteOnMergeProposal.get_jinja_environment') | ||
1238 | 146 | def test_no_commit_message_set(self, gje, gta, icms, | ||
1239 | 147 | rtl, gmphandle, sys_argv): | ||
1240 | 140 | """Vote on a proposal where tests passed but no commit message | 148 | """Vote on a proposal where tests passed but no commit message |
1241 | 141 | was set.""" | 149 | was set.""" |
1242 | 142 | 150 | ||
1243 | @@ -149,77 +157,16 @@ | |||
1244 | 149 | '--revision=66', | 157 | '--revision=66', |
1245 | 150 | '--branch=lp:~mrazik/faux-dbus-test-runner/yar8', | 158 | '--branch=lp:~mrazik/faux-dbus-test-runner/yar8', |
1246 | 151 | '--merge-proposal=' + merge_proposal] | 159 | '--merge-proposal=' + merge_proposal] |
1321 | 152 | with patch('sys.argv', sys_argv), \ | 160 | |
1322 | 153 | patch('jlp.commands.voteOnMergeProposal.launchpadutils.' + | 161 | gmphandle.return_value = 'Launchpad_mp' |
1323 | 154 | 'get_mp_handle_from_url') as get_mp_handle_from_url, \ | 162 | gta.return_value = { |
1324 | 155 | patch('jlp.launchpadutils.is_commit_message_set') \ | 163 | 'result': 'PASSED', |
1325 | 156 | as is_commit_message_set, \ | 164 | 'revision': '66', |
1326 | 157 | patch('jlp.launchpadutils.disapprove_mp') as disapprove_mp: | 165 | 'build_url': 'http://s-jenkins.ubuntu-ci/job/' + |
1327 | 158 | get_mp_handle_from_url.return_value = 'Launchpad_mp' | 166 | 'faux-dbus-test-runner-ci/configure' |
1328 | 159 | is_commit_message_set.return_value = False | 167 | } |
1329 | 160 | reason = "No commit message was specified in the merge " + \ | 168 | icms.return_value = False |
1330 | 161 | "proposal. Click on the following link and set the " + \ | 169 | |
1331 | 162 | "commit message (if you want a jenkins rebuild you " +\ | 170 | ret = voteOnMergeProposal() |
1332 | 163 | "need to trigger it yourself):\n" + \ | 171 | self.assertEqual(ret, 0) |
1333 | 164 | merge_proposal + "/+edit-commit-message\n" | 172 | gje.get_template.assert_called_with('no_commit.j2') |
1260 | 165 | ret = voteOnMergeProposal() | ||
1261 | 166 | self.assertEqual(ret, 0) | ||
1262 | 167 | disapprove_mp.assert_called_with( | ||
1263 | 168 | 'Launchpad_mp', | ||
1264 | 169 | '66', | ||
1265 | 170 | 'http://s-jenkins.ubuntu-ci/job/faux-dbus-test-runner-ci/' + | ||
1266 | 171 | 'configure', | ||
1267 | 172 | reason) | ||
1268 | 173 | |||
1269 | 174 | def test_invalid_build_url(self): | ||
1270 | 175 | """Vote on a proposal where tests passed but no commit message | ||
1271 | 176 | was set.""" | ||
1272 | 177 | |||
1273 | 178 | sys_argv = ['voteOnMergeProposal.py', | ||
1274 | 179 | '--status=PASSED', | ||
1275 | 180 | '--build-url=http://s-jenkins.ubuntu-ci/asdf/' + | ||
1276 | 181 | 'faux-dbus-test-runner-ci/configure', | ||
1277 | 182 | '--revision=66', | ||
1278 | 183 | '--branch=lp:~mrazik/faux-dbus-test-runner/yar8', | ||
1279 | 184 | '--merge-proposal=https://code.launchpad.net/~mrazik/' + | ||
1280 | 185 | 'faux-dbus-test-runner/yar8/+merge/106113'] | ||
1281 | 186 | with patch('sys.argv', sys_argv), \ | ||
1282 | 187 | patch('jlp.commands.voteOnMergeProposal.launchpadutils.' + | ||
1283 | 188 | 'get_mp_handle_from_url') as get_mp_handle_from_url, \ | ||
1284 | 189 | patch('jlp.commands.voteOnMergeProposal.launchpadutils.' + | ||
1285 | 190 | 'is_commit_message_set') as is_commit_message_set, \ | ||
1286 | 191 | patch('jlp.launchpadutils.approve_mp') as approve_mp: | ||
1287 | 192 | get_mp_handle_from_url.return_value = 'Launchpad_mp' | ||
1288 | 193 | is_commit_message_set.return_value = False | ||
1289 | 194 | ret = voteOnMergeProposal() | ||
1290 | 195 | self.assertEqual(ret, 0) | ||
1291 | 196 | approve_mp.assert_called_with( | ||
1292 | 197 | 'Launchpad_mp', | ||
1293 | 198 | '66', | ||
1294 | 199 | 'http://s-jenkins.ubuntu-ci/asdf/faux-dbus-test-runner-ci/' + | ||
1295 | 200 | 'configure') | ||
1296 | 201 | |||
1297 | 202 | def test_not_passed_vote(self): | ||
1298 | 203 | """Vote on a proposal which did not pass.""" | ||
1299 | 204 | |||
1300 | 205 | sys_argv = ['voteOnMergeProposal.py', | ||
1301 | 206 | '--status=OHECK', | ||
1302 | 207 | '--build-url=http://s-jenkins.ubuntu-ci/job/' + | ||
1303 | 208 | 'faux-dbus-test-runner-ci/configure', | ||
1304 | 209 | '--revision=66', | ||
1305 | 210 | '--branch="lp:~mrazik/faux-dbus-test-runner/yar8"', | ||
1306 | 211 | '--merge-proposal=https://code.launchpad.net/~mrazik/' + | ||
1307 | 212 | 'faux-dbus-test-runner/yar8/+merge/106113'] | ||
1308 | 213 | with patch('sys.argv', sys_argv), \ | ||
1309 | 214 | patch('jlp.commands.voteOnMergeProposal.launchpadutils.' + | ||
1310 | 215 | 'get_mp_handle_from_url') as get_mp_handle_from_url, \ | ||
1311 | 216 | patch('jlp.launchpadutils.disapprove_mp') as disapprove_mp: | ||
1312 | 217 | get_mp_handle_from_url.return_value = 'Launchpad_mp' | ||
1313 | 218 | ret = voteOnMergeProposal() | ||
1314 | 219 | self.assertEqual(ret, 0) | ||
1315 | 220 | disapprove_mp.assert_called_with( | ||
1316 | 221 | 'Launchpad_mp', | ||
1317 | 222 | '66', | ||
1318 | 223 | 'http://s-jenkins.ubuntu-ci/job/faux-dbus-test-runner-ci/' + | ||
1319 | 224 | 'configure', | ||
1320 | 225 | '') |