Add template support to issue create, pr create

If multiple templates are found, the user is prompted to select one.

The templates are searched for, in order of preference:

- issues:
  1. `.github/ISSUE_TEMPLATE/*.md`
  2. `.github/ISSUE_TEMPLATE.md`
  3. `ISSUE_TEMPLATE/*.md`
  4. `ISSUE_TEMPLATE.md`
  5. `docs/ISSUE_TEMPLATE/*.md`
  6. `docs/ISSUE_TEMPLATE.md`

- pull requests:
  1. `.github/PULL_REQUEST_TEMPLATE/*.md`
  2. `.github/PULL_REQUEST_TEMPLATE.md`
  3. `PULL_REQUEST_TEMPLATE/*.md`
  4. `PULL_REQUEST_TEMPLATE.md`
  5. `docs/PULL_REQUEST_TEMPLATE/*.md`
  6. `docs/PULL_REQUEST_TEMPLATE.md`

The filename matches are case-insensitive.
This commit is contained in:
Mislav Marohnić 2019-12-18 22:11:25 +01:00
parent 2c94616969
commit d5ba3de751
6 changed files with 418 additions and 6 deletions

View file

@ -3,13 +3,14 @@ package command
import (
"fmt"
"io"
"os"
"regexp"
"strconv"
"strings"
"github.com/github/gh-cli/api"
"github.com/github/gh-cli/context"
"github.com/github/gh-cli/git"
"github.com/github/gh-cli/pkg/githubtemplate"
"github.com/github/gh-cli/utils"
"github.com/pkg/errors"
"github.com/spf13/cobra"
@ -241,11 +242,16 @@ func issueCreate(cmd *cobra.Command, args []string) error {
return err
}
var templateFiles []string
if rootDir, err := git.ToplevelDir(); err == nil {
// TODO: figure out how to stub this in tests
templateFiles = githubtemplate.Find(rootDir, "ISSUE_TEMPLATE")
}
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() {
if len(templateFiles) > 1 {
openURL += "/choose"
}
cmd.Printf("Opening %s in your browser.\n", openURL)
@ -269,7 +275,7 @@ func issueCreate(cmd *cobra.Command, args []string) error {
interactive := title == "" || body == ""
if interactive {
tb, err := titleBodySurvey(cmd, title, body)
tb, err := titleBodySurvey(cmd, title, body, templateFiles)
if err != nil {
return errors.Wrap(err, "could not collect title and/or body")
}

View file

@ -8,6 +8,7 @@ import (
"github.com/github/gh-cli/api"
"github.com/github/gh-cli/context"
"github.com/github/gh-cli/git"
"github.com/github/gh-cli/pkg/githubtemplate"
"github.com/github/gh-cli/utils"
"github.com/pkg/errors"
"github.com/spf13/cobra"
@ -71,7 +72,13 @@ func prCreate(cmd *cobra.Command, _ []string) error {
interactive := title == "" || body == ""
if interactive {
tb, err := titleBodySurvey(cmd, title, body)
var templateFiles []string
if rootDir, err := git.ToplevelDir(); err == nil {
// TODO: figure out how to stub this in tests
templateFiles = githubtemplate.Find(rootDir, "PULL_REQUEST_TEMPLATE")
}
tb, err := titleBodySurvey(cmd, title, body, templateFiles)
if err != nil {
return errors.Wrap(err, "could not collect title and/or body")
}

View file

@ -2,7 +2,9 @@ package command
import (
"fmt"
"github.com/AlecAivazis/survey/v2"
"github.com/github/gh-cli/pkg/githubtemplate"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
@ -44,9 +46,45 @@ func confirm() (int, error) {
return confirmAnswers.Confirmation, nil
}
func titleBodySurvey(cmd *cobra.Command, providedTitle string, providedBody string) (*titleBody, error) {
func selectTemplate(templatePaths []string) (string, error) {
templateResponse := struct {
Index int
}{}
if len(templatePaths) > 1 {
templateNames := []string{}
for _, p := range templatePaths {
templateNames = append(templateNames, githubtemplate.ExtractName(p))
}
selectQs := []*survey.Question{
{
Name: "index",
Prompt: &survey.Select{
Message: "Choose a template",
Options: templateNames,
},
},
}
if err := survey.Ask(selectQs, &templateResponse); err != nil {
return "", errors.Wrap(err, "could not prompt")
}
}
templateContents := githubtemplate.ExtractContents(templatePaths[templateResponse.Index])
return string(templateContents), nil
}
func titleBodySurvey(cmd *cobra.Command, providedTitle string, providedBody string, templatePaths []string) (*titleBody, error) {
inProgress := titleBody{}
if providedBody == "" && len(templatePaths) > 0 {
templateContents, err := selectTemplate(templatePaths)
if err != nil {
return nil, err
}
inProgress.Body = templateContents
}
confirmed := false
editor := determineEditor()
@ -64,6 +102,7 @@ func titleBodySurvey(cmd *cobra.Command, providedTitle string, providedBody stri
Message: fmt.Sprintf("Body (%s)", editor),
FileName: "*.md",
Default: inProgress.Body,
HideDefault: true,
AppendDefault: true,
Editor: editor,
},