Add ability to pass milestone by number

This commit is contained in:
Mislav Marohnić 2020-08-11 19:27:26 +02:00
parent 20ffa49d69
commit e12c35cc17
4 changed files with 86 additions and 21 deletions

View file

@ -4,6 +4,7 @@ import (
"context"
"encoding/base64"
"fmt"
"strconv"
"strings"
"time"
@ -250,25 +251,24 @@ func IssueList(client *Client, repo ghrepo.Interface, state string, labels []str
}
if milestoneString != "" {
milestones, err := RepoMilestones(client, repo)
if err != nil {
return nil, err
}
for i := range milestones {
if strings.EqualFold(milestones[i].Title, milestoneString) {
id, err := milestoneNodeIdToDatabaseId(milestones[i].ID)
if err != nil {
return nil, err
}
variables["milestone"] = id
break
var milestone *RepoMilestone
if milestoneNumber, err := strconv.Atoi(milestoneString); err == nil {
milestone, err = MilestoneByNumber(client, repo, milestoneNumber)
if err != nil {
return nil, err
}
} else {
milestone, err = MilestoneByTitle(client, repo, milestoneString)
if err != nil {
return nil, err
}
}
if variables["milestone"] == nil {
return nil, fmt.Errorf("no milestone found with title: %q", milestoneString)
milestoneRESTID, err := milestoneNodeIdToDatabaseId(milestone.ID)
if err != nil {
return nil, err
}
variables["milestone"] = milestoneRESTID
}
var response struct {

View file

@ -804,3 +804,43 @@ func RepoMilestones(client *Client, repo ghrepo.Interface) ([]RepoMilestone, err
return milestones, nil
}
func MilestoneByTitle(client *Client, repo ghrepo.Interface, title string) (*RepoMilestone, error) {
milestones, err := RepoMilestones(client, repo)
if err != nil {
return nil, err
}
for i := range milestones {
if strings.EqualFold(milestones[i].Title, title) {
return &milestones[i], nil
}
}
return nil, fmt.Errorf("no milestone found with title %q", title)
}
func MilestoneByNumber(client *Client, repo ghrepo.Interface, number int) (*RepoMilestone, error) {
var query struct {
Repository struct {
Milestone *RepoMilestone `graphql:"milestone(number: $number)"`
} `graphql:"repository(owner: $owner, name: $name)"`
}
variables := map[string]interface{}{
"owner": githubv4.String(repo.RepoOwner()),
"name": githubv4.String(repo.RepoName()),
"number": githubv4.Int(number),
}
gql := graphQLClient(client.http, repo.RepoHost())
err := gql.QueryNamed(context.Background(), "RepositoryMilestoneByNumber", &query, variables)
if err != nil {
return nil, err
}
if query.Repository.Milestone == nil {
return nil, fmt.Errorf("no milestone found with number '%d'", number)
}
return query.Repository.Milestone, nil
}

View file

@ -46,7 +46,7 @@ func init() {
issueListCmd.Flags().IntP("limit", "L", 30, "Maximum number of issues to fetch")
issueListCmd.Flags().StringP("author", "A", "", "Filter by author")
issueListCmd.Flags().String("mention", "", "Filter by mention")
issueListCmd.Flags().StringP("milestone", "m", "", "Filter by milestone `name`")
issueListCmd.Flags().StringP("milestone", "m", "", "Filter by milestone `number` or title")
issueCmd.AddCommand(issueViewCmd)
issueViewCmd.Flags().BoolP("web", "w", false, "Open an issue in the browser")

View file

@ -285,11 +285,8 @@ func TestIssueList_web(t *testing.T) {
func TestIssueList_milestoneNotFound(t *testing.T) {
initBlankContext("", "OWNER/REPO", "master")
http := initFakeHTTP()
defer http.Verify(t)
http.StubRepoResponse("OWNER", "REPO")
http.Register(
httpmock.GraphQL(`query IssueList\b`),
httpmock.FileResponse("../test/fixtures/issueList.json"),
)
http.Register(
httpmock.GraphQL(`query RepositoryMilestoneList\b`),
httpmock.StringResponse(`
@ -300,11 +297,39 @@ func TestIssueList_milestoneNotFound(t *testing.T) {
`))
_, err := RunCommand("issue list --milestone NotFound")
if err == nil || err.Error() != `no milestone found with title: "NotFound"` {
if err == nil || err.Error() != `no milestone found with title "NotFound"` {
t.Errorf("error running command `issue list`: %v", err)
}
}
func TestIssueList_milestoneByNumber(t *testing.T) {
initBlankContext("", "OWNER/REPO", "master")
http := initFakeHTTP()
defer http.Verify(t)
http.StubRepoResponse("OWNER", "REPO")
http.Register(
httpmock.GraphQL(`query RepositoryMilestoneByNumber\b`),
httpmock.StringResponse(`
{ "data": { "repository": { "milestone": {
"id": "MDk6TWlsZXN0b25lMTIzNDU="
} } } }
`))
http.Register(
httpmock.GraphQL(`query IssueList\b`),
httpmock.GraphQLQuery(`
{ "data": { "repository": {
"hasIssuesEnabled": true,
"issues": { "nodes": [] }
} } }`, func(_ string, params map[string]interface{}) {
assert.Equal(t, "12345", params["milestone"].(string)) // Database ID for the Milestone (see #1462)
}))
_, err := RunCommand("issue list --milestone 13")
if err != nil {
t.Fatalf("error running issue list: %v", err)
}
}
func TestIssueView_web(t *testing.T) {
initBlankContext("", "OWNER/REPO", "master")
http := initFakeHTTP()