예제 #1
0
    def _scratch_build(self, session: koji.ClientSession, name: str,
                       source: str) -> int:
        """
        Uploads source RPM and starts scratch build of package in Koji.

        Params:
            session: Koji session to use for starting build.
            name: Name of the package to build
            source: Path to SRPM.

        Returns:
            Build id.
        """
        _logger.info("Uploading {source} to koji".format(source=source))
        suffix = "".join(
            [random.choice(string.ascii_letters) for i in range(8)])
        serverdir = "%s/%r.%s" % ("cli-build", time.time(), suffix)
        session.uploadWrapper(source, serverdir)

        remote = "%s/%s" % (serverdir, os.path.basename(source))
        _logger.info("Intiating koji build for %r" % dict(
            name=name, target=self.target_tag, source=remote, opts=self.opts))
        task_id = session.build(remote,
                                self.target_tag,
                                self.opts,
                                priority=self.priority)
        _logger.info("Scratch build created for {name}: {url}".format(
            name=name,
            url=self.web_url + "/taskinfo?taskID={}".format(task_id)))

        return task_id
예제 #2
0
def list_buildroot(session: koji.ClientSession, nvr: str) -> List[str]:
    build = session.getBuild(nvr, strict=True)

    if build["state"] != koji.BUILD_STATES["COMPLETE"]:
        raise Exception("Build is not yet complete.")

    task = session.listTasks(
        opts={
            "method": "buildArch",
            "parent": build["task_id"],
        },
        queryOpts={"limit": 1}
    )[0]

    buildroot = session.listBuildroots(
        taskID=task["id"],
        queryOpts={"order": "-id", "limit": 1}
    )[0]

    rpms = session.listRPMs(componentBuildrootID=buildroot["id"])

    with session.multicall(strict=True) as multi:
        srpms = [
            multi.listRPMs(
                buildID=rpm['build_id'],
                arches='src',
                queryOpts={'limit': 1}
            )
            for rpm in rpms
            if rpm['name'].startswith('rust-') and rpm['name'].endswith('-devel')
        ]

    nvrs = set(data.result[0]['nvr'] for data in srpms)
    return [*sorted(nvrs)]
예제 #3
0
 def get_koji_builds(self, ) -> Dict:
     """
     Get latest koji builds as a dict of branch: latest build in that branch.
     """
     session = ClientSession(
         baseurl="https://koji.fedoraproject.org/kojihub")
     package_id = session.getPackageID(
         self.dg.package_config.downstream_package_name)
     # This method returns only latest builds,
     # so we don't need to get whole build history from Koji,
     # get just recent year to speed things up.
     since = datetime.now() - timedelta(days=365)
     builds_l = session.listBuilds(
         packageID=package_id,
         state=BUILD_STATES["COMPLETE"],
         completeAfter=since.timestamp(),
     )
     logger.debug(
         f"Recent Koji builds fetched: {[b['nvr'] for b in builds_l]}")
     # Select latest build for each branch.
     # [{'nvr': 'python-ogr-0.5.0-1.fc29'}, {'nvr':'python-ogr-0.6.0-1.fc29'}]
     # -> {'fc29': 'python-ogr-0.6.0-1.fc29'}
     return {
         b["nvr"].rsplit(".", 1)[1]: b["nvr"]
         for b in reversed(builds_l)
     }
예제 #4
0
def cli_filter_tags(session: ClientSession,
                    tag_list: List[Union[int, str]],
                    search: Optional[str] = None,
                    regex: Optional[str] = None,
                    tag_sifter: Optional[Sifter] = None,
                    sorting: Optional[str] = None,
                    outputs: Optional[dict] = None,
                    strict: bool = False):

    if search:
        tag_list.extend(t["id"] for t in session.search(search, "tag", "glob")
                        if t)

    if regex:
        tag_list.extend(t["id"] for t in session.search(regex, "tag", "regex")
                        if t)

    tag_list = unique(map(int_or_str, tag_list))
    loaded = bulk_load_tags(session, tag_list, err=strict)
    tags = tag_dedup(loaded.values())

    if tag_sifter:
        results = tag_sifter(session, tags)
    else:
        results = {"default": list(tags)}

    if sorting == SORT_BY_NAME:
        sortkey = "name"
    elif sorting == SORT_BY_ID:
        sortkey = "id"
    else:
        sortkey = None

    # unsure why
    output_sifted(results, "name", outputs, sort=sortkey)  # type: ignore
