diff --git a/src/github/pullRequest.ts b/src/github/pullRequest.ts index bba1e7b..0a52700 100644 --- a/src/github/pullRequest.ts +++ b/src/github/pullRequest.ts @@ -1,5 +1,6 @@ import { PullRequest, PullRequestReview } from "@octokit/webhooks-types"; +import { caseInsensitiveEqual } from "../util"; import { ActionLogger, GitHubClient } from "./types"; /** API class that uses the default token to access the data from the pull request and the repository */ @@ -55,9 +56,42 @@ export class PullRequestApi { const request = await this.api.rest.pulls.listReviews({ ...this.repoInfo, pull_number: this.number }); const reviews = request.data as PullRequestReview[]; this.logger.debug(`List of reviews: ${JSON.stringify(reviews)}`); - const approvals = reviews.filter( - (review) => review.state.localeCompare("approved", undefined, { sensitivity: "accent" }) === 0, + + const latestReviewsMap = new Map(); + + for (const review of reviews) { + if ( + caseInsensitiveEqual(review.state, "commented") || + // the user may have been deleted + review.user === null || + review.user === undefined + ) { + continue; + } + + // we check if there is already a review from this user + const prevReview = latestReviewsMap.get(review.user.id); + if ( + prevReview === undefined || + // Newer reviews have a higher id number + prevReview.id < review.id + ) { + // if the review is more modern (and not a comment) we replace the one in our map + latestReviewsMap.set(review.user.id, review); + } + } + + const latestReviews = Array.from(latestReviewsMap.values()); + + this.logger.info( + `Latest reviews are ${JSON.stringify( + latestReviews.map((r) => { + return { user: r.user.login, state: r.state }; + }), + )}`, ); + + const approvals = latestReviews.filter((review) => caseInsensitiveEqual(review.state, "approved")); this.usersThatApprovedThePr = approvals.map((approval) => approval.user.login); } this.logger.debug(`PR approvals are ${JSON.stringify(this.usersThatApprovedThePr)}`); diff --git a/src/util.ts b/src/util.ts index 95688d0..dad646b 100644 --- a/src/util.ts +++ b/src/util.ts @@ -13,3 +13,10 @@ export function concatArraysUniquely(arr1?: T[], arr2?: T[]): T[] { // We remove the duplicated values and return the array return concatedArray.filter((item, pos) => concatedArray.indexOf(item) === pos); } + +/** Case insentive comparison of two strings + * @example caseInsensitiveEqual("hi", "HI") === true + */ +export function caseInsensitiveEqual(a: T, b: T): boolean { + return a.localeCompare(b, undefined, { sensitivity: "accent" }) === 0; +}