diff --git a/icinga-build-upload-aptly b/icinga-build-upload-aptly index a49b49178db300f459a977e3c9d3d8f092e5d681..dc8ecbc16dd9e424bbd127f3317f4b9f63f0ef40 100755 --- a/icinga-build-upload-aptly +++ b/icinga-build-upload-aptly @@ -11,6 +11,14 @@ import re # internals APTLY_SESSION = None +CI_JOB_NAME = 'CI_JOB_NAME' +CI_JOB_UPLOAD_PREFIX = 'upload/' +ICINGA_BUILD_TYPE = 'ICINGA_BUILD_TYPE' +ICINGA_BUILD_TYPE_DEFAULT = 'release' + +UPLOAD_TYPE_DEB = 'DEB' +UPLOAD_TYPE_RPM = 'RPM' + def scan_dir(path, pattern): found = [] for root, dirs, files in os.walk(path): @@ -65,6 +73,69 @@ def upload_checksum(files): h.update(fh) return (h.hexdigest(), d) +def ci_split_name(): + """ + Split the CI_JOB_NAME into target and release + e.g. upload/debian/stretch -> ['debian', 'stretch'] + or upload/stack/dev/debian/stretch -> ['stack/dev/debian', 'stretch'] + """ + job_name = os.environ.get(CI_JOB_NAME) + if job_name: + match = re.match("^%s(.+)/([^/]+)$" % CI_JOB_UPLOAD_PREFIX, job_name) + if match: + return match.groups() + + return None + +def get_build_type(): + """ + Get ICINGA_BUILD_TYPE from environ + """ + return os.environ.get(ICINGA_BUILD_TYPE, ICINGA_BUILD_TYPE_DEFAULT) + +def ci_release(upload_type, release): + """ + Build the release name from CI_JOB_NAME and ICINGA_BUILD_TYPE + + Examples: + DEB / stretch / release -> icinga-stretch + DEB / stretch / snapshot -> icinga-stretch-snapshots + DEB / stretch / Y -> icinga-stretch-Y + + RPM / 7 / release -> 7/release + RPM / X / Y -> X/Y + """ + build_type = get_build_type() + + if upload_type == UPLOAD_TYPE_DEB: + publish_release = 'icinga-' + release + if build_type != 'release': + publish_release += '-' + build_type + + if build_type == 'snapshot': + publish_release += 's' # snapshots + + return publish_release + elif upload_type == UPLOAD_TYPE_RPM: + return release + '/' + build_type + else: + raise StandardError, "Unknown upload type %s" % upload_type + +def ci_repo(upload_type, target, release): + """ + Build the aptly repo from target, release and ICINGA_BUILD_TYPE (only for DEB) + + Examples: + icinga-debian-stretch-release + icinga-debian-stretch-snapshot + """ + if upload_type != UPLOAD_TYPE_DEB: + raise StandardError, "Repo can only be set on DEB uploads!" + + build_type = get_build_type() + + return 'icinga-%s-%s-%s' % (target, release, build_type) + def aptly_session(): global APTLY_SESSION if APTLY_SESSION is None: @@ -88,9 +159,9 @@ parser.add_argument('--password', help='APTLY API password', default=os.environ.get('APTLY_PASSWORD'), metavar='APTLY_PASSWORD') parser.add_argument('--result', metavar='path', default='build/', help='Build result to upload') -parser.add_argument('--target', metavar='target', required=True, +parser.add_argument('--target', metavar='target', help='Repository to install the package to (e.g. stack/dev/epel or stack/dev/ubuntu)') -parser.add_argument('--release', metavar='release', required=True, +parser.add_argument('--release', metavar='release', help='Version of the repository to install to (e.g. 7 or icinga-xenial)') parser.add_argument('--repo', metavar='repo', help='Specific repository name in aptly') @@ -111,26 +182,39 @@ rpms = detect_rpm(args.result) debs = detect_deb(args.result) files = None if rpms: - type = 'RPM' + type = UPLOAD_TYPE_RPM files = rpms elif debs: - type = 'DEB' + type = UPLOAD_TYPE_DEB files = debs if not files: raise StandardError, 'No packages found in %s' % (args.result) +pair = ci_split_name() + +if not args.target: + if pair: + args.target = pair[0] + else: + raise StandardError, "Could not detect --target from %s, please specify!" % CI_JOB_NAME + +if not args.release: + if pair: + args.release = ci_release(type, pair[1]) + else: + raise StandardError, "Could not detect --release from %s, please specify!" % CI_JOB_NAME + +if not args.repo and type == UPLOAD_TYPE_DEB: + if pair: + args.repo = ci_repo(type, *pair) + else: + raise StandardError, "Could not detect --repo from %s, please specify!" % CI_JOB_NAME + (checksum, checksums) = upload_checksum(files) upload_prefix = re.sub('[/\-_]+', '_', args.target + '_' + args.release) upload_name = '%s_%s' % (upload_prefix, checksum) -# ensure target is absent -r = aptly_session().delete(aptly_url('/files/' + upload_name)) -if r.status_code == requests.codes.ok: - print "Deleted existing upload %s" % (upload_name) -elif r.status_code != requests.codes.not_found: - raise StandardError, 'Unexpected result code: %s' % (r.status_code) - # meta and upload file upload_meta = { 'target': args.target, @@ -139,8 +223,9 @@ upload_meta = { 'checksums': checksums, } -if args.repo: +if args.repo and type == UPLOAD_TYPE_DEB: upload_meta['repo'] = args.repo + if args.architectures: upload_meta['architectures'] = re.split(r'\s*,\s*', args.architectures) @@ -148,6 +233,13 @@ if args.architectures: if 'amd64' in upload_meta['architectures'] and not 'i386' in upload_meta['architectures']: upload_meta['architectures'].append('i386') +# ensure target is absent +r = aptly_session().delete(aptly_url('/files/' + upload_name)) +if r.status_code == requests.codes.ok: + print "Deleted existing upload %s" % (upload_name) +elif r.status_code != requests.codes.not_found: + raise StandardError, 'Unexpected result code: %s' % (r.status_code) + # uploading files upload_url = aptly_url('/files/' + upload_name) print "Uploading %d files to %s" % (len(files), upload_name)