-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
Show approvals on the PR listing page #8762
Conversation
Codecov Report
@@ Coverage Diff @@
## master #8762 +/- ##
==========================================
- Coverage 41.39% 41.38% -0.01%
==========================================
Files 539 539
Lines 69501 69514 +13
==========================================
- Hits 28770 28769 -1
- Misses 37032 37051 +19
+ Partials 3699 3694 -5
Continue to review full report at Codecov.
|
models/branches.go
Outdated
ApprovalsWhitelistUserIDs []int64 `xorm:"JSON TEXT"` | ||
ApprovalsWhitelistTeamIDs []int64 `xorm:"JSON TEXT"` | ||
RequiredApprovals int64 `xorm:"NOT NULL DEFAULT 0"` | ||
GrantedApprovalsCount int64 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should not be added column so database so should be marked so:
GrantedApprovalsCount int64 | |
GrantedApprovalsCount int64 `xorm:"-"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
granted aprovals Should be stored for each PR and not for each branch?!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And the information Iis stored already somewhere ... have to check where ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aah, so any properties I add are mapped to the database by default?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can get the information via models.GetUniqueApprovalsByPullRequestID(prID int64) ([]*Review, error)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
summary:
- no changes in models/branches.go
- call models.GetUniqueApprovalsByPullRequestID(prID int64) in routers/repo/issue.go and store in
ctx.Data["GrantedApprovalsCount"]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
call models.GetUniqueApprovalsByPullRequestID(prID int64) in routers/repo/issue.go and store in ctx.Data["GrantedApprovalsCount"]
How would I reference that per PR, seeing as I have an array of them? Issues get popped under ctx.Data["Issues"]
as a whole so I created a property to be able to access it from each one within the template. I presume something dynamic like ctx.Data["Issues"][i].GrantedApprovals = count
isn't possible - I come from a JS background 😉.
The reason I left it as a property of ProtectedBranch
was simply because GetGrantedApprovalsCount
lived there already, and I just assumed I would keep them together.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can look into it later ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm attempting to change it to a solution similar to ctx.Data["CommitStatus"]
and removing the extra property on ProtectedBranch
.
Looking at it, GetUniqueApprovalsByPullRequestID
will return all approved reviews for a given PR, not just those on the approval whitelist. This might be equally valid - what would the user reasonably expect to see? Personally I think only reviews "which matter" should count to quickly determine if a PR is ready to be merged.
@@ -222,6 +222,14 @@ | |||
<a class="ui label has-emoji" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&state={{$.State}}&labels={{.ID}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}" style="color: {{.ForegroundColor}}; background-color: {{.Color}}" title="{{.Description}}">{{.Name}}</a> | |||
{{end}} | |||
|
|||
{{if .IsPull}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this can be reduced to one if
statement:
{{if .IsPull}} | |
{{if and .IsPull .PullRequest.ProtectedBranch .PullRequest.ProtectedBranch.RequiredApprovals}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aah that's much simpler, will do
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately this didn't work for branches without protection enabled
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
{{if and .IsPull (if ne (index $.RequiredApprovals .PullRequest.ID) 0)}}
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose that requires that $.RequiredApprovals contain all indexes? Should be possible by setting them 0 in issue.go.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Beside this ... nice idear
models/branches.go
Outdated
ApprovalsWhitelistUserIDs []int64 `xorm:"JSON TEXT"` | ||
ApprovalsWhitelistTeamIDs []int64 `xorm:"JSON TEXT"` | ||
RequiredApprovals int64 `xorm:"NOT NULL DEFAULT 0"` | ||
GrantedApprovalsCount int64 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
granted aprovals Should be stored for each PR and not for each branch?!
models/branches.go
Outdated
ApprovalsWhitelistUserIDs []int64 `xorm:"JSON TEXT"` | ||
ApprovalsWhitelistTeamIDs []int64 `xorm:"JSON TEXT"` | ||
RequiredApprovals int64 `xorm:"NOT NULL DEFAULT 0"` | ||
GrantedApprovalsCount int64 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And the information Iis stored already somewhere ... have to check where ...
templates/repo/issue/list.tmpl
Outdated
{{if .IsPull}} | ||
{{if .PullRequest.ProtectedBranch}} | ||
{{if .PullRequest.ProtectedBranch.RequiredApprovals}} | ||
<span class="comment ui right"><i class="octicon octicon-eye"></i> {{.PullRequest.ProtectedBranch.GrantedApprovalsCount}} / {{.PullRequest.ProtectedBranch.RequiredApprovals}}</span> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
<span class="comment ui right"><i class="octicon octicon-eye"></i> {{.PullRequest.ProtectedBranch.GrantedApprovalsCount}} / {{.PullRequest.ProtectedBranch.RequiredApprovals}}</span> | |
<span class="comment ui right"><i class="octicon octicon-eye"></i> {{.PullRequest.GrantedApprovalsCount}} / {{.PullRequest.ProtectedBranch.RequiredApprovals}}</span> |
Continue things .. from abouth
@jamesorlakin look at #8762 (comment) ;) |
I think you guys should consider the page load performance. Protected branches could be load once. Or I should send another PR to do that after this one. |
routers/repo/issue.go
Outdated
|
||
commitStatus[issues[i].PullRequest.ID], _ = issues[i].PullRequest.GetLastCommitStatus() | ||
if err := pull.LoadProtectedBranch(); err == nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're not handling the error here. Please do something like
if err := pull.LoadProtectedBranch(); err != nil {
return
}
if pull.ProtectedBranch != nil && pull.ProtectedBranch.RequiredApprovals != 0 {
ProtectedBranch.GrantedApprovalsCount = pull.ProtectedBranch.GetGrantedApprovalsCount(
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aah ok, is there a subtle difference in the behaviour of errors and nil?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the function returns nil
for an error, there was no error. You don't check for the case where the error was not nil
which means you're never actually doing something with the error.
In Go, there is this pattern of keeping a "happy path" of code, that's why you'll see a lot of if err != nil
code used to handle errors. Take a look at this article for more information: https://medium.com/@matryer/line-of-sight-in-code-186dd7cdea88
Hi all, Thanks for the comments. I've reworked it to now use a method similar to the last commit status - a map by PR ID for both required approvals and approved accepted ones. 6543 mentioned using lunny, you're right, I didn't think about performance! 3 PRs rendered quick enough on my laptop... A to-do (assuming this approach looks okay) would be to cache protected branches during the loop - say a page had 25 PRs all for the same target branch, we would only need to load the |
The number of protected branches in a given repository should not be too large (3? 6? 10?). In my experience, it's more performant to load all of them at once rather than reaching for them one by one. Databases do that themselves: for example, for tables under a certain number of rows, indexes are never used for querying (only for updating); the database considers that reading one disk block is the "expensive" part; sorting/filtering is quickly done in memory. Context/process switching from Gitea to and from the database is costly as well. |
For the number of approvals, I'd use a single database query, which is much faster than retrieving the information each time:
Hope this helps. |
@@ -222,6 +222,14 @@ | |||
<a class="ui label has-emoji" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&state={{$.State}}&labels={{.ID}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}" style="color: {{.ForegroundColor}}; background-color: {{.Color}}" title="{{.Description}}">{{.Name}}</a> | |||
{{end}} | |||
|
|||
{{if .IsPull}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
{{if and .IsPull (if ne (index $.RequiredApprovals .PullRequest.ID) 0)}}
?
Thanks for the suggestions @guillep2k! Unfortunately I'm not sure I'm capable at dropping to such complex SQL (joining and comparing whitelisted approvers including teams, etc). That said, loading all protected branches at once initially could be better optimised than the individual looping - I'll try and do that.
I would be under the assumption closed PRs should show the same as open ones? Moving forward, I'm also considering showing total approvals (not whitelisted) for PRs that aren't on a protected branch. This would just be a simple number next to the eye. If possible I'll want to grab all approvals for the PRs at once, and then do the whitelist filtering using a util function (similar to how I've since backported this to our production 1.9 instance and performance seems to be fine - though it's not a great representative measurement! |
@jamesorlakin are you still working on this? |
@6543 yep I'm keen to finish it, but I likely won't have much time until the weekend. Feel free to tweak if you want to in the meantime 😃 . |
if pull.ProtectedBranch != nil && pull.ProtectedBranch.RequiredApprovals != 0 { | ||
requiredApprovals[pull.ID] = pull.ProtectedBranch.RequiredApprovals | ||
approvals[pull.ID] = pull.ProtectedBranch.GetGrantedApprovalsCount(pull) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Set value in slice also when branch is not protected? (with 0 value)
@jamesorlakin what is the stats? |
@jamesorlakin ping |
Hi all, Apologies for the general radio silence - everything has been a tad busy of recent and it all generally got forgotten about 😥. In the meantime I've had a look around and #9274 seems to be a generally more polished implementation if you would like to go ahead with that. I don't mind continuing on if @oscarcosta doesn't want to. |
As suggested in #8659, this PR displays the whitelisted approvals in Gitea's PR listing page if a given branch is protected and requires more than 0 approvals to be merged. I've chosen the eye Octicon but perhaps a person one would be better?
I've tested this works locally in the browser but as I'm on a Windows environment Docker doesn't work properly for the full test suite 😢 . This is also my first time using Go, so all suggestions (nitpicking) are most welcome!