Skip to content

Instantly share code, notes, and snippets.

@justinabrahms
Created March 13, 2015 21:55
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save justinabrahms/40c256ce2548da2d6e79 to your computer and use it in GitHub Desktop.
Save justinabrahms/40c256ce2548da2d6e79 to your computer and use it in GitHub Desktop.
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