예제 #5
0
def gather_affected_targets(session: ClientSession,
                            tagnames: Iterable[TagSpec]) -> List[TargetInfo]:
    """
    Returns the list of target info dicts representing the targets
    which inherit any of the given named tags. That is to say, the
    targets whose build tags are children of the named tags.

    This list allows us to gauge what build configurations would be
    impacted by changes to the given tags.

    :param tagnames: List of tag names

    :raises NoSuchTag: if any of the names do not resolve to a tag
      info

    :since: 1.0
    """

    tags = [as_taginfo(session, t) for t in set(tagnames)]

    ifn = lambda tag: session.getFullInheritance(tag['id'], reverse=True)
    loaded = bulk_load(session, ifn, tags)
    parents = filter(None, loaded.values())

    tagids = set(chain(*((ch['tag_id'] for ch in ti) for ti in parents)))
    tagids.update(tag['id'] for tag in tags)

    tfn = lambda ti: session.getBuildTargets(buildTagID=ti)
    loaded = bulk_load(session, tfn, tagids)
    targets = chain(*filter(None, loaded.values()))

    return list(targets)
예제 #6
0
def as_taginfo(session: ClientSession, tag: TagSpec) -> TagInfo:
    """
    Coerces a tag value into a koji tag info dict.

    If tag is an
     * int, will attempt to load as a tag ID
     * str, will attempt to load as a tag name
     * dict, will presume already a tag info

    :param session: active koji session

    :param tag: value to lookup

    :raises NoSuchTag: if the tag value could not be resolved into a
      tag info dict

    :since: 1.0
    """

    if isinstance(tag, (str, int)):
        if version_check(session, (1, 23)):
            info = session.getTag(tag, blocked=True)
        else:
            info = session.getTag(tag)

    elif isinstance(tag, dict):
        info = tag

    else:
        info = None

    if not info:
        raise NoSuchTag(tag)

    return info
예제 #7
0
def cli_renum_tag(session: ClientSession,
                  tagname: Union[int, str],
                  begin: int = 10,
                  step: int = 10,
                  verbose: bool = False,
                  test: bool = False):

    as_taginfo(session, tagname)

    original = session.getInheritanceData(tagname)
    renumbered = renum_inheritance(original, begin, step)

    if test or verbose:
        print("Renumbering inheritance priorities for", tagname)
        for left, right in zip(original, renumbered):
            name = left['name']
            lp = left['priority']
            rp = right['priority']
            print(f" {lp:>3} -> {rp:>3}  {name}")

    if test:
        print("Changes not committed in test mode.")

    else:
        session.setInheritanceData(tagname, renumbered)
예제 #8
0
def gather_hosts_checkins(
        session: ClientSession,
        arches: Optional[List[str]] = None,
        channel: Optional[str] = None,
        skiplist: Optional[List[str]] = None) -> List[DecoratedHostInfo]:
    """
    Similar to session.listHosts, but results are decorated with a new
    "last_update" entry, which is the timestamp for the host's most
    recent check-in with the hub. This can be used to identify
    builders which are enabled, but no longer responding.

    :param session: an active koji client session

    :param arches: List of architecture names to filter builders by.
        Default, all arches

    :param channel: Channel name to filter builders by. Default,
        builders in any channel.

    :param skiplist: List of glob-style patterns of builders to
        omit. Default, all builders included

    :since: 1.0
    """

    arches = arches or None

    # listHosts only accepts channel filtering by the ID, so let's
    # resolve those. This should also work if channel is already an
    # ID, and should validate that the channel exists.
    if channel:
        chan_data = session.getChannel(channel)
        if chan_data is None:
            raise NoSuchChannel(channel)
        chan_id = chan_data["id"]
    else:
        chan_id = None

    loaded: Iterable[HostInfo]
    loaded = session.listHosts(arches, chan_id, None, True, None, None)
    loaded = filter(None, loaded)

    if skiplist:
        loaded = globfilter(loaded, skiplist, key="name", invert=True)

    # collect a mapping of builder ids to builder info
    bldrs: Dict[int, DecoratedHostInfo]
    bldrs = {b["id"]: cast(DecoratedHostInfo, b) for b in loaded}

    updates = iter_bulk_load(session, session.getLastHostUpdate, bldrs)

    # correlate the update timestamps with the builder info
    for bldr_id, data in updates:
        data = parse_datetime(data, strict=False) if data else None
        bldrs[bldr_id]["last_update"] = data

    return list(bldrs.values())
예제 #9
0
def as_userinfo(session: ClientSession, user: UserSpec) -> UserInfo:
    """
    Resolves user to a userinfo dict.

    If user is a str or int, then getUser will be invoked. If user is
    already a dict, it's presumed to be a userinfo already and it's
    returned unaltered.

    :param session: active koji session

    :param user: Name, ID, or User Info describing a koji user

    :raises NoSuchUser: when user cannot be found

    :since: 1.0
    """

    if isinstance(user, (str, int)):
        session_vars = vars(session)
        new_get_user = session_vars.get("__new_get_user")

        if new_get_user:
            # we've tried the new way and it worked, so keep doing it.
            info = session.getUser(user, False, True)

        elif new_get_user is None:
            # an API incompatibility emerged at some point in Koji's
            # past, so we need to try the new way first and fall back
            # to the older signature if that fails. This happened
            # before Koji hub started reporting its version, so we
            # cannot use the version_check function to gate this.
            try:
                info = session.getUser(user, False, True)
                session_vars["__new_get_user"] = True

            except ParameterError:
                info = session.getUser(user)
                session_vars["__new_get_user"] = False

        else:
            # we've already tried the new way once and it didn't work.
            info = session.getUser(user)

    elif isinstance(user, dict):
        info = user

    else:
        info = None

    if not info:
        raise NoSuchUser(user)

    return info
예제 #10
0
def iter_bulk_load(session: ClientSession,
                   loadfn: Callable[[Any], Any],
                   keys: Iterable[KT],
                   err: bool = True,
                   size: int = 100) -> Iterator[Tuple[KT, Any]]:
    """
    Generic bulk loading generator. Invokes the given loadfn on each
    key in keys using chunking multicalls limited to the specified
    size.

    Yields (key, result) pairs in order.

    If err is True (default) then any faults will raise an exception.
    If err is False, then a None will be substituted as the result for
    the failing key.

    :param session: The koji session

    :param loadfn: The loading function, to be invoked in a multicall
      arrangement. Will be called once with each given key from keys

    :param keys: The sequence of keys to be used to invoke loadfn.

    :param err: Whether to raise any underlying fault returns as
      exceptions. Default, True

    :param size: How many calls to loadfn to chunk up for each
      multicall. Default, 100

    :raises koji.GenericError: if err is True and an issue
      occurrs while invoking the loadfn

    :since: 1.0
    """

    for key_chunk in chunkseq(keys, size):
        session.multicall = True

        for key in key_chunk:
            loadfn(key)

        for key, info in zip(key_chunk, session.multiCall(strict=err)):
            if info:
                if "faultCode" in info:
                    if err:
                        raise convertFault(Fault(**info))  # type: ignore
                    else:
                        yield key, None
                else:
                    yield key, info[0]  # type: ignore
            else:
                yield key, None
예제 #11
0
def as_taskinfo(session: ClientSession, task: TaskSpec) -> TaskInfo:
    """
    Coerces a task value into a koji task info dict.

    If task is an
     * int, will attempt to load as a task ID
     * dict, will presume already a task info

    Note that if this function does attempt to load a task, it will
    request it with the task's request data as well.

    :param session: active koji session

    :param task: value to lookup

    :raises NoSuchTask: if the task value could not be resolved
      into a task info dict

    :since: 1.0
    """

    if isinstance(task, int):
        info = session.getTaskInfo(task, True)
    elif isinstance(task, dict):
        info = task
    else:
        info = None

    if not info:
        raise NoSuchTask(task)

    return info
예제 #12
0
def as_packageinfo(session: ClientSession, pkg: PackageSpec) -> PackageInfo:
    """
    Coerces a host value into a host info dict.

    If pkg is an:
     * int, will attempt to load as a package ID
     * str, will attempt to load as a package name
     * dict, will presume already a package info

    :param session: an active koji client session

    :param pkg: value to lookup

    :raises NoSuchPackage: if the pkg value could not be resolved into
      a package info dict

    :since: 1.1
    """

    if isinstance(pkg, (str, int)):
        info = session.getPackage(pkg)
    elif isinstance(pkg, dict):
        info = pkg
    else:
        info = None

    if not info:
        raise NoSuchPackage(pkg)

    return info
예제 #13
0
def as_hostinfo(session: ClientSession, host: HostSpec) -> HostInfo:
    """
    Coerces a host value into a host info dict.

    If host is an:
     * int, will attempt to load as a host ID
     * str, will attempt to load as a host name
     * dict, will presume already a host info

    :param session: active koji session

    :param host: value to lookup

    :raises NoSuchHost: if the host value could not be resolved
      into a host info dict

    :since: 1.0
    """

    if isinstance(host, (str, int)):
        info = session.getHost(host)
    elif isinstance(host, dict):
        info = host
    else:
        info = None

    if not info:
        raise NoSuchHost(host)

    return info
예제 #14
0
def as_targetinfo(session: ClientSession, target: TargetSpec) -> TargetInfo:
    """
    Coerces a target value into a koji target info dict.

    If target is an
     * int, will attempt to load as a target ID
     * str, will attempt to load as a target name
     * dict, will presume already a target info

    :param session: active koji session

    :param target: value to lookup

    :raises NoSuchTarget: if the target value could not be resolved
      into a target info dict

    :since: 1.0
    """

    if isinstance(target, (str, int)):
        info = session.getBuildTarget(target)
    elif isinstance(target, dict):
        info = target
    else:
        info = None

    if not info:
        raise NoSuchTarget(target)

    return info
예제 #15
0
def as_channelinfo(session: ClientSession,
                   channel: ChannelSpec) -> ChannelInfo:
    """
    Coerces a channel value into a koji channel info dict.

    If channel is an
     * int, will attempt to load as a channel ID
     * str, will attempt to load as a channel name
     * dict, will presume already a channel info

    :param session: an active koji client session

    :param channel: value to lookup

    :raises NoSuchChannel: if the channel value could not be resolved
      into a channel info dict

    :since: 1.1
    """

    if isinstance(channel, (str, int)):
        info = session.getChannel(channel)
    elif isinstance(channel, dict):
        info = channel
    else:
        info = None

    if not info:
        raise NoSuchChannel(channel)

    return info
예제 #16
0
def as_buildinfo(session: ClientSession, build: BuildSpec) -> BuildInfo:
    """
    Coerces a build value into a koji build info dict.

    If build is an
     * int, will attempt to load as a build ID
     * str, will attempt to load as an NVR
     * dict, will presume already a build info

    :param session: active koji session

    :param build: value to lookup

    :raises NoSuchBuild: if the build value could not be resolved
      into a build info dict

    :since: 1.0
    """

    if isinstance(build, (str, int)):
        info = session.getBuild(build)
    elif isinstance(build, dict):
        info = build
    else:
        info = None

    if not info:
        raise NoSuchBuild(build)

    return info
예제 #17
0
def as_rpminfo(session: ClientSession, rpm: RPMSpec) -> RPMInfo:
    """
    Coerces a host value into a RPM info dict.

    If rpm is specified as an:
     * int, will attempt to load as a RPM ID
     * str, will attempt to load as a RPM NVRA
     * dict, will presume already an RPM info

    :param session: active koji session

    :param rpm: value to lookup

    :raises NoSuchRPM: if the rpm value could not be resolved
      into a RPM info dict

    :since: 1.0
    """

    info: RPMInfo

    if isinstance(rpm, (str, int)):
        info = session.getRPM(rpm)  # type: ignore
    elif isinstance(rpm, dict):
        info = rpm
    else:
        info = None

    if not info:
        raise NoSuchRPM(rpm)

    return info
예제 #18
0
    def bulk_list_packages(
            self,
            session: ClientSession,
            tag_ids: Iterable[int],
            inherited: bool = True) -> Dict[int, List[TagPackageInfo]]:
        """
        a multicall caching wrapper for ``session.listPackages``

        shares the same cache as `list_packages` (and therefore
        `allowed_packages` and `blocked_packages`)
        """

        cache = cast(Dict[Tuple[int, bool], List[TagPackageInfo]],
                     self._mixin_cache("list_packages"))

        result: Dict[int, List[TagPackageInfo]] = {}
        needed = []

        for tid in tag_ids:
            if (tid, inherited) not in cache:
                needed.append(tid)
            else:
                result[tid] = cache[(tid, inherited)]

        fn = lambda i: session.listPackages(i, inherited=inherited)
        for tid, pkgs in iter_bulk_load(session, fn, needed):
            result[tid] = cache[(tid, inherited)] = pkgs

        return result
예제 #19
0
파일: brew.py 프로젝트: vfreex/doozer
def list_archives_by_builds(
        build_ids: List[int], build_type: str,
        session: koji.ClientSession) -> List[Optional[List[Dict]]]:
    """ Retrieve information about archives by builds
    :param build_ids: List of build IDs
    :param build_type: build type, such as "image"
    :param session: instance of Brew session
    :return: a list of Koji/Brew archive lists (augmented with "rpms" entries for RPM lists)
    """
    tasks = []
    with session.multicall(strict=True) as m:
        for build_id in build_ids:
            if not build_id:
                tasks.append(None)
                continue
            tasks.append(m.listArchives(buildID=build_id, type=build_type))
    archives_list = [task.result if task else None for task in tasks]

    # each archives record contains an archive per arch; look up RPMs for each
    archives = [ar for rec in archives_list for ar in rec or []]
    archives_rpms = list_image_rpms([ar["id"] for ar in archives], session)
    for archive, rpms in zip(archives, archives_rpms):
        archive["rpms"] = rpms

    return archives_list
예제 #20
0
def gather_latest_maven_archives(
        session: ClientSession,
        tagname: TagSpec,
        inherit: bool = True,
        path: Optional[PathSpec] = None) -> List[DecoratedArchiveInfo]:
    """
    Similar to session.getLatestMavenArchives(tagname) but augments
    the results to include a new "filepath" entry which will point to
    the matching maven artifact's file location.

    :param session: an active koji client session

    :param tagname: Name of the tag to search in for maven artifacts

    :param inherit: Follow tag inheritance, default True

    :raises NoSuchTag: if specified tag doesn't exist
    """

    tag = as_taginfo(session, tagname)
    path = as_pathinfo(path)

    found = session.getLatestMavenArchives(tag['id'], inherit=inherit)
    for f in found:
        # unlike getLatestRPMs, getLatestMavenArchives only provides
        # the archives themselves. We don't want to have to do a bulk
        # load for all those, so we fake a build info from the values
        # in the archive itself. Since we're only using it to
        # determine paths, the missing fields shouldn't be a problem
        bld = _fake_maven_build(f, path)
        d = cast(DecoratedArchiveInfo, f)
        d["filepath"] = join(bld["build_path"], path.mavenfile(f))

    return cast(List[DecoratedArchiveInfo], found)
예제 #21
0
파일: brew.py 프로젝트: vfreex/doozer
def get_tagged_builds(tag_component_tuples: Iterable[Tuple[str,
                                                           Optional[str]]],
                      build_type: Optional[str],
                      event: Optional[int],
                      session: koji.ClientSession,
                      inherit: bool = False) -> List[Optional[List[Dict]]]:
    """ Get tagged builds as of the given event

    In each list for a component, builds are ordered from newest tagged to oldest tagged:
    https://pagure.io/koji/blob/3fed02c8adb93cde614af9f61abd12bbccdd6682/f/hub/kojihub.py#_1392

    :param tag_component_tuples: List of (tag, component_name) tuples
    :param build_type: if given, only retrieve specified build type (rpm, image)
    :param event: Brew event ID, or None for now.
    :param session: instance of Brew session
    :param inherit: True to include builds inherited from parent tags
    :return: a list of lists of Koji/Brew build dicts
    """
    tasks = []
    with session.multicall(strict=True) as m:
        for tag, component_name in tag_component_tuples:
            if not tag:
                tasks.append(None)
                continue
            tasks.append(
                m.listTagged(tag,
                             event=event,
                             package=component_name,
                             type=build_type,
                             inherit=inherit))
    return [task.result if task else None for task in tasks]
