Files
rqlite/package.py
2016-05-21 15:48:36 -07:00

186 lines
5.7 KiB
Python

#!/usr/bin/python
import argparse
import logging
import requests
import json
import subprocess
import sys
import tempfile
URL = 'https://api.github.com/repos/rqlite/rqlite/releases'
def run(command, allow_failure=False, shell=False):
"""
Run shell command (convenience wrapper around subprocess).
"""
out = None
logging.debug("{}".format(command))
try:
if shell:
out = subprocess.check_output(command, stderr=subprocess.STDOUT, shell=shell)
else:
out = subprocess.check_output(command.split(), stderr=subprocess.STDOUT)
out = out.decode('utf-8').strip()
# logging.debug("Command output: {}".format(out))
except subprocess.CalledProcessError as e:
if allow_failure:
logging.warn("Command '{}' failed with error: {}".format(command, e.output))
return None
else:
logging.error("Command '{}' failed with error: {}".format(command, e.output))
sys.exit(1)
except OSError as e:
if allow_failure:
logging.warn("Command '{}' failed with error: {}".format(command, e))
return out
else:
logging.error("Command '{}' failed with error: {}".format(command, e))
sys.exit(1)
else:
return out
def get_system_arch():
"""Retrieve current system architecture.
"""
arch = os.uname()[4]
if arch == "x86_64":
arch = "amd64"
elif arch == "386":
arch = "i386"
elif 'arm' in arch:
# Prevent uname from reporting full ARM arch (eg 'armv7l')
arch = "arm"
return arch
def get_system_platform():
"""Retrieve current system platform.
"""
if sys.platform.startswith("linux"):
return "linux"
else:
return sys.platform
def create_temp_dir(prefix=None):
"""
Create temporary directory with optional prefix.
"""
if prefix is None:
return tempfile.mkdtemp(prefix="{}-build.".format(PACKAGE_NAME))
else:
return tempfile.mkdtemp(prefix=prefix)
def get_current_commit(short=False):
"""Retrieve the current git commit.
"""
command = None
if short:
command = "git log --pretty=format:'%h' -n 1"
else:
command = "git rev-parse HEAD"
out = run(command)
return out.strip('\'\n\r ')
def get_current_branch():
"""Retrieve the current git branch.
"""
command = "git rev-parse --abbrev-ref HEAD"
out = run(command)
return out.strip()
def get_go_version():
"""Retrieve version information for Go.
"""
out = run("go version")
matches = re.search('go version go(\S+)', out)
if matches is not None:
return matches.groups()[0].strip()
return None
def build(version=None,
platform=None,
arch=None,
clean=False,
outdir="."):
"""Build each target for the specified architecture and platform.
"""
logging.info("Starting build for {}/{}...".format(platform, arch))
logging.info("Using Go version: {}".format(get_go_version()))
logging.info("Using git branch: {}".format(get_current_branch()))
logging.info("Using git commit: {}".format(get_current_commit()))
logging.info("Sending build output to: {}".format(outdir))
if not os.path.exists(outdir):
os.makedirs(outdir)
elif clean and outdir != '/' and outdir != ".":
logging.info("Cleaning build directory '{}' before building.".format(outdir))
shutil.rmtree(outdir)
os.makedirs(outdir)
logging.info("Using version '{}' for build.".format(version))
for target, path in targets.items():
logging.info("Building target: {}".format(target))
build_command = ""
# Handle variations in architecture output
if arch == "i386" or arch == "i686":
arch = "386"
build_command += "GOOS={} GOARCH={} ".format(platform, arch)
build_command += "go build -o {} ".format(os.path.join(outdir, target))
build_command += '-ldflags="-X main.version={} -X main.branch={} -X main.commit={}" '.format(version,
get_current_branch(),
get_current_commit())
build_command += path
start_time = datetime.utcnow()
run(build_command, shell=True)
end_time = datetime.utcnow()
logging.info("Time taken: {}s".format((end_time - start_time).total_seconds()))
return True
class Parser(object):
def __init__(self, text):
self.text = text
def parse(self):
self.json = json.loads(self.text)
def release_id(self, tag):
for release in self.json:
if release['tag_name'] == tag:
return release['id']
return None
def upload_url(self, tag):
for release in self.json:
if release['tag_name'] == tag:
return release['upload_url']
return None
def parse_args():
parser = argparse.ArgumentParser(description='Publish a rqlite release to GitHub.')
parser.add_argument('tag', metavar='TAG', type=str,
help='tag in the form "vX.Y.Z"')
parser.add_argument('token', metavar='TOKEN', type=str,
help='GitHub API token')
return parser.parse_args()
def main():
args = parse_args()
r = requests.get(URL)
if r.status_code != 200:
print 'failed to download release information'
sys.exit(1)
p = Parser(r.text)
p.parse()
release_id = p.release_id(args.tag)
if release_id == None:
print 'unable to determine release ID for tag %s' % args.tag
sys.exit(1)
if __name__ == '__main__':
main()