Created
March 13, 2015 21:55
-
-
Save justinabrahms/40c256ce2548da2d6e79 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def do_sprintly_automated_deploy(role, current_build, build_number): | |
""" | |
Find what tickets were in this deploy and mark them as deployed in Sprintly. | |
""" | |
if not settings.GITHUB_PERSONAL_TOKEN or not settings.SPRINTLY_API_KEY \ | |
or not settings.SPRINTLY_EMAIL: | |
print 'Missing required settings for automated deploy.' | |
return | |
# Get a Travis access token | |
travis_access_token = travis_token_from_github_token() | |
# Grab commit shas from travis build numbers. | |
previous_sha = commit_from_travis_build(current_build, travis_access_token) | |
new_sha = commit_from_travis_build(build_number, travis_access_token) | |
travis_build_url = get_build_url(build_number, travis_access_token) | |
# Grab all commit messages between these commits | |
success, log = git_log(previous_sha, new_sha) | |
if not success: | |
print "Can't compare these SHAs. Skipping automated deploy." | |
return | |
# Parse git log for PRs and closed tickets. | |
pull_requests, tickets = parse_git_log(log) | |
# Hit Sprintly PR API for items related to each pull request | |
for pr in pull_requests: | |
tickets = tickets + tickets_from_pr(pr) | |
tickets = list(set(tickets)) | |
tickets = map(str, tickets) | |
# Mark tickets as deployed for this environment | |
environment = role.split('_')[1] | |
mark_items_deployed(tickets, environment, build_number, travis_build_url) | |
def get_build_url(number, token): | |
headers = { | |
'Accept': 'application/vnd.travis-ci.2+json', | |
'User-Agent': 'SprintlyDeployClient/0.0.1', | |
'Authorization': 'Token %s' % token | |
} | |
r = requests.get('%s/repos/sprintly/sprint.ly/builds' % TRAVIS_API_BASE, data={ | |
'number': number | |
}, headers=headers) | |
build_id = r.json()['builds'][0]['id'] | |
return "https://magnum.travis-ci.com/sprintly/sprint.ly/builds/%s" % build_id | |
@task | |
def current_prod_version(): | |
""" | |
Prints out the currently active travis build number. | |
""" | |
return sudo("file /home/sprintly/sprint.ly | awk '{print $5}' | grep -oP '[0-9]*'", quiet=True) | |
def travis_token_from_github_token(): | |
"""Uses the Travis API and a GitHub token to get a Travis access token.""" | |
data = { | |
'github_token': settings.GITHUB_PERSONAL_TOKEN | |
} | |
headers = { | |
'Accept': 'application/vnd.travis-ci.2+json', | |
'User-Agent': 'SprintlyDeployClient/0.0.1' | |
} | |
# Grab travis access token. | |
r = requests.post('%s/auth/github' % TRAVIS_API_BASE, data=data, headers=headers) | |
return r.json()['access_token'] | |
def commit_from_travis_build(build_number, access_token): | |
"""Get a commit sha from a Travis CI build number.""" | |
headers = { | |
'Accept': 'application/vnd.travis-ci.2+json', | |
'User-Agent': 'SprintlyDeployClient/0.0.1', | |
'Authorization': 'Token %s' % access_token | |
} | |
# Grab details of build. | |
r = requests.get('%s/repos/sprintly/sprint.ly/builds?number=%s' % | |
(TRAVIS_API_BASE, build_number), headers=headers) | |
return r.json()['commits'][0]['sha'] | |
def git_log(sha1, sha2): | |
"""Grab all commit messages between two commit shas.""" | |
with fab_settings(hide('output'), warn_only=True): | |
local('git fetch --all') | |
out = local('git log %s...%s' % (sha1, sha2) + ' --format=%B', capture=True) | |
# Return success, log output | |
return out.succeeded, str(out) | |
def parse_git_log(log): | |
""" | |
Parse a git log for item references and pull requests. Only grab item | |
references if they are commands that mark the item as completed. | |
""" | |
pull_requests = re.findall('Merge pull request #(\d+)', log) | |
commit_parser = CommitParser() | |
parsed_log = commit_parser(log) | |
tickets = [] | |
for p in parsed_log: | |
command, item_number = p.items().pop() | |
if command == 'close_ticket': | |
tickets.append(item_number) | |
return pull_requests, tickets | |
def tickets_from_pr(number): | |
"""Use the sprintly API to grab PR info. Only return tickets that are done.""" | |
r = requests.get('%s/products/1/pullrequests/%s.json' % (SPRINTLY_API_BASE, number), | |
auth=(settings.SPRINTLY_EMAIL, settings.SPRINTLY_API_KEY)) | |
tickets = [] | |
# Only return items that are completed or accepted. | |
for item in r.json()['items']: | |
if item['status'] in ['completed', 'accepted']: | |
tickets.append(str(item['number'])) | |
return tickets | |
def mark_items_deployed(tickets, environment, version, travis_build_url): | |
"""Use the sprintly API to mark items as deployed.""" | |
data = { | |
'environment': environment, | |
'numbers': ','.join(tickets), | |
'version': version, | |
'notes': """ | |
Deployed Travis Build [Number %(version)s](%(url)s). | |
""" % {'version': version, 'url': travis_build_url} | |
} | |
requests.post('%s/products/1/deploys.json' % SPRINTLY_API_BASE, | |
auth=(settings.SPRINTLY_EMAIL, settings.SPRINTLY_API_KEY), | |
data=data) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment