Prototype issue create

This commit is contained in:
Mislav Marohnić 2019-11-01 15:31:07 +01:00
parent 5d2ecf12ca
commit 401aef283f
3 changed files with 154 additions and 0 deletions

View file

@ -32,6 +32,7 @@ type IssuesPayload struct {
type Issue struct {
Number int
Title string
URL string
}
func Issues(client *Client, ghRepo Repo, currentUsername string) (*IssuesPayload, error) {

70
api/queries_issue.go Normal file
View file

@ -0,0 +1,70 @@
package api
import "fmt"
func IssueCreate(client *Client, ghRepo Repo, params map[string]interface{}) (*Issue, error) {
repoId, err := GitHubRepoId(client, ghRepo)
if err != nil {
return nil, err
}
query := `
mutation CreateIssue($input: CreateIssueInput!) {
createIssue(input: $input) {
issue {
url
}
}
}`
inputParams := map[string]interface{}{
"repositoryId": repoId,
}
for key, val := range params {
inputParams[key] = val
}
variables := map[string]interface{}{
"input": inputParams,
}
result := struct {
CreateIssue struct {
Issue Issue
}
}{}
err = client.GraphQL(query, variables, &result)
if err != nil {
return nil, err
}
return &result.CreateIssue.Issue, nil
}
func GitHubRepoId(client *Client, ghRepo Repo) (string, error) {
owner := ghRepo.RepoOwner()
repo := ghRepo.RepoName()
query := `
query FindRepoID($owner:String!, $name:String!) {
repository(owner:$owner, name:$name) {
id
}
}`
variables := map[string]interface{}{
"owner": owner,
"name": repo,
}
result := struct {
Repository struct {
Id string
}
}{}
err := client.GraphQL(query, variables, &result)
if err != nil || result.Repository.Id == "" {
return "", fmt.Errorf("failed to determine GH repo ID: %s", err)
}
return result.Repository.Id, nil
}

View file

@ -2,11 +2,15 @@ package command
import (
"fmt"
"io/ioutil"
"os"
"strconv"
"strings"
"github.com/github/gh-cli/api"
"github.com/github/gh-cli/utils"
"github.com/spf13/cobra"
"golang.org/x/crypto/ssh/terminal"
)
func init() {
@ -24,6 +28,9 @@ func init() {
RunE: issueView,
},
)
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")
}
var issueCmd = &cobra.Command{
@ -31,6 +38,11 @@ var issueCmd = &cobra.Command{
Short: "Work with GitHub issues",
Long: `Helps you work with issues.`,
}
var issueCreateCmd = &cobra.Command{
Use: "create",
Short: "Create a new issue",
RunE: issueCreate,
}
func issueList(cmd *cobra.Command, args []string) error {
cmd.SilenceUsage = true
@ -106,6 +118,77 @@ func issueView(cmd *cobra.Command, args []string) error {
return utils.OpenInBrowser(openURL)
}
func issueCreate(cmd *cobra.Command, args []string) error {
ctx := contextForCommand(cmd)
baseRepo, err := ctx.BaseRepo()
if err != nil {
return err
}
if isWeb, err := cmd.Flags().GetBool("web"); err == nil && isWeb {
// TODO: move URL generation into GitHubRepository
openURL := fmt.Sprintf("https://github.com/%s/%s/issues/new", baseRepo.RepoOwner(), baseRepo.RepoName())
// TODO: figure out how to stub this in tests
if stat, err := os.Stat(".github/ISSUE_TEMPLATE"); err == nil && stat.IsDir() {
openURL += "/choose"
}
return utils.OpenInBrowser(openURL)
}
var title string
var body string
message, err := cmd.Flags().GetStringArray("message")
if err != nil {
return err
}
apiClient, err := apiClientForContext(ctx)
if err != nil {
return err
}
if len(message) > 0 {
title = message[0]
body = strings.Join(message[1:], "\n\n")
} else {
// TODO: open the text editor for issue title & body
input := os.Stdin
if terminal.IsTerminal(int(input.Fd())) {
cmd.Println("Enter the issue title and body; press Enter + Ctrl-D when done:")
}
inputBytes, err := ioutil.ReadAll(input)
if err != nil {
return err
}
parts := strings.SplitN(string(inputBytes), "\n\n", 2)
if len(parts) > 0 {
title = parts[0]
}
if len(parts) > 1 {
body = parts[1]
}
}
if title == "" {
return fmt.Errorf("aborting due to empty title")
}
params := map[string]interface{}{
"title": title,
"body": body,
}
newIssue, err := api.IssueCreate(apiClient, baseRepo, params)
if err != nil {
return err
}
fmt.Fprintln(cmd.OutOrStdout(), newIssue.URL)
return nil
}
func printIssues(issues ...api.Issue) {
for _, issue := range issues {
fmt.Printf(" #%d %s\n", issue.Number, truncateTitle(issue.Title, 70))