2015-04-06 06:38:01 +00:00
|
|
|
import os
|
|
|
|
import sys
|
|
|
|
import json
|
|
|
|
import re
|
|
|
|
import subprocess
|
|
|
|
import requests
|
|
|
|
|
|
|
|
github_token = os.environ['GITHUB_TOKEN']
|
|
|
|
auth = (github_token, 'x-oauth-basic')
|
2015-11-26 08:34:16 +00:00
|
|
|
repo = 'getredash/redash'
|
2015-04-06 06:38:01 +00:00
|
|
|
|
|
|
|
def _github_request(method, path, params=None, headers={}):
|
|
|
|
if not path.startswith('https://api.github.com'):
|
|
|
|
url = "https://api.github.com/{}".format(path)
|
|
|
|
else:
|
|
|
|
url = path
|
|
|
|
|
|
|
|
if params is not None:
|
|
|
|
params = json.dumps(params)
|
|
|
|
|
|
|
|
response = requests.request(method, url, data=params, auth=auth)
|
|
|
|
return response
|
|
|
|
|
|
|
|
def exception_from_error(message, response):
|
|
|
|
return Exception("({}) {}: {}".format(response.status_code, message, response.json().get('message', '?')))
|
|
|
|
|
|
|
|
def rc_tag_name(version):
|
|
|
|
return "v{}-rc".format(version)
|
|
|
|
|
|
|
|
def get_rc_release(version):
|
|
|
|
tag = rc_tag_name(version)
|
|
|
|
response = _github_request('get', 'repos/{}/releases/tags/{}'.format(repo, tag))
|
|
|
|
|
|
|
|
if response.status_code == 404:
|
|
|
|
return None
|
|
|
|
elif response.status_code == 200:
|
|
|
|
return response.json()
|
|
|
|
|
|
|
|
raise exception_from_error("Unknown error while looking RC release: ", response)
|
|
|
|
|
|
|
|
def create_release(version, commit_sha):
|
|
|
|
tag = rc_tag_name(version)
|
|
|
|
|
|
|
|
params = {
|
|
|
|
'tag_name': tag,
|
|
|
|
'name': "{} - RC".format(version),
|
|
|
|
'target_commitish': commit_sha,
|
|
|
|
'prerelease': True
|
|
|
|
}
|
|
|
|
|
|
|
|
response = _github_request('post', 'repos/{}/releases'.format(repo), params)
|
|
|
|
|
|
|
|
if response.status_code != 201:
|
|
|
|
raise exception_from_error("Failed creating new release", response)
|
|
|
|
|
|
|
|
return response.json()
|
|
|
|
|
|
|
|
def upload_asset(release, filepath):
|
2015-09-20 06:22:41 +00:00
|
|
|
upload_url = release['upload_url'].replace('{?name,label}', '')
|
2015-04-06 06:38:01 +00:00
|
|
|
filename = filepath.split('/')[-1]
|
|
|
|
|
|
|
|
with open(filepath) as file_content:
|
|
|
|
headers = {'Content-Type': 'application/gzip'}
|
|
|
|
response = requests.post(upload_url, file_content, params={'name': filename}, headers=headers, auth=auth, verify=False)
|
|
|
|
|
2016-02-29 09:31:32 +00:00
|
|
|
if response.status_code != 201: # not 200/201/...
|
2015-04-06 06:38:01 +00:00
|
|
|
raise exception_from_error('Failed uploading asset', response)
|
|
|
|
|
|
|
|
return response
|
|
|
|
|
|
|
|
def remove_previous_builds(release):
|
|
|
|
for asset in release['assets']:
|
|
|
|
response = _github_request('delete', asset['url'])
|
|
|
|
if response.status_code != 204:
|
|
|
|
raise exception_from_error("Failed deleting asset", response)
|
|
|
|
|
|
|
|
def get_changelog(commit_sha):
|
|
|
|
latest_release = _github_request('get', 'repos/{}/releases/latest'.format(repo))
|
|
|
|
if latest_release.status_code != 200:
|
|
|
|
raise exception_from_error('Failed getting latest release', latest_release)
|
|
|
|
|
|
|
|
latest_release = latest_release.json()
|
|
|
|
previous_sha = latest_release['target_commitish']
|
|
|
|
|
|
|
|
args = ['git', '--no-pager', 'log', '--merges', '--grep', 'Merge pull request', '--pretty=format:"%h|%s|%b|%p"', '{}...{}'.format(previous_sha, commit_sha)]
|
|
|
|
log = subprocess.check_output(args)
|
|
|
|
changes = ["Changes since {}:".format(latest_release['name'])]
|
|
|
|
|
|
|
|
for line in log.split('\n'):
|
|
|
|
try:
|
|
|
|
sha, subject, body, parents = line[1:-1].split('|')
|
|
|
|
except ValueError:
|
|
|
|
continue
|
|
|
|
|
|
|
|
try:
|
|
|
|
pull_request = re.match("Merge pull request #(\d+)", subject).groups()[0]
|
|
|
|
pull_request = " #{}".format(pull_request)
|
|
|
|
except Exception, ex:
|
|
|
|
pull_request = ""
|
|
|
|
|
|
|
|
author = subprocess.check_output(['git', 'log', '-1', '--pretty=format:"%an"', parents.split(' ')[-1]])[1:-1]
|
|
|
|
|
|
|
|
changes.append("{}{}: {} ({})".format(sha, pull_request, body.strip(), author))
|
|
|
|
|
|
|
|
return "\n".join(changes)
|
|
|
|
|
2015-05-14 06:58:12 +00:00
|
|
|
def update_release_commit_sha(release, commit_sha):
|
|
|
|
params = {
|
|
|
|
'target_commitish': commit_sha,
|
|
|
|
}
|
|
|
|
|
|
|
|
response = _github_request('patch', 'repos/{}/releases/{}'.format(repo, release['id']), params)
|
|
|
|
|
|
|
|
if response.status_code != 200:
|
|
|
|
raise exception_from_error("Failed updating commit sha for existing release", response)
|
|
|
|
|
2015-05-14 07:09:57 +00:00
|
|
|
return response.json()
|
2015-05-14 06:58:12 +00:00
|
|
|
|
2015-04-06 06:38:01 +00:00
|
|
|
def update_release(version, build_filepath, commit_sha):
|
|
|
|
try:
|
2015-05-14 06:58:12 +00:00
|
|
|
release = get_rc_release(version)
|
|
|
|
if release:
|
|
|
|
release = update_release_commit_sha(release, commit_sha)
|
|
|
|
else:
|
|
|
|
release = create_release(version, commit_sha)
|
|
|
|
|
2015-04-06 06:38:01 +00:00
|
|
|
print "Using release id: {}".format(release['id'])
|
|
|
|
|
|
|
|
remove_previous_builds(release)
|
|
|
|
response = upload_asset(release, build_filepath)
|
|
|
|
|
|
|
|
changelog = get_changelog(commit_sha)
|
|
|
|
|
|
|
|
response = _github_request('patch', release['url'], {'body': changelog})
|
|
|
|
if response.status_code != 200:
|
|
|
|
raise exception_from_error("Failed updating release description", response)
|
|
|
|
|
|
|
|
except Exception, ex:
|
|
|
|
print ex
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
commit_sha = sys.argv[1]
|
|
|
|
version = sys.argv[2]
|
|
|
|
filepath = sys.argv[3]
|
|
|
|
|
|
|
|
# TODO: make sure running from git directory & remote = repo
|
|
|
|
update_release(version, filepath, commit_sha)
|