Ejemplo n.º 1
0
def _buildrepo_bootstrap(opts, cdir):
    _log.section_start(_LOGGER, "bootstrap", "Bootstrapping container...")
    cont_make_args = []
    if opts.repodest:
        cont_make_args += ["--repodest", opts.repodest]
        opts.repodest = Path(opts.repodest)
        if not _ensure_dir(opts.repodest):
            return None
    if opts.cache_src:
        cont_make_args += ["--cache-src", opts.cache_src]
        opts.cache_src = Path(opts.cache_src)
        if not _ensure_dir(opts.cache_src):
            return None
    if opts.cache_apk:
        cont_make_args += ["--cache-apk", opts.cache_apk]
        opts.cache_apk = Path(opts.cache_apk)
        if not _ensure_dir(opts.cache_apk):
            return None
    if opts.setarch:
        cont_make_args += ["--setarch", opts.setarch]

    cont_make_args += [
        "--arch",
        opts.arch,
        "--branch",
        opts.branch,
        "--",
        str(cdir),
        str(opts.aportsdir),
    ]
    cont = apkfoundry.container.cont_make(cont_make_args)

    _log.section_end(_LOGGER)
    return cont
Ejemplo n.º 2
0
def run_after(rc, cont, conf, afterdir, script):
    if not script:
        return 0

    _log.section_start(
        _LOGGER,
        "run-after-script",
        "Running after-script...",
    )
    if afterdir and not Path(afterdir).is_dir():
        _LOGGER.warning("After-script directory %s was not found!", afterdir)
        afterdir = None
    elif afterdir:
        logging.info("After-script directory is enabled")

    rc, _ = cont.run(
        [script],
        repo=conf.get("after.repo", conf["repo.default"]),
        net=conf.getboolean("after.networking"),
        afterdir=afterdir,
        env={
            "AF_RC": str(rc),
            "AF_AFTERDIR": "/af/config/afterdir" if afterdir else "",
            "AF_FILELIST": "/af/config/filelist",
        },
    )
    _log.section_end(_LOGGER)
    return rc
Ejemplo n.º 3
0
def run_job(cont, conf, opts):
    _log.section_start(
        _LOGGER,
        "gen-build-order",
        "Generating build order...",
    )
    graph = apkfoundry.digraph.generate_graph(conf, cont=cont)
    if not graph or not graph.is_acyclic():
        _LOGGER.error("failed to generate dependency graph")
        return 1
    _log.section_end(_LOGGER)

    return run_graph(cont, conf, graph, opts)
Ejemplo n.º 4
0
def _build_list(conf, opts):
    if opts.startdirs:
        _log.section_start(_LOGGER, "manual_pkgs",
                           "The following packages were manually included:")
        _log.msg2(_LOGGER, opts.startdirs)
        _log.section_end(_LOGGER)

    if opts.rev_range:
        _log.section_start(_LOGGER, "changed_pkgs",
                           "Determining changed packages...")
        pkgs = changed_pkgs(conf, opts)
        _log.msg2(_LOGGER, pkgs)
        _log.section_end(_LOGGER)
        opts.startdirs.extend(_filter_list(conf, opts, pkgs))
Ejemplo n.º 5
0
def _filter_list(conf, opts, startdirs):
    _log.section_start(
        _LOGGER,
        "skip_pkgs",
        "Determining packages to skip...",
    )

    repos = conf.getmaplist("repo.arch")
    skip = conf.getmaplist("build.skip")
    for startdir in startdirs:
        # Already manually included
        if startdir in opts.startdirs:
            continue
        repo, _ = startdir.split("/", maxsplit=1)
        arches = repos.get(repo)
        if arches is None:
            _log.msg2(
                _LOGGER,
                "%s - repository not configured",
                startdir,
            )
            continue
        if opts.arch not in arches:
            _log.msg2(
                _LOGGER,
                "%s - repository not enabled for %s",
                startdir,
                opts.arch,
            )
            continue
        if opts.arch in skip.get(startdir, {}):
            _log.msg2(
                _LOGGER,
                "%s - package skipped for %s",
                startdir,
                opts.arch,
            )
            continue
        yield startdir

    _log.section_end(_LOGGER)
