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: do not apply approved label if change requested #270

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 14 additions & 8 deletions pkg/plugins/approve/approve.go
Original file line number Diff line number Diff line change
Expand Up @@ -590,15 +590,21 @@ func addApprovers(approversHandler *approvers.Approvers, approveComments []*comm
continue
}

if reviewActsAsApprove && c.ReviewState == github.ReviewStateApproved {
approversHandler.AddApprover(
c.Author,
c.HTMLURL,
false,
)
if c.ReviewState == github.ReviewStateApproved {
approversHandler.RemoveChangeRequested(c.Author)
if reviewActsAsApprove {
approversHandler.AddApprover(
c.Author,
c.HTMLURL,
false,
)
}
}
if reviewActsAsApprove && c.ReviewState == github.ReviewStateChangesRequested {
approversHandler.RemoveApprover(c.Author)
if c.ReviewState == github.ReviewStateChangesRequested {
approversHandler.AddChangeRequested(c.Author)
if reviewActsAsApprove {
approversHandler.RemoveApprover(c.Author)
}
}

for _, match := range commandRegex.FindAllStringSubmatch(c.Body, -1) {
Expand Down
48 changes: 43 additions & 5 deletions pkg/plugins/approve/approve_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1054,11 +1054,14 @@ Approvers can cancel approval by writing ` + "`/approve cancel`" + ` in a commen
<!-- META={"approvers":["alice","cjwagner"]} -->`,
},
{
name: "approve command supersedes simultaneous changes requested review",
hasLabel: false,
files: []string{"a/a.go"},
comments: []github.IssueComment{},
reviews: []github.Review{newTestReview("Alice", "/approve", github.ReviewStateChangesRequested)},
name: "approve command supersedes prior changes requested review",
hasLabel: false,
files: []string{"a/a.go"},
comments: []github.IssueComment{},
reviews: []github.Review{
newTestReview("Alice", "/approve", github.ReviewStateChangesRequested),
newTestReview("Alice", "/approve", github.ReviewStateApproved),
},
selfApprove: false,
needsIssue: false,
lgtmActsAsApprove: false,
Expand All @@ -1081,6 +1084,41 @@ Needs approval from an approver in each of these files:

- ~~[a/OWNERS](https://github.com/org/repo/blob/master/a/OWNERS)~~ [Alice]

Approvers can indicate their approval by writing ` + "`/approve`" + ` in a comment
Approvers can cancel approval by writing ` + "`/approve cancel`" + ` in a comment
</details>
<!-- META={"approvers":[]} -->`,
},
{
name: "changes requested supersedes approve command",
hasLabel: false,
files: []string{"a/a.go"},
comments: []github.IssueComment{},
reviews: []github.Review{
newTestReview("Alice", "/approve", github.ReviewStateChangesRequested),
},
selfApprove: false,
needsIssue: false,
lgtmActsAsApprove: false,
reviewActsAsApprove: true,
githubLinkURL: &url.URL{Scheme: "https", Host: "github.com"},

expectDelete: false,
expectToggle: false,
expectComment: true,
expectedComment: `[APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by: *<a href="" title="Approved">Alice</a>*

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=org%2Frepo).

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

<details >
Needs approval from an approver in each of these files:

- ~~[a/OWNERS](https://github.com/org/repo/blob/master/a/OWNERS)~~ [Alice]

Approvers can indicate their approval by writing ` + "`/approve`" + ` in a comment
Approvers can cancel approval by writing ` + "`/approve cancel`" + ` in a comment
</details>
Expand Down
26 changes: 22 additions & 4 deletions pkg/plugins/approve/approvers/owners.go
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@ func (a Approval) String() string {
type Approvers struct {
owners Owners
approvers map[string]Approval // The keys of this map are normalized to lowercase.
changeRequested map[string]bool // CHANGE_REQUESTED from any reviewer prevents submission
assignees sets.Set[string]
AssociatedIssue int
RequireIssue bool
Expand Down Expand Up @@ -316,9 +317,10 @@ func CaseInsensitiveIntersection(one, other sets.Set[string]) sets.Set[string] {
// NewApprovers create a new "Approvers" with no approval.
func NewApprovers(owners Owners) Approvers {
return Approvers{
owners: owners,
approvers: map[string]Approval{},
assignees: sets.New[string](),
owners: owners,
approvers: map[string]Approval{},
changeRequested: map[string]bool{},
assignees: sets.New[string](),

ManuallyApproved: func() bool {
return false
Expand Down Expand Up @@ -364,6 +366,11 @@ func (ap *Approvers) AddApprover(login, reference string, noIssue bool) {
}
}

// AddChangeRequested adds a new changeRequested
func (ap *Approvers) AddChangeRequested(login string) {
ap.changeRequested[strings.ToLower(login)] = true
}

// AddAuthorSelfApprover adds the author self approval
func (ap *Approvers) AddAuthorSelfApprover(login, reference string, noIssue bool) {
if ap.shouldNotOverrideApproval(login, noIssue) {
Expand All @@ -382,6 +389,11 @@ func (ap *Approvers) RemoveApprover(login string) {
delete(ap.approvers, strings.ToLower(login))
}

// RemoveChangeRequested removes a changeRequested from the map.
func (ap *Approvers) RemoveChangeRequested(login string) {
delete(ap.changeRequested, strings.ToLower(login))
}

// AddAssignees adds assignees to the list
func (ap *Approvers) AddAssignees(logins ...string) {
for _, login := range logins {
Expand Down Expand Up @@ -542,6 +554,12 @@ func (ap Approvers) GetCCs() []string {
return sets.List(suggested.Union(keepAssignees))
}

// AreChangesRequested returns a bool indicating whether changes are requested on the PR.
// A PR cannot be submitted if there is an outstanding CHANGES_REQUESTED state.
func (ap Approvers) AreChangesRequested() bool {
return len(ap.changeRequested) > 0
}

// AreFilesApproved returns a bool indicating whether or not OWNERS files associated with
// the PR are approved. A PR with no OWNERS files is not considered approved. If this
// returns true, the PR may still not be fully approved depending on the associated issue
Expand All @@ -557,7 +575,7 @@ func (ap Approvers) AreFilesApproved() bool {
// - that there is an associated issue with the PR
// - an OWNER has indicated that the PR is trivial enough that an issue need not be associated with the PR
func (ap Approvers) RequirementsMet() bool {
return ap.AreFilesApproved() && (!ap.RequireIssue || ap.AssociatedIssue != 0 || len(ap.NoIssueApprovers()) != 0)
return !ap.AreChangesRequested() && ap.AreFilesApproved() && (!ap.RequireIssue || ap.AssociatedIssue != 0 || len(ap.NoIssueApprovers()) != 0)
}

// IsApproved returns a bool indicating whether the PR is fully approved.
Expand Down