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: 18 additions & 1 deletion api/export_pr.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,24 @@ func (issue *Issue) ExportData(fields []string) map[string]interface{} {
})
}
data[f] = items
case "closedByPullRequestsReferences":
items := make([]map[string]interface{}, 0, len(issue.ClosedByPullRequestsReferences.Nodes))
for _, n := range issue.ClosedByPullRequestsReferences.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,
},
},
})
}
data[f] = items
default:
sf := fieldByName(v, f)
data[f] = sf.Interface()
Expand Down Expand Up @@ -143,7 +161,6 @@ func (pr *PullRequest) ExportData(fields []string) map[string]interface{} {
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,
Expand Down
73 changes: 72 additions & 1 deletion api/export_pr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,70 @@ func TestIssue_ExportData(t *testing.T) {
}
`),
},
{
name: "linked pull requests",
fields: []string{"closedByPullRequestsReferences"},
inputJSON: heredoc.Doc(`
{ "closedByPullRequestsReferences": { "nodes": [
{
"id": "I_123",
"number": 123,
"url": "https://github.com/cli/cli/pull/123",
"repository": {
"id": "R_123",
"name": "cli",
"owner": {
"id": "O_123",
"login": "cli"
}
}
},
{
"id": "I_456",
"number": 456,
"url": "https://github.com/cli/cli/pull/456",
"repository": {
"id": "R_456",
"name": "cli",
"owner": {
"id": "O_456",
"login": "cli"
}
}
}
] } }
`),
outputJSON: heredoc.Doc(`
{ "closedByPullRequestsReferences": [
{
"id": "I_123",
"number": 123,
"repository": {
"id": "R_123",
"name": "cli",
"owner": {
"id": "O_123",
"login": "cli"
}
},
"url": "https://github.com/cli/cli/pull/123"
},
{
"id": "I_456",
"number": 456,
"repository": {
"id": "R_456",
"name": "cli",
"owner": {
"id": "O_456",
"login": "cli"
}
},
"url": "https://github.com/cli/cli/pull/456"
}
] }
`),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand All @@ -120,7 +184,14 @@ func TestIssue_ExportData(t *testing.T) {
enc := json.NewEncoder(&buf)
enc.SetIndent("", "\t")
require.NoError(t, enc.Encode(exported))
assert.Equal(t, tt.outputJSON, buf.String())

var gotData interface{}
dec = json.NewDecoder(&buf)
require.NoError(t, dec.Decode(&gotData))
var expectData interface{}
require.NoError(t, json.Unmarshal([]byte(tt.outputJSON), &expectData))

assert.Equal(t, expectData, gotData)
})
}
}
Expand Down
22 changes: 22 additions & 0 deletions api/queries_issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,28 @@ type Issue struct {
Milestone *Milestone
ReactionGroups ReactionGroups
IsPinned bool

ClosedByPullRequestsReferences ClosedByPullRequestsReferences
}

type ClosedByPullRequestsReferences 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
}
}

// return values for Issue.Typename
Expand Down
22 changes: 22 additions & 0 deletions api/query_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,25 @@ var issueCommentLast = shortenQuery(`
}
`)

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

var prReviewRequests = shortenQuery(`
reviewRequests(first: 100) {
nodes {
Expand Down Expand Up @@ -296,6 +315,7 @@ var sharedIssuePRFields = []string{
var issueOnlyFields = []string{
"isPinned",
"stateReason",
"closedByPullRequestsReferences",
}

var IssueFields = append(sharedIssuePRFields, issueOnlyFields...)
Expand Down Expand Up @@ -388,6 +408,8 @@ func IssueGraphQL(fields []string) string {
q = append(q, StatusCheckRollupGraphQLWithCountByState())
case "closingIssuesReferences":
q = append(q, prClosingIssuesReferences)
case "closedByPullRequestsReferences":
q = append(q, issueClosedByPullRequestsReferences)
default:
q = append(q, field)
}
Expand Down
39 changes: 39 additions & 0 deletions pkg/cmd/issue/view/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,42 @@ func preloadIssueComments(client *http.Client, repo ghrepo.Interface, issue *api
issue.Comments.PageInfo.HasNextPage = false
return nil
}

func preloadClosedByPullRequestsReferences(client *http.Client, repo ghrepo.Interface, issue *api.Issue) error {
if !issue.ClosedByPullRequestsReferences.PageInfo.HasNextPage {
return nil
}

type response struct {
Node struct {
Issue struct {
ClosedByPullRequestsReferences api.ClosedByPullRequestsReferences `graphql:"closedByPullRequestsReferences(first: 100, after: $endCursor)"`
} `graphql:"...on Issue"`
} `graphql:"node(id: $id)"`
}

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

gql := api.NewClientFromHTTP(client)

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

issue.ClosedByPullRequestsReferences.Nodes = append(issue.ClosedByPullRequestsReferences.Nodes, query.Node.Issue.ClosedByPullRequestsReferences.Nodes...)

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

issue.ClosedByPullRequestsReferences.PageInfo.HasNextPage = false
return nil
}
20 changes: 12 additions & 8 deletions pkg/cmd/issue/view/view.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package view

import (
"errors"
"fmt"
"io"
"net/http"
Expand Down Expand Up @@ -134,6 +133,8 @@ func viewRun(opts *ViewOptions) error {
opts.IO.DetectTerminalTheme()

opts.IO.StartProgressIndicator()
defer opts.IO.StopProgressIndicator()

lookupFields.Add("id")

issue, err := issueShared.FindIssueOrPR(httpClient, baseRepo, opts.IssueNumber, lookupFields.ToSlice())
Expand All @@ -144,18 +145,21 @@ func viewRun(opts *ViewOptions) error {
if lookupFields.Contains("comments") {
// FIXME: this re-fetches the comments connection even though the initial set of 100 were
// fetched in the previous request.
err = preloadIssueComments(httpClient, baseRepo, issue)
err := preloadIssueComments(httpClient, baseRepo, issue)
if err != nil {
return err
}
}
opts.IO.StopProgressIndicator()
if err != nil {
var loadErr *issueShared.PartialLoadError
if opts.Exporter == nil && errors.As(err, &loadErr) {
fmt.Fprintf(opts.IO.ErrOut, "warning: %s\n", loadErr.Error())
} else {

if lookupFields.Contains("closedByPullRequestsReferences") {
err := preloadClosedByPullRequestsReferences(httpClient, baseRepo, issue)
if err != nil {
return err
}
}

opts.IO.StopProgressIndicator()

if opts.WebMode {
openURL := issue.URL
if opts.IO.IsStdoutTTY() {
Expand Down
1 change: 1 addition & 0 deletions pkg/cmd/issue/view/view_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ func TestJSONFields(t *testing.T) {
"body",
"closed",
"comments",
"closedByPullRequestsReferences",
"createdAt",
"closedAt",
"id",
Expand Down
Loading