Skip to content

Commit 29fd429

Browse files
Add comment information about how to correctly specify co-authors if any co-author is not found
Signed-off-by: Lukasz Gryglicki <[email protected]> Assisted by [OpenAI](https://platform.openai.com/) Assisted by [GitHub Copilot](https://github.com/features/copilot)
1 parent 0705843 commit 29fd429

File tree

5 files changed

+136
-42
lines changed

5 files changed

+136
-42
lines changed

cla-backend-go/github/github_repository.go

Lines changed: 59 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,31 @@ var (
3131
GithubUsernameRegex = regexp.MustCompile(`^[A-Za-z0-9-]{3,39}$`)
3232
)
3333

34+
// Note: we use | and ||| as placeholders for inline and fenced code, then swap to backticks at render time.
35+
const MissingCoAuthorsMessage = `
36+
37+
One or more co-authors of this pull request were not found. You must specify co-authors in commit message trailer via:
38+
39+
|||
40+
Co-authored-by: name <email>
41+
|||
42+
43+
Supported |Co-authored-by:| formats include:
44+
45+
1) |Anything <[email protected]>| - it will locate your GitHub user by |id| part.
46+
2) |Anything <[email protected]>| - it will locate your GitHub user by |login| part.
47+
3) |Anything <public-email>| - it will locate your GitHub user by |public-email| part. Note that this email must be made public on Github.
48+
4) |Anything <other-email>| - it will locate your GitHub user by |other-email| part but only if that email was used before for any other CLA as a main commit author.
49+
5) |login <any-valid-email>| - it will locate your GitHub user by |login| part, note that |login| part must be at least 3 characters long.
50+
51+
Please update your commit message(s) by doing |git commit --amend| and then |git push [--force]| and then request re-running CLA check via commenting on this pull request:
52+
53+
|||
54+
/easycla
55+
|||
56+
57+
`
58+
3459
const (
3560
help = "https://help.github.com/en/github/committing-changes-to-your-project/why-are-my-commits-linked-to-the-wrong-user"
3661
unknown = "Unknown"
@@ -351,17 +376,22 @@ func ExpandWithCoAuthors(
351376
pr int,
352377
installationID int64,
353378
commitAuthors *[]*UserCommitSummary,
354-
) {
379+
) bool {
355380
f := logrus.Fields{
356381
"functionName": "github.github_repository.ExpandWithCoAuthors",
357382
"pr": pr,
358383
}
359384
coAuthors := GetCoAuthorsFromCommit(ctx, commit)
360385
log.WithFields(f).Debugf("co-authors found: %s", coAuthors)
386+
missing := false
361387
for _, coAuthor := range coAuthors {
362-
summary := GetCoAuthorCommits(ctx, client, usersService, coAuthor, commit, pr, installationID)
388+
summary, found := GetCoAuthorCommits(ctx, client, usersService, coAuthor, commit, pr, installationID)
363389
*commitAuthors = append(*commitAuthors, summary)
390+
if !missing && !found {
391+
missing = true
392+
}
364393
}
394+
return missing
365395
}
366396

367397
// IsValidGitHubUsername checks if the provided username is a valid GitHub username.
@@ -387,7 +417,7 @@ func GetCoAuthorCommits(
387417
commit *github.RepositoryCommit,
388418
pr int,
389419
installationID int64,
390-
) *UserCommitSummary {
420+
) (*UserCommitSummary, bool) {
391421
f := logrus.Fields{
392422
"functionName": "github.github_repository.GetCoAuthorCommits",
393423
"pr": pr,
@@ -409,6 +439,7 @@ func GetCoAuthorCommits(
409439
cacheKey := [2]string{lName, email}
410440
if cachedUser, ok := GithubUserCache.Get(cacheKey); ok {
411441
log.WithFields(f).Debugf("GitHub user found in cache for name/email: %s/%s: %+v", name, email, cachedUser)
442+
found := false
412443
var summary *UserCommitSummary
413444
if cachedUser != nil {
414445
summary = &UserCommitSummary{
@@ -417,6 +448,7 @@ func GetCoAuthorCommits(
417448
Affiliated: false,
418449
Authorized: false,
419450
}
451+
found = cachedUser.ID != nil
420452
} else {
421453
summary = &UserCommitSummary{
422454
SHA: utils.StringValue(commit.SHA),
@@ -431,7 +463,7 @@ func GetCoAuthorCommits(
431463
}
432464
}
433465
log.WithFields(f).Debugf("PR: %d, %+v (from cache)", pr, summary)
434-
return summary
466+
return summary, found
435467
}
436468

437469
log.WithFields(f).Debugf("Getting co-author details: %+v", coAuthor)
@@ -528,12 +560,14 @@ func GetCoAuthorCommits(
528560
log.WithFields(f).Debugf("Co-author: %v, user: %+v", coAuthor, user)
529561

530562
var summary *UserCommitSummary
563+
found := false
531564
if user != nil {
532565
if user.Login != nil {
533566
login = *user.Login
534567
}
535568
if user.ID != nil {
536569
githubID = *user.ID
570+
found = true
537571
}
538572
if user.Name == nil || (user.Name != nil && strings.TrimSpace(*user.Name) == "") {
539573
user.Name = &name
@@ -565,10 +599,10 @@ func GetCoAuthorCommits(
565599
}
566600

567601
GithubUserCache.Set(cacheKey, user)
568-
return summary
602+
return summary, found
569603
}
570604

571-
func GetPullRequestCommitAuthors(ctx context.Context, usersService users.Service, installationID int64, pullRequestID int, owner, repo string, withCoAuthors bool) ([]*UserCommitSummary, *string, error) {
605+
func GetPullRequestCommitAuthors(ctx context.Context, usersService users.Service, installationID int64, pullRequestID int, owner, repo string, withCoAuthors bool) ([]*UserCommitSummary, *string, bool, error) {
572606
f := logrus.Fields{
573607
"functionName": "github.github_repository.GetPullRequestCommitAuthors",
574608
"pullRequestID": pullRequestID,
@@ -579,21 +613,22 @@ func GetPullRequestCommitAuthors(ctx context.Context, usersService users.Service
579613
client, err := NewGithubAppClient(installationID)
580614
if err != nil {
581615
log.WithFields(f).WithError(err).Warn("unable to create Github client")
582-
return nil, nil, err
616+
return nil, nil, false, err
583617
}
584618

585619
commits, resp, comErr := client.PullRequests.ListCommits(ctx, owner, repo, pullRequestID, &github.ListOptions{})
586620
if comErr != nil {
587621
log.WithFields(f).WithError(comErr).Warnf("problem listing commits for repo: %s/%s pull request: %d", owner, repo, pullRequestID)
588-
return nil, nil, comErr
622+
return nil, nil, false, comErr
589623
}
590624
if resp.StatusCode != http.StatusOK {
591625
msg := fmt.Sprintf("unexpected status code: %d - expected: %d", resp.StatusCode, http.StatusOK)
592626
log.WithFields(f).Warn(msg)
593-
return nil, nil, errors.New(msg)
627+
return nil, nil, false, errors.New(msg)
594628
}
595629

596630
log.WithFields(f).Debugf("found %d commits for pull request: %d", len(commits), pullRequestID)
631+
anyMissing := false
597632
for _, commit := range commits {
598633
log.WithFields(f).Debugf("loaded commit: %+v", commit)
599634
commitAuthor := ""
@@ -623,7 +658,10 @@ func GetPullRequestCommitAuthors(ctx context.Context, usersService users.Service
623658
Authorized: false,
624659
})
625660
if withCoAuthors {
626-
ExpandWithCoAuthors(ctx, client, usersService, commit, pullRequestID, installationID, &userCommitSummary)
661+
missing := ExpandWithCoAuthors(ctx, client, usersService, commit, pullRequestID, installationID, &userCommitSummary)
662+
if !anyMissing && missing {
663+
anyMissing = true
664+
}
627665
}
628666
}
629667

@@ -636,10 +674,10 @@ func GetPullRequestCommitAuthors(ctx context.Context, usersService users.Service
636674
// }
637675
// log.WithFields(f).Debugf("user commit summary: %+v", *summary)
638676
//}
639-
return userCommitSummary, latestCommitSHA, nil
677+
return userCommitSummary, latestCommitSHA, anyMissing, nil
640678
}
641679

642-
func UpdatePullRequest(ctx context.Context, installationID int64, pullRequestID int, owner, repo string, repoID *int64, latestSHA string, signed []*UserCommitSummary, missing []*UserCommitSummary, CLABaseAPIURL, CLALandingPage, CLALogoURL string) error {
680+
func UpdatePullRequest(ctx context.Context, installationID int64, pullRequestID int, owner, repo string, repoID *int64, latestSHA string, signed []*UserCommitSummary, missing []*UserCommitSummary, anyMissing bool, CLABaseAPIURL, CLALandingPage, CLALogoURL string) error {
643681
f := logrus.Fields{
644682
"functionName": "github.github_repository.UpdatePullRequest",
645683
"installationID": installationID,
@@ -670,7 +708,7 @@ func UpdatePullRequest(ctx context.Context, installationID int64, pullRequestID
670708
return failedErr
671709
}
672710

673-
body := assembleCLAComment(ctx, int(installationID), pullRequestID, repoID, signed, missing, CLABaseAPIURL, CLALogoURL, CLALandingPage)
711+
body := assembleCLAComment(ctx, int(installationID), pullRequestID, repoID, signed, missing, anyMissing, CLABaseAPIURL, CLALogoURL, CLALandingPage)
674712

675713
if len(missing) == 0 {
676714
// All contributors are passing
@@ -701,7 +739,7 @@ func UpdatePullRequest(ctx context.Context, installationID int64, pullRequestID
701739
// If we have previously succeeded, then we also need to update the comment (pass => fail)
702740
log.WithFields(f).Debugf("Found previously succeeeded checks - updating the CLA comment in the PR : %d", pullRequestID)
703741
// Generate a new comment with all the failed CLA info
704-
failedComment := assembleCLAComment(ctx, int(installationID), pullRequestID, repoID, signed, missing, CLABaseAPIURL, CLALogoURL, CLALandingPage)
742+
failedComment := assembleCLAComment(ctx, int(installationID), pullRequestID, repoID, signed, missing, anyMissing, CLABaseAPIURL, CLALogoURL, CLALandingPage)
705743
previousSucceededComment.Body = &failedComment
706744
_, _, err = client.Issues.EditComment(ctx, owner, repo, *previousSucceededComment.ID, previousSucceededComment)
707745
if err != nil {
@@ -818,7 +856,7 @@ func assembleCLAStatus(authorName string, signed bool) (string, string) {
818856
return authorName, "Missing CLA Authorization."
819857
}
820858

821-
func assembleCLAComment(ctx context.Context, installationID, pullRequestID int, repositoryID *int64, signed, missing []*UserCommitSummary, apiBaseURL, CLALogoURL, CLALandingPage string) string {
859+
func assembleCLAComment(ctx context.Context, installationID, pullRequestID int, repositoryID *int64, signed, missing []*UserCommitSummary, anyMissing bool, apiBaseURL, CLALogoURL, CLALandingPage string) string {
822860
f := logrus.Fields{
823861
"functionName": "github.github_repository.assembleCLAComment",
824862
utils.XREQUESTID: ctx.Value(utils.XREQUESTID),
@@ -838,13 +876,13 @@ func assembleCLAComment(ctx context.Context, installationID, pullRequestID int,
838876

839877
log.WithFields(f).Debug("Building CLAComment body ")
840878
signURL := getFullSignURL(repositoryType, strconv.Itoa(installationID), strconv.Itoa(int(*repositoryID)), strconv.Itoa(pullRequestID), apiBaseURL)
841-
commentBody := getCommentBody(repositoryType, signURL, signed, missing)
879+
commentBody := getCommentBody(repositoryType, signURL, signed, missing, anyMissing)
842880
allSigned := len(missing) == 0
843881
badge := getCommentBadge(allSigned, signURL, missingID, false, CLALandingPage, CLALogoURL)
844882
return fmt.Sprintf("%s<br >%s", badge, commentBody)
845883
}
846884

847-
func getCommentBody(repositoryType, signURL string, signed, missing []*UserCommitSummary) string {
885+
func getCommentBody(repositoryType, signURL string, signed, missing []*UserCommitSummary, anyMissing bool) string {
848886
f := logrus.Fields{
849887
"functionName": "github.github_repository:getCommentBody",
850888
"repositoryType": repositoryType,
@@ -916,6 +954,10 @@ func getCommentBody(repositoryType, signURL string, signed, missing []*UserCommi
916954
text = "<br>The committers listed above are authorized under a signed CLA."
917955
}
918956

957+
if anyMissing {
958+
committersComment.WriteString(strings.ReplaceAll(MissingCoAuthorsMessage, "|", "`"))
959+
log.WithFields(f).Debug("some co-authors are missing for this PR, added the missing co-author message")
960+
}
919961
return fmt.Sprintf("%s%s", committersComment.String(), text)
920962
}
921963

cla-backend-go/signatures/service.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1023,7 +1023,7 @@ func (s service) updateChangeRequest(ctx context.Context, ghOrg *models.GithubOr
10231023
// Fetch committers
10241024
withCoAuthors := github.IsCoAuthorsEnabledForRepo(ghOrg.EnableCoAuthors, gitHubRepoName)
10251025
log.WithFields(f).Debugf("fetching commit authors for PR: %d using repository owner: %s, repo: %s", pullRequestID, gitHubOrgName, gitHubRepoName)
1026-
authors, latestSHA, authorsErr := github.GetPullRequestCommitAuthors(ctx, s.usersService, ghOrg.OrganizationInstallationID, int(pullRequestID), gitHubOrgName, gitHubRepoName, withCoAuthors)
1026+
authors, latestSHA, anyMissing, authorsErr := github.GetPullRequestCommitAuthors(ctx, s.usersService, ghOrg.OrganizationInstallationID, int(pullRequestID), gitHubOrgName, gitHubRepoName, withCoAuthors)
10271027
if authorsErr != nil {
10281028
log.WithFields(f).WithError(authorsErr).Warnf("unable to get commit authors for %s/%s for PR: %d", gitHubOrgName, gitHubRepoName, pullRequestID)
10291029
return authorsErr
@@ -1124,7 +1124,7 @@ func (s service) updateChangeRequest(ctx context.Context, ghOrg *models.GithubOr
11241124
log.WithFields(f).Debugf("commit authors status after allowlisting bots => signed: %+v, missing: %+v, allowlisted: %+v", signed, unsigned, allowlisted)
11251125

11261126
// update pull request
1127-
updateErr := github.UpdatePullRequest(ctx, ghOrg.OrganizationInstallationID, int(pullRequestID), gitHubOrgName, gitHubRepoName, githubRepository.ID, *latestSHA, signed, unsigned, s.claBaseAPIURL, s.claLandingPage, s.claLogoURL)
1127+
updateErr := github.UpdatePullRequest(ctx, ghOrg.OrganizationInstallationID, int(pullRequestID), gitHubOrgName, gitHubRepoName, githubRepository.ID, *latestSHA, signed, unsigned, anyMissing, s.claBaseAPIURL, s.claLandingPage, s.claLogoURL)
11281128
if updateErr != nil {
11291129
log.WithFields(f).Debugf("unable to update PR: %d", pullRequestID)
11301130
return updateErr

cla-backend-go/v2/sign/helpers.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ func (s service) updateChangeRequest(ctx context.Context, installationID, reposi
6161
withCoAuthors = github.IsCoAuthorsEnabledForRepo(ghOrg.EnableCoAuthors, gitHubRepoName)
6262
}
6363
log.WithFields(f).Debugf("fetching commit authors for PR: %d using repository owner: %s, repo: %s", pullRequestID, gitHubOrgName, gitHubRepoName)
64-
authors, latestSHA, authorsErr := github.GetPullRequestCommitAuthors(ctx, s.userService, installationID, int(pullRequestID), gitHubOrgName, gitHubRepoName, withCoAuthors)
64+
authors, latestSHA, anyMissing, authorsErr := github.GetPullRequestCommitAuthors(ctx, s.userService, installationID, int(pullRequestID), gitHubOrgName, gitHubRepoName, withCoAuthors)
6565
if authorsErr != nil {
6666
log.WithFields(f).WithError(authorsErr).Warnf("unable to get commit authors for %s/%s for PR: %d", gitHubOrgName, gitHubRepoName, pullRequestID)
6767
return authorsErr
@@ -164,7 +164,7 @@ func (s service) updateChangeRequest(ctx context.Context, installationID, reposi
164164
}
165165

166166
// update pull request
167-
updateErr := github.UpdatePullRequest(ctx, installationID, int(pullRequestID), gitHubOrgName, gitHubRepoName, githubRepository.ID, *latestSHA, signed, unsigned, s.ClaV1ApiURL, s.claLandingPage, s.claLogoURL)
167+
updateErr := github.UpdatePullRequest(ctx, installationID, int(pullRequestID), gitHubOrgName, gitHubRepoName, githubRepository.ID, *latestSHA, signed, unsigned, anyMissing, s.ClaV1ApiURL, s.claLandingPage, s.claLogoURL)
168168
if updateErr != nil {
169169
log.WithFields(f).Debugf("unable to update PR: %d", pullRequestID)
170170
return updateErr

0 commit comments

Comments
 (0)