commit ba9e266535f5c1704c277e5402192008034adc16
parent 8d9dbdfc8a07bca44bcef1a030dc1e248a6ddeaf
Author: Oliver Lowe <o@olowe.co>
Date: Thu, 19 Sep 2024 07:49:18 +1000
jira: printing
Diffstat:
3 files changed, 82 insertions(+), 39 deletions(-)
diff --git a/jira/jira.go b/jira/jira.go
@@ -1,4 +1,5 @@
-//
+// https://developer.atlassian.com/cloud/jira/platform/rest/v2/
+// https://jira.atlassian.com/rest/api/latest/issue/JRA-9
package main
import (
@@ -7,12 +8,18 @@ import (
"time"
)
+const timestamp = "2006-01-02T15:04:05.999-0700"
+
type Issue struct {
- ID string `json:"id"` // TODO(otl): int?
- URL string `json:"self"`
- Key string `json:"key"`
+ ID string // TODO(otl): int?
+ URL string
+ Key string
+ Reporter User
+ Summary string
Description string
Project Project
+ Created time.Time
+ Updated time.Time
Comments []Comment
}
@@ -23,8 +30,8 @@ type Project struct {
}
type Comment struct {
- URL string `json:"self"`
ID string `json:"id"` // TODO(otl): int?
+ URL string `json:"self"`
Body string `json:"body"`
Created time.Time `json:"created"`
Updated time.Time `json:"updated"`
@@ -45,12 +52,11 @@ func (c *Comment) UnmarshalJSON(b []byte) error {
return err
}
var err error
- tstamp := "2006-01-02T15:04:05.999-0700"
- c.Created, err = time.Parse(tstamp, aux.Created)
+ c.Created, err = time.Parse(timestamp, aux.Created)
if err != nil {
return fmt.Errorf("parse created time: %w", err)
}
- c.Updated, err = time.Parse(tstamp, aux.Updated)
+ c.Updated, err = time.Parse(timestamp, aux.Updated)
if err != nil {
return fmt.Errorf("parse updated time: %w", err)
}
@@ -63,22 +69,46 @@ type User struct {
}
func (issue *Issue) UnmarshalJSON(b []byte) error {
- type alias Issue
aux := &struct {
- Fields struct {
- Description string
- Comment []Comment
- Project Project
- }
+ ID string
+ Self string
+ Key string
+ Fields json.RawMessage
+ }{}
+ if err := json.Unmarshal(b, aux); err != nil {
+ return err
+ }
+ issue.ID = aux.ID
+ issue.URL = aux.Self
+ issue.Key = aux.Key
+
+ type alias Issue
+ iaux := &struct {
+ Created string
+ Updated string
+ Comment map[string]json.RawMessage
*alias
}{
alias: (*alias)(issue),
}
- if err := json.Unmarshal(b, aux); err != nil {
+ if err := json.Unmarshal(aux.Fields, iaux); err != nil {
return err
}
- issue.Comments = aux.Fields.Comment
- issue.Description = aux.Fields.Description
- issue.Project = aux.Fields.Project
+
+ var err error
+ issue.Created, err = time.Parse(timestamp, iaux.Created)
+ if err != nil {
+ return fmt.Errorf("created time: %w", err)
+ }
+ issue.Updated, err = time.Parse(timestamp, iaux.Updated)
+ if err != nil {
+ return fmt.Errorf("updated time: %w", err)
+ }
+
+ if bb, ok := iaux.Comment["comments"]; ok {
+ if err := json.Unmarshal(bb, &issue.Comments); err != nil {
+ return fmt.Errorf("unmarshal comments: %w", err)
+ }
+ }
return nil
}
diff --git a/jira/jira_test.go b/jira/jira_test.go
@@ -3,30 +3,24 @@ package main
import (
"encoding/json"
"os"
+ "path/filepath"
"testing"
)
func TestIssue(t *testing.T) {
- f, err := os.Open("issue.json")
+ names, err := filepath.Glob("issue*.json")
if err != nil {
t.Fatal(err)
}
- defer f.Close()
- var issue Issue
- if err := json.NewDecoder(f).Decode(&issue); err != nil {
- t.Fatal(err)
- }
-}
-
-func TestPrint(t *testing.T) {
- f, err := os.Open("issue.json")
- if err != nil {
- t.Fatal(err)
- }
- defer f.Close()
- var issue Issue
- if err := json.NewDecoder(f).Decode(&issue); err != nil {
- t.Fatal(err)
+ for _, name := range names {
+ f, err := os.Open(name)
+ if err != nil {
+ t.Fatalf("%s: %v", name, err)
+ }
+ defer f.Close()
+ var issue Issue
+ if err := json.NewDecoder(f).Decode(&issue); err != nil {
+ t.Fatalf("%s: %v", name, err)
+ }
}
- printIssue(os.Stdout, &issue)
}
diff --git a/jira/print.go b/jira/print.go
@@ -4,19 +4,24 @@ import (
"fmt"
"io"
"strings"
+ "time"
)
func printIssue(w io.Writer, i *Issue) (n int, err error) {
buf := &strings.Builder{}
+ fmt.Fprintln(buf, "From:", i.Reporter.Name)
fmt.Fprintln(buf, "URL:", i.URL)
+ fmt.Fprintln(buf, "Subject:", i.Summary)
fmt.Fprintln(buf)
fmt.Fprintln(buf, i.Description)
fmt.Fprintln(buf)
-
for _, c := range i.Comments {
- buf.WriteString("\t")
- printComment(buf, &c)
+ date := c.Created
+ if !c.Updated.IsZero() {
+ date = c.Updated
+ }
+ fmt.Fprintf(buf, "%s/\t%s\t%s (%s)\n", c.ID, summarise(c.Body), c.Author.Name, date.Format(time.DateTime))
}
return w.Write([]byte(buf.String()))
}
@@ -33,3 +38,17 @@ func printComment(w io.Writer, c *Comment) (n int, err error) {
fmt.Fprintln(buf, c.Body)
return w.Write([]byte(buf.String()))
}
+
+func summarise(body string) string {
+ max := 36
+ if len(body) < max {
+ body = strings.ReplaceAll(body, "\n", " ")
+ return strings.TrimSpace(body)
+ }
+ body = body[:max]
+ body = strings.ReplaceAll(body, "\r", "")
+ body = strings.ReplaceAll(body, "\n", " ")
+ body = strings.TrimSpace(body)
+ body = strings.ReplaceAll(body, " ", " ")
+ return body + "..."
+}