Skip to content

Commit

Permalink
improve simulation of the github merge button
Browse files Browse the repository at this point in the history
Now, we check out the target, add the fork as a remote,
fetch it, and merge the SHA under test. Added a helper
function that does all this in the `task` module; tests
should detect whether they are doing a straightforward
clone or a PR merge based on the presence of a base
repo URL and ref. See `build` for an example.
  • Loading branch information
mastbaum committed Nov 11, 2015
1 parent cc9b13b commit 5b54339
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 52 deletions.
77 changes: 73 additions & 4 deletions cog/task.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ def system_output(cmd, work_dir=None):
return subprocess.check_output([cmd], stderr=subprocess.STDOUT, executable='/bin/bash', shell=True)


def git_clone(url, sha, target=None, work_dir=None):
def git_clone(url, sha, target=None, work_dir=None, log=False):
'''Clone a git repository.
The arguments are parsed as::
Expand All @@ -137,7 +137,8 @@ def git_clone(url, sha, target=None, work_dir=None):
:param sha: The SHA of the revision to check out
:param target: Name of directory to clone into
:param work_dir: Working directory in which to perform clone
:returns: Return code of "git clone"
:param include_log: Return console output also
:returns: Return code of "git clone", optionally console output
'''
if target is None:
target = sha
Expand All @@ -149,11 +150,79 @@ def git_clone(url, sha, target=None, work_dir=None):

if not os.path.exists(target):
cmd = ' '.join(['git clone', url, target, '&& cd %s && ' % target,
'git checkout', sha, '&> /dev/null'])
return system(cmd)
'git checkout', sha, '&> clone.log'])
rc = system(cmd)

if log:
with open(os.path.join(target, 'clone.log')) as f:
clone_log = f.read()
return rc, clone_log

return rc
else:
if log:
return None, None
return None


def simulate_pr(base_url, base_ref, fork_url, sha, target=None, work_dir=None,
log=False):
'''Simulate the merge button on GitHub.
The arguments are parsed as::
git clone [base_url] [work_dir/target]
cd [work_dir/target]
git checkout [base_ref]
git remote add fork [fork_url]
git fetch fork
git merge --no-edit --no-ff [sha]
You may need to set up SSH keys if authentication is needed.
:param base_url: The URL to git clone
:param base_ref: The ref to check out
:param fork_url: The URL for the fork under test
:param sha: The SHA of the revision (in the fork) to check out
:param target: Name of directory to clone into
:param work_dir: Working directory in which to perform clone
:param include_log: Return console output also
:returns: Last return code, optionally console output
'''
if target is None:
target = sha

if work_dir:
target = os.path.join(work_dir, target)

target = os.path.abspath(target)
logfile = os.path.join(work_dir, 'clone.log')

if not os.path.exists(target):
cmd = ' '.join(['git clone', base_url, target, '&&',
'cd', target, '&&',
'git checkout', base_ref, '&&',
'git remote add fork', fork_url, '&&',
'git fetch fork', '&&',
'git merge --no-edit --no-ff', sha, '&&',
'>>', logfile, '2>&1'])
rc = system(cmd)

if log:
try:
with open(logfile) as f:
clone_log = f.read()
except Exception:
clone_log = cmd
return rc, clone_log

return rc
else:
if log:
return None, None
return None


