🐛 Add GitHub committer verification (#1695)

* Add GitHub committer verification and fix empty reviewers

* update comment

* linter

* comments
This commit is contained in:
laurentsimon 2022-03-03 10:04:05 -08:00 committed by GitHub
parent 57b4664c71
commit 3c92dec81b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -16,6 +16,7 @@ package githubrepo
import (
"context"
"errors"
"fmt"
"strings"
"sync"
@ -36,6 +37,8 @@ const (
commitsToAnalyze = 30
)
var errorInvalidCommitterLogin = errors.New("cannot retrieve committer login")
// nolint: govet
type graphqlData struct {
Repository struct {
@ -58,6 +61,10 @@ type graphqlData struct {
Login *string
}
}
Signature struct {
IsValid bool
WasSignedByGitHub bool
}
AssociatedPullRequests struct {
Nodes []struct {
Repository struct {
@ -191,15 +198,26 @@ func (handler *graphqlHandler) isArchived() (bool, error) {
return handler.archived, nil
}
// nolint: unparam
func commitsFrom(data *graphqlData, repoOwner, repoName string) ([]clients.Commit, error) {
ret := make([]clients.Commit, 0)
for _, commit := range data.Repository.Object.Commit.History.Nodes {
var committer string
if commit.Committer.User.Login != nil {
// Find the commit's committer.
if commit.Committer.User.Login != nil && *commit.Committer.User.Login != "" {
committer = *commit.Committer.User.Login
} else if commit.Committer.Name != nil &&
// Username "GitHub" may indicate the commit was committed by GitHub.
// We verify that the commit is signed by GitHub, because the name can be spoofed.
*commit.Committer.Name == "GitHub" &&
commit.Signature.IsValid &&
commit.Signature.WasSignedByGitHub {
committer = "github"
}
// TODO(#1543): Figure out a way to safely get committer if `User.Login` is `nil`.
if committer == "" {
return ret, fmt.Errorf("commit %s: %w", commit.Oid, errorInvalidCommitterLogin)
}
var associatedPR clients.PullRequest
for i := range commit.AssociatedPullRequests.Nodes {
pr := commit.AssociatedPullRequests.Nodes[i]
@ -226,6 +244,9 @@ func commitsFrom(data *graphqlData, repoOwner, repoName string) ([]clients.Commi
for _, review := range pr.Reviews.Nodes {
associatedPR.Reviews = append(associatedPR.Reviews, clients.Review{
State: string(review.State),
Author: &clients.User{
Login: string(review.Author.Login),
},
})
}
break