예제 #22
0
def collect_cg_access(session: ClientSession,
                      user: UserSpec) -> List[NamedCGInfo]:
    """
    List of content generators user has access to run CGImport with.

    :param session: an active koji client session

    :param user: Name, ID, or userinfo dict

    :raises NoSuchUser: if user is an ID or name which cannot be
      resolved

    :since: 1.0
    """

    userinfo = as_userinfo(session, user)
    username = userinfo["name"]

    found = []
    for cgname, val in session.listCGs().items():
        if username in val.get("users", ()):
            nval = cast(NamedCGInfo, val)
            nval["name"] = cgname
            found.append(nval)
    return found
예제 #23
0
def gather_build_image_archives(
        session: ClientSession,
        binfo: BuildSpec,
        path: Optional[PathSpec] = None) -> List[DecoratedArchiveInfo]:
    """
    Gathers a list of image archives for a given build_info. The
    archive records are augmented with an additional "filepath" entry,
    the value of which is an expanded path to the file itself.

    :param session: an active koji client session

    :param binfo: Build info to fetch archives for

    :param path: The root dir for the archive file paths, default None

    :raises NoSuchBuild: if binfo could not be resolved
    """

    binfo = as_buildinfo(session, binfo)
    bid = binfo["id"]
    path = as_pathinfo(path)

    build_path = path.imagebuild(binfo)
    found = session.listArchives(buildID=bid, type="image")
    for f in found:
        d = cast(DecoratedArchiveInfo, f)
        d["filepath"] = join(build_path, f["filename"])

    return cast(List[DecoratedArchiveInfo], found)
예제 #24
0
def collect_cgs(session: ClientSession,
                name: Optional[str] = None) -> List[NamedCGInfo]:
    """
    :param name: only collect the given CG. Default, collect all

    :raises NoSuchContentGenerator: if name is specified and no
      content generator matches

    :since: 1.0
    """

    cgs = session.listCGs()

    if name:
        # filter the cgs dict down to just the named one
        if name in cgs:
            cgs = {name: cgs[name]}
        else:
            raise NoSuchContentGenerator(name)

    result = []

    # convert the cgs dict into a list, augmenting the cg data with
    # its own name
    for name, cg in cgs.items():
        ncg = cast(NamedCGInfo, cg)
        ncg["name"] = name
        result.append(ncg)

    return result
예제 #25
0
def iter_bulk_tag_builds(
        session: ClientSession,
        tag: TagSpec,
        build_infos: BuildInfos,
        force: bool = False,
        notify: bool = False,
        size: int = 100,
        strict: bool = False) -> Iterator[List[Tuple[BuildInfo, Any]]]:
    """
    Tags a large number of builds using multicall invocations of
    tagBuildBypass. Builds are specified by build info dicts.

    yields lists of tuples containing a build info dict and the result
    of the tagBuildBypass call for that build. This gives the caller a
    chance to record the results of each multicall, and to present
    feedback to a user to indicate that the operations are continuing.

    :param session: an active koji session

    :param tag: Destination tag's name or ID

    :param build_infos: Build infos to be tagged

    :param force: Force tagging. Re-tags if necessary, bypasses
        policy. Default, False

    :param notify: Send tagging notifications. Default, False

    :param size: Count of tagging operations to perform in a single
        multicall. Default, 100

    :param strict: Raise an exception and discontinue execution at the
        first error. Default, False

    :raises NoSuchTag: If tag does not exist
    """

    tag = as_taginfo(session, tag)
    tagid = tag["id"]

    for build_chunk in chunkseq(build_infos, size):
        session.multicall = True
        for build in build_chunk:
            session.tagBuildBypass(tagid, build["id"], force, notify)
        results = session.multiCall(strict=strict)
        yield list(zip(build_chunk, results))
