Allow standalone command to create issues
This commit is contained in:
parent
ab2e28e29e
commit
1b66405f39
6 changed files with 148 additions and 93 deletions
|
@ -23,7 +23,7 @@ func GrepAddCmd() *cobra.Command {
|
||||||
Run: grepAddCmdF,
|
Run: grepAddCmdF,
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.Flags().BoolP("file-only", "f", false, "generates one ticket per file instead of per match")
|
cmd.Flags().BoolP("file-only", "f", false, "Generates one ticket per file instead of per match")
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ func AgAddCmd() *cobra.Command {
|
||||||
RunE: agAddCmdF,
|
RunE: agAddCmdF,
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.Flags().BoolP("file-only", "f", false, "generates one ticket per file instead of per match")
|
cmd.Flags().BoolP("file-only", "f", false, "Generates one ticket per file instead of per match")
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ func GovetAddCmd() *cobra.Command {
|
||||||
RunE: govetAddCmdF,
|
RunE: govetAddCmdF,
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.Flags().BoolP("file-only", "f", false, "generates one ticket per file instead of per match")
|
cmd.Flags().BoolP("file-only", "f", false, "Generates one ticket per file instead of per match")
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,7 @@ func CsvAddCmd() *cobra.Command {
|
||||||
RunE: csvAddCmdF,
|
RunE: csvAddCmdF,
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.Flags().BoolP("file-only", "f", false, "generates one ticket per file instead of per match")
|
cmd.Flags().BoolP("file-only", "f", false, "Generates one ticket per file instead of per match")
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
20
cmd/init.go
20
cmd/init.go
|
@ -15,14 +15,16 @@ func InitCmd() *cobra.Command {
|
||||||
Run: initCmdF,
|
Run: initCmdF,
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.Flags().StringP("url", "u", "", "the jira server URL")
|
cmd.Flags().StringP("url", "u", "", "The jira server URL")
|
||||||
_ = cmd.MarkFlagRequired("url")
|
_ = cmd.MarkFlagRequired("url")
|
||||||
cmd.Flags().StringP("project", "p", "", "the jira project key to associate the tickets with")
|
cmd.Flags().StringP("project", "p", "", "The jira project key to associate the tickets with")
|
||||||
_ = cmd.MarkFlagRequired("project")
|
_ = cmd.MarkFlagRequired("project")
|
||||||
cmd.Flags().StringP("epic", "e", "", "the epic id to associate this campaign with")
|
cmd.Flags().StringP("epic", "e", "", "The epic id to associate this campaign with")
|
||||||
_ = cmd.MarkFlagRequired("epic")
|
_ = cmd.MarkFlagRequired("epic")
|
||||||
cmd.Flags().StringP("summary", "s", "", "the summary of the tickets")
|
cmd.Flags().StringP("summary", "s", "", "The summary of the tickets")
|
||||||
_ = cmd.MarkFlagRequired("summary")
|
_ = cmd.MarkFlagRequired("summary")
|
||||||
|
cmd.Flags().StringP("template", "t", "", "The template path for the description of the tickets")
|
||||||
|
_ = cmd.MarkFlagRequired("template")
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
@ -32,12 +34,14 @@ func initCmdF(cmd *cobra.Command, _ []string) {
|
||||||
project, _ := cmd.Flags().GetString("project")
|
project, _ := cmd.Flags().GetString("project")
|
||||||
epic, _ := cmd.Flags().GetString("epic")
|
epic, _ := cmd.Flags().GetString("epic")
|
||||||
summary, _ := cmd.Flags().GetString("summary")
|
summary, _ := cmd.Flags().GetString("summary")
|
||||||
|
template, _ := cmd.Flags().GetString("template")
|
||||||
|
|
||||||
cmp := &model.Campaign{
|
cmp := &model.Campaign{
|
||||||
Url: url,
|
Url: url,
|
||||||
Project: project,
|
Project: project,
|
||||||
Epic: epic,
|
Epic: epic,
|
||||||
Summary: summary,
|
Summary: summary,
|
||||||
|
Template: template,
|
||||||
}
|
}
|
||||||
if err := campaign.Save(cmp); err != nil {
|
if err := campaign.Save(cmp); err != nil {
|
||||||
ErrorAndExit(cmd, err)
|
ErrorAndExit(cmd, err)
|
||||||
|
|
|
@ -5,12 +5,17 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func JiraPublishCmd() *cobra.Command {
|
func JiraPublishCmd() *cobra.Command {
|
||||||
return &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "jira",
|
Use: "jira",
|
||||||
Short: "Publishes the campaign tickets in JIRA",
|
Short: "Publishes the campaign tickets in JIRA",
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
Run: jiraPublishCmdF,
|
RunE: jiraPublishCmdF,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cmd.Flags().BoolP("all", "a", false, "Publish all the tickets of the campaign")
|
||||||
|
cmd.Flags().IntP("batch", "b", 0, "Number of tickets to publish")
|
||||||
|
|
||||||
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func PublishCmd() *cobra.Command {
|
func PublishCmd() *cobra.Command {
|
||||||
|
@ -26,4 +31,15 @@ func PublishCmd() *cobra.Command {
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func jiraPublishCmdF(_ *cobra.Command, _ []string) {}
|
func jiraPublishCmdF(cmd *cobra.Command, _ []string) error {
|
||||||
|
/*
|
||||||
|
all, _ := cmd.Flags().GetBool("all")
|
||||||
|
batch, _ := cmd.Flags().GetInt("batch")
|
||||||
|
|
||||||
|
if !all && batch == 0 {
|
||||||
|
return fmt.Errorf("One of --all or --batch flags is required")
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
|
||||||
|
|
||||||
"git.ctrlz.es/mgdelacroix/campaigner/config"
|
"git.ctrlz.es/mgdelacroix/campaigner/config"
|
||||||
"git.ctrlz.es/mgdelacroix/campaigner/jira"
|
"git.ctrlz.es/mgdelacroix/campaigner/jira"
|
||||||
|
"git.ctrlz.es/mgdelacroix/campaigner/model"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
@ -34,19 +33,19 @@ func CreateJiraTicketStandaloneCmd() *cobra.Command {
|
||||||
RunE: createJiraTicketStandaloneCmdF,
|
RunE: createJiraTicketStandaloneCmdF,
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.Flags().String("url", "", "the jira server URL")
|
cmd.Flags().String("url", "", "The jira server URL")
|
||||||
_ = cmd.MarkFlagRequired("url")
|
_ = cmd.MarkFlagRequired("url")
|
||||||
cmd.Flags().String("epic", "", "the jira epic id to associate the ticket with")
|
cmd.Flags().String("epic", "", "The jira epic id to associate the ticket with")
|
||||||
_ = cmd.MarkFlagRequired("epic")
|
_ = cmd.MarkFlagRequired("epic")
|
||||||
cmd.Flags().String("team", "", "the team for the new ticket")
|
cmd.Flags().StringP("project", "p", "", "The jira project key to associate the tickets with")
|
||||||
_ = cmd.MarkFlagRequired("epic")
|
_ = cmd.MarkFlagRequired("project")
|
||||||
cmd.Flags().String("username", "", "the jira username")
|
cmd.Flags().String("summary", "", "The summary of the ticket")
|
||||||
cmd.Flags().String("token", "", "the jira token")
|
|
||||||
cmd.Flags().String("summary", "", "the summary of the ticket")
|
|
||||||
_ = cmd.MarkFlagRequired("summary")
|
_ = cmd.MarkFlagRequired("summary")
|
||||||
cmd.Flags().String("template", "", "the template to render the description of the ticket")
|
cmd.Flags().String("template", "", "The template to render the description of the ticket")
|
||||||
_ = cmd.MarkFlagRequired("template")
|
_ = cmd.MarkFlagRequired("template")
|
||||||
cmd.Flags().StringSliceP("vars", "v", []string{}, "the variables to use in the 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")
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
@ -59,16 +58,16 @@ func GetJiraTicketStandaloneCmd() *cobra.Command {
|
||||||
Run: getJiraTicketStandaloneCmdF,
|
Run: getJiraTicketStandaloneCmdF,
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.Flags().String("url", "", "the jira server URL")
|
cmd.Flags().String("url", "", "The jira server URL")
|
||||||
_ = cmd.MarkFlagRequired("url")
|
_ = cmd.MarkFlagRequired("url")
|
||||||
cmd.Flags().String("username", "", "the jira username")
|
cmd.Flags().String("username", "", "The jira username")
|
||||||
cmd.Flags().String("token", "", "the jira token")
|
cmd.Flags().String("token", "", "The jira token")
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func getVarMap(vars []string) (map[string]string, error) {
|
func getVarMap(vars []string) (map[string]interface{}, error) {
|
||||||
varMap := map[string]string{}
|
varMap := map[string]interface{}{}
|
||||||
for _, v := range vars {
|
for _, v := range vars {
|
||||||
parts := strings.Split(v, "=")
|
parts := strings.Split(v, "=")
|
||||||
if len(parts) < 2 {
|
if len(parts) < 2 {
|
||||||
|
@ -81,12 +80,12 @@ func getVarMap(vars []string) (map[string]string, error) {
|
||||||
|
|
||||||
func createJiraTicketStandaloneCmdF(cmd *cobra.Command, _ []string) error {
|
func createJiraTicketStandaloneCmdF(cmd *cobra.Command, _ []string) error {
|
||||||
url, _ := cmd.Flags().GetString("url")
|
url, _ := cmd.Flags().GetString("url")
|
||||||
epicId, _ := cmd.Flags().GetString("epic")
|
epic, _ := cmd.Flags().GetString("epic")
|
||||||
team, _ := cmd.Flags().GetString("team")
|
project, _ := cmd.Flags().GetString("project")
|
||||||
username, _ := cmd.Flags().GetString("username")
|
username, _ := cmd.Flags().GetString("username")
|
||||||
token, _ := cmd.Flags().GetString("token")
|
token, _ := cmd.Flags().GetString("token")
|
||||||
summaryTmplStr, _ := cmd.Flags().GetString("summary")
|
summary, _ := cmd.Flags().GetString("summary")
|
||||||
templatePath, _ := cmd.Flags().GetString("template")
|
template, _ := cmd.Flags().GetString("template")
|
||||||
vars, _ := cmd.Flags().GetStringSlice("vars")
|
vars, _ := cmd.Flags().GetStringSlice("vars")
|
||||||
|
|
||||||
if username == "" || token == "" {
|
if username == "" || token == "" {
|
||||||
|
@ -108,39 +107,25 @@ func createJiraTicketStandaloneCmdF(cmd *cobra.Command, _ []string) error {
|
||||||
return fmt.Errorf("error processing vars: %w", err)
|
return fmt.Errorf("error processing vars: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
sumTmpl, err := template.New("").Parse(summaryTmplStr)
|
|
||||||
if err != nil {
|
|
||||||
ErrorAndExit(cmd, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var summaryBytes bytes.Buffer
|
|
||||||
if err := sumTmpl.Execute(&summaryBytes, varMap); err != nil {
|
|
||||||
ErrorAndExit(cmd, err)
|
|
||||||
}
|
|
||||||
summary := summaryBytes.String()
|
|
||||||
|
|
||||||
descTmpl, err := template.ParseFiles(templatePath)
|
|
||||||
if err != nil {
|
|
||||||
ErrorAndExit(cmd, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var descriptionBytes bytes.Buffer
|
|
||||||
if err := descTmpl.Execute(&descriptionBytes, varMap); err != nil {
|
|
||||||
ErrorAndExit(cmd, err)
|
|
||||||
}
|
|
||||||
description := descriptionBytes.String()
|
|
||||||
|
|
||||||
jiraClient, err := jira.NewClient(url, username, token)
|
jiraClient, err := jira.NewClient(url, username, token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ErrorAndExit(cmd, err)
|
ErrorAndExit(cmd, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ticketKey, err := jiraClient.CreateIssue(epicId, team, summary, description)
|
campaign := &model.Campaign{
|
||||||
|
Epic: epic,
|
||||||
|
Project: project,
|
||||||
|
Summary: summary,
|
||||||
|
Template: template,
|
||||||
|
}
|
||||||
|
ticket := &model.Ticket{Data: varMap}
|
||||||
|
|
||||||
|
issue, err := jiraClient.CreateTicket(ticket, campaign)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ErrorAndExit(cmd, err)
|
ErrorAndExit(cmd, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.Printf("Ticket %s successfully created in JIRA", ticketKey)
|
cmd.Printf("Ticket %s successfully created in JIRA", issue.Key)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
106
jira/jira.go
106
jira/jira.go
|
@ -1,6 +1,13 @@
|
||||||
package jira
|
package jira
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"bytes"
|
||||||
|
"text/template"
|
||||||
|
|
||||||
|
"git.ctrlz.es/mgdelacroix/campaigner/model"
|
||||||
|
|
||||||
jira "gopkg.in/andygrunwald/go-jira.v1"
|
jira "gopkg.in/andygrunwald/go-jira.v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -8,6 +15,64 @@ type JiraClient struct {
|
||||||
*jira.Client
|
*jira.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *JiraClient) GetIssueFromTicket(ticket *model.Ticket, campaign *model.Campaign) (*jira.Issue, error) {
|
||||||
|
summaryTmpl, err := template.New("").Parse(campaign.Summary)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var summaryBytes bytes.Buffer
|
||||||
|
if err := summaryTmpl.Execute(&summaryBytes, ticket.Data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
summary := summaryBytes.String()
|
||||||
|
|
||||||
|
descriptionTemplate, err := template.ParseFiles(campaign.Template)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var descriptionBytes bytes.Buffer
|
||||||
|
if err := descriptionTemplate.Execute(&descriptionBytes, ticket.Data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
description := descriptionBytes.String()
|
||||||
|
|
||||||
|
data := map[string]string{
|
||||||
|
"Description": description,
|
||||||
|
"Summary": summary,
|
||||||
|
"Project": campaign.Project,
|
||||||
|
"Issue Type": "Story",
|
||||||
|
"Epic Link": campaign.Epic,
|
||||||
|
}
|
||||||
|
|
||||||
|
if team, ok := ticket.Data["team"]; ok {
|
||||||
|
data["team"] = team.(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
createMetaInfo, _, err := c.Issue.GetCreateMeta(campaign.Project)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
project := createMetaInfo.GetProjectWithKey(campaign.Project)
|
||||||
|
if project == nil {
|
||||||
|
return nil, fmt.Errorf("Error retrieving project with key %s", campaign.Project)
|
||||||
|
}
|
||||||
|
|
||||||
|
issueType := project.GetIssueTypeWithName("Story")
|
||||||
|
if issueType == nil {
|
||||||
|
return nil, fmt.Errorf("Error retrieving issue type with name Story")
|
||||||
|
}
|
||||||
|
|
||||||
|
issue, err := jira.InitIssueWithMetaAndFields(project, issueType, data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return issue, nil
|
||||||
|
}
|
||||||
|
|
||||||
func NewClient(url, username, token string) (*JiraClient, error) {
|
func NewClient(url, username, token string) (*JiraClient, error) {
|
||||||
tp := jira.BasicAuthTransport{
|
tp := jira.BasicAuthTransport{
|
||||||
Username: username,
|
Username: username,
|
||||||
|
@ -22,38 +87,21 @@ func NewClient(url, username, token string) (*JiraClient, error) {
|
||||||
return &JiraClient{client}, nil
|
return &JiraClient{client}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *JiraClient) CreateIssue(epicId, team, summary, description string) (string, error) {
|
func (c *JiraClient) CreateTicket(ticket *model.Ticket, campaign *model.Campaign) (*jira.Issue, error) {
|
||||||
/*
|
issue, err := c.GetIssueFromTicket(ticket, campaign)
|
||||||
data := map[string]interface{}{
|
if err != nil {
|
||||||
"fields": map[string]interface{}{
|
return nil, err
|
||||||
"project": map[string]interface{}{"key": "MM"},
|
}
|
||||||
"summary": summary,
|
|
||||||
"description": description,
|
|
||||||
"issuetype": map[string]interface{}{"name": "Story"},
|
|
||||||
"customfield_10007": epicId,
|
|
||||||
"customfield_11101": map[string]interface{}{"value": team},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
body, err := json.Marshal(data)
|
b, _ := json.MarshalIndent(issue, "", " ")
|
||||||
if err != nil {
|
fmt.Println(string(b))
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
res, err := http.DoPost(c.Username, c.Token, c.Url+"issue/", body)
|
newIssue, _, err := c.Issue.Create(issue)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer res.Body.Close()
|
|
||||||
|
|
||||||
issue, err := IssueFromJson(res.Body)
|
return newIssue, nil
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return issue.Key, nil
|
|
||||||
*/
|
|
||||||
return "", nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *JiraClient) GetIssue(issueNo string) (*jira.Issue, error) {
|
func (c *JiraClient) GetIssue(issueNo string) (*jira.Issue, error) {
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
package model
|
package model
|
||||||
|
|
||||||
|
// ToDo: add key-value extra params as a map to allow for customfield_whatever = team
|
||||||
type Campaign struct {
|
type Campaign struct {
|
||||||
Url string `json:"url"`
|
Url string `json:"url"`
|
||||||
Project string `json:"project"`
|
Project string `json:"project"`
|
||||||
Epic string `json:"epic"`
|
Epic string `json:"epic"`
|
||||||
Summary string `json:"summary"`
|
Summary string `json:"summary"`
|
||||||
Tickets []*Ticket `json:"tickets,omitempty"`
|
Template string `json:"template"`
|
||||||
|
Tickets []*Ticket `json:"tickets,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue