@@ -255,34 +255,73 @@ func (rf *ReviewerFinder) prsForOrgWithBatchSize(ctx context.Context, org string
255255
256256// parseOrgPRsFromGraphQL parses PRs from GraphQL response.
257257func (rf * ReviewerFinder ) parseOrgPRsFromGraphQL (result map [string ]any ) (prs []* PullRequest , hasNextPage bool , cursor string ) {
258+ repos := rf .extractOrgRepositories (result )
259+ if repos == nil {
260+ return prs , false , ""
261+ }
258262
259- // Navigate through the GraphQL response structure
260- if data , ok := result ["data" ].(map [string ]any ); ok {
261- if org , ok := data ["organization" ].(map [string ]any ); ok {
262- if repos , ok := org ["repositories" ].(map [string ]any ); ok {
263- // Get pagination info
264- if pageInfo , ok := repos ["pageInfo" ].(map [string ]any ); ok {
265- if next , ok := pageInfo ["hasNextPage" ].(bool ); ok {
266- hasNextPage = next
267- }
268- if endCursor , ok := pageInfo ["endCursor" ].(string ); ok {
269- cursor = endCursor
270- }
271- }
263+ hasNextPage , cursor = rf .extractPaginationInfo (repos )
264+ prs = rf .extractPRsFromRepos (repos )
272265
273- // Process repositories
274- if nodes , ok := repos ["nodes" ].([]any ); ok {
275- for _ , node := range nodes {
276- if repo , ok := node .(map [string ]any ); ok {
277- prs = append (prs , rf .parsePRsFromRepo (repo )... )
278- }
279- }
280- }
281- }
266+ return prs , hasNextPage , cursor
267+ }
268+
269+ // extractOrgRepositories extracts the repositories object from org GraphQL response.
270+ func (* ReviewerFinder ) extractOrgRepositories (result map [string ]any ) map [string ]any {
271+ data , ok := result ["data" ].(map [string ]any )
272+ if ! ok {
273+ return nil
274+ }
275+
276+ org , ok := data ["organization" ].(map [string ]any )
277+ if ! ok {
278+ return nil
279+ }
280+
281+ repos , ok := org ["repositories" ].(map [string ]any )
282+ if ! ok {
283+ return nil
284+ }
285+
286+ return repos
287+ }
288+
289+ // extractPaginationInfo extracts pagination info from repositories response.
290+ func (* ReviewerFinder ) extractPaginationInfo (repos map [string ]any ) (hasNextPage bool , cursor string ) {
291+ pageInfo , ok := repos ["pageInfo" ].(map [string ]any )
292+ if ! ok {
293+ return false , ""
294+ }
295+
296+ if next , ok := pageInfo ["hasNextPage" ].(bool ); ok {
297+ hasNextPage = next
298+ }
299+
300+ if endCursor , ok := pageInfo ["endCursor" ].(string ); ok {
301+ cursor = endCursor
302+ }
303+
304+ return hasNextPage , cursor
305+ }
306+
307+ // extractPRsFromRepos extracts PRs from repository nodes.
308+ func (rf * ReviewerFinder ) extractPRsFromRepos (repos map [string ]any ) []* PullRequest {
309+ var prs []* PullRequest
310+
311+ nodes , ok := repos ["nodes" ].([]any )
312+ if ! ok {
313+ return prs
314+ }
315+
316+ for _ , node := range nodes {
317+ repo , ok := node .(map [string ]any )
318+ if ! ok {
319+ continue
282320 }
321+ prs = append (prs , rf .parsePRsFromRepo (repo )... )
283322 }
284323
285- return prs , hasNextPage , cursor
324+ return prs
286325}
287326
288327// parsePRsFromRepo parses PRs from a repository node.
@@ -323,26 +362,43 @@ func (rf *ReviewerFinder) parsePRFromGraphQL(prData map[string]any, owner, repo
323362 Repository : repo ,
324363 }
325364
326- // Parse basic fields
365+ rf .parseBasicPRFields (prData , pr )
366+ rf .parsePRAuthor (prData , pr )
367+ rf .parsePRDates (prData , pr )
368+ rf .parsePRAssignees (prData , pr )
369+ rf .parsePRReviewers (prData , pr )
370+ rf .parsePRLastCommit (prData , pr )
371+
372+ return pr
373+ }
374+
375+ // parseBasicPRFields parses basic PR fields like number, title, and draft status.
376+ func (* ReviewerFinder ) parseBasicPRFields (prData map [string ]any , pr * PullRequest ) {
327377 if number , ok := prData ["number" ].(float64 ); ok {
328378 pr .Number = int (number )
329379 }
330380 if title , ok := prData ["title" ].(string ); ok {
331381 pr .Title = title
332382 }
333- // URL field doesn't exist in PullRequest struct, skip it
334383 if isDraft , ok := prData ["isDraft" ].(bool ); ok {
335384 pr .Draft = isDraft
336385 }
386+ }
337387
338- // Parse author
339- if author , ok := prData [ "author" ].( map [string ]any ); ok {
340- if login , ok := author [ "login " ].(string ); ok {
341- pr . Author = login
342- }
388+ // parsePRAuthor parses the PR author information.
389+ func ( * ReviewerFinder ) parsePRAuthor ( prData map [string ]any , pr * PullRequest ) {
390+ author , ok := prData [ "author " ].(map [ string ] any )
391+ if ! ok {
392+ return
343393 }
344394
345- // Parse dates
395+ if login , ok := author ["login" ].(string ); ok {
396+ pr .Author = login
397+ }
398+ }
399+
400+ // parsePRDates parses PR creation and update dates.
401+ func (* ReviewerFinder ) parsePRDates (prData map [string ]any , pr * PullRequest ) {
346402 if createdAt , ok := prData ["createdAt" ].(string ); ok {
347403 if t , err := time .Parse (time .RFC3339 , createdAt ); err == nil {
348404 pr .CreatedAt = t
@@ -353,60 +409,86 @@ func (rf *ReviewerFinder) parsePRFromGraphQL(prData map[string]any, owner, repo
353409 pr .UpdatedAt = t
354410 }
355411 }
412+ }
356413
357- // Parse assignees
358- if assignees , ok := prData ["assignees" ].(map [string ]any ); ok {
359- if nodes , ok := assignees ["nodes" ].([]any ); ok {
360- for _ , node := range nodes {
361- if assignee , ok := node .(map [string ]any ); ok {
362- if login , ok := assignee ["login" ].(string ); ok {
363- pr .Assignees = append (pr .Assignees , login )
364- }
365- }
366- }
367- }
414+ // parsePRAssignees parses the list of PR assignees.
415+ func (* ReviewerFinder ) parsePRAssignees (prData map [string ]any , pr * PullRequest ) {
416+ assignees , ok := prData ["assignees" ].(map [string ]any )
417+ if ! ok {
418+ return
368419 }
369420
370- // Parse existing reviewers
371- if reviewRequests , ok := prData ["reviewRequests" ].(map [string ]any ); ok {
372- if nodes , ok := reviewRequests ["nodes" ].([]any ); ok {
373- for _ , node := range nodes {
374- if request , ok := node .(map [string ]any ); ok {
375- if reviewer , ok := request ["requestedReviewer" ].(map [string ]any ); ok {
376- if login , ok := reviewer ["login" ].(string ); ok {
377- pr .Reviewers = append (pr .Reviewers , login )
378- }
379- }
380- }
381- }
421+ nodes , ok := assignees ["nodes" ].([]any )
422+ if ! ok {
423+ return
424+ }
425+
426+ for _ , node := range nodes {
427+ assignee , ok := node .(map [string ]any )
428+ if ! ok {
429+ continue
430+ }
431+
432+ if login , ok := assignee ["login" ].(string ); ok {
433+ pr .Assignees = append (pr .Assignees , login )
382434 }
383435 }
436+ }
384437
385- // Parse last commit date
386- if commits , ok := prData ["commits" ].(map [string ]any ); ok {
387- if nodes , ok := commits ["nodes" ].([]any ); ok && len (nodes ) > 0 {
388- if commit , ok := nodes [0 ].(map [string ]any ); ok {
389- if commitData , ok := commit ["commit" ].(map [string ]any ); ok {
390- if committedDate , ok := commitData ["committedDate" ].(string ); ok {
391- if t , err := time .Parse (time .RFC3339 , committedDate ); err == nil {
392- pr .LastCommit = t
393- }
394- }
395- }
396- }
438+ // parsePRReviewers parses the list of requested reviewers.
439+ func (* ReviewerFinder ) parsePRReviewers (prData map [string ]any , pr * PullRequest ) {
440+ reviewRequests , ok := prData ["reviewRequests" ].(map [string ]any )
441+ if ! ok {
442+ return
443+ }
444+
445+ nodes , ok := reviewRequests ["nodes" ].([]any )
446+ if ! ok {
447+ return
448+ }
449+
450+ for _ , node := range nodes {
451+ request , ok := node .(map [string ]any )
452+ if ! ok {
453+ continue
454+ }
455+
456+ reviewer , ok := request ["requestedReviewer" ].(map [string ]any )
457+ if ! ok {
458+ continue
459+ }
460+
461+ if login , ok := reviewer ["login" ].(string ); ok {
462+ pr .Reviewers = append (pr .Reviewers , login )
397463 }
398464 }
465+ }
399466
400- // LastReview will be fetched on-demand when needed for detailed analysis
401- // Removed from initial query to reduce GraphQL payload size
467+ // parsePRLastCommit parses the last commit date from the PR.
468+ func (* ReviewerFinder ) parsePRLastCommit (prData map [string ]any , pr * PullRequest ) {
469+ commits , ok := prData ["commits" ].(map [string ]any )
470+ if ! ok {
471+ return
472+ }
473+
474+ nodes , ok := commits ["nodes" ].([]any )
475+ if ! ok || len (nodes ) == 0 {
476+ return
477+ }
402478
403- // Parse file statistics - these fields don't exist in our PullRequest struct
404- // We would need to fetch file details separately if needed
405- // additions, deletions, and changedFiles are available in the GraphQL response
406- // but our PullRequest struct doesn't have these fields directly
479+ commit , ok := nodes [ 0 ].( map [ string ] any )
480+ if ! ok {
481+ return
482+ }
407483
408- // Note: ChangedFiles array would need a separate query for file details
409- // For now, we'll fetch those on-demand when needed
484+ commitData , ok := commit ["commit" ].(map [string ]any )
485+ if ! ok {
486+ return
487+ }
410488
411- return pr
489+ if committedDate , ok := commitData ["committedDate" ].(string ); ok {
490+ if t , err := time .Parse (time .RFC3339 , committedDate ); err == nil {
491+ pr .LastCommit = t
492+ }
493+ }
412494}
0 commit comments