From 1e7c61c77aa7ced6872eb7671f65549248013afd Mon Sep 17 00:00:00 2001
From: Markus Frosch <markus.frosch@icinga.com>
Date: Fri, 8 Feb 2019 16:08:33 +0100
Subject: [PATCH] upload: Build target, release and repo from environment

CI_JOB_NAME and ICINGA_BUILD_TYPE
---
 icinga-build-upload-aptly | 116 ++++++++++++++++++++++++++++++++++----
 1 file changed, 104 insertions(+), 12 deletions(-)

diff --git a/icinga-build-upload-aptly b/icinga-build-upload-aptly
index a49b491..dc8ecbc 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)
-- 
GitLab