예제 #26
0
def collect_userinfo(session: ClientSession,
                     user: UserSpec) -> DecoratedUserInfo:
    """
    Gather information about a named user, including the list of
    permissions the user has.

    Will convert the older `'krb_principal'` value (koji < 1.19) into
    a `'krb_principals'` list (koji >= 1.19) to provide some level of
    uniformity.

    :param session: an active koji client session

    :param user: name of a user or their kerberos ID

    :raises NoSuchUser: if user is an ID or name which cannot be
      resolved

    :since: 1.0
    """

    userinfo = cast(DecoratedUserInfo, as_userinfo(session, user))

    # depending on koji version, getUser resulted in either a
    # krb_principal or krb_principals entry (or neither if it's not
    # set up for kerberos). Let's normalize on the newer
    # krb_principals one by converting. See
    # https://pagure.io/koji/issue/1629

    if "krb_principal" in userinfo:
        krb = userinfo["krb_principal"]
        userinfo["krb_principals"] = [krb] if krb else []

    uid = userinfo["id"]

    userinfo["permissions"] = session.getUserPerms(uid)
    userinfo["content_generators"] = collect_cg_access(session, userinfo)

    if userinfo.get("usertype", UserType.NORMAL) == UserType.GROUP:
        try:
            userinfo["members"] = session.getGroupMembers(uid)
        except Exception:
            # non-admin accounts cannot query group membership, so omit
            userinfo["members"] = None  # type: ignore

    return userinfo
예제 #27
0
파일: brew.py 프로젝트: Ximinhan/doozer
def list_image_rpms(image_ids: List[int], session: koji.ClientSession) -> List[Optional[List[Dict]]]:
    """ Retrieve RPMs in given images
    :param image_ids: image IDs list
    :param session: instance of Brew session
    :return: a list of Koji/Brew RPM lists
    """
    with session.multicall(strict=True) as m:
        tasks = [m.listRPMs(imageID=image_id) for image_id in image_ids]
    return [task.result for task in tasks]
예제 #28
0
def untag_builds(tag: str, builds: List[str], session: koji.ClientSession):
    tasks = []
    with session.multicall(strict=False) as m:
        for build in builds:
            if not build:
                tasks.append(None)
                continue
            tasks.append(m.untagBuild(tag, build))
    return tasks
예제 #29
0
def ensure_tag(session: ClientSession, name: str) -> TagInfo:
    """
    Given a name, resolve it to a tag info dict. If there is no such
    tag, then create it and return its newly created tag info.

    :param session: active koji session

    :param name: tag name

    :since: 1.0
    """

    try:
        session.createTag(name)
    except GenericError:
        pass

    return as_taginfo(session, name)
예제 #30
0
파일: brew.py 프로젝트: Ximinhan/doozer
def list_build_rpms(build_ids: List[int], session: koji.ClientSession) -> List[Optional[List[Dict]]]:
    """ Retrieve RPMs in given package builds (not images)
    :param build_ids: list of build IDs
    :param session: instance of Brew session
    :return: a list of Koji/Brew RPM lists
    """
    with session.multicall(strict=True) as m:
        tasks = [m.listBuildRPMs(build) for build in build_ids]
    return [task.result for task in tasks]
예제 #31
0
REPO_DIR = '/var/cache/fedoracommunity/git.fedoraproject.org'
TIMESTAMP = '/var/cache/fedoracommunity/git.fedoraproject.org/.timestamp'

# Get a list of active git branches
pkgdb = PackageDB()
collections = pkgdb.get_collection_list(eol=False)
active = [c[0].gitbranchname for c in collections]

# Grab a list of all koji builds since our last run
# if there is no saved timestamp, do a full run
packages = []
if not os.path.exists(TIMESTAMP):
    packages = os.listdir(REPO_DIR)
else:
    timestamp = file(TIMESTAMP).read().strip()
    koji = ClientSession('http://koji.fedoraproject.org/kojihub')
    builds = koji.listBuilds(createdAfter=float(timestamp))
    packages = set([build['name'] for build in builds])
    packages = [pkg for pkg in packages
                if os.path.isdir(os.path.join(REPO_DIR, pkg))]

for repo in packages:
    print("[ %s ]" % repo)
    for branch in os.listdir(os.path.join(REPO_DIR, repo)):
        if branch in active:
            subprocess.call('git pull', shell=True,
                    cwd=os.path.join(REPO_DIR, repo, branch))
        else:
            print("Deleting EOL branch %s" % branch)
            shutil.rmtree(os.path.join(REPO_DIR, repo, branch))