Repository: ankitpokhrel/jira-cli
Pull request #66 (2021-01-24 12:01:36)

feat: Allow to add components during issue creation


Patch:
diff --git a/internal/cmd/epic/create/create.go b/internal/cmd/epic/create/create.go
index 8f55466..7354e77 100644
--- a/internal/cmd/epic/create/create.go
+++ b/internal/cmd/epic/create/create.go
@@ -71,6 +71,7 @@ func create(cmd *cobra.Command, _ []string) {
 			Body:          flags.body,
 			Priority:      flags.priority,
 			Labels:        flags.labels,
+			Components:    flags.components,
 			EpicFieldName: viper.GetString("epic.field"),
 		})
 		cmdutil.ExitIfError(err)
@@ -95,6 +96,7 @@ func SetFlags(cmd *cobra.Command) {
 	cmd.Flags().StringP("body", "b", "", "Epic description")
 	cmd.Flags().StringP("priority", "y", "", "Epic priority")
 	cmd.Flags().StringArrayP("label", "l", []string{}, "Epic labels")
+	cmd.Flags().StringArrayP("component", "C", []string{}, "Epic components")
 	cmd.Flags().Bool("web", false, "Open epic in web browser after successful creation")
 	cmd.Flags().Bool("no-input", false, "Disable prompt for non-required fields")
 }
@@ -130,13 +132,14 @@ func getQuestions(params *createParams) []*survey.Question {
 }
 
 type createParams struct {
-	name     string
-	summary  string
-	body     string
-	priority string
-	labels   []string
-	noInput  bool
-	debug    bool
+	name       string
+	summary    string
+	body       string
+	priority   string
+	labels     []string
+	components []string
+	noInput    bool
+	debug      bool
 }
 
 func parseFlags(flags query.FlagParser) *createParams {
@@ -155,6 +158,9 @@ func parseFlags(flags query.FlagParser) *createParams {
 	labels, err := flags.GetStringArray("label")
 	cmdutil.ExitIfError(err)
 
+	components, err := flags.GetStringArray("component")
+	cmdutil.ExitIfError(err)
+
 	noInput, err := flags.GetBool("no-input")
 	cmdutil.ExitIfError(err)
 
@@ -162,12 +168,13 @@ func parseFlags(flags query.FlagParser) *createParams {
 	cmdutil.ExitIfError(err)
 
 	return &createParams{
-		name:     name,
-		summary:  summary,
-		body:     body,
-		priority: priority,
-		labels:   labels,
-		noInput:  noInput,
-		debug:    debug,
+		name:       name,
+		summary:    summary,
+		body:       body,
+		priority:   priority,
+		labels:     labels,
+		components: components,
+		noInput:    noInput,
+		debug:      debug,
 	}
 }
diff --git a/internal/cmd/issue/create/create.go b/internal/cmd/issue/create/create.go
index 7ad9159..dd507a5 100644
--- a/internal/cmd/issue/create/create.go
+++ b/internal/cmd/issue/create/create.go
@@ -86,14 +86,17 @@ func create(cmd *cobra.Command, _ []string) {
 		s := cmdutil.Info("Creating an issue...")
 		defer s.Stop()
 
-		resp, err := client.Create(&jira.CreateRequest{
-			Project:   project,
-			IssueType: params.issueType,
-			Summary:   params.summary,
-			Body:      params.body,
-			Priority:  params.priority,
-			Labels:    params.labels,
-		})
+		cr := jira.CreateRequest{
+			Project:    project,
+			IssueType:  params.issueType,
+			Summary:    params.summary,
+			Body:       params.body,
+			Priority:   params.priority,
+			Labels:     params.labels,
+			Components: params.components,
+		}
+
+		resp, err := client.Create(&cr)
 		cmdutil.ExitIfError(err)
 
 		return resp.Key
@@ -116,6 +119,7 @@ func SetFlags(cmd *cobra.Command) {
 	cmd.Flags().StringP("body", "b", "", "Issue description")
 	cmd.Flags().StringP("priority", "y", "", "Issue priority")
 	cmd.Flags().StringArrayP("label", "l", []string{}, "Issue labels")
+	cmd.Flags().StringArrayP("component", "C", []string{}, "Issue components")
 	cmd.Flags().Bool("web", false, "Open issue in web browser after successful creation")
 	cmd.Flags().Bool("no-input", false, "Disable prompt for non-required fields")
 }
@@ -208,13 +212,14 @@ func (cc *createCmd) getQuestions() []*survey.Question {
 }
 
 type createParams struct {
-	issueType string
-	summary   string
-	body      string
-	priority  string
-	labels    []string
-	noInput   bool
-	debug     bool
+	issueType  string
+	summary    string
+	body       string
+	priority   string
+	labels     []string
+	components []string
+	noInput    bool
+	debug      bool
 }
 
 func parseFlags(flags query.FlagParser) *createParams {
@@ -233,6 +238,9 @@ func parseFlags(flags query.FlagParser) *createParams {
 	labels, err := flags.GetStringArray("label")
 	cmdutil.ExitIfError(err)
 
+	components, err := flags.GetStringArray("component")
+	cmdutil.ExitIfError(err)
+
 	noInput, err := flags.GetBool("no-input")
 	cmdutil.ExitIfError(err)
 
@@ -240,12 +248,13 @@ func parseFlags(flags query.FlagParser) *createParams {
 	cmdutil.ExitIfError(err)
 
 	return &createParams{
-		issueType: issueType,
-		summary:   summary,
-		body:      body,
-		priority:  priority,
-		labels:    labels,
-		noInput:   noInput,
-		debug:     debug,
+		issueType:  issueType,
+		summary:    summary,
+		body:       body,
+		priority:   priority,
+		labels:     labels,
+		components: components,
+		noInput:    noInput,
+		debug:      debug,
 	}
 }
diff --git a/pkg/jira/create.go b/pkg/jira/create.go
index 7bd3834..b150f9d 100644
--- a/pkg/jira/create.go
+++ b/pkg/jira/create.go
@@ -14,13 +14,14 @@ type CreateResponse struct {
 
 // CreateRequest struct holds request data for create request.
 type CreateRequest struct {
-	Project   string
-	Name      string
-	IssueType string
-	Summary   string
-	Body      string
-	Priority  string
-	Labels    []string
+	Project    string
+	Name       string
+	IssueType  string
+	Summary    string
+	Body       string
+	Priority   string
+	Labels     []string
+	Components []string
 	// EpicFieldName is the dynamic epic field name
 	// that changes per jira installation.
 	EpicFieldName string
@@ -85,7 +86,10 @@ type createFields struct {
 	Priority    *struct {
 		Name string `json:"name,omitempty"`
 	} `json:"priority,omitempty"`
-	Labels []string `json:"labels,omitempty"`
+	Labels     []string `json:"labels,omitempty"`
+	Components []struct {
+		Name string `json:"name,omitempty"`
+	} `json:"components,omitempty"`
 
 	epicFieldName string
 }
@@ -163,6 +167,18 @@ func (c *Client) getRequestData(req *CreateRequest) *createRequest {
 			}},
 		}
 	}
+	if len(req.Components) > 0 {
+		comps := make([]struct {
+			Name string `json:"name,omitempty"`
+		}, 0, len(req.Components))
+
+		for _, c := range req.Components {
+			comps = append(comps, struct {
+				Name string `json:"name,omitempty"`
+			}{c})
+		}
+		data.Fields.M.Components = comps
+	}
 
 	return &data
 }


Test patch:
diff --git a/pkg/jira/create_test.go b/pkg/jira/create_test.go
index 691ad41..5a13774 100644
--- a/pkg/jira/create_test.go
+++ b/pkg/jira/create_test.go
@@ -45,7 +45,8 @@ func (c createTestServer) statusCode(code int) {
 func TestCreate(t *testing.T) {
 	expectedBody := `{"update":{},"fields":{"project":{"key":"TEST"},"issuetype":{"name":"Bug"},` +
 		`"summary":"Test bug","description":{"version":1,"type":"doc","content":[{"type":"paragraph","content":` +
-		`[{"type":"text","text":"Test description"}]}]},"priority":{"name":"Normal"},"labels":["test","dev"]}}`
+		`[{"type":"text","text":"Test description"}]}]},"priority":{"name":"Normal"},"labels":["test","dev"],` +
+		`"components":[{"name":"BE"},{"name":"FE"}]}}`
 	testServer := createTestServer{code: 201}
 	server := testServer.serve(t, expectedBody)
 	defer server.Close()
@@ -53,12 +54,13 @@ func TestCreate(t *testing.T) {
 	client := NewClient(Config{Server: server.URL}, WithTimeout(3))
 
 	requestData := CreateRequest{
-		Project:   "TEST",
-		IssueType: "Bug",
-		Summary:   "Test bug",
-		Body:      "Test description",
-		Priority:  "Normal",
-		Labels:    []string{"test", "dev"},
+		Project:    "TEST",
+		IssueType:  "Bug",
+		Summary:    "Test bug",
+		Body:       "Test description",
+		Priority:   "Normal",
+		Labels:     []string{"test", "dev"},
+		Components: []string{"BE", "FE"},
 	}
 	actual, err := client.Create(&requestData)
 	assert.NoError(t, err)