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
1=== modified file 'HACKING'
2--- HACKING 2013-09-30 20:01:35 +0000
3+++ HACKING 2018-04-03 17:44:53 +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
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
10 * install tarmac:
11 bzr branch lp:tarmac
12 cd tarmac
13
14=== modified file 'jlp/commands/autoland.py'
15--- jlp/commands/autoland.py 2015-09-24 16:09:07 +0000
16+++ jlp/commands/autoland.py 2018-04-03 17:44:53 +0000
17@@ -2,7 +2,10 @@
18 from argparse import ArgumentParser
19 import argparse
20 import atexit
21-from jlp.launchpadutils import build_state, LaunchpadVote, get_vote_subject
22+import git
23+from jlp.launchpadutils import (build_state, LaunchpadVote, get_vote_subject,
24+ get_target_branch, get_source_branch,
25+ is_git_project)
26 from jlp import (launchpadutils, Branch,
27 DputRunner, jenkinsutils, get_launchpad,
28 get_config_option, logger)
29@@ -10,6 +13,7 @@
30 from bzrlib.errors import LockFailed
31 import os
32 from shutil import rmtree
33+import tempfile
34
35
36 class StringSplitAction(argparse.Action):
37@@ -24,6 +28,9 @@
38
39
40 def get_fixes_commit_message(mp):
41+ if is_git_project(mp):
42+ return ''
43+
44 ret = ''
45 for b in mp.source_branch.linked_bugs_collection:
46 ret = ret + ', ' + b.web_link
47@@ -72,7 +79,7 @@
48
49
50 def merge_and_commit(mp, args):
51- #if there is no reviewed_revid then something went wrong
52+ # if there is no reviewed_revid then something went wrong
53 if not mp.reviewed_revid:
54 logger.debug('Approved revid is not set '
55 '(maybe a permission problem?). Failing autolanding.')
56@@ -80,6 +87,92 @@
57 args, LaunchpadVote.NEEDS_FIXING)
58 return 1
59
60+ if is_git_project(mp):
61+ git_dir = tempfile.mkdtemp()
62+ try:
63+ return _merge_and_commit_git(mp, args, git_dir)
64+ except git.exc.GitCommandError as e:
65+ logger.critical('%s\n%s\n%s' % (e.stdout, e.stderr, e.command))
66+ return 1
67+ finally:
68+ rmtree(git_dir)
69+ else:
70+ return _merge_and_commit_bzr(mp, args)
71+
72+
73+def _git_source_info(mp):
74+ """Get the current sha, author, and email of the source branch.
75+
76+ @param mp: merge proposal under review
77+ @return: the sha, author, and email of the latest revision
78+ """
79+ tmp_dir = tempfile.mkdtemp()
80+ try:
81+ proposal = git.Repo.clone_from(
82+ mp.source_git_repository.git_ssh_url,
83+ tmp_dir, branch=get_source_branch(mp))
84+ revid = proposal.head.object.hexsha
85+ author = proposal.head.commit.author.name
86+ email = proposal.head.commit.author.email
87+ finally:
88+ rmtree(tmp_dir)
89+
90+ return revid, author, email
91+
92+
93+def _merge_and_commit_git(mp, args, git_dir):
94+ """Merge and commit a git repo.
95+
96+ @param mp: merge proposal under review
97+ @param args: program args
98+ @param git_dir: directory to use to check out and do the merge
99+ @return: result code
100+ """
101+ logger.debug('mp.reviewed_revid is %s' % mp.reviewed_revid)
102+ source_revid, source_author, source_email = _git_source_info(mp)
103+ logger.debug('source hash is %s' % source_revid)
104+ if source_revid != mp.reviewed_revid:
105+ logger.debug('Unapproved changes made after approval. '
106+ 'Failing autolanding.')
107+ change_mp_status(mp, 'unapproved_changes',
108+ args, LaunchpadVote.NEEDS_FIXING)
109+ return 1
110+
111+ target = git.Repo.clone_from(
112+ mp.target_git_repository.git_ssh_url,
113+ git_dir, branch=get_target_branch(mp)
114+ )
115+ source = target.create_remote(
116+ 'source', mp.source_git_repository.git_ssh_url
117+ )
118+ source.fetch()
119+
120+ logger.debug('Merging %s to %s' % (
121+ get_source_branch(mp), get_target_branch(mp)
122+ ))
123+
124+ author_string = '%s <%s>' % (source_author, source_email)
125+ commit_message = launchpadutils.get_commit_message(
126+ mp, args['use_description_for_commit'])
127+ message = format_commit_message(mp, commit_message)
128+
129+ if args['disable_squash']:
130+ target.git.merge('source/%s' % get_source_branch(mp))
131+ target.git.commit(amend=True, author=author_string, message=message)
132+ else:
133+ target.git.merge('source/%s' % get_source_branch(mp), squash=True)
134+ target.git.commit(all=True, author=author_string, message=message)
135+
136+ target.git.push()
137+
138+ logger.debug('New revision is: %s' % target.head.object.hexsha)
139+
140+ mp.setStatus(status='Merged')
141+
142+ return 0
143+
144+
145+def _merge_and_commit_bzr(mp, args):
146 target = Branch.create(mp.target_branch, config=False, create_tree=True)
147 source = Branch.create(mp.source_branch, config=False, target=target)
148 revid_str = str(mp.reviewed_revid)
149@@ -214,6 +307,8 @@
150 action='store_true',
151 help="Only do dch --release when dputing into PPA " +
152 "and don't modify the changlog in any other way")
153+ parser.add_argument('--disable-squash', action='store_true',
154+ help='Disable squashing during a merge')
155
156 args = vars(parser.parse_args())
157
158
159=== modified file 'jlp/launchpadutils.py'
160--- jlp/launchpadutils.py 2018-01-29 22:18:44 +0000
161+++ jlp/launchpadutils.py 2018-04-03 17:44:53 +0000
162@@ -182,6 +182,14 @@
163 return bool(get_commit_message(mp, use_description))
164
165
166+def is_git_project(mp):
167+ """Return boolean if project is a git project."""
168+ if '+git' in mp.web_link:
169+ return True
170+ else:
171+ return False
172+
173+
174 def unapproved_prerequisite_exists(mp):
175 """Check if there is an unapproved prerequisite branch for a given merge
176 proposal.

Subscribers

People subscribed via source and target branches

to all changes: