From 527d3cdc0329568c018b14353d88107590c1e581 Mon Sep 17 00:00:00 2001 From: Rodrigue Cloutier Date: Sat, 27 Jul 2024 05:40:38 -0400 Subject: [PATCH] feat: Add original estimate option to issue creation (#748) --- internal/cmd/issue/create/create.go | 63 ++++++++++++++++------------- internal/cmdcommon/create.go | 34 ++++++++-------- pkg/jira/create.go | 27 ++++++++----- pkg/jira/create_test.go | 28 +++++++------ 4 files changed, 84 insertions(+), 68 deletions(-) diff --git a/internal/cmd/issue/create/create.go b/internal/cmd/issue/create/create.go index d2122682..5e418826 100644 --- a/internal/cmd/issue/create/create.go +++ b/internal/cmd/issue/create/create.go @@ -99,20 +99,21 @@ func create(cmd *cobra.Command, _ []string) { defer s.Stop() cr := jira.CreateRequest{ - Project: project, - IssueType: params.IssueType, - ParentIssueKey: params.ParentIssueKey, - Summary: params.Summary, - Body: params.Body, - Reporter: params.Reporter, - Assignee: params.Assignee, - Priority: params.Priority, - Labels: params.Labels, - Components: params.Components, - FixVersions: params.FixVersions, - AffectsVersions: params.AffectsVersions, - CustomFields: params.CustomFields, - EpicField: viper.GetString("epic.link"), + Project: project, + IssueType: params.IssueType, + ParentIssueKey: params.ParentIssueKey, + Summary: params.Summary, + Body: params.Body, + Reporter: params.Reporter, + Assignee: params.Assignee, + Priority: params.Priority, + Labels: params.Labels, + Components: params.Components, + FixVersions: params.FixVersions, + AffectsVersions: params.AffectsVersions, + OriginalEstimate: params.OriginalEstimate, + CustomFields: params.CustomFields, + EpicField: viper.GetString("epic.link"), } cr.ForProjectType(projectType) cr.ForInstallationType(installation) @@ -347,6 +348,9 @@ func parseFlags(flags query.FlagParser) *cmdcommon.CreateParams { affectsVersions, err := flags.GetStringArray("affects-version") cmdutil.ExitIfError(err) + originalEstimate, err := flags.GetString("original-estimate") + cmdutil.ExitIfError(err) + custom, err := flags.GetStringToString("custom") cmdutil.ExitIfError(err) @@ -360,20 +364,21 @@ func parseFlags(flags query.FlagParser) *cmdcommon.CreateParams { cmdutil.ExitIfError(err) return &cmdcommon.CreateParams{ - IssueType: issueType, - ParentIssueKey: parentIssueKey, - Summary: summary, - Body: body, - Priority: priority, - Assignee: assignee, - Labels: labels, - Reporter: reporter, - Components: components, - FixVersions: fixVersions, - AffectsVersions: affectsVersions, - CustomFields: custom, - Template: template, - NoInput: noInput, - Debug: debug, + IssueType: issueType, + ParentIssueKey: parentIssueKey, + Summary: summary, + Body: body, + Priority: priority, + Assignee: assignee, + Labels: labels, + Reporter: reporter, + Components: components, + FixVersions: fixVersions, + AffectsVersions: affectsVersions, + OriginalEstimate: originalEstimate, + CustomFields: custom, + Template: template, + NoInput: noInput, + Debug: debug, } } diff --git a/internal/cmdcommon/create.go b/internal/cmdcommon/create.go index 47ef9933..7615ba70 100644 --- a/internal/cmdcommon/create.go +++ b/internal/cmdcommon/create.go @@ -23,22 +23,23 @@ const ( // CreateParams holds parameters for create command. type CreateParams struct { - Name string - IssueType string - ParentIssueKey string - Summary string - Body string - Priority string - Reporter string - Assignee string - Labels []string - Components []string - FixVersions []string - AffectsVersions []string - CustomFields map[string]string - Template string - NoInput bool - Debug bool + Name string + IssueType string + ParentIssueKey string + Summary string + Body string + Priority string + Reporter string + Assignee string + Labels []string + Components []string + FixVersions []string + AffectsVersions []string + OriginalEstimate string + CustomFields map[string]string + Template string + NoInput bool + Debug bool } // SetCreateFlags sets flags supported by create command. @@ -63,6 +64,7 @@ And, this field is mandatory when creating a sub-task.`) cmd.Flags().StringArrayP("component", "C", []string{}, prefix+" components") cmd.Flags().StringArray("fix-version", []string{}, "Release info (fixVersions)") cmd.Flags().StringArray("affects-version", []string{}, "Release info (affectsVersions)") + cmd.Flags().StringP("original-estimate", "e", "", prefix+" Original estimate") cmd.Flags().StringToString("custom", custom, "Set custom fields") cmd.Flags().StringP("template", "T", "", "Path to a file to read body/description from") cmd.Flags().Bool("web", false, "Open in web browser after successful creation") diff --git a/pkg/jira/create.go b/pkg/jira/create.go index 0f4edbd7..7915dcc6 100644 --- a/pkg/jira/create.go +++ b/pkg/jira/create.go @@ -24,16 +24,17 @@ type CreateRequest struct { IssueType string // ParentIssueKey is required when creating a sub-task for classic project. // This can also be used to attach epic for next-gen project. - ParentIssueKey string - Summary string - Body interface{} // string in v1/v2 and adf.ADF in v3 - Reporter string - Assignee string - Priority string - Labels []string - Components []string - FixVersions []string - AffectsVersions []string + ParentIssueKey string + Summary string + Body interface{} // string in v1/v2 and adf.ADF in v3 + Reporter string + Assignee string + Priority string + Labels []string + Components []string + FixVersions []string + AffectsVersions []string + OriginalEstimate string // EpicField is the dynamic epic field name // that changes per jira installation. EpicField string @@ -132,6 +133,9 @@ func (*Client) getRequestData(req *CreateRequest) *createRequest { Summary: req.Summary, Labels: req.Labels, epicField: req.EpicField, + TimeTracking: struct { + OriginalEstimate string `json:"originalEstimate,omitempty"` + }{OriginalEstimate: req.OriginalEstimate}, } switch v := req.Body.(type) { @@ -303,6 +307,9 @@ type createFields struct { AffectsVersions []struct { Name string `json:"name,omitempty"` } `json:"versions,omitempty"` + TimeTracking struct { + OriginalEstimate string `json:"originalEstimate,omitempty"` + } `json:"timetracking,omitempty"` epicField string customFields customField } diff --git a/pkg/jira/create_test.go b/pkg/jira/create_test.go index e1320d76..8f8ba490 100644 --- a/pkg/jira/create_test.go +++ b/pkg/jira/create_test.go @@ -46,7 +46,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":"Test description","priority":{"name":"Normal"},"labels":["test","dev"],` + - `"components":[{"name":"BE"},{"name":"FE"}],"fixVersions":[{"name":"v2.0"},{"name":"v2.1-hotfix"}],"versions":[{"name":"v3.0"},{"name":"v3.1-hotfix"}]}}` + `"components":[{"name":"BE"},{"name":"FE"}],"fixVersions":[{"name":"v2.0"},{"name":"v2.1-hotfix"}],"versions":[{"name":"v3.0"},{"name":"v3.1-hotfix"}],` + + `"timetracking":{"originalEstimate":"2d"}}}` testServer := createTestServer{code: 201} server := testServer.serve(t, expectedBody) defer server.Close() @@ -54,15 +55,16 @@ func TestCreate(t *testing.T) { client := NewClient(Config{Server: server.URL}, WithTimeout(3*time.Second)) requestData := CreateRequest{ - Project: "TEST", - IssueType: "Bug", - Summary: "Test bug", - Body: "Test description", - Priority: "Normal", - Labels: []string{"test", "dev"}, - Components: []string{"BE", "FE"}, - FixVersions: []string{"v2.0", "v2.1-hotfix"}, - AffectsVersions: []string{"v3.0", "v3.1-hotfix"}, + Project: "TEST", + IssueType: "Bug", + Summary: "Test bug", + Body: "Test description", + Priority: "Normal", + Labels: []string{"test", "dev"}, + Components: []string{"BE", "FE"}, + FixVersions: []string{"v2.0", "v2.1-hotfix"}, + AffectsVersions: []string{"v3.0", "v3.1-hotfix"}, + OriginalEstimate: "2d", } actual, err := client.CreateV2(&requestData) assert.NoError(t, err) @@ -82,7 +84,7 @@ func TestCreate(t *testing.T) { func TestCreateSubtask(t *testing.T) { expectedBody := `{"update":{},"fields":{"project":{"key":"TEST"},"issuetype":{"name":"Sub-task"},` + - `"parent":{"key":"TEST-123"},"summary":"Test sub-task","description":"Test description"}}` + `"parent":{"key":"TEST-123"},"summary":"Test sub-task","description":"Test description","timetracking":{}}}` testServer := createTestServer{code: 201} server := testServer.serve(t, expectedBody) defer server.Close() @@ -114,7 +116,7 @@ func TestCreateSubtask(t *testing.T) { func TestCreateEpic(t *testing.T) { expectedBody := `{"update":{},"fields":{"customfield_10001":"CLI","description":"Test description","issuetype":{"name":` + - `"Bug"},"priority":{"name":"Normal"},"project":{"key":"TEST"},"summary":"Test bug"}}` + `"Bug"},"priority":{"name":"Normal"},"project":{"key":"TEST"},"summary":"Test bug", "timetracking":{}}}` testServer := createTestServer{code: 201} server := testServer.serve(t, expectedBody) defer server.Close() @@ -146,7 +148,7 @@ func TestCreateEpic(t *testing.T) { func TestCreateEpicNextGen(t *testing.T) { expectedBody := `{"update":{},"fields":{"description":"Test description","issuetype":{"name":"Bug"},` + - `"parent":{"key":"TEST-123"},"project":{"key":"TEST"},"summary":"Test bug"}}` + `"parent":{"key":"TEST-123"},"project":{"key":"TEST"},"summary":"Test bug","timetracking":{}}}` testServer := createTestServer{code: 201} server := testServer.serve(t, expectedBody) defer server.Close()