commit 6de81a7b43fe19e0a9e9791192ffa8c723c0c4ad from: Oliver Lowe date: Thu Jun 19 01:40:34 2025 UTC jira: set correct fields when creating issues Need to omit lots of fields commit - 82b8536397b0c1fe84af1b0ca1aabf33faaabceb commit + 6de81a7b43fe19e0a9e9791192ffa8c723c0c4ad blob - fb5a932b3fc71fc0b29256b428ffa3c53f47ffad blob + 0fca4f89803514e2c44e429cccfbf22ca671a43a --- jira/http.go +++ jira/http.go @@ -9,6 +9,7 @@ import ( "net/url" "os" "path" + "strings" ) type Client struct { @@ -18,6 +19,20 @@ type Client struct { APIRoot *url.URL } +type errorResponse struct { + Errors map[string]string +} + +func (resp errorResponse) Error() string { + errs := make([]string, len(resp.Errors)) + var i int + for k, v := range resp.Errors { + errs[i] = fmt.Sprintf("%s: %s", k, v) + i++ + } + return strings.Join(errs, "; ") +} + func (c *Client) Projects() ([]Project, error) { u := *c.APIRoot u.Path = path.Join(u.Path, "project") @@ -157,10 +172,19 @@ func (c *Client) CreateIssue(issue Issue) (*Issue, err if err != nil { return nil, fmt.Errorf("post json: %w", err) } + defer resp.Body.Close() if resp.StatusCode >= http.StatusBadRequest { - return nil, fmt.Errorf("non-ok status: %s", resp.Status) + var eresp errorResponse + if err := json.NewDecoder(resp.Body).Decode(&eresp); err != nil { + return nil, fmt.Errorf("status %s: decode error response: %w", resp.Status, err) + } + return nil, eresp } - return nil, fmt.Errorf("TODO") + var created Issue + if err := json.NewDecoder(resp.Body).Decode(&created); err != nil { + return nil, fmt.Errorf("decode created issue: %w", err) + } + return &created, nil } func (c *Client) PostComment(issueKey string, body io.Reader) error { blob - a4339567b02f6a29f302567eda5fbba16a3fd198 blob + 3eecbeb0c6c3453c9913ab8c323ee8a3e6d4e38e --- jira/jira.go +++ jira/jira.go @@ -9,29 +9,32 @@ import ( const timestamp = "2006-01-02T15:04:05.999-0700" type Issue struct { - ID string // TODO(otl): int? - URL string - Key string - Reporter User - Assignee User - Summary string - Status struct { + ID string `json:"id,omitempty"` // TODO(otl): int? + URL string `json:"url,omitempty"` + Key string `json:"key,omitempty"` + Reporter *User `json:"reporter,omitempty"` + Assignee *User `json:"assignee,omitempty"` + Summary string `json:"summary"` + Status *struct { Name string `json:"name"` - } `json:"status"` - Description string - Project Project - Created time.Time - Updated time.Time - Comments []Comment - Links []Issue - Subtasks []Issue + } `json:"status,omitempty"` + Description string `json:"description"` + Project Project `json:"project"` + Created time.Time `json:"created,omitzero"` + Updated time.Time `json:"updated,omitzero"` + Type struct { + Name string `json:"name"` + } `json:"issuetype"` + Comments []Comment `json:"comments,omitempty"` + Links []Issue `json:"links,omitempty"` + Subtasks []Issue `json:"subtasks,omitempty"` } type Project struct { - ID string `json:"id"` // TODO(otl): int? + ID string `json:"id,omitempty"` // TODO(otl): int? // Name string `json:"name"` - Key string `json:"key"` - URL string `json:"self"` + Key string `json:"key,omitempty"` + URL string `json:"self,omitempty"` } type Comment struct { @@ -97,8 +100,8 @@ func (issue *Issue) UnmarshalJSON(b []byte) error { type alias Issue iaux := &struct { - Created string - Updated string + Created string `json:"created"` + Updated string `json:"updated"` Comment map[string]json.RawMessage IssueLinks []struct { InwardIssue *Issue @@ -140,3 +143,11 @@ func (issue *Issue) UnmarshalJSON(b []byte) error { } return nil } + +func (issue *Issue) MarshalJSON() ([]byte, error) { + type alias Issue + aux := struct { + Fields *alias `json:"fields"` + }{(*alias)(issue)} + return json.Marshal(aux) +} blob - 2af937f6316d5c2ea8d6b78d866af66a24992d70 blob + 65b1c6661d55328871224e5b858fc401e0e3f060 --- jira/print.go +++ jira/print.go @@ -19,9 +19,11 @@ func printIssues(issues []Issue) string { func printIssue(i *Issue) string { buf := &strings.Builder{} - fmt.Fprintln(buf, "From:", i.Reporter) + if i.Reporter != nil { + fmt.Fprintln(buf, "From:", i.Reporter) + } fmt.Fprintln(buf, "Date:", i.Created.Format(time.RFC1123Z)) - if i.Assignee.String() != "" { + if i.Assignee != nil { fmt.Fprintln(buf, "Assignee:", i.Assignee) } if u, err := url.Parse(i.URL); err == nil {