async getPendingReviews()

in functions/src/plugins/merge.ts [269:310]


  async getPendingReviews(context: Context, pr: CachedPullRequest): Promise<number> {
    const {owner, repo} = context.repo();
    // We can have a lot of reviews on a PR, we need to paginate to get all of them
    const reviews = (await context.github.paginate(context.github.pullRequests.listReviews({
      owner,
      repo,
      number: pr.number,
      per_page: 100
    }), pages => (pages as any).data) as Review[])
      // We only want reviews with state: PENDING, APPROVED, CHANGES_REQUESTED, DISMISSED.
      // We ignore comments because they can be done after a review was approved / refused, and also because
      // anyone can add comments, it doesn't mean that it's someone who is actually reviewing the PR
      .filter(review => review.state !== REVIEW_STATE.Commented)
      // We ignore reviews from individuals who aren't members of the repository
      .filter(review => review.author_association !== AUTHOR_ASSOCIATION.None)
      // Order by latest review first
      .sort((review1, review2) => new Date(review2.submitted_at).getTime() - new Date(review1.submitted_at).getTime());

    // The list of requested reviewers only contains people that have been requested for review but have not
    // given the review yet. Once they do, they disappear from this list, and we need to check the reviews.
    // We only take the reviews from users and ignore team reviews so that we don't conflict with Github code owners
    // that automatically add team to the reviewers list
    const reviewRequests =(await context.github.pullRequests.listReviewRequests({owner, repo, number: pr.number})).data.users || [];

    const usersReviews: number[] = [];
    const finalReviews: any[] = [];

    // For each individual that reviewed this PR, we only keep the latest review (it can either be pending, approved,
    // changes_requested or dismissed)
    reviews.forEach(review => {
      const reviewUser = review.user.id;
      if(!usersReviews.includes(reviewUser)) {
        usersReviews.push(reviewUser);
        finalReviews.push(review);
      }
    });

    // We want the list of "non-approved" reviews, so we only keep the reviews that are pending / requested changes
    const nonApprovedReviews = finalReviews.filter(review => review.state === REVIEW_STATE.Pending || review.state === REVIEW_STATE.ChangesRequest);

    return reviewRequests.length + nonApprovedReviews.length;
  }