Beispiel #1
0
def ensure_tagged(buildinfo, tags, session, dryrun):
    """
    Ensure this build is tagged into Koji.

    :param dict buildinfo: dict from getBuild with this name/version/release
    :param list tags: list of tags for this build.
    :param session: Koji session
    :param bool dryrun: show what would happen, but don't do it.
    """
    task_ids = []
    nvr = '%(name)s-%(version)s-%(release)s' % buildinfo
    for tag in sorted(tags):
        tagged_builds = session.listTagged(tag,
                                           package=buildinfo['name'],
                                           type='debian')
        tagged_nvrs = [tagged_build['nvr'] for tagged_build in tagged_builds]
        if nvr in tagged_nvrs:
            log.info('%s is already tagged into %s' % (nvr, tag))
            continue
        log.info('tagging %s into %s' % (nvr, tag))
        if dryrun:
            continue
        task_id = session.tagBuild(tag, nvr)
        task_ids.append(task_id)
    if not task_ids:
        # This build is already tagged into all the necessary tags.
        return
    task_result = watch_tasks(session, task_ids, poll_interval=15)
    if task_result != 0 and not dryrun:
        raise RuntimeError('failed to tag build %s' % nvr)
Beispiel #2
0
def main(args):

    # Pre-flight checks
    directory = args.directory
    assert os.path.isdir(directory)

    session = misoctl.session.get_session(args.profile)
    # TODO: verify this session is authorized to import to the debian CG.
    # Needs https://pagure.io/koji/pull-request/1160

    owner = args.owner
    verify_user(owner, session)

    tag = args.tag
    if tag:
        verify_tag(tag, session)

    buildinfo = import_from_directory(directory, session, args.owner,
                                      args.skip_log, args.scm_url, args.dryrun)
    log.info('imported %(name)s-%(version)s-%(release)s' % buildinfo)

    if tag:
        tag_build(buildinfo, tag, session)
    else:
        log.info('not tagging %(name)s-%(version)s-%(release)s' % buildinfo)
Beispiel #3
0
def ensure_uploaded(nvr, chacra_url, rsession, session, owner, scm_template,
                    dryrun):
    """
    Ensure this build is uploaded into Koji.

    :param nvr: build's name_versionrelease in chacra
    :param chacra_url: base url to chacra instance
    :param rsession: requests.Session object
    :param session: Koji session
    :param owner: Koji user name that will own this build
    :param scm_template: format string for this build's scm_url
    :param dryrun: if True, show what would have happened, but don't do it
    """
    koji_nvr = get_koji_nvr(nvr)
    # Check if this build exists in Koji
    buildinfo = session.getBuild(koji_nvr)
    if buildinfo:
        return buildinfo
    if dryrun:
        log.info('would download chacra build %s' % nvr)
        return
    directory = chacra.download_build(nvr, chacra_url, rsession)
    skip_log = True
    (name, version) = chacra.name_version(nvr)
    scm_url = scm_template.format(name=name)
    buildinfo = upload.import_from_directory(directory, session, owner,
                                             skip_log, scm_url, dryrun)
    return buildinfo
Beispiel #4
0
def tag_build(buildinfo, tag, session):
    """ Tag this build in Koji. """
    nvr = '%(name)s-%(version)s-%(release)s' % buildinfo
    log.info('tagging %s into %s' % (nvr, tag))
    task_id = session.tagBuild(tag, nvr)
    task_result = watch_tasks(session, [task_id], poll_interval=15)
    if task_result != 0:
        raise RuntimeError('failed to tag builds')
Beispiel #5
0
def upload(all_files, session):
    """
    Upload all files to a remote directory in Koji.
    """
    remote_directory = unique_path('cli-import')
    log.info('uploading files to %s' % remote_directory)

    for filename in all_files:
        callback = _progress_callback
        log.info("Uploading %s" % filename)
        session.uploadWrapper(filename, remote_directory, callback=callback)
        if callback:
            print('')
    return remote_directory
Beispiel #6
0
def get_session(profile):
    """
    Return an authenticated Koji session
    """
    # Return a cached session, if available.
    mykoji = koji.get_profile_module(profile)
    opts = mykoji.grab_session_options(mykoji.config)
    session = mykoji.ClientSession(mykoji.config.server, opts)
    # Log in ("activate") this sesssion:
    # Note: this can raise SystemExit if there is a problem, eg with Kerberos:
    activate_session(session, mykoji.config)
    assert session.logged_in
    userinfo = session.getLoggedInUser()
    username = userinfo['name']
    log.info('authenticated to %s as %s' % (mykoji.config.server, username))
    return session
