Skip to content
This repository has been archived by the owner on Aug 27, 2024. It is now read-only.

ISSUE-544: Add support for native approvals, fix validation bug, fix typos #586

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

GeorgySerga
Copy link

An attempt to fix: #544
This is a draft, work in progress. Code is working (expected to be working), no tests or toggle is implemented. More on the changes and reasoning would be inside inline comments. Thanks for reviews.

@@ -29,7 +29,7 @@ export default class Approval extends Check {
static TYPE = 'approval'
static CONTEXT = context
static NAME = 'Approval check'
static HOOK_EVENTS = [EVENTS.PULL_REQUEST, EVENTS.ISSUE_COMMENT]
static HOOK_EVENTS = [EVENTS.PULL_REQUEST, EVENTS.ISSUE_COMMENT, EVENTS.PULL_REQUEST_REVIEW]
Copy link
Author

Choose a reason for hiding this comment

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

A new event is added to ask GitHub to notify on PULL_REQUEST_REVIEW events.

@@ -118,39 +118,38 @@ export default class Approval extends Check {
}

/**
* Returns the comment if it matches the config, null otherwise.
* Returns `true` if username is in the config, false `otherwise`.
Copy link
Author

Choose a reason for hiding this comment

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

Just for consistency, comment wasn't used, but return value was checked inside conditions. Seems like booleans are more suitable for that.

const approvalTime = a.submitted_at || a.created_at
return new Date(vetoTime) > new Date(approvalTime) || a.user !== v.user
})
})
Copy link
Author

Choose a reason for hiding this comment

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

This is probably not the most efficient way to filter but IMO rather explicit. As the number of comments wouldn't be any large, these operations would be quick. This can be extracted to a separate function on the one hand, on the other it would be slightly weird to pass comparison operation inside, while these wouldn't be reused anywhere else. Might be a good idea to extract though, to to unit test later on.

This part also fixes (what I think is) a bug, when a user leaves-1 and then adds +1 build would be blocked unless new commit is pushed.

@@ -323,7 +352,19 @@ export default class Approval extends Check {
const user = repository.owner.login
const upstreamComments = await this.github.getComments(user, repository.name, pull_request.number, formatDate(last_push), token)
const comments = [...frozenComments, ...upstreamComments].filter((c, idx, array) => idx === array.findIndex(c2 => c.id === c2.id))
return await this.countApprovalsAndVetos(repository, pull_request, comments, config.approvals, token)

const upstreamReviews = await this.github.getReviews(user, repository.name, pull_request.number, formatDate(last_push), token)
Copy link
Author

Choose a reason for hiding this comment

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

As many other changes part getReviews is written to be consistent with getComments.


const upstreamReviews = await this.github.getReviews(user, repository.name, pull_request.number, formatDate(last_push), token)

const entries = [...comments, ...upstreamReviews].sort((a, b) => {
Copy link
Author

Choose a reason for hiding this comment

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

Comments and reviews are being combined and sorted to check if any of the -1 are overwritten by the later native Approval.

@@ -122,7 +122,7 @@ export class CheckHandler {
*/
async onEnableCheck(user, repository, type) {
const repo = repository.get('json')
const types = [type, ...repository.checks.map(c => c.type)]
const types = Array.from(new Set([type, ...repository.checks.map(c => c.type)]))
Copy link
Author

Choose a reason for hiding this comment

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

I had an error from GitHub at some point, that multiple types where being sent. This just removes possible duplicates.

.replace('${owner}', user)
.replace('${repo}', repo)
.replace('${number}', number)
const path = `${basePathFromTemplate}?per_page=100`
Copy link
Author

Choose a reason for hiding this comment

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

By default GitHub return the first 30 entries. 100 is the maximum. Also since query param is not described in the docs and doesn't work (hence filtering was written before, I assume).

Copy link
Contributor

@stoewer stoewer left a comment

Choose a reason for hiding this comment

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

Overall the the added logic to support native pull request reviews seems to work well. However, it is important that there is a feature toggle both on the server side (globally allow/ignore native reviews) and from within the .zappr.yaml to configure the behavior per repository. When no extra configuration is added zappr should ignore native reviews and should not allow users to change this behavior per repository.

@@ -430,7 +471,7 @@ export default class Approval extends Check {
const approvals = {total: []}
const vetos = []
const status = Approval.generateStatus({approvals, vetos}, config.approvals)
await this.github.setCommitStatus(user, repoName, sha, status, token)
await this.github.setCommitStatus(user, repoName, sha, status, token) // TODO: seems unnecessary
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks redundant to me too

@@ -384,10 +425,10 @@ export default class Approval extends Check {
* @param dbRepoId The database ID of the affected repository
*/
async execute(config, event, hookPayload, token, dbRepoId) {
const {action, repository, pull_request, number, issue} = hookPayload
const {action, repository, pull_request = {}, number = pull_request.number} = hookPayload
Copy link
Contributor

Choose a reason for hiding this comment

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

When the default value pull_request = {} is applied, number is undefined. I a relatively huge function like this it is not obvious whether this is harmful or not.

@@ -8,7 +8,7 @@ export const PING = 'ping'
*/
export const COMMIT_COMMENT = 'commit_comment'
/**
* Any time a Commit is commented on.
* Any time a Commit is commented on. TODO: Mistake, copied from above?
Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, looks like a c&p error.

@GeorgySerga
Copy link
Author

@stoewer Thank you for the review. I'll try to comment/fix issues asap, but it might take longer than usual as I'm taking a long vacation soon.

@louis993546
Copy link

@GeorgySerga are you still working on this PR? if not maybe I can give it a shot?

@GeorgySerga
Copy link
Author

@louistsaitszho Hello! You're right, I've been lazy :) The code worked for me (counts native approvals and +1s), but in order to go through: need to make CR changes, write tests, add a toggle and update readme here, I think. If you want to contribute, sure thing, I can help as well, explaining some decisions, or setting things up (4 months passed, wow).

@red-avtovo
Copy link

3 more years passed. Is there any update on that?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

count github native approvals
4 participants