From 212df1725df7f17191fdffbcbb2c322883e37f28 Mon Sep 17 00:00:00 2001 From: Corey Johnson Date: Tue, 8 Oct 2019 16:40:10 -0700 Subject: [PATCH] Pull out queries --- command/pr.go | 93 ++------------------------ graphql/client.go | 8 ++- graphql/queries.go | 159 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 171 insertions(+), 89 deletions(-) create mode 100644 graphql/queries.go diff --git a/command/pr.go b/command/pr.go index e21d66e74..78557c999 100644 --- a/command/pr.go +++ b/command/pr.go @@ -3,8 +3,8 @@ package command import ( "fmt" - "github.com/github/gh-cli/git" - "github.com/github/gh-cli/github" + "github.com/github/gh-cli/graphql" + "github.com/spf13/cobra" ) @@ -32,89 +32,10 @@ var prListCmd = &cobra.Command{ }, } -type prFilter int - -const ( - createdByViewer prFilter = iota - reviewRequested -) - func ExecutePr() { - // prsForCurrentBranch := pullRequestsForCurrentBranch() - prsCreatedByViewer := pullRequests(createdByViewer) - // prsRequestingReview := pullRequests(reviewRequested) - - fmt.Printf("🌭 count! %d\n", len(prsCreatedByViewer)) -} - -type searchBody struct { - Items []github.PullRequest `json:"items"` -} - -func pullRequestsForCurrentBranch() []github.PullRequest { - project := project() - client := github.NewClient(project.Host) - currentBranch, error := git.Head() - if error != nil { - panic(error) - } - - headWithOwner := fmt.Sprintf("%s:%s", project.Owner, currentBranch) - filterParams := map[string]interface{}{"headWithOwner": headWithOwner} - prs, error := client.FetchPullRequests(&project, filterParams, 10, nil) - if error != nil { - panic(error) - } - - return prs -} - -func pullRequests(filter prFilter) []github.PullRequest { - project := project() - client := github.NewClient(project.Host) - owner := project.Owner - name := project.Name - user, error := client.CurrentUser() - if error != nil { - panic(error) - } - - var headers map[string]string - var q string - if filter == createdByViewer { - q = fmt.Sprintf("user:%s repo:%s state:open is:pr author:%s", owner, name, user.Login) - } else if filter == reviewRequested { - q = fmt.Sprintf("user:%s repo:%s state:open review-requested:%s", owner, name, user.Login) - } else { - panic("This is not a fitler") - } - - data := map[string]interface{}{"q": q} - - response, error := client.GenericAPIRequest("GET", "search/issues", data, headers, 60) - if error != nil { - panic(fmt.Sprintf("GenericAPIRequest failed %+v", error)) - } - searchBody := searchBody{} - error = response.Unmarshal(&searchBody) - if error != nil { - panic(fmt.Sprintf("Unmarshal failed %+v", error)) - } - - return searchBody.Items -} - -func project() github.Project { - remotes, error := github.Remotes() - if error != nil { - panic(error) - } - - for _, remote := range remotes { - if project, error := remote.Project(); error == nil { - return *project - } - } - - panic("Could not get the project. What is a project? I don't know, it's kind of like a git repository I think?") + prPayload, err := graphql.PullRequests() + if err != nil { + panic(err) + } + fmt.Printf("%+v!\n", prPayload) } diff --git a/graphql/client.go b/graphql/client.go index 41cb8cdcd..5c154a453 100644 --- a/graphql/client.go +++ b/graphql/client.go @@ -18,7 +18,7 @@ type graphQLResponse struct { } /* -GraphQL usage +graphQL usage type repoResponse struct { repository struct { @@ -42,7 +42,7 @@ if err != nil { fmt.Printf("%+v\n", resp) */ -func GraphQL(query string, variables map[string]string, v interface{}) error { +func graphQL(query string, variables map[string]string, v interface{}) error { url := "https://api.github.com/graphql" reqBody, err := json.Marshal(map[string]interface{}{"query": query, "variables": variables}) if err != nil { @@ -108,7 +108,9 @@ func handleHTTPError(resp *http.Response) error { return fmt.Errorf("http error, '%s' failed (%d): '%s'", resp.Request.URL, resp.StatusCode, message) } -// THIS IS A BULLSHIT FUNCTION THAT SHOULD BE REMOVED +// TODO: THIS IS NO GOOD. I need to figure out if the GraphQL function has direct +// access to the token, or if we should pass the token into the GraphQL function. For +// now I'm asuming that this has direct access so I'm simulating that with this function. func getToken() string { usr, err := user.Current() if err != nil { diff --git a/graphql/queries.go b/graphql/queries.go new file mode 100644 index 000000000..dec455f71 --- /dev/null +++ b/graphql/queries.go @@ -0,0 +1,159 @@ +package graphql + +import ( + "fmt" + "strings" + + "github.com/github/gh-cli/git" + "github.com/github/gh-cli/github" +) + +type PullRequestsPayload struct { + viewerCreated []PullRequest + reviewRequested []PullRequest + currentPR *PullRequest +} + +type PullRequest struct { + Number int + Title string + URL string + HeadRefName string +} + +func PullRequests() (PullRequestsPayload, error) { + type edges struct { + Edges []PullRequest + PageInfo struct { + HasNextPage bool + EndCursor string + } + } + + type response struct { + Repository struct { + PullRequests edges + } + ViewerCreated edges + ReviewRequested edges + } + + query := ` + fragment pr on PullRequest { + number + title + url + } + + query($owner: String!, $repo: String!, $headRefName: String!, $viewerQuery: String!, $reviewerQuery: String!, $per_page: Int = 10) { + repository(owner: $owner, name: $repo) { + pullRequests(headRefName: $headRefName, first: 1) { + edges { + node { + ...pr + } + } + } + } + viewerCreated: search(query: $viewerQuery, type: ISSUE, first: $per_page) { + edges { + node { + ...pr + } + } + pageInfo { + hasNextPage + } + } + reviewRequested: search(query: $reviewerQuery, type: ISSUE, first: $per_page) { + edges { + node { + ...pr + } + } + pageInfo { + hasNextPage + } + } + } + ` + + project := project() + owner := project.Owner + repo := project.Name + currentBranch := currentBranch() + + viewerQuery := fmt.Sprintf("repo:%s/%s state:open is:pr author:%s", owner, repo, currentUsername()) + reviewerQuery := fmt.Sprintf("repo:%s/%s state:open review-requested:%s", owner, repo, currentUsername()) + + variables := map[string]string{ + "viewerQuery": viewerQuery, + "reviewerQuery": reviewerQuery, + "owner": owner, + "repo": repo, + "headRefName": currentBranch, + } + + var resp response + err := graphQL(query, variables, &resp) + if err != nil { + return PullRequestsPayload{}, err + } + + var viewerCreated []PullRequest + for _, pr := range resp.ViewerCreated.Edges { + viewerCreated = append(viewerCreated, pr) + } + + var reviewRequested []PullRequest + for _, pr := range resp.ReviewRequested.Edges { + reviewRequested = append(reviewRequested, pr) + } + + var currentPR *PullRequest + for _, pr := range resp.Repository.PullRequests.Edges { + currentPR = &pr + } + + payload := PullRequestsPayload{ + viewerCreated, + reviewRequested, + currentPR, + } + + return payload, nil +} + +// These will be replaced by nate's context stuff +// 💥💥💥💥💥💥💥💥💥💥💥💥💥💥💥💥💥💥💥💥💥 +func project() github.Project { + remotes, error := github.Remotes() + if error != nil { + panic(error) + } + + for _, remote := range remotes { + if project, error := remote.Project(); error == nil { + return *project + } + } + + panic("Could not get the project. What is a project? I don't know, it's kind of like a git repository I think?") +} + +func currentBranch() string { + currentBranch, err := git.Head() + if err != nil { + panic(err) + } + + return strings.Replace(currentBranch, "refs/heads/", "", 1) +} + +func currentUsername() string { + host, err := github.CurrentConfig().DefaultHost() + if err != nil { + panic(err) + } + return host.User +}