diff --git a/api/queries_comments.go b/api/queries_comments.go index 8af17fd2a..b0450c068 100644 --- a/api/queries_comments.go +++ b/api/queries_comments.go @@ -129,7 +129,7 @@ func (c Comment) Identifier() string { } func (c Comment) AuthorLogin() string { - return c.Author.Login + return copilotDisplayName(c.Author.Login) } func (c Comment) Association() string { diff --git a/api/queries_pr_review.go b/api/queries_pr_review.go index a6fa34f9e..7f23f8b5e 100644 --- a/api/queries_pr_review.go +++ b/api/queries_pr_review.go @@ -52,7 +52,7 @@ func (prr PullRequestReview) Identifier() string { } func (prr PullRequestReview) AuthorLogin() string { - return prr.Author.Login + return copilotDisplayName(prr.Author.Login) } func (prr PullRequestReview) Association() string { @@ -158,8 +158,9 @@ func (r RequestedReviewer) DisplayName() string { if r.TypeName == teamTypeName { return fmt.Sprintf("%s/%s", r.Organization.Login, r.Slug) } - if r.TypeName == botTypeName && r.Login == CopilotReviewerLogin { - return "Copilot (AI)" + displayName := copilotDisplayName(r.Login) + if displayName != r.Login { + return displayName } if r.Name != "" { return fmt.Sprintf("%s (%s)", r.Login, r.Name) @@ -221,10 +222,7 @@ func NewReviewerBot(login string) ReviewerBot { } func (b ReviewerBot) DisplayName() string { - if b.login == CopilotReviewerLogin { - return fmt.Sprintf("%s (AI)", CopilotActorName) - } - return b.Login() + return copilotDisplayName(b.login) } func (r ReviewerBot) sealedReviewerCandidate() {} diff --git a/api/queries_repo.go b/api/queries_repo.go index d8ffa191d..31dbf75f1 100644 --- a/api/queries_repo.go +++ b/api/queries_repo.go @@ -1087,6 +1087,16 @@ const CopilotAssigneeLogin = "copilot-swe-agent" const CopilotReviewerLogin = "copilot-pull-request-reviewer" const CopilotActorName = "Copilot" +// copilotDisplayName returns "Copilot (AI)" if the login is a known Copilot bot login, +// otherwise returns the login unchanged. Use this to translate raw bot logins into +// user-friendly display names in command output. +func copilotDisplayName(login string) string { + if login == CopilotReviewerLogin || login == CopilotAssigneeLogin { + return fmt.Sprintf("%s (AI)", CopilotActorName) + } + return login +} + type AssignableActor interface { DisplayName() string ID() string @@ -1145,10 +1155,7 @@ func NewAssignableBot(id, login string) AssignableBot { } func (b AssignableBot) DisplayName() string { - if b.login == CopilotAssigneeLogin { - return fmt.Sprintf("%s (AI)", CopilotActorName) - } - return b.Login() + return copilotDisplayName(b.login) } func (b AssignableBot) ID() string { diff --git a/api/queries_repo_test.go b/api/queries_repo_test.go index ad0b8e857..928a9e885 100644 --- a/api/queries_repo_test.go +++ b/api/queries_repo_test.go @@ -563,6 +563,26 @@ func TestDisplayName(t *testing.T) { } } +func TestCopilotDisplayName(t *testing.T) { + tests := []struct { + login string + want string + }{ + {login: "copilot-pull-request-reviewer", want: "Copilot (AI)"}, + {login: "copilot-swe-agent", want: "Copilot (AI)"}, + {login: "octocat", want: "octocat"}, + {login: "", want: ""}, + } + for _, tt := range tests { + t.Run(tt.login, func(t *testing.T) { + got := copilotDisplayName(tt.login) + if got != tt.want { + t.Errorf("copilotDisplayName(%q) = %q, want %q", tt.login, got, tt.want) + } + }) + } +} + func TestRepoExists(t *testing.T) { tests := []struct { name string diff --git a/pkg/cmd/pr/view/view.go b/pkg/cmd/pr/view/view.go index 564cce913..e6ae63a10 100644 --- a/pkg/cmd/pr/view/view.go +++ b/pkg/cmd/pr/view/view.go @@ -351,7 +351,7 @@ func parseReviewers(pr api.PullRequest) []*reviewerState { for _, review := range pr.Reviews.Nodes { if review.Author.Login != pr.Author.Login { - name := review.Author.Login + name := review.AuthorLogin() if name == "" { name = ghostName } @@ -364,7 +364,7 @@ func parseReviewers(pr api.PullRequest) []*reviewerState { // Overwrite reviewer's state if a review request for the same reviewer exists. for _, reviewRequest := range pr.ReviewRequests.Nodes { - name := reviewRequest.RequestedReviewer.LoginOrSlug() + name := reviewRequest.RequestedReviewer.DisplayName() reviewerStates[name] = &reviewerState{ Name: name, State: requestedReviewState,