From 9d82baa0e3edb21ca347933438003651afae72a5 Mon Sep 17 00:00:00 2001 From: eximus Date: Sun, 25 Feb 2024 10:31:38 -0500 Subject: [PATCH] issue estimate - progress on estimations function (need updates on project side to enable setting estimation value) --- README.md | 4 --- api/jira-api.go | 19 +++++++++++++- api/jira-types.go | 60 ++++++++++++++++--------------------------- cmd/issue/estimate.go | 28 +++++++++++++++++--- cmd/issue/issue.go | 1 + 5 files changed, 66 insertions(+), 46 deletions(-) diff --git a/README.md b/README.md index 301c2b4..1b1a08a 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,3 @@ bb help [COMMAND] ``` ## TODO - -- pr list | status filter should include options defined in config file (like issue list) -- pipeline list | status filter should include options defined in config file (like issue list) - diff --git a/api/jira-api.go b/api/jira-api.go index 6a69b5a..aa3e1c5 100644 --- a/api/jira-api.go +++ b/api/jira-api.go @@ -1,3 +1,5 @@ +// vim: foldmethod=indent foldnestmax=1 + package api import ( @@ -64,7 +66,7 @@ func _jiraApiPostPut(method string, endpoint string, body io.Reader) []byte { req.SetBasicAuth(viper.GetString("email"), viper.GetString("jira_token")) resp, err := client.Do(req) cobra.CheckErr(err) - if resp.StatusCode != 204 && resp.StatusCode != 201 { + if resp.StatusCode != 204 && resp.StatusCode != 201 && resp.StatusCode != 200 { errBody, err := io.ReadAll(resp.Body) cobra.CheckErr(err) cobra.CheckErr(string(errBody)) @@ -78,6 +80,10 @@ func jiraApiPost(endpoint string, body io.Reader) []byte { return _jiraApiPostPut("POST", endpoint, body) } +func jiraApiPut(endpoint string, body io.Reader) []byte { + return _jiraApiPostPut("PUT", endpoint, body) +} + // HIGH LEVEL METHODS func GetIssue(key string) <-chan JiraIssue { @@ -186,3 +192,14 @@ func PostWorklog(key string, seconds int) { cobra.CheckErr(err) jiraApiPost(fmt.Sprintf("/issue/%s/worklog", key), bytes.NewReader(content)) } + +func UpdateIssue(key string, data UpdateIssueRequestBody) JiraIssue { + content, err := json.Marshal(data) + cobra.CheckErr(err) + fmt.Println(string(content)) + response := jiraApiPut(fmt.Sprintf("/issue/%s?returnIssue=true", key), bytes.NewReader(content)) + var issue JiraIssue + err = json.Unmarshal(response, &issue) + cobra.CheckErr(err) + return issue +} diff --git a/api/jira-types.go b/api/jira-types.go index f07497d..6c2d375 100644 --- a/api/jira-types.go +++ b/api/jira-types.go @@ -1,22 +1,7 @@ package api -import ( - "errors" - "fmt" -) - const JiraIssueKeyRegex = "[A-Z][A-Z0-9_]*-\\d+" -type IssueStatus string - -const ( - TODO IssueStatus = "todo" - INPROGRESS IssueStatus = "inprogress" - TESTING IssueStatus = "testing" - DONE IssueStatus = "done" - BLOCKED IssueStatus = "blocked" -) - type JiraIssue struct { Key string `json:"key"` Fields struct { @@ -71,6 +56,28 @@ type JiraIssue struct { } `json:"fields"` } +type UpdateIssueRequestBody struct { + Fields struct { + // This on might be enough when set on project + TimeTracking *TimeTracking `json:"timetracking,omitempty"` + Summary string `json:"summary,omitempty"` + } `json:"fields,omitempty"` + Update struct { + TimeTracking []UpdateType[TimeTracking] `json:"timetracking,omitempty"` + } `json:"update,omitempty"` +} + +type UpdateType[K TimeTracking] struct { + Edit *K `json:"edit,omitempty"` + Set *K `json:"set,omitempty"` +} + +type TimeTracking struct { + OriginalEstimate string `json:"originalEstimate,omitempty"` + RemainingEstimate string `json:"remainingEstimate,omitempty"` + TimeSpent string `json:"timeSpent,omitempty"` +} + type JiraTransition struct { Id string Name string @@ -79,26 +86,3 @@ type JiraTransition struct { Name string } } - -// DEFAULT ACTIONS OVERRIDES - -// String is used both by fmt.Print and by Cobra in help text -func (e *IssueStatus) String() string { - return string(*e) -} - -// Set must have pointer receiver so it doesn't change the value of a copy -func (e *IssueStatus) Set(v IssueStatus) error { - switch v { - case TODO, INPROGRESS, TESTING, DONE, BLOCKED: - *e = IssueStatus(v) - return nil - default: - return errors.New(fmt.Sprintf(`must be one of "%s", "%s", "%s", "%s" or "%s"`, TODO, INPROGRESS, TESTING, DONE, BLOCKED)) - } -} - -// Type is only used in help text -func (e *IssueStatus) Type() string { - return "state" -} diff --git a/cmd/issue/estimate.go b/cmd/issue/estimate.go index 25ac32e..93e64cc 100644 --- a/cmd/issue/estimate.go +++ b/cmd/issue/estimate.go @@ -5,6 +5,7 @@ import ( "bb/util" "fmt" "regexp" + "strings" "github.com/spf13/cobra" ) @@ -35,10 +36,31 @@ var EstimateCmd = &cobra.Command{ key = args[0] } - seconds, err := util.ConvertToSeconds(args[1:]) - cobra.CheckErr(err) + var data = api.UpdateIssueRequestBody{} + // data.Fields.Summary = "TASKS - Data recovery for existing tasks" + data.Fields.TimeTracking = &api.TimeTracking{ + OriginalEstimate: strings.Join(args[1:], " "), + } + // data.Update.TimeTracking = []api.UpdateType[api.TimeTracking]{ + // api.UpdateType[api.TimeTracking]{}, + // } + // data.Update.TimeTracking[0].Set = &api.TimeTracking{ + // OriginalEstimate: strings.Join(args[1:], " "), + // } + + api.UpdateIssue(key, data) + issue := <-api.GetIssue(key) + + timeSpent := "-" + if issue.Fields.TimeTracking.TimeSpent != " " { + timeSpent = issue.Fields.TimeTracking.TimeSpent + } - fmt.Println("Not implemented.", key, seconds) + fmt.Println() + util.Printf("%s \033[1;32m%s\033[m %s %s %s\n", util.FormatIssueStatus(issue.Fields.Status.Name), issue.Key, util.FormatIssueType(issue.Fields.Type.Name), issue.Fields.Summary, util.FormatIssuePriority(issue.Fields.Priority.Id, issue.Fields.Priority.Name)) + util.Printf(" Assigned: \033[1;33m%s\033[m -> Reporter: \033[1;36m%s\033[m \033[37m(%d comments)\n", issue.Fields.Assignee.DisplayName, issue.Fields.Reporter.DisplayName, issue.Fields.Comment.Total) + util.Printf(" Time spent: \033[1;34m%s\033[m [ %s/%s ]\n", timeSpent, issue.Fields.TimeTracking.RemainingEstimate, issue.Fields.TimeTracking.OriginalEstimate) + fmt.Println() if transition { } diff --git a/cmd/issue/issue.go b/cmd/issue/issue.go index 14fabf2..100a463 100644 --- a/cmd/issue/issue.go +++ b/cmd/issue/issue.go @@ -31,6 +31,7 @@ func init() { IssueCmd.AddCommand(TransitionCmd) IssueCmd.AddCommand(AssignCmd) IssueCmd.AddCommand(LogCmd) + IssueCmd.AddCommand(EstimateCmd) IssueCmd.PersistentFlags().StringP("repo", "R", "", "selected repository") IssueCmd.PersistentFlags().StringP("domain", "D", "", "your jira domain ( XXXX in https://XXXX.atlassian.net)") }