예제 #1
0
def process_pull_request(world: World, pull_request: PullRequest,
                         repository_url: Text) -> Optional[Iterator[Task]]:

    if pull_request.postponed:
        skipping_pr("postponed", pull_request.number)
        return None

    if not pull_request.mergeable:
        skipping_pr("can't be merged", pull_request.number)
        if not pull_request.needs_rebase:
            pull_request.add_rebase_label(world)
        return None

    try:
        tasks_data = pull_request.get_tasks_data(world)
    except (yaml.error.YAMLError, TypeError, KeyError) as e:
        logger.error(e)
        return None

    if pull_request.needs_rerun:
        # If all statuses are not failed (not in state ERROR or FAILURE) and
        # re-run label was set previously, remove the re-run label
        if all(
                map(
                    lambda t: t in pull_request.commit.statuses and
                    not pull_request.commit.statuses[t].failed,
                    tasks_data.keys())):
            try:
                pull_request.remove_rerun_label(world)
            except NotFoundError as e:
                logger.warning(e)

    for name, task_data in tasks_data.items():
        task = Task(name, pull_request.number, pull_request.commit.sha,
                    pull_request.author, repository_url, task_data,
                    JobDispatcher)
        if task.name not in pull_request.commit.statuses:
            if (pull_request.author in world.whitelist
                    or pull_request.needs_rerun):
                logger.info("PR#%s %s updating status to unassigned",
                            pull_request.number, task.name)
                try:
                    task.set_unassigned(world)
                except EnvironmentError as e:
                    logger.error(e)
                continue

        status = pull_request.commit.statuses.get(task.name)
        if status is not None:
            task = process_status(world, status, task,
                                  pull_request.needs_rerun)
            if task is None:
                continue

        task = process_task(world, task, pull_request.commit.statuses)
        if task is None:
            continue

        yield task
예제 #2
0
def main():
    parser = create_parser()
    args = parser.parse_args()

    runner_id = args.ID
    config = args.config

    credentials = config["credentials"]
    repo = config["repository"]
    tasks_path = config["tasks_file"]
    whitelist = config["whitelist"]
    no_task_backoff_time = config["no_task_backoff_time"]

    logging.config.dictConfig(config["logging"])

    exit_handler = ExitHandler()
    signal.signal(signal.SIGINT, exit_handler.finish)
    signal.signal(signal.SIGTERM, exit_handler.abort)

    gh = github3.login(token=credentials["token"])
    session = util.create_session(util.make_headers(credentials["token"]))
    do_request = partial(util.perform_request, session=session)

    world = World(graphql_request=do_request,
                  github_api=gh,
                  session=session,
                  repo_owner=repo["owner"],
                  repo_name=repo["name"],
                  runner_id=runner_id,
                  tasks_path=tasks_path,
                  whitelist=whitelist)

    while not exit_handler.done:
        world.check_graphql_limit()

        try:
            response = do_request(query=queries.make_pull_requests_query(
                world.repo_owner, world.repo_name))
        except EnvironmentError as e:
            logger.error(e)
            sys.exit(1)

        data = util.get_data(response)
        repo = util.get_repository(data)
        repo_url = util.get_repository_url(repo)
        pull_requests_data = util.get_pull_requests(repo)

        pull_requests = sorted(
            (PullRequest.from_dict(pr_data) for pr_data in pull_requests_data),
            key=lambda pr: not pr.prioritized)
        for pull_request in pull_requests:
            for task in process_pull_request(world, pull_request, repo_url):
                exit_handler.register_task(task)
                world.available_resources.take(task)
                logger.info("Available resources: %s",
                            world.available_resources)
                try:
                    task.execute(world, pull_request.commit.statuses)
                except ReferenceError as e:
                    logger.warning(e)
                except (EnvironmentError, RuntimeError) as e:
                    logger.error(e)
                    sentry_report_exception({"module": "github"})
                    sleep(ERROR_BACKOFF_TIME)
                finally:
                    exit_handler.unregister_task()
                    world.available_resources.give(task)
                    logger.info("Available resources: %s",
                                world.available_resources)

        sleep(no_task_backoff_time)