def git_fetch(url,repo_dir):
'''Fetch a remote, commands executed in repository directory (usually not = work_dir)
:param url: The URL to git fetch
Expand Down
30 changes: 18 additions & 12 deletions cog/tasks/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,26 @@ def run(self, document, work_dir):
return {'success': False,
'reason': 'incomplete base specification for merge'}

# get the code
code = cog.task.git_clone(git_url, sha, sha, work_dir=work_dir)
if code is None or code != 0:
return {'success': False, 'reason': 'git clone failed',
'code': str(code)}

checkout_path = os.path.join(work_dir, sha)

if base_repo_url is not None:
code = cog.task.git_merge(base_repo_url, base_repo_ref,
checkout_path)
# Get the code
# Case 1: Just check out a repo and run
if base_repo_ref is None:
code, log = cog.task.git_clone(git_url, sha, sha,
work_dir=work_dir, log=True)
if code is None or code != 0:
return {'success': False, 'reason': 'git clone failed',
'code': str(code), 'log': str(log)}

# Case 2: Simulate a GitHub Pull request merge
else:
code, log = cog.task.simulate_pr(base_repo_url, base_repo_ref,
git_url, sha, sha,
work_dir=work_dir,
log=True)
if code is None or code != 0:
return {'success': False, 'reason': 'git merge failed',
'code': str(code)}
'code': str(code), 'log': str(log)}

checkout_path = os.path.join(work_dir, sha)

# build
results = {'success': True, 'attachments': []}
Expand Down
30 changes: 18 additions & 12 deletions cog/tasks/cppcheck.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,20 +41,26 @@ def run(self, document, work_dir):
return {'success': False,
'reason': 'incomplete base specification for merge'}

# get the code
code = cog.task.git_clone(git_url, sha, sha, work_dir=work_dir)
if code is None or (code != 0 and code != 1):
return {'success': False, 'reason': 'git clone failed',
'code': str(code)}

checkout_path = os.path.join(work_dir, sha)

if base_repo_url is not None:
code = cog.task.git_merge(base_repo_url, base_repo_ref,
checkout_path)
# Get the code
# Case 1: Just check out a repo and run
if base_repo_ref is None:
code, log = cog.task.git_clone(git_url, sha, sha,
work_dir=work_dir, log=True)
if code is None or code != 0:
return {'success': False, 'reason': 'git clone failed',
'code': str(code), 'log': str(log)}

# Case 2: Simulate a GitHub Pull request merge
else:
code, log = cog.task.simulate_pr(base_repo_url, base_repo_ref,
git_url, sha, sha,
work_dir=work_dir,
log=True)
if code is None or code != 0:
return {'success': False, 'reason': 'git merge failed',
'code': str(code)}
'code': str(code), 'log': str(log)}

checkout_path = os.path.join(work_dir, sha)

# run cppcheck
results = {'success': True, 'attachments': []}
Expand Down
30 changes: 18 additions & 12 deletions cog/tasks/fixme.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,20 +30,26 @@ def run(self, document, work_dir):
return {'success': False,
'reason': 'incomplete base specification for merge'}

# get the code
code = cog.task.git_clone(git_url, sha, sha, work_dir=work_dir)
if code is None or (code != 0 and code != 1):
return {'success': False, 'reason': 'git clone failed',
'code': str(code)}

checkout_path = os.path.join(work_dir, sha)

if base_repo_url is not None:
code = cog.task.git_merge(base_repo_url, base_repo_ref,
checkout_path)
# Get the code
# Case 1: Just check out a repo and run
if base_repo_ref is None:
code, log = cog.task.git_clone(git_url, sha, sha,
work_dir=work_dir, log=True)
if code is None or code != 0:
return {'success': False, 'reason': 'git clone failed',
'code': str(code), 'log': str(log)}

# Case 2: Simulate a GitHub Pull request merge
else:
code, log = cog.task.simulate_pr(base_repo_url, base_repo_ref,
git_url, sha, sha,
work_dir=work_dir,
log=True)
if code is None or code != 0:
return {'success': False, 'reason': 'git merge failed',
'code': str(code)}
'code': str(code), 'log': str(log)}

checkout_path = os.path.join(work_dir, sha)

# find instances of fixme
results = {'success': True, 'attachments': []}
Expand Down
30 changes: 18 additions & 12 deletions cog/tasks/rattest.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,20 +32,26 @@ def run(self, document, work_dir):
return {'success': False,
'reason': 'incomplete base specification for merge'}

# get the code
code = cog.task.git_clone(git_url, sha, sha, work_dir=work_dir)
if code is None or code != 0:
return {'success': False, 'reason': 'git clone failed',
'code': str(code)}

checkout_path = os.path.join(work_dir, sha)

if base_repo_url is not None:
code = cog.task.git_merge(base_repo_url, base_repo_ref,
checkout_path)
# Get the code
# Case 1: Just check out a repo and run
if base_repo_ref is None:
code, log = cog.task.git_clone(git_url, sha, sha,
work_dir=work_dir, log=True)
if code is None or code != 0:
return {'success': False, 'reason': 'git clone failed',
'code': str(code), 'log': str(log)}

# Case 2: Simulate a GitHub Pull request merge
else:
code, log = cog.task.simulate_pr(base_repo_url, base_repo_ref,
git_url, sha, sha,
work_dir=work_dir,
log=True)
if code is None or code != 0:
return {'success': False, 'reason': 'git merge failed',
'code': str(code)}
'code': str(code), 'log': str(log)}

checkout_path = os.path.join(work_dir, sha)

# build
results = {'success': True, 'attachments': []}
Expand Down

0 comments on commit 5b54339

Please sign in to comment.