Simplifies init process and adds github issue publishing

This commit is contained in:
Miguel de la Cruz 2020-04-27 11:42:29 +02:00
parent 21c18b3095
commit be543e2cc4
23 changed files with 581 additions and 390 deletions

View file

@ -16,9 +16,14 @@ import (
func GrepAddCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "grep",
Short: "Generates the tickets reading grep's output from stdin",
Long: "Generates tickets for the campaign reading from the standard input the output grep. The grep command must be run with the -n flag",
Use: "grep",
Short: "Generates the tickets reading grep's output from stdin",
Long: `Generates tickets for the campaign reading from the standard input the output grep. The grep command must be run with the -n flag. The generated ticket will contain three fields:
- filename: the filename yield by grep
- lineNo: the line number yield by grep
- text: the trimmed line that grep captured for the expression
`,
Example: ` grep -nriIF --include \*.go cobra.Command | campaigner add grep`,
Args: cobra.NoArgs,
Run: grepAddCmdF,
@ -104,7 +109,7 @@ func parseGrepLine(line string) (*model.Ticket, error) {
Data: map[string]interface{}{
"filename": filename,
"lineNo": lineNo,
"text": text,
"text": strings.TrimSpace(text),
},
}, nil
}

View file

@ -1,6 +1,9 @@
package cmd
import (
"bufio"
"fmt"
"os"
"strings"
"git.ctrlz.es/mgdelacroix/campaigner/campaign"
@ -14,44 +17,78 @@ func InitCmd() *cobra.Command {
Use: "init",
Short: "Creates a new campaign in the current directory",
Example: ` campaigner init \
--jira-username johndoe \
--jira-token secret \
--github-token TOKEN \
--url http://my-jira-instance.com \
--epic ASD-27 \
--issue-type Story \
--repository johndoe/awesomeproject \
-l 'Area/API' -l 'Tech/Go' \
--summary 'Refactor {{.function}} to inject the configuration service' \
--template ./refactor-config.tmpl`,
Args: cobra.NoArgs,
Run: initCmdF,
Args: cobra.NoArgs,
Run: initCmdF,
}
cmd.Flags().StringP("url", "u", "", "The jira server URL")
_ = cmd.MarkFlagRequired("url")
cmd.Flags().StringP("epic", "e", "", "The epic id to associate this campaign with")
_ = cmd.MarkFlagRequired("epic")
cmd.Flags().StringP("summary", "s", "", "The summary of the tickets")
_ = cmd.MarkFlagRequired("summary")
cmd.Flags().StringP("template", "t", "", "The template path for the description of the tickets")
_ = cmd.MarkFlagRequired("template")
cmd.Flags().StringP("issue-type", "i", "Story", "The issue type to create the tickets as")
cmd.Flags().String("jira-username", "", "the jira username")
cmd.Flags().String("jira-token", "", "the jira token or password")
cmd.Flags().String("github-token", "", "the github token")
cmd.Flags().StringP("url", "u", "", "the jira server URL")
cmd.Flags().StringP("epic", "e", "", "the epic id to associate this campaign with")
cmd.Flags().StringP("repository", "r", "", "the github repository")
cmd.Flags().StringSliceP("label", "l", []string{}, "the labels to add to the Github issues")
cmd.Flags().StringP("summary", "s", "", "the summary of the tickets")
cmd.Flags().StringP("template", "t", "", "the template path for the description of the tickets")
cmd.Flags().StringP("issue-type", "i", "Story", "the issue type to create the tickets as")
return cmd
}
func initCmdF(cmd *cobra.Command, _ []string) {
url, _ := cmd.Flags().GetString("url")
epic, _ := cmd.Flags().GetString("epic")
summary, _ := cmd.Flags().GetString("summary")
template, _ := cmd.Flags().GetString("template")
getStringFlagOrAskIfEmpty := func(name string, question string) string {
val, _ := cmd.Flags().GetString(name)
if val == "" {
reader := bufio.NewReader(os.Stdin)
fmt.Printf("%s ", question)
answer, err := reader.ReadString('\n')
if err != nil {
ErrorAndExit(cmd, err)
}
val = strings.TrimSpace(answer)
}
return val
}
jiraUsername := getStringFlagOrAskIfEmpty("jira-username", "JIRA username:")
jiraToken := getStringFlagOrAskIfEmpty("jira-token", "JIRA password or token:")
githubToken := getStringFlagOrAskIfEmpty("github-token", "GitHub token:")
url := getStringFlagOrAskIfEmpty("url", "JIRA server URL:")
epic := getStringFlagOrAskIfEmpty("epic", "JIRA epic:")
repo := getStringFlagOrAskIfEmpty("repository", "GitHub repository:")
summary := getStringFlagOrAskIfEmpty("summary", "Ticket summary template:")
template := getStringFlagOrAskIfEmpty("template", "Ticket description template path:")
issueType, _ := cmd.Flags().GetString("issue-type")
labels, _ := cmd.Flags().GetStringSlice("label")
project := strings.Split(epic, "-")[0]
cmp := &model.Campaign{
Url: url,
Project: project,
Epic: epic,
IssueType: issueType,
Summary: summary,
Template: template,
Jira: model.ConfigJira{
Url: url,
Username: jiraUsername,
Token: jiraToken,
Project: project,
Epic: epic,
IssueType: issueType,
},
Github: model.ConfigGithub{
Token: githubToken,
Repo: repo,
Labels: labels,
},
Summary: summary,
Template: template,
}
if err := campaign.Save(cmp); err != nil {
ErrorAndExit(cmd, err)

View file

@ -4,7 +4,6 @@ import (
"fmt"
"git.ctrlz.es/mgdelacroix/campaigner/campaign"
"git.ctrlz.es/mgdelacroix/campaigner/config"
"git.ctrlz.es/mgdelacroix/campaigner/github"
"git.ctrlz.es/mgdelacroix/campaigner/jira"
@ -64,17 +63,12 @@ func jiraPublishCmdF(cmd *cobra.Command, _ []string) error {
return fmt.Errorf("One of --all or --batch flags is required")
}
cfg, err := config.ReadConfig()
if err != nil {
ErrorAndExit(cmd, err)
}
cmp, err := campaign.Read()
if err != nil {
ErrorAndExit(cmd, err)
}
jiraClient, err := jira.NewClient(cmp.Url, cfg.JiraUsername, cfg.JiraToken)
jiraClient, err := jira.NewClient(cmp.Jira.Url, cmp.Jira.Username, cmp.Jira.Token)
if err != nil {
ErrorAndExit(cmd, err)
}
@ -104,17 +98,12 @@ func githubPublishCmdF(cmd *cobra.Command, _ []string) error {
return fmt.Errorf("One of --all or --batch flags is required")
}
cfg, err := config.ReadConfig()
if err != nil {
ErrorAndExit(cmd, err)
}
cmp, err := campaign.Read()
if err != nil {
ErrorAndExit(cmd, err)
}
githubClient := github.NewClient("my/repo", cfg.GithubToken)
githubClient := github.NewClient(cmp.Github.Repo, cmp.Github.Token)
if all {
count, err := githubClient.PublishAll(cmp, dryRun)

View file

@ -17,9 +17,7 @@ func RootCmd() *cobra.Command {
AddCmd(),
FilterCmd(),
InitCmd(),
StandaloneCmd(),
StatusCmd(),
TokenCmd(),
PublishCmd(),
SyncCmd(),
)

View file

@ -1,163 +0,0 @@
package cmd
import (
"fmt"
"strings"
"git.ctrlz.es/mgdelacroix/campaigner/config"
"git.ctrlz.es/mgdelacroix/campaigner/jira"
"git.ctrlz.es/mgdelacroix/campaigner/model"
"github.com/spf13/cobra"
)
func StandaloneCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "standalone",
Short: "Standalone fire-and-forget commands",
}
cmd.AddCommand(
CreateJiraTicketStandaloneCmd(),
GetJiraTicketStandaloneCmd(),
)
return cmd
}
func CreateJiraTicketStandaloneCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "create-jira-ticket",
Short: "Creates a jira ticket from a template",
Args: cobra.NoArgs,
RunE: createJiraTicketStandaloneCmdF,
}
cmd.Flags().String("url", "", "The jira server URL")
_ = cmd.MarkFlagRequired("url")
cmd.Flags().String("epic", "", "The jira epic id to associate the ticket with")
_ = cmd.MarkFlagRequired("epic")
cmd.Flags().String("summary", "", "The summary of the ticket")
_ = cmd.MarkFlagRequired("summary")
cmd.Flags().String("template", "", "The template to render the description of the ticket")
_ = cmd.MarkFlagRequired("template")
cmd.Flags().String("username", "", "The jira username")
cmd.Flags().String("token", "", "The jira token")
cmd.Flags().StringSliceP("vars", "v", []string{}, "The variables to use in the template")
cmd.Flags().Bool("dry-run", false, "Print the ticket information instead of creating it")
return cmd
}
func GetJiraTicketStandaloneCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "get-jira-ticket",
Short: "Gets the ticket from jira",
Args: cobra.ExactArgs(1),
Run: getJiraTicketStandaloneCmdF,
}
cmd.Flags().String("url", "", "The jira server URL")
_ = cmd.MarkFlagRequired("url")
cmd.Flags().String("username", "", "The jira username")
cmd.Flags().String("token", "", "The jira token")
return cmd
}
func getVarMap(vars []string) (map[string]interface{}, error) {
varMap := map[string]interface{}{}
for _, v := range vars {
parts := strings.Split(v, "=")
if len(parts) < 2 {
return nil, fmt.Errorf("cannot parse var %s", v)
}
varMap[parts[0]] = strings.Join(parts[1:], "=")
}
return varMap, nil
}
func createJiraTicketStandaloneCmdF(cmd *cobra.Command, _ []string) error {
url, _ := cmd.Flags().GetString("url")
epic, _ := cmd.Flags().GetString("epic")
username, _ := cmd.Flags().GetString("username")
token, _ := cmd.Flags().GetString("token")
summary, _ := cmd.Flags().GetString("summary")
template, _ := cmd.Flags().GetString("template")
vars, _ := cmd.Flags().GetStringSlice("vars")
dryRun, _ := cmd.Flags().GetBool("dry-run")
project := strings.Split(epic, "-")[0]
if username == "" || token == "" {
cfg, err := config.ReadConfig()
if err != nil {
ErrorAndExit(cmd, err)
}
if username == "" {
username = cfg.JiraUsername
}
if token == "" {
token = cfg.JiraToken
}
}
varMap, err := getVarMap(vars)
if err != nil {
return fmt.Errorf("error processing vars: %w", err)
}
jiraClient, err := jira.NewClient(url, username, token)
if err != nil {
ErrorAndExit(cmd, err)
}
campaign := &model.Campaign{
Epic: epic,
Project: project,
Summary: summary,
Template: template,
}
ticket := &model.Ticket{Data: varMap}
issue, err := jiraClient.PublishTicket(ticket, campaign, dryRun)
if err != nil {
ErrorAndExit(cmd, err)
}
cmd.Printf("Ticket %s successfully created in JIRA", issue.Key)
return nil
}
func getJiraTicketStandaloneCmdF(cmd *cobra.Command, args []string) {
url, _ := cmd.Flags().GetString("url")
username, _ := cmd.Flags().GetString("username")
token, _ := cmd.Flags().GetString("token")
if username == "" || token == "" {
cfg, err := config.ReadConfig()
if err != nil {
ErrorAndExit(cmd, err)
}
if username == "" {
username = cfg.JiraUsername
}
if token == "" {
token = cfg.JiraToken
}
}
jiraClient, err := jira.NewClient(url, username, token)
if err != nil {
ErrorAndExit(cmd, err)
}
issue, err := jiraClient.GetIssue(args[0])
if err != nil {
ErrorAndExit(cmd, err)
}
fmt.Printf("Summary: %s\nKey: %s\nStatus: %s\nAsignee: %s\n", issue.Fields.Summary, issue.Key, issue.Fields.Status.Name, issue.Fields.Assignee.DisplayName)
}

View file

@ -1,79 +0,0 @@
package cmd
import (
"git.ctrlz.es/mgdelacroix/campaigner/config"
"github.com/spf13/cobra"
)
func TokenSetJiraCmd() *cobra.Command {
return &cobra.Command{
Use: "jira USERNAME TOKEN",
Short: "Sets the value of the jira token",
Args: cobra.ExactArgs(2),
RunE: tokenSetJiraCmdF,
}
}
func TokenSetGithubCmd() *cobra.Command {
return &cobra.Command{
Use: "github TOKEN",
Short: "Sets the value of the github token",
Args: cobra.ExactArgs(1),
RunE: tokenSetGithubCmdF,
}
}
func TokenSetCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "set",
Short: "Sets the value of the platform tokens",
}
cmd.AddCommand(
TokenSetJiraCmd(),
TokenSetGithubCmd(),
)
return cmd
}
func TokenCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "token",
Short: "Subcommands related to tokens",
}
cmd.AddCommand(
TokenSetCmd(),
)
return cmd
}
func tokenSetJiraCmdF(cmd *cobra.Command, args []string) error {
cfg, err := config.ReadConfig()
if err != nil {
ErrorAndExit(cmd, err)
}
cfg.JiraUsername = args[0]
cfg.JiraToken = args[1]
if err := config.SaveConfig(cfg); err != nil {
ErrorAndExit(cmd, err)
}
return nil
}
func tokenSetGithubCmdF(cmd *cobra.Command, args []string) error {
cfg, err := config.ReadConfig()
if err != nil {
ErrorAndExit(cmd, err)
}
cfg.GithubToken = args[0]
if err := config.SaveConfig(cfg); err != nil {
ErrorAndExit(cmd, err)
}
return nil
}