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

moosetechnology / GitProjectHealth / 9746494520

01 Jul 2024 02:55PM UTC coverage: 29.879% (+0.02%) from 29.855%
9746494520

push

github

HLAD Nicolas
Merge f7e69aebf

44 of 163 new or added lines in 8 files covered. (26.99%)

546 existing lines in 10 files now uncovered.

2266 of 7584 relevant lines covered (29.88%)

0.3 hits per line

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

64.5
/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 [
1✔
9

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

16
{ #category : #commit }
17
GLPHModelImporter >> chainsCommitsFrom: commitsCollection [
1✔
18

1✔
19
        | dic |
1✔
20
        
1✔
21
        ('Chains ', commitsCollection size printString , ' commits') recordInfo.
1✔
22
        
1✔
23
        dic := ((self glhModel allWithType: GLHCommit) collect: [ :commit |
1✔
24
                        commit id -> commit ]) asSet asDictionary.
1✔
25

1✔
26
        commitsCollection do: [ :commit |
1✔
27
                commit parent_ids do: [ :parentId | 
1✔
28
                        dic
1✔
29
                                at: parentId
1✔
30
                                ifPresent: [ :parentCommit |
1✔
31
                                        parentCommit childCommits
1✔
32
                                                add: commit
1✔
33
                                                unless: self blockOnIdEquality ]
1✔
34
                                ifAbsent: [  ] ] ].
1✔
35
        ^ commitsCollection
1✔
36
]
1✔
37

38
{ #category : #commit }
39
GLPHModelImporter >> commitsOfProject: aGLHProject forRefName: refName until: toDate [
×
40

×
41
        | newlyFoundCommit page |
×
42
        page := 0.
×
43
        newlyFoundCommit := { true }.
×
44
        [ newlyFoundCommit isNotEmpty ] whileTrue: [
×
45
                | results parsedResults existingCommits |
×
46
                page := page + 1.
×
47
                ('import commit page ' , page printString) recordInfo.
×
48
                results := self glhApi
×
49
                                   commitsOfProject: aGLHProject id
×
50
                                   forRefName: refName
×
51
                                   since: nil
×
52
                                   until: nil
×
53
                                   path: nil
×
54
                                   author: nil
×
55
                                   all: nil
×
56
                                   with_stats: nil
×
57
                                   firstParent: nil
×
58
                                   order: nil
×
59
                                   trailers: nil
×
60
                                   perPage: 100
×
61
                                   page: page.
×
62
                parsedResults := self parseCommitsResult: results.
×
63
                existingCommits := aGLHProject mooseModel allWithType: GLHCommit.
×
64

×
65
                newlyFoundCommit := parsedResults reject: [ :commitParsed |
×
66
                                            (toDate isNil or: [
×
67
                                                     commitParsed committed_date
×
68
                                                     < toDate asDateAndTime ]) or: [
×
69
                                                    existingCommits anySatisfy: [ :existingCommit |
×
70
                                                            existingCommit id = commitParsed id ] ] ].
×
71
                self glhModel addAll: newlyFoundCommit unless: self blockOnIdEquality.
×
72
                aGLHProject repository commits addAll: newlyFoundCommit unless: self blockOnIdEquality  ].
×
73
        self withCommitDiffs ifTrue: [
×
74
                aGLHProject repository commits do: [ :commit |
×
75
                        self importDiffOfCommit: commit ] ]
×
76
]
×
77

78
{ #category : #'private - api' }
79
GLPHModelImporter >> completeImportProject: aGLHProject [
1✔
80

1✔
81
        super completeImportProject: aGLHProject.
1✔
82

1✔
83
        "for this initial import, with only look at some but not all MR"
1✔
84
        withInitialMergeRequest ifTrue: [ self
1✔
85
                importMergeRequests: aGLHProject
1✔
86
                since: DateAndTime today
1✔
87
                until: DateAndTime now. ].
1✔
88

1✔
89
        ^ aGLHProject
1✔
90
]
1✔
91

92
{ #category : #'private - configure reader' }
93
GLPHModelImporter >> configureReaderForMergeRequest: reader [
1✔
94
        "declare quil y a un array a mapper"
1✔
95

1✔
96
        reader for: #ArrayOfMergeRequest customDo: [ :customMappting |
1✔
97
                customMappting listOfElementSchema: GLPHEMergeRequest ].
1✔
98

1✔
99
        "declare la liste des properties"
1✔
100
        reader for: GLPHEMergeRequest do: [ :mapping |
1✔
101
                mapping mapInstVars:
1✔
102
                        #( blocking_discussions_resolved changes_count description
1✔
103
                           detailed_merge_status discussion_locked downvotes draft first_deployed_to_production_at
1✔
104
                           force_remove_source_branch has_conflicts id iid labels latest_build_finished_at
1✔
105
                           latest_build_started_at merge_commit_sha merge_status
1✔
106
                           merge_when_pipeline_succeeds merged_at milestone project_id
1✔
107
                           reference references_full references_relative
1✔
108
                           references_short sha should_remove_source_branch
1✔
109
                           source_branch source_project_id squash squash_commit_sha
1✔
110
                           squash_on_merge state subscribed target_branch target_project_id
1✔
111
                           task_completion_status_completed_count
1✔
112
                           task_completion_status_count time_stats_human_time_estimate
1✔
113
                           time_stats_human_total_time_spent
1✔
114
                           time_stats_time_estimate time_stats_total_time_spent
1✔
115
                           title updated_at upvotes user_notes_count web_url work_in_progress ).
1✔
116
                (mapping mapInstVar: #created_at) valueSchema: DateAndTime.
1✔
117
                (mapping mapInstVar: #updated_at) valueSchema: DateAndTime.
1✔
118
                (mapping mapInstVar: #merged_at) valueSchema: DateAndTime.
1✔
119
                (mapping mapInstVar: #closed_at) valueSchema: DateAndTime
1✔
120
                "                
1✔
121
                (mapping mapInstVar: #assignee) valueSchema: GLHUser.
1✔
122
                (mapping mapInstVar: #author) valueSchema: GLHUser.
1✔
123
                (mapping mapInstVar: #closed_by) valueSchema: GLHUser.
1✔
124
                (mapping mapInstVar: #mergeCommit) valueSchema: GLHCommit." ].
1✔
125

1✔
126
        "indique ce que doit faire le reader lorsqu'il parse une DateAndTime object"
1✔
127
        reader for: DateAndTime customDo: [ :mapping |
1✔
128
                mapping decoder: [ :string |
1✔
129
                        string ifNil: [ nil ] ifNotNil: [ DateAndTime fromString: string ] ] ]
1✔
130
]
1✔
131

132
{ #category : #'private - configure reader' }
NEW
133
GLPHModelImporter >> configureReaderForMergeRequestApproval: reader [
×
NEW
134
        "declare quil y a un array a mapper"
×
NEW
135

×
NEW
136
        reader for: #ArrayOfMergeRequest customDo: [ :customMappting |
×
NEW
137
                customMappting listOfElementSchema: GLPHEMergeRequest ].
×
NEW
138

×
NEW
139
        "declare la liste des properties"
×
NEW
140
        reader for: GLPHEMergeRequest do: [ :mapping |
×
NEW
141
                mapping mapInstVars:
×
NEW
142
                        #( blocking_discussions_resolved changes_count description
×
NEW
143
                           detailed_merge_status discussion_locked downvotes draft first_deployed_to_production_at
×
NEW
144
                           force_remove_source_branch has_conflicts id iid labels latest_build_finished_at
×
NEW
145
                           latest_build_started_at merge_commit_sha merge_status
×
NEW
146
                           merge_when_pipeline_succeeds merged_at milestone project_id
×
NEW
147
                           reference references_full references_relative
×
NEW
148
                           references_short sha should_remove_source_branch
×
NEW
149
                           source_branch source_project_id squash squash_commit_sha
×
NEW
150
                           squash_on_merge state subscribed target_branch target_project_id
×
NEW
151
                           task_completion_status_completed_count
×
NEW
152
                           task_completion_status_count time_stats_human_time_estimate
×
NEW
153
                           time_stats_human_total_time_spent
×
NEW
154
                           time_stats_time_estimate time_stats_total_time_spent
×
NEW
155
                           title updated_at upvotes user_notes_count web_url work_in_progress ).
×
NEW
156
                (mapping mapInstVar: #created_at) valueSchema: DateAndTime.
×
NEW
157
                (mapping mapInstVar: #updated_at) valueSchema: DateAndTime.
×
NEW
158
                (mapping mapInstVar: #merged_at) valueSchema: DateAndTime.
×
NEW
159
                (mapping mapInstVar: #closed_at) valueSchema: DateAndTime
×
NEW
160
                "                
×
NEW
161
                (mapping mapInstVar: #assignee) valueSchema: GLHUser.
×
NEW
162
                (mapping mapInstVar: #author) valueSchema: GLHUser.
×
NEW
163
                (mapping mapInstVar: #closed_by) valueSchema: GLHUser.
×
NEW
164
                (mapping mapInstVar: #mergeCommit) valueSchema: GLHCommit." ].
×
NEW
165

×
NEW
166
        "indique ce que doit faire le reader lorsqu'il parse une DateAndTime object"
×
NEW
167
        reader for: DateAndTime customDo: [ :mapping |
×
NEW
168
                mapping decoder: [ :string |
×
NEW
169
                        string ifNil: [ nil ] ifNotNil: [ DateAndTime fromString: string ] ] ]
×
NEW
170
]
×
171

172
{ #category : #import }
UNCOV
173
GLPHModelImporter >> importCommitsOfBranch: aGLHBranch [
×
UNCOV
174

×
UNCOV
175
        | commits |
×
UNCOV
176
        "        result := self glhApi
×
UNCOV
177
                          commitsOfProject: aGLHBranch repository project id
×
UNCOV
178
                          forRefName: aGLHBranch name."
×
UNCOV
179
        commits := self
×
UNCOV
180
                           importCommitsOfBranch: aGLHBranch
×
UNCOV
181
                           forRefName: aGLHBranch name
×
UNCOV
182
                           since: withCommitsSince.
×
UNCOV
183

×
UNCOV
184
        self chainsCommitsFrom: commits.
×
UNCOV
185

×
UNCOV
186
        commits do: [ :aCommit |
×
UNCOV
187
                aCommit repository: aGLHBranch repository.
×
UNCOV
188
                self completeImportedCommit: aCommit. 
×
UNCOV
189
                 ]
×
UNCOV
190
]
×
191

192
{ #category : #import }
193
GLPHModelImporter >> importCommitsOfMergeResquest: aGLPHEMergeRequest [
1✔
194

1✔
195
        | foundCommits |
1✔
196
        foundCommits := OrderedCollection new.
1✔
197

1✔
198
        ('Import commit sha of MR:  ' , aGLPHEMergeRequest iid printString)
1✔
199
                recordInfo.
1✔
200
        "the founds commits are added to the model during their respective import"
1✔
201
        aGLPHEMergeRequest mergeRequestCommit: ((self
1✔
202
                          importCommitOfProject: aGLPHEMergeRequest project
1✔
203
                          withId: aGLPHEMergeRequest sha) ifNotNil: [ :commit |
1✔
204
                         foundCommits add: commit ]).
1✔
205

1✔
206
        ('Import commit merge_commit_sha of MR:  '
1✔
207
         , aGLPHEMergeRequest iid printString) recordInfo.
1✔
208
        aGLPHEMergeRequest mergedCommit: ((self
1✔
209
                          importCommitOfProject: aGLPHEMergeRequest project
1✔
210
                          withId: aGLPHEMergeRequest merge_commit_sha) ifNotNil: [ :commit |
1✔
211
                         foundCommits add: commit ]).
1✔
212

1✔
213
        ('Import commit squash_commit_sha of MR:  '
1✔
214
         , aGLPHEMergeRequest iid printString) recordInfo.
1✔
215
        aGLPHEMergeRequest squashCommit: ((self
1✔
216
                          importCommitOfProject: aGLPHEMergeRequest project
1✔
217
                          withId: aGLPHEMergeRequest squash_commit_sha) ifNotNil: [ :commit |
1✔
218
                         foundCommits add: commit ]).
1✔
219

1✔
220

1✔
221
        self chainsCommitsFrom: foundCommits.
1✔
222
        ^ foundCommits
1✔
223
]
1✔
224

225
{ #category : #api }
226
GLPHModelImporter >> importDiffOfCommit: aCommit [
1✔
227

1✔
228
        super importDiffOfCommit: aCommit.
1✔
229
        
1✔
230
        "changes are added into the model during the import"
1✔
231
        aCommit diffs do: [ :diff | self importDiffRangesForDiff: diff ].
1✔
232

1✔
233
        ^ aCommit diffs
1✔
234
]
1✔
235

236
{ #category : #'as yet unclassified' }
237
GLPHModelImporter >> importDiffOfMergeRequest: aMergeRequest [
1✔
238

1✔
239
        | result diffsResult |
1✔
240
        aMergeRequest diffs ifNotEmpty: [
1✔
241
                'Diff of already importer: '
1✔
242
                , aMergeRequest iid printString recordInfo.
1✔
243
                ^ aMergeRequest diffs ].
1✔
244
        ('Import diff commits of MR ' , aMergeRequest iid printString)
1✔
245
                recordInfo.
1✔
246
        result := self glhApi
1✔
247
                          diffsMergeRequestOfProject: aMergeRequest project_id
1✔
248
                          withId: aMergeRequest iid.
1✔
249

1✔
250
        diffsResult := self parseDiffResult: result.
1✔
251

1✔
252

1✔
253
        aMergeRequest diffs
1✔
254
                addAll: diffsResult
1✔
255
                unless: self blockForDiffEquality.
1✔
256
        self glhModel
1✔
257
                addAll: aMergeRequest diffs
1✔
258
                unless: self blockForDiffEquality.
1✔
259

1✔
260
        aMergeRequest diffs do: [ :diff | self importDiffRangesForDiff: diff ].
1✔
261

1✔
262
        ^ aMergeRequest diffs
1✔
263
]
1✔
264

265
{ #category : #import }
266
GLPHModelImporter >> importDiffRangesForDiff: aGLHDiff [
1✔
267

1✔
268
        | diffRanges |
1✔
269
        aGLHDiff diffRanges ifNotEmpty: [
1✔
270
                ('Diffs already imported for ' , aGLHDiff printString) recordInfo.
1✔
271
                ^ aGLHDiff diffRanges ].
1✔
272

1✔
273
        ('Import changes of diff ' , aGLHDiff printString) recordInfo.
1✔
274
        "the import of 'diffRanges' entites is technically done inside the parseDiffString"
1✔
275

1✔
276
        diffRanges := self glhModel
1✔
277
                              addAll: (self parseDiffString: aGLHDiff)
1✔
278
                              unless: self blockForDiffRangeEquality.
1✔
279
        ^ aGLHDiff diffRanges
1✔
280
                  addAll: diffRanges
1✔
281
                  unless: self blockForDiffRangeEquality
1✔
282
]
1✔
283

284
{ #category : #import }
285
GLPHModelImporter >> importMergeRequests: aGLHProject [
1✔
286

1✔
287
        | results parsedResults |
1✔
288
        ('Import merge request of Project: ' , aGLHProject id printString)
1✔
289
                recordInfo.
1✔
290

1✔
291
        results := self glhApi mergeRequestOfProject: aGLHProject id.
1✔
292
        parsedResults := self parseMergeRequestResult: results.
1✔
293

1✔
294
        aGLHProject mergeRequests
1✔
295
                addAll: parsedResults
1✔
296
                unless: self blockOnIdEquality.
1✔
297

1✔
298
        self glhModel
1✔
299
                addAll: aGLHProject mergeRequests
1✔
300
                unless: self blockOnIdEquality.
1✔
301

1✔
302

1✔
303
        "gets it related commits"
1✔
304
        aGLHProject mergeRequests do: [ :mr |
1✔
305
                self importCommitsOfMergeResquest: mr ].
1✔
306

1✔
307

1✔
308
        self withCommitDiffs ifTrue: [
1✔
309
                aGLHProject mergeRequests do: [ :mr |
1✔
310
                        self importDiffOfMergeRequest: mr ] ]
1✔
311
]
1✔
312

313
{ #category : #import }
UNCOV
314
GLPHModelImporter >> importMergeRequests: aGLHProject since: fromDate until: toDate [
×
UNCOV
315

×
UNCOV
316
        | newlyFoundMR page foundMR |
×
UNCOV
317
        ('import MR of Project ' , aGLHProject name) recordInfo.
×
UNCOV
318

×
UNCOV
319
        page := 0.
×
UNCOV
320
        foundMR := OrderedCollection new.
×
UNCOV
321
        newlyFoundMR := { true }.
×
UNCOV
322
        [ newlyFoundMR isNotEmpty ] whileTrue: [
×
UNCOV
323
                | results |
×
UNCOV
324
                page := page + 1.
×
UNCOV
325
                ('import MR page ' , page printString) recordInfo.
×
UNCOV
326
                results := self glhApi
×
UNCOV
327
                                   mergeRequestsOfProject: aGLHProject id
×
UNCOV
328
                                   createdAfter:
×
UNCOV
329
                                   (fromDate ifNotNil: [ fromDate asDateAndTime asString ])
×
UNCOV
330
                                   createdBefore:
×
UNCOV
331
                                   (toDate ifNotNil: [ toDate asDateAndTime asString ])
×
UNCOV
332
                                   authorId: nil
×
UNCOV
333
                                   authorUsername: nil
×
UNCOV
334
                                   scope: 'all'
×
UNCOV
335
                                   orderBy: 'created_at'
×
UNCOV
336
                                   page: page.
×
UNCOV
337

×
UNCOV
338

×
UNCOV
339
                newlyFoundMR := aGLHProject mergeRequests
×
UNCOV
340
                                        addAll: (self parseMergeRequestResult: results)
×
UNCOV
341
                                        unless: self blockOnIdEquality.
×
UNCOV
342
                foundMR addAll: newlyFoundMR ].
×
UNCOV
343

×
UNCOV
344

×
UNCOV
345
        "gets it related commits"
×
UNCOV
346
        aGLHProject mergeRequests do: [ :mr |
×
UNCOV
347
                self importCommitsOfMergeResquest: mr ].
×
UNCOV
348

×
UNCOV
349
        self withCommitDiffs ifTrue: [
×
UNCOV
350
                aGLHProject mergeRequests do: [ :mr |
×
UNCOV
351
                        self importDiffOfMergeRequest: mr ] ].
×
UNCOV
352
        
×
UNCOV
353
        self glhModel addAll: foundMR unless: (self blockEqualityOn: #iid).
×
UNCOV
354

×
UNCOV
355
        ^ foundMR
×
UNCOV
356
]
×
357

358
{ #category : #import }
NEW
359
GLPHModelImporter >> importMergeResquestApprovals: aGLPHEMergeRequest [
×
NEW
360

×
NEW
361
        | results parsedResult |
×
NEW
362
        (String streamContents: [ :str |
×
NEW
363
                 str << 'Check approvals of '.
×
NEW
364
                 aGLPHEMergeRequest printOn: str ]) recordInfo.
×
NEW
365
        results := self glhApi
×
NEW
366
                           approvalsOfMergeQuest: aGLPHEMergeRequest iid
×
NEW
367
                           ofProject: aGLPHEMergeRequest project id.
×
NEW
368

×
NEW
369
        parsedResult := generalReader
×
NEW
370
                                on: results readStream;
×
NEW
371
                                next.
×
NEW
372
        aGLPHEMergeRequest approved: (parsedResult at: #approved).
×
NEW
373
        ^ aGLPHEMergeRequest
×
NEW
374
]
×
375

376
{ #category : #'as yet unclassified' }
377
GLPHModelImporter >> importProject: aProjectID [
1✔
378

1✔
379
        | result projectResult |
1✔
380
        ('Import project with id:  ' , aProjectID printString) recordInfo.
1✔
381

1✔
382
        result := self glhApi project: aProjectID.
1✔
383
        projectResult := self parseProjectResult: result.
1✔
384

1✔
385
        ^ self completeImportProject: projectResult
1✔
386
]
1✔
387

388
{ #category : #'private - api' }
389
GLPHModelImporter >> importRepository: aGLHRepository [
1✔
390

1✔
391
        super importRepository: aGLHRepository.
1✔
392

1✔
393
        withInitialCommits ifTrue: [
1✔
394
                aGLHRepository branches do: [ :branch |
1✔
395
                        self importCommitsOfBranch: branch ] ]
1✔
396
]
1✔
397

398
{ #category : #initialization }
399
GLPHModelImporter >> initReader [
1✔
400

1✔
401
        super initReader.
1✔
402
        self configureReaderForMergeRequest: generalReader
1✔
403
]
1✔
404

405
{ #category : #initialization }
406
GLPHModelImporter >> initialize [
1✔
407

1✔
408
        super initialize.
1✔
409
        withCommitDiffs := true
1✔
410
]
1✔
411

412
{ #category : #parsing }
413
GLPHModelImporter >> parseDiffString: aDiff [
1✔
414
        "parse diff string to create entities for each lines"
1✔
415

1✔
416
        | lines range index firstChangeRange |
1✔
417
        lines := aDiff diffString lines.
1✔
418
        index := 0.
1✔
419
        range := nil.
1✔
420

1✔
421
        lines ifEmpty: [ ^ aDiff diffRanges ].
1✔
422
        lines := self filterCommitChanges: lines.
1✔
423
        (lines first beginsWith: '@@') ifFalse: [ ^ aDiff diffRanges ].
1✔
424

1✔
425
        lines do: [ :line |
1✔
426
                | aChange |
1✔
427
                firstChangeRange := false.
1✔
428
                (line trim beginsWith: #'@@') ifTrue: [
1✔
429
                        range := GLPHEDiffRange newFrom: line.
1✔
430
                        firstChangeRange := true.
1✔
431
                        range := aDiff diffRanges add: range unless: [ :existing :new |
1✔
432
                                         existing originalLineRange = new originalLineRange and: [
1✔
433
                                                 existing newLineRange = new newLineRange ] ] ].
1✔
434

1✔
435
                self withCommitDiffs ifTrue: [
1✔
436
                        firstChangeRange ifFalse: [
1✔
437
                                aChange := GLPHEChange newFrom: line.
1✔
438
                                aChange relativeIndex: index.
1✔
439
                                aChange := range changes add: aChange unless: [ :existing :new |
1✔
440
                                                   existing sourceCode = new sourceCode and: [
1✔
441
                                                           existing index = new index ] ].
1✔
442
                                index := index + 1 ] ] ].
1✔
443

1✔
444
        "add changes to the diff range"
1✔
445
        aDiff diffRanges do: [ :diffRange |
1✔
446
                self glhModel addAll: diffRange changes unless: [ :existing :new |
1✔
447
                        existing diffRange mooseID = new diffRange mooseID and: [
1✔
448
                                existing sourceCode = new sourceCode and: [
1✔
449
                                        existing index = new index ] ] ] ].
1✔
450

1✔
451
        ^ aDiff diffRanges
1✔
452
]
1✔
453

454
{ #category : #parsing }
455
GLPHModelImporter >> parseMergeRequestResult: result [
1✔
456

1✔
457
        generalReader on: result readStream.
1✔
458
        ^ generalReader nextAs: #ArrayOfMergeRequest
1✔
459
]
1✔
460

461
{ #category : #parsing }
462
GLPHModelImporter >> parseProjectResult: aResult [ 
1✔
463
                | reader |
1✔
464
        reader := NeoJSONReader on: aResult readStream.
1✔
465
        reader for: GLHProject do: [ :mapping |
1✔
466
                mapping mapInstVars. ].
1✔
467
"        reader mapInstVarsFor: GLHProject."
1✔
468

1✔
469
        ^ reader nextAs: GLHProject
1✔
470
]
1✔
471

1✔
472
{ #category : #accessing }
1✔
473
GLPHModelImporter >> withCommitsSince: someDays [
1✔
474
        "substract the current date with a given number of days. Use to retrieve the commits submit in the last giving days"
1✔
475
        "(GLPHModelImporter new withCommitsSince: 1 week ) >>> (Date today - 1 week) asDateAndTime"
1✔
476
        "(GLPHModelImporter new withCommitsSince: 30 day ) >>> (Date today - 30 day) asDateAndTime"
1✔
477
        withCommitsSince := (Date today - someDays) asDateAndTime
1✔
478
]
1✔
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