add reviewer assigning
This commit is contained in:
102
github.go
102
github.go
@@ -30,6 +30,12 @@ type GitHubPullRequestWriteService interface {
|
||||
UpdatePullRequest(context.Context, string, PullRequestMetadata) (PullRequestMetadata, error)
|
||||
}
|
||||
|
||||
type GitHubPullRequestPeopleWriteService interface {
|
||||
UpdatePullRequestPeople(
|
||||
context.Context, string, string, int, PullRequestPeopleUpdate,
|
||||
) (PullRequestPeople, error)
|
||||
}
|
||||
|
||||
type GitHubMergeService interface {
|
||||
SetPullRequestAutoMerge(context.Context, string, string, string, bool) (*AutoMergeRequest, error)
|
||||
MergePullRequest(context.Context, string, string, string) (PullRequestMergeResult, error)
|
||||
@@ -39,6 +45,10 @@ type GitHubBranchService interface {
|
||||
ListBranches(context.Context, string, string) ([]RepositoryBranch, error)
|
||||
}
|
||||
|
||||
type GitHubRepositoryPeopleService interface {
|
||||
ListRepositoryUsers(context.Context, string, string) ([]RepositoryUser, error)
|
||||
}
|
||||
|
||||
type GitHubEnrichmentService interface {
|
||||
EnrichPullRequest(context.Context, PRDetails) PRDetailsEnrichment
|
||||
}
|
||||
@@ -464,7 +474,10 @@ query PullRequestDetails($owner: String!, $name: String!, $number: Int!) {
|
||||
}
|
||||
}
|
||||
author { login }
|
||||
assignees(first: 20) { nodes { login } }
|
||||
assignees(first: 100) {
|
||||
pageInfo { hasNextPage endCursor }
|
||||
nodes { id login name }
|
||||
}
|
||||
labels(first: 20) { nodes { name } }
|
||||
milestone { title }
|
||||
additions deletions changedFiles
|
||||
@@ -565,6 +578,18 @@ query TimelinePage($owner: String!, $name: String!, $number: Int!, $after: Strin
|
||||
}
|
||||
}`
|
||||
|
||||
const assigneesPageQuery = `
|
||||
query AssigneesPage($owner: String!, $name: String!, $number: Int!, $after: String) {
|
||||
repository(owner: $owner, name: $name) {
|
||||
pullRequest(number: $number) {
|
||||
assignees(first: 100, after: $after) {
|
||||
pageInfo { hasNextPage endCursor }
|
||||
nodes { id login name }
|
||||
}
|
||||
}
|
||||
}
|
||||
}`
|
||||
|
||||
const checkContextsPageQuery = `
|
||||
query CheckContextsPage($id: ID!, $after: String) {
|
||||
node(id: $id) {
|
||||
@@ -722,6 +747,11 @@ type githubPRCommentConnection struct {
|
||||
Nodes []githubPRComment `json:"nodes"`
|
||||
}
|
||||
|
||||
type githubUserConnection struct {
|
||||
PageInfo githubPageInfo `json:"pageInfo"`
|
||||
Nodes []githubActor `json:"nodes"`
|
||||
}
|
||||
|
||||
type githubReviewSummary struct {
|
||||
ID, Body, State, URL string
|
||||
SubmittedAt time.Time
|
||||
@@ -819,10 +849,8 @@ type githubPullRequestDetails struct {
|
||||
Position, EstimatedTimeToMerge int
|
||||
EnqueuedAt time.Time
|
||||
}
|
||||
Assignees struct {
|
||||
Nodes []githubActor `json:"nodes"`
|
||||
}
|
||||
Labels struct {
|
||||
Assignees githubUserConnection
|
||||
Labels struct {
|
||||
Nodes []struct {
|
||||
Name string `json:"name"`
|
||||
} `json:"nodes"`
|
||||
@@ -954,6 +982,36 @@ func (c *GitHubClient) allConversationComments(
|
||||
return nodes, nil
|
||||
}
|
||||
|
||||
func (c *GitHubClient) allAssignees(
|
||||
ctx context.Context, owner, name string, number int, connection githubUserConnection,
|
||||
) ([]githubActor, error) {
|
||||
nodes := append([]githubActor(nil), connection.Nodes...)
|
||||
for pages := 0; connection.PageInfo.HasNextPage; pages++ {
|
||||
if pages >= 100 {
|
||||
return nil, errors.New("assignee pagination exceeded 100 pages")
|
||||
}
|
||||
var data struct {
|
||||
Repository *struct {
|
||||
PullRequest *struct {
|
||||
Assignees githubUserConnection `json:"assignees"`
|
||||
} `json:"pullRequest"`
|
||||
} `json:"repository"`
|
||||
}
|
||||
if err := c.query(ctx, assigneesPageQuery, map[string]any{
|
||||
"owner": owner, "name": name, "number": number,
|
||||
"after": connection.PageInfo.EndCursor,
|
||||
}, &data); err != nil {
|
||||
return nil, fmt.Errorf("load more assignees: %w", err)
|
||||
}
|
||||
if data.Repository == nil || data.Repository.PullRequest == nil {
|
||||
return nil, errors.New("pull request disappeared while loading assignees")
|
||||
}
|
||||
connection = data.Repository.PullRequest.Assignees
|
||||
nodes = append(nodes, connection.Nodes...)
|
||||
}
|
||||
return nodes, nil
|
||||
}
|
||||
|
||||
func (c *GitHubClient) allReviewSummaries(
|
||||
ctx context.Context, owner, name string, number int, connection githubReviewSummaryConnection,
|
||||
) ([]githubReviewSummary, error) {
|
||||
@@ -1112,22 +1170,30 @@ func (c *GitHubClient) GetPullRequest(ctx context.Context, owner, name string, n
|
||||
node := data.Repository.PullRequest
|
||||
var (
|
||||
threadNodes []githubReviewThread
|
||||
assigneeNodes []githubActor
|
||||
conversationNodes []githubPRComment
|
||||
reviewNodes []githubReviewSummary
|
||||
timelineNodes []githubTimelineNode
|
||||
checkNodes []githubCheckContext
|
||||
threadErr error
|
||||
assigneeErr error
|
||||
conversationErr error
|
||||
reviewErr error
|
||||
timelineErr error
|
||||
checkErr error
|
||||
wait sync.WaitGroup
|
||||
)
|
||||
wait.Add(4)
|
||||
wait.Add(5)
|
||||
go func() {
|
||||
defer wait.Done()
|
||||
threadNodes, threadErr = c.allReviewThreads(ctx, owner, name, number, node.ReviewThreads)
|
||||
}()
|
||||
go func() {
|
||||
defer wait.Done()
|
||||
assigneeNodes, assigneeErr = c.allAssignees(
|
||||
ctx, owner, name, number, node.Assignees,
|
||||
)
|
||||
}()
|
||||
go func() {
|
||||
defer wait.Done()
|
||||
conversationNodes, conversationErr = c.allConversationComments(ctx, owner, name, number, node.Comments)
|
||||
@@ -1152,6 +1218,9 @@ func (c *GitHubClient) GetPullRequest(ctx context.Context, owner, name string, n
|
||||
if threadErr != nil {
|
||||
threadNodes = append([]githubReviewThread(nil), node.ReviewThreads.Nodes...)
|
||||
}
|
||||
if assigneeErr != nil {
|
||||
assigneeNodes = append([]githubActor(nil), node.Assignees.Nodes...)
|
||||
}
|
||||
if conversationErr != nil {
|
||||
conversationNodes = append([]githubPRComment(nil), node.Comments.Nodes...)
|
||||
}
|
||||
@@ -1186,6 +1255,7 @@ func (c *GitHubClient) GetPullRequest(ctx context.Context, owner, name string, n
|
||||
Permissions: ViewerPermissions{
|
||||
Repository: data.Repository.ViewerPermission,
|
||||
CanUpdatePR: node.ViewerCanUpdate, CanReact: node.ViewerCanReact,
|
||||
CanAssign: viewerCanAssign(data.Repository.ViewerPermission),
|
||||
CanSubscribe: node.ViewerCanSubscribe, CanEnableMerge: node.ViewerCanEnableAutoMerge,
|
||||
CanDisableMerge: node.ViewerCanDisableAutoMerge,
|
||||
},
|
||||
@@ -1211,7 +1281,8 @@ func (c *GitHubClient) GetPullRequest(ctx context.Context, owner, name string, n
|
||||
}
|
||||
for component, err := range map[string]error{
|
||||
"review threads": threadErr, "conversation": conversationErr,
|
||||
"submitted reviews": reviewErr, "timeline": timelineErr, "checks": checkErr,
|
||||
"submitted reviews": reviewErr, "assignees": assigneeErr,
|
||||
"timeline": timelineErr, "checks": checkErr,
|
||||
} {
|
||||
if err != nil {
|
||||
details.DataIssues = append(details.DataIssues, DataIssue{
|
||||
@@ -1260,7 +1331,7 @@ func (c *GitHubClient) GetPullRequest(ctx context.Context, owner, name string, n
|
||||
if node.Milestone != nil {
|
||||
details.Milestone = node.Milestone.Title
|
||||
}
|
||||
for _, assignee := range node.Assignees.Nodes {
|
||||
for _, assignee := range assigneeNodes {
|
||||
details.Assignees = append(details.Assignees, assignee.Login)
|
||||
}
|
||||
reviewers := map[string]string{}
|
||||
@@ -1269,6 +1340,11 @@ func (c *GitHubClient) GetPullRequest(ctx context.Context, owner, name string, n
|
||||
if login != "" {
|
||||
reviewers[login] = "REVIEW_REQUESTED"
|
||||
}
|
||||
if request.RequestedReviewer.Login != "" {
|
||||
details.RequestedReviewers = append(
|
||||
details.RequestedReviewers, request.RequestedReviewer.Login,
|
||||
)
|
||||
}
|
||||
}
|
||||
for _, review := range node.LatestReviews.Nodes {
|
||||
if review.Author != nil {
|
||||
@@ -1279,6 +1355,7 @@ func (c *GitHubClient) GetPullRequest(ctx context.Context, owner, name string, n
|
||||
details.Reviewers = append(details.Reviewers, Reviewer{Login: login, State: state})
|
||||
}
|
||||
sort.Slice(details.Reviewers, func(i, j int) bool { return details.Reviewers[i].Login < details.Reviewers[j].Login })
|
||||
sort.Strings(details.RequestedReviewers)
|
||||
if len(node.Commits.Nodes) > 0 && node.Commits.Nodes[0].Commit.StatusCheckRollup != nil {
|
||||
rollup := node.Commits.Nodes[0].Commit.StatusCheckRollup
|
||||
details.CheckState = rollup.State
|
||||
@@ -1646,6 +1723,15 @@ func actorLogin(actor *githubActor) string {
|
||||
return actor.Login
|
||||
}
|
||||
|
||||
func viewerCanAssign(permission string) bool {
|
||||
switch strings.ToUpper(permission) {
|
||||
case "TRIAGE", "WRITE", "MAINTAIN", "ADMIN":
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func intValue(value *int) int {
|
||||
if value == nil {
|
||||
return 0
|
||||
|
||||
Reference in New Issue
Block a user