Beispiel #7
0
def main(args):
    rsession = requests.Session()
    session = misoctl.session.get_session(args.profile)

    upload.verify_user(args.owner, session)

    nvrs = find_all_nvrs(args.directory)

    sorted_nvrs = sort_nvrs(nvrs.keys())

    for nvr in sorted_nvrs:
        log.info('nvr: "%s"' % nvr)
        buildinfo = ensure_uploaded(nvr, args.chacra_url, rsession, session,
                                    args.owner, args.scm_template, args.dryrun)

        if args.dryrun and not buildinfo:
            # Minimally fake the buildinfo we would have generated above.
            (name, version, release) = chacra.name_version_release(nvr)
            buildinfo = {'name': name, 'version': version, 'release': release}
        tags = nvrs[nvr]
        ensure_tagged(buildinfo, tags, session, args.dryrun)
Beispiel #8
0
def download_build(nvr, base_url, session):
    """
    Download an NVR from chacra to a nvr-named directory.

    :param nvr: build NVR to download, eg ceph-ansible_3.2.0~rc3-2redhat1
    :param base_url: chacra base URL
    :param session: persistent requests.Session() to use for HTTPS requests
    :returns: destination directory for this build
    """
    (pkg, version) = name_version(nvr)
    dest_dir = os.path.join('downloads', nvr)
    ensure_directory(dest_dir)
    build_url = posixpath.join(base_url, 'binaries/', pkg, version, 'ubuntu',
                               'all')
    log.info('searching %s for builds' % build_url)
    build_response = session.get(build_url)
    build_response.raise_for_status()
    payload = build_response.json()
    for arch, binaries in payload.items():
        metadata_url = posixpath.join(build_url, arch)
        metadata_response = session.get(metadata_url)
        metadata_response.raise_for_status()
        metadata = metadata_response.json()
        for binary in binaries:
            output_path = os.path.join(dest_dir, binary)
            if os.path.isfile(output_path):
                checksum = metadata[binary]['checksum']
                if verify_checksum(output_path, checksum):
                    log.info('skipping %s' % binary)
                    continue
                else:
                    log.warning('checksum mismatch on %s' % binary)
            log.info('downloading %s' % binary)
            binary_url = posixpath.join(build_url, arch, binary) + '/'
            r = session.get(binary_url, stream=True)
            r.raise_for_status()
            with open(output_path, 'wb') as f:
                for chunk in r.iter_content(4096):
                    f.write(chunk)
    return dest_dir
Beispiel #9
0
def import_from_directory(directory, session, owner, skip_log, scm_url,
                          dryrun):
    """
    Import the build artifacts in this directory into a Koji CG build.

    :param directory: dir containing the build artifacts, with one dsc file.
    :param session: Koji session.
    :param owner: Koji user to own this imported build.
    :param skip_log: Don't try to import log files for this build.
    :param scm_url: SCM (dist-git) url for this build.
    :param dryrun: show what would be done, but don't do it.
    """
    # Discover our files on disk
    dsc_file = filemanager.find_dsc_file(directory)
    dsc = filemanager.parse_dsc(dsc_file)
    source_files = filemanager.find_source_files(dsc, directory)
    deb_files = filemanager.find_deb_files(directory)
    log_files = set()
    log_file = filemanager.find_log_file(directory, fatal=not skip_log)
    if log_file:
        log_file = rename_log_file(log_file)
        log_files.add(log_file)

    # Bail early if this build already exists
    nvr = '%(Source)s-deb-%(Version)s' % dsc
    if session.getBuild(nvr):
        raise RuntimeError('%s build exists in koji' % nvr)

    # Determine build metadata
    if log_file:
        (start_time, end_time) = filemanager.get_build_times(log_file)
    else:
        # This is not optimial, because the start and end times are the same,
        # so it looks as if the build took zero seconds.
        changes_file = filemanager.find_changes_file(directory)
        changes_time = filemanager.get_changes_time(changes_file)
        start_time = changes_time
        end_time = changes_time
    build = get_build_data(dsc, start_time, end_time, scm_url, owner)

    # Determine buildroot metadata
    buildroots = get_buildroots()

    # Determine output metadata
    dsc_files = set([dsc_file])
    all_files = set.union(dsc_files, source_files, deb_files, log_files)
    output = get_output_data(all_files)

    # Generate the main metdata JSON
    metadata = get_metadata(build, buildroots, output)
    with open('metadata.json', 'w') as f:
        json.dump(metadata, f)
    all_files.add('metadata.json')

    # TODO: check if this build already exists in Koji before uploading here

    if dryrun:
        log.info('dryrun: would upload')
        for filename in all_files:
            log.info(filename)
        return {}
    buildinfo = cg_import(all_files, metadata, session)
    return buildinfo