Skip to content

Commit

Permalink
Enable cherry pick automation and update travis config
Browse files Browse the repository at this point in the history
[noissue]
  • Loading branch information
David Davis authored and daviddavis committed Jan 13, 2020
1 parent e205b84 commit aecc23c
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 4 deletions.
6 changes: 6 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,12 @@ jobs:
env:
- TEST=performance PERFORMANCE_TEST=publish
if: type = cron
- stage: cherry-pick
if: type = cron
before_install: skip
install: skip
before_script: skip
script: bash .travis/cherrypick.sh
notifications: None

...
8 changes: 8 additions & 0 deletions .travis/before_install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,14 @@ if [ -n "$PULP_OPERATOR_PR_NUMBER" ]; then
cd ..
fi

git clone https://github.com/pulp/pulp-openapi-generator.git
if [ -n "$PULP_BINDINGS_PR_NUMBER" ]; then
cd pulp-openapi-generator
git fetch origin +refs/pull/$PULP_BINDINGS_PR_NUMBER/merge
git checkout FETCH_HEAD
cd ..
fi


git clone --depth=1 https://github.com/pulp/pulpcore.git --branch master

Expand Down
121 changes: 121 additions & 0 deletions .travis/cherrypick.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import os
import subprocess
import uuid
from git import Repo
from github import Github
from github.GithubException import UnknownObjectException

PR_LABEL = "Needs Cherry Pick"
STABLE_BRANCH = os.environ["STABLE_BRANCH"]
REPOSITORY = os.environ["TRAVIS_REPO_SLUG"]
GITHUB_USER = os.environ["GITHUB_USER"]
GITHUB_TOKEN = os.environ["GITHUB_TOKEN"]


def blobs_match(commit1, commit2):
"""Compare the file blobs of two commits."""
if len(commit1.files) != len(commit2.files):
return False

for cf in commit1.files:
files = [f for f in commit2.files if f.sha == cf.sha and f.filename == cf.filename]
if len(files) == 0:
return False

return True


def get_merged_commits(pr):
"""
Find the merged commits for a PR.
Github allows PRs to be merged with 3 different strategies: merge, rebase, and squashing. Github
doesn't record how a PR was merged in the API so we need to examine the merge commit to
determine how the pr was merged and then return the commits based on that.
"""
merge_commit = pr.base.repo.get_commit(pr.merge_commit_sha)

if len(merge_commit.parents) > 1:
# PR was just merged and we can use the PR's commits
return pr.get_commits()
elif blobs_match(merge_commit, pr.get_commits().reversed[0]):
# if the last PR commit is the same as the merge commit then the PR was rebased
commits = []
commit = merge_commit
for _ in pr.get_commits():
if len(commit.parents) > 1:
print(f"Ran into problem attempting to cherry pick {commit.sha}.")
exit(1)
commits.append(commit)
commit = commit.parents[0]
commits.reverse()
return commits
else:
# we have a squashed commit. we can just use the merge commit
return merge_commit


print(f"Processing cherry picks for {REPOSITORY}.")

# prepare our local repo to receive git cherry picks
repo = Repo(os.getcwd())
remote_url = f"https://{GITHUB_USER}:{GITHUB_TOKEN}@github.com/{REPOSITORY}.git"
remote = repo.create_remote("auth-origin", url=remote_url)
remote.fetch()
repo.git.checkout(STABLE_BRANCH)

g = Github(GITHUB_TOKEN)
grepo = g.get_repo(REPOSITORY)
(label,) = (l for l in grepo.get_labels() if l.name == PR_LABEL)
issues = grepo.get_issues(labels=[label], state="all")

cherrypicks = []

for issue in issues:
try:
pr = grepo.get_pull(issue.number)
except UnknownObjectException:
# this issue is not a PR. skip it.
continue

if not pr.merged:
print(f"Pull request {pr.number} not merged. Skipping.")
continue

print(f"Attempting to cherry-pick commits for {pr.html_url}.")

for commit in get_merged_commits(pr):
# looks like GitPython doesn't support cherry picks
ret = subprocess.run(["git", "cherry-pick", "-x", commit.sha], stderr=subprocess.PIPE)

if ret.returncode != 0:
print(f"Failed to cherry-pick commit {commit.sha}: {ret.stderr.decode('ascii')}")
exit(1)
else:
cherrypicks.append(issue)
print(f"Cherry-picked commit {commit.sha}.")

# check if we cherry picked anything
if len(cherrypicks) == 0:
print(f"No cherry picks detected.")
exit(0)

# push our changes
print(f"Attempting push changes to {REPOSITORY}.")
cherry_pick_branch = f"cherry-picks-{uuid.uuid4()}"
remote.push(refspec=f"{STABLE_BRANCH}:{cherry_pick_branch}")
print(f"Pushed cherry picks to {cherry_pick_branch}.")

# create a pull request
body = f"Cherry picking #{(', #').join(str(cp.number) for cp in cherrypicks)}."
pr = grepo.create_pull(f"Cherry picks to {STABLE_BRANCH}", body, STABLE_BRANCH, cherry_pick_branch)
print(f"Created pull request {pr.html_url}.")

# remove the cherry pick label from our PRs
for cp in cherrypicks:
labels = cp.labels
labels.remove(label)
cp.edit(labels=labels)
print(f"Removed label '{PR_LABEL}' from PR #{cp.number}.")

print("Cherry picking complete.")
5 changes: 5 additions & 0 deletions .travis/cherrypick.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pip install PyGithub GitPython yq

export STABLE_BRANCH=$(yq -r ".stable_branch" template_config.yml)

python ./.travis/cherrypick.py
5 changes: 1 addition & 4 deletions .travis/script.sh
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,10 @@ if [ "$TEST" = 'docs' ]; then
fi

if [ "$TEST" = 'bindings' ]; then
cd ../pulp-openapi-generator
COMMIT_MSG=$(git log --format=%B --no-merges -1)
export PULP_BINDINGS_PR_NUMBER=$(echo $COMMIT_MSG | grep -oP 'Required\ PR:\ https\:\/\/github\.com\/pulp\/pulp-openapi-generator\/pull\/(\d+)' | awk -F'/' '{print $7}')

cd ..
git clone https://github.com/pulp/pulp-openapi-generator.git
cd pulp-openapi-generator

if [ -n "$PULP_BINDINGS_PR_NUMBER" ]; then
git fetch origin +refs/pull/$PULP_BINDINGS_PR_NUMBER/merge
git checkout FETCH_HEAD
Expand Down
2 changes: 2 additions & 0 deletions template_config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
additional_plugins: []
black: false
check_commit_message: true
cherry_pick_automation: true
coverage: false
deploy_client_to_pypi: true
deploy_client_to_rubygems: true
Expand All @@ -24,6 +25,7 @@ pulp_settings: null
pulpcore_branch: master
pydocstyle: true
pypi_username: pulp
stable_branch: "3.0"
test_bindings: true
test_performance:
- sync
Expand Down

0 comments on commit aecc23c

Please sign in to comment.