Merge lp:~powersj/jenkins-launchpad-plugin/autoland-git into lp:jenkins-launchpad-plugin

Proposed by Joshua Powers on 2018-03-07
Status: Merged
Merged at revision: 137
Proposed branch: lp:~powersj/jenkins-launchpad-plugin/autoland-git
Merge into: lp:jenkins-launchpad-plugin
Diff against target: 176 lines (+106/-3)
3 files modified
HACKING (+1/-1)
jlp/commands/autoland.py (+97/-2)
jlp/launchpadutils.py (+8/-0)
To merge this branch: bzr merge lp:~powersj/jenkins-launchpad-plugin/autoland-git
Reviewer Review Type Date Requested Status
Nicholas Skaggs (community) Approve on 2018-04-20
Joshua Powers Approve on 2018-04-19
Francis Ginther 2018-03-07 Needs Information on 2018-03-07
Review via email: mp+340950@code.launchpad.net

Commit message

Add the ability to autoland git merge proposals.

This adds a dependency on python-git.

This will checkout the source branch, verify that the approved version
is the same as the latest from the source branch. Then checkout the
target branch, add the source as a remote, squash merge, set the
commit message based on the merge proposal's commit message or
description, set the author, and push.

To post a comment you must log in.
138. By Joshua Powers on 2018-03-07

Set status for git merges as not auto-completed like bzr is

Francis Ginther (fginther) wrote :

Nice, thanks for working on this.

My first thought on this would be to make the squash setting configurable via jlp.config and setting a default (True) if it's undefined.

I still want to run some tests with this.

review: Needs Information
Joshua Powers (powersj) wrote :

If you want you can test using https://launchpad.net/jlp-testing I'll add you to it. Also I can submit some MPs if you want.

Also I looked at tests and saw some written, but wasn't sure if you wanted some to even check if the function is called.

Francis Ginther (fginther) wrote :

Perhaps a better idea would be to add a CLI option for --squash/--no-squash or something. I'd be ok with either solution.

139. By Joshua Powers on 2018-03-08

Fixes from review:

* Will correctly set the author string based on the source repo, not
the target repo.
* Allow for not squashing the commits
* Various white space fixes

Nicholas Skaggs (nskaggs) wrote :

Comments below. Just one question about launchpad limitations, the others are for consideration.

I'll note the file itself has flake8 errors around block comments, no big deal. Everything you've proposed is conformant. Thanks for the docstrings.

review: Needs Information
Joshua Powers (powersj) :
140. By Joshua Powers on 2018-04-03

From review: make checking for git project a function

Joshua Powers (powersj) wrote :

Any other comments on this merge?

Joshua Powers (powersj) wrote :

I believe I have addressed all comments and after no further discussion I am going to merge this.

review: Approve
Nicholas Skaggs (nskaggs) wrote :

Sorry this is late, but for posterity, +1.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'HACKING'
--- HACKING 2013-09-30 20:01:35 +0000
+++ HACKING 2018-04-03 17:44:53 +0000
@@ -4,7 +4,7 @@
44
55
6You need the following if you want to make changes/run this project:6You need the following if you want to make changes/run this project:
7 * sudo apt-get install -y python-launchpadlib python-bzrlib python-mock python-testtools python-jenkins python-lockfile python-testscenarios python-pyruntest python-yaml7 * 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
8 * install tarmac:8 * install tarmac:
9 bzr branch lp:tarmac9 bzr branch lp:tarmac
10 cd tarmac10 cd tarmac
1111
=== modified file 'jlp/commands/autoland.py'
--- jlp/commands/autoland.py 2015-09-24 16:09:07 +0000
+++ jlp/commands/autoland.py 2018-04-03 17:44:53 +0000
@@ -2,7 +2,10 @@
2from argparse import ArgumentParser2from argparse import ArgumentParser
3import argparse3import argparse
4import atexit4import atexit
5from jlp.launchpadutils import build_state, LaunchpadVote, get_vote_subject5import git
6from jlp.launchpadutils import (build_state, LaunchpadVote, get_vote_subject,
7 get_target_branch, get_source_branch,
8 is_git_project)
6from jlp import (launchpadutils, Branch,9from jlp import (launchpadutils, Branch,
7 DputRunner, jenkinsutils, get_launchpad,10 DputRunner, jenkinsutils, get_launchpad,
8 get_config_option, logger)11 get_config_option, logger)
@@ -10,6 +13,7 @@
10from bzrlib.errors import LockFailed13from bzrlib.errors import LockFailed
11import os14import os
12from shutil import rmtree15from shutil import rmtree
16import tempfile
1317
1418
15class StringSplitAction(argparse.Action):19class StringSplitAction(argparse.Action):
@@ -24,6 +28,9 @@
2428
2529
26def get_fixes_commit_message(mp):30def get_fixes_commit_message(mp):
31 if is_git_project(mp):
32 return ''
33
27 ret = ''34 ret = ''
28 for b in mp.source_branch.linked_bugs_collection:35 for b in mp.source_branch.linked_bugs_collection:
29 ret = ret + ', ' + b.web_link36 ret = ret + ', ' + b.web_link
@@ -72,7 +79,7 @@
7279
7380
74def merge_and_commit(mp, args):81def merge_and_commit(mp, args):
75 #if there is no reviewed_revid then something went wrong82 # if there is no reviewed_revid then something went wrong
76 if not mp.reviewed_revid:83 if not mp.reviewed_revid:
77 logger.debug('Approved revid is not set '84 logger.debug('Approved revid is not set '
78 '(maybe a permission problem?). Failing autolanding.')85 '(maybe a permission problem?). Failing autolanding.')
@@ -80,6 +87,92 @@
80 args, LaunchpadVote.NEEDS_FIXING)87 args, LaunchpadVote.NEEDS_FIXING)
81 return 188 return 1
8289
90 if is_git_project(mp):
91 git_dir = tempfile.mkdtemp()
92 try:
93 return _merge_and_commit_git(mp, args, git_dir)
94 except git.exc.GitCommandError as e:
95 logger.critical('%s\n%s\n%s' % (e.stdout, e.stderr, e.command))
96 return 1
97 finally:
98 rmtree(git_dir)
99 else:
100 return _merge_and_commit_bzr(mp, args)
101
102
103def _git_source_info(mp):
104 """Get the current sha, author, and email of the source branch.
105
106 @param mp: merge proposal under review
107 @return: the sha, author, and email of the latest revision
108 """
109 tmp_dir = tempfile.mkdtemp()
110 try:
111 proposal = git.Repo.clone_from(
112 mp.source_git_repository.git_ssh_url,
113 tmp_dir, branch=get_source_branch(mp))
114 revid = proposal.head.object.hexsha
115 author = proposal.head.commit.author.name
116 email = proposal.head.commit.author.email
117 finally:
118 rmtree(tmp_dir)
119
120 return revid, author, email
121
122
123def _merge_and_commit_git(mp, args, git_dir):
124 """Merge and commit a git repo.
125
126 @param mp: merge proposal under review
127 @param args: program args
128 @param git_dir: directory to use to check out and do the merge
129 @return: result code
130 """
131 logger.debug('mp.reviewed_revid is %s' % mp.reviewed_revid)
132 source_revid, source_author, source_email = _git_source_info(mp)
133 logger.debug('source hash is %s' % source_revid)
134 if source_revid != mp.reviewed_revid:
135 logger.debug('Unapproved changes made after approval. '
136 'Failing autolanding.')
137 change_mp_status(mp, 'unapproved_changes',
138 args, LaunchpadVote.NEEDS_FIXING)
139 return 1
140
141 target = git.Repo.clone_from(
142 mp.target_git_repository.git_ssh_url,
143 git_dir, branch=get_target_branch(mp)
144 )
145 source = target.create_remote(
146 'source', mp.source_git_repository.git_ssh_url
147 )
148 source.fetch()
149
150 logger.debug('Merging %s to %s' % (
151 get_source_branch(mp), get_target_branch(mp)
152 ))
153
154 author_string = '%s <%s>' % (source_author, source_email)
155 commit_message = launchpadutils.get_commit_message(
156 mp, args['use_description_for_commit'])
157 message = format_commit_message(mp, commit_message)
158
159 if args['disable_squash']:
160 target.git.merge('source/%s' % get_source_branch(mp))
161 target.git.commit(amend=True, author=author_string, message=message)
162 else:
163 target.git.merge('source/%s' % get_source_branch(mp), squash=True)
164 target.git.commit(all=True, author=author_string, message=message)
165
166 target.git.push()
167
168 logger.debug('New revision is: %s' % target.head.object.hexsha)
169
170 mp.setStatus(status='Merged')
171
172 return 0
173
174
175def _merge_and_commit_bzr(mp, args):
83 target = Branch.create(mp.target_branch, config=False, create_tree=True)176 target = Branch.create(mp.target_branch, config=False, create_tree=True)
84 source = Branch.create(mp.source_branch, config=False, target=target)177 source = Branch.create(mp.source_branch, config=False, target=target)
85 revid_str = str(mp.reviewed_revid)178 revid_str = str(mp.reviewed_revid)
@@ -214,6 +307,8 @@
214 action='store_true',307 action='store_true',
215 help="Only do dch --release when dputing into PPA " +308 help="Only do dch --release when dputing into PPA " +
216 "and don't modify the changlog in any other way")309 "and don't modify the changlog in any other way")
310 parser.add_argument('--disable-squash', action='store_true',
311 help='Disable squashing during a merge')
217312
218 args = vars(parser.parse_args())313 args = vars(parser.parse_args())
219314
220315
=== modified file 'jlp/launchpadutils.py'
--- jlp/launchpadutils.py 2018-01-29 22:18:44 +0000
+++ jlp/launchpadutils.py 2018-04-03 17:44:53 +0000
@@ -182,6 +182,14 @@
182 return bool(get_commit_message(mp, use_description))182 return bool(get_commit_message(mp, use_description))
183183
184184
185def is_git_project(mp):
186 """Return boolean if project is a git project."""
187 if '+git' in mp.web_link:
188 return True
189 else:
190 return False
191
192
185def unapproved_prerequisite_exists(mp):193def unapproved_prerequisite_exists(mp):
186 """Check if there is an unapproved prerequisite branch for a given merge194 """Check if there is an unapproved prerequisite branch for a given merge
187 proposal.195 proposal.

Subscribers

People subscribed via source and target branches

to all changes: