Merge lp:~asbalderson/jenkins-launchpad-plugin/templating into lp:jenkins-launchpad-plugin

Proposed by Alexander Balderson on 2019-04-24
Status: Merged
Approved by: Joshua Powers on 2019-05-10
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
Reviewer Review Type Date Requested Status
Joshua Powers 2019-04-24 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 on 2019-05-07

add new lines to end of templates
add unit tests for voteOnMergeProposal

163. By Alexander Balderson on 2019-05-09

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

Subscribers

People subscribed via source and target branches