示例#1
0
 async def _started(self, session, build_id):
     build = session.query(Build).filter(Build.id == build_id).first()
     if not build:
         logger.error("build_started: no build found for %d", build_id)
         return
     write_log(build.parent.parent.id, "I: started build %d\n" % build_id)
     await build.set_building()
     session.commit()
示例#2
0
 async def fail():
     write_log(parent_build_id, "E: building source package failed\n")
     write_log_title(build.id,
                     "Done",
                     no_footer_newline=True,
                     no_header_newline=True)
     repo.set_ready()
     await build.set_failed()
     session.commit()
示例#3
0
async def BuildDebSrc(repo_id, repo_path, build_id, ci_version, is_ci, author,
                      email):
    write_log(build_id, "I: getting debian build information\n")
    src_package_name = await get_changelog_attr("Source", repo_path)
    version = await get_changelog_attr("Version", repo_path)
    repo_path = Path(repo_path)

    key = Configuration().debsign_gpg_email
    if not key:
        write_log(build_id, "E: Signing key not defined in configuration\n")
        logger.error("Signing key not defined in configuration")
        return False

    logger.info("%s: creating source package", src_package_name)
    write_log(
        build_id,
        "I: creating source package: %s (%s)\n" % (src_package_name, version))

    async def outh(line):
        line = line.strip()
        if line:
            write_log(build_id, "%s\n" % line)

    if is_ci:
        # in order to publish a sourcepackage for a ci build we need
        # to create a ci changelog with the correct version

        distribution = await get_changelog_attr("Distribution", repo_path)

        env = os.environ.copy()
        env["DEBFULLNAME"] = author
        env["DEBEMAIL"] = email
        dchcmd = "dch -v %s --distribution %s --force-distribution 'CI Build'" % (
            ci_version, distribution)
        version = ci_version

        process = Launchy(shlex.split(dchcmd),
                          outh,
                          outh,
                          cwd=str(repo_path),
                          env=env)
        await process.launch()
        ret = await process.wait()
        if ret != 0:
            logger.error("Error running dch for CI build")
            return False

    cmd = "dpkg-buildpackage -S -d -nc -I.git -pgpg1 -k{}".format(key)
    process = Launchy(shlex.split(cmd), outh, outh, cwd=str(repo_path))
    await process.launch()
    ret = await process.wait()
    if ret != 0:
        write_log(build_id, "E: Error building source package\n")
        logger.error("source packaging failed, dpkg-builpackage returned %d",
                     ret)
        return False

    logger.info("%s (%d): source package v%s created", src_package_name,
                repo_id, version)
    return True
示例#4
0
async def GitClone(build_id, repo_id, task_queue):

    with Session() as session:
        repo = (session.query(SourceRepository).filter(
            SourceRepository.id == repo_id).first())

        build = session.query(Build).filter(Build.id == build_id).first()
        if not build:
            logger.error("BuildProcess: build %d not found", build_id)
            return

        repo.set_busy()
        session.commit()

        write_log_title(build_id, "Clone Respository")
        logger.info("cloning repository '%s' into '%s'", repo.url,
                    str(repo.src_path))
        write_log(build_id, "I: cloning repository '{}'\n".format(repo.url))

        if not repo.path.exists():
            repo.path.mkdir()

        if repo.src_path.exists():
            logger.info("clone task: removing git repo %s", str(repo.src_path))
            shutil.rmtree(str(repo.src_path))

        ret = await run_git(
            "git clone --config http.sslVerify=false {}".format(repo.url),
            str(repo.path), build_id)
        if ret != 0:
            logger.error("error running git clone")
            repo.set_error()
            await build.set_failed()
            session.commit()
            return

        git_commands = ["git config http.sslverify false", "git lfs install"]
        for git_command in git_commands:
            ret = await run_git(git_command, str(repo.src_path), build_id)
            if ret != 0:
                logger.error("error running git command: %s", git_command)
                return

        write_log(build_id, "\n")

        repo.set_ready()
        session.commit()

        args = {"buildlatest": [repo.id, build_id]}
        await task_queue.put(args)
示例#5
0
    async def _src_publish(self, args, session):
        build_id = args[0]
        projectversion_ids = args[1]

        build = session.query(Build).filter(Build.id == build_id).first()
        if not build:
            logger.error("aptly worker: build with id %d not found", build_id)
            return

        await build.set_publishing()
        session.commit()

        ret = False
        try:
            ret = await DebSrcPublish(build.id, build.sourcename,
                                      build.version, projectversion_ids,
                                      build.is_ci)
        except Exception as exc:
            logger.exception(exc)

        if not ret:
            write_log(build.parent.id, "E: publishing source package failed\n")
            write_log_title(build.id,
                            "Done",
                            no_footer_newline=True,
                            no_header_newline=True)
            await build.set_publish_failed()
            session.commit()
            return

        await build.set_successful()
        session.commit()

        write_log_title(build.id,
                        "Done",
                        no_footer_newline=True,
                        no_header_newline=True)

        write_log(build.parent.id, "I: scheduling deb package builds\n")
        # schedule child builds
        childs = session.query(Build).filter(Build.parent_id == build.id).all()
        if not childs:
            logger.error("publishsrc_succeeded no build childs found for %d",
                         build_id)
            write_log(build.parent.id, "E: no deb builds found\n")
            write_log_title(build.parent.id,
                            "Done",
                            no_footer_newline=True,
                            no_header_newline=True)
            await build.parent.set_failed()
            session.commit()
            return False

        for child in childs:
            await child.set_needs_build()
            session.commit()

        # Schedule builds
        args = {"schedule": []}
        await self.task_queue.put(args)
示例#6
0
    async def _failed(self, session, build_id):
        build = session.query(Build).filter(Build.id == build_id).first()
        if not build:
            logger.error("build_failed: no build found for %d", build_id)
            return
        write_log(build.parent.parent.id, "E: build %d failed\n" % build_id)
        await build.set_failed()
        session.commit()

        buildtask = session.query(BuildTask).filter(
            BuildTask.build == build).first()
        session.delete(buildtask)
        session.commit()

        # FIXME: do not remove the logs!
        # src_repo = build.buildconfiguration.sourcerepositories[0]
        # for _file in src_repo.path.glob("*_{}*.*".format(build.version)):
        #    logger.info("removing: %s", _file)
        #    os.remove(str(_file))

        if not build.is_ci:
            send_mail_notification(build)
示例#7
0
 async def outh(line):
     line = line.strip()
     if line:
         write_log(build_id, "%s\n" % line)
示例#8
0
async def ScheduleBuilds():

    logger.info("scheduler: checking for pending builds")

    with Session() as session:

        needed_builds = (session.query(Build).filter(
            Build.buildstate == "needs_build", Build.buildtype == "deb").all())
        for build in needed_builds:
            if not chroot_ready(build, session):
                continue

            repo_id = build.sourcerepository_id
            for projectversion in build.buildconfiguration.projectversions:
                projectversion_id = projectversion.id
                # build.log_state("scheduler: projectversion %d, repo %d needs build" % (projectversion_id, repo_id))

                repo_deps = []
                if build.parent.build_after:
                    for build_after_repo in build.parent.build_after:
                        repo_deps.append(build_after_repo.id)
                else:
                    repo_deps_query = """
                    WITH RECURSIVE getparents(sourcerepository, dependency) AS (
                    SELECT s1.sourcerepository, s1.dependency
                      FROM buildorder s1
                      WHERE s1.sourcerepository = :repo_id
                    UNION ALL
                    SELECT s2.sourcerepository, s2.dependency
                      FROM
                        buildorder s2,
                        getparents s1
                      WHERE s2.sourcerepository = s1.dependency
                    )
                    SELECT * from getparents;
                    """
                    results = session.execute(repo_deps_query,
                                              {"repo_id": repo_id})
                    for row in results:
                        repo_deps.append(row[1])

                if not repo_deps:
                    # build.log_state("scheduler: no build order dependencies, scheduling...")
                    await schedule_build(build, session)
                    break

                pv_deps = get_projectversion_deps(projectversion.id, session)
                projectversion_ids = [projectversion_id]
                # FIXME: no mirrors
                projectversion_ids.extend(pv_deps)

                ready = True
                for dep_repo_id in repo_deps:
                    dep_repo = (session.query(SourceRepository).filter(
                        SourceRepository.id == dep_repo_id).first())
                    if not dep_repo:
                        logger.warning("scheduler: repo %d not found",
                                       dep_repo_id)
                        continue

                    # FIXME: buildconfig arch dependent!

                    # find running builds in the same and dependent projectversions
                    found_running = False
                    for pv_id in projectversion_ids:
                        # build.log_state("scheduler: trying to find running build order dependency in projectversion %d" % pv_id)

                        # check no build order dep is needs_build, building, publishing, ...
                        # FIXME: this needs maybe checking of source packages as well?
                        running_builds = (session.query(Build).join(
                            Build.buildconfiguration).filter(
                                or_(
                                    Build.buildstate == "new",
                                    Build.buildstate == "needs_build",
                                    Build.buildstate == "scheduled",
                                    Build.buildstate == "building",
                                    Build.buildstate == "needs_publish",
                                    Build.buildstate == "publishing",
                                ),
                                Build.buildtype == "deb",
                                Build.sourcerepository_id == dep_repo_id,
                                BuildConfiguration.projectversions.any(
                                    ProjectVersion.id == pv_id),
                            ).all())

                        if running_builds:
                            found_running = True

                            projectversion = (
                                session.query(ProjectVersion).filter(
                                    ProjectVersion.id == pv_id).first())
                            if not projectversion:
                                pvname = "unknown"
                                logger.warning(
                                    "scheduler: projectversion %d not found",
                                    pv_id)
                            else:
                                pvname = projectversion.fullname
                            builds = [str(b.id) for b in running_builds]
                            write_log(
                                build.id,
                                "W: waiting for repo {} to finish builds ({}) in projectversion {}\n"
                                .format(dep_repo.name, ", ".join(builds),
                                        pvname))
                            break

                    if found_running:
                        ready = False
                        break

                    # find successful builds in the same and dependent projectversions
                    found = False
                    for pv_id in projectversion_ids:
                        successful_builds = (session.query(Build).join(
                            Build.buildconfiguration).filter(
                                Build.buildstate == "successful",
                                Build.buildtype == "deb",
                                Build.sourcerepository_id == dep_repo_id,
                                BuildConfiguration.projectversions.any(
                                    ProjectVersion.id == pv_id),
                            ).all())

                        if successful_builds:
                            found = True
                            break
                    if not found:
                        ready = False
                        projectversion = (session.query(ProjectVersion).filter(
                            ProjectVersion.id == pv_id).first())
                        if not projectversion:
                            pvname = "unknown"
                            logger.warning(
                                "scheduler: projectversion %d not found",
                                pv_id)
                        else:
                            pvname = projectversion.fullname

                        write_log(
                            build.id,
                            "W: waiting for repo {} to be built in projectversion {}\n"
                            .format(dep_repo.name, pvname))
                        break

                if ready:
                    # build.log_state("scheduler: found all required build order dependencies, scheduling...")
                    await schedule_build(build, session)
示例#9
0
async def BuildProcess(task_queue, aptly_queue, parent_build_id, repo_id,
                       git_ref, ci_branch):
    with Session() as session:
        parent = session.query(Build).filter(
            Build.id == parent_build_id).first()
        if not parent:
            logger.error("BuildProcess: parent build {} not found".format(
                parent_build_id))
            return

        write_log_title(parent_build_id, "Molior Build")

        repo = session.query(SourceRepository).filter(
            SourceRepository.id == repo_id).first()
        if not repo:
            logger.error("source repository %d not found", repo_id)
            write_log(parent_build_id,
                      "E: source repository {} not found\n".format(repo_id))
            write_log_title(parent_build_id,
                            "Done",
                            no_footer_newline=True,
                            no_header_newline=False)
            await parent.set_failed()
            session.commit()
            return

        write_log(parent_build_id, "I: git checkout {}\n".format(git_ref))

        # Checkout
        ret = await asyncio.ensure_future(
            GitCheckout(repo.src_path, git_ref, parent_build_id))
        if not ret:
            write_log(parent_build_id, "E: git checkout failed\n")
            write_log_title(parent_build_id,
                            "Done",
                            no_footer_newline=True,
                            no_header_newline=False)
            await parent.set_failed()
            repo.set_ready()
            session.commit()
            return

        write_log(parent_build_id, "\nI: get build information\n")
        info = None
        try:
            info = await GetBuildInfo(repo.src_path, git_ref)
        except Exception as exc:
            logger.exception(exc)

        if not info:
            write_log(parent_build_id, "E: Error getting build information\n")
            write_log_title(parent_build_id,
                            "Done",
                            no_footer_newline=True,
                            no_header_newline=False)
            await parent.set_failed()
            repo.set_ready()
            session.commit()
            return

        targets = get_targets(info.plain_targets, repo, session)
        if not targets:
            repo.log_state(
                "unknown target projectversions in debian/molior.yml")
            write_log(
                parent_build_id,
                "E: the repository is not added to any projectversions referenced in debian/molior.yml\n"
            )
            write_log_title(parent_build_id,
                            "Done",
                            no_footer_newline=True,
                            no_header_newline=False)
            repo.set_ready()
            await parent.set_failed()
            session.commit()
            return

        # check if it is a CI build
        # i.e. if gittag does not match version in debian/changelog
        is_ci = False
        gittag = ""

        async def outh(line):
            nonlocal gittag
            gittag += line

        process = Launchy(shlex.split("git describe --tags --abbrev=40"),
                          outh,
                          outh,
                          cwd=str(repo.src_path))
        await process.launch()
        ret = await process.wait()
        if ret != 0:
            logger.error("error running git describe")
        else:
            v = strip_epoch_version(info.version)
            if not re.match("^v?{}$".format(v.replace("~", "-")), gittag):
                is_ci = True

        ci_cfg = Configuration().ci_builds
        ci_enabled = ci_cfg.get("enabled") if ci_cfg else False

        if is_ci and not ci_enabled:
            repo.log_state("CI builds are not enabled in configuration")
            write_log(parent_build_id,
                      "E: CI builds are not enabled in configuration\n")
            write_log_title(parent_build_id,
                            "Done",
                            no_footer_newline=True,
                            no_header_newline=False)
            await parent.set_successful()
            repo.set_ready()
            session.commit()
            return

        parent.is_ci = is_ci
        session.commit()

        if is_ci:
            # create CI version with git hash suffix
            info.origversion = info.version
            if is_ci:
                info.version += "+git{}.{}".format(
                    info.tag_dt.strftime("%Y%m%d%H%M%S"), git_ref[:6])

            # check if CI builds enabled in any project version
            found = False
            for target in targets:
                projectversion = session.query(ProjectVersion).filter(
                    ProjectVersion.ci_builds_enabled == True,  # noqa: E712
                    ProjectVersion.id == target.projectversion_id).first()
                if projectversion:
                    found = True
                    break
            if not found:
                repo.log_state(
                    "CI builds not enabled in specified projectversions, not building..."
                )
                write_log(
                    parent_build_id,
                    "E: CI builds not enabled in specified projectversions, not building...\n"
                )
                write_log_title(parent_build_id,
                                "Done",
                                no_footer_newline=True,
                                no_header_newline=False)
                await parent.set_successful()
                repo.set_ready()
                session.commit()
                return

        # Check if source build already exists
        build = session.query(Build).filter(
            Build.buildtype == "source", Build.sourcerepository == repo,
            Build.version == info.version).first()
        if build:
            repo.log_state(
                "source package already built for version {}".format(
                    info.version))
            write_log(
                parent_build_id,
                "E: source package already built for version {}\n".format(
                    info.version))
            write_log_title(parent_build_id,
                            "Done",
                            no_footer_newline=True,
                            no_header_newline=False)
            repo.set_ready()
            await parent.set_successful()
            session.commit()
            args = {"schedule": []}
            await task_queue.put(args)
            return

        # Use commiter name as maintainer for CI builds
        if is_ci:
            t = info.author_name.split(" ", 2)
            if len(t) == 2:
                firstname = t[0]
                lastname = t[1]
            else:
                firstname = t[0]
                lastname = ""
            email = info.author_email
        else:
            firstname = info.firstname
            lastname = info.lastname
            email = info.email

        maintainer = session.query(Maintainer).filter(
            Maintainer.email == email).first()
        if not maintainer:
            repo.log_state("creating new maintainer: %s %s <%s>" %
                           (firstname, lastname, email))
            write_log(
                parent_build_id, "I: creating new maintainer: %s %s <%s>\n" %
                (firstname, lastname, email))
            maintainer = Maintainer(firstname=firstname,
                                    surname=lastname,
                                    email=email)
            session.add(maintainer)
            session.commit()

        # FIXME: assert version == git tag

        build = Build(
            version=info.version,
            git_ref=info.commit_hash,
            ci_branch=ci_branch,
            is_ci=is_ci,
            versiontimestamp=info.tag_stamp,
            sourcename=info.sourcename,
            buildstate="new",
            buildtype="source",
            buildconfiguration=None,
            parent_id=parent_build_id,
            sourcerepository=repo,
            maintainer=maintainer,
        )

        session.add(build)
        session.commit()
        build.log_state("created")
        await build_added(build)

        # add build order dependencies
        build_after = get_buildorder(repo.src_path)
        build_after_deps = []
        found = False
        for dep_git in build_after:
            dep_repo = session.query(SourceRepository).filter(
                SourceRepository.url == dep_git).first()
            if not dep_repo:
                build.log_state("Error: build after repo '%s' not found" %
                                dep_git)
                write_log(parent_build_id,
                          "E: build after repo '%s' not found\n" % dep_git)
                # FIXME: write to build log
                continue
            found = True
            build.log_state("adding build after dependency to: %s" % dep_git)
            write_log(parent_build_id,
                      "I: adding build after dependency to: %s\n" % dep_git)
            build_after_deps.append(dep_repo)

        if found:
            build.build_after = build_after_deps
            session.commit()

        projectversion_ids = []
        build_configs = get_buildconfigs(targets, session)
        found = False
        for build_config in build_configs:
            projectversion_ids.extend([
                projectversion.id
                for projectversion in build_config.projectversions
            ])
            # FIXME: filter for buildtype?
            deb_build = (session.query(Build).filter(
                Build.buildconfiguration == build_config,
                Build.versiontimestamp == info.tag_stamp,
                Build.version == info.version,
            ).first())
            if deb_build:
                logger.warning("already built %s", repo.name)
                write_log(parent_build_id,
                          "E: already built {}\n".format(repo.name))
                continue

            # FIXME: why projectversion[0] ??
            if build_config.projectversions[0].is_locked:
                repo.log_state(
                    "build to locked projectversion '%s-%s' not permitted" % (
                        build_config.projectversions[0].project.name,
                        build_config.projectversions[0].name,
                    ))
                write_log(
                    parent_build_id,
                    "W: build to locked projectversion '%s-%s' not permitted\n"
                    % (
                        build_config.projectversions[0].project.name,
                        build_config.projectversions[0].name,
                    ))
                continue

            if is_ci and not build_config.projectversions[0].ci_builds_enabled:
                repo.log_state(
                    "CI builds not enabled in projectversion '%s-%s'" % (
                        build_config.projectversions[0].project.name,
                        build_config.projectversions[0].name,
                    ))
                write_log(
                    parent_build_id,
                    "W: CI builds not enabled in projectversion '%s-%s'\n" % (
                        build_config.projectversions[0].project.name,
                        build_config.projectversions[0].name,
                    ))
                continue

            found = True

            write_log(
                parent_build_id,
                "I: creating build for projectversion '%s/%s'\n" % (
                    build_config.projectversions[0].project.name,
                    build_config.projectversions[0].name,
                ))

            deb_build = Build(
                version=info.version,
                git_ref=info.commit_hash,
                ci_branch=ci_branch,
                is_ci=is_ci,
                versiontimestamp=info.tag_stamp,
                sourcename=info.sourcename,
                buildstate="new",
                buildtype="deb",
                buildconfiguration=build_config,
                parent_id=build.id,
                sourcerepository=repo,
                maintainer=maintainer,
            )

            session.add(deb_build)
            session.commit()

            deb_build.log_state("created")
            await build_added(deb_build)

        # FIXME: if not found, abort?

        session.commit()

        # make list unique, filter duplicates (multiple archs)
        projectversion_ids = list(set(projectversion_ids))

        await build.set_building()
        session.commit()

        write_log(parent_build_id, "I: building source package\n")

        async def fail():
            write_log(parent_build_id, "E: building source package failed\n")
            write_log_title(build.id,
                            "Done",
                            no_footer_newline=True,
                            no_header_newline=True)
            repo.set_ready()
            await build.set_failed()
            session.commit()
            # FIXME: cancel deb builds, or only create deb builds after source build ok

        # Build Source Package
        write_log_title(build.id, "Source Build")
        try:
            ret = await BuildDebSrc(repo_id, repo.src_path, build.id,
                                    info.version, is_ci,
                                    "{} {}".format(firstname, lastname), email)
        except Exception as exc:
            logger.exception(exc)
            await fail()
            return

        if not ret:
            await fail()
            return

        await build.set_needs_publish()
        session.commit()

        repo.set_ready()
        session.commit()

        write_log(parent_build_id, "I: publishing source package\n")
        await aptly_queue.put({"src_publish": [build.id, projectversion_ids]})
示例#10
0
    async def _buildlatest(self, args, session):
        logger.debug("worker: got buildlatest task")
        repo_id = args[0]
        build_id = args[1]

        build = session.query(Build).filter(Build.id == build_id).first()
        if not build:
            logger.error("rebuild: build %d not found", build_id)
            return

        repo = (session.query(SourceRepository).filter(
            SourceRepository.id == repo_id).first())
        if not repo:
            logger.error("buildlatest: repo %d not found", repo_id)
            return
        if repo.state != "ready":
            await self.task_queue.put({"buildlatest": args})
            logger.info("worker: repo %d not ready, requeueing", repo_id)
            await asyncio.sleep(2)
            return

        await build.set_building()
        repo.set_busy()
        session.commit()  # pylint: disable=no-member

        write_log_title(build.id, "Checking Repository")

        write_log(build.id, "I: fetching git tags\n")
        try:
            # this does a git fetch
            latest_tag = await get_latest_tag(repo.src_path, build_id)
        except Exception as exc:
            logger.error("worker: error getting latest git tag")
            write_log(build.id, "E: Error getting git tags\n")
            write_log_title(build.id,
                            "Done",
                            no_footer_newline=True,
                            no_header_newline=False)
            logger.exception(exc)
            await build.set_failed()
            repo.set_ready()
            session.commit()  # pylint: disable=no-member
            return

        repo.set_ready()
        session.commit()  # pylint: disable=no-member

        if not latest_tag:
            logger.error("sourcerepository '%s' has no release tag", repo.url)
            write_log(build.id, "E: no git tags found\n")
            write_log_title(build.id,
                            "Done",
                            no_footer_newline=True,
                            no_header_newline=False)
            await build.set_failed()
            session.commit()  # pylint: disable=no-member
            return

        write_log(build.id, "\n")
        git_ref = str(latest_tag)
        args = {"build": [build_id, repo_id, git_ref, None]}
        await self.task_queue.put(args)
示例#11
0
 async def outh(line):
     write_log(build_id, "%s\n" % line)
示例#12
0
    async def _update_mirror(self, args, session):
        build_id = args[0]
        mirror_id = args[1]
        base_mirror = args[2]
        base_mirror_version = args[3]
        mirror_name = args[4]
        mirror_version = args[5]
        components = args[6]

        write_log(build_id, "I: updating mirror\n")

        mirror = session.query(ProjectVersion).filter(
            ProjectVersion.id == mirror_id).first()
        if not mirror:
            write_log(
                build_id,
                "E: aptly worker: mirror with id %d not found\n" % mirror_id)
            logger.error("aptly worker: mirror with id %d not found",
                         mirror_id)
            return

        build = session.query(Build).filter(
            Build.projectversion_id == mirror_id
            and Build.buildtype == "mirror").first()
        if not build:
            write_log(
                build_id,
                "E: aptly worker: no build found for mirror with id %d\n" %
                str(mirror_id))
            logger.error("aptly worker: no build found for mirror with id %d",
                         str(mirror_id))
            return

        await build.set_building()
        session.commit()

        try:
            await update_mirror(
                self.task_queue,
                build_id,
                base_mirror,
                base_mirror_version,
                mirror_name,
                mirror_version,
                components,
            )
        except NotFoundError as exc:
            write_log(build_id,
                      "E: aptly seems to be not available: %s\n" % str(exc))
            logger.error("aptly seems to be not available: %s", str(exc))
            # FIXME: remove from db
            await build.set_failed()
            session.commit()
            return
        except AptlyError as exc:
            write_log(
                build_id, "E: failed to update mirror %s on aptly: %s\n" %
                (mirror_name, str(exc)))
            logger.error("failed to update mirror %s on aptly: %s",
                         mirror_name, str(exc))
            # FIXME: remove from db
            await build.set_failed()
            session.commit()
            return

        mirror.mirror_state = "updating"
        session.commit()  # pylint: disable=no-member
示例#13
0
    async def _create_mirror(self, args, session):
        (
            mirror,
            url,
            mirror_distribution,
            components,
            keys,
            keyserver,
            is_basemirror,
            architectures,
            version,
            key_url,
            basemirror_id,
            download_sources,
            download_installer,
        ) = args

        build = Build(
            version=version,
            git_ref=None,
            ci_branch=None,
            is_ci=False,
            versiontimestamp=None,
            sourcename=mirror,
            buildstate="new",
            buildtype="mirror",
            buildconfiguration=None,
            sourcerepository=None,
            maintainer=None,
        )

        build.log_state("created")
        session.add(build)
        await build_added(build)
        session.commit()

        write_log_title(build.id, "Create Mirror")

        mirror_project = (
            session.query(Project)  # pylint: disable=no-member
            .filter(Project.name == mirror,
                    Project.is_mirror.is_(True)).first())
        if not mirror_project:
            mirror_project = Project(name=mirror,
                                     is_mirror=True,
                                     is_basemirror=is_basemirror)
            session.add(mirror_project)  # pylint: disable=no-member

        project_version = (
            session.query(ProjectVersion).join(Project).filter(  # pylint: disable=no-member
                Project.name == mirror, Project.is_mirror.is_(True)).filter(
                    ProjectVersion.name == version).first())

        if project_version:
            write_log(
                build.id,
                "W: mirror with name '%s' and version '%s' already exists\n" %
                (mirror, version))
            logger.error(
                "mirror with name '%s' and version '%s' already exists",
                mirror, version)
            await build.set_successful()
            session.commit()
            return True

        base_mirror = None
        base_mirror_version = None
        db_buildvariant = None
        if not is_basemirror:
            db_basemirror = (
                session.query(ProjectVersion)  # pylint: disable=no-member
                .filter(ProjectVersion.id == basemirror_id).first())
            if not db_basemirror:
                write_log(
                    build.id, "E: could not find a basemirror with id '%d'\n" %
                    basemirror_id)
                logger.error("could not find a basemirror with id '%d'",
                             basemirror_id)
                await build.set_failed()
                session.commit()
                return False

            base_mirror = db_basemirror.project.name
            base_mirror_version = db_basemirror.name
            db_buildvariant = (
                session.query(BuildVariant)  # pylint: disable=no-member
                .filter(BuildVariant.base_mirror_id == basemirror_id).first())

            if not db_buildvariant:
                write_log(
                    build.id,
                    "E: could not find a buildvariant for basemirror with id '%d'\n"
                    % db_basemirror.id)
                logger.error(
                    "could not find a buildvariant for basemirror with id '%d'",
                    db_basemirror.id)
                await build.set_failed()
                session.commit()
                return False

        mirror_project_version = ProjectVersion(
            name=version,
            project=mirror_project,
            mirror_url=url,
            mirror_distribution=mirror_distribution,
            mirror_components=",".join(components),
            mirror_architectures="{" + ",".join(architectures) + "}",
            mirror_with_sources=download_sources,
            mirror_with_installer=download_installer,
        )

        if db_buildvariant:
            mirror_project_version.buildvariants.append(db_buildvariant)

        session.add(mirror_project_version)
        session.commit()

        build.projectversion_id = mirror_project_version.id
        session.commit()

        write_log(build.id, "I: adding GPG keys\n")

        apt = get_aptly_connection()
        if key_url:
            try:
                await apt.gpg_add_key(key_url=key_url)
            except AptlyError as exc:
                write_log(build.id,
                          "E: Error adding keys from '%s'\n" % key_url)
                logger.error("key error: %s", exc)
                await build.set_failed()
                return False
        elif keyserver and keys:
            try:
                await apt.gpg_add_key(key_server=keyserver, keys=keys)
            except AptlyError as exc:
                write_log(build.id, "E: Error adding keys %s\n" % str(keys))
                logger.error("key error: %s", exc)
                await build.set_failed()
                return False

        write_log(build.id, "I: creating mirror\n")
        try:
            await apt.mirror_create(
                mirror,
                version,
                base_mirror,
                base_mirror_version,
                url,
                mirror_distribution,
                components,
                architectures,
                download_sources=download_sources,
                download_udebs=download_installer,
                download_installer=download_installer,
            )

        except NotFoundError as exc:
            write_log(build.id,
                      "E: aptly seems to be not available: %s\n" % str(exc))
            logger.error("aptly seems to be not available: %s", str(exc))
            await build.set_failed()
            return False

        except AptlyError as exc:
            write_log(
                build.id, "E: failed to create mirror %s on aptly: %s\n" %
                (mirror, str(exc)))
            logger.error("failed to create mirror %s on aptly: %s", mirror,
                         str(exc))
            await build.set_failed()
            return False

        args = {
            "update_mirror": [
                build.id, mirror_project_version.id, base_mirror,
                base_mirror_version, mirror, version, components
            ]
        }
        await self.aptly_queue.put(args)
示例#14
0
async def create_schroot(task_queue, chroot_id, build_id, dist, name, version,
                         arch):
    """
    Creates a sbuild chroot and other build environments.

    Args:
        dist (str): The distrelease
        version (str): The version
        arch (str): The architecture

    Returns:
        bool: True on success
    """

    with Session() as session:
        build = session.query(Build).filter(Build.id == build_id).first()
        if not build:
            logger.error("aptly worker: mirror build with id %d not found",
                         build_id)
            return False

        write_log_title(build_id, "Chroot Environment")

        await build.set_building()
        session.commit()

        logger.info("creating build environments for %s-%s-%s", dist, version,
                    arch)
        write_log(
            build_id, "Creating build environments for %s-%s-%s\n\n" %
            (dist, version, arch))

        async def outh(line):
            write_log(build_id, "%s\n" % line)

        process = Launchy([
            "sudo", "run-parts", "-a", "build", "-a", dist, "-a", name, "-a",
            version, "-a", arch, "/etc/molior/mirror-hooks.d"
        ], outh, outh)
        await process.launch()
        ret = await process.wait()

        if not ret == 0:
            logger.error("error creating build env")
            write_log(build_id, "Error creating build environment\n")
            write_log_title(build_id, "Done", no_footer_newline=True)
            await build.set_failed()
            session.commit()
            return False

        await build.set_needs_publish()
        session.commit()

        await build.set_publishing()
        session.commit()

        process = Launchy([
            "sudo", "run-parts", "-a", "publish", "-a", dist, "-a", name, "-a",
            version, "-a", arch, "/etc/molior/mirror-hooks.d"
        ], outh, outh)
        await process.launch()
        ret = await process.wait()

        if not ret == 0:
            logger.error("error publishing build env")
            write_log(build_id, "Error publishing build environment\n")
            write_log_title(build_id, "Done", no_footer_newline=True)
            await build.set_publish_failed()
            session.commit()
            return False

        write_log(build_id, "\n")
        write_log_title(build_id, "Done", no_footer_newline=True)
        await build.set_successful()
        session.commit()

        chroot = session.query(Chroot).filter(Chroot.id == chroot_id).first()
        chroot.ready = True
        session.commit()

        # Schedule builds
        args = {"schedule": []}
        await task_queue.put(args)

        return True
示例#15
0
async def finalize_mirror(task_queue, build_id, base_mirror,
                          base_mirror_version, mirror, version, components,
                          task_id):
    """
    """
    try:
        mirrorname = "{}-{}".format(mirror, version)
        logger.info("finalizing mirror %s task %d, build_%d", mirrorname,
                    task_id, build_id)

        with Session() as session:

            # FIXME: get entry from build.projectversion_id
            query = session.query(ProjectVersion)  # pylint: disable=no-member
            query = query.join(Project,
                               Project.id == ProjectVersion.project_id)
            query = query.filter(Project.is_mirror.is_(True))
            query = query.filter(ProjectVersion.name == version)
            entry = query.filter(Project.name == mirror).first()

            if not entry:
                logger.error("finalize mirror: mirror '%s' not found",
                             mirrorname)
                return

            build = session.query(Build).filter(Build.id == build_id).first()
            if not build:
                logger.error("aptly worker: mirror build with id %d not found",
                             build_id)
                return

            apt = get_aptly_connection()

            if entry.mirror_state == "updating":
                while True:
                    try:
                        upd_progress = await apt.mirror_get_progress(task_id)
                    except Exception as exc:
                        logger.error(
                            "update mirror %s get progress exception: %s",
                            mirrorname, exc)
                        entry.mirror_state = "error"
                        await build.set_failed()
                        session.commit()  # pylint: disable=no-member
                        return

                    # 0: init, 1: running, 2: success, 3: failed
                    if upd_progress["State"] == 2:
                        break

                    if upd_progress["State"] == 3:
                        logger.error("update mirror %s progress error",
                                     mirrorname)
                        entry.mirror_state = "error"
                        await build.set_failed()
                        session.commit()  # pylint: disable=no-member
                        return

                    logger.info(
                        "mirrored %d/%d files (%.02f%%), %.02f/%.02fGB (%.02f%%)",
                        upd_progress["TotalNumberOfPackages"] -
                        upd_progress["RemainingNumberOfPackages"],
                        upd_progress["TotalNumberOfPackages"],
                        upd_progress["PercentPackages"],
                        (upd_progress["TotalDownloadSize"] -
                         upd_progress["RemainingDownloadSize"]) / 1024.0 /
                        1024.0 / 1024.0,
                        upd_progress["TotalDownloadSize"] / 1024.0 / 1024.0 /
                        1024.0,
                        upd_progress["PercentSize"],
                    )

                    await asyncio.sleep(2)

                await apt.delete_task(task_id)

                write_log(build.id, "I: creating snapshot\n")

                await build.set_publishing()
                session.commit()

                # snapshot after initial download
                logger.info("creating snapshot for: %s", mirrorname)
                try:
                    task_id = await apt.mirror_snapshot(
                        base_mirror, base_mirror_version, mirror, version)
                except AptlyError as exc:
                    logger.error("error creating mirror %s snapshot: %s",
                                 mirrorname, exc)
                    entry.mirror_state = "error"
                    await build.set_publish_failed()
                    session.commit()  # pylint: disable=no-member
                    return

                while True:
                    try:
                        task_state = await apt.get_task_state(task_id)
                    except Exception:
                        logger.exception("error getting mirror %s state",
                                         mirrorname)
                        entry.mirror_state = "error"
                        await build.set_publish_failed()
                        session.commit()  # pylint: disable=no-member
                        return
                    # States:
                    # 0: init, 1: running, 2: success, 3: failed
                    if task_state["State"] == 2:
                        break
                    if task_state["State"] == 3:
                        logger.error("creating mirror %s snapshot failed",
                                     mirrorname)
                        entry.mirror_state = "error"
                        await build.set_publish_failed()
                        session.commit()  # pylint: disable=no-member
                        return

                    # FIMXE: why sleep ?
                    await asyncio.sleep(2)

                await apt.delete_task(task_id)

                entry.mirror_state = "publishing"
                session.commit()  # pylint: disable=no-member

                # publish new snapshot
                write_log(build.id, "I: publishing mirror\n")
                logger.info("publishing snapshot: %s", mirrorname)
                try:
                    task_id = await apt.mirror_publish(
                        base_mirror, base_mirror_version, mirror, version,
                        entry.mirror_distribution, components)
                except Exception as exc:
                    logger.error("error publishing mirror %s snapshot: %s",
                                 mirrorname, str(exc))
                    entry.mirror_state = "error"
                    await build.set_publish_failed()
                    session.commit()  # pylint: disable=no-member
                    await apt.mirror_snapshot_delete(base_mirror,
                                                     base_mirror_version,
                                                     mirror, version)
                    return

            if entry.mirror_state == "publishing":
                while True:
                    try:
                        upd_progress = await apt.mirror_get_progress(task_id)
                    except Exception as exc:
                        logger.error("error publishing mirror %s: %s",
                                     mirrorname, str(exc))

                        entry.mirror_state = "error"
                        await build.set_publish_failed()
                        session.commit()  # pylint: disable=no-member

                        await apt.mirror_snapshot_delete(
                            base_mirror, base_mirror_version, mirror, version)
                        return

                    # States:
                    # 0: init, 1: running, 2: success, 3: failed
                    if upd_progress["State"] == 2:
                        break
                    if upd_progress["State"] == 3:
                        logger.error("error publishing mirror %s snapshot",
                                     mirrorname)
                        entry.mirror_state = "error"
                        await build.set_publish_failed()
                        session.commit()  # pylint: disable=no-member
                        await apt.mirror_snapshot_delete(
                            base_mirror, base_mirror_version, mirror, version)
                        return

                    logger.info(
                        "published %d/%d packages (%.02f%%)",
                        upd_progress["TotalNumberOfPackages"] -
                        upd_progress["RemainingNumberOfPackages"],
                        upd_progress["TotalNumberOfPackages"],
                        upd_progress["PercentPackages"],
                    )

                    await asyncio.sleep(2)

            if entry.project.is_basemirror:
                for arch_name in entry.mirror_architectures[1:-1].split(","):
                    arch = (session.query(Architecture).filter(
                        Architecture.name == arch_name).first())  # pylint: disable=no-member
                    if not arch:
                        await build.set_publish_failed()
                        logger.error(
                            "finalize mirror: architecture '%s' not found",
                            arch_name)
                        return

                    buildvariant = BuildVariant(base_mirror=entry,
                                                architecture=arch)
                    session.add(buildvariant)  # pylint: disable=no-member

                    write_log(build.id,
                              "I: starting chroot environments build\n")

                    chroot_build = Build(
                        version=version,
                        git_ref=None,
                        ci_branch=None,
                        is_ci=None,
                        versiontimestamp=None,
                        sourcename=mirror,
                        buildstate="new",
                        buildtype="chroot",
                        projectversion_id=build.projectversion_id,
                        buildconfiguration=None,
                        parent_id=build.id,
                        sourcerepository=None,
                        maintainer=None,
                    )

                    session.add(chroot_build)
                    session.commit()
                    chroot_build.log_state("created")
                    await build_added(chroot_build)

                    await chroot_build.set_needs_build()
                    session.commit()

                    await chroot_build.set_scheduled()
                    session.commit()

                    chroot = Chroot(buildvariant=buildvariant, ready=False)
                    session.add(chroot)
                    session.commit()

                    loop = asyncio.get_event_loop()
                    loop.create_task(
                        create_schroot(
                            task_queue,
                            chroot.id,
                            chroot_build.id,
                            buildvariant.base_mirror.mirror_distribution,
                            buildvariant.base_mirror.project.name,
                            buildvariant.base_mirror.name,
                            buildvariant.architecture.name,
                        ))

            entry.is_locked = True
            entry.mirror_state = "ready"
            session.commit()  # pylint: disable=no-member

            await build.set_successful()
            session.commit()

            logger.info("mirror %s succesfully created", mirrorname)
            write_log_title(build.id, "Done")

    except Exception as exc:
        logger.exception(exc)