Ejemplo n.º 6
0
def buildrepo(args):
    opts = _buildrepo_args(args)

    if opts.dry_run:
        opts.delete = "always"

    if not opts.arch:
        opts.arch = apkfoundry.DEFAULT_ARCH

    if not (opts.aportsdir or opts.git_url) \
            or (opts.aportsdir and opts.git_url):
        _LOGGER.error(
            "You must specify only one of -a APORTSDIR or -g GIT_URL")
        return _cleanup(1, None, opts.delete)

    if opts.aportsdir:
        opts.aportsdir = Path(opts.aportsdir)
        if not opts.branch:
            opts.branch = _util.get_branch(opts.aportsdir)

    if opts.directory:
        cdir = Path(opts.directory)
    else:
        apkfoundry.LOCALSTATEDIR.mkdir(parents=True, exist_ok=True)
        cdir = Path(
            tempfile.mkdtemp(dir=apkfoundry.LOCALSTATEDIR, suffix=".af"))

    if opts.git_url:
        if not opts.branch:
            opts.branch = "master"

        _log.section_start(_LOGGER, "clone", "Cloning git repository...")
        opts.aportsdir = cdir / apkfoundry.MOUNTS["aportsdir"].lstrip("/")
        opts.aportsdir.mkdir(parents=True, exist_ok=True)
        _util.check_call((
            "git",
            "clone",
            opts.git_url,
            opts.aportsdir,
        ))
        _util.check_call((
            "git",
            "-C",
            opts.aportsdir,
            "checkout",
            opts.branch,
        ))
        if not (opts.aportsdir / ".apkfoundry").is_dir():
            _LOGGER.critical("No .apkfoundry configuration directory exists!")
            return _cleanup(1, cdir, opts.delete)
        _log.section_end(_LOGGER)

    branchdir = _util.get_branchdir(opts.aportsdir, opts.branch)
    if opts.config_option:
        conf = dict(map(lambda i: i.split("=", maxsplit=1),
                        opts.config_option))
    else:
        conf = None
    conf = apkfoundry.proj_conf(opts.aportsdir, opts.branch, conf)

    if opts.build_script is None:
        opts.build_script = Path(apkfoundry.MOUNTS["aportsdir"]) \
            / ".apkfoundry" / branchdir.name / "build"
    if opts.after_script is None:
        opts.after_script = Path(apkfoundry.MOUNTS["aportsdir"]) \
            / ".apkfoundry" / branchdir.name / "after"

    _build_list(conf, opts)
    if not opts.startdirs:
        _LOGGER.info("No packages to build!")
        return _cleanup(0, cdir, opts.delete)

    if opts.dry_run:
        return _cleanup(0, cdir, opts.delete)

    cont = _buildrepo_bootstrap(opts, cdir)
    if not cont:
        _LOGGER.error("Failed to bootstrap container")
        return _cleanup(1, cont, opts.delete)

    start = time.time()
    rc = run_job(cont, conf, opts)
    _save_filelist(cont, start)
    rc = run_after(rc, cont, conf, opts.afterdir, opts.after_script) or rc

    return _cleanup(rc, cont, opts.delete)
Ejemplo n.º 7
0
def run_graph(cont, conf, graph, opts):
    initial = set(opts.startdirs)
    done = {}

    try:
        on_failure = FailureAction[conf["build.on-failure"].upper()]
    except KeyError:
        _LOGGER.error(
            "build.on-failure = %s is invalid; defaulting to STOP",
            conf["build.on-failure"].upper(),
        )
        on_failure = FailureAction.STOP

    for i in initial:
        if i not in graph.graph:
            _LOGGER.error("%s/APKBUILD does not exist!", i)
            return 1

    while True:
        order = [
            i for i in graph.topological_sort()
            if i in initial and i not in done
        ]
        if not order:
            break

        tot = len(order) + len(done.keys())
        cur = len(done.keys())

        _log.section_start(_LOGGER, "build_order", "Build order:\n")
        for startdir in order:
            cur += 1
            _log.msg2(_LOGGER, "(%d/%d) %s", cur, tot, startdir)
        _log.section_end(_LOGGER)

        cur = len(done.keys())
        for startdir in order:
            cur += 1
            _log.section_start(_LOGGER, "build_" + startdir.replace("/", "_"),
                               "(%d/%d) Start: %s", cur, tot, startdir)

            rc = run_task(cont, conf, startdir, opts.build_script)

            if rc == 0:
                _log.section_end(
                    _LOGGER,
                    "(%d/%d) Success: %s",
                    cur,
                    tot,
                    startdir,
                )
                done[startdir] = Status.SUCCESS

            else:
                _log.section_end(
                    _LOGGER,
                    "(%d/%d) Fail: %s",
                    cur,
                    tot,
                    startdir,
                )
                done[startdir] = Status.FAIL

                if opts.interactive:
                    action = _interrupt(cont, startdir)
                    while action is None:
                        action = _interrupt(cont, startdir)
                else:
                    action = on_failure

                if action == FailureAction.RECALCULATE:
                    _log.section_start(_LOGGER, "recalc-order",
                                       "Recalculating build order")

                    depfails = set(graph.all_downstreams(startdir))
                    for rdep in depfails:
                        graph.delete_node(rdep)
                    graph.delete_node(startdir)

                    depfails &= initial
                    for rdep in depfails:
                        _LOGGER.error("Depfail: %s", rdep)
                        done[rdep] = Status.DEPFAIL

                    _log.section_end(_LOGGER)

                elif action == FailureAction.STOP:
                    _LOGGER.error("Stopping due to previous error")
                    cancels = initial - set(done.keys())
                    for rdep in cancels:
                        done[rdep] = Status.DEPFAIL
                    graph.reset_graph()

                elif action == FailureAction.IGNORE:
                    _LOGGER.info("Ignoring error and continuing")
                    continue

                break

    return _stats_builds(done)