Add closedByPullRequestsReferences JSON field to issue view (#10941)
* [gh issue view] Expose `closedByPullRequestsReferences` JSON fields * Incorporate GitHub Copilot review suggestions * Incorporate review changes
This commit is contained in:
parent
315876852a
commit
ee281fd9ba
7 changed files with 187 additions and 11 deletions
|
|
@ -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()
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
@ -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)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
@ -296,6 +315,7 @@ var sharedIssuePRFields = []string{
|
|||
var issueOnlyFields = []string{
|
||||
"isPinned",
|
||||
"stateReason",
|
||||
"closedByPullRequestsReferences",
|
||||
}
|
||||
|
||||
var IssueFields = append(sharedIssuePRFields, issueOnlyFields...)
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package view
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
|
|
@ -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())
|
||||
|
|
@ -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)
|
||||
}
|
||||
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 {
|
||||
err := preloadIssueComments(httpClient, baseRepo, issue)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
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() {
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ func TestJSONFields(t *testing.T) {
|
|||
"body",
|
||||
"closed",
|
||||
"comments",
|
||||
"closedByPullRequestsReferences",
|
||||
"createdAt",
|
||||
"closedAt",
|
||||
"id",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue