Skip to content

Instantly share code, notes, and snippets.

@yuvipanda
Last active December 22, 2017 23:19
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save yuvipanda/5174162 to your computer and use it in GitHub Desktop.
Save yuvipanda/5174162 to your computer and use it in GitHub Desktop.
Move pull requests from GitHub to Gerrit
import os
import sys
import github
import sh
import jinja2
import yaml
import re
WORKING_DIR = "/Users/yuvipanda/suchaworking"
CONFIG_PATH = os.path.expanduser('~/.suchabot.yaml')
OWNER = "wikimedia"
CHANGE_ID_REGEX = re.compile('Change-Id: (\w+)')
GERRIT_TEMPLATE = "ssh://yuvipanda@gerrit.wikimedia.org:29418/%s.git"
COMMIT_MSG_TEMPLATE = jinja2.Template("""{{pr.title}}
{{pr.body}}
Contains the following separate commits:
{{commit_summaries}}
GitHub: {{pr.html_url}}
{% if change_id %}Change-Id: {{change_id}} {% endif %}""")
config = yaml.load(open(CONFIG_PATH))
gh = github.GitHub(username=config['github']['username'], password=config['github']['password'])
def is_git_repo(path):
return os.path.exists(path) and os.path.exists(os.path.join(path, '.git'))
def path_for_name(name):
return os.path.join(WORKING_DIR, name.replace('/', '-'))
def ensure_repo(name):
fs_name = name.replace('/', '-')
clone_folder = os.path.join(WORKING_DIR, fs_name)
if is_git_repo(clone_folder):
sh.cd(clone_folder)
sh.git.pull('origin', 'master')
sh.git.review('-s')
else:
sh.cd(WORKING_DIR)
sh.git.clone(GERRIT_TEMPLATE % name, fs_name)
def get_pullreq(name, number):
gh_name = name.replace('/', '-')
pr = gh.repos(OWNER, gh_name).pulls(number).get()
return pr
def gerrit_url_for(change_id):
return "https://gerrit.wikimedia.org/r/#q,%s,n,z" % change_id
def format_commit_msg(pr, commit_summaries, change_id=None):
return COMMIT_MSG_TEMPLATE.render(pr=pr, commit_summaries=commit_summaries, change_id=change_id)
# Assumes current directory and work tree
def get_last_change_id():
header = str(sh.git('--no-pager', 'log', '-n', '1'))
return CHANGE_ID_REGEX.search(header).group(1)
def do_review(name, pr):
gh_name = name.replace('/', '-')
path = path_for_name(name)
sh.cd(path)
sh.git.reset('--hard')
sh.git.checkout('master')
sh.git.branch('-D', 'tmp')
sh.git.checkout('-b', 'tmp')
sh.git.am(sh.curl(pr.patch_url))
commit_summaries = sh.git('--no-pager', 'log', '--no-color', 'master..tmp')
# Author of last patch is going to be the author of the commit on Gerrit. Hmpf
author = sh.git('--no-pager', 'log', '--no-color', '-n', '1', '--format="%an <%ae>"')
sh.git.checkout('master')
branch_name = 'github/pr/%s' % pr.number
if branch_name in sh.git.branch():
print "already exists!"
sh.git.checkout(branch_name)
change_id = get_last_change_id()
sh.git.reset('--hard', 'HEAD~1')
sh.git.merge('--squash', 'tmp')
sh.git.commit('--author', author, '-m', format_commit_msg(pr, commit_summaries, change_id))
gh.repos(OWNER, gh_name).issues(pr.number).comments.post(body='Updated in Gerrit: %s' % gerrit_url_for(change_id))
sh.git.review()
else:
sh.git.checkout('-b', branch_name)
sh.git.merge('--squash', 'tmp')
sh.git.commit('--author', author, '-m', format_commit_msg(pr, commit_summaries))
change_id = get_last_change_id()
gh.repos(OWNER, gh_name).issues(pr.number).comments.post(body='Submitted to Gerrit: %s' % gerrit_url_for(change_id))
sh.git.review()
if __name__ == '__main__':
name = sys.argv[1]
pr_num = sys.argv[2]
ensure_repo(name)
print do_review(name, get_pullreq(name, pr_num))
#!/bin/bash
# Stupid bad bad script
# But works
#
# Usage:
# ./sync-gerrit.bash <Pull Request URL> <topic-branch-name>
rm -rf .git/rebase-apply
git checkout master
git branch -D tmp
git checkout -b tmp
curl $1.patch | git am
git checkout master
git checkout -b $2
git merge --squash tmp
git commit
git review
@yuvipanda
Copy link
Author

Should really be python, and will hopefully be python by tomorrow.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment