def METHOD_NAME(  # pylint: disable=too-many-arguments, too-many-branches
    ctx,
    src,
    lib,
    exclude,
    board,
    build_dir,
    keep_build_dir,
    project_conf,
    project_option,
    environments,
    verbose,
):
    if not src and os.getenv("PLATFORMIO_CI_SRC"):
        src = validate_path(ctx, None, os.getenv("PLATFORMIO_CI_SRC").split(":"))
    if not src:
        raise click.BadParameter("Missing argument 'src'")
    try:
        if not keep_build_dir and os.path.isdir(build_dir):
            fs.rmtree(build_dir)
        if not os.path.isdir(build_dir):
            os.makedirs(build_dir)
        for dir_name, patterns in dict(lib=lib, src=src).items():
            if not patterns:
                continue
            contents = []
            for p in patterns:
                contents += glob.glob(p, recursive=True)
            _copy_contents(os.path.join(build_dir, dir_name), contents)
        if project_conf and os.path.isfile(project_conf):
            _copy_project_conf(build_dir, project_conf)
        elif not board:
            raise CIBuildEnvsEmpty()
        if exclude:
            _exclude_contents(build_dir, exclude)
        # initialise project
        ctx.invoke(
            project_init_cmd,
            project_dir=build_dir,
            boards=board,
            project_options=project_option,
        )
        # process project
        ctx.invoke(
            cmd_run, project_dir=build_dir, environment=environments, verbose=verbose
        )
    finally:
        if not keep_build_dir:
            fs.rmtree(build_dir)