| 15 | var outcomeReviewGHAPIGetArray = ghAPIGetArray |
| 16 | |
| 17 | func evalAddReviewer(item CreatedItemReport, repoOverride string) OutcomeReport { |
| 18 | repo := resolveItemRepo(item, repoOverride) |
| 19 | num := resolveItemNumber(item) |
| 20 | report := OutcomeReport{ |
| 21 | Type: item.Type, |
| 22 | ObjectURL: item.URL, |
| 23 | ObjectNumber: num, |
| 24 | Repo: repo, |
| 25 | } |
| 26 | outcomeReviewLog.Printf("Evaluating add-reviewer outcome: repo=%s, pr=%d", repo, num) |
| 27 | if num == 0 || repo == "" { |
| 28 | report.Result = OutcomeError |
| 29 | report.EvalError = "missing PR number or repo" |
| 30 | return report |
| 31 | } |
| 32 | |
| 33 | requestedReviewers := metadataStringSlice(item.Metadata, "requested_reviewers") |
| 34 | requestedTeams := metadataStringSlice(item.Metadata, "requested_team_reviewers") |
| 35 | |
| 36 | reviews, err := outcomeReviewGHAPIGetArray(fmt.Sprintf("pulls/%d/reviews", num), repo) |
| 37 | if err != nil { |
| 38 | report.Result = OutcomeError |
| 39 | report.EvalError = err.Error() |
| 40 | return report |
| 41 | } |
| 42 | |
| 43 | requested, err := outcomeReviewGHAPIGet(fmt.Sprintf("pulls/%d/requested_reviewers", num), repo) |
| 44 | if err != nil { |
| 45 | report.Result = OutcomeError |
| 46 | report.EvalError = err.Error() |
| 47 | return report |
| 48 | } |
| 49 | |
| 50 | outcomeReviewLog.Printf("Fetched %d reviews for PR #%d (requested reviewers=%d, teams=%d)", len(reviews), num, len(requestedReviewers), len(requestedTeams)) |
| 51 | requestedReviewerSet := make(map[string]struct{}, len(requestedReviewers)) |
| 52 | for _, reviewer := range requestedReviewers { |
| 53 | requestedReviewerSet[strings.ToLower(reviewer)] = struct{}{} |
| 54 | } |
| 55 | |
| 56 | latestByReviewer := make(map[string]map[string]any, len(requestedReviewerSet)) |
| 57 | for _, review := range reviews { |
| 58 | login := strings.ToLower(outcomeNestedString(review["user"], "login")) |
| 59 | if _, ok := requestedReviewerSet[login]; !ok { |
| 60 | continue |
| 61 | } |
| 62 | state := strings.ToUpper(outcomeString(review["state"])) |
| 63 | submittedAt := outcomeString(review["submitted_at"]) |
| 64 | if state == "" || state == "PENDING" || submittedAt == "" { //nolint:tolowerequalfold |
| 65 | continue |
| 66 | } |
| 67 | if !timestampOnOrAfter(submittedAt, item.Timestamp) { |
| 68 | continue |
| 69 | } |
| 70 | prev, ok := latestByReviewer[login] |
| 71 | if !ok || timestampOnOrAfter(submittedAt, outcomeString(prev["submitted_at"])) { |
| 72 | latestByReviewer[login] = review |
| 73 | } |
| 74 | } |