@@ -4,9 +4,11 @@ import (
44 "encoding/json"
55 "fmt"
66 "os"
7+ "strings"
78 "time"
89
910 "github.com/andygrunwald/go-jira"
11+ "github.com/briandowns/spinner"
1012 tea "github.com/charmbracelet/bubbletea"
1113 "github.com/charmbracelet/lipgloss"
1214 "github.com/rs/zerolog/log"
2224 jiraComment bool // if true, post a comment when marking as skipped
2325 ticketsDryRun bool // if true, do not send anything to Jira
2426 hideSkipped bool // if true, do not show skipped tests
27+ missingPillars bool // if true, only show tickets with missing pillar names
2528)
2629
2730// TicketsCmd is the new CLI command for managing tickets.
@@ -99,11 +102,13 @@ Actions:
99102 SkippedAt : entry .SkippedAt ,
100103 }
101104
102- // Map user ID based on test package pattern
103- if userID := model .MapTestPackageToUser (entry .TestPackage , patternToUserID ); userID != "" {
104- if userMapping , exists := userMap [userID ]; exists {
105- tickets [i ].AssigneeId = userID
106- tickets [i ].AssigneeName = userMapping .UserName
105+ // Map user based on assignee ID from local DB
106+ if entry .AssigneeID != "" {
107+ if _ , exists := userMap [entry .AssigneeID ]; exists {
108+ tickets [i ].AssigneeId = entry .AssigneeID
109+ } else {
110+ tickets [i ].AssigneeId = entry .AssigneeID
111+ tickets [i ].MissingUserMapping = true
107112 }
108113 }
109114 }
@@ -126,6 +131,77 @@ Actions:
126131 jiraClient = nil
127132 }
128133
134+ // Fetch pillar names with spinner
135+ if jiraClient != nil {
136+ s := spinner .New (spinner .CharSets [14 ], 100 * time .Millisecond )
137+ s .Suffix = " Fetching pillar names from Jira..."
138+ s .Start ()
139+
140+ // Collect all Jira keys that need pillar names
141+ var jiraKeys []string
142+ for _ , t := range tickets {
143+ if t .ExistingJiraKey != "" {
144+ jiraKeys = append (jiraKeys , t .ExistingJiraKey )
145+ }
146+ }
147+
148+ // Process tickets in batches of 50 (Jira's recommended batch size)
149+ batchSize := 50
150+ for i := 0 ; i < len (jiraKeys ); i += batchSize {
151+ end := i + batchSize
152+ if end > len (jiraKeys ) {
153+ end = len (jiraKeys )
154+ }
155+ batch := jiraKeys [i :end ]
156+
157+ // Create JQL query for the batch
158+ jql := fmt .Sprintf ("key IN (%s)" , strings .Join (batch , "," ))
159+
160+ // Fetch issues in batch
161+ issues , _ , err := jiraClient .Issue .Search (jql , & jira.SearchOptions {
162+ Fields : []string {"key" , "customfield_11016" },
163+ MaxResults : batchSize ,
164+ })
165+
166+ if err != nil {
167+ log .Warn ().Err (err ).Msgf ("Failed to fetch pillar names for batch of tickets" )
168+ continue
169+ }
170+
171+ // Update tickets with pillar names
172+ for _ , issue := range issues {
173+ // Find the corresponding ticket
174+ for j := range tickets {
175+ if tickets [j ].ExistingJiraKey == issue .Key {
176+ if issue .Fields != nil {
177+ if pillarField , ok := issue .Fields .Unknowns ["customfield_11016" ].(map [string ]interface {}); ok {
178+ if value , ok := pillarField ["value" ].(string ); ok {
179+ tickets [j ].PillarName = value
180+ }
181+ }
182+ }
183+ break
184+ }
185+ }
186+ }
187+
188+ // Update spinner progress
189+ s .Suffix = fmt .Sprintf (" Fetching pillar names from Jira... (%d/%d)" , end , len (jiraKeys ))
190+ }
191+ s .Stop ()
192+ }
193+
194+ // Filter tickets with missing pillars if the flag is set
195+ if missingPillars {
196+ filtered := make ([]model.FlakyTicket , 0 , len (tickets ))
197+ for _ , t := range tickets {
198+ if t .PillarName == "" {
199+ filtered = append (filtered , t )
200+ }
201+ }
202+ tickets = filtered
203+ }
204+
129205 // 6) Initialize the Bubble Tea model.
130206 m := initialTicketsModel (tickets , userMap , testPatternMap )
131207 m .JiraClient = jiraClient
@@ -153,7 +229,8 @@ func init() {
153229 TicketsCmd .Flags ().StringVar (& ticketsJSONPath , "test-db-path" , "flaky_test_db.json" , "Path to the JSON file containing tickets" )
154230 TicketsCmd .Flags ().BoolVar (& jiraComment , "jira-comment" , true , "If true, post a comment to the Jira ticket when marking as skipped" )
155231 TicketsCmd .Flags ().BoolVar (& ticketsDryRun , "dry-run" , false , "If true, do not send anything to Jira" )
156- TicketsCmd .Flags ().BoolVar (& hideSkipped , "hide-skipped" , false , "If true, do not show skipped tests" )
232+ TicketsCmd .Flags ().BoolVar (& hideSkipped , "hide-skipped" , false , "If true, dbto not show skipped tests" )
233+ TicketsCmd .Flags ().BoolVar (& missingPillars , "missing-pillars" , false , "If true, only show tickets with missing pillar names" )
157234 TicketsCmd .Flags ().StringVar (& userMappingPath , "user-mapping-path" , "user_mapping.json" , "Path to the JSON file containing user mapping" )
158235 TicketsCmd .Flags ().StringVar (& userTestMappingPath , "user-test-mapping-path" , "user_test_mapping.json" , "Path to the JSON file containing user test mapping" )
159236 InitCommonFlags (TicketsCmd )
@@ -328,18 +405,34 @@ func (m ticketModel) View() string {
328405 view += fmt .Sprintf ("%s %s\n " , labelStyle .Render ("Jira:" ), jirautils .GetJiraLink (t .ExistingJiraKey ))
329406 }
330407
408+ // Show assignee information
409+ if t .AssigneeId != "" {
410+ view += fmt .Sprintf ("%s %s\n " , labelStyle .Render ("Assignee ID:" ), t .AssigneeId )
411+ }
412+
331413 // Show status with color.
332414 if ! t .SkippedAt .IsZero () {
333415 view += fmt .Sprintf ("%s %s\n " , labelStyle .Render ("Status:" ), fmt .Sprintf ("skipped at: %s" , t .SkippedAt .UTC ().Format (time .RFC822 )))
334416 } else {
335417 view += fmt .Sprintf ("%s %s\n " , labelStyle .Render ("Status:" ), infoStyle .Render ("not skipped" ))
336418 }
337419
420+ view += fmt .Sprintf ("%s %s\n " , labelStyle .Render ("Pillar:" ), t .PillarName )
421+
338422 // Display any info message.
339423 if m .infoMessage != "" {
340424 view += "\n " + infoStyle .Render (m .infoMessage ) + "\n "
341425 }
342426
343- view += "\n " + actionStyle .Render ("Actions:" ) + " [s] mark as skipped, [u] unskip, [i] set pillar name, [n] next, [q] quit"
427+ // Build actions list
428+ actions := []string {
429+ "[s] mark as skipped" ,
430+ "[u] unskip" ,
431+ "[i] set pillar name" ,
432+ "[n] next" ,
433+ "[q] quit" ,
434+ }
435+
436+ view += "\n " + actionStyle .Render ("Actions:" ) + " " + strings .Join (actions , ", " )
344437 return view
345438}
0 commit comments