From 4f44943d90d021657cd66d6d2b787b037d0a5967 Mon Sep 17 00:00:00 2001 From: Olivier Tremblay Date: Wed, 26 Nov 2025 11:34:13 -0500 Subject: [PATCH] Some cleanup --- .gitignore | 2 +- Makefile | 3 +++ cmd/acb/summarize.go | 9 ++------- contributions/gh.go | 33 +++++++++++++++++++++++++-------- go.mod | 13 +++++++++++++ go.sum | 24 ++++++++++++++++++++++++ issues/jira.go | 25 ++++++++++++++++++++++--- 7 files changed, 90 insertions(+), 19 deletions(-) create mode 100644 Makefile create mode 100644 go.sum diff --git a/.gitignore b/.gitignore index d5ac763..49d3410 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ .aider* -.env +.env* diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..a40d072 --- /dev/null +++ b/Makefile @@ -0,0 +1,3 @@ +all: + go build ./... + go test ./... diff --git a/cmd/acb/summarize.go b/cmd/acb/summarize.go index e1b51fc..3bec11b 100644 --- a/cmd/acb/summarize.go +++ b/cmd/acb/summarize.go @@ -159,15 +159,10 @@ func (a *AnthropicSummarizer) Summarize(fullPrompt string) (string, error) { } // buildPrompt constructs the prompt string from PRs, issues, and tasks -func buildPrompt(employeename string, prs map[string][]contributions.PullRequest, issues []issues.Issue, tasks []vikunja.Task, prompt string) string { +func buildPrompt(employeename string, prs contributions.PRMap, issues []issues.Issue, tasks []vikunja.Task, prompt string) string { // Build a prompt string fullPrompt := prompt + fmt.Sprintf("\n\nHere's the PRs and Tickets for the employee %s:\n\n", employeename) - for repo, prList := range prs { - fullPrompt += fmt.Sprintf("Repository: %s\n", repo) - for _, pr := range prList { - fullPrompt += pr.String() - } - } + fullPrompt += prs.String() fullPrompt += "Issues:\n" for _, issue := range issues { fullPrompt += fmt.Sprintf("Summary: %s\n", issue.Summary) diff --git a/contributions/gh.go b/contributions/gh.go index caaf2a3..6614911 100644 --- a/contributions/gh.go +++ b/contributions/gh.go @@ -33,22 +33,39 @@ type PullRequest struct { URL string } -// String returns a formatted string representation of the PullRequest -func (pr PullRequest) String() string { - tmpl := template.Must(template.New("pr").Parse(`- Title: {{.Title}} +var prtmpl = template.Must(template.New("pr").Parse(`- Title: {{.Title}} Body: {{.Body}} `)) - + +// String returns a formatted string representation of the PullRequest +func (pr PullRequest) String() string { var buf bytes.Buffer - err := tmpl.Execute(&buf, pr) + err := prtmpl.Execute(&buf, pr) if err != nil { return "" // Return empty string on error } - + return buf.String() } -func GetPRs(org, username string, from string, to string) (map[string][]PullRequest, error) { +type PRMap map[string][]PullRequest + +var prlisttmpl = template.Must(template.New("prlist").Parse(`{{range $k, $v := .}} + {{$k}}: + {{$v}} +{{end}}`)) + +func (p PRMap) String() string { + var buf bytes.Buffer + err := prlisttmpl.Execute(&buf, p) + if err != nil { + return "" // Return empty string on error + } + + return buf.String() +} + +func GetPRs(org, username string, from string, to string) (PRMap, error) { req, err := http.NewRequest( http.MethodGet, fmt.Sprintf( @@ -81,7 +98,7 @@ func GetPRs(org, username string, from string, to string) (map[string][]PullRequ return nil, fmt.Errorf("error decoding response: %w", err) } - allthings := map[string][]PullRequest{} + allthings := PRMap{} for _, pr := range r.Items { reponameparts := strings.Split(pr.RepositoryUrl, "/") diff --git a/go.mod b/go.mod index fdb17da..c521219 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,16 @@ module o5r.ca/autocrossbow go 1.25.0 + +require ( + github.com/anthropics/anthropic-sdk-go v1.18.0 // indirect + github.com/eliziario/jira-lib v0.4.0 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/ollama/ollama v0.12.11 // indirect + github.com/tidwall/gjson v1.18.0 // indirect + github.com/tidwall/match v1.1.1 // indirect + github.com/tidwall/pretty v1.2.1 // indirect + github.com/tidwall/sjson v1.2.5 // indirect + golang.org/x/crypto v0.40.0 // indirect + golang.org/x/sys v0.36.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..d2aea89 --- /dev/null +++ b/go.sum @@ -0,0 +1,24 @@ +github.com/anthropics/anthropic-sdk-go v1.18.0 h1:jfxRA7AqZoCm83nHO/OVQp8xuwjUKtBziEdMbfmofHU= +github.com/anthropics/anthropic-sdk-go v1.18.0/go.mod h1:WTz31rIUHUHqai2UslPpw5CwXrQP3geYBioRV4WOLvE= +github.com/eliziario/jira-lib v0.4.0 h1:7ALdGwDKPvUlSvGMe93SN+Xv5arqrzbTkf/rkn9WR78= +github.com/eliziario/jira-lib v0.4.0/go.mod h1:LOG+j6Aey6sjlPGJpmLUhArCR9+vGwaWZtyCvgQKTwM= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/ollama/ollama v0.12.11 h1:QOoD6hSCXuGO9bkWLL7h53XZPD1hG8jaun5mirIyNFM= +github.com/ollama/ollama v0.12.11/go.mod h1:RUSmYywUWx/YZMaHrqtnT1ZChu+iSz/7jx2aO9+Mgfg= +github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= +github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= +github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= +github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= +github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= +golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= +golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= +golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM= +golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY= +golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= +golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= diff --git a/issues/jira.go b/issues/jira.go index 3efc6e0..fe9280b 100644 --- a/issues/jira.go +++ b/issues/jira.go @@ -7,9 +7,9 @@ import ( "io" "net/http" "os" -) -//curl -u olivier@circleci.com:"$(cat ~/jiratoken)" 'https://circleci.atlassian.net/rest/api/2/search?jql=sprint+in+openSprints()+and+project=CIAM' + "github.com/eliziario/jira-lib/pkg/adf" +) var jcl = http.Client{} @@ -88,6 +88,7 @@ func GetIssues(instance, user, from, to string) ([]Issue, error) { q := req.URL.Query() q.Add("jql", fmt.Sprintf("assignee was %s and resolved >= %s and resolved <= %s", accountID, from, to)) q.Add("fields", "*all") + q.Add("expand", "renderedFields") req.URL.RawQuery = q.Encode() req.SetBasicAuth(os.Getenv("JIRA_USER"), os.Getenv("JIRA_TOKEN")) req.Header.Add("Accept", "application/json") @@ -116,7 +117,8 @@ func GetIssues(instance, user, from, to string) ([]Issue, error) { iss.Summary, _ = s.(string) } if d, ok := i.Fields["description"]; ok { - iss.Description, _ = d.(string) + doc := ifaceToADF(d) + iss.Description = adf.NewTranslator(doc, adf.NewMarkdownTranslator()).Translate() } if comms, ok := i.Fields["comment"].([]map[string]any); ok && len(comms) > 0 { iss.Comments = make([]Comment, 0, len(comms)) @@ -131,3 +133,20 @@ func GetIssues(instance, user, from, to string) ([]Issue, error) { return out, nil } +func ifaceToADF(v any) *adf.ADF { + if v == nil { + return nil + } + + var doc *adf.ADF + + js, err := json.Marshal(v) + if err != nil { + return nil // ignore invalid data + } + if err = json.Unmarshal(js, &doc); err != nil { + return nil // ignore invalid data + } + + return doc +}