• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

moosetechnology / GitProjectHealth / 10662325514

02 Sep 2024 06:59AM UTC coverage: 17.281%. First build
10662325514

Pull #45

github

web-flow
Merge 3be43eb61 into 012a80f9f
Pull Request #45: Feature levenshtein

4 of 78 new or added lines in 5 files covered. (5.13%)

1590 of 9201 relevant lines covered (17.28%)

0.17 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/GitLabHealth-Model-Analysis/GitMetric4User.class.st
1
Class {
2
        #name : #GitMetric4User,
3
        #superclass : #GitMetric,
4
        #instVars : [
5
                'itsCommits',
6
                'itsMergeRequests',
7
                'emailDomain'
8
        ],
9
        #category : #'GitLabHealth-Model-Analysis'
10
}
11

12
{ #category : #'metrics - commits' }
13
GitMetric4User >> averageTimeBetweenCommitSince: since until: until overA: aDateWeekMonthOrYear [
×
14

×
15
        | commits commitSortedByDate commits1 commits2 differences groupedByDate dateOver average |
×
16
        groupedByDate := self
×
17
                                 setupGroupedDateFrom: since
×
18
                                 to: until
×
19
                                 over: aDateWeekMonthOrYear.
×
20

×
21
        gitAnalyzer := GitAnalyzer new
×
22
                               onModel: glhModel;
×
23
                               glhImporter: glhImporter.
×
24

×
25
        glhImporter withCommitDiffs: false.
×
26
        commits := self
×
27
                           loadCommitsFromProjectsIds: itsProjects keys
×
28
                           since: since
×
29
                           until: until.
×
30
        glhImporter withCommitDiffs: true.
×
31
        commits := commits reject: [ :commit | commit commitCreator ~= user ].
×
32

×
33
        commitSortedByDate := commits sorted: [ :commit1 :commit2 |
×
34
                                      commit1 committed_date
×
35
                                      < commit2 committed_date ].
×
36

×
37
        commitSortedByDate do: [ :commit |
×
38
                dateOver := self
×
39
                                    transformDate: commit committed_date
×
40
                                    to: aDateWeekMonthOrYear.
×
41

×
42
                groupedByDate
×
43
                        at: dateOver printString
×
44
                        ifPresent: [ :value | value add: commit ] ].
×
45

×
46
        groupedByDate := groupedByDate select: [ :group | group size >= 2 ].
×
47

×
48

×
49
        groupedByDate := groupedByDate collect: [ :group |
×
50
                                 differences := (1 to: group size - 1) collect: [ :i |
×
51
                                                        commits1 := group at: i.
×
52
                                                        commits2 := group at: i + 1.
×
53

×
54
                                                        (commits2 committed_date
×
55
                                                         - commits1 committed_date)
×
56
                                                                asSeconds ].
×
57

×
58
                                 differences average asDuration ].
×
59

×
60
        average := groupedByDate
×
61
                           ifEmpty: [ nil ]
×
62
                           ifNotEmpty: [ groupedByDate average ].
×
63

×
64
        ^ {
×
65
                  (#overEach -> aDateWeekMonthOrYear name).
×
66
                  (#forOver -> (groupedByDate keys size printString
×
67
                    , aDateWeekMonthOrYear printString)).
×
68
                  (#average -> average).
×
69
                  (#details -> groupedByDate).
×
70
                  (#userCommits -> commits size) } asDictionary
×
71
]
×
72

73
{ #category : #churn }
74
GitMetric4User >> codeChurnSince: since until: until onACommitWindowOf: commitLimit overA: aDateWeekMonthOrYear [
×
75

×
76
        | commits res groupedByDate totalContributions userCommits |
×
77
        "for each commit, we get its churn result (a dictionnary)"
×
78
        'GitMetric4User: code churn' recordInfo.
×
79
        totalContributions := OrderedCollection new.
×
80
        groupedByDate := self
×
81
                                 setupGroupedDateFrom: since
×
82
                                 to: until
×
83
                                 over: aDateWeekMonthOrYear.
×
84
        gitAnalyzer := GitAnalyzer new
×
85
                               glhImporter: glhImporter;
×
86
                               onModel: glhModel;
×
87
                               maxChildCommit: commitLimit.
×
88
        glhImporter withCommitDiffs: false.
×
89
        commits := self
×
90
                           loadCommitsFromProjectsIds: itsProjects keys
×
91
                           since: since
×
92
                           until: until.
×
93
        glhImporter withCommitDiffs: true.
×
94
        userCommits := commits reject: [ :commit |
×
95
                               commit commitCreator ~= user ].
×
96
        commits := self
×
97
                           foundSuccessorOf: userCommits
×
98
                           andCompleteImportForMax: commitLimit.
×
99

×
100

×
101
        res := commits collect: [ :commit |
×
102
                       commit -> (gitAnalyzer
×
103
                                fromCommit: commit;
×
104
                                analyseChurn) ].
×
105
        res do: [ :commits4Churns |
×
106
                | commit allChurnsInCommit sumChurnInCommit overDate contribution churnOnCommit |
×
107
                commit := commits4Churns key.
×
108
                allChurnsInCommit := commits4Churns value.
×
109
                sumChurnInCommit := (allChurnsInCommit at: #churns) sum: [ :churn |
×
110
                                            | numerator |
×
111
                                            numerator := churn value at: #churnLoC.
×
112
                                            numerator ].
×
113
                contribution := allChurnsInCommit at: #totalContribution.
×
114
                totalContributions add: contribution.
×
115
                churnOnCommit := {
×
116
                                         (#churnOnCommit -> sumChurnInCommit).
×
117
                                         (#LoCOnCommit -> contribution) } asDictionary.
×
118
                overDate := self
×
119
                                    transformDate: commit created_at
×
120
                                    to: aDateWeekMonthOrYear.
×
121
                groupedByDate
×
122
                        at: overDate printString
×
123
                        ifPresent: [ :array | array add: churnOnCommit ]
×
124
                        ifAbsentPut: [
×
125
                                OrderedCollection new
×
126
                                        add: churnOnCommit;
×
127
                                        yourself ] ].
×
128
        groupedByDate := groupedByDate collect: [ :churnsAtDate |
×
129
                                 | totalChurn totalContribution percentage |
×
130
                                 totalChurn := churnsAtDate sum: [ :churn |
×
131
                                                       churn at: #churnOnCommit ].
×
132
                                 totalContribution := churnsAtDate sum: [ :churn |
×
133
                                                              churn at: #LoCOnCommit ].
×
134
                                 totalContribution = 0
×
135
                                         ifTrue: [ percentage := 0 asFloat ]
×
136
                                         ifFalse: [
×
137
                                         percentage := (totalChurn * 100
×
138
                                                        / totalContribution) asFloat ].
×
139
                                 {
×
140
                                         (#churn -> totalChurn).
×
141
                                         (#contribution -> totalContribution).
×
142
                                         (#percentage -> percentage) } asDictionary ].
×
143
        ^ {
×
144
                  (#details -> groupedByDate).
×
145
                  (#totalContribution -> (totalContributions
×
146
                            ifEmpty: [ 0 ]
×
147
                            ifNotEmpty: [ totalContributions sum ])).
×
148
                  (#totalChurn -> (groupedByDate sum: [ :date | date at: #churn ])).
×
149
                  (#churn
×
150
                   ->
×
151
                   (groupedByDate collect: [ :date | date at: #percentage ]) average).
×
152
                  (#overEach -> aDateWeekMonthOrYear name).
×
153
                  (#forOver -> (groupedByDate keys size printString
×
154
                    , aDateWeekMonthOrYear printString)).
×
155
                  (#userCommits -> commits size).
×
156
                  (#churnWindow -> commitLimit) } asDictionary
×
157
]
×
158

159
{ #category : #'metrics - commits' }
160
GitMetric4User >> codeContributionsSince: since until: until overA: aDateWeekMonthOrYear [
×
161

×
162
        | commits contributions groupedByDate |
×
163
        'GitMetric4User: code contribution' recordInfo.
×
164

×
165
        groupedByDate := self
×
166
                                 setupGroupedDateFrom: since
×
167
                                 to: until
×
168
                                 over: aDateWeekMonthOrYear.
×
169

×
170
        gitAnalyzer := GitAnalyzer new
×
171
                               onModel: glhModel;
×
172
                               glhImporter: glhImporter.
×
173

×
174
        glhImporter withCommitDiffs: false.
×
175
        commits := self
×
176
                           loadCommitsFromProjectsIds: itsProjects keys
×
177
                           since: since
×
178
                           until: until.
×
179
        glhImporter withCommitDiffs: true.
×
180
        commits := commits reject: [ :commit | commit commitCreator ~= user ].
×
181

×
182
        contributions := commits collect: [ :commit |
×
183
                                 commit -> (gitAnalyzer
×
184
                                          fromCommit: commit;
×
185
                                          analyseCommitContribution) ].
×
186

×
187
        contributions do: [ :assoc |
×
188
                | dateOver |
×
189
                dateOver := self
×
190
                                    transformDate: assoc key created_at
×
191
                                    to: aDateWeekMonthOrYear.
×
192
                groupedByDate
×
193
                        at: dateOver printString
×
194
                        ifPresent: [ :v | v add: assoc value ]
×
195
                        ifAbsentPut: [
×
196
                                OrderedCollection new
×
197
                                        add: assoc value;
×
198
                                        yourself ] ].
×
199

×
200
        groupedByDate := groupedByDate collect: [ :contribs |
×
201
                                 | totalAdd totalDele |
×
202
                                 totalAdd := contribs sum: [ :v | v at: #addition ].
×
203
                                 totalDele := contribs sum: [ :v | v at: #deletion ].
×
204
                                 {
×
205
                                         (#addition -> totalAdd).
×
206
                                         (#deletion -> totalDele) } asDictionary ].
×
207

×
208
        ^ {
×
209
                  (#overEach -> aDateWeekMonthOrYear name).
×
210
                  (#forOver -> (groupedByDate keys size printString
×
211
                    , aDateWeekMonthOrYear printString)).
×
212
                  (#avgAddition
×
213
                   ->
×
214
                   (groupedByDate collect: [ :d | d at: #addition ]) average asFloat).
×
215
                  (#avgDeletion
×
216
                   ->
×
217
                   (groupedByDate collect: [ :d | d at: #deletion ]) average asFloat).
×
218
                  (#details -> groupedByDate).
×
219
                  (#userCommits -> commits size) } asDictionary
×
220
]
×
221

222
{ #category : #'metrics - commits' }
223
GitMetric4User >> commentsContributionsSince: since until: until overA: aDateWeekMonthOrYear [
×
224

×
225
        | commits contributions groupedByDate |
×
226
        'GitMetric4User: comment contribution' recordInfo.
×
227

×
228
        groupedByDate := self
×
229
                                 setupGroupedDateFrom: since
×
230
                                 to: until
×
231
                                 over: aDateWeekMonthOrYear.
×
232

×
233
        gitAnalyzer := GitAnalyzer new
×
234
                               onModel: glhModel;
×
235
                               glhImporter: glhImporter.
×
236

×
237
        glhImporter withCommitDiffs: false.
×
238
        commits := self
×
239
                           loadCommitsFromProjectsIds: itsProjects keys
×
240
                           since: since
×
241
                           until: until.
×
242
        glhImporter withCommitDiffs: true.
×
243
        commits := commits reject: [ :commit | commit commitCreator ~= user ].
×
244
        commits do: [ :commit | glhImporter completeImportedCommit: commit ].
×
245

×
246

×
247
        contributions := commits collect: [ :commit |
×
248
                                 commit -> (gitAnalyzer
×
249
                                          fromCommit: commit;
×
250
                                          analyseCommentContribution) ].
×
251

×
252

×
253
        contributions do: [ :assoc |
×
254
                | dateOver |
×
255
                dateOver := self
×
256
                                    transformDate: assoc key created_at
×
257
                                    to: aDateWeekMonthOrYear.
×
258
                groupedByDate
×
259
                        at: dateOver printString
×
260
                        ifPresent: [ :v | v add: assoc value ]
×
261
                        ifAbsentPut: [
×
262
                                OrderedCollection new
×
263
                                        add: assoc value;
×
264
                                        yourself ] ].
×
265

×
266
        groupedByDate := groupedByDate collect: [ :contribs |
×
267
                                 contribs
×
268
                                         ifNotEmpty: [ contribs sum ]
×
269
                                         ifEmpty: [ 0 ] ].
×
270

×
271

×
272
        ^ {
×
273
                  (#details -> groupedByDate).
×
274
                  (#totalComments -> groupedByDate values sum).
×
275
                  (#avgComments -> groupedByDate values average asFloat).
×
276
                  (#overEach -> aDateWeekMonthOrYear name).
×
277
                  (#forOver -> (groupedByDate keys size printString
×
278
                    , aDateWeekMonthOrYear printString)).
×
279
                  (#userCommits -> commits size) } asDictionary
×
280
]
×
281

282
{ #category : #'metrics - commits' }
283
GitMetric4User >> commitFrequencySince: since until: until overA: aDateWeekMonthOrYear [
×
284

×
285
        | periods total groupedByDate userCommits |
×
286
        'GitMetric4User: commit frequency' recordInfo.
×
287

×
288
        groupedByDate := self
×
289
                                 setupGroupedDateFrom: since
×
290
                                 to: until
×
291
                                 over: aDateWeekMonthOrYear.
×
292

×
293
        glhImporter withCommitDiffs: false.
×
294
        userCommits := self
×
295
                               loadCommitsFromProjectsIds: itsProjects keys
×
296
                               since: since
×
297
                               until: until.
×
298
        glhImporter withCommitDiffs: true.
×
299
        userCommits := userCommits reject: [ :c | c commitCreator ~= user ].
×
300

×
301
        userCommits do: [ :c |
×
302
                | dateOver |
×
303
                dateOver := self
×
304
                                    transformDate: c created_at
×
305
                                    to: aDateWeekMonthOrYear.
×
306
                groupedByDate at: dateOver printString ifPresent: [ :v | v add: c ] ].
×
307

×
308
        periods := groupedByDate keys size.
×
309
        total := groupedByDate values sum: [ :commits | commits size ].
×
310

×
311

×
312
        ^ {
×
313
                  (#averageFrac -> (total / periods)).
×
314
                  (#averageFloat -> (total / periods) asFloat).
×
315
                  (#userCommit -> total).
×
316
                  (#forOver -> (groupedByDate keys size printString
×
317
                    , aDateWeekMonthOrYear printString)).
×
318
                  (#periode -> aDateWeekMonthOrYear name).
×
319
                  (#details -> groupedByDate) } asOrderedDictionary
×
320
]
×
321

322
{ #category : #'metrics - commits' }
323
GitMetric4User >> commitsProducedOnProject: projectId since: sinceDate until: untilDate [
×
324

×
325
        | frequencies |
×
326
        
×
327
        
×
328
        gitAnalyzer := GitAnalyzer new 
×
329
        glhImporter: glhImporter; 
×
330
        onModel: glhModel.
×
331
         
×
332
        frequencies := gitAnalyzer
×
333
                               onProject: (itsProjects at: projectId);
×
334
                               analyseCommitFrequencySince: sinceDate
×
335
                               until: untilDate. 
×
336
        
×
337
        "complete each commit "
×
338
        frequencies values flattened do: [ :commit |
×
339
                glhImporter completeImportedCommit: commit.
×
340
                 ].
×
341
        
×
342
        "Filter the associations in the 'frequencies' collection, removing any commits not created by the specified 'user'. "
×
343
        frequencies associations do: [ :assoc |
×
344
                |commits| 
×
345
                commits := assoc value.
×
346
                assoc value: (commits reject: [ :commit | commit commitCreator ~= user ]). 
×
347
        ].
×
348
        
×
349
        ^ frequencies 
×
350
]
×
351

352
{ #category : #'metrics - commits' }
353
GitMetric4User >> commitsProducedOnProject: aProjectId since: since until: until overA: aWeekOrMonthOrYear [
×
354
        "'aWeekOrMonthOrYear' should be the class of Data, Week, Month or Year"
×
355

×
356
        | frequency aggregatedFrequencies |
×
357
        aggregatedFrequencies := self
×
358
                                         setupGroupedDateFrom: since
×
359
                                         to: until
×
360
                                         over: aWeekOrMonthOrYear.
×
361

×
362
        frequency := self
×
363
                             commitsProducedOnProject: aProjectId
×
364
                             since: since
×
365
                             until: until.
×
366

×
367
        frequency associations do: [ :assoc |
×
368
                | date commits overDate |
×
369
                date := assoc key.
×
370
                commits := assoc value.
×
371

×
372
                commits ifNotEmpty: [ " convert the date as its week date. For some english reason, the week start in sunday so we should add a + 1 day "
×
373
                        overDate := self transformDate: date to: aWeekOrMonthOrYear.
×
374
                        aggregatedFrequencies
×
375
                                at: overDate printString
×
376
                                ifPresent: [ :collection | collection addAll: commits ]
×
377
                                ifAbsentPut: [ commits ] ] ].
×
378

×
379
        ^ aggregatedFrequencies
×
380
]
×
381

382
{ #category : #churn }
383
GitMetric4User >> delayUntilFirstChurnSince: since until: until onACommitWindowOf: maxCommitWindow overA: aDateWeekMonthOrYear [
×
384

×
385
        | commits groupedByDate res avg userCommits |
×
386
        'GitMetric4User: delay until first churn' recordInfo.
×
387

×
388
        groupedByDate := self
×
389
                                 setupGroupedDateFrom: since
×
390
                                 to: until
×
391
                                 over: aDateWeekMonthOrYear.
×
392

×
393
        glhImporter withCommitDiffs: false.
×
394
        commits := self
×
395
                           loadCommitsFromProjectsIds: itsProjects keys
×
396
                           since: since
×
397
                           until: until.
×
398
        glhImporter withCommitDiffs: true.
×
399

×
400
        userCommits := commits reject: [ :commit |
×
401
                               commit commitCreator ~= user ].
×
402
        commits := self
×
403
                           foundSuccessorOf: userCommits
×
404
                           andCompleteImportForMax: maxCommitWindow.
×
405

×
406

×
407
        "class commit by dates, filter none user commits"
×
408
        commits do: [ :commit |
×
409
                commit commitCreator = user ifTrue: [
×
410
                        | overDate |
×
411
                        overDate := self
×
412
                                            transformDate: commit created_at
×
413
                                            to: aDateWeekMonthOrYear.
×
414

×
415
                        groupedByDate
×
416
                                at: overDate printString
×
417
                                ifPresent: [ :arrayOfCommits | arrayOfCommits add: commit ]
×
418
                                ifAbsentPut: [
×
419
                                        OrderedCollection new
×
420
                                                add: commit;
×
421
                                                yourself ] ] ].
×
422

×
423

×
424

×
425
        res := groupedByDate collect: [ :commits4Date |
×
426
                       | durationFromA2B |
×
427
                       commits4Date collect: [ :commitA |
×
428
                               | commitB |
×
429
                               commitB := GitAnalyzer new
×
430
                                                  glhImporter: glhImporter;
×
431
                                                  onModel: glhModel;
×
432
                                                  fromCommit: commitA;
×
433
                                                  maxChildCommit: maxCommitWindow;
×
434
                                                  analyseDelayUntilFirstChurn.
×
435

×
436
                               durationFromA2B := commitB
×
437
                                                          ifNil: [ 0 ]
×
438
                                                          ifNotNil: [
×
439
                                                          commitB created_at - commitA created_at ].
×
440
                               durationFromA2B ] ].
×
441

×
442

×
443

×
444
        res := res collect: [ :durationsByDate |
×
445
                       | filtered |
×
446
                       filtered := durationsByDate reject: [ :value | value = 0 ].
×
447
                       filtered isEmpty
×
448
                               ifTrue: [ nil ]
×
449
                               ifFalse: [
×
450
                               (filtered sum: [ :v | v asDuration asSeconds]) / filtered size ] ].
×
451

×
452
        res := res reject: #isNil.
×
453

×
454
        res
×
455
                ifEmpty: [ avg := nil ]
×
456
                ifNotEmpty: [ avg := res values average asFloat ].
×
457

×
458

×
459
        ^ {
×
460
                  (#avgDelay -> avg).
×
461
                  (#overEach -> aDateWeekMonthOrYear name).
×
462
                  (#forOver -> (groupedByDate keys size printString
×
463
                    , aDateWeekMonthOrYear printString)).
×
464
                  (#details -> groupedByDate) } asDictionary
×
465
]
×
466

467
{ #category : #churn }
468
GitMetric4User >> delayUntilFirstChurnSince: since until: until overA: aDateWeekMonthOrYear [
×
469

×
470
        | commits groupedByDate res avg |
×
471
        self
×
472
                deprecated:
×
473
                'Use #delayUntilFirstChurnSince:until:onACommitWindowOf:overA: instead'
×
474
                on: '1 July 2024'
×
475
                in:
×
476
                'Pharo-11.0.0+build.726.sha.aece1b5473acf3830a0e082c1bc3a15d4ff3522b (64 Bit)'.
×
477

×
478
        'GitMetric4User: delay until first churn' recordInfo.
×
479

×
480
        groupedByDate := self
×
481
                                 setupGroupedDateFrom: since
×
482
                                 to: until
×
483
                                 over: aDateWeekMonthOrYear.
×
484

×
485
        commits := self
×
486
                           loadCommitsFromProjectsIds: itsProjects keys
×
487
                           since: since
×
488
                           until: until.
×
489

×
490
        "class commit by dates, filter none user commits"
×
491
        commits do: [ :commit |
×
492
                commit commitCreator = user ifTrue: [
×
493
                        | overDate |
×
494
                        overDate := self
×
495
                                            transformDate: commit created_at
×
496
                                            to: aDateWeekMonthOrYear.
×
497

×
498
                        groupedByDate
×
499
                                at: overDate printString
×
500
                                ifPresent: [ :arrayOfCommits | arrayOfCommits add: commit ]
×
501
                                ifAbsentPut: [
×
502
                                        OrderedCollection new
×
503
                                                add: commit;
×
504
                                                yourself ] ] ].
×
505

×
506

×
507

×
508
        res := groupedByDate collect: [ :commits4Date |
×
509
                       | durationFromA2B |
×
510
                       commits4Date collect: [ :commitA |
×
511
                               | commitB |
×
512
                               commitB := GitAnalyzer new
×
513
                                                  glhImporter: glhImporter;
×
514
                                                  onModel: glhModel;
×
515
                                                  fromCommit: commitA;
×
516
                                                  maxChildCommit: 5;
×
517
                                                  analyseDelayUntilFirstChurn.
×
518

×
519
                               durationFromA2B := commitB
×
520
                                                          ifNil: [ 0 ]
×
521
                                                          ifNotNil: [
×
522
                                                          commitB created_at - commitA created_at ].
×
523
                               durationFromA2B ] ].
×
524

×
525

×
526

×
527
        res := res collect: [ :durationsByDate |
×
528
                       | filtered |
×
529
                       filtered := durationsByDate reject: [ :value | value = 0 ].
×
530
                       filtered isEmpty
×
531
                               ifTrue: [ nil ]
×
532
                               ifFalse: [
×
533
                               (filtered sum: [ :v | v asDuration ]) / filtered size ] ].
×
534

×
535
        res := res reject: #isNil.
×
536

×
537
        res
×
538
                ifEmpty: [ avg := nil ]
×
539
                ifNotEmpty: [ avg := res values sum / res keys size ].
×
540

×
541

×
542
        ^ {
×
543
                  (#avgDelay -> avg).
×
544
                  (#overEach -> aDateWeekMonthOrYear name).
×
545
                  (#forOver -> (groupedByDate keys size printString
×
546
                    , aDateWeekMonthOrYear printString)).
×
547
                  (#details -> groupedByDate) } asDictionary
×
548
]
×
549

550
{ #category : #churn }
551
GitMetric4User >> foundSuccessorOf: userCommits andCompleteImportForMax: commitLimit [
×
552

×
553
        | analyzingCommits i size|
×
554
        analyzingCommits := Set new.
×
555
        glhImporter withCommitDiffs: true.
×
556

×
557
        userCommits do: [ :c |
×
558
                gitAnalyzer
×
559
                        visitChildCommits: c childCommits
×
560
                        toStoreThemIn: analyzingCommits
×
561
                        upto: commitLimit ].
×
562

×
563
        i := 0.
×
564
        size := analyzingCommits size. 
×
565
        analyzingCommits do: [ :c |
×
566
                ('import complete commits  [' , (i:=i+1) printString, '/', size printString , ']'  ) recordInfo.
×
567
                glhImporter completeImportedCommit: c ].
×
568

×
569
        ^ analyzingCommits
×
570
]
×
571

572
{ #category : #analysis }
573
GitMetric4User >> generateAnalysisForPeriod: period over: aDateWeekMonthOrYear withMaxCommitWindows: maxCommitWindow [
×
574

×
575
        | contribution commitFrequency commentContribution mergeRequestDuration codeChurn delayUntilFirstChurn averageTimeBetweenCommits numberOfProjectWithCommit until since numberOfOpenMergeRequests numberOfMergedMergeRequests numberOfClosedMergeRequests numberOfMergeRequestWithoutReview numberOfTicketsClosed |
×
576
        since := period at: #since.
×
577
        until := period at: #until.
×
578
        contribution := self
×
579
                                codeContributionsSince: since
×
580
                                until: until
×
581
                                overA: aDateWeekMonthOrYear.
×
582
        commitFrequency := self
×
583
                                   commitFrequencySince: since
×
584
                                   until: until
×
585
                                   overA: aDateWeekMonthOrYear.
×
586
        commentContribution := self
×
587
                                       commentsContributionsSince: since
×
588
                                       until: until
×
589
                                       overA: aDateWeekMonthOrYear.
×
590
        codeChurn := self
×
591
                             codeChurnSince: since
×
592
                             until: until
×
593
                             onACommitWindowOf: maxCommitWindow
×
594
                             overA: aDateWeekMonthOrYear.
×
595
        delayUntilFirstChurn := self
×
596
                                        delayUntilFirstChurnSince: since
×
597
                                        until: until
×
598
                                        onACommitWindowOf: maxCommitWindow
×
599
                                        overA: aDateWeekMonthOrYear.
×
600
        numberOfProjectWithCommit := self
×
601
                                             numberOfProjectWithCommitSince: since
×
602
                                             until: until
×
603
                                             overA: aDateWeekMonthOrYear.
×
604
        averageTimeBetweenCommits := self
×
605
                                             averageTimeBetweenCommitSince: since
×
606
                                             until: until
×
607
                                             overA: aDateWeekMonthOrYear.
×
608
        mergeRequestDuration := self
×
609
                                        mergeRequestDurationSince: since
×
610
                                        until: until
×
611
                                        overA: aDateWeekMonthOrYear.
×
612
        numberOfOpenMergeRequests := self
×
613
                                             numberOfOpenMergeRequestsSince: since
×
614
                                             until: until
×
615
                                             overA: aDateWeekMonthOrYear.
×
616
        numberOfMergedMergeRequests := self
×
617
                                               numberOfMergedMergeRequestsSince:
×
618
                                               since
×
619
                                               until: until
×
620
                                               overA: aDateWeekMonthOrYear.
×
621
        numberOfClosedMergeRequests := self
×
622
                                               numberOfClosedMergeRequestSince:
×
623
                                               since
×
624
                                               until: until
×
625
                                               overA: aDateWeekMonthOrYear.
×
626
        numberOfMergeRequestWithoutReview := self
×
627
                                                     numberOfMergeRequestsMergedWithoutReviewSince:
×
628
                                                     since
×
629
                                                     until: until
×
630
                                                     overA: aDateWeekMonthOrYear.
×
631
        numberOfTicketsClosed := self
×
632
                                         numberOfTicketsClosedSince: since
×
633
                                         until: until
×
634
                                         overA: aDateWeekMonthOrYear.
×
635
        ^ AnalysisReport new
×
636
                  username: self user name;
×
637
                  period: period;
×
638
                  over: aDateWeekMonthOrYear asString;
×
639
                  codeAddition: (contribution at: #avgAddition);
×
640
                  codeDeletion: (contribution at: #avgDeletion);
×
641
                  commitFrequency: (commitFrequency at: #averageFloat);
×
642
                  commentContribution: (commentContribution at: #avgComments);
×
643
                  mergeRequestDuration: (mergeRequestDuration at: #avgDuration);
×
644
                  codeChurn: (codeChurn at: #churn);
×
645
                  delayUntilFirstChurn: (delayUntilFirstChurn at: #avgDelay);
×
646
                  numberOfProjectWithCommit:
×
647
                          (numberOfProjectWithCommit at: #average);
×
648
                  averageTimeBetweenCommits:
×
649
                          (averageTimeBetweenCommits at: #average);
×
650
                  numberOfOpenMergeRequests:
×
651
                          (numberOfOpenMergeRequests at: #average);
×
652
                  numberOfMergedMergeRequest:
×
653
                          (numberOfMergedMergeRequests at: #average);
×
654
                  numberOfClosedMergeRequests:
×
655
                          (numberOfClosedMergeRequests at: #average);
×
656
                  numberOfMergeRequestsWithoutReview:
×
657
                          (numberOfMergeRequestWithoutReview at: #average);
×
658
                  numberOfTicketsClosed: (numberOfTicketsClosed at: #average)
×
659
]
×
660

661
{ #category : #initialization }
662
GitMetric4User >> initialize [
×
663

×
664
        user := GLHUser new.
×
665
        itsProjects := Dictionary new.
×
666
        itsCommits := Dictionary new.
×
667
        itsMergeRequests := Dictionary new.
×
668
        
×
669
        emailDomain := '@generic-domain.com'
×
670
]
×
671

672
{ #category : #accessing }
673
GitMetric4User >> itsProjects: projects [
×
674
        itsProjects := projects .
×
675
]
×
676

677
{ #category : #churn }
678
GitMetric4User >> loadCommitOfProjects: aCollection since: aTimespan [
×
679
        |commits|
×
680
        
×
681
        commits := (aCollection collect: [ :id |
×
682
                 glhImporter
×
683
                        importCommitsOProject: (itsProjects at: id)
×
684
                        since: aTimespan
×
685
                        until: nil ]) flattened.
×
686

×
687
        commits do: [ :commit |
×
688
                glhImporter completeImportedCommit: commit. 
×
689
                 ].
×
690

×
691
        ^ self userCommits.
×
692
]
×
693

694
{ #category : #loading }
695
GitMetric4User >> loadItsMergeRequesWithJiraIssueSince: since until: until [
×
696

×
697
        |email|
×
698
        itsMergeRequests := self
×
699
                                    loadItsMergeRequestsSince: since
×
700
                                    until: until.
×
701

×
702
        email := self userEmail. 
×
703

×
704
        jiraImporter importAllCurrentAndPastIssuesOf:
×
705
                email.
×
706

×
707
        GPJCConnector new
×
708
                gpModel: glhImporter glhModel;
×
709
                jiraModel: jiraImporter model;
×
710
                connect.
×
711

×
712
        ^ itsMergeRequests select: [ :mergeRequest |
×
713
                  mergeRequest jiraIssue isNotNil ]
×
714
]
×
715

716
{ #category : #loading }
717
GitMetric4User >> loadItsMergeRequestsSince: since until: until [
×
718

×
719
        | mergeRequests |
×
720
        gitAnalyzer := GitAnalyzer new
×
721
                               glhImporter: glhImporter;
×
722
                               onModel: glhModel.
×
723

×
724
        glhImporter withCommitDiffs: false.
×
725
        mergeRequests := self
×
726
                                 loadMergeRequestsFromProjectsIds: itsProjects keys
×
727
                                 since: since
×
728
                                 until: until.
×
729
        glhImporter withCommitDiffs: true.
×
730

×
731
        mergeRequests do: [ :mr | glhImporter importMergeResquestAuthor: mr ].
×
732

×
733
        itsMergeRequests := mergeRequests select: [ :mergeRequest |
×
734
                                    mergeRequest author = self user ].
×
735

×
736
        ^ itsMergeRequests
×
737
]
×
738

739
{ #category : #'metrics - merge request' }
740
GitMetric4User >> mergeRequestDurationSince: since until: until overA: aDateWeekMonthOrYear [
×
741

×
742
        | mergeRequest res groupedByDate filterGroups avg |
×
743
        groupedByDate := self
×
744
                                 setupGroupedDateFrom: since
×
745
                                 to: until
×
746
                                 over: aDateWeekMonthOrYear.
×
747

×
748
        mergeRequest := self loadItsMergeRequestsSince: since until: until.
×
749

×
750
        mergeRequest ifEmpty: [
×
751
                ^ {
×
752
                          (#avgDuration -> nil).
×
753
                          (#overEach -> aDateWeekMonthOrYear name).
×
754
                          (#forOver -> (groupedByDate keys size printString
×
755
                            , aDateWeekMonthOrYear printString)).
×
756
                          (#totalMergeRequest -> 0).
×
757
                          (#details -> nil) } asDictionary ].
×
758

×
759
        res := mergeRequest collect: [ :mr |
×
760
                       gitAnalyzer analyseMergeResquestValidation: mr ].
×
761

×
762

×
763
        res do: [ :dic |
×
764
                | overDate |
×
765
                overDate := self
×
766
                                    transformDate: (dic at: #created_at)
×
767
                                    to: aDateWeekMonthOrYear.
×
768

×
769
                groupedByDate
×
770
                        at: overDate printString
×
771
                        ifPresent: [ :durations | durations add: (dic at: #duration) ]
×
772
                        ifAbsentPut: [
×
773
                                OrderedCollection new
×
774
                                        add: (dic at: #duration);
×
775
                                        yourself ] ].
×
776

×
777

×
778
        filterGroups := groupedByDate reject: [ :array | array isEmpty ].
×
779

×
780
        filterGroups associations do: [ :assoc |
×
781
                | sum denominator |
×
782
                denominator := assoc value size.
×
783

×
784
                sum := assoc value sum: [ :v |
×
785
                               v ifNil: [
×
786
                                       denominator := denominator - 1.
×
787
                                       0 asDuration ] ].
×
788
                denominator = 0 ifTrue: [ denominator := 1 ].
×
789

×
790
                filterGroups at: assoc key put: sum / denominator ].
×
791

×
792
        avg := 0.
×
793
        filterGroups keys
×
794
                ifNotEmpty: [
×
795
                avg := filterGroups values sum / filterGroups keys size ].
×
796

×
797

×
798
        ^ {
×
799
                  (#avgDuration -> avg).
×
800
                  (#overEach -> aDateWeekMonthOrYear name).
×
801
                  (#forOver -> (groupedByDate keys size printString
×
802
                    , aDateWeekMonthOrYear printString)).
×
803
                  (#totalMergeRequest -> mergeRequest size).
×
804
                  (#details -> groupedByDate) } asDictionary
×
805
]
×
806

807
{ #category : #'metrics - merge request' }
808
GitMetric4User >> numberOfClosedMergeRequestSince: since until: until overA: aDateWeekMonthOrYear [
×
809

×
810
        | groupedByDate userMergeRequests dateOver average userClosedMergeRequests |
×
811
        groupedByDate := self
×
812
                                 setupGroupedDateFrom: since
×
813
                                 to: until
×
814
                                 over: aDateWeekMonthOrYear.
×
815

×
816
        userMergeRequests := self
×
817
                                     loadItsMergeRequestsSince: since
×
818
                                     until: until.
×
819

×
820
        userClosedMergeRequests := userMergeRequests select: [
×
821
                                           :userMergeRequest |
×
822
                                           userMergeRequest merged_at isNil and:
×
823
                                                   userMergeRequest state = 'closed' ].
×
824

×
825
        userClosedMergeRequests do: [ :userMergeRequest |
×
826
                dateOver := self
×
827
                                    transformDate: userMergeRequest created_at
×
828
                                    to: aDateWeekMonthOrYear.
×
829

×
830
                groupedByDate
×
831
                        at: dateOver printString
×
832
                        ifPresent: [ :value | value add: userMergeRequest ] ].
×
833

×
834

×
835
        groupedByDate := groupedByDate collect: [ :group | group size ].
×
836

×
837

×
838
        average := groupedByDate
×
839
                           ifEmpty: [ 0 ]
×
840
                           ifNotEmpty: [ groupedByDate average ].
×
841

×
842
        ^ {
×
843
                  (#overEach -> aDateWeekMonthOrYear name).
×
844
                  (#forOver -> (groupedByDate keys size printString
×
845
                    , aDateWeekMonthOrYear printString)).
×
846
                  (#average -> average asFloat).
×
847
                  (#details -> groupedByDate).
×
848
                  (#userMergeRequests -> userMergeRequests size) } asDictionary
×
849
]
×
850

851
{ #category : #'metrics - merge request' }
852
GitMetric4User >> numberOfMergeRequestsMergedWithoutReviewSince: since until: until overA: aDateWeekMonthOrYear [
×
853

×
854
        | groupedByDate userMergeRequests dateOver average noVerificationMergeRequests mergedMergeRequest |
×
855
        groupedByDate := self
×
856
                                 setupGroupedDateFrom: since
×
857
                                 to: until
×
858
                                 over: aDateWeekMonthOrYear.
×
859

×
860
        userMergeRequests := self
×
861
                                     loadItsMergeRequestsSince: since
×
862
                                     until: until.
×
863

×
864
        mergedMergeRequest := userMergeRequests select: [ :mr |
×
865
                                      mr merged_at isNotNil ].
×
866

×
867

×
868
        noVerificationMergeRequests := mergedMergeRequest select: [
×
869
                                               :userMergeRequest |
×
870
                                               | validation |
×
871
                                               glhImporter
×
872
                                                       importMergeResquestMerger:
×
873
                                                       userMergeRequest.
×
874

×
875
                                               validation := gitAnalyzer
×
876
                                                                     analyseMergeResquestValidation:
×
877
                                                                     userMergeRequest.
×
878

×
879
                                               userMergeRequest merge_user
×
880
                                               = userMergeRequest author and:
×
881
                                                       (validation at: #duration)
×
882
                                                       < 1 minutes ].
×
883

×
884

×
885
        noVerificationMergeRequests do: [ :userMergeRequest |
×
886
                dateOver := self
×
887
                                    transformDate: userMergeRequest created_at
×
888
                                    to: aDateWeekMonthOrYear.
×
889

×
890
                groupedByDate
×
891
                        at: dateOver printString
×
892
                        ifPresent: [ :value | value add: userMergeRequest ] ].
×
893

×
894

×
895
        groupedByDate := groupedByDate collect: [ :group | group size ].
×
896

×
897

×
898
        average := groupedByDate
×
899
                           ifEmpty: [ 0 ]
×
900
                           ifNotEmpty: [ groupedByDate average ].
×
901

×
902
        ^ {
×
903
                  (#overEach -> aDateWeekMonthOrYear name).
×
904
                  (#forOver -> (groupedByDate keys size printString
×
905
                    , aDateWeekMonthOrYear printString)).
×
906
                  (#average -> average asFloat).
×
907
                  (#details -> groupedByDate).
×
908
                  (#userMergeRequests -> userMergeRequests size) } asDictionary
×
909
]
×
910

911
{ #category : #'metrics - merge request' }
912
GitMetric4User >> numberOfMergedMergeRequestsSince: since until: until overA: aDateWeekMonthOrYear [
×
913

×
914
        | groupedByDate userMergeRequests dateOver average userMergedMergeRequests |
×
915
        groupedByDate := self
×
916
                                 setupGroupedDateFrom: since
×
917
                                 to: until
×
918
                                 over: aDateWeekMonthOrYear.
×
919
        userMergeRequests := self
×
920
                                     loadItsMergeRequestsSince: since
×
921
                                     until: until.
×
922

×
923
        userMergedMergeRequests := userMergeRequests select: [
×
924
                                           :userMergeRequest |
×
925
                                           userMergeRequest merged_at isNotNil ].
×
926

×
927
        userMergedMergeRequests do: [ :userMergeRequest |
×
928
                dateOver := self
×
929
                                    transformDate: userMergeRequest created_at
×
930
                                    to: aDateWeekMonthOrYear.
×
931
                groupedByDate
×
932
                        at: dateOver printString
×
933
                        ifPresent: [ :value | value add: userMergeRequest ] ].
×
934
        groupedByDate := groupedByDate collect: [ :group | group size ].
×
935

×
936
        average := groupedByDate
×
937
                           ifEmpty: [ 0 ]
×
938
                           ifNotEmpty: [ groupedByDate average ].
×
939
        ^ {
×
940
                  (#overEach -> aDateWeekMonthOrYear name).
×
941
                  (#forOver -> (groupedByDate keys size printString
×
942
                    , aDateWeekMonthOrYear printString)).
×
943
                  (#average -> average asFloat).
×
944
                  (#details -> groupedByDate).
×
945
                  (#userMergeRequests -> userMergeRequests size) } asDictionary
×
946
]
×
947

948
{ #category : #'metrics - merge request' }
949
GitMetric4User >> numberOfOpenMergeRequestsSince: since until: until overA: aDateWeekMonthOrYear [
×
950

×
951
        | groupedByDate userMergeRequests dateOver average |
×
952
        groupedByDate := self
×
953
                                 setupGroupedDateFrom: since
×
954
                                 to: until
×
955
                                 over: aDateWeekMonthOrYear.
×
956

×
957
        userMergeRequests := self
×
958
                                     loadItsMergeRequestsSince: since
×
959
                                     until: until.
×
960

×
961
        userMergeRequests do: [ :userMergeRequest |
×
962
                dateOver := self
×
963
                                    transformDate: userMergeRequest created_at
×
964
                                    to: aDateWeekMonthOrYear.
×
965

×
966
                groupedByDate
×
967
                        at: dateOver printString
×
968
                        ifPresent: [ :value | value add: userMergeRequest ] ].
×
969

×
970

×
971
        groupedByDate := groupedByDate collect: [ :group | group size ].
×
972

×
973

×
974
        average := groupedByDate
×
975
                           ifEmpty: [ 0 ]
×
976
                           ifNotEmpty: [ groupedByDate average ].
×
977

×
978
        ^ {
×
979
                  (#overEach -> aDateWeekMonthOrYear name).
×
980
                  (#forOver -> (groupedByDate keys size printString
×
981
                    , aDateWeekMonthOrYear printString)).
×
982
                  (#average -> average asFloat).
×
983
                  (#details -> groupedByDate).
×
984
                  (#userMergeRequests -> userMergeRequests size) } asDictionary
×
985
]
×
986

987
{ #category : #'metrics - commits' }
988
GitMetric4User >> numberOfProjectWithCommitSince: since until: until overA: aDateWeekMonthOrYear [
×
989
        | groupedByDate commits userCommits dateOver projects |
×
990
        groupedByDate := self
×
991
                                 setupGroupedDateFrom: since
×
992
                                 to: until
×
993
                                 over: aDateWeekMonthOrYear.
×
994
                
×
995
        gitAnalyzer := GitAnalyzer new
×
996
                               onModel: glhModel;
×
997
                               glhImporter: glhImporter.
×
998

×
999
        glhImporter withCommitDiffs: false.
×
1000
        commits := self
×
1001
                           loadCommitsFromProjectsIds: itsProjects keys
×
1002
                           since: since
×
1003
                           until: until.
×
1004
        glhImporter withCommitDiffs: true.
×
1005
        userCommits := commits reject: [ :commit | commit commitCreator ~= user ].
×
1006
        
×
1007

×
1008
        userCommits do: [ :userCommit |
×
1009
                 dateOver := self
×
1010
                                    transformDate: userCommit committed_date 
×
1011
                                    to: aDateWeekMonthOrYear.
×
1012
                        
×
1013
                groupedByDate at: dateOver printString ifPresent: [ :value | value add: (userCommit repository project) ].
×
1014
        ].
×
1015

×
1016
        groupedByDate := groupedByDate collect: [ :group |                 
×
1017
                projects := Set newFrom: group.                
×
1018
                projects size.
×
1019
        ].
×
1020

×
1021
        ^ {
×
1022
                  (#overEach -> aDateWeekMonthOrYear name).
×
1023
                  (#forOver -> (groupedByDate keys size printString
×
1024
                    , aDateWeekMonthOrYear printString)).
×
1025
                  (#average
×
1026
                   ->
×
1027
                   groupedByDate average asFloat).
×
1028
                  (#details -> groupedByDate).
×
1029
                  (#userCommits -> commits size) } asDictionary
×
1030

×
1031
]
×
1032

1033
{ #category : #'metrics -jira' }
1034
GitMetric4User >> numberOfTicketsClosedSince: since until: until overA: aDateWeekMonthOrYear [
×
1035

×
1036
        | groupedByDate itsMergeRequestsWithJiraIssue dateOver average mergedMergeRequestWithJiraIssue |
×
1037
        groupedByDate := self
×
1038
                                 setupGroupedDateFrom: since
×
1039
                                 to: until
×
1040
                                 over: aDateWeekMonthOrYear.
×
1041

×
1042
        itsMergeRequestsWithJiraIssue := self
×
1043
                                                 loadItsMergeRequesWithJiraIssueSince:
×
1044
                                                 since
×
1045
                                                 until: until.
×
1046

×
1047
        mergedMergeRequestWithJiraIssue := itsMergeRequestsWithJiraIssue
×
1048
                                                   select: [ :mr |
×
1049
                                                   mr merged_at isNotNil ].
×
1050

×
1051
        mergedMergeRequestWithJiraIssue do: [ :userMergeRequest |
×
1052
                dateOver := self
×
1053
                                    transformDate: userMergeRequest created_at
×
1054
                                    to: aDateWeekMonthOrYear.
×
1055
                groupedByDate
×
1056
                        at: dateOver printString
×
1057
                        ifPresent: [ :value | value add: userMergeRequest ] ].
×
1058

×
1059
        groupedByDate := groupedByDate collect: [ :group | group size ].
×
1060

×
1061
        average := groupedByDate
×
1062
                           ifEmpty: [ 0 ]
×
1063
                           ifNotEmpty: [ groupedByDate average ].
×
1064
        ^ {
×
1065
                  (#overEach -> aDateWeekMonthOrYear name).
×
1066
                  (#forOver -> (groupedByDate keys size printString
×
1067
                    , aDateWeekMonthOrYear printString)).
×
1068
                  (#average -> average asFloat).
×
1069
                  (#details -> groupedByDate).
×
1070
                  (#userMergeRequestsWithJiraIssue -> itsMergeRequestsWithJiraIssue size) }
×
1071
                  asDictionary
×
1072
]
×
1073

1074
{ #category : #accessing }
1075
GitMetric4User >> user [
×
1076
        ^ user
×
1077
]
×
1078

1079
{ #category : #accessing }
1080
GitMetric4User >> user: anUser [
×
1081
        user := anUser. 
×
1082
]
×
1083

1084
{ #category : #accessing }
1085
GitMetric4User >> userCommits [
×
1086
        ^ user commits
×
1087
]
×
1088

1089
{ #category : #email }
NEW
1090
GitMetric4User >> userEmail [
×
NEW
1091
        "overide this method to adapt on your situation"
×
NEW
1092
 
×
NEW
1093
        ^ ('' join: {
×
NEW
1094
                                  user username.
×
NEW
1095
                                  emailDomain }) asLowercase.
×
NEW
1096
]
×
1097

1098
{ #category : #email }
NEW
1099
GitMetric4User >> withUserEmailDomain: aEmailDomain [
×
NEW
1100
        emailDomain :=  aEmailDomain. 
×
NEW
1101
]
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc