Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix review dismissals bug #485

Merged
merged 6 commits into from
Oct 26, 2022

Conversation

devinburnette
Copy link
Contributor

@devinburnette devinburnette commented Oct 13, 2022

Closes #480

In #463 we introduced a feature to dismiss stale reviews, while iterating on it some additional logic slipped in to also dismiss reviews that didn't match review patterns if people were using the github_review_comment_patterns field in their policies. This worked well until a predicate was included in a policy causing certain reviews to be skipped from evaluation and therefore not added to the list of approved candidates. This manifested in buggy/broken behavior with a misleading dismissal reason until the predicate was satisfied.

After deliberating in the issue above, I think we agreed that the dismissal of non-matching patterns is just a little too heavy handed and doesn't really fit well with dismissing "stale" reviews. In other words, if we aren't also dismissing all other reviews that can never satisfy a rule under any condition than the feature seems broken. So this PR removes dismissal of non-matching patterns, but keeps dismissal for both edited and invalidated reviews, classifying those as "stale" if people have the ignore_edited_comments or invalidate_on_push fields set to true in their policies. In addition, this PR also highlights which patterns will satisfy which rules on the details page in hopes to clear up confusion for folks using approval comments.

Screen Shot 2022-10-13 at 6 21 30 PM

@devinburnette devinburnette changed the title Devin fix dismiss bug Fix review dismissals bug Oct 13, 2022
@@ -111,7 +111,8 @@ func (r *Rule) Evaluate(ctx context.Context, prctx pull.Context) (res common.Res
res.Name = r.Name
res.Description = r.Description
res.Status = common.StatusSkipped
res.Requires = r.Requires.Actors
res.Requires = common.Requires{Count: r.Requires.Count, Actors: r.Requires.Actors}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this felt a little funny, but i kept getting cyclical dependency issues when just trying to use the existing approval.Requires

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moving types to common is normal as they end up used in common.Result, so I think this is fine.

"getRequires": func(results *common.Result) map[string][]Membership {
return getRequires(results, strings.TrimSuffix(githubURL, "/"))
"hasPatterns": func(results *common.Result) bool {
return !results.Methods.IsEmpty()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there's one thing I think I'm missing here and that's what if a github review approval (without comments) would satisfy the policy just fine? I think i can make it only show the Patterns if github_review: true and github_review_comment_patterns is not set.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but then it's like the logic is slipping into the frontend a little bit.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if instead of thinking of this as patterns-only, we show all methods? I think that removes the need for hasPatterns (every rule will have methods) and then we can change getPatterns to getMethods and update the template accordingly (see later comments)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sgtm

@@ -179,3 +179,7 @@ func (m *Methods) BodyMatches(prBody string) bool {
}
return false
}

func (m *Methods) IsEmpty() bool {
return m == nil || (len(m.Comments) == 0 && len(m.CommentPatterns) == 0 && len(m.GithubReviewCommentPatterns) == 0 && len(m.BodyPatterns) == 0)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh i can just put it here, and maybe call this something different.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this also needs to check that m.GithubReview is non-nil to account for all fields.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yea i realized that, but with the new approach, i think we don't need it anymore.

Copy link
Member

@bluekeyes bluekeyes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for fixing this and expanding the details view! I had some suggestions on the UI part, but the rest of the change looks good.

@@ -111,7 +111,8 @@ func (r *Rule) Evaluate(ctx context.Context, prctx pull.Context) (res common.Res
res.Name = r.Name
res.Description = r.Description
res.Status = common.StatusSkipped
res.Requires = r.Requires.Actors
res.Requires = common.Requires{Count: r.Requires.Count, Actors: r.Requires.Actors}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moving types to common is normal as they end up used in common.Result, so I think this is fine.

@@ -59,14 +59,20 @@ type ReviewRequestRule struct {
Mode RequestMode
}

type Requires struct {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of duplicating Requires in this package, I think it might be better to move approval.Requires to this package and then fix the references in the approval packages. That should reduce confusion between the two types in the future since they're otherwise the same.

@@ -179,3 +179,7 @@ func (m *Methods) BodyMatches(prBody string) bool {
}
return false
}

func (m *Methods) IsEmpty() bool {
return m == nil || (len(m.Comments) == 0 && len(m.CommentPatterns) == 0 && len(m.GithubReviewCommentPatterns) == 0 && len(m.BodyPatterns) == 0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this also needs to check that m.GithubReview is non-nil to account for all fields.

server/handler/frontend.go Show resolved Hide resolved
"getRequires": func(results *common.Result) map[string][]Membership {
return getRequires(results, strings.TrimSuffix(githubURL, "/"))
"hasPatterns": func(results *common.Result) bool {
return !results.Methods.IsEmpty()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if instead of thinking of this as patterns-only, we show all methods? I think that removes the need for hasPatterns (every rule will have methods) and then we can change getPatterns to getMethods and update the template accordingly (see later comments)

<div class="pt-2">
{{template "result-requires-permissions-details" .}}
{{template "result-patterns-details" .}}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would make sense to reorder these templates so it reads something like:

This rule needs N approvals from people in these groups or people with these permissions. Approvals can use these patterns.

As currently structured, it kind of implies that the sections are independent so that the pattern section doesn't also require the approvers have certain team membership/permissions.

{{define "result-requires-details"}}
<b class="font-bold text-sm">This rule requires review from</b>
{{define "result-patterns-details"}}
<b class="font-bold text-sm">This rule requires {{.Requires.Count}} review(s) using any of these patterns</b>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call adding the count to all of these - I'm not sure why we didn't add it earlier. I think it would be better to only show the count once before all the other approval details. With the count repeated, people could interpret it as if they need N reviews for each section instead of N reviews total for the rule.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yea that's fair, i was trying to play with the wording so that wouldn't be the case, but I think this is a better idea.

}
} else {
patternInfo["Github Review State"] = append(patternInfo["Github Review State"], string(result.Methods.GithubReviewState))
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is the only part where i feel like the logic slipped into the view a little, but i thought the result would be more helpful for humans to read.

Disapproval does not support counts, so using the common type is
misleading. Add an new comment explaining this.
This shouldn't be nil in practice, but would prefer to not panic
over this if something changes in the future.
Copy link
Member

@bluekeyes bluekeyes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for addressing the comments and sorry about the delayed review, this looks good to merge

@bluekeyes bluekeyes merged commit 4690ee8 into palantir:develop Oct 26, 2022
@devinburnette devinburnette deleted the devin-fix-dismiss-bug branch October 29, 2022 21:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

bug: review approval dismissals are misleading when predicates are not satisfied
2 participants