Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 62 additions & 43 deletions internal/cmd/issue/edit/edit.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,16 +148,16 @@ func edit(cmd *cobra.Command, args []string) {
}

edr := jira.EditRequest{
ParentIssueKey: parent,
Summary: params.summary,
Body: body,
Priority: params.priority,
Labels: labels,
Components: components,
FixVersions: fixVersions,
AffectsVersions: affectsVersions,
CustomFields: params.customFields,
SkipNotify: params.skipNotify,
ParentIssueKey: parent,
Summary: params.summary,
Body: body,
Priority: params.priority,
Labels: labels,
OriginalEstimate: params.originalEstimate,
Components: components,
FixVersions: fixVersions,
AffectsVersions: affectsVersions,
CustomFields: params.customFields,
}
if configuredCustomFields, err := cmdcommon.GetConfiguredCustomFields(); err == nil {
cmdcommon.ValidateCustomFields(edr.CustomFields, configuredCustomFields)
Expand Down Expand Up @@ -195,11 +195,12 @@ func getAnswers(params *editParams, issue *jira.Issue) {
if len(ans.Metadata) > 0 {
qs := getMetadataQuestions(ans.Metadata, issue)
ans := struct {
Priority string
Labels string
Components string
FixVersions string
AffectsVersions string
Priority string
Labels string
OriginalEstimate string
Components string
FixVersions string
AffectsVersions string
}{}
err := survey.Ask(qs, &ans)
cmdutil.ExitIfError(err)
Expand All @@ -210,6 +211,9 @@ func getAnswers(params *editParams, issue *jira.Issue) {
if len(ans.Labels) > 0 {
params.labels = strings.Split(ans.Labels, ",")
}
if ans.OriginalEstimate != "" {
params.originalEstimate = ans.OriginalEstimate
}
if len(ans.Components) > 0 {
params.components = strings.Split(ans.Components, ",")
}
Expand Down Expand Up @@ -301,20 +305,21 @@ func (ec *editCmd) askQuestions(issue *jira.Issue, originalBody string) error {
}

type editParams struct {
issueKey string
parentIssueKey string
summary string
body string
priority string
assignee string
labels []string
components []string
fixVersions []string
affectsVersions []string
customFields map[string]string
skipNotify bool
noInput bool
debug bool
issueKey string
parentIssueKey string
summary string
body string
priority string
assignee string
labels []string
originalEstimate string
components []string
fixVersions []string
affectsVersions []string
customFields map[string]string
noInput bool
debug bool
skipNotify bool
}

func parseArgsAndFlags(flags query.FlagParser, args []string, project string) *editParams {
Expand All @@ -336,6 +341,9 @@ func parseArgsAndFlags(flags query.FlagParser, args []string, project string) *e
labels, err := flags.GetStringArray("label")
cmdutil.ExitIfError(err)

originalEstimate, err := flags.GetString("original-estimate")
cmdutil.ExitIfError(err)

components, err := flags.GetStringArray("component")
cmdutil.ExitIfError(err)

Expand All @@ -358,20 +366,21 @@ func parseArgsAndFlags(flags query.FlagParser, args []string, project string) *e
cmdutil.ExitIfError(err)

return &editParams{
issueKey: cmdutil.GetJiraIssueKey(project, args[0]),
parentIssueKey: parentIssueKey,
summary: summary,
body: body,
priority: priority,
assignee: assignee,
labels: labels,
components: components,
fixVersions: fixVersions,
affectsVersions: affectsVersions,
customFields: custom,
skipNotify: skipNotify,
noInput: noInput,
debug: debug,
issueKey: cmdutil.GetJiraIssueKey(project, args[0]),
parentIssueKey: parentIssueKey,
summary: summary,
body: body,
priority: priority,
assignee: assignee,
labels: labels,
originalEstimate: originalEstimate,
components: components,
fixVersions: fixVersions,
affectsVersions: affectsVersions,
customFields: custom,
noInput: noInput,
debug: debug,
skipNotify: skipNotify,
}
}

Expand Down Expand Up @@ -412,6 +421,15 @@ func getMetadataQuestions(meta []string, issue *jira.Issue) []*survey.Question {
Default: strings.Join(issue.Fields.Labels, ","),
},
})
case "OriginalEstimate":
qs = append(qs, &survey.Question{
Name: "originalestimate",
Prompt: &survey.Input{
Message: "Estimate",
Help: "Estimate in hours",
Default: issue.Fields.OriginalEstimate,
},
})
case "FixVersions":
qs = append(qs, &survey.Question{
Name: "fixversions",
Expand Down Expand Up @@ -447,6 +465,7 @@ func setFlags(cmd *cobra.Command) {
cmd.Flags().StringP("priority", "y", "", "Edit priority")
cmd.Flags().StringP("assignee", "a", "", "Edit assignee (email or display name)")
cmd.Flags().StringArrayP("label", "l", []string{}, "Append labels")
cmd.Flags().StringP("original-estimate", "e", "", "Original Estimate in hours")
cmd.Flags().StringArrayP("component", "C", []string{}, "Replace components")
cmd.Flags().StringArray("fix-version", []string{}, "Add/Append release info (fixVersions)")
cmd.Flags().StringArray("affects-version", []string{}, "Add/Append release info (affectsVersions)")
Expand Down
28 changes: 20 additions & 8 deletions internal/cmdcommon/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ func GetMetadata() []*survey.Question {
Name: "metadata",
Prompt: &survey.MultiSelect{
Message: "What would you like to add?",
Options: []string{"Priority", "Components", "Labels", "FixVersions", "AffectsVersions"},
Options: []string{"Priority", "Components", "Labels", "OriginalEstimate", "FixVersions", "AffectsVersions"},
Copy link
Owner

@ankitpokhrel ankitpokhrel Mar 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Edit seem to work fine but this will add OriginalEstimate for create command as well and we don't actually seem to process that. We'd need to fix original estimate in create flow.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @ankitpokhrel , now my time to say.. sorry for late repply.
The OriginalEstimate field is already part of the creation flow. It was included in the editing flow. Unless I am misunderstanding, the field already belongs to the creation flow.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I think I now understand the treatment for the field, I made the adjustments as informed.

},
},
}
Expand Down Expand Up @@ -127,6 +127,14 @@ func GetMetadataQuestions(cat []string) []*survey.Question {
Help: "Comma separated list of labels. For eg: backend,urgent",
},
})
case "OriginalEstimate":
qs = append(qs, &survey.Question{
Name: "originalestimate",
Prompt: &survey.Input{
Message: "Original Estimate",
Help: "Original estimate in the format of 1w 2d 3h 4m (weeks, days, hours, minutes). For eg: 1w 2d 3h 4m",
},
})
case "FixVersions":
qs = append(qs, &survey.Question{
Name: "fixversions",
Expand Down Expand Up @@ -171,11 +179,12 @@ func HandleNoInput(params *CreateParams) error {
if len(ans.Metadata) > 0 {
qs := GetMetadataQuestions(ans.Metadata)
ans := struct {
Priority string
Labels string
Components string
FixVersions string
AffectsVersions string
Priority string
Labels string
OriginalEstimate string
Components string
FixVersions string
AffectsVersions string
}{}
err := survey.Ask(qs, &ans)
if err != nil {
Expand All @@ -188,6 +197,9 @@ func HandleNoInput(params *CreateParams) error {
if len(ans.Labels) > 0 {
params.Labels = strings.Split(ans.Labels, ",")
}
if len(ans.OriginalEstimate) > 0 {
params.OriginalEstimate = ans.OriginalEstimate
}
if len(ans.Components) > 0 {
params.Components = strings.Split(ans.Components, ",")
}
Expand Down Expand Up @@ -248,13 +260,13 @@ func ValidateCustomFields(fields map[string]string, configuredFields []jira.Issu

fieldsMap := make(map[string]string)
for _, configured := range configuredFields {
identifier := strings.ReplaceAll(strings.ToLower(strings.TrimSpace(configured.Name)), " ", "-")
identifier := strings.ToLower(strings.TrimSpace(strings.ReplaceAll(configured.Name, " ", "-")))
fieldsMap[identifier] = configured.Name
}

invalidCustomFields := make([]string, 0, len(fields))
for key := range fields {
if _, ok := fieldsMap[key]; !ok {
if _, ok := fieldsMap[strings.ToLower(strings.TrimSpace(key))]; !ok {
invalidCustomFields = append(invalidCustomFields, key)
}
}
Expand Down
31 changes: 22 additions & 9 deletions pkg/jira/edit.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,16 @@ type EditResponse struct {
// EditRequest struct holds request data for edit request.
// Setting an Assignee requires an account ID.
type EditRequest struct {
IssueType string
ParentIssueKey string
Summary string
Body string
Priority string
Labels []string
Components []string
FixVersions []string
AffectsVersions []string
IssueType string
ParentIssueKey string
Summary string
Body string
Priority string
Labels []string
OriginalEstimate string
Components []string
FixVersions []string
AffectsVersions []string
// CustomFields holds all custom fields passed
// while editing the issue.
CustomFields map[string]string
Expand Down Expand Up @@ -92,6 +93,11 @@ type editFields struct {
Add string `json:"add,omitempty"`
Remove string `json:"remove,omitempty"`
} `json:"labels,omitempty"`
Timetracking []struct {
Edit struct {
OriginalEstimate string `json:"originalEstimate,omitempty"`
} `json:"edit,omitempty"`
} `json:"timetracking,omitempty"`
Components []struct {
Add *struct {
Name string `json:"name,omitempty"`
Expand Down Expand Up @@ -186,6 +192,13 @@ func getRequestDataForEdit(req *EditRequest) *editRequest {
}{{Set: struct {
Name string `json:"name,omitempty"`
}{Name: req.Priority}}},
Timetracking: []struct {
Edit struct {
OriginalEstimate string `json:"originalEstimate,omitempty"`
} `json:"edit,omitempty"`
}{{Edit: struct {
OriginalEstimate string `json:"originalEstimate,omitempty"`
}{OriginalEstimate: req.OriginalEstimate}}},
}}

if len(req.Labels) > 0 {
Expand Down
9 changes: 5 additions & 4 deletions pkg/jira/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,11 @@ type Issue struct {

// IssueFields holds issue fields.
type IssueFields struct {
Summary string `json:"summary"`
Description interface{} `json:"description"` // string in v1/v2, adf.ADF in v3
Labels []string `json:"labels"`
Resolution struct {
Summary string `json:"summary"`
Description interface{} `json:"description"` // string in v1/v2, adf.ADF in v3
Labels []string `json:"labels"`
OriginalEstimate string `json:"originalEstimate"`
Resolution struct {
Name string `json:"name"`
} `json:"resolution"`
IssueType IssueType `json:"issueType"`
Expand Down