Add state

This commit is contained in:
Corey Johnson 2019-11-12 14:31:24 -08:00
parent 817820e464
commit 44c7495bab
5 changed files with 252 additions and 145 deletions

View file

@ -2,7 +2,6 @@ package api
import (
"fmt"
"time"
)
type PullRequestsPayload struct {
@ -24,109 +23,6 @@ type Repo interface {
RepoOwner() string
}
type IssuesPayload struct {
Assigned []Issue
Mentioned []Issue
Recent []Issue
}
type Issue struct {
Number int
Title string
URL string
}
func Issues(client *Client, ghRepo Repo, currentUsername string) (*IssuesPayload, error) {
type issues struct {
Issues struct {
Edges []struct {
Node Issue
}
}
}
type response struct {
Assigned issues
Mentioned issues
Recent issues
}
query := `
fragment issue on Issue {
number
title
}
query($owner: String!, $repo: String!, $since: DateTime!, $viewer: String!, $per_page: Int = 10) {
assigned: repository(owner: $owner, name: $repo) {
issues(filterBy: {assignee: $viewer}, first: $per_page, orderBy: {field: CREATED_AT, direction: DESC}) {
edges {
node {
...issue
}
}
}
}
mentioned: repository(owner: $owner, name: $repo) {
issues(filterBy: {mentioned: $viewer}, first: $per_page, orderBy: {field: CREATED_AT, direction: DESC}) {
edges {
node {
...issue
}
}
}
}
recent: repository(owner: $owner, name: $repo) {
issues(filterBy: {since: $since}, first: $per_page, orderBy: {field: CREATED_AT, direction: DESC}) {
edges {
node {
...issue
}
}
}
}
}
`
owner := ghRepo.RepoOwner()
repo := ghRepo.RepoName()
since := time.Now().UTC().Add(time.Hour * -24).Format("2006-01-02T15:04:05-0700")
variables := map[string]interface{}{
"owner": owner,
"repo": repo,
"viewer": currentUsername,
"since": since,
}
var resp response
err := client.GraphQL(query, variables, &resp)
if err != nil {
return nil, err
}
var assigned []Issue
for _, edge := range resp.Assigned.Issues.Edges {
assigned = append(assigned, edge.Node)
}
var mentioned []Issue
for _, edge := range resp.Mentioned.Issues.Edges {
mentioned = append(mentioned, edge.Node)
}
var recent []Issue
for _, edge := range resp.Recent.Issues.Edges {
recent = append(recent, edge.Node)
}
payload := IssuesPayload{
assigned,
mentioned,
recent,
}
return &payload, nil
}
func PullRequests(client *Client, ghRepo Repo, currentBranch, currentUsername string) (*PullRequestsPayload, error) {
type edges struct {
Edges []struct {

View file

@ -1,5 +1,10 @@
package api
import (
"fmt"
"time"
)
func IssueCreate(client *Client, ghRepo Repo, params map[string]interface{}) (*Issue, error) {
repoID, err := GitHubRepoId(client, ghRepo)
if err != nil {
@ -38,3 +43,162 @@ func IssueCreate(client *Client, ghRepo Repo, params map[string]interface{}) (*I
return &result.CreateIssue.Issue, nil
}
type IssuesPayload struct {
Assigned []Issue
Mentioned []Issue
Recent []Issue
}
type Issue struct {
Number int
Title string
URL string
}
type apiIssues struct {
Issues struct {
Edges []struct {
Node Issue
}
}
}
func IssueStatus(client *Client, ghRepo Repo, currentUsername string) (*IssuesPayload, error) {
type response struct {
Assigned apiIssues
Mentioned apiIssues
Recent apiIssues
}
query := `
fragment issue on Issue {
number
title
}
query($owner: String!, $repo: String!, $since: DateTime!, $viewer: String!, $per_page: Int = 10) {
assigned: repository(owner: $owner, name: $repo) {
issues(filterBy: {assignee: $viewer}, first: $per_page, orderBy: {field: CREATED_AT, direction: DESC}) {
edges {
node {
...issue
}
}
}
}
mentioned: repository(owner: $owner, name: $repo) {
issues(filterBy: {mentioned: $viewer}, first: $per_page, orderBy: {field: CREATED_AT, direction: DESC}) {
edges {
node {
...issue
}
}
}
}
recent: repository(owner: $owner, name: $repo) {
issues(filterBy: {since: $since}, first: $per_page, orderBy: {field: CREATED_AT, direction: DESC}) {
edges {
node {
...issue
}
}
}
}
}
`
owner := ghRepo.RepoOwner()
repo := ghRepo.RepoName()
since := time.Now().UTC().Add(time.Hour * -24).Format("2006-01-02T15:04:05-0700")
variables := map[string]interface{}{
"owner": owner,
"repo": repo,
"viewer": currentUsername,
"since": since,
}
var resp response
err := client.GraphQL(query, variables, &resp)
if err != nil {
return nil, err
}
var assigned []Issue
for _, edge := range resp.Assigned.Issues.Edges {
assigned = append(assigned, edge.Node)
}
var mentioned []Issue
for _, edge := range resp.Mentioned.Issues.Edges {
mentioned = append(mentioned, edge.Node)
}
var recent []Issue
for _, edge := range resp.Recent.Issues.Edges {
recent = append(recent, edge.Node)
}
payload := IssuesPayload{
assigned,
mentioned,
recent,
}
return &payload, nil
}
func IssueList(client *Client, ghRepo Repo, state string) ([]Issue, error) {
var states []string
switch state {
case "open", "":
states = []string{"OPEN"}
case "closed":
states = []string{"CLOSED"}
case "all":
states = []string{"OPEN", "CLOSED"}
default:
return nil, fmt.Errorf("invalid state: %s", state)
}
query := `
fragment issue on Issue {
number
title
}
query($owner: String!, $repo: String!, $per_page: Int = 10, $states: [IssueState!] = OPEN) {
repository(owner: $owner, name: $repo) {
issues(first: $per_page, orderBy: {field: CREATED_AT, direction: DESC}, states: $states) {
edges {
node {
...issue
}
}
}
}
}
`
owner := ghRepo.RepoOwner()
repo := ghRepo.RepoName()
variables := map[string]interface{}{
"owner": owner,
"repo": repo,
"states": states,
}
var resp struct {
Repository apiIssues
}
err := client.GraphQL(query, variables, &resp)
if err != nil {
return nil, err
}
var issues []Issue
for _, edge := range resp.Repository.Issues.Edges {
issues = append(issues, edge.Node)
}
return issues, nil
}

View file

@ -19,7 +19,7 @@ func init() {
&cobra.Command{
Use: "status",
Short: "Show status of relevant issues",
RunE: issueList,
RunE: issueStatus,
},
&cobra.Command{
Use: "view <issue-number>",
@ -31,6 +31,16 @@ func init() {
issueCmd.AddCommand(issueCreateCmd)
issueCreateCmd.Flags().StringArrayP("message", "m", nil, "set title and body")
issueCreateCmd.Flags().BoolP("web", "w", false, "open the web browser to create an issue")
issueListCmd := &cobra.Command{
Use: "list",
Short: "List open issues",
RunE: issueList,
}
issueListCmd.Flags().StringP("assignee", "a", "", "filter by assignee")
issueListCmd.Flags().StringP("label", "l", "", "Filter by assignee")
issueListCmd.Flags().StringP("state", "s", "", "Filter by state")
issueCmd.AddCommand((issueListCmd))
}
var issueCmd = &cobra.Command{
@ -56,12 +66,43 @@ func issueList(cmd *cobra.Command, args []string) error {
return err
}
state, err := cmd.Flags().GetString("state")
if err != nil {
return err
}
issues, err := api.IssueList(apiClient, baseRepo, state)
if err != nil {
return err
}
if len(issues) > 0 {
printIssues(issues...)
} else {
message := fmt.Sprintf("There are no open issues")
printMessage(message)
}
return nil
}
func issueStatus(cmd *cobra.Command, args []string) error {
ctx := contextForCommand(cmd)
apiClient, err := apiClientForContext(ctx)
if err != nil {
return err
}
baseRepo, err := ctx.BaseRepo()
if err != nil {
return err
}
currentUser, err := ctx.AuthLogin()
if err != nil {
return err
}
issuePayload, err := api.Issues(apiClient, baseRepo, currentUser)
issuePayload, err := api.IssueStatus(apiClient, baseRepo, currentUser)
if err != nil {
return err
}

View file

@ -40,6 +40,32 @@ func TestIssueStatus(t *testing.T) {
}
}
func TestIssueList(t *testing.T) {
initBlankContext("OWNER/REPO", "master")
http := initFakeHTTP()
jsonFile, _ := os.Open("../test/fixtures/issueList.json")
defer jsonFile.Close()
http.StubResponse(200, jsonFile)
output, err := test.RunCommand(RootCmd, "issue list")
if err != nil {
t.Errorf("error running command `issue list`: %v", err)
}
expectedIssues := []*regexp.Regexp{
regexp.MustCompile(`#1.*won`),
regexp.MustCompile(`#2.*too`),
regexp.MustCompile(`#4.*fore`),
}
for _, r := range expectedIssues {
if !r.MatchString(output) {
t.Errorf("output did not match regexp /%s/", r)
}
}
}
func TestIssueView(t *testing.T) {
initBlankContext("OWNER/REPO", "master")
http := initFakeHTTP()

View file

@ -1,47 +1,27 @@
{
"data": {
"assigned": {
"issues": {
"edges": [
{
"node": {
"number": 9,
"title": "corey thinks squash tastes bad"
}
},
{
"node": {
"number": 10,
"title": "broccoli is a superfood"
}
"issues": {
"edges": [
{
"node": {
"number": 1,
"title": "number won"
}
]
}
},
"mentioned": {
"issues": {
"edges": [
{
"node": {
"number": 8,
"title": "rabbits eat carrots"
}
},
{
"node": {
"number": 11,
"title": "swiss chard is neutral"
}
},
{
"node": {
"number": 2,
"title": "number too"
}
]
}
},
{
"node": {
"number": 4,
"title": "number fore"
}
}
]
},
"recent": {
"issues": {
"edges": []
}
},
"pageInfo": { "hasNextPage": false }
}
}