Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions api/export_pr.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,25 @@ func (pr *PullRequest) ExportData(fields []string) map[string]interface{} {
}
}
data[f] = &requests
case "closingIssuesReferences":
items := make([]map[string]interface{}, 0, len(pr.ClosingIssuesReferences.Nodes))
for _, n := range pr.ClosingIssuesReferences.Nodes {
items = append(items, map[string]interface{}{

"id": n.ID,
"number": n.Number,
"url": n.URL,
"repository": map[string]interface{}{
"id": n.Repository.ID,
"name": n.Repository.Name,
"owner": map[string]interface{}{
"id": n.Repository.Owner.ID,
"login": n.Repository.Owner.Login,
},
},
})
Comment on lines +145 to +158
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I wanted to refactor this plain map into a temporary type with json tags on it, but then noticed the other fields (other cases in the switch-statement) are using the same approach. So, let's leave it as is to keep it consistent with the rest of the code. Thanks, again.

}
data[f] = items
default:
sf := fieldByName(v, f)
data[f] = sf.Interface()
Expand Down
64 changes: 64 additions & 0 deletions api/export_pr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,70 @@ func TestPullRequest_ExportData(t *testing.T) {
}
`),
},
{
name: "linked issues",
fields: []string{"closingIssuesReferences"},
inputJSON: heredoc.Doc(`
{ "closingIssuesReferences": { "nodes": [
{
"id": "I_123",
"number": 123,
"url": "https://github.com/cli/cli/issues/123",
"repository": {
"id": "R_123",
"name": "cli",
"owner": {
"id": "O_123",
"login": "cli"
}
}
},
{
"id": "I_456",
"number": 456,
"url": "https://github.com/cli/cli/issues/456",
"repository": {
"id": "R_456",
"name": "cli",
"owner": {
"id": "O_456",
"login": "cli"
}
}
}
] } }
`),
outputJSON: heredoc.Doc(`
{ "closingIssuesReferences": [
{
"id": "I_123",
"number": 123,
"repository": {
"id": "R_123",
"name": "cli",
"owner": {
"id": "O_123",
"login": "cli"
}
},
"url": "https://github.com/cli/cli/issues/123"
},
{
"id": "I_456",
"number": 456,
"repository": {
"id": "R_456",
"name": "cli",
"owner": {
"id": "O_456",
"login": "cli"
}
},
"url": "https://github.com/cli/cli/issues/456"
}
] }
`),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down
22 changes: 22 additions & 0 deletions api/queries_pr.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ type PullRequest struct {
Reviews PullRequestReviews
LatestReviews PullRequestReviews
ReviewRequests ReviewRequests

ClosingIssuesReferences ClosingIssuesReferences
}

type StatusCheckRollupNode struct {
Expand All @@ -107,6 +109,26 @@ type CommitStatusCheckRollup struct {
Contexts CheckContexts
}

type ClosingIssuesReferences struct {
Nodes []struct {
ID string
Number int
URL string
Repository struct {
ID string
Name string
Owner struct {
ID string
Login string
}
}
}
PageInfo struct {
HasNextPage bool
EndCursor string
}
}

// https://docs.github.com/en/graphql/reference/enums#checkrunstate
type CheckRunState string

Expand Down
22 changes: 22 additions & 0 deletions api/query_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,25 @@ var prCommits = shortenQuery(`
}
`)

var prClosingIssuesReferences = shortenQuery(`
closingIssuesReferences(first: 100) {
nodes {
id,
number,
url,
repository {
id,
name,
owner {
id,
login
}
}
}
pageInfo{hasNextPage,endCursor}
}
`)

var autoMergeRequest = shortenQuery(`
autoMergeRequest {
authorEmail,
Expand Down Expand Up @@ -287,6 +306,7 @@ var PullRequestFields = append(sharedIssuePRFields,
"baseRefName",
"baseRefOid",
"changedFiles",
"closingIssuesReferences",
"commits",
"deletions",
"files",
Expand Down Expand Up @@ -366,6 +386,8 @@ func IssueGraphQL(fields []string) string {
q = append(q, StatusCheckRollupGraphQLWithoutCountByState(""))
case "statusCheckRollupWithCountByState": // pseudo-field
q = append(q, StatusCheckRollupGraphQLWithCountByState())
case "closingIssuesReferences":
q = append(q, prClosingIssuesReferences)
default:
q = append(q, field)
}
Expand Down
44 changes: 44 additions & 0 deletions pkg/cmd/pr/shared/finder.go
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,11 @@ func (f *finder) Find(opts FindOptions) (*api.PullRequest, ghrepo.Interface, err
return preloadPrComments(httpClient, f.baseRefRepo, pr)
})
}
if fields.Contains("closingIssuesReferences") {
g.Go(func() error {
return preloadPrClosingIssuesReferences(httpClient, f.baseRefRepo, pr)
})
}
if fields.Contains("statusCheckRollup") {
g.Go(func() error {
return preloadPrChecks(httpClient, f.baseRefRepo, pr)
Expand Down Expand Up @@ -558,6 +563,45 @@ func preloadPrComments(client *http.Client, repo ghrepo.Interface, pr *api.PullR
return nil
}

func preloadPrClosingIssuesReferences(client *http.Client, repo ghrepo.Interface, pr *api.PullRequest) error {
if !pr.ClosingIssuesReferences.PageInfo.HasNextPage {
return nil
}

type response struct {
Node struct {
PullRequest struct {
ClosingIssuesReferences api.ClosingIssuesReferences `graphql:"closingIssuesReferences(first: 100, after: $endCursor)"`
} `graphql:"...on PullRequest"`
} `graphql:"node(id: $id)"`
}

variables := map[string]interface{}{
"id": githubv4.ID(pr.ID),
"endCursor": githubv4.String(pr.ClosingIssuesReferences.PageInfo.EndCursor),
}

gql := api.NewClientFromHTTP(client)

for {
var query response
err := gql.Query(repo.RepoHost(), "closingIssuesReferences", &query, variables)
if err != nil {
return err
}

pr.ClosingIssuesReferences.Nodes = append(pr.ClosingIssuesReferences.Nodes, query.Node.PullRequest.ClosingIssuesReferences.Nodes...)

if !query.Node.PullRequest.ClosingIssuesReferences.PageInfo.HasNextPage {
break
}
variables["endCursor"] = githubv4.String(query.Node.PullRequest.ClosingIssuesReferences.PageInfo.EndCursor)
}

pr.ClosingIssuesReferences.PageInfo.HasNextPage = false
return nil
}

func preloadPrChecks(client *http.Client, repo ghrepo.Interface, pr *api.PullRequest) error {
if len(pr.StatusCheckRollup.Nodes) == 0 {
return nil
Expand Down
1 change: 1 addition & 0 deletions pkg/cmd/pr/view/view_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ func TestJSONFields(t *testing.T) {
"changedFiles",
"closed",
"closedAt",
"closingIssuesReferences",
"comments",
"commits",
"createdAt",
Expand Down
Loading