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

moosetechnology / GitProjectHealth / 10918907131

18 Sep 2024 08:57AM UTC coverage: 20.103% (-0.2%) from 20.328%
10918907131

push

github

web-flow
Merge pull request #61 from moosetechnology/feat-jira-time-vs-merge-request-time

feat: add jira time and merge request time difference metric

0 of 207 new or added lines in 11 files covered. (0.0%)

4 existing lines in 2 files now uncovered.

1961 of 9755 relevant lines covered (20.1%)

0.2 hits per line

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

29.27
/src/GitLabProjectHealth-Model-Importer/GLPHModelImporter.class.st
1
Class {
2
        #name : #GLPHModelImporter,
3
        #superclass : #GLHModelImporter,
4
        #category : #'GitLabProjectHealth-Model-Importer'
5
}
6

7
{ #category : #'as yet unclassified' }
8
GLPHModelImporter >> blockForDiffRangeEquality [
×
9

×
10
        ^ [ :existing :new |
×
11
          existing diff mooseID = new diff mooseID and: [
×
12
                  existing originalLineRange = new originalLineRange and: [
×
13
                          existing newLineRange = new newLineRange ] ] ]
×
14
]
×
15

16
{ #category : #commit }
17
GLPHModelImporter >> commitsOfProject: aGLHProject forRefName: refName until: toDate [
×
18

×
19
        | newlyFoundCommit page |
×
20
        page := 0.
×
21
        newlyFoundCommit := { true }.
×
22
        [ newlyFoundCommit isNotEmpty ] whileTrue: [
×
23
                | results parsedResults existingCommits |
×
24
                page := page + 1.
×
25
                ('import commit page ' , page printString) recordInfo.
×
26
                results := self glhApi
×
27
                                   commitsOfProject: aGLHProject id
×
28
                                   forRefName: refName
×
29
                                   since: nil
×
30
                                   until: nil
×
31
                                   path: nil
×
32
                                   author: nil
×
33
                                   all: nil
×
34
                                   with_stats: nil
×
35
                                   firstParent: nil
×
36
                                   order: nil
×
37
                                   trailers: nil
×
38
                                   perPage: 100
×
39
                                   page: page.
×
40
                parsedResults := self parseCommitsResult: results.
×
41
                existingCommits := aGLHProject mooseModel allWithType: GLHCommit.
×
42

×
43
                newlyFoundCommit := parsedResults reject: [ :commitParsed |
×
44
                                            (toDate isNil or: [
×
45
                                                     commitParsed committed_date
×
46
                                                     < toDate asDateAndTime ]) or: [
×
47
                                                    existingCommits anySatisfy: [ :existingCommit |
×
48
                                                            existingCommit id = commitParsed id ] ] ].
×
49
                self glhModel addAll: newlyFoundCommit unless: self blockOnIdEquality.
×
50
                aGLHProject repository commits addAll: newlyFoundCommit unless: self blockOnIdEquality  ].
×
51
        self withCommitDiffs ifTrue: [
×
52
                aGLHProject repository commits do: [ :commit |
×
53
                        self importDiffOfCommit: commit ] ]
×
54
]
×
55

56
{ #category : #'private - api' }
57
GLPHModelImporter >> completeImportProject: aGLHProject [
×
58
        |completedProject|
×
59
        completedProject := super completeImportProject: aGLHProject.
×
60

×
61
        "for this initial import, with only look at some but not all MR"
×
62
        withInitialMergeRequest ifTrue: [ self
×
63
                importMergeRequests: completedProject
×
64
                since: DateAndTime today
×
65
                until: DateAndTime now. ].
×
66

×
67
        ^ completedProject
×
68
]
×
69

70
{ #category : #'private - configure reader' }
71
GLPHModelImporter >> configureReaderForMergeRequest: reader [
1✔
72
        "declare quil y a un array a mapper"
1✔
73

1✔
74
        reader for: #ArrayOfMergeRequest customDo: [ :customMappting |
1✔
75
                customMappting listOfElementSchema: GLPHEMergeRequest ].
1✔
76

1✔
77
        "declare la liste des properties"
1✔
78
        reader for: GLPHEMergeRequest do: [ :mapping |
1✔
79
                mapping mapInstVars:
1✔
80
                        #( blocking_discussions_resolved changes_count description
1✔
81
                           detailed_merge_status discussion_locked downvotes draft first_deployed_to_production_at
1✔
82
                           force_remove_source_branch has_conflicts id iid labels latest_build_finished_at
1✔
83
                           latest_build_started_at merge_commit_sha merge_status
1✔
84
                           merge_when_pipeline_succeeds merged_at milestone project_id
1✔
85
                           reference references_full references_relative
1✔
86
                           references_short sha should_remove_source_branch
1✔
87
                           source_branch source_project_id squash squash_commit_sha
1✔
88
                           squash_on_merge state subscribed target_branch target_project_id
1✔
89
                           task_completion_status_completed_count
1✔
90
                           task_completion_status_count time_stats_human_time_estimate
1✔
91
                           time_stats_human_total_time_spent
1✔
92
                           time_stats_time_estimate time_stats_total_time_spent
1✔
93
                           title updated_at upvotes user_notes_count web_url work_in_progress ).
1✔
94
                (mapping mapInstVar: #created_at) valueSchema: DateAndTime.
1✔
95
                (mapping mapInstVar: #updated_at) valueSchema: DateAndTime.
1✔
96
                (mapping mapInstVar: #merged_at) valueSchema: DateAndTime.
1✔
97
                (mapping mapInstVar: #closed_at) valueSchema: DateAndTime.
1✔
98
                "(mapping mapInstVar: #assignee) valueSchema: GLHUser."
1✔
99
                mapping
1✔
100
                        mapProperty: #author
1✔
101
                        getter: [  ]
1✔
102
                        setter: [ :object :value |
1✔
103
                        object cacheAt: #authorID put: (value at: #id) ].
1✔
104
                mapping
1✔
105
                        mapProperty: #merge_user
1✔
106
                        getter: [  ]
1✔
107
                        setter: [ :object :value | 
1✔
108
                                value ifNotNil: [
1✔
109
                                        object cacheAt: #mergeUserID put: (value at: #id) ] ] ].
1✔
110

1✔
111
        "(mapping mapInstVar: #closed_by) valueSchema: GLHUser.
1✔
112
        (mapping mapInstVar: #mergeCommit) valueSchema: GLHCommit."
1✔
113
        "indique ce que doit faire le reader lorsqu'il parse une DateAndTime object"
1✔
114
        reader for: DateAndTime customDo: [ :mapping |
1✔
115
                mapping decoder: [ :string |
1✔
116
                        string ifNil: [ nil ] ifNotNil: [ DateAndTime fromString: string ] ] ]
1✔
117
]
1✔
118

119
{ #category : #import }
120
GLPHModelImporter >> importCommitsOfBranch: aGLHBranch [
×
121

×
122
        | commits |
×
123
        "        result := self glhApi
×
124
                          commitsOfProject: aGLHBranch repository project id
×
125
                          forRefName: aGLHBranch name."
×
126
        commits := self
×
127
                           importCommitsOfBranch: aGLHBranch
×
128
                           forRefName: aGLHBranch name
×
129
                           since: withCommitsSince.
×
130

×
131
        self chainsCommitsFrom: commits.
×
132

×
133
        commits do: [ :aCommit |
×
134
                aCommit repository: aGLHBranch repository.
×
135
                self completeImportedCommit: aCommit. 
×
136
                 ]
×
137
]
×
138

139
{ #category : #api }
140
GLPHModelImporter >> importDiffOfCommit: aCommit [
×
141

×
142
        super importDiffOfCommit: aCommit.
×
143
        
×
144
        "changes are added into the model during the import"
×
145
        aCommit diffs do: [ :diff | self importDiffRangesForDiff: diff ].
×
146

×
147
        ^ aCommit diffs
×
148
]
×
149

150
{ #category : #'as yet unclassified' }
151
GLPHModelImporter >> importDiffOfMergeRequest: aMergeRequest [
×
152

×
153
        | result diffsResult |
×
154
        aMergeRequest diffs ifNotEmpty: [
×
155
                'Diff of already importer: '
×
156
                , aMergeRequest iid printString recordInfo.
×
157
                ^ aMergeRequest diffs ].
×
158
        ('Import diff commits of MR ' , aMergeRequest iid printString)
×
159
                recordInfo.
×
160
        result := self glhApi
×
161
                          diffsMergeRequestOfProject: aMergeRequest project_id
×
162
                          withId: aMergeRequest iid.
×
163

×
164
        diffsResult := self newParseDiffResult: result.
×
165

×
166

×
167
        aMergeRequest diffs
×
168
                addAll: diffsResult
×
169
                unless: self blockForDiffEquality.
×
170
        self glhModel
×
171
                addAll: aMergeRequest diffs
×
172
                unless: self blockForDiffEquality.
×
173

×
174
        aMergeRequest diffs do: [ :diff | self importDiffRangesForDiff: diff ].
×
175

×
176
        ^ aMergeRequest diffs
×
177
]
×
178

179
{ #category : #import }
180
GLPHModelImporter >> importDiffRangesForDiff: aGLHDiff [
×
181

×
182
        | diffRanges |
×
183
        aGLHDiff diffRanges ifNotEmpty: [
×
184
                ('Diffs already imported for ' , aGLHDiff printString) recordInfo.
×
185
                ^ aGLHDiff diffRanges ].
×
186

×
187
        ('Import changes of diff ' , aGLHDiff printString) recordInfo.
×
188
        "the import of 'diffRanges' entites is technically done inside the parseDiffString"
×
189

×
190
        diffRanges := self glhModel
×
191
                              addAll: (self parseDiffString: aGLHDiff)
×
192
                              unless: self blockForDiffRangeEquality.
×
193
        ^ aGLHDiff diffRanges
×
194
                  addAll: diffRanges
×
195
                  unless: self blockForDiffRangeEquality
×
196
]
×
197

198
{ #category : #'import - merge request' }
NEW
199
GLPHModelImporter >> importMergeRequestCommits: aGLPHEMergeRequest [
×
NEW
200

×
NEW
201
        | results page commits parseResult |
×
NEW
202
        aGLPHEMergeRequest commits ifNotNil: [ ^ aGLPHEMergeRequest commits ].
×
NEW
203
        page := 1.
×
NEW
204

×
NEW
205
        parseResult := { nil }.
×
NEW
206
        commits := OrderedCollection new.
×
NEW
207

×
NEW
208
        [
×
NEW
209
        results := glhApi
×
NEW
210
                           commitsOfMergeRequest: aGLPHEMergeRequest iid
×
NEW
211
                           ofProject: aGLPHEMergeRequest project id
×
NEW
212
                           page: page
×
NEW
213
                           perPage: 100.
×
NEW
214
        parseResult := self parseCommitsResult: results.
×
NEW
215

×
NEW
216
        commits addAll: parseResult.
×
NEW
217
        page := page + 1 ] doWhileTrue: [ parseResult isNotEmpty ].
×
NEW
218

×
NEW
219

×
NEW
220
        commits := commits collect: [ :commit | self importCommit: commit id ofProject: aGLPHEMergeRequest project ].
×
NEW
221
        aGLPHEMergeRequest commits: commits.
×
NEW
222

×
NEW
223

×
NEW
224
        ^ commits
×
NEW
225
]
×
226

227
{ #category : #import }
NEW
228
GLPHModelImporter >> importMergeRequestMergeCommits: aGLPHEMergeRequest [
×
NEW
229

×
NEW
230
        | foundCommits |
×
NEW
231
        foundCommits := OrderedCollection new.
×
NEW
232

×
NEW
233
        ('Import commit sha of MR:  ' , aGLPHEMergeRequest iid printString)
×
NEW
234
                recordInfo.
×
NEW
235
        "the founds commits are added to the model during their respective import"
×
NEW
236
        aGLPHEMergeRequest mergeRequestCommit: ((self
×
NEW
237
                          importCommitOfProject: aGLPHEMergeRequest project
×
NEW
238
                          withId: aGLPHEMergeRequest sha) ifNotNil: [ :commit |
×
NEW
239
                         foundCommits add: commit ]).
×
NEW
240

×
NEW
241
        ('Import commit merge_commit_sha of MR:  '
×
NEW
242
         , aGLPHEMergeRequest iid printString) recordInfo.
×
NEW
243
        aGLPHEMergeRequest mergedCommit: ((self
×
NEW
244
                          importCommitOfProject: aGLPHEMergeRequest project
×
NEW
245
                          withId: aGLPHEMergeRequest merge_commit_sha) ifNotNil: [ :commit |
×
NEW
246
                         foundCommits add: commit ]).
×
NEW
247

×
NEW
248
        ('Import commit squash_commit_sha of MR:  '
×
NEW
249
         , aGLPHEMergeRequest iid printString) recordInfo.
×
NEW
250
        aGLPHEMergeRequest squashCommit: ((self
×
NEW
251
                          importCommitOfProject: aGLPHEMergeRequest project
×
NEW
252
                          withId: aGLPHEMergeRequest squash_commit_sha) ifNotNil: [ :commit |
×
NEW
253
                         foundCommits add: commit ]).
×
NEW
254

×
NEW
255

×
NEW
256
        self chainsCommitsFrom: foundCommits.
×
NEW
257
        ^ foundCommits
×
NEW
258
]
×
259

260
{ #category : #'import - merge request' }
261
GLPHModelImporter >> importMergeRequests: aGLHProject [
×
262

×
263
        | results parsedResults mrs|
×
264
        ('Import merge request of Project: ' , aGLHProject id printString)
×
265
                recordInfo.
×
266

×
267
        results := self glhApi mergeRequestOfProject: aGLHProject id.
×
268
        parsedResults := self parseMergeRequestResult: results.
×
269

×
270
        aGLHProject mergeRequests
×
271
                addAll: parsedResults
×
272
                unless: self blockOnIdEquality.
×
273

×
274
        mrs := self glhModel
×
275
                addAll: aGLHProject mergeRequests
×
276
                unless: self blockOnIdEquality.
×
277

×
278

×
279
        "gets it related commits"
×
280
        aGLHProject mergeRequests do: [ :mr |
×
NEW
281
                self importMergeRequestMergeCommits: mr ].
×
282

×
283

×
284
        self withCommitDiffs ifTrue: [
×
285
                aGLHProject mergeRequests do: [ :mr |
×
286
                        self importDiffOfMergeRequest: mr ] ].
×
287
        
×
288
        ^ mrs
×
289
]
×
290

291
{ #category : #'import - merge request' }
292
GLPHModelImporter >> importMergeRequests: aGLHProject since: fromDate until: toDate [
×
293

×
294
        | newlyFoundMR page foundMR |
×
295
        ('import MR of Project ' , aGLHProject name) recordInfo.
×
296

×
297
        page := 0.
×
298
        foundMR := OrderedCollection new.
×
299
        newlyFoundMR := { true }.
×
300
        [ newlyFoundMR isNotEmpty ] whileTrue: [
×
301
                | results |
×
302
                page := page + 1.
×
303
                ('import MR page ' , page printString) recordInfo.
×
304
                results := self glhApi
×
305
                                   mergeRequestsOfProject: aGLHProject id
×
306
                                   createdAfter:
×
307
                                   (fromDate ifNotNil: [ fromDate asDateAndTime asString ])
×
308
                                   createdBefore:
×
309
                                   (toDate ifNotNil: [ toDate asDateAndTime asString ])
×
310
                                   authorId: nil
×
311
                                   authorUsername: nil
×
312
                                   scope: 'all'
×
313
                                   orderBy: 'created_at'
×
314
                                   page: page.
×
315

×
316

×
317
                newlyFoundMR := aGLHProject mergeRequests
×
318
                                        addAll: (self parseMergeRequestResult: results)
×
319
                                        unless: self blockOnIdEquality.
×
320
                foundMR addAll: newlyFoundMR ].
×
321

×
322

×
323
        "gets it related commits"
×
324
        aGLHProject mergeRequests do: [ :mr |
×
NEW
325
                self importMergeRequestMergeCommits: mr ].
×
326

×
327
        self withCommitDiffs ifTrue: [
×
328
                aGLHProject mergeRequests do: [ :mr |
×
329
                        self importDiffOfMergeRequest: mr ] ].
×
330

×
331
        self glhModel addAll: foundMR unless: (self blockEqualityOn: #iid).
×
332

×
333
        ^ foundMR
×
334
]
×
335

336
{ #category : #'import - merge request' }
337
GLPHModelImporter >> importMergeResquestApprovals: aGLPHEMergeRequest [
×
338

×
339
        | results parsedResult |
×
340
        (String streamContents: [ :str |
×
341
                 str << 'Check approvals of '.
×
342
                 aGLPHEMergeRequest printOn: str ]) recordInfo.
×
343
        results := self glhApi
×
344
                           approvalsOfMergeQuest: aGLPHEMergeRequest iid
×
345
                           ofProject: aGLPHEMergeRequest project id.
×
346

×
347
        parsedResult := generalReader
×
348
                                on: results readStream;
×
349
                                next.
×
350

×
351
        (parsedResult at: #approved_by) do: [ :approvedUser |
×
352
                aGLPHEMergeRequest addApproved_by:
×
353
                        (self importUser: ((approvedUser at: #user) at: #id)) ].
×
354
        aGLPHEMergeRequest approved: (parsedResult at: #approved).
×
355
        ^ aGLPHEMergeRequest
×
356
]
×
357

358
{ #category : #'import - merge request' }
359
GLPHModelImporter >> importMergeResquestAuthor: aGLPHEMergeRequest [
1✔
360

1✔
361
        | authorID |
1✔
362
        aGLPHEMergeRequest author ifNotNil: [ ^ aGLPHEMergeRequest author ].
1✔
363
        authorID := aGLPHEMergeRequest cacheAt: #authorID ifAbsent: [
1✔
364
                            (generalReader
1✔
365
                                     on: (self glhApi
1✔
366
                                                      mergeRequestOfProject:
1✔
367
                                                              aGLPHEMergeRequest project_id
1✔
368
                                                      withId: aGLPHEMergeRequest iid) readStream;
1✔
369
                                     next) at: #author at: #id ].
1✔
370
        aGLPHEMergeRequest author: (self importUser: authorID)
1✔
371
]
1✔
372

373
{ #category : #'import - merge request' }
374
GLPHModelImporter >> importMergeResquestMerger: aGLPHEMergeRequest [
1✔
375

1✔
376
        | authorID |
1✔
377
        aGLPHEMergeRequest merge_user ifNotNil: [
1✔
378
                ^ aGLPHEMergeRequest merge_user ].
1✔
379
        authorID := aGLPHEMergeRequest cacheAt: #mergeUserID ifAbsent: [
1✔
380
                            (generalReader
1✔
381
                                     on: (self glhApi
1✔
382
                                                      mergeRequestOfProject:
1✔
383
                                                              aGLPHEMergeRequest project_id
1✔
384
                                                      withId: aGLPHEMergeRequest iid) readStream;
1✔
385
                                     next)
1✔
386
                                    at: #merge_user
1✔
387
                                    ifPresent: [ :mergeUser |
1✔
388
                                    mergeUser ifNotNil: [ :mruser | mruser at: #id ] ] ].
1✔
389
        aGLPHEMergeRequest merge_user: (self importUser: authorID)
1✔
390
]
1✔
391

392
{ #category : #'private - api' }
393
GLPHModelImporter >> importProject: aProjectID [
×
394

×
395
        | result projectResult |
×
396
        ('Import project with id:  ' , aProjectID printString) recordInfo.
×
397

×
398
        result := self glhApi project: aProjectID.
×
399
        projectResult := self parseProjectResult: result.
×
400

×
401
        ^ self completeImportProject: projectResult
×
402
]
×
403

404
{ #category : #'private - api' }
405
GLPHModelImporter >> importRepository: aGLHRepository [
×
406

×
407
        super importRepository: aGLHRepository.
×
408

×
409
        withInitialCommits ifTrue: [
×
410
                aGLHRepository branches do: [ :branch |
×
411
                        self importCommitsOfBranch: branch ] ]
×
412
]
×
413

414
{ #category : #initialization }
415
GLPHModelImporter >> initReader [
1✔
416

1✔
417
        super initReader.
1✔
418
        self configureReaderForMergeRequest: generalReader
1✔
419
]
1✔
420

421
{ #category : #initialization }
422
GLPHModelImporter >> initialize [
1✔
423

1✔
424
        super initialize.
1✔
425
        withCommitDiffs := true
1✔
426
]
1✔
427

428
{ #category : #parsing }
429
GLPHModelImporter >> parseDiffString: aDiff [
1✔
430
        "parse diff string to create entities for each lines"
1✔
431

1✔
432
        | lines range index firstChangeRange |
1✔
433
        lines := aDiff diffString lines.
1✔
434
        index := 0.
1✔
435
        range := nil.
1✔
436

1✔
437
        lines ifEmpty: [ ^ aDiff diffRanges ].
1✔
438
        lines := self filterCommitChanges: lines.
1✔
439
        (lines first beginsWith: '@@') ifFalse: [ ^ aDiff diffRanges ].
1✔
440

1✔
441
        lines do: [ :line |
1✔
442
                | aChange |
1✔
443
                firstChangeRange := false.
1✔
444
                (line trim beginsWith: #'@@') ifTrue: [
1✔
445
                        range := GLPHEDiffRange newFrom: line.
1✔
446
                        firstChangeRange := true.
1✔
447
                        range := aDiff diffRanges add: range unless: [ :existing :new |
1✔
448
                                         existing originalLineRange = new originalLineRange and: [
1✔
449
                                                 existing newLineRange = new newLineRange ] ] ].
1✔
450

1✔
451
                self withCommitDiffs ifTrue: [
1✔
452
                        firstChangeRange ifFalse: [
1✔
453
                                aChange := GLPHEChange newFrom: line.
1✔
454
                                aChange relativeIndex: index.
1✔
455
                                aChange := range changes add: aChange unless: [ :existing :new |
1✔
456
                                                   existing sourceCode = new sourceCode and: [
1✔
457
                                                           existing index = new index ] ].
1✔
458
                                index := index + 1 ] ] ].
1✔
459

1✔
460
        "add changes to the diff range"
1✔
461
        aDiff diffRanges do: [ :diffRange |
1✔
462
                self glhModel addAll: diffRange changes unless: [ :existing :new |
1✔
463
                        existing diffRange mooseID = new diffRange mooseID and: [
1✔
464
                                existing sourceCode = new sourceCode and: [
1✔
465
                                        existing index = new index ] ] ] ].
1✔
466

1✔
467
        ^ aDiff diffRanges
1✔
468
]
1✔
469

470
{ #category : #parsing }
471
GLPHModelImporter >> parseMergeRequestResult: result [
1✔
472

1✔
473
        generalReader on: result readStream.
1✔
474
        ^ generalReader nextAs: #ArrayOfMergeRequest
1✔
475
]
1✔
476

477
{ #category : #parsing }
478
GLPHModelImporter >> parseProjectResult: aResult [ 
×
479
                | reader |
×
480
        reader := NeoJSONReader on: aResult readStream.
×
481
        reader for: GLHProject do: [ :mapping |
×
482
                mapping mapInstVars. ].
×
483
"        reader mapInstVarsFor: GLHProject."
×
484

×
485
        ^ reader nextAs: GLHProject
×
486
]
×
487

×
488
{ #category : #accessing }
×
489
GLPHModelImporter >> withCommitsSince: someDays [
×
490
        "substract the current date with a given number of days. Use to retrieve the commits submit in the last giving days"
×
491

×
492
        "(GLPHModelImporter new withCommitsSince: 1 week ) >>> (Date today - 1 week) asDateAndTime"
×
493

×
494
        "(GLPHModelImporter new withCommitsSince: 30 day ) >>> (Date today - 30 day) asDateAndTime"
×
495

×
496
        (someDays isKindOf: DateAndTime)
×
497
                ifTrue: [ withCommitsSince := someDays ]
×
498
                ifFalse: [
×
499
                withCommitsSince := (Date today - someDays) asDateAndTime ]
×
500
]
×
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

© 2025 Coveralls, Inc