11import { IUseCase } from '@/shared/domain/interfaces/use-case.interface' ;
22import { Inject , Injectable } from '@nestjs/common' ;
33import { OrganizationAndTeamData } from '@/config/types/general/organizationAndTeamData' ;
4- import { PullRequestWithFiles } from '@/core/domain/platformIntegrations/types/codeManagement/pullRequests.type' ;
54import { CodeManagementService } from '@/core/infrastructure/adapters/services/platformIntegration/codeManagement.service' ;
6- import * as moment from 'moment-timezone' ;
7- import { DeliveryStatus } from '@/core/domain/pullRequests/enums/deliveryStatus.enum' ;
5+ import { IPullRequestWithDeliveredSuggestions } from '@/core/domain/pullRequests/interfaces/pullRequests.interface' ;
86import {
97 PULL_REQUESTS_SERVICE_TOKEN ,
108 IPullRequestsService ,
119} from '@/core/domain/pullRequests/contracts/pullRequests.service.contracts' ;
12- import { ICodeReviewFeedback } from '@/core/domain/codeReviewFeedback/interfaces/codeReviewFeedback.interface' ;
10+ import { PullRequestState } from '@/shared/domain/enums/pullRequestState.enum' ;
11+ import { PinoLoggerService } from '@/core/infrastructure/adapters/services/logger/pino.service' ;
1312
1413@Injectable ( )
1514export class GetReactionsUseCase implements IUseCase {
@@ -18,141 +17,142 @@ export class GetReactionsUseCase implements IUseCase {
1817
1918 @Inject ( PULL_REQUESTS_SERVICE_TOKEN )
2019 private readonly pullRequestService : IPullRequestsService ,
21- ) { }
2220
23- async execute ( organizationAndTeamData : OrganizationAndTeamData ) {
24- const period = this . calculatePeriod ( ) ;
21+ private readonly logger : PinoLoggerService ,
22+ ) { }
2523
26- const mergedPullRequests =
27- await this . codeManagementService . getPullRequestsWithFiles ( {
28- organizationAndTeamData : organizationAndTeamData ,
29- filters : {
30- period,
31- prStatus : 'merged' ,
32- } ,
33- } ) ;
24+ async execute (
25+ organizationAndTeamData : OrganizationAndTeamData ,
26+ automationExecutionsPRs : number [ ] ,
27+ ) {
28+ if ( ! automationExecutionsPRs ?. length ) {
29+ return [ ] ;
30+ }
3431
35- const closedPullRequests =
36- await this . codeManagementService . getPullRequestsWithFiles ( {
37- organizationAndTeamData : organizationAndTeamData ,
38- filters : {
39- period,
40- prStatus : 'closed' ,
41- } ,
42- } ) ;
32+ const pullRequests =
33+ await this . pullRequestService . findPullRequestsWithDeliveredSuggestions (
34+ organizationAndTeamData . organizationId ,
35+ automationExecutionsPRs ,
36+ [ PullRequestState . MERGED , PullRequestState . CLOSED ] ,
37+ ) ;
4338
44- const allPullRequests = [ ...mergedPullRequests , ...closedPullRequests ] ;
39+ if ( ! pullRequests ?. length ) {
40+ return [ ] ;
41+ }
4542
46- return await this . getReactions (
47- allPullRequests ,
48- organizationAndTeamData ,
49- ) ;
43+ return await this . getReactions ( pullRequests , organizationAndTeamData ) ;
5044 }
5145
5246 private async getReactions (
53- pullRequests : PullRequestWithFiles [ ] ,
47+ pullRequests : IPullRequestWithDeliveredSuggestions [ ] ,
5448 organizationAndTeamData : OrganizationAndTeamData ,
55- ) : Promise < ICodeReviewFeedback [ ] > {
56- const reactions : any [ ] = [ ] ;
49+ ) {
50+ const reactionsPromises = pullRequests . map ( async ( pr ) => {
51+ if ( ! pr . suggestions ?. length ) {
52+ return [ ] ;
53+ }
5754
58- if ( ! pullRequests ?. length ) {
59- return [ ] ;
60- }
55+ const suggestionsByCommentId = new Map (
56+ pr . suggestions . map ( ( s ) => [ s . comment ?. id , s ] ) ,
57+ ) ;
6158
62- for ( const pr of pullRequests ) {
6359 const comments =
6460 await this . codeManagementService . getPullRequestReviewComment ( {
65- organizationAndTeamData : organizationAndTeamData ,
61+ organizationAndTeamData,
6662 filters : {
67- repository : pr . repository ,
68- pullRequestNumber : pr . pull_number ,
63+ repository : pr . repository . name ,
64+ pullRequestNumber : pr . number ,
6965 } ,
7066 } ) ;
7167
72- const suggestions =
73- await this . pullRequestService . findSuggestionsByPR (
74- organizationAndTeamData . organizationId ,
75- pr . pull_number ,
76- DeliveryStatus . SENT ,
77- ) ;
68+ const commentsLinkedToSuggestions = comments . filter ( ( comment ) => {
69+ const commentId = comment ?. threadId
70+ ? comment . threadId
71+ : comment ?. notes ?. [ 0 ] ?. id || comment ?. id ;
72+ return suggestionsByCommentId . has ( commentId ) ;
73+ } ) ;
7874
79- if ( ! suggestions ? .length ) {
80- continue ;
75+ if ( ! commentsLinkedToSuggestions . length ) {
76+ return [ ] ;
8177 }
8278
83- const commentsLinkedToSuggestions = comments . filter ( ( comment ) =>
84- suggestions ?. some (
85- ( suggestion ) => {
86- // We dont save the commentId for azure, but the threadId.
87- if ( comment ?. threadId ) {
88- return suggestion ?. comment ?. id === comment ?. threadId ;
89- }
90- else {
91- return suggestion ?. comment ?. id === ( comment ?. notes ?. [ 0 ] ?. id || comment ?. id ) ;
92- }
93- }
94- ) ,
95- ) ;
96-
9779 const reactionsInComments =
9880 await this . codeManagementService . countReactions ( {
99- organizationAndTeamData : organizationAndTeamData ,
81+ organizationAndTeamData,
10082 comments : commentsLinkedToSuggestions ,
101- pr,
83+ pr : {
84+ pull_number : pr . number ,
85+ repository : pr . repository . name ,
86+ } ,
10287 } ) ;
10388
104- // Adds the suggestionId to each reaction
105- const reactionsWithSuggestionId = reactionsInComments
106- . filter ( ( reaction ) =>
107- suggestions . some (
108- ( s ) => s ?. comment ?. id === reaction . comment . id ,
109- ) ,
110- )
89+ if ( ! reactionsInComments ?. length ) {
90+ return [ ] ;
91+ }
92+
93+ return reactionsInComments
11194 . map ( ( reaction ) => {
112- const suggestion = suggestions . find (
113- ( s ) => s ?. comment ?. id === reaction . comment . id ,
95+ const suggestion = suggestionsByCommentId . get (
96+ reaction . comment . id ,
11497 ) ;
98+ if ( ! suggestion ) {
99+ return null ;
100+ }
101+
115102 return {
116103 reactions : reaction . reactions ,
117104 comment : {
118105 id : reaction . comment . id ,
119106 pullRequestReviewId :
120107 reaction . comment ?. pull_request_review_id ,
121108 } ,
122- suggestionId : suggestion ? .id ,
109+ suggestionId : suggestion . id ,
123110 pullRequest : {
124111 id : reaction . pullRequest . id ,
125112 number : reaction . pullRequest . number ,
126113 repository : {
127114 id :
128115 reaction ?. pullRequest ?. repository ?. id ||
129- pr ?. repositoryData ? .id ,
116+ pr . repository . id ,
130117 fullName :
131- pr ?. repositoryData ?. fullName ||
132- reaction ?. pullRequest ? .repository ?. fullName ,
118+ reaction ?. pullRequest ?. repository
119+ ?. fullName || pr . repository . name ,
133120 } ,
134121 } ,
135122 organizationId : organizationAndTeamData . organizationId ,
136123 } ;
137- } ) ;
138-
139- reactions . push ( ...reactionsWithSuggestionId ) ;
124+ } )
125+ . filter ( ( reaction ) => reaction !== null ) ;
126+ } ) ;
127+
128+ const reactionsResults = await Promise . all ( reactionsPromises ) ;
129+ const flattenedReactions = reactionsResults . flat ( ) ;
130+
131+ const prsWithoutReactions = pullRequests . filter ( ( pr , index ) => {
132+ return reactionsResults [ index ] . length === 0 ;
133+ } ) ;
134+
135+ if ( prsWithoutReactions . length > 0 ) {
136+ this . logger . log ( {
137+ message : 'PRs without reactions summary' ,
138+ context : GetReactionsUseCase . name ,
139+ metadata : {
140+ organizationId : organizationAndTeamData . organizationId ,
141+ totalPRs : pullRequests . length ,
142+ prsWithReactions :
143+ pullRequests . length - prsWithoutReactions . length ,
144+ prsWithoutReactions : prsWithoutReactions . length ,
145+ prsWithoutReactionsDetails : prsWithoutReactions . map (
146+ ( pr ) => ( {
147+ prNumber : pr . number ,
148+ repository : pr . repository . name ,
149+ suggestionsCount : pr . suggestions ?. length || 0 ,
150+ } ) ,
151+ ) ,
152+ } ,
153+ } ) ;
140154 }
141155
142- return reactions ;
143- }
144-
145- private calculatePeriod ( ) {
146- const now = new Date ( ) ;
147- const endDate = now ;
148- const startDate = new Date ( now ) ;
149-
150- startDate . setDate ( startDate . getDate ( ) - 1 ) ;
151- startDate . setHours ( 0 , 0 , 0 , 0 ) ;
152-
153- return {
154- startDate : moment ( startDate ) . format ( 'YYYY-MM-DD HH:mm' ) ,
155- endDate : moment ( endDate ) . format ( 'YYYY-MM-DD HH:mm' ) ,
156- } ;
156+ return flattenedReactions ;
157157 }
158158}
0 commit comments