From 6248d65a626bf8d99626f452f1aff8b0a7a5c003 Mon Sep 17 00:00:00 2001 From: HLAD Nicolas Date: Thu, 21 Aug 2025 15:40:43 +0200 Subject: [PATCH 01/52] finalize importer deprecation --- src/GitHubHealth-Model-Importer/GHApi.class.st | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/GitHubHealth-Model-Importer/GHApi.class.st b/src/GitHubHealth-Model-Importer/GHApi.class.st index 7e74616f..b2b13f8d 100644 --- a/src/GitHubHealth-Model-Importer/GHApi.class.st +++ b/src/GitHubHealth-Model-Importer/GHApi.class.st @@ -19,9 +19,17 @@ GHApi class >> isDeprecated [ { #category : #api } GHApi >> actionsRunOfRepo: aRepoName ofOrganization: anOrganizationName [ - ^ self client get: +" ^ self client get: self baseAPIUrl , '/repos/' , anOrganizationName , '/' , aRepoName - , '/actions/runs' + , '/actions/runs'" + + self + deprecated: 'Use self actions getLatestForRepo:ofOwner: instead of current one' + on: '21 august 2025' + in: + 'Pharo-12.0.0+SNAPSHOT.build.1571.sha.cf5fcd22e66957962c97dffc58b0393b7f368147 (64 Bit)'. + + ^ self actions getLatestForRepo: aRepoName ofOwner: anOrganizationName. ] { #category : #accessing } From 38b6421ebe261e4bb5a291ada17590a8866bdd81 Mon Sep 17 00:00:00 2001 From: HLAD Nicolas Date: Thu, 21 Aug 2025 15:57:44 +0200 Subject: [PATCH 02/52] starting migrating importer toward new reader configuration --- .../GithubModelImporter.class.st | 48 +++++++++++++++++-- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st index c1ea4528..bad82a1d 100644 --- a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st +++ b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st @@ -1,6 +1,9 @@ Class { #name : #GithubModelImporter, #superclass : #GitModelImporter, + #instVars : [ + 'generalReader' + ], #category : #'GitHubHealth-Model-Importer' } @@ -72,6 +75,25 @@ GithubModelImporter >> completeImportedProject: aGLHProject [ self chainsCommitsFrom: commits ] ] +{ #category : #'as yet unclassified' } +GithubModelImporter >> configureReaderForProject: reader [ + +" reader mapInstVarsFor: GLHProject. " + + reader for: GLHProject do: [ :mapping | + mapping mapInstVar: #name to: #name. + mapping mapInstVar: #description to: #description. + mapping mapInstVar: #id to: #id. + mapping mapInstVar: #archived to: #archived. + mapping mapInstVar: #web_url to: #html_url. + mapping mapInstVar: #topics to: #topics ]. + + reader + for: #ArrayOfProjects + customDo: [ :customMappting | + customMappting listOfElementSchema: GLHProject ]. +] + { #category : #private } GithubModelImporter >> convertApiFileAsFile: aAPIFile [ @@ -336,6 +358,13 @@ GithubModelImporter >> importUser: userID [ unless: [ :current :new | current id = new id ] ] +{ #category : #initialization } +GithubModelImporter >> initReader [ + + generalReader := NeoJSONReader new. + self configureReaderForProject: generalReader. +] + { #category : #initialization } GithubModelImporter >> initialize [ @@ -343,18 +372,22 @@ GithubModelImporter >> initialize [ self repoApi: GHApi new. self repoApi output: 'json'. self withCommitDiffs: false. - withFiles := false + withFiles := false. + + self initReader ] { #category : #parsing } GithubModelImporter >> parseArrayOfProject: arrayOfProjects [ | reader | - reader := NeoJSONReader on: arrayOfProjects readStream. +" reader := NeoJSONReader on: arrayOfProjects readStream. + reader for: #ArrayOfProjects customDo: [ :customMappting | customMappting listOfElementSchema: GLHProject ]. + reader for: GLHProject do: [ :mapping | mapping mapInstVar: #name to: #name. mapping mapInstVar: #description to: #description. @@ -363,6 +396,11 @@ GithubModelImporter >> parseArrayOfProject: arrayOfProjects [ mapping mapInstVar: #web_url to: #html_url. mapping mapInstVar: #topics to: #topics ]. ^ reader nextAs: #ArrayOfProjects + " + + reader := generalReader on: arrayOfProjects readStream. + + ^ reader nextAs: #ArrayOfProjects ] { #category : #parsing } @@ -532,7 +570,7 @@ GithubModelImporter >> parsePipelinesResult: pipelineOverview [ GithubModelImporter >> parseProjectResult: aResult [ | reader | - reader := NeoJSONReader on: aResult readStream. +" reader := NeoJSONReader on: aResult readStream. reader for: GLHProject do: [ :mapping | mapping mapInstVar: #name to: #name. mapping mapInstVar: #description to: #description. @@ -540,6 +578,10 @@ GithubModelImporter >> parseProjectResult: aResult [ mapping mapInstVar: #archived to: #archived. mapping mapInstVar: #web_url to: #html_url. mapping mapInstVar: #topics to: #topics ]. + ^ reader nextAs: GLHProject" + + reader := generalReader on: aResult readStream. + ^ reader nextAs: GLHProject ] From ff95a6d8836502ecc631ffbb2c4b9f9f16b006c2 Mon Sep 17 00:00:00 2001 From: HLAD Nicolas Date: Mon, 1 Sep 2025 13:53:19 +0200 Subject: [PATCH 03/52] add return for files in branches --- src/GitHubHealth-Model-Importer/GithubModelImporter.class.st | 3 ++- src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st index 51797bfa..e5e76b84 100644 --- a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st +++ b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st @@ -255,7 +255,8 @@ GithubModelImporter >> importFilesOfBranch: aBranch [ files select: [ :file | file isKindOf: GLHFileDirectory ] thenCollect: [ :file | - self importDirectoryFiles: file OfBranch: aBranch ] + self importDirectoryFiles: file OfBranch: aBranch ]. + ^ files ] { #category : #api } diff --git a/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st b/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st index e4953f63..0663eb7a 100644 --- a/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st +++ b/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st @@ -1003,7 +1003,9 @@ GitlabModelImporter >> importFilesOfBranch: aBranch [ files select: [ :file | file isKindOf: GLHFileDirectory ] thenCollect: [ :file | - self importDirectoryFiles: file OfBranch: aBranch ] + self importDirectoryFiles: file OfBranch: aBranch ]. + + ^files. ] { #category : #'import - groups' } From e6e6c5ace44c912d91afe93cf023a9c96e4cb7cd Mon Sep 17 00:00:00 2001 From: HLAD Nicolas Date: Thu, 18 Sep 2025 10:38:42 +0200 Subject: [PATCH 04/52] add git reference as Trait for commit tag and branch --- .../GLHMetamodelGenerator.class.st | 30 +++++++++++++++++-- .../GitlabModelImporter.class.st | 6 ++++ 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/src/GitLabHealth-Model-Generator/GLHMetamodelGenerator.class.st b/src/GitLabHealth-Model-Generator/GLHMetamodelGenerator.class.st index d4e52c12..0ff5fef1 100644 --- a/src/GitLabHealth-Model-Generator/GLHMetamodelGenerator.class.st +++ b/src/GitLabHealth-Model-Generator/GLHMetamodelGenerator.class.st @@ -26,7 +26,8 @@ Class { 'release', 'tag', 'issue', - 'milestone' + 'milestone', + 'tRef' ], #category : #'GitLabHealth-Model-Generator' } @@ -74,7 +75,7 @@ GLHMetamodelGenerator class >> submetamodels [ { #category : #branches } GLHMetamodelGenerator >> branchProperties [ - branch property: #name type: #String + ] { #category : #changes } @@ -213,6 +214,11 @@ GLHMetamodelGenerator >> defineHierarchy [ diff --|> #TNamedEntity. job --|> #TNamedEntity. note --|> #TNamedEntity. + + tRef --|> #TNamedEntity. + tRef <|-- commit . + tRef <|-- branch . + tRef <|-- tag . change --|> #TNamedEntity. change <|-- addition. @@ -246,6 +252,8 @@ GLHMetamodelGenerator >> defineProperties [ self releaseProperties. self issueProperties. self milestoneProperties. + + self tRefProperties. ] { #category : #definition } @@ -284,6 +292,15 @@ GLHMetamodelGenerator >> defineRelations [ self milestoneRelations. ] +{ #category : #definition } +GLHMetamodelGenerator >> defineTraits [ + super defineTraits. + + tRef := builder newTraitNamed: #TRef comment: 'I''m representing a Git reference, that is a reference point in a repository''s history'. + "generate the identity isXXX method (see https://modularmoose.org/developers/create-new-metamodel/#generating-test-method)" + tRef withTesting. +] + { #category : #diffs } GLHMetamodelGenerator >> diffProperties [ @@ -597,10 +614,17 @@ GLHMetamodelGenerator >> releaseRelations [ (release property: #project) *-<> (project property: #releases) ] +{ #category : #'as yet unclassified' } +GLHMetamodelGenerator >> tRefProperties [ + "define the properties of a ref instance" + + tag property: #sha type: #String. + tag property: #name type: #String. +] + { #category : #tags } GLHMetamodelGenerator >> tagProperties [ - tag property: #name type: #String. tag property: #message type: #String. tag property: #target type: #String. tag property: #protected type: #Boolean. diff --git a/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st b/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st index 0663eb7a..09937d94 100644 --- a/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st +++ b/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st @@ -981,6 +981,12 @@ GitlabModelImporter >> importDirectoryFiles: aDirectoryFile OfBranch: aBranch [ self importDirectoryFiles: file OfBranch: aBranch ] ] +{ #category : #'import - file' } +GitlabModelImporter >> importFileWithPath: aPath ofProject: aGLHProject inBranch: aBranch [ + self flag: 'imported file need need to be store inside the model'. + ^ self repoApi repositories getRawFile: aPath ofProject: aGLHProject id withParams: {#ref -> aBranch name} asDictionary . +] + { #category : #'import - repositories' } GitlabModelImporter >> importFilesOfBranch: aBranch [ From 1835d48396af27ffe0ec56bf242b17e799703a39 Mon Sep 17 00:00:00 2001 From: HLAD Nicolas Date: Thu, 18 Sep 2025 10:44:12 +0200 Subject: [PATCH 05/52] generate new metamodel with ref --- src/GitLabHealth-Model/GLHBranch.class.st | 19 ++--------- src/GitLabHealth-Model/GLHCommit.class.st | 6 ++-- src/GitLabHealth-Model/GLHEntity.class.st | 7 ++++ src/GitLabHealth-Model/GLHGroupGroup.class.st | 7 ++++ src/GitLabHealth-Model/GLHIssue.class.st | 2 +- .../GLHTEntityCreator.trait.st | 14 ++++++++ src/GitLabHealth-Model/GLHTRef.trait.st | 33 +++++++++++++++++++ src/GitLabHealth-Model/GLHTag.class.st | 21 +++++++++++- src/GitLabHealth-Model/GLHUser.class.st | 2 +- 9 files changed, 89 insertions(+), 22 deletions(-) create mode 100644 src/GitLabHealth-Model/GLHTRef.trait.st diff --git a/src/GitLabHealth-Model/GLHBranch.class.st b/src/GitLabHealth-Model/GLHBranch.class.st index 0b217803..98f108b8 100644 --- a/src/GitLabHealth-Model/GLHBranch.class.st +++ b/src/GitLabHealth-Model/GLHBranch.class.st @@ -25,14 +25,15 @@ A git branch | Name | Type | Default value | Comment | |---| -| `name` | `String` | nil | | +| `name` | `String` | nil | Basic name of the entity, not full reference.| " Class { #name : #GLHBranch, #superclass : #GLHEntity, + #traits : 'GLHTRef', + #classTraits : 'GLHTRef classTrait', #instVars : [ - '#name => FMProperty', '#repository => FMOne type: #GLHRepository opposite: #branches', '#files => FMMany type: #GLHFile opposite: #branch', '#commits => FMMany type: #GLHCommit opposite: #branch' @@ -100,20 +101,6 @@ GLHBranch >> filesGroup [ ^ MooseSpecializedGroup withAll: self files asSet ] -{ #category : #accessing } -GLHBranch >> name [ - - - - ^ name -] - -{ #category : #accessing } -GLHBranch >> name: anObject [ - - name := anObject -] - { #category : #accessing } GLHBranch >> repository [ "Relation named: #repository type: #GLHRepository opposite: #branches" diff --git a/src/GitLabHealth-Model/GLHCommit.class.st b/src/GitLabHealth-Model/GLHCommit.class.st index 401d7f4b..aa2e6d9c 100644 --- a/src/GitLabHealth-Model/GLHCommit.class.st +++ b/src/GitLabHealth-Model/GLHCommit.class.st @@ -21,8 +21,8 @@ a commit attached to a repository |---| | `branch` | `GLHCommit` | `commits` | `GLHBranch` | | | `childCommits` | `GLHCommit` | `parentCommits` | `GLHCommit` | | -| `commitedMergeRequest` | `GLHCommit` | `mergeRequestCommit` | `GLHMergeRequest` | | | `commitedMergeRequest` | `GLHCommit` | `mergedCommit` | `GLHMergeRequest` | | +| `commitedMergeRequest` | `GLHCommit` | `mergeRequestCommit` | `GLHMergeRequest` | | | `parentCommits` | `GLHCommit` | `childCommits` | `GLHCommit` | | | `squashedMergeRequest` | `GLHCommit` | `squashCommit` | `GLHMergeRequest` | | | `tag` | `GLHCommit` | `commit` | `GLHTag` | | @@ -54,8 +54,8 @@ a commit attached to a repository Class { #name : #GLHCommit, #superclass : #GLHEntity, - #traits : 'FamixTNamedEntity', - #classTraits : 'FamixTNamedEntity classTrait', + #traits : 'FamixTNamedEntity + GLHTRef', + #classTraits : 'FamixTNamedEntity classTrait + GLHTRef classTrait', #instVars : [ '#parent_ids => FMProperty defaultValue: \'OrderedCollection new\'', '#id => FMProperty', diff --git a/src/GitLabHealth-Model/GLHEntity.class.st b/src/GitLabHealth-Model/GLHEntity.class.st index f5ed0647..61e3a593 100644 --- a/src/GitLabHealth-Model/GLHEntity.class.st +++ b/src/GitLabHealth-Model/GLHEntity.class.st @@ -43,3 +43,10 @@ GLHEntity >> isDeletion [ ^ false ] + +{ #category : #testing } +GLHEntity >> isRef [ + + + ^ false +] diff --git a/src/GitLabHealth-Model/GLHGroupGroup.class.st b/src/GitLabHealth-Model/GLHGroupGroup.class.st index e518f32b..6959d043 100644 --- a/src/GitLabHealth-Model/GLHGroupGroup.class.st +++ b/src/GitLabHealth-Model/GLHGroupGroup.class.st @@ -40,3 +40,10 @@ GLHGroupGroup >> isQueryable [ ^ false ] + +{ #category : #testing } +GLHGroupGroup >> isRef [ + + + ^ false +] diff --git a/src/GitLabHealth-Model/GLHIssue.class.st b/src/GitLabHealth-Model/GLHIssue.class.st index 8935e3aa..20a52a29 100644 --- a/src/GitLabHealth-Model/GLHIssue.class.st +++ b/src/GitLabHealth-Model/GLHIssue.class.st @@ -27,8 +27,8 @@ an Issues help collaboration within a team to plan, track, and deliver work | `description` | `String` | nil | | | `due_date` | `Object` | nil | | | `id` | `Number` | nil | | -| `name` | `String` | nil | Basic name of the entity, not full reference.| | `name` | `String` | nil | | +| `name` | `String` | nil | Basic name of the entity, not full reference.| | `state` | `String` | nil | | | `updated_at` | `Object` | nil | | diff --git a/src/GitLabHealth-Model/GLHTEntityCreator.trait.st b/src/GitLabHealth-Model/GLHTEntityCreator.trait.st index 5394ff21..f50e3745 100644 --- a/src/GitLabHealth-Model/GLHTEntityCreator.trait.st +++ b/src/GitLabHealth-Model/GLHTEntityCreator.trait.st @@ -32,6 +32,13 @@ GLHTEntityCreator >> newBranch [ ^ self add: GLHBranch new ] +{ #category : #'entity creation' } +GLHTEntityCreator >> newBranchNamed: aName [ + + + ^ self add: (GLHBranch named: aName) +] + { #category : #'entity creation' } GLHTEntityCreator >> newChange [ @@ -242,6 +249,13 @@ GLHTEntityCreator >> newTag [ ^ self add: GLHTag new ] +{ #category : #'entity creation' } +GLHTEntityCreator >> newTagNamed: aName [ + + + ^ self add: (GLHTag named: aName) +] + { #category : #'entity creation' } GLHTEntityCreator >> newUser [ diff --git a/src/GitLabHealth-Model/GLHTRef.trait.st b/src/GitLabHealth-Model/GLHTRef.trait.st new file mode 100644 index 00000000..b5e9154c --- /dev/null +++ b/src/GitLabHealth-Model/GLHTRef.trait.st @@ -0,0 +1,33 @@ +" +I'm representing a Git reference, that is a reference point in a repository's history + +## Properties +====================== + +| Name | Type | Default value | Comment | +|---| +| `name` | `String` | nil | Basic name of the entity, not full reference.| + +" +Trait { + #name : #GLHTRef, + #traits : 'FamixTNamedEntity', + #classTraits : 'FamixTNamedEntity classTrait', + #category : #'GitLabHealth-Model-Traits' +} + +{ #category : #meta } +GLHTRef classSide >> annotation [ + + + + + ^ self +] + +{ #category : #testing } +GLHTRef >> isRef [ + + + ^ true +] diff --git a/src/GitLabHealth-Model/GLHTag.class.st b/src/GitLabHealth-Model/GLHTag.class.st index 7f966331..7c331c0a 100644 --- a/src/GitLabHealth-Model/GLHTag.class.st +++ b/src/GitLabHealth-Model/GLHTag.class.st @@ -24,19 +24,24 @@ a Tag is a reference to a specific point in the repository's history | `created_at` | `Object` | nil | | | `message` | `String` | nil | | | `name` | `String` | nil | | +| `name` | `String` | nil | Basic name of the entity, not full reference.| | `protected` | `Boolean` | nil | | +| `sha` | `String` | nil | | | `target` | `String` | nil | | " Class { #name : #GLHTag, #superclass : #GLHEntity, + #traits : 'GLHTRef', + #classTraits : 'GLHTRef classTrait', #instVars : [ - '#name => FMProperty', '#message => FMProperty', '#target => FMProperty', '#protected => FMProperty', '#created_at => FMProperty', + '#sha => FMProperty', + '#name => FMProperty', '#commit => FMOne type: #GLHCommit opposite: #tag', '#release => FMOne type: #GLHRelease opposite: #tag', '#repository => FMOne type: #GLHRepository opposite: #tags' @@ -162,6 +167,20 @@ GLHTag >> repositoryGroup [ ^ MooseSpecializedGroup with: self repository ] +{ #category : #accessing } +GLHTag >> sha [ + + + + ^ sha +] + +{ #category : #accessing } +GLHTag >> sha: anObject [ + + sha := anObject +] + { #category : #accessing } GLHTag >> target [ diff --git a/src/GitLabHealth-Model/GLHUser.class.st b/src/GitLabHealth-Model/GLHUser.class.st index 2859bbf0..889e8660 100644 --- a/src/GitLabHealth-Model/GLHUser.class.st +++ b/src/GitLabHealth-Model/GLHUser.class.st @@ -51,8 +51,8 @@ A GitLab User | `job_title` | `String` | nil | | | `linkedin` | `String` | nil | | | `location` | `String` | nil | | -| `name` | `String` | nil | Basic name of the entity, not full reference.| | `name` | `String` | nil | | +| `name` | `String` | nil | Basic name of the entity, not full reference.| | `organization` | `String` | nil | | | `pronouns` | `String` | nil | | | `public_email` | `String` | nil | | From e5fac281ba96ab2537fff292372bd4bb33dac42c Mon Sep 17 00:00:00 2001 From: HLAD Nicolas Date: Fri, 19 Sep 2025 10:25:36 +0200 Subject: [PATCH 06/52] add constructor in class since of GitModelImporter for quality of life setup --- .../GithubModelImporter.class.st | 2 +- .../GitModelImporter.class.st | 54 ++++++++++++++++++- 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st index e5e76b84..12f5d35e 100644 --- a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st +++ b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st @@ -370,7 +370,7 @@ GithubModelImporter >> initReader [ GithubModelImporter >> initialize [ super initialize. - self repoApi: GHApi new. + self repoApi: GithubApi new. self repoApi output: 'json'. self withCommitDiffs: false. withFiles := false. diff --git a/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st b/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st index 7d913d3b..aa89f125 100644 --- a/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st +++ b/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st @@ -21,6 +21,58 @@ Class { #category : #'GitProjectHealth-Model-Importer' } +{ #category : #github } +GitModelImporter class >> forGithubWithToken: anApiToken [ + ^ self forGithubWithToken: anApiToken andModel: GLHModel new +] + +{ #category : #github } +GitModelImporter class >> forGithubWithToken: anApiToken andModel: aGitModel [ + |githubImport| + githubImport := GithubModelImporter new + glhModel: aGitModel; + privateToken: anApiToken; + withCommitsSince: (Date today - 10 day) asDateAndTime ; + yourself. + ^ githubImport +] + +{ #category : #gitlab } +GitModelImporter class >> forGitlabHostOn: anHostURL withToken: anApiToken [ + ^ self forGitlabHostOn: anHostURL withToken: anApiToken andModel: GLHModel new. +] + +{ #category : #gitlab } +GitModelImporter class >> forGitlabHostOn: anHostURL withToken: anApiToken andModel: aGitModel [ + "use it when accessing onpremise or custom gitlab platform" + | glphApi gitlabImporter | + + glphApi := GitlabApi new + privateToken: anApiToken; + hostUrl: anHostURL; + output: 'json'; + yourself. + + gitlabImporter := GitlabModelImporter new + repoApi: glphApi; + glhModel: aGitModel; + withFiles: false; + withCommitsSince: 3 day; + withCommitDiffs: false. + + ^ gitlabImporter +] + +{ #category : #gitlab } +GitModelImporter class >> forGitlabWithToken: anApiToken [ + ^ self forGitlabHostOn: 'https://gitlab.com/api/v4' withToken: anApiToken andModel: GLHModel new. +] + +{ #category : #gitlab } +GitModelImporter class >> forGitlabWithToken: anApiToken andModel: aGitModel [ + ^ self forGitlabHostOn: 'https://gitlab.com/api/v4' withToken: anApiToken andModel: aGitModel +] + { #category : #'accessing - global variables' } GitModelImporter class >> importers [ ^ currentImporter @@ -216,7 +268,7 @@ GitModelImporter >> initialize [ super initialize. self withCommitsSince: (Date today - 1 week) asDateAndTime. - userCatalogue := GLHUserCatalogueV2 new + userCatalogue := GLHUserCatalogueV2 new anImporter: self; yourself. ] From 146c4c783bb0d8cfdf08b3a419897820682aedf8 Mon Sep 17 00:00:00 2001 From: HLAD Nicolas Date: Fri, 19 Sep 2025 11:27:11 +0200 Subject: [PATCH 07/52] add bitbucket constructor class side --- .../GitModelImporter.class.st | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st b/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st index aa89f125..4cd71909 100644 --- a/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st +++ b/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st @@ -21,6 +21,29 @@ Class { #category : #'GitProjectHealth-Model-Importer' } +{ #category : #bitbucket } +GitModelImporter class >> forBitbucketHostOn: anHostURL withToken: anApiToken [ + + ^ self forBitbucketHostOn: anHostURL withToken: anApiToken andModel: GLHModel new. +] + +{ #category : #bitbucket } +GitModelImporter class >> forBitbucketHostOn: anHostURL withToken: anApiToken andModel: aGitModel [ + + | bitbucketApi bitBucketImporter | + bitbucketApi := BitbucketApi new + host: anHostURL; + bearerToken: anApiToken. + + bitBucketImporter := BitBucketModelImporter new + repoApi: bitbucketApi; + glhModel: aGitModel; + withFiles: false; + withCommitsSince: 3 day; + withCommitDiffs: false. + ^bitBucketImporter +] + { #category : #github } GitModelImporter class >> forGithubWithToken: anApiToken [ ^ self forGithubWithToken: anApiToken andModel: GLHModel new From b59e3bc46a9e28d00ee3abc0f1e6b3d6b4b4ee60 Mon Sep 17 00:00:00 2001 From: HLAD Nicolas Date: Fri, 19 Sep 2025 11:40:49 +0200 Subject: [PATCH 08/52] stylish --- .../GitModelImporter.class.st | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st b/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st index 4cd71909..496e1b2f 100644 --- a/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st +++ b/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st @@ -51,13 +51,14 @@ GitModelImporter class >> forGithubWithToken: anApiToken [ { #category : #github } GitModelImporter class >> forGithubWithToken: anApiToken andModel: aGitModel [ - |githubImport| + + | githubImport | githubImport := GithubModelImporter new - glhModel: aGitModel; - privateToken: anApiToken; - withCommitsSince: (Date today - 10 day) asDateAndTime ; - yourself. - ^ githubImport + glhModel: aGitModel; + privateToken: anApiToken; + withCommitsSince: 3 day; + yourself. + ^ githubImport ] { #category : #gitlab } @@ -82,7 +83,7 @@ GitModelImporter class >> forGitlabHostOn: anHostURL withToken: anApiToken andMo withFiles: false; withCommitsSince: 3 day; withCommitDiffs: false. - + ^ gitlabImporter ] From 78c8747d5eae3f947c199eb0911923ad3572f9c9 Mon Sep 17 00:00:00 2001 From: HLAD Nicolas Date: Fri, 19 Sep 2025 11:51:30 +0200 Subject: [PATCH 09/52] add protocols --- .../GitModelImporter.class.st | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st b/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st index 496e1b2f..0865d5cd 100644 --- a/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st +++ b/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st @@ -119,13 +119,13 @@ GitModelImporter >> beWithoutFiles [ withFiles := false ] -{ #category : #'as yet unclassified' } +{ #category : #equality } GitModelImporter >> blockEqualityOn: aSymbol [ ^ [ :existing :new | (existing perform: aSymbol) = (new perform: aSymbol) ] ] -{ #category : #'as yet unclassified' } +{ #category : #equality } GitModelImporter >> blockEqualityOn: aSymbol andOn: aSecondSymbol [ ^ (self blockEqualityOn: aSymbol) and: [ self blockEqualityOn: aSecondSymbol ] ] @@ -144,7 +144,7 @@ GitModelImporter >> blockForDiffEquality [ existing diffString = new diffString ] ] ] -{ #category : #'as yet unclassified' } +{ #category : #equality } GitModelImporter >> blockForDiffRangeEquality [ ^ [ :existing :new | @@ -204,7 +204,7 @@ GitModelImporter >> completeImportedCommit: aGLHCommit [ ^ aGLHCommit ] -{ #category : #'as yet unclassified' } +{ #category : #utils } GitModelImporter >> filterCommitChanges: aCollection [ ^ aCollection reject: [ :line | @@ -297,12 +297,12 @@ GitModelImporter >> initialize [ yourself. ] -{ #category : #'as yet unclassified' } +{ #category : #import } GitModelImporter >> makeGlobal [ ^ self makeGlobal: DateAndTime now printString. ] -{ #category : #'as yet unclassified' } +{ #category : #import } GitModelImporter >> makeGlobal: aLabel [ currentImporter := GithubModelImporter importers ifNil: [ OrderedDictionary new ]. From d8726f3e7c9e9fd64125f21a24d68959570d56a5 Mon Sep 17 00:00:00 2001 From: HLAD Nicolas Date: Fri, 19 Sep 2025 14:05:05 +0200 Subject: [PATCH 10/52] change protocol --- src/GitHubHealth-Model-Importer/GithubModelImporter.class.st | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st index 12f5d35e..26e2d53b 100644 --- a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st +++ b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st @@ -31,7 +31,7 @@ GithubModelImporter >> api: anObject [ repoApi := anObject ] -{ #category : #commit } +{ #category : #'import - commits' } GithubModelImporter >> completeImportedCommit: aGLHCommit [ | result | From 678264de4a04005deb5b7bed9fc8085811bf1d2d Mon Sep 17 00:00:00 2001 From: HLAD Nicolas Date: Fri, 19 Sep 2025 14:44:51 +0200 Subject: [PATCH 11/52] moving methods to top class and fixing protocol names --- .../BitBucketModelImporter.class.st | 10 +-- .../GithubModelImporter.class.st | 2 +- .../GitlabModelImporter.class.st | 2 +- .../GitModelImporter.class.st | 61 ++++++++++++++++++- 4 files changed, 66 insertions(+), 9 deletions(-) diff --git a/src/BitBucketHealth-Model-Importer/BitBucketModelImporter.class.st b/src/BitBucketHealth-Model-Importer/BitBucketModelImporter.class.st index 63566300..226ec0e3 100644 --- a/src/BitBucketHealth-Model-Importer/BitBucketModelImporter.class.st +++ b/src/BitBucketHealth-Model-Importer/BitBucketModelImporter.class.st @@ -31,7 +31,7 @@ BitBucketModelImporter >> bitBucketApi: anObject [ repoApi := anObject ] -{ #category : #commit } +{ #category : #'import - commits' } BitBucketModelImporter >> completeImportedCommit: aCommit [ ('completing commit: ' , aCommit short_id printString) recordInfo. @@ -118,7 +118,7 @@ BitBucketModelImporter >> convertBitBucketDiffToGitDiff: response [ ^ result ] -{ #category : #'as yet unclassified' } +{ #category : #'import - notes' } BitBucketModelImporter >> extractNoteFromComment: aDictionary [ ^ GLHNote new @@ -186,7 +186,7 @@ BitBucketModelImporter >> importAndLoadLatestsCommitsOfProject: aGLHProject [ ^ commits ] -{ #category : #'import - repositories' } +{ #category : #'import - branches' } BitBucketModelImporter >> importBranchesOf: aGLHProject [ | branches glhBranches | @@ -377,7 +377,7 @@ BitBucketModelImporter >> importMergeRequestCommits: mergeRequest [ ^ commits ] -{ #category : #'import - merge request' } +{ #category : #'import - merge-requests' } BitBucketModelImporter >> importMergeRequestMergeCommits: aGLHMergeRequest [ aGLHMergeRequest mergedCommit ifNotNil: [ @@ -406,7 +406,7 @@ BitBucketModelImporter >> importMergeRequestMergeCommits: aGLHMergeRequest [ ^ { found } ] ] -{ #category : #'import - merge request' } +{ #category : #'import - merge-requests' } BitBucketModelImporter >> importMergeRequestStats: aMergeRequest [ | commitDiffs contribution | diff --git a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st index 26e2d53b..61b2349b 100644 --- a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st +++ b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st @@ -75,7 +75,7 @@ GithubModelImporter >> completeImportedProject: aGLHProject [ self chainsCommitsFrom: commits ] ] -{ #category : #'as yet unclassified' } +{ #category : #'private - configure reader' } GithubModelImporter >> configureReaderForProject: reader [ " reader mapInstVarsFor: GLHProject. " diff --git a/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st b/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st index 09937d94..3e171cc8 100644 --- a/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st +++ b/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st @@ -1491,7 +1491,7 @@ GitlabModelImporter >> importRepository: aGLHRepository [ self importCommitsOfBranch: branch ] ] ] -{ #category : #'as yet unclassified' } +{ #category : #'import - commits' } GitlabModelImporter >> importSZZFromCommit: aCommit [ | result diffRanges diffs szzCommits| diff --git a/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st b/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st index 0865d5cd..841be8d8 100644 --- a/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st +++ b/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st @@ -166,7 +166,7 @@ GitModelImporter >> blockOnNameEquality [ ^ self blockEqualityOn: #name ] -{ #category : #commit } +{ #category : #'import - commits' } GitModelImporter >> chainsCommitsFrom: commitsCollection [ | dic | @@ -188,7 +188,7 @@ GitModelImporter >> chainsCommitsFrom: commitsCollection [ ^ commitsCollection ] -{ #category : #commit } +{ #category : #'import - commits' } GitModelImporter >> completeImportedCommit: aGLHCommit [ @@ -204,6 +204,10 @@ GitModelImporter >> completeImportedCommit: aGLHCommit [ ^ aGLHCommit ] +{ #category : #'import - projects' } +GitModelImporter >> completeImportedProject: aGLHProject [ +] + { #category : #utils } GitModelImporter >> filterCommitChanges: aCollection [ @@ -227,12 +231,41 @@ GitModelImporter >> glhModel: anObject [ glhModel := anObject ] +{ #category : #'import - commits' } +GitModelImporter >> importAndLoadLatestsCommitsOfProject: aGLHProject [ + + +] + { #category : #'import - repositories' } GitModelImporter >> importBranchesOf: aGLHProject [ ^ self subclassResponsibility ] +{ #category : #'import - commits' } +GitModelImporter >> importCommit: aCommitID ofProject: aGLHProject [ + +] + +{ #category : #'import - commits' } +GitModelImporter >> importCommitsOfProject: aGLHProject since: since until: until [ + +] + +{ #category : #'import - projects' } +GitModelImporter >> importContributedProjectsOfUser: aGLHUser [ +] + +{ #category : #'import - commits' } +GitModelImporter >> importCreatorOfCommit: aGLHCommit [ + +] + +{ #category : #'import - commits' } +GitModelImporter >> importDiffOfCommit: aCommit [ +] + { #category : #import } GitModelImporter >> importDiffRangesForDiff: aGLHDiff [ @@ -265,6 +298,22 @@ GitModelImporter >> importLatestPipelinesOfProject: aGLHProject [ aGLHProject pipelines add: pipeline unless: self blockOnIdEquality] ] +{ #category : #'import - merge request' } +GitModelImporter >> importMergeRequestCommits: mergeRequest [ +] + +{ #category : #'import - merge request' } +GitModelImporter >> importMergeRequestMergeCommits: aGLHMergeRequest [ +] + +{ #category : #'import - merge-requests' } +GitModelImporter >> importMergeResquestAuthor: mergeRequest [ +] + +{ #category : #'import - merge-requests' } +GitModelImporter >> importMergeResquestMerger: mergeRequest [ +] + { #category : #'import - notes' } GitModelImporter >> importNotesfromMergeRequest: mergeRequest [ @@ -280,6 +329,10 @@ GitModelImporter >> importProject: id [ ^ self subclassResponsibility ] +{ #category : #api } +GitModelImporter >> importProject: aProjectID ofGroup: aGroup [ +] + { #category : #'import - projects' } GitModelImporter >> importProjects: aCollectionOfProjectID [ @@ -287,6 +340,10 @@ GitModelImporter >> importProjects: aCollectionOfProjectID [ ^ aCollectionOfProjectID collect: [ :id | self importProject: id ] ] +{ #category : #'import - users' } +GitModelImporter >> importUserByUsername: username [ +] + { #category : #initialization } GitModelImporter >> initialize [ From 7295c43b0699ca2ba58a7f3f8ccb2d5e067f6801 Mon Sep 17 00:00:00 2001 From: HLAD Nicolas Date: Fri, 19 Sep 2025 16:50:37 +0200 Subject: [PATCH 12/52] refactoring protocol; moving up method declaration for importers and deprecating old methods; minoir renaming --- .../BitBucketModelImporterTest.class.st | 8 +- .../BitBucketModelImporter.class.st | 4 +- .../GithubModelImporter.class.st | 22 +-- .../GLPHImporterMock.class.st | 4 +- .../GitAnalyzerTest.class.st | 2 +- .../CreatedACRPipelineByProject.class.st | 2 +- ...dNoteInMergedOrClosedMergeRequest.class.st | 2 +- .../CreatedNotesByACRByProjectMetric.class.st | 2 +- .../ProjectMetric.class.st | 2 +- .../UserMetric.class.st | 2 +- .../GitlabModelImporter.class.st | 155 +++++++++--------- .../GitModelImporter.class.st | 125 ++++++++++++-- 12 files changed, 213 insertions(+), 117 deletions(-) diff --git a/src/BitBucketHealth-Model-Importer-Tests/BitBucketModelImporterTest.class.st b/src/BitBucketHealth-Model-Importer-Tests/BitBucketModelImporterTest.class.st index 644714be..7c206c44 100644 --- a/src/BitBucketHealth-Model-Importer-Tests/BitBucketModelImporterTest.class.st +++ b/src/BitBucketHealth-Model-Importer-Tests/BitBucketModelImporterTest.class.st @@ -672,7 +672,7 @@ BitBucketModelImporterTest >> testImportMergeRequestsSinceUntil [ "When" mergeRequests := bitBucketImporter - importMergeRequests: project + importMergeRequestsOfProject: project since: '09-23-2024' until: '09-25-2024'. @@ -712,7 +712,7 @@ BitBucketModelImporterTest >> testImportMergeRequestsSinceUntilAttachedToGoodPro "When" mergeRequests := bitBucketImporter - importMergeRequests: project + importMergeRequestsOfProject: project since: '09-23-2024' until: '09-25-2024'. @@ -749,7 +749,7 @@ BitBucketModelImporterTest >> testImportMergeRequestsSinceUntilClosedMR [ "When" mergeRequests := bitBucketImporter - importMergeRequests: project + importMergeRequestsOfProject: project since: '09-23-2024' until: '09-25-2024'. @@ -790,7 +790,7 @@ BitBucketModelImporterTest >> testImportMergeRequestsSinceUntilDeclinedMR [ "When" mergeRequests := bitBucketImporter - importMergeRequests: project + importMergeRequestsOfProject: project since: '09-23-2024' until: '09-25-2024'. diff --git a/src/BitBucketHealth-Model-Importer/BitBucketModelImporter.class.st b/src/BitBucketHealth-Model-Importer/BitBucketModelImporter.class.st index 226ec0e3..fce27c07 100644 --- a/src/BitBucketHealth-Model-Importer/BitBucketModelImporter.class.st +++ b/src/BitBucketHealth-Model-Importer/BitBucketModelImporter.class.st @@ -432,7 +432,7 @@ BitBucketModelImporter >> importMergeRequestStats: aMergeRequest [ ] { #category : #'import - merge-requests' } -BitBucketModelImporter >> importMergeRequests: aGLHProject since: fromDate until: toDate [ +BitBucketModelImporter >> importMergeRequestsOfProject: aGLHProject since: fromDate until: toDate [ | pullRequests params | params := { @@ -484,7 +484,7 @@ BitBucketModelImporter >> importMergeResquestMerger: mergeRequest [ ] { #category : #'import - notes' } -BitBucketModelImporter >> importNotesfromMergeRequest: mergeRequest [ +BitBucketModelImporter >> importNotesOfMergeRequest: mergeRequest [ | results notes | results := self repoApi pullRequests diff --git a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st index 61b2349b..cc5e5559 100644 --- a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st +++ b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st @@ -64,10 +64,10 @@ GithubModelImporter >> completeImportedCommit: aGLHCommit [ ^ aGLHCommit ] -{ #category : #api } +{ #category : #'import - projects' } GithubModelImporter >> completeImportedProject: aGLHProject [ - self importPipelinesOf: aGLHProject. + self importPipelinesOfProject: aGLHProject. self importBranchesOf: aGLHProject. self withCommitsSince ifNotNil: [ :withCommitSince | "If not nil, it means we have to import commit" | commits | @@ -134,7 +134,7 @@ GithubModelImporter >> importBranchesOf: project [ self withFiles ifTrue: [ self importFilesOfBranch: branch ] ] ] -{ #category : #api } +{ #category : #'import - commits' } GithubModelImporter >> importCommitsOfProject: aGLHProject [ | itemByPage foundCommits tmp pageNumber | @@ -194,7 +194,7 @@ GithubModelImporter >> importCreatorOfCommit: aGLHCommit [ ^ creator ] -{ #category : #api } +{ #category : #'import - commits' } GithubModelImporter >> importDiffOfCommit: aGLHCommit [ | result diffsResult | @@ -259,7 +259,7 @@ GithubModelImporter >> importFilesOfBranch: aBranch [ ^ files ] -{ #category : #api } +{ #category : #'import - groups' } GithubModelImporter >> importGroup: aGroupName [ | result groupResult | @@ -271,7 +271,7 @@ GithubModelImporter >> importGroup: aGroupName [ ] { #category : #'import - merge request' } -GithubModelImporter >> importMergeRequests: aProject [ +GithubModelImporter >> importMergeRequestsOfProject: aProject [ |response mergeRequests| response := self repoApi mergeRequestsOfRepo: aProject group name @@ -283,8 +283,8 @@ GithubModelImporter >> importMergeRequests: aProject [ ] -{ #category : #api } -GithubModelImporter >> importPipelinesOf: project [ +{ #category : #'import - pipelines' } +GithubModelImporter >> importPipelinesOfProject: project [ "add the pipeline (actions runs) in the project" @@ -297,7 +297,7 @@ GithubModelImporter >> importPipelinesOf: project [ project addPipeline: pipeline ] ] -{ #category : #api } +{ #category : #'import - projects' } GithubModelImporter >> importProject: aProjectName ofGroup: aGroupName [ | result projectResult group | @@ -310,7 +310,7 @@ GithubModelImporter >> importProject: aProjectName ofGroup: aGroupName [ ^ projectResult ] -{ #category : #api } +{ #category : #'import - groups' } GithubModelImporter >> importRepositoriesOfGroup: groupResult [ | reposResult itemByPage pageNumber reposFound tmp | @@ -344,7 +344,7 @@ GithubModelImporter >> importRepositoriesOfGroup: groupResult [ ^ groupResult ] -{ #category : #api } +{ #category : #'import - users' } GithubModelImporter >> importUser: userID [ | result userResult | diff --git a/src/GitLabHealth-Model-Analysis-Tests/GLPHImporterMock.class.st b/src/GitLabHealth-Model-Analysis-Tests/GLPHImporterMock.class.st index a3961e0e..db667ab3 100644 --- a/src/GitLabHealth-Model-Analysis-Tests/GLPHImporterMock.class.st +++ b/src/GitLabHealth-Model-Analysis-Tests/GLPHImporterMock.class.st @@ -99,7 +99,7 @@ GLPHImporterMock >> importMergeRequestMergeCommits: aGLHMergeRequest [ ] { #category : #'import - merge request' } -GLPHImporterMock >> importMergeRequests: project since: since until: until [ +GLPHImporterMock >> importMergeRequestsOfProject: project since: since until: until [ self flag: 'Adds MR regardless of their creation date !'. glhModel addAll: mergeRequests . @@ -118,7 +118,7 @@ GLPHImporterMock >> importMergeResquestMerger: mergeRequest [ ] { #category : #'import - notes' } -GLPHImporterMock >> importNotesfromMergeRequest: mriid [ +GLPHImporterMock >> importNotesOfMergeRequest: mriid [ ^OrderedCollection with: (notes select: [ :note | (note noteable_iid == mriid) ]) ] diff --git a/src/GitLabHealth-Model-Analysis-Tests/GitAnalyzerTest.class.st b/src/GitLabHealth-Model-Analysis-Tests/GitAnalyzerTest.class.st index dc327f93..8743b651 100644 --- a/src/GitLabHealth-Model-Analysis-Tests/GitAnalyzerTest.class.st +++ b/src/GitLabHealth-Model-Analysis-Tests/GitAnalyzerTest.class.st @@ -114,7 +114,7 @@ GitAnalyzerTest >> testAnalyseCommitFrequencySinceUntil [ GitAnalyzerTest >> testAnalyseMergeResquestValidation [ | mergeResquest res | - glhImporter importMergeRequests: projects anyOne. + glhImporter importMergeRequestsOfProject: projects anyOne. mergeResquest := (glhImporter glhModel allWithType: GLHMergeRequest) detect: [ :mr | mr iid = 1 ]. diff --git a/src/GitLabHealth-Model-Analysis/CreatedACRPipelineByProject.class.st b/src/GitLabHealth-Model-Analysis/CreatedACRPipelineByProject.class.st index 3b87a077..ef496dcd 100644 --- a/src/GitLabHealth-Model-Analysis/CreatedACRPipelineByProject.class.st +++ b/src/GitLabHealth-Model-Analysis/CreatedACRPipelineByProject.class.st @@ -41,5 +41,5 @@ CreatedACRPipelineByProject >> load [ projectMergeRequests := self loadMergeRequestsSince: (period at: #since) until: (period at: #until) . - projectMergeRequests do: [ :mr | glhImporter importNotesfromMergeRequest: mr ]. + projectMergeRequests do: [ :mr | glhImporter importNotesOfMergeRequest: mr ]. ] diff --git a/src/GitLabHealth-Model-Analysis/CreatedNoteInMergedOrClosedMergeRequest.class.st b/src/GitLabHealth-Model-Analysis/CreatedNoteInMergedOrClosedMergeRequest.class.st index 0b5d4e12..1f190105 100644 --- a/src/GitLabHealth-Model-Analysis/CreatedNoteInMergedOrClosedMergeRequest.class.st +++ b/src/GitLabHealth-Model-Analysis/CreatedNoteInMergedOrClosedMergeRequest.class.st @@ -44,5 +44,5 @@ CreatedNoteInMergedOrClosedMergeRequest >> load [ projectMergeRequests := self loadMergeRequestsSince: (period at: #since) until: (period at: #until) . - projectMergeRequests do: [ :mr | glhImporter importNotesfromMergeRequest: mr ]. + projectMergeRequests do: [ :mr | glhImporter importNotesOfMergeRequest: mr ]. ] diff --git a/src/GitLabHealth-Model-Analysis/CreatedNotesByACRByProjectMetric.class.st b/src/GitLabHealth-Model-Analysis/CreatedNotesByACRByProjectMetric.class.st index 7d1b62b6..42ea9619 100644 --- a/src/GitLabHealth-Model-Analysis/CreatedNotesByACRByProjectMetric.class.st +++ b/src/GitLabHealth-Model-Analysis/CreatedNotesByACRByProjectMetric.class.st @@ -45,5 +45,5 @@ CreatedNotesByACRByProjectMetric >> load [ projectMergeRequests := self loadMergeRequestsSince: (period at: #since) until: (period at: #until) . - projectMergeRequests do: [ :mr | glhImporter importNotesfromMergeRequest: mr ]. + projectMergeRequests do: [ :mr | glhImporter importNotesOfMergeRequest: mr ]. ] diff --git a/src/GitLabHealth-Model-Analysis/ProjectMetric.class.st b/src/GitLabHealth-Model-Analysis/ProjectMetric.class.st index f7fd6daf..8eb46d30 100644 --- a/src/GitLabHealth-Model-Analysis/ProjectMetric.class.st +++ b/src/GitLabHealth-Model-Analysis/ProjectMetric.class.st @@ -78,7 +78,7 @@ ProjectMetric >> loadMergeRequestsSince: since until: until [ ifAbsentPut: [ | foundMergeRequests | foundMergeRequests := glhImporter - importMergeRequests: + importMergeRequestsOfProject: project since: since until: until. diff --git a/src/GitLabHealth-Model-Analysis/UserMetric.class.st b/src/GitLabHealth-Model-Analysis/UserMetric.class.st index f4257c5a..27c55eb0 100644 --- a/src/GitLabHealth-Model-Analysis/UserMetric.class.st +++ b/src/GitLabHealth-Model-Analysis/UserMetric.class.st @@ -73,7 +73,7 @@ UserMetric >> loadMergeRequestsSince: since until: until [ | mr | project cacheAt: cacheSymbol ifAbsentPut: [ mr := glhImporter - importMergeRequests: project + importMergeRequestsOfProject: project since: since until: until. mr ] ]. diff --git a/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st b/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st index 3e171cc8..acf071c5 100644 --- a/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st +++ b/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st @@ -48,28 +48,6 @@ GitlabModelImporter >> allPipelinesOf: aProjectID [ self parsePipelinesResult: pipelinesJson ]) flattened ] -{ #category : #private } -GitlabModelImporter >> chainsCommitsFrom: commitsCollection [ - - | dic | - - ('Chains ', commitsCollection size printString , ' commits') recordInfo. - - dic := ((self glhModel allWithType: GLHCommit) collect: [ :commit | - commit id -> commit ]) asSet asDictionary. - - commitsCollection do: [ :commit | - commit parent_ids do: [ :parentId | - dic - at: parentId - ifPresent: [ :parentCommit | - parentCommit childCommits - add: commit - unless: self blockOnIdEquality ] - ifAbsent: [ ] ] ]. - ^ commitsCollection -] - { #category : #'import - commits' } GitlabModelImporter >> commitsOfProject: aGLHProject forRefName: refName until: toDate [ @@ -119,7 +97,7 @@ GitlabModelImporter >> completeImportProject: aGLHProject [ withInitialMergeRequest ifTrue: [ self - importMergeRequests: importedProject + importMergeRequestsOfProject: importedProject since: DateAndTime today until: DateAndTime now ]. @@ -196,7 +174,7 @@ GitlabModelImporter >> completeImportedProject: aGLHProject [ withInitialMergeRequest ifTrue: [ self - importMergeRequests: importedProject + importMergeRequestsOfProject: importedProject since: DateAndTime today until: DateAndTime now ]. @@ -529,14 +507,13 @@ GitlabModelImporter >> importAllGroups [ { #category : #'import - pipelines' } GitlabModelImporter >> importAllPipelinesOfProject: aGLHProject [ - + (self allPipelinesOf: aGLHProject id) do: [ :pipeline | - |pip| - pip := self glhModel add: pipeline unless: self blockOnIdEquality . + | pip | + pip := self glhModel add: pipeline unless: self blockOnIdEquality. pip := aGLHProject pipelines add: pip unless: self blockOnIdEquality. - self completeImportedPipeline: pip. - ]. - + self completeImportedPipeline: pip ]. + ^ aGLHProject pipelines ] @@ -551,11 +528,19 @@ GitlabModelImporter >> importAndLoadLatestsCommitsOfProject: aGLHProject [ ^ commits ] -{ #category : #'import - user' } -GitlabModelImporter >> importAuthorOfCommit: aGLHCommit [ - |user| - user:= (self importUserByUsername: aGLHCommit author_name) . - aGLHCommit commitCreator: user. +{ #category : #'import - users' } +GitlabModelImporter >> importAuthorOfCommit: aGLHCommit [ + + | user | + self + deprecated: 'Use importCreatorOfCommit: instead of current one' + on: '19 September 2025' + in: + 'Pharo-12.0.0+SNAPSHOT.build.1571.sha.cf5fcd22e66957962c97dffc58b0393b7f368147 (64 Bit)'. + + + user := self importUserByUsername: aGLHCommit author_name. + aGLHCommit commitCreator: user. ^ user ] @@ -662,11 +647,20 @@ GitlabModelImporter >> importCommits: aGLHProject [ "limited to the last 20 commits" | results parsedResults params | - params := { - #with_stats -> 'true' - } asDictionary. - results := self repoApi commits getByPage: 1 perPage: 20 inProject: aGLHProject id withParams: params. - + self + deprecated: + 'Use importLatestCommitsOfProject: instead of current one' + on: '19 September 2025' + in: + 'Pharo-12.0.0+SNAPSHOT.build.1571.sha.cf5fcd22e66957962c97dffc58b0393b7f368147 (64 Bit)'. + + params := { (#with_stats -> 'true') } asDictionary. + results := self repoApi commits + getByPage: 1 + perPage: 20 + inProject: aGLHProject id + withParams: params. + parsedResults := self parseCommitsResult: results. self glhModel addAll: parsedResults unless: self blockOnIdEquality. @@ -675,8 +669,8 @@ GitlabModelImporter >> importCommits: aGLHProject [ self withCommitDiffs ifTrue: [ parsedResults do: [ :commit | self importDiffOfCommit: commit ] ]. - - ^ parsedResults. + + ^ parsedResults ] { #category : #'import - commits' } @@ -889,7 +883,7 @@ GitlabModelImporter >> importContributedProjectsOfUser: aGLHUser [ ^ projects ] -{ #category : #'import - commits' } +{ #category : #'import - users' } GitlabModelImporter >> importCreatorOfCommit: aCommit [ aCommit commitCreator ifNil: [ @@ -926,7 +920,7 @@ GitlabModelImporter >> importDiffOfCommit: aCommit [ ^ aCommit diffs ] -{ #category : #'import - merge request' } +{ #category : #'import - merge-requests' } GitlabModelImporter >> importDiffOfMergeRequest: aMergeRequest [ | result diffsResult | @@ -1081,7 +1075,7 @@ GitlabModelImporter >> importLastestCommitsOfProject: aGLHProject [ ^ parsedResults ] -{ #category : #'import - merge request' } +{ #category : #'import - merge-requests' } GitlabModelImporter >> importLatestMergeRequestsOfProject: aGLHProject [ |results parsedResults| @@ -1105,7 +1099,7 @@ GitlabModelImporter >> importLatestPipelinesOfProject: aGLHProject [ ^ aGLHProject pipelines ] -{ #category : #'import - release' } +{ #category : #'import - releases' } GitlabModelImporter >> importLatestReleaseOfProject: aGLHProject [ |result foundRelease| @@ -1120,7 +1114,7 @@ GitlabModelImporter >> importLatestReleaseOfProject: aGLHProject [ ^ foundRelease. ] -{ #category : #'import - merge request' } +{ #category : #'import - merge-requests' } GitlabModelImporter >> importMergeRequestCommits: aGLPHEMergeRequest [ | commits result | @@ -1136,7 +1130,7 @@ GitlabModelImporter >> importMergeRequestCommits: aGLPHEMergeRequest [ ^ commits ] -{ #category : #'import - merge request' } +{ #category : #'import - merge-requests' } GitlabModelImporter >> importMergeRequestMergeCommits: aGLPHEMergeRequest [ | foundCommits | @@ -1185,8 +1179,8 @@ GitlabModelImporter >> importMergeRequestPipelines: aGLHMergeRequest [ ] -{ #category : #'import - merge request' } -GitlabModelImporter >> importMergeRequests: aGLHProject [ +{ #category : #'import - merge-requests' } +GitlabModelImporter >> importMergeRequestsOfProject: aGLHProject [ | results parsedResults mrs | ('Import merge request of Project: ' , aGLHProject id printString) @@ -1216,8 +1210,8 @@ GitlabModelImporter >> importMergeRequests: aGLHProject [ ^ mrs ] -{ #category : #'import - merge request' } -GitlabModelImporter >> importMergeRequests: aGLHProject since: fromDate until: toDate [ +{ #category : #'import - merge-requests' } +GitlabModelImporter >> importMergeRequestsOfProject: aGLHProject since: fromDate until: toDate [ | params result mergeRequests | ('import MR of Project ' , aGLHProject name) recordInfo. @@ -1260,7 +1254,7 @@ GitlabModelImporter >> importMergeRequests: aGLHProject since: fromDate until: t ^ mergeRequests ] -{ #category : #'import - merge request' } +{ #category : #'import - merge-requests' } GitlabModelImporter >> importMergeResquestApprovals: aGLPHEMergeRequest [ | results parsedResult | @@ -1280,7 +1274,7 @@ GitlabModelImporter >> importMergeResquestApprovals: aGLPHEMergeRequest [ ^ aGLPHEMergeRequest ] -{ #category : #'import - merge request' } +{ #category : #'import - merge-requests' } GitlabModelImporter >> importMergeResquestAuthor: aGLPHEMergeRequest [ | authorID | @@ -1297,7 +1291,7 @@ GitlabModelImporter >> importMergeResquestAuthor: aGLPHEMergeRequest [ ^aGLPHEMergeRequest author: (self importUser: authorID) ] -{ #category : #'import - merge request' } +{ #category : #'import - merge-requests' } GitlabModelImporter >> importMergeResquestMerger: aGLPHEMergeRequest [ | authorID | @@ -1318,7 +1312,7 @@ GitlabModelImporter >> importMergeResquestMerger: aGLPHEMergeRequest [ ] { #category : #'import - notes' } -GitlabModelImporter >> importNotesfromMergeRequest: mergeRequest [ +GitlabModelImporter >> importNotesOfMergeRequest: mergeRequest [ | results notes | results := self repoApi notes allInMergeRequest: mergeRequest iid ofProject: mergeRequest project id. @@ -1380,6 +1374,13 @@ GitlabModelImporter >> importPipeline: pipelineId OfProject: aGLHProject [ ^ self completeImportedPipeline: pipeline. ] +{ #category : #'import - pipelines' } +GitlabModelImporter >> importPipelinesOfProject: aGLHProject [ + + self flag: 'WARNING: this import ALL the pipelines at ones. Prefered ImportLatestPipleinesOfProject: for faster performance (if possible)'. + ^ self importAllPipelinesOfProject: aGLHProject +] + { #category : #'import - pipelines' } GitlabModelImporter >> importPipelinesOfProject: aGLHProject after: after andBefore: before [ ^ (self pipelinesOf: aGLHProject id after: after andBefore: before) collect: [ :pipeline | @@ -1494,25 +1495,27 @@ GitlabModelImporter >> importRepository: aGLHRepository [ { #category : #'import - commits' } GitlabModelImporter >> importSZZFromCommit: aCommit [ - | result diffRanges diffs szzCommits| - szzCommits := Set new. - diffs := (self importDiffOfCommit: aCommit). + | diffRanges diffs szzCommits | + szzCommits := Set new. + diffs := self importDiffOfCommit: aCommit. diffRanges := diffs flatCollect: #diffRanges. diffRanges do: [ :range | - |blames| - - blames := NeoJSONReader fromString:( self repoApi repositories getBlameOf: range diff new_path inRef: aCommit id start: range start end:range end ofProject: (aCommit repository project id)). - blames collect: [ :blame | - blame isDictionary ifTrue: [ szzCommits add: (self importCommit:(blame at: #commit at: #id) ofProject: aCommit repository project). ] - - ] - - ]. - ^ szzCommits . - -] - -{ #category : #'import - tag' } + | blames | + blames := NeoJSONReader fromString: (self repoApi repositories + getBlameOf: range diff new_path + inRef: aCommit id + start: range start + end: range end + ofProject: aCommit repository project id). + blames collect: [ :blame | + blame isDictionary ifTrue: [ + szzCommits add: (self + importCommit: (blame at: #commit at: #id) + ofProject: aCommit repository project) ] ] ]. + ^ szzCommits +] + +{ #category : #'import - tags' } GitlabModelImporter >> importTagsForProject: aProject [ |results tags | results := repoApi tags getAllOfProject: aProject id. @@ -1945,7 +1948,7 @@ GitlabModelImporter >> parseProjectResult: aResult [ ^ reader nextAs: GLHProject ] -{ #category : #parsing } +{ #category : #'private - parsing' } GitlabModelImporter >> parseReleaseResult: result [ |reader| reader := generalReader on: result readStream. @@ -1953,7 +1956,7 @@ GitlabModelImporter >> parseReleaseResult: result [ ^ reader nextAs: GLHRelease ] -{ #category : #parsing } +{ #category : #'private - parsing' } GitlabModelImporter >> parseReleasesResult: result [ |reader| reader := generalReader on: result readStream. @@ -1970,7 +1973,7 @@ GitlabModelImporter >> parseSubGroupResult: aResult [ ^ reader nextAs: #ArrayOfGroups ] -{ #category : #parsing } +{ #category : #'private - parsing' } GitlabModelImporter >> parseTagsResult: result [ |reader| reader := generalReader on: result readStream. diff --git a/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st b/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st index 841be8d8..8378c32c 100644 --- a/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st +++ b/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st @@ -107,13 +107,13 @@ GitModelImporter class >> reset [ currentImporter := OrderedDictionary new. ] -{ #category : #accessing } +{ #category : #initialization } GitModelImporter >> beWithFiles [ withFiles := true ] -{ #category : #accessing } +{ #category : #initialization } GitModelImporter >> beWithoutFiles [ withFiles := false @@ -234,7 +234,19 @@ GitModelImporter >> glhModel: anObject [ { #category : #'import - commits' } GitModelImporter >> importAndLoadLatestsCommitsOfProject: aGLHProject [ - + self subclassResponsibility +] + +{ #category : #'import - users' } +GitModelImporter >> importAuthorOfCommit: aGLHCommit [ + + self + deprecated: 'Use importCreatorOfCommit: instead of current one' + on: '19 September 2025' + in: + 'Pharo-12.0.0+SNAPSHOT.build.1571.sha.cf5fcd22e66957962c97dffc58b0393b7f368147 (64 Bit)'. + + self subclassResponsibility ] { #category : #'import - repositories' } @@ -246,27 +258,32 @@ GitModelImporter >> importBranchesOf: aGLHProject [ { #category : #'import - commits' } GitModelImporter >> importCommit: aCommitID ofProject: aGLHProject [ + self subclassResponsibility ] { #category : #'import - commits' } GitModelImporter >> importCommitsOfProject: aGLHProject since: since until: until [ + self subclassResponsibility ] { #category : #'import - projects' } GitModelImporter >> importContributedProjectsOfUser: aGLHUser [ ] -{ #category : #'import - commits' } +{ #category : #'import - users' } GitModelImporter >> importCreatorOfCommit: aGLHCommit [ + self subclassResponsibility ] { #category : #'import - commits' } GitModelImporter >> importDiffOfCommit: aCommit [ + + self subclassResponsibility ] -{ #category : #import } +{ #category : #'import - commits' } GitModelImporter >> importDiffRangesForDiff: aGLHDiff [ | diffRanges | @@ -291,21 +308,57 @@ GitModelImporter >> importGroup: aGroupID [ self subclassResponsibility ] -{ #category : #pipelines } -GitModelImporter >> importLatestPipelinesOfProject: aGLHProject [ - (self pipelinesOf: aGLHProject id withLimit:30) do: [ :pipeline | - self glhModel add: pipeline unless: self blockOnIdEquality . - aGLHProject pipelines add: pipeline unless: self blockOnIdEquality] +{ #category : #'import - issues' } +GitModelImporter >> importIssuesOfProject: aGLHProject [ + self subclassResponsibility ] -{ #category : #'import - merge request' } +{ #category : #'import - jobs' } +GitModelImporter >> importJobsOf: aGLHPipeline [ + self subclassResponsibility +] + +{ #category : #'import - merge-requests' } +GitModelImporter >> importLastestCommitsOfProject: aGLHProject [ + "limited to the last 50 commits" + self subclassResponsibility +] + +{ #category : #'import - merge-requests' } +GitModelImporter >> importLatestMergeRequestsOfProject: aGLHProject [ + self subclassResponsibility +] + +{ #category : #'import - pipelines' } +GitModelImporter >> importLatestPipelinesOfProject: aGLHProject [ + self subclassResponsibility + +] + +{ #category : #'import - releases' } +GitModelImporter >> importLatestReleaseOfProject: aGLHProject [ + ^ self subclassResponsibility +] + +{ #category : #'import - merge-requests' } GitModelImporter >> importMergeRequestCommits: mergeRequest [ ] -{ #category : #'import - merge request' } +{ #category : #'import - merge-requests' } GitModelImporter >> importMergeRequestMergeCommits: aGLHMergeRequest [ ] +{ #category : #'import - merge-requests' } +GitModelImporter >> importMergeRequestsOfProject: aGLHProject [ + + self subclassResponsibility +] + +{ #category : #'import - merge-requests' } +GitModelImporter >> importMergeRequestsOfProject: aGLHProject since: fromDate until: toDate [ + self subclassResponsibility +] + { #category : #'import - merge-requests' } GitModelImporter >> importMergeResquestAuthor: mergeRequest [ ] @@ -314,12 +367,28 @@ GitModelImporter >> importMergeResquestAuthor: mergeRequest [ GitModelImporter >> importMergeResquestMerger: mergeRequest [ ] +{ #category : #'import - milestones' } +GitModelImporter >> importMilestonesOfProject: aGLHProject [ + self subclassResponsibility +] + { #category : #'import - notes' } -GitModelImporter >> importNotesfromMergeRequest: mergeRequest [ +GitModelImporter >> importNotesOfMergeRequest: mergeRequest [ self subclassResponsibility ] +{ #category : #'import - pipelines' } +GitModelImporter >> importPipeline: aPipelineId OfProject: aGLHProject [ + + self subclassResponsibility +] + +{ #category : #'import - merge-requests' } +GitModelImporter >> importPipelinesOfProject: aGLHProject [ + ^ self subclassResponsibility +] + { #category : #'import - projects' } GitModelImporter >> importProject: id [ "id can be a string or an integer depending on the APi implementation" @@ -329,7 +398,7 @@ GitModelImporter >> importProject: id [ ^ self subclassResponsibility ] -{ #category : #api } +{ #category : #'import - projects' } GitModelImporter >> importProject: aProjectID ofGroup: aGroup [ ] @@ -340,8 +409,32 @@ GitModelImporter >> importProjects: aCollectionOfProjectID [ ^ aCollectionOfProjectID collect: [ :id | self importProject: id ] ] +{ #category : #'import - projects' } +GitModelImporter >> importProjectsOfUser: aGLHUser [ + "https://docs.github.com/fr/rest/repos/repos?apiVersion=2022-11-28#list-repositories-for-a-user" + + self subclassResponsibility +] + +{ #category : #'import - releases' } +GitModelImporter >> importRelease: aReleaseID ofProject: aGLHProject [ + self subclassResponsibility +] + +{ #category : #'import - tags' } +GitModelImporter >> importTagsForProject: aGLHProject [ + self subclassResponsibility +] + +{ #category : #'import - users' } +GitModelImporter >> importUser: aUserID [ + self subclassResponsibility +] + { #category : #'import - users' } GitModelImporter >> importUserByUsername: username [ + + self subclassResponsibility ] { #category : #initialization } @@ -354,12 +447,12 @@ GitModelImporter >> initialize [ yourself. ] -{ #category : #import } +{ #category : #initialization } GitModelImporter >> makeGlobal [ ^ self makeGlobal: DateAndTime now printString. ] -{ #category : #import } +{ #category : #initialization } GitModelImporter >> makeGlobal: aLabel [ currentImporter := GithubModelImporter importers ifNil: [ OrderedDictionary new ]. From 97d432169805071056ced1319d3d44dd9140edc0 Mon Sep 17 00:00:00 2001 From: HLAD Nicolas Date: Mon, 22 Sep 2025 11:54:55 +0200 Subject: [PATCH 13/52] modify github import to support new API --- .../GithubModelImporter.class.st | 227 ++++++++++++------ .../GLHMetamodelGenerator.class.st | 6 +- .../GitModelImporter.class.st | 6 +- 3 files changed, 157 insertions(+), 82 deletions(-) diff --git a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st index cc5e5559..6e289c7b 100644 --- a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st +++ b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st @@ -67,6 +67,13 @@ GithubModelImporter >> completeImportedCommit: aGLHCommit [ { #category : #'import - projects' } GithubModelImporter >> completeImportedProject: aGLHProject [ + ('Complete import of project: ' , aGLHProject id printString) + recordInfo. + aGLHProject repository ifNotNil: [ ^ aGLHProject ]. + + aGLHProject repository: GLHRepository new. + self glhModel add: aGLHProject repository. + self importPipelinesOfProject: aGLHProject. self importBranchesOf: aGLHProject. self withCommitsSince ifNotNil: [ :withCommitSince | "If not nil, it means we have to import commit" @@ -75,6 +82,77 @@ GithubModelImporter >> completeImportedProject: aGLHProject [ self chainsCommitsFrom: commits ] ] +{ #category : #'as yet unclassified' } +GithubModelImporter >> configureReaderForBranches: reader [ + + reader mapInstVarsFor: GLHBranch. + + + reader for: GLHBranch do: [ :mapping | + mapping + mapProperty: #sha + getter: [ :branch | #ignore ] + setter: [ :branch :value | + branch sha: (value at: #sha). + ]]. + + + reader + for: #ArrayOfBranches + customDo: [ :customMappting | + customMappting listOfElementSchema: GLHBranch ] +] + +{ #category : #'private - configure reader' } +GithubModelImporter >> configureReaderForCommit: reader [ + + reader for: GLHCommit do: [ :mapping | + mapping mapInstVar: #id to: #sha. + mapping mapInstVar: #web_url to: #html_url. + + mapping + mapProperty: #commit + getter: [ :object | #ignore ] + setter: [ :glhCommit :value | + glhCommit message: (value at: #message). + glhCommit authored_date: + (DateAndTime fromString: (value at: #author at: #date)). + glhCommit committed_date: + (DateAndTime fromString: (value at: #committer at: #date)) ]. + + mapping + mapProperty: #author + getter: [ :object | #ignore ] + setter: [ :glhCommit :value | + value ifNotNil: [ + glhCommit author_name: (value at: #login). + value + at: #id + ifPresent: [ :authorId | + glhCommit commitCreator: (self importUser: authorId) ] ] ]. + + mapping + mapProperty: #committer + getter: [ :object | #ignore ] + setter: [ :glhCommit :value | + value ifNotNil: [ glhCommit committer_name: (value at: #login) ] ]. + + (mapping mapInstVar: #parent_ids to: #parents) valueSchema: + #ArrayOfIds ]. + + reader for: DateAndTime customDo: [ :mapping | + mapping decoder: [ :string | DateAndTime fromString: string ] ]. + + reader for: #ArrayOfIds customDo: [ :mapping | + mapping decoder: [ :parents | + parents collect: [ :parent | parent at: #sha ] ] ]. + + reader + for: #ArrayOfCommits + customDo: [ :customMappting | + customMappting listOfElementSchema: GLHCommit ] +] + { #category : #'private - configure reader' } GithubModelImporter >> configureReaderForProject: reader [ @@ -116,22 +194,58 @@ GithubModelImporter >> ensureGroupNamed: aGroupName [ ] { #category : #'import - repositories' } -GithubModelImporter >> importBranchesOf: project [ - +GithubModelImporter >> importBranchesOf: aGLHProject [ "add the pipeline (actions runs) in the project" - | branchesResult branches repository | - branchesResult := self repoApi - branchesOfRepo: project name - ofOrganization: project group name. - branches := self parseBranchesResult: branchesResult. - self glhModel addAll: branches. - repository := GLHRepository new. - self glhModel add: repository. - project repository: repository. - branches do: [ :branch | - repository addBranch: branch. - self withFiles ifTrue: [ self importFilesOfBranch: branch ] ] + | branchesResults foundBranches branches | + branchesResults := self repoApi branches + getAllForRepo: aGLHProject name + ofOwner: aGLHProject group name. + + foundBranches := (branchesResults collect: [ :branchesResult | + self parseBranchesResult: branchesResult ]) + flattened. + + + "WARNING: always add branch first into repository, than into model !" + branches := aGLHProject repository branches + addAll: foundBranches + unless: self blockOnNameEquality. + + "branch HEAD commit is not imported by default. use branch ref (sha) to import it specifically" + + branches := self glhModel + addAll: branches + unless: self blockForBranchEquality. + + self withFiles ifTrue: [ + branches do: [ :branch | self importFilesOfBranch: branch ] ] +] + +{ #category : #'import - commits' } +GithubModelImporter >> importCommit: aCommitID ofProject: aGLHProject [ + + | result parsedResult | + (self glhModel allWithType: GLHCommit) asOrderedCollection + detect: [ :commit | commit id = aCommitID ] + ifFound: [ :commit | ^ commit ]. + + result := self repoApi commits + get: aCommitID + inProject: aGLHProject id. + + parsedResult := self parseCommitResult: result. + + parsedResult := self glhModel + add: parsedResult + unless: self blockOnIdEquality. + parsedResult := aGLHProject repository commits + add: parsedResult + unless: self blockOnIdEquality. + + self withCommitDiffs ifTrue: [ self importDiffOfCommit: parsedResult ]. + + ^ parsedResult ] { #category : #'import - commits' } @@ -263,7 +377,7 @@ GithubModelImporter >> importFilesOfBranch: aBranch [ GithubModelImporter >> importGroup: aGroupName [ | result groupResult | - result := self repoApi organization: aGroupName. + result := self repoApi organizations get: aGroupName. groupResult := self parseGroupResult: result. self glhModel add: groupResult. self importRepositoriesOfGroup: groupResult. @@ -289,9 +403,9 @@ GithubModelImporter >> importPipelinesOfProject: project [ "add the pipeline (actions runs) in the project" | pipelinesResult ghApiPipelineOverview | - pipelinesResult := self repoApi - actionsRunOfRepo: project name - ofOrganization: project group name. + pipelinesResult := self repoApi actions + getLatestForRepo: project name + ofOwner: project group name. ghApiPipelineOverview := self parsePipelinesResult: pipelinesResult. ghApiPipelineOverview workflow_runs do: [ :pipeline | project addPipeline: pipeline ] @@ -312,6 +426,7 @@ GithubModelImporter >> importProject: aProjectName ofGroup: aGroupName [ { #category : #'import - groups' } GithubModelImporter >> importRepositoriesOfGroup: groupResult [ + "Github Repository = GLHProject" | reposResult itemByPage pageNumber reposFound tmp | itemByPage := 100. @@ -321,7 +436,7 @@ GithubModelImporter >> importRepositoriesOfGroup: groupResult [ ('Extract commits from ' , reposFound size printString , ' to ' , (reposFound size + itemByPage) printString) recordInfo. tmp := self parseArrayOfProject: (self repoApi - reposOfOrganization: groupResult name + organizations getRepositoriesOfOrganization: groupResult name perPage: itemByPage page: pageNumber). @@ -336,7 +451,7 @@ GithubModelImporter >> importRepositoriesOfGroup: groupResult [ page: pageNumber). reposFound addAll: tmp ]. - reposResult := self repoApi reposOfOrganization: groupResult name. + reposResult := self repoApi organizations getRepositoriesOfOrganization: groupResult name. groupResult projects addAll: reposFound. self glhModel addAll: groupResult projects. groupResult projects do: [ :project | @@ -364,6 +479,8 @@ GithubModelImporter >> initReader [ generalReader := NeoJSONReader new. self configureReaderForProject: generalReader. + self configureReaderForCommit: generalReader. + self configureReaderForBranches: generalReader. ] { #category : #initialization } @@ -408,13 +525,18 @@ GithubModelImporter >> parseArrayOfProject: arrayOfProjects [ GithubModelImporter >> parseBranchesResult: arrayOfBranch [ | reader | - reader := NeoJSONReader on: arrayOfBranch readStream. - reader mapInstVarsFor: GLHBranch. - reader - for: #ArrayOfBranch - customDo: [ :customMappting | - customMappting listOfElementSchema: GLHBranch ]. - ^ reader nextAs: #ArrayOfBranch + reader := generalReader on: arrayOfBranch readStream. + + ^ reader nextAs: #ArrayOfBranches +] + +{ #category : #parsing } +GithubModelImporter >> parseCommitResult: result [ + | reader | + + reader := generalReader on: result readStream. + + ^ reader nextAs: GLHCommit ] { #category : #parsing } @@ -424,56 +546,9 @@ GithubModelImporter >> parseCommitsResult: result [ (result includesSubstring: '"status":"409"') ifTrue: [ GHRepositoryEmptyError signal: 'Git Repository is empty' ]. - reader := NeoJSONReader on: result readStream. - - reader for: GLHCommit do: [ :mapping | - mapping mapInstVar: #id to: #sha. - mapping mapInstVar: #web_url to: #html_url. - - mapping - mapProperty: #commit - getter: [ :object | #ignore ] - setter: [ :glhCommit :value | - glhCommit message: (value at: #message). - glhCommit authored_date: - (DateAndTime fromString: (value at: #author at: #date)). - glhCommit committed_date: - (DateAndTime fromString: (value at: #committer at: #date)) ]. - - mapping - mapProperty: #author - getter: [ :object | #ignore ] - setter: [ :glhCommit :value | - value ifNotNil: [ - glhCommit author_name: (value at: #login). - value - at: #id - ifPresent: [ :authorId | - glhCommit commitCreator: (self importUser: authorId) ] ] ]. - - mapping - mapProperty: #committer - getter: [ :object | #ignore ] - setter: [ :glhCommit :value | - value ifNotNil: [ glhCommit committer_name: (value at: #login) ] ]. - - (mapping mapInstVar: #parent_ids to: #parents) valueSchema: - #ArrayOfIds ]. - - reader for: DateAndTime customDo: [ :mapping | - mapping decoder: [ :string | DateAndTime fromString: string ] ]. - - reader for: #ArrayOfIds customDo: [ :mapping | - mapping decoder: [ :parents | - parents collect: [ :parent | parent at: #sha ] ] ]. - - reader - for: #ArrayOfCommit - customDo: [ :customMappting | - customMappting listOfElementSchema: GLHCommit ]. - + reader := generalReader on: result readStream. - ^ reader nextAs: #ArrayOfCommit + ^ reader nextAs: #ArrayOfCommits ] { #category : #parsing } diff --git a/src/GitLabHealth-Model-Generator/GLHMetamodelGenerator.class.st b/src/GitLabHealth-Model-Generator/GLHMetamodelGenerator.class.st index 0ff5fef1..6719aafa 100644 --- a/src/GitLabHealth-Model-Generator/GLHMetamodelGenerator.class.st +++ b/src/GitLabHealth-Model-Generator/GLHMetamodelGenerator.class.st @@ -617,9 +617,9 @@ GLHMetamodelGenerator >> releaseRelations [ { #category : #'as yet unclassified' } GLHMetamodelGenerator >> tRefProperties [ "define the properties of a ref instance" - - tag property: #sha type: #String. - tag property: #name type: #String. + + tRef property: #sha type: #String. + tRef property: #name type: #String ] { #category : #tags } diff --git a/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st b/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st index 8378c32c..7169aaf1 100644 --- a/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st +++ b/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st @@ -166,7 +166,7 @@ GitModelImporter >> blockOnNameEquality [ ^ self blockEqualityOn: #name ] -{ #category : #'import - commits' } +{ #category : #utils } GitModelImporter >> chainsCommitsFrom: commitsCollection [ | dic | @@ -277,13 +277,13 @@ GitModelImporter >> importCreatorOfCommit: aGLHCommit [ self subclassResponsibility ] -{ #category : #'import - commits' } +{ #category : #'import - diffs' } GitModelImporter >> importDiffOfCommit: aCommit [ self subclassResponsibility ] -{ #category : #'import - commits' } +{ #category : #'import - diffs' } GitModelImporter >> importDiffRangesForDiff: aGLHDiff [ | diffRanges | From f5af8ad9d77aede5d4f441118ca4a22e35ed302e Mon Sep 17 00:00:00 2001 From: HLAD Nicolas Date: Mon, 22 Sep 2025 14:48:45 +0200 Subject: [PATCH 14/52] add importer for MR (or PR) in Github --- .../GithubModelImporter.class.st | 92 ++++++++++++++++--- 1 file changed, 77 insertions(+), 15 deletions(-) diff --git a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st index 6e289c7b..6de08faf 100644 --- a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st +++ b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st @@ -82,7 +82,7 @@ GithubModelImporter >> completeImportedProject: aGLHProject [ self chainsCommitsFrom: commits ] ] -{ #category : #'as yet unclassified' } +{ #category : #'private - configure reader' } GithubModelImporter >> configureReaderForBranches: reader [ reader mapInstVarsFor: GLHBranch. @@ -153,6 +153,37 @@ GithubModelImporter >> configureReaderForCommit: reader [ customMappting listOfElementSchema: GLHCommit ] ] +{ #category : #'private - configure reader' } +GithubModelImporter >> configureReaderForMergeRequest: reader [ + " reader mapInstVarsFor: GLHProject. " + + reader for: GLHMergeRequest do: [ :mapping | + + (mapping mapInstVar: #created_at) valueSchema: DateAndTime. + (mapping mapInstVar: #updated_at) valueSchema: DateAndTime. + (mapping mapInstVar: #merged_at) valueSchema: DateAndTime. + (mapping mapInstVar: #closed_at) valueSchema: DateAndTime. + + mapping + mapProperty: #author + getter: [ ] + setter: [ :object :value | + object cacheAt: #authorID put: (value at: #id) ]. + mapping + mapProperty: #merge_user + getter: [ ] + setter: [ :object :value | + value ifNotNil: [ + object cacheAt: #mergeUserID put: (value at: #id) ] ] + + ]. + + + reader for: #ArrayOfMergeRequest customDo: [ :customMappting | + customMappting listOfElementSchema: GLHMergeRequest ]. + +] + { #category : #'private - configure reader' } GithubModelImporter >> configureReaderForProject: reader [ @@ -260,12 +291,13 @@ GithubModelImporter >> importCommitsOfProject: aGLHProject [ , (foundCommits size + itemByPage) printString) recordInfo. "also check that there is at least one commit with the error handling" [ - tmp := self parseCommitsResult: (self repoApi - commitsOfProject: aGLHProject name - ofOrganization: aGLHProject group name - since: self withCommitsSince - perPage: itemByPage - page: pageNumber) ] + tmp := self parseCommitsResult: (self repoApi commits + getForRepo: aGLHProject name + ofOwner: aGLHProject group name + withParms: { + (#since -> self withCommitsSince). + (#perPage -> itemByPage). + (#page -> pageNumber) } asDictionary) ] on: GHRepositoryEmptyError do: [ ^ { } ]. @@ -274,12 +306,13 @@ GithubModelImporter >> importCommitsOfProject: aGLHProject [ pageNumber := pageNumber + 1. ('Extract issues from ' , foundCommits size printString , ' to ' , (foundCommits size + itemByPage) printString) recordInfo. - tmp := self parseCommitsResult: (self repoApi - commitsOfProject: aGLHProject name - ofOrganization: aGLHProject group name - since: self withCommitsSince - perPage: itemByPage - page: pageNumber). + tmp := self parseCommitsResult: (self repoApi commits + getForRepo: aGLHProject name + ofOwner: aGLHProject group name + withParms: { + (#sine -> self withCommitsSince). + (#perPage -> itemByPage). + (#page -> pageNumber) } asDictionary). foundCommits addAll: tmp ]. "add the imported commits (unless they are already added to this repository)" @@ -384,6 +417,28 @@ GithubModelImporter >> importGroup: aGroupName [ ^ groupResult ] +{ #category : #'import - merge-requests' } +GithubModelImporter >> importLatestMergeRequestsOfProject: aGLHProject [ + + | results parsedResults | + results := self repoApi pullRequests getLatestForRepo: aGLHProject name ofOwner: aGLHProject group name. + parsedResults := self parseMergeRequestsResult: results. + + parsedResults := glhModel + addAll: parsedResults + unless: self blockOnIdEquality. + parsedResults := aGLHProject mergeRequests + addAll: parsedResults + unless: self blockOnIdEquality. + ^ parsedResults +] + +{ #category : #'import - merge-requests' } +GithubModelImporter >> importLatestPullRequestsOfProject: aGLHProject [ + "alias method since PullRequest = MergeRequest in model" + ^ self importLatestMergeRequestsOfProject: aGLHProject +] + { #category : #'import - merge request' } GithubModelImporter >> importMergeRequestsOfProject: aProject [ |response mergeRequests| @@ -467,7 +522,7 @@ GithubModelImporter >> importUser: userID [ detect: [ :user | user id = userID ] ifFound: [ :user | ^ user ]. ('Import user: ' , userID printString) recordInfo. - result := self repoApi user: userID. + result := self repoApi users getUserId: userID. userResult := self parseUserResult: result. ^ glhModel add: userResult @@ -478,9 +533,16 @@ GithubModelImporter >> importUser: userID [ GithubModelImporter >> initReader [ generalReader := NeoJSONReader new. + + "will be reuse for all reader next" + generalReader for: DateAndTime customDo: [ :mapping | + mapping decoder: [ :string | + string ifNil: [ nil ] ifNotNil: [ DateAndTime fromString: string ] ] ]. + + self configureReaderForProject: generalReader. self configureReaderForCommit: generalReader. - self configureReaderForBranches: generalReader. + self configureReaderForBranches: generalReader ] { #category : #initialization } From 783e2bb484ebe1307234f2e79cc732efcebd2309 Mon Sep 17 00:00:00 2001 From: HLAD Nicolas Date: Mon, 22 Sep 2025 17:21:22 +0200 Subject: [PATCH 15/52] move reader configuration to super class importer --- .../GithubModelImporter.class.st | 3 - .../GitlabModelImporter.class.st | 18 ++---- .../GitModelImporter.class.st | 57 ++++++++++++++++++- 3 files changed, 61 insertions(+), 17 deletions(-) diff --git a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st index 6de08faf..906bcf53 100644 --- a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st +++ b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st @@ -1,9 +1,6 @@ Class { #name : #GithubModelImporter, #superclass : #GitModelImporter, - #instVars : [ - 'generalReader' - ], #category : #'GitHubHealth-Model-Importer' } diff --git a/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st b/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st index acf071c5..7c3c2975 100644 --- a/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st +++ b/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st @@ -3,8 +3,7 @@ Class { #superclass : #GitModelImporter, #instVars : [ 'withInitialCommits', - 'withInitialMergeRequest', - 'generalReader' + 'withInitialMergeRequest' ], #category : #'GitLabHealth-Model-Importer' } @@ -1620,16 +1619,9 @@ GitlabModelImporter >> importUserByUsername: anUsername [ { #category : #initialization } GitlabModelImporter >> initReader [ - - generalReader := NeoJSONReader new. - self configureReaderForCommit: generalReader. - self configureReaderForGroup: generalReader. - self configureReaderForDiffs: generalReader. - self configureReaderForMergeRequest: generalReader. - self configureReaderForPipeline: generalReader. - self configureReaderForTags: generalReader. - self configureReaderForReleases: generalReader. - self configureReaderForUsers: generalReader. + + "add specific reader for this importer here" + super initReader ] { #category : #initialization } @@ -1642,7 +1634,7 @@ GitlabModelImporter >> initialize [ self withCommitsSince: 1 week. - self initReader + ] { #category : #private } diff --git a/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st b/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st index 7169aaf1..4f09fb08 100644 --- a/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st +++ b/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st @@ -13,7 +13,8 @@ Class { 'glhModel', 'userCatalogue', 'repoApi', - 'withCommitDiffs' + 'withCommitDiffs', + 'generalReader' ], #classVars : [ 'currentImporter' @@ -102,6 +103,11 @@ GitModelImporter class >> importers [ ^ currentImporter ] +{ #category : #'class initialization' } +GitModelImporter class >> initialize [ + currentImporter := Dictionary new. +] + { #category : #initialization } GitModelImporter class >> reset [ currentImporter := OrderedDictionary new. @@ -208,6 +214,39 @@ GitModelImporter >> completeImportedCommit: aGLHCommit [ GitModelImporter >> completeImportedProject: aGLHProject [ ] +{ #category : #'private - configure reader' } +GitModelImporter >> configureReaderForCommit: reader [ +] + +{ #category : #'private - configure reader' } +GitModelImporter >> configureReaderForDiffs: reader [ +] + +{ #category : #'private - configure reader' } +GitModelImporter >> configureReaderForGroup: reader [ +] + +{ #category : #'private - configure reader' } +GitModelImporter >> configureReaderForMergeRequest: reader [ +] + +{ #category : #'private - configure reader' } +GitModelImporter >> configureReaderForPipeline: reader [ +] + +{ #category : #'private - configure reader' } +GitModelImporter >> configureReaderForReleases: reader [ +] + +{ #category : #'private - configure reader' } +GitModelImporter >> configureReaderForTags: reader [ +] + +{ #category : #'private - configure reader' } +GitModelImporter >> configureReaderForUsers: reader [ + +] + { #category : #utils } GitModelImporter >> filterCommitChanges: aCollection [ @@ -437,6 +476,20 @@ GitModelImporter >> importUserByUsername: username [ self subclassResponsibility ] +{ #category : #'private - configure reader' } +GitModelImporter >> initReader [ + + generalReader := NeoJSONReader new. + self configureReaderForCommit: generalReader. + self configureReaderForGroup: generalReader. + self configureReaderForDiffs: generalReader. + self configureReaderForMergeRequest: generalReader. + self configureReaderForPipeline: generalReader. + self configureReaderForTags: generalReader. + self configureReaderForReleases: generalReader. + self configureReaderForUsers: generalReader +] + { #category : #initialization } GitModelImporter >> initialize [ @@ -445,6 +498,8 @@ GitModelImporter >> initialize [ userCatalogue := GLHUserCatalogueV2 new anImporter: self; yourself. + + self initReader ] { #category : #initialization } From 40acb6972cf986a2f69d34900eb9467aca25ffba Mon Sep 17 00:00:00 2001 From: HLAD Nicolas Date: Mon, 22 Sep 2025 17:27:06 +0200 Subject: [PATCH 16/52] move up initReader to super class --- src/GitHubHealth-Model-Importer/GithubModelImporter.class.st | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st index 906bcf53..af076b93 100644 --- a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st +++ b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st @@ -550,8 +550,7 @@ GithubModelImporter >> initialize [ self repoApi output: 'json'. self withCommitDiffs: false. withFiles := false. - - self initReader + ] { #category : #parsing } From dbe32af10c4480b3ec1311ac0bcd4e1082ee1cc8 Mon Sep 17 00:00:00 2001 From: HLAD Nicolas Date: Mon, 22 Sep 2025 17:50:54 +0200 Subject: [PATCH 17/52] initiate refactoring naming convention for Readers --- .../GithubModelImporter.class.st | 87 +++++++++---------- .../GitlabModelImporter.class.st | 18 ++-- .../GitModelImporter.class.st | 54 ++++++++++-- 3 files changed, 92 insertions(+), 67 deletions(-) diff --git a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st index af076b93..a9308343 100644 --- a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st +++ b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st @@ -4,7 +4,7 @@ Class { #category : #'GitHubHealth-Model-Importer' } -{ #category : #accessing } +{ #category : #api } GithubModelImporter >> api [ self @@ -16,7 +16,7 @@ GithubModelImporter >> api [ ^ repoApi ] -{ #category : #accessing } +{ #category : #api } GithubModelImporter >> api: anObject [ self @@ -80,7 +80,7 @@ GithubModelImporter >> completeImportedProject: aGLHProject [ ] { #category : #'private - configure reader' } -GithubModelImporter >> configureReaderForBranches: reader [ +GithubModelImporter >> configureReaderForBranch: reader [ reader mapInstVarsFor: GLHBranch. @@ -89,13 +89,11 @@ GithubModelImporter >> configureReaderForBranches: reader [ mapping mapProperty: #sha getter: [ :branch | #ignore ] - setter: [ :branch :value | - branch sha: (value at: #sha). - ]]. + setter: [ :branch :value | branch sha: (value at: #sha) ] ]. reader - for: #ArrayOfBranches + for: #ArrayOfBranch customDo: [ :customMappting | customMappting listOfElementSchema: GLHBranch ] ] @@ -103,6 +101,8 @@ GithubModelImporter >> configureReaderForBranches: reader [ { #category : #'private - configure reader' } GithubModelImporter >> configureReaderForCommit: reader [ + super configureReaderForCommit: reader. + reader for: GLHCommit do: [ :mapping | mapping mapInstVar: #id to: #sha. mapping mapInstVar: #web_url to: #html_url. @@ -135,19 +135,14 @@ GithubModelImporter >> configureReaderForCommit: reader [ value ifNotNil: [ glhCommit committer_name: (value at: #login) ] ]. (mapping mapInstVar: #parent_ids to: #parents) valueSchema: - #ArrayOfIds ]. + #ArrayOfId ]. reader for: DateAndTime customDo: [ :mapping | mapping decoder: [ :string | DateAndTime fromString: string ] ]. - reader for: #ArrayOfIds customDo: [ :mapping | + reader for: #ArrayOfId customDo: [ :mapping | mapping decoder: [ :parents | - parents collect: [ :parent | parent at: #sha ] ] ]. - - reader - for: #ArrayOfCommits - customDo: [ :customMappting | - customMappting listOfElementSchema: GLHCommit ] + parents collect: [ :parent | parent at: #sha ] ] ] ] { #category : #'private - configure reader' } @@ -183,10 +178,9 @@ GithubModelImporter >> configureReaderForMergeRequest: reader [ { #category : #'private - configure reader' } GithubModelImporter >> configureReaderForProject: reader [ + " reader mapInstVarsFor: GLHProject. " -" reader mapInstVarsFor: GLHProject. " - - reader for: GLHProject do: [ :mapping | + reader for: GLHProject do: [ :mapping | mapping mapInstVar: #name to: #name. mapping mapInstVar: #description to: #description. mapping mapInstVar: #id to: #id. @@ -195,9 +189,9 @@ GithubModelImporter >> configureReaderForProject: reader [ mapping mapInstVar: #topics to: #topics ]. reader - for: #ArrayOfProjects + for: #ArrayOfProject customDo: [ :customMappting | - customMappting listOfElementSchema: GLHProject ]. + customMappting listOfElementSchema: GLHProject ] ] { #category : #private } @@ -212,9 +206,10 @@ GithubModelImporter >> convertApiFileAsFile: aAPIFile [ yourself ] -{ #category : #api } +{ #category : #'import - groups' } GithubModelImporter >> ensureGroupNamed: aGroupName [ + self flag: 'WARNING: group from different platform (github vs gitlab) can share the same name, thus being confused here'. ^ self glhModel detect: [ :a | (a isKindOf: GLHGroup) and: [ a name = aGroupName ] ] @@ -359,7 +354,7 @@ GithubModelImporter >> importDiffOfCommit: aGLHCommit [ unless: self blockForDiffEquality ] -{ #category : #api } +{ #category : #'import - files' } GithubModelImporter >> importDirectoryFiles: aDirectoryFile OfBranch: aBranch [ | result files apiFiles | @@ -381,7 +376,7 @@ GithubModelImporter >> importDirectoryFiles: aDirectoryFile OfBranch: aBranch [ self importDirectoryFiles: file OfBranch: aBranch ] ] -{ #category : #api } +{ #category : #'import - files' } GithubModelImporter >> importFilesOfBranch: aBranch [ | result files apiFiles | @@ -436,7 +431,7 @@ GithubModelImporter >> importLatestPullRequestsOfProject: aGLHProject [ ^ self importLatestMergeRequestsOfProject: aGLHProject ] -{ #category : #'import - merge request' } +{ #category : #'import - merge-requests' } GithubModelImporter >> importMergeRequestsOfProject: aProject [ |response mergeRequests| response := self repoApi @@ -476,6 +471,13 @@ GithubModelImporter >> importProject: aProjectName ofGroup: aGroupName [ ^ projectResult ] +{ #category : #'import - merge-requests' } +GithubModelImporter >> importPullRequestsOfProject: aProject [ + "alias method since PullRequest = MergeRequest in model" + + ^ self importMergeRequestsOfProject: aProject +] + { #category : #'import - groups' } GithubModelImporter >> importRepositoriesOfGroup: groupResult [ "Github Repository = GLHProject" @@ -529,17 +531,7 @@ GithubModelImporter >> importUser: userID [ { #category : #initialization } GithubModelImporter >> initReader [ - generalReader := NeoJSONReader new. - - "will be reuse for all reader next" - generalReader for: DateAndTime customDo: [ :mapping | - mapping decoder: [ :string | - string ifNil: [ nil ] ifNotNil: [ DateAndTime fromString: string ] ] ]. - - - self configureReaderForProject: generalReader. - self configureReaderForCommit: generalReader. - self configureReaderForBranches: generalReader + super initReader. ] { #category : #initialization } @@ -557,7 +549,7 @@ GithubModelImporter >> initialize [ GithubModelImporter >> parseArrayOfProject: arrayOfProjects [ | reader | -" reader := NeoJSONReader on: arrayOfProjects readStream. + " reader := NeoJSONReader on: arrayOfProjects readStream. reader for: #ArrayOfProjects @@ -573,10 +565,9 @@ GithubModelImporter >> parseArrayOfProject: arrayOfProjects [ mapping mapInstVar: #topics to: #topics ]. ^ reader nextAs: #ArrayOfProjects " - reader := generalReader on: arrayOfProjects readStream. - - ^ reader nextAs: #ArrayOfProjects + + ^ reader nextAs: #ArrayOfProject ] { #category : #parsing } @@ -584,8 +575,8 @@ GithubModelImporter >> parseBranchesResult: arrayOfBranch [ | reader | reader := generalReader on: arrayOfBranch readStream. - - ^ reader nextAs: #ArrayOfBranches + + ^ reader nextAs: #ArrayOfBranch ] { #category : #parsing } @@ -606,7 +597,7 @@ GithubModelImporter >> parseCommitsResult: result [ reader := generalReader on: result readStream. - ^ reader nextAs: #ArrayOfCommits + ^ reader nextAs: #ArrayOfCommit ] { #category : #parsing } @@ -679,16 +670,16 @@ GithubModelImporter >> parsePipelinesResult: pipelineOverview [ | reader | reader := NeoJSONReader on: pipelineOverview readStream. - + reader for: GHAPIPipelineOverview do: [ :mapping | mapping mapInstVar: #total_count to: #total_count. - (mapping mapInstVar: #workflow_runs) valueSchema: #ArrayOfPipelines ]. - + (mapping mapInstVar: #workflow_runs) valueSchema: #ArrayOfPipeline ]. + reader - for: #ArrayOfPipelines + for: #ArrayOfPipeline customDo: [ :customMappting | customMappting listOfElementSchema: GLHPipeline ]. - + reader for: GLHPipeline do: [ :mapping | mapping mapInstVar: #status to: #conclusion; @@ -696,7 +687,7 @@ GithubModelImporter >> parsePipelinesResult: pipelineOverview [ getter: [ :object | #ignore ] setter: [ :object :value | object runDate: (DateAndTime fromString: value) ] ]. - + ^ reader nextAs: GHAPIPipelineOverview ] diff --git a/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st b/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st index 7c3c2975..e8df7e95 100644 --- a/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st +++ b/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st @@ -185,7 +185,9 @@ GitlabModelImporter >> completeImportedProject: aGLHProject [ { #category : #'private - configure reader' } GitlabModelImporter >> configureReaderForCommit: reader [ - reader for: GLHCommit do: [ :mapping | + super configureReaderForCommit: reader. + + reader for: GLHCommit do: [ :mapping | mapping mapInstVars: #( id short_id title author_name author_email committer_name committer_email message web_url ). @@ -206,16 +208,12 @@ GitlabModelImporter >> configureReaderForCommit: reader [ reader for: #ArrayOfIds customDo: [ :mapping | mapping decoder: [ :string | string ] ]. - - reader - for: #ArrayOfCommit - customDo: [ :customMappting | - customMappting listOfElementSchema: GLHCommit ]. + ] { #category : #'private - configure reader' } -GitlabModelImporter >> configureReaderForDiffs: reader [ +GitlabModelImporter >> configureReaderForDiff: reader [ reader for: GLHDiff do: [ :mapping | mapping mapInstVars: @@ -360,7 +358,7 @@ GitlabModelImporter >> configureReaderForPipeline: reader [ ] { #category : #'private - configure reader' } -GitlabModelImporter >> configureReaderForReleases: reader [ +GitlabModelImporter >> configureReaderForRelease: reader [ reader mapInstVarsFor: GLHRelease . @@ -378,7 +376,7 @@ GitlabModelImporter >> configureReaderForReleases: reader [ ] { #category : #'private - configure reader' } -GitlabModelImporter >> configureReaderForTags: reader [ +GitlabModelImporter >> configureReaderForTag: reader [ reader mapInstVarsFor: GLHTag . @@ -403,7 +401,7 @@ GitlabModelImporter >> configureReaderForTags: reader [ ] { #category : #'private - configure reader' } -GitlabModelImporter >> configureReaderForUsers: reader [ +GitlabModelImporter >> configureReaderForUser: reader [ reader mapInstVarsFor: GLHUser. diff --git a/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st b/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st index 4f09fb08..ae518998 100644 --- a/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st +++ b/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st @@ -214,36 +214,61 @@ GitModelImporter >> completeImportedCommit: aGLHCommit [ GitModelImporter >> completeImportedProject: aGLHProject [ ] +{ #category : #'private - configure reader' } +GitModelImporter >> configureReaderForBranch: reader [ +] + { #category : #'private - configure reader' } GitModelImporter >> configureReaderForCommit: reader [ + + reader + for: #ArrayOfCommit + customDo: [ :customMappting | + customMappting listOfElementSchema: GLHCommit ] ] { #category : #'private - configure reader' } -GitModelImporter >> configureReaderForDiffs: reader [ +GitModelImporter >> configureReaderForDiff: reader [ ] { #category : #'private - configure reader' } GitModelImporter >> configureReaderForGroup: reader [ ] +{ #category : #'private - configure reader' } +GitModelImporter >> configureReaderForIssue: reader [ + + +] + { #category : #'private - configure reader' } GitModelImporter >> configureReaderForMergeRequest: reader [ ] +{ #category : #'private - configure reader' } +GitModelImporter >> configureReaderForMilestone: reader [ + + +] + { #category : #'private - configure reader' } GitModelImporter >> configureReaderForPipeline: reader [ ] { #category : #'private - configure reader' } -GitModelImporter >> configureReaderForReleases: reader [ +GitModelImporter >> configureReaderForProject: reader [ +] + +{ #category : #'private - configure reader' } +GitModelImporter >> configureReaderForRelease: reader [ ] { #category : #'private - configure reader' } -GitModelImporter >> configureReaderForTags: reader [ +GitModelImporter >> configureReaderForTag: reader [ ] { #category : #'private - configure reader' } -GitModelImporter >> configureReaderForUsers: reader [ +GitModelImporter >> configureReaderForUser: reader [ ] @@ -357,7 +382,7 @@ GitModelImporter >> importJobsOf: aGLHPipeline [ self subclassResponsibility ] -{ #category : #'import - merge-requests' } +{ #category : #'import - commits' } GitModelImporter >> importLastestCommitsOfProject: aGLHProject [ "limited to the last 50 commits" self subclassResponsibility @@ -480,14 +505,25 @@ GitModelImporter >> importUserByUsername: username [ GitModelImporter >> initReader [ generalReader := NeoJSONReader new. + + "will be reuse for all reader next" + generalReader for: DateAndTime customDo: [ :mapping | + mapping decoder: [ :string | + string ifNil: [ nil ] ifNotNil: [ DateAndTime fromString: string ] ] ]. + + self configureReaderForCommit: generalReader. self configureReaderForGroup: generalReader. - self configureReaderForDiffs: generalReader. + self configureReaderForDiff: generalReader. self configureReaderForMergeRequest: generalReader. self configureReaderForPipeline: generalReader. - self configureReaderForTags: generalReader. - self configureReaderForReleases: generalReader. - self configureReaderForUsers: generalReader + self configureReaderForTag: generalReader. + self configureReaderForRelease: generalReader. + self configureReaderForUser: generalReader. + self configureReaderForBranch: generalReader. + self configureReaderForIssue: generalReader. + self configureReaderForMilestone: generalReader. + self configureReaderForProject: generalReader. ] { #category : #initialization } From 01c27fe519685ad21a841b07026d62a949a3851a Mon Sep 17 00:00:00 2001 From: HLAD Nicolas Date: Tue, 23 Sep 2025 09:58:09 +0200 Subject: [PATCH 18/52] debug --- .../GithubModelImporter.class.st | 7 +++---- src/GitLabHealth-Model-Analysis/ProjectMetric.class.st | 8 +++----- .../GLHMetamodelGenerator.class.st | 2 +- .../GitlabModelImporter.class.st | 8 +++++--- .../GitModelImporter.class.st | 6 ++++++ 5 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st index a9308343..f7afb7f9 100644 --- a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st +++ b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st @@ -82,6 +82,8 @@ GithubModelImporter >> completeImportedProject: aGLHProject [ { #category : #'private - configure reader' } GithubModelImporter >> configureReaderForBranch: reader [ + super configureReaderForBranch: reader. + reader mapInstVarsFor: GLHBranch. @@ -92,10 +94,7 @@ GithubModelImporter >> configureReaderForBranch: reader [ setter: [ :branch :value | branch sha: (value at: #sha) ] ]. - reader - for: #ArrayOfBranch - customDo: [ :customMappting | - customMappting listOfElementSchema: GLHBranch ] + ] { #category : #'private - configure reader' } diff --git a/src/GitLabHealth-Model-Analysis/ProjectMetric.class.st b/src/GitLabHealth-Model-Analysis/ProjectMetric.class.st index 8eb46d30..f88d88ab 100644 --- a/src/GitLabHealth-Model-Analysis/ProjectMetric.class.st +++ b/src/GitLabHealth-Model-Analysis/ProjectMetric.class.st @@ -25,11 +25,9 @@ ProjectMetric >> loadAllTags [ ] { #category : #load } -ProjectMetric >> loadBranchesSince: since until: until [ - - - ^ glhImporter importBranchesOf: project. - +ProjectMetric >> loadBranchesSince: since until: until [ + self flag: 'must import commits of branches in a separate way'. + ^ glhImporter importBranchesOf: project ] { #category : #loading } diff --git a/src/GitLabHealth-Model-Generator/GLHMetamodelGenerator.class.st b/src/GitLabHealth-Model-Generator/GLHMetamodelGenerator.class.st index 6719aafa..83d3b3f1 100644 --- a/src/GitLabHealth-Model-Generator/GLHMetamodelGenerator.class.st +++ b/src/GitLabHealth-Model-Generator/GLHMetamodelGenerator.class.st @@ -617,7 +617,7 @@ GLHMetamodelGenerator >> releaseRelations [ { #category : #'as yet unclassified' } GLHMetamodelGenerator >> tRefProperties [ "define the properties of a ref instance" - + 1 halt. tRef property: #sha type: #String. tRef property: #name type: #String ] diff --git a/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st b/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st index e8df7e95..13af6cb5 100644 --- a/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st +++ b/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st @@ -548,7 +548,7 @@ GitlabModelImporter >> importBranchesOf: aGLHProject [ "aGLHProject repository branches removeAll " resultBranches := self repoApi branches getAllFromProject: aGLHProject id. - + 1 halt. foundBranches := (resultBranches collect: [ :branchesJson | self parseBranchesResult: branchesJson @@ -1695,10 +1695,12 @@ GitlabModelImporter >> parseBranchesResult: result ofProject: aGLHProject [ getter: [ ] setter: [ :branch :rawCommit | | commit | - commit := self + + branch sha: (rawCommit at: #id). + "commit := self importCommit: (rawCommit at: #id) ofProject: aGLHProject. - branch commits add: commit unless: self blockOnIdEquality ] ]. + branch commits add: commit unless: self blockOnIdEquality "] ]. reader for: #ArrayOfBranch diff --git a/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st b/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st index ae518998..aeb2217e 100644 --- a/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st +++ b/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st @@ -216,6 +216,12 @@ GitModelImporter >> completeImportedProject: aGLHProject [ { #category : #'private - configure reader' } GitModelImporter >> configureReaderForBranch: reader [ + + + reader + for: #ArrayOfBranch + customDo: [ :customMappting | + customMappting listOfElementSchema: GLHBranch ] ] { #category : #'private - configure reader' } From 175603e41d52e7d777429599692c1d1c6df0f38c Mon Sep 17 00:00:00 2001 From: HLAD Nicolas Date: Tue, 23 Sep 2025 10:00:47 +0200 Subject: [PATCH 19/52] add model TRef properties --- .../GLHMetamodelGenerator.class.st | 3 +- src/GitLabHealth-Model/GLHBranch.class.st | 1 + src/GitLabHealth-Model/GLHCommit.class.st | 3 +- src/GitLabHealth-Model/GLHTRef.trait.st | 18 +++++++++++ src/GitLabHealth-Model/GLHTag.class.st | 31 ------------------- 5 files changed, 22 insertions(+), 34 deletions(-) diff --git a/src/GitLabHealth-Model-Generator/GLHMetamodelGenerator.class.st b/src/GitLabHealth-Model-Generator/GLHMetamodelGenerator.class.st index 83d3b3f1..b25e5165 100644 --- a/src/GitLabHealth-Model-Generator/GLHMetamodelGenerator.class.st +++ b/src/GitLabHealth-Model-Generator/GLHMetamodelGenerator.class.st @@ -617,9 +617,8 @@ GLHMetamodelGenerator >> releaseRelations [ { #category : #'as yet unclassified' } GLHMetamodelGenerator >> tRefProperties [ "define the properties of a ref instance" - 1 halt. + tRef property: #sha type: #String. - tRef property: #name type: #String ] { #category : #tags } diff --git a/src/GitLabHealth-Model/GLHBranch.class.st b/src/GitLabHealth-Model/GLHBranch.class.st index 98f108b8..dacc3849 100644 --- a/src/GitLabHealth-Model/GLHBranch.class.st +++ b/src/GitLabHealth-Model/GLHBranch.class.st @@ -26,6 +26,7 @@ A git branch | Name | Type | Default value | Comment | |---| | `name` | `String` | nil | Basic name of the entity, not full reference.| +| `sha` | `String` | nil | | " Class { diff --git a/src/GitLabHealth-Model/GLHCommit.class.st b/src/GitLabHealth-Model/GLHCommit.class.st index aa2e6d9c..13d2c100 100644 --- a/src/GitLabHealth-Model/GLHCommit.class.st +++ b/src/GitLabHealth-Model/GLHCommit.class.st @@ -21,8 +21,8 @@ a commit attached to a repository |---| | `branch` | `GLHCommit` | `commits` | `GLHBranch` | | | `childCommits` | `GLHCommit` | `parentCommits` | `GLHCommit` | | -| `commitedMergeRequest` | `GLHCommit` | `mergedCommit` | `GLHMergeRequest` | | | `commitedMergeRequest` | `GLHCommit` | `mergeRequestCommit` | `GLHMergeRequest` | | +| `commitedMergeRequest` | `GLHCommit` | `mergedCommit` | `GLHMergeRequest` | | | `parentCommits` | `GLHCommit` | `childCommits` | `GLHCommit` | | | `squashedMergeRequest` | `GLHCommit` | `squashCommit` | `GLHMergeRequest` | | | `tag` | `GLHCommit` | `commit` | `GLHTag` | | @@ -46,6 +46,7 @@ a commit attached to a repository | `message` | `String` | nil | | | `name` | `String` | nil | Basic name of the entity, not full reference.| | `parent_ids` | `Object` | 'OrderedCollection new' | | +| `sha` | `String` | nil | | | `short_id` | `String` | nil | | | `title` | `String` | nil | | | `web_url` | `String` | nil | | diff --git a/src/GitLabHealth-Model/GLHTRef.trait.st b/src/GitLabHealth-Model/GLHTRef.trait.st index b5e9154c..aae54e5e 100644 --- a/src/GitLabHealth-Model/GLHTRef.trait.st +++ b/src/GitLabHealth-Model/GLHTRef.trait.st @@ -7,10 +7,14 @@ I'm representing a Git reference, that is a reference point in a repository's hi | Name | Type | Default value | Comment | |---| | `name` | `String` | nil | Basic name of the entity, not full reference.| +| `sha` | `String` | nil | | " Trait { #name : #GLHTRef, + #instVars : [ + '#sha => FMProperty' + ], #traits : 'FamixTNamedEntity', #classTraits : 'FamixTNamedEntity classTrait', #category : #'GitLabHealth-Model-Traits' @@ -31,3 +35,17 @@ GLHTRef >> isRef [ ^ true ] + +{ #category : #accessing } +GLHTRef >> sha [ + + + + ^ sha +] + +{ #category : #accessing } +GLHTRef >> sha: anObject [ + + sha := anObject +] diff --git a/src/GitLabHealth-Model/GLHTag.class.st b/src/GitLabHealth-Model/GLHTag.class.st index 7c331c0a..8715d8b0 100644 --- a/src/GitLabHealth-Model/GLHTag.class.st +++ b/src/GitLabHealth-Model/GLHTag.class.st @@ -23,7 +23,6 @@ a Tag is a reference to a specific point in the repository's history |---| | `created_at` | `Object` | nil | | | `message` | `String` | nil | | -| `name` | `String` | nil | | | `name` | `String` | nil | Basic name of the entity, not full reference.| | `protected` | `Boolean` | nil | | | `sha` | `String` | nil | | @@ -40,8 +39,6 @@ Class { '#target => FMProperty', '#protected => FMProperty', '#created_at => FMProperty', - '#sha => FMProperty', - '#name => FMProperty', '#commit => FMOne type: #GLHCommit opposite: #tag', '#release => FMOne type: #GLHRelease opposite: #tag', '#repository => FMOne type: #GLHRepository opposite: #tags' @@ -101,20 +98,6 @@ GLHTag >> message: anObject [ message := anObject ] -{ #category : #accessing } -GLHTag >> name [ - - - - ^ name -] - -{ #category : #accessing } -GLHTag >> name: anObject [ - - name := anObject -] - { #category : #accessing } GLHTag >> protected [ @@ -167,20 +150,6 @@ GLHTag >> repositoryGroup [ ^ MooseSpecializedGroup with: self repository ] -{ #category : #accessing } -GLHTag >> sha [ - - - - ^ sha -] - -{ #category : #accessing } -GLHTag >> sha: anObject [ - - sha := anObject -] - { #category : #accessing } GLHTag >> target [ From 987b1a8ad0863985d8a342aa1911be7276d8114d Mon Sep 17 00:00:00 2001 From: HLAD Nicolas Date: Tue, 23 Sep 2025 10:27:06 +0200 Subject: [PATCH 20/52] fix branch loading commits --- .../GLPHImporterMock.class.st | 5 ++++ .../ActiveBranchesProjectMetric.class.st | 25 ++++++++----------- .../ProjectMetric.class.st | 9 +++++-- .../GitlabModelImporter.class.st | 11 ++------ .../GitModelImporter.class.st | 19 ++++++++++++++ 5 files changed, 44 insertions(+), 25 deletions(-) diff --git a/src/GitLabHealth-Model-Analysis-Tests/GLPHImporterMock.class.st b/src/GitLabHealth-Model-Analysis-Tests/GLPHImporterMock.class.st index db667ab3..f89adf80 100644 --- a/src/GitLabHealth-Model-Analysis-Tests/GLPHImporterMock.class.st +++ b/src/GitLabHealth-Model-Analysis-Tests/GLPHImporterMock.class.st @@ -123,6 +123,11 @@ GLPHImporterMock >> importNotesOfMergeRequest: mriid [ ^OrderedCollection with: (notes select: [ :note | (note noteable_iid == mriid) ]) ] +{ #category : #'as yet unclassified' } +GLPHImporterMock >> importRefCommitOfBranch: aGLHBranch [ + ^ aGLHBranch +] + { #category : #'import - tag' } GLPHImporterMock >> importTagsForProject: aGLHProject [ ^ tags. diff --git a/src/GitLabHealth-Model-Analysis/ActiveBranchesProjectMetric.class.st b/src/GitLabHealth-Model-Analysis/ActiveBranchesProjectMetric.class.st index 91054c6b..5777f2c0 100644 --- a/src/GitLabHealth-Model-Analysis/ActiveBranchesProjectMetric.class.st +++ b/src/GitLabHealth-Model-Analysis/ActiveBranchesProjectMetric.class.st @@ -8,27 +8,24 @@ Class { ActiveBranchesProjectMetric >> calculate [ | groupedByDate | - + projectBranches ifNil: [ self load ]. - - projectBranches ifNil:[ self load]. - - - - groupedByDate := self setupGroupedDate. - + "convert group collect to set, to ensure no duplicated data" - groupedByDate keys do: [ :key | groupedByDate at: key put: Set new]. - + groupedByDate keys do: [ :key | groupedByDate at: key put: Set new ]. + projectBranches do: [ :branch | - | dateOver commit| + | dateOver commit | "sort commits by ASC date" - commit := (branch commits sort: [ :c1 :c2 | c1 created_at > c2 created_at]) first. - + commit := (branch commits sort: [ :c1 :c2 | + c1 created_at > c2 created_at ]) first. + dateOver := self transformDate: commit created_at to: over. - groupedByDate at: dateOver printString ifPresent: [ :v | v add: commit created_at ] ]. + groupedByDate + at: dateOver printString + ifPresent: [ :v | v add: commit created_at ] ]. groupedByDate := groupedByDate collect: [ :group | group size ]. diff --git a/src/GitLabHealth-Model-Analysis/ProjectMetric.class.st b/src/GitLabHealth-Model-Analysis/ProjectMetric.class.st index f88d88ab..a5e2b9de 100644 --- a/src/GitLabHealth-Model-Analysis/ProjectMetric.class.st +++ b/src/GitLabHealth-Model-Analysis/ProjectMetric.class.st @@ -26,8 +26,13 @@ ProjectMetric >> loadAllTags [ { #category : #load } ProjectMetric >> loadBranchesSince: since until: until [ - self flag: 'must import commits of branches in a separate way'. - ^ glhImporter importBranchesOf: project + + | branches | + branches := glhImporter importBranchesOf: project. + + + branches do: [ :branch | glhImporter importRefCommitOfBranch: branch ]. + ^ branches ] { #category : #loading } diff --git a/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st b/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st index 13af6cb5..bd1bdd11 100644 --- a/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st +++ b/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st @@ -548,7 +548,7 @@ GitlabModelImporter >> importBranchesOf: aGLHProject [ "aGLHProject repository branches removeAll " resultBranches := self repoApi branches getAllFromProject: aGLHProject id. - 1 halt. + foundBranches := (resultBranches collect: [ :branchesJson | self parseBranchesResult: branchesJson @@ -561,19 +561,12 @@ GitlabModelImporter >> importBranchesOf: aGLHProject [ addAll: foundBranches unless: self blockOnNameEquality. - foundBranches do: [ :fb | - branches do: [ :b | - fb name = b name ifTrue: [ - b commits addAll: fb commits unless: self blockOnIdEquality ] ] ]. branches := self glhModel addAll: branches unless: self blockForBranchEquality. - branches do: [ :b | - b commits do: [ :c | - b repository commits add: c unless: self blockOnIdEquality ] ]. - + "WARNING : branch must load its HEAD commit (ref) in a second time " ^ branches ] diff --git a/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st b/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st index aeb2217e..8085dbde 100644 --- a/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st +++ b/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st @@ -331,6 +331,13 @@ GitModelImporter >> importCommit: aCommitID ofProject: aGLHProject [ self subclassResponsibility ] +{ #category : #'import - commits' } +GitModelImporter >> importCommitsOfBranch: aGLHBranch [ + self subclassResponsibility + + +] + { #category : #'import - commits' } GitModelImporter >> importCommitsOfProject: aGLHProject since: since until: until [ @@ -486,6 +493,18 @@ GitModelImporter >> importProjectsOfUser: aGLHUser [ self subclassResponsibility ] +{ #category : #'as yet unclassified' } +GitModelImporter >> importRefCommitOfBranch: aGLHBranch [ + |commit| + commit := self + importCommit: aGLHBranch sha + ofProject: aGLHBranch repository project. + commit := aGLHBranch commits + add: commit + unless: self blockOnIdEquality. + ^ commit +] + { #category : #'import - releases' } GitModelImporter >> importRelease: aReleaseID ofProject: aGLHProject [ self subclassResponsibility From 47f4a2b177856a9840f72efdbb289245d55dc3a5 Mon Sep 17 00:00:00 2001 From: HLAD Nicolas Date: Tue, 23 Sep 2025 10:54:53 +0200 Subject: [PATCH 21/52] refactoring configuration reader to super class with default implementation --- .../GithubModelImporter.class.st | 10 +-- .../GitlabModelImporterRemoteTest.class.st | 2 +- .../GitlabModelImporter.class.st | 51 +++++++++---- .../GitModelImporter.class.st | 73 +++++++++++++++++-- 4 files changed, 105 insertions(+), 31 deletions(-) diff --git a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st index f7afb7f9..19f8aa54 100644 --- a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st +++ b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st @@ -82,19 +82,13 @@ GithubModelImporter >> completeImportedProject: aGLHProject [ { #category : #'private - configure reader' } GithubModelImporter >> configureReaderForBranch: reader [ - super configureReaderForBranch: reader. - - reader mapInstVarsFor: GLHBranch. - + super configureReaderForBranch: reader. reader for: GLHBranch do: [ :mapping | mapping mapProperty: #sha getter: [ :branch | #ignore ] - setter: [ :branch :value | branch sha: (value at: #sha) ] ]. - - - + setter: [ :branch :value | branch sha: (value at: #sha) ] ] ] { #category : #'private - configure reader' } diff --git a/src/GitLabHealth-Model-Importer-Tests/GitlabModelImporterRemoteTest.class.st b/src/GitLabHealth-Model-Importer-Tests/GitlabModelImporterRemoteTest.class.st index 9e02b794..1764e285 100644 --- a/src/GitLabHealth-Model-Importer-Tests/GitlabModelImporterRemoteTest.class.st +++ b/src/GitLabHealth-Model-Importer-Tests/GitlabModelImporterRemoteTest.class.st @@ -67,7 +67,7 @@ GitlabModelImporterRemoteTest >> testImportCommits [ | projectTestCodeChurn | projectTestCodeChurn := (self model allWithType: GLHProject) detect: [ :project | project id = 57841283 ]. - self glhImporter importLastestCommitsOfProject: projectTestCodeChurn. + self glhImporter importLatestCommitsOfProject: projectTestCodeChurn. self assert: projectTestCodeChurn repository commits last author_name diff --git a/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st b/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st index bd1bdd11..206d022e 100644 --- a/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st +++ b/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st @@ -182,6 +182,18 @@ GitlabModelImporter >> completeImportedProject: aGLHProject [ ] +{ #category : #'private - configure reader' } +GitlabModelImporter >> configureReaderForBranch: reader [ + + super configureReaderForBranch: reader. + + reader for: GLHBranch do: [ :mapping | + mapping + mapProperty: #commit + getter: [ ] + setter: [ :branch :rawCommit | branch sha: (rawCommit at: #id) ] ]. +] + { #category : #'private - configure reader' } GitlabModelImporter >> configureReaderForCommit: reader [ @@ -215,15 +227,14 @@ GitlabModelImporter >> configureReaderForCommit: reader [ { #category : #'private - configure reader' } GitlabModelImporter >> configureReaderForDiff: reader [ - reader for: GLHDiff do: [ :mapping | - mapping mapInstVars: - #( deleted_file new_file new_path old_path renamed_file ). - mapping mapInstVar: #diffString to: #diff ]. - + super configureReaderForDiff: reader. reader - for: #ArrayOfDiffs - customDo: [ :customMappting | - customMappting listOfElementSchema: GLHDiff ]. + for: GLHDiff + do: [ :mapping | + "mapping mapInstVars: + #( deleted_file new_file new_path old_path renamed_file )." + mapping mapInstVar: #diffString to: #diff ]. + ^ reader ] @@ -519,7 +530,7 @@ GitlabModelImporter >> importAndLoadLatestsCommitsOfProject: aGLHProject [ | commits completedProject | completedProject := self completeImportedProject: aGLHProject. - commits := self importLastestCommitsOfProject: completedProject. + commits := self importLatestCommitsOfProject: completedProject. commits do: [ :commit | self completeImportedCommit: commit ]. self chainsCommitsFrom: commits. ^ commits @@ -541,7 +552,7 @@ GitlabModelImporter >> importAuthorOfCommit: aGLHCommit [ ^ user ] -{ #category : #'import - repositories' } +{ #category : #'import - branches' } GitlabModelImporter >> importBranchesOf: aGLHProject [ | resultBranches branches foundBranches | @@ -1040,7 +1051,7 @@ GitlabModelImporter >> importJobsOf: aPipeline [ ] { #category : #'import - commits' } -GitlabModelImporter >> importLastestCommitsOfProject: aGLHProject [ +GitlabModelImporter >> importLatestCommitsOfProject: aGLHProject [ "limited to the last 50 commits" | results parsedResults params | @@ -1653,7 +1664,7 @@ GitlabModelImporter >> newParseCommitResult: result [ GitlabModelImporter >> newParseDiffResult: result [ generalReader on: result readStream. - ^ generalReader nextAs: #ArrayOfDiffs + ^ generalReader nextAs: #ArrayOfDiff ] { #category : #'private - parsing' } @@ -1675,6 +1686,16 @@ GitlabModelImporter >> parseArrayOfProject: arrayOfProjects [ ^ reader nextAs: #ArrayOfProjects ] +{ #category : #'private - parsing' } +GitlabModelImporter >> parseBranchesResult: result [ + + | reader | + reader := generalReader on: result readStream. + + + ^ reader nextAs: #ArrayOfBranch +] + { #category : #'private - parsing' } GitlabModelImporter >> parseBranchesResult: result ofProject: aGLHProject [ @@ -1687,13 +1708,11 @@ GitlabModelImporter >> parseBranchesResult: result ofProject: aGLHProject [ mapProperty: #commit getter: [ ] setter: [ :branch :rawCommit | - | commit | - - branch sha: (rawCommit at: #id). + branch sha: (rawCommit at: #id) "commit := self importCommit: (rawCommit at: #id) ofProject: aGLHProject. - branch commits add: commit unless: self blockOnIdEquality "] ]. + branch commits add: commit unless: self blockOnIdEquality " ] ]. reader for: #ArrayOfBranch diff --git a/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st b/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st index 8085dbde..c8ffe614 100644 --- a/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st +++ b/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st @@ -216,8 +216,9 @@ GitModelImporter >> completeImportedProject: aGLHProject [ { #category : #'private - configure reader' } GitModelImporter >> configureReaderForBranch: reader [ - - + + reader mapInstVarsFor: GLHBranch. + reader for: #ArrayOfBranch customDo: [ :customMappting | @@ -226,7 +227,9 @@ GitModelImporter >> configureReaderForBranch: reader [ { #category : #'private - configure reader' } GitModelImporter >> configureReaderForCommit: reader [ - + + reader mapInstVarsFor: GLHCommit . + reader for: #ArrayOfCommit customDo: [ :customMappting | @@ -235,6 +238,13 @@ GitModelImporter >> configureReaderForCommit: reader [ { #category : #'private - configure reader' } GitModelImporter >> configureReaderForDiff: reader [ + + reader mapInstVarsFor: GLHDiff. + + reader + for: #ArrayOfDiff + customDo: [ :customMappting | + customMappting listOfElementSchema: GLHDiff ] ] { #category : #'private - configure reader' } @@ -244,38 +254,89 @@ GitModelImporter >> configureReaderForGroup: reader [ { #category : #'private - configure reader' } GitModelImporter >> configureReaderForIssue: reader [ - + reader mapInstVarsFor: GLHIssue. + + reader + for: #ArrayOfIssue + customDo: [ :customMappting | + customMappting listOfElementSchema: GLHIssue ] ] { #category : #'private - configure reader' } GitModelImporter >> configureReaderForMergeRequest: reader [ + + reader mapInstVarsFor: GLHMergeRequest. + + reader + for: #ArrayOfMergeRequest + customDo: [ :customMappting | + customMappting listOfElementSchema: GLHMergeRequest ] ] { #category : #'private - configure reader' } GitModelImporter >> configureReaderForMilestone: reader [ - + reader mapInstVarsFor: GLHMilestone. + + reader + for: #ArrayOfMilestone + customDo: [ :customMappting | + customMappting listOfElementSchema: GLHMilestone ] ] { #category : #'private - configure reader' } GitModelImporter >> configureReaderForPipeline: reader [ + + reader mapInstVarsFor: GLHPipeline. + + reader + for: #ArrayOfPipeline + customDo: [ :customMappting | + customMappting listOfElementSchema: GLHPipeline ] ] { #category : #'private - configure reader' } GitModelImporter >> configureReaderForProject: reader [ + + reader mapInstVarsFor: GLHProject. + + reader + for: #ArrayOfProject + customDo: [ :customMappting | + customMappting listOfElementSchema: GLHProject ] ] { #category : #'private - configure reader' } GitModelImporter >> configureReaderForRelease: reader [ + + reader mapInstVarsFor: GLHRelease. + + reader + for: #ArrayOfRelease + customDo: [ :customMappting | + customMappting listOfElementSchema: GLHRelease ] ] { #category : #'private - configure reader' } GitModelImporter >> configureReaderForTag: reader [ + + reader mapInstVarsFor: GLHTag. + + reader + for: #ArrayOfTag + customDo: [ :customMappting | + customMappting listOfElementSchema: GLHTag ] ] { #category : #'private - configure reader' } GitModelImporter >> configureReaderForUser: reader [ + reader mapInstVarsFor: GLHUser. + + reader + for: #ArrayOfUser + customDo: [ :customMappting | + customMappting listOfElementSchema: GLHUser ] ] { #category : #utils } @@ -396,7 +457,7 @@ GitModelImporter >> importJobsOf: aGLHPipeline [ ] { #category : #'import - commits' } -GitModelImporter >> importLastestCommitsOfProject: aGLHProject [ +GitModelImporter >> importLatestCommitsOfProject: aGLHProject [ "limited to the last 50 commits" self subclassResponsibility ] From 292f2d7acaaf510162f453116d24053e1f2fb465 Mon Sep 17 00:00:00 2001 From: HLAD Nicolas Date: Tue, 23 Sep 2025 11:10:18 +0200 Subject: [PATCH 22/52] super reader for group and project --- .../GitlabModelImporter.class.st | 146 ++++++++---------- .../GitModelImporter.class.st | 7 + 2 files changed, 73 insertions(+), 80 deletions(-) diff --git a/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st b/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st index 206d022e..191261d1 100644 --- a/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st +++ b/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st @@ -241,18 +241,12 @@ GitlabModelImporter >> configureReaderForDiff: reader [ { #category : #'private - configure reader' } GitlabModelImporter >> configureReaderForGroup: reader [ + super configureReaderForGroup: reader. + reader for: GLHGroup do: [ :mapping | - mapping mapInstVars. (mapping mapInstVar: #projects) valueSchema: #ArrayOfProjects ]. - reader mapInstVarsFor: GLHProject. - reader - for: #ArrayOfProjects - customDo: [ :customMappting | - customMappting listOfElementSchema: GLHProject ]. - reader - for: #ArrayOfGroups - customDo: [ :customMappting | - customMappting listOfElementSchema: GLHGroup ] + + ] { #category : #'private - configure reader' } @@ -308,64 +302,69 @@ GitlabModelImporter >> configureReaderForMergeRequest: reader [ GitlabModelImporter >> configureReaderForPipeline: reader [ reader mapInstVarsFor: GLHPipeline. - - reader for: GLHPipeline do: [ :mapping | + reader for: GLHPipeline do: [ :mapping | mapping mapProperty: #created_at getter: [ :object | #ignore ] setter: [ :object :value | - object created_at: (value ifNotNil: [DateAndTime fromString: value]). - object runDate: (value ifNotNil: [DateAndTime fromString: value]) ]. - + object created_at: + (value ifNotNil: [ DateAndTime fromString: value ]). + object runDate: + (value ifNotNil: [ DateAndTime fromString: value ]) ]. + mapping mapProperty: #updated_at getter: [ :object | #ignore ] setter: [ :object :value | - object updated_at: (value ifNotNil: [DateAndTime fromString: value]). - ]. - + object updated_at: + (value ifNotNil: [ DateAndTime fromString: value ]) ]. + mapping mapProperty: #finished_at getter: [ :object | #ignore ] setter: [ :object :value | - object finished_at: (value ifNotNil: [DateAndTime fromString: value]). - ]. - + object finished_at: + (value ifNotNil: [ DateAndTime fromString: value ]) ]. + mapping - mapProperty: #started_at + mapProperty: #started_at getter: [ :object | #ignore ] setter: [ :object :value | - object started_at: (value ifNotNil: [DateAndTime fromString: value]). - ]. - + object started_at: + (value ifNotNil: [ DateAndTime fromString: value ]) ]. + mapping mapProperty: #source getter: [ :object | #ignore ] - setter: [ :object :value | - object sourceEvent: value. - ]. - + setter: [ :object :value | object sourceEvent: value ]. + mapping mapProperty: #duration getter: [ :object | #ignore ] setter: [ :object :value | - object duration: (value ifNotNil: [value asDuration]) . - ]. - + object duration: (value ifNotNil: [ value asDuration ]) ]. + mapping mapProperty: #user getter: [ :object | #ignore ] setter: [ :object :value | - value ifNotNil: [object cacheAt: #userID put: (value at: #id)]. - ]. - - ]. - + value ifNotNil: [ object cacheAt: #userID put: (value at: #id) ] ] ]. + reader - for: #ArrayOfPipelines + for: #ArrayOfPipeline customDo: [ :customMappting | - customMappting listOfElementSchema: GLHPipeline ]. + customMappting listOfElementSchema: GLHPipeline ] +] + +{ #category : #'private - configure reader' } +GitlabModelImporter >> configureReaderForProject: reader [ + + super configureReaderForProject: reader. + + reader for: GLHProject do: [ :mapping | + mapping mapInstVar: #web_url to: #html_url. + ]. ] { #category : #'private - configure reader' } @@ -559,11 +558,11 @@ GitlabModelImporter >> importBranchesOf: aGLHProject [ "aGLHProject repository branches removeAll " resultBranches := self repoApi branches getAllFromProject: aGLHProject id. - + foundBranches := (resultBranches collect: [ :branchesJson | self parseBranchesResult: branchesJson - ofProject: aGLHProject ]) flattened. + ]) flattened. 'import the branches of project ' recordInfo. @@ -1671,19 +1670,9 @@ GitlabModelImporter >> newParseDiffResult: result [ GitlabModelImporter >> parseArrayOfProject: arrayOfProjects [ | reader | - reader := NeoJSONReader on: arrayOfProjects readStream. - reader - for: #ArrayOfProjects - customDo: [ :customMappting | - customMappting listOfElementSchema: GLHProject ]. - reader for: GLHProject do: [ :mapping | - mapping mapInstVar: #name to: #name. - mapping mapInstVar: #description to: #description. - mapping mapInstVar: #id to: #id. - mapping mapInstVar: #archived to: #archived. - mapping mapInstVar: #web_url to: #html_url. - mapping mapInstVar: #topics to: #topics ]. - ^ reader nextAs: #ArrayOfProjects + reader := generalReader on: arrayOfProjects readStream. + + ^ reader nextAs: #ArrayOfProject ] { #category : #'private - parsing' } @@ -1700,6 +1689,13 @@ GitlabModelImporter >> parseBranchesResult: result [ GitlabModelImporter >> parseBranchesResult: result ofProject: aGLHProject [ | reader | + self + deprecated: 'Use parseBranchesResult: instead of current one' + on: '23 September 2025' + in: + 'Pharo-12.0.0+SNAPSHOT.build.1571.sha.cf5fcd22e66957962c97dffc58b0393b7f368147 (64 Bit)'. + + reader := NeoJSONReader on: result readStream. reader mapInstVarsFor: GLHBranch. @@ -1829,16 +1825,8 @@ GitlabModelImporter >> parseFileTreeResult: aResult [ GitlabModelImporter >> parseGroupResult: aResult [ | reader | + reader := generalReader on: aResult readStream. - reader := NeoJSONReader on: aResult readStream. - reader for: GLHGroup do: [ :mapping | - mapping mapInstVars. - (mapping mapInstVar: #projects) valueSchema: #ArrayOfProjects ]. - reader mapInstVarsFor: GLHProject. - reader - for: #ArrayOfProjects - customDo: [ :customMappting | - customMappting listOfElementSchema: GLHProject ]. ^ reader nextAs: GLHGroup ] @@ -1933,21 +1921,18 @@ GitlabModelImporter >> parsePipelineResult: result [ GitlabModelImporter >> parsePipelinesResult: result [ | reader | - - (result includesSubstring: '{"message":"40' )ifTrue: [ ^ { } ]. - + (result includesSubstring: '{"message":"40') ifTrue: [ ^ { } ]. + reader := generalReader on: result readStream. - - ^ reader nextAs: #ArrayOfPipelines + + ^ reader nextAs: #ArrayOfPipeline ] { #category : #'private - parsing' } -GitlabModelImporter >> parseProjectResult: aResult [ - | reader | - reader := NeoJSONReader on: aResult readStream. - reader for: GLHProject do: [ :mapping | - mapping mapInstVars. ]. -" reader mapInstVarsFor: GLHProject." +GitlabModelImporter >> parseProjectResult: aResult [ + + | reader | + reader := generalReader on: aResult readStream. ^ reader nextAs: GLHProject ] @@ -1962,19 +1947,20 @@ GitlabModelImporter >> parseReleaseResult: result [ { #category : #'private - parsing' } GitlabModelImporter >> parseReleasesResult: result [ - |reader| + + | reader | reader := generalReader on: result readStream. - - ^ reader nextAs: #ArrayOfReleases + + ^ reader nextAs: #ArrayOfRelease ] { #category : #'private - parsing' } GitlabModelImporter >> parseSubGroupResult: aResult [ | reader | - reader := NeoJSONReader on: aResult readStream. - self configureReaderForGroup: reader. - ^ reader nextAs: #ArrayOfGroups + reader := generalReader on: aResult readStream. + + ^ reader nextAs: #ArrayOfGroup ] { #category : #'private - parsing' } diff --git a/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st b/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st index c8ffe614..cdd817ba 100644 --- a/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st +++ b/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st @@ -249,6 +249,13 @@ GitModelImporter >> configureReaderForDiff: reader [ { #category : #'private - configure reader' } GitModelImporter >> configureReaderForGroup: reader [ + + reader mapInstVarsFor: GLHGroup. + + reader + for: #ArrayOfGroup + customDo: [ :customMappting | + customMappting listOfElementSchema: GLHGroup ] ] { #category : #'private - configure reader' } From 2883c8372a5e0a4510267e9881d76fd09ccffa31 Mon Sep 17 00:00:00 2001 From: HLAD Nicolas Date: Tue, 23 Sep 2025 11:17:21 +0200 Subject: [PATCH 23/52] fix reader declaration --- .../GithubModelImporter.class.st | 5 +---- .../GitlabModelImporter.class.st | 6 ++---- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st index 19f8aa54..3995210a 100644 --- a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st +++ b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st @@ -624,10 +624,7 @@ GithubModelImporter >> parseGroupResult: aResult [ | reader | reader := NeoJSONReader on: aResult readStream. - reader for: GLHGroup do: [ :mapping | - mapping mapInstVar: #name to: #login. - mapping mapInstVar: #description to: #description. - mapping mapInstVar: #id to: #id. + reader for: GLHGroup do: [ :mapping | mapping mapInstVar: #web_url to: #html_url ]. ^ reader nextAs: GLHGroup ] diff --git a/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st b/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st index 191261d1..ab94aaea 100644 --- a/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st +++ b/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st @@ -241,12 +241,10 @@ GitlabModelImporter >> configureReaderForDiff: reader [ { #category : #'private - configure reader' } GitlabModelImporter >> configureReaderForGroup: reader [ - super configureReaderForGroup: reader. + super configureReaderForGroup: reader. reader for: GLHGroup do: [ :mapping | - (mapping mapInstVar: #projects) valueSchema: #ArrayOfProjects ]. - - + (mapping mapInstVar: #projects) valueSchema: #ArrayOfProject ] ] { #category : #'private - configure reader' } From ac91f8eaff48255aed9734fe9a7ab694b2bf6605 Mon Sep 17 00:00:00 2001 From: HLAD Nicolas Date: Tue, 23 Sep 2025 11:53:16 +0200 Subject: [PATCH 24/52] Fix readers for Commit, MR, Note, pipeline, release, user --- .../GithubModelImporter.class.st | 11 +- .../GitlabModelImporter.class.st | 148 +++++++----------- .../GitModelImporter.class.st | 22 ++- 3 files changed, 74 insertions(+), 107 deletions(-) diff --git a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st index 3995210a..402f9bca 100644 --- a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st +++ b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st @@ -142,8 +142,9 @@ GithubModelImporter >> configureReaderForCommit: reader [ GithubModelImporter >> configureReaderForMergeRequest: reader [ " reader mapInstVarsFor: GLHProject. " + super configureReaderForMergeRequest: reader. + reader for: GLHMergeRequest do: [ :mapping | - (mapping mapInstVar: #created_at) valueSchema: DateAndTime. (mapping mapInstVar: #updated_at) valueSchema: DateAndTime. (mapping mapInstVar: #merged_at) valueSchema: DateAndTime. @@ -159,13 +160,9 @@ GithubModelImporter >> configureReaderForMergeRequest: reader [ getter: [ ] setter: [ :object :value | value ifNotNil: [ - object cacheAt: #mergeUserID put: (value at: #id) ] ] - - ]. - + object cacheAt: #mergeUserID put: (value at: #id) ] ] ]. + - reader for: #ArrayOfMergeRequest customDo: [ :customMappting | - customMappting listOfElementSchema: GLHMergeRequest ]. ] diff --git a/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st b/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st index ab94aaea..3d242e26 100644 --- a/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st +++ b/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st @@ -214,9 +214,6 @@ GitlabModelImporter >> configureReaderForCommit: reader [ commit deletions: (value at: #deletions). commit additions: (value at: #additions) ] ]. - reader for: DateAndTime customDo: [ :mapping | - mapping decoder: [ :string | DateAndTime fromString: string ] ]. - reader for: #ArrayOfIds customDo: [ :mapping | mapping decoder: [ :string | string ] ]. @@ -250,56 +247,49 @@ GitlabModelImporter >> configureReaderForGroup: reader [ { #category : #'private - configure reader' } GitlabModelImporter >> configureReaderForMergeRequest: reader [ "declare quil y a un array a mapper" - - reader for: #ArrayOfMergeRequest customDo: [ :customMappting | - customMappting listOfElementSchema: GLHMergeRequest ]. + self flag: 'assignee.s must be parsed with nil condition'. + super configureReaderForMergeRequest: reader. "declare la liste des properties" - reader for: GLHMergeRequest do: [ :mapping | - mapping mapInstVars: - #( blocking_discussions_resolved changes_count description - detailed_merge_status discussion_locked downvotes draft first_deployed_to_production_at - force_remove_source_branch has_conflicts id iid labels latest_build_finished_at - latest_build_started_at merge_commit_sha merge_status - merge_when_pipeline_succeeds merged_at milestone project_id - reference references_full references_relative - references_short sha should_remove_source_branch - source_branch source_project_id squash squash_commit_sha - squash_on_merge state subscribed target_branch target_project_id - task_completion_status_completed_count - task_completion_status_count time_stats_human_time_estimate - time_stats_human_total_time_spent - time_stats_time_estimate time_stats_total_time_spent - title updated_at upvotes user_notes_count web_url work_in_progress ). - (mapping mapInstVar: #created_at) valueSchema: DateAndTime. - (mapping mapInstVar: #updated_at) valueSchema: DateAndTime. - (mapping mapInstVar: #merged_at) valueSchema: DateAndTime. - (mapping mapInstVar: #closed_at) valueSchema: DateAndTime. - "(mapping mapInstVar: #assignee) valueSchema: GLHUser." - mapping - mapProperty: #author - getter: [ ] - setter: [ :object :value | - object cacheAt: #authorID put: (value at: #id) ]. - mapping - mapProperty: #merge_user - getter: [ ] - setter: [ :object :value | - value ifNotNil: [ - object cacheAt: #mergeUserID put: (value at: #id) ] ] ]. + reader + for: GLHMergeRequest + do: [ :mapping | + + "(mapping mapInstVar: #assignee) valueSchema: GLHUser." + "(mapping mapInstVar: #assignees) valueSchema: #ArrayOfUser." + (mapping mapInstVar: #created_at) valueSchema: DateAndTime. + (mapping mapInstVar: #updated_at) valueSchema: DateAndTime. + (mapping mapInstVar: #merged_at) valueSchema: DateAndTime. + (mapping mapInstVar: #closed_at) valueSchema: DateAndTime. + + mapping + mapProperty: #author + getter: [ ] + setter: [ :object :value | + object cacheAt: #authorID put: (value at: #id) ]. + mapping + mapProperty: #merge_user + getter: [ ] + setter: [ :object :value | + value ifNotNil: [ + object cacheAt: #mergeUserID put: (value at: #id) ] ] ] +] - "(mapping mapInstVar: #closed_by) valueSchema: GLHUser. - (mapping mapInstVar: #mergeCommit) valueSchema: GLHCommit." - "indique ce que doit faire le reader lorsqu'il parse une DateAndTime object" - reader for: DateAndTime customDo: [ :mapping | - mapping decoder: [ :string | - string ifNil: [ nil ] ifNotNil: [ DateAndTime fromString: string ] ] ] +{ #category : #'private - parsing' } +GitlabModelImporter >> configureReaderForNote: reader [ + + super configureReaderForNote: reader. + + reader for: GLHNote do: [ :mapping | + + (mapping mapInstVar: #created_at) valueSchema: DateAndTime. + (mapping mapInstVar: #updated_at) valueSchema: DateAndTime ] ] { #category : #'private - configure reader' } GitlabModelImporter >> configureReaderForPipeline: reader [ - reader mapInstVarsFor: GLHPipeline. + super configureReaderForPipeline: reader. reader for: GLHPipeline do: [ :mapping | mapping @@ -349,10 +339,6 @@ GitlabModelImporter >> configureReaderForPipeline: reader [ setter: [ :object :value | value ifNotNil: [ object cacheAt: #userID put: (value at: #id) ] ] ]. - reader - for: #ArrayOfPipeline - customDo: [ :customMappting | - customMappting listOfElementSchema: GLHPipeline ] ] { #category : #'private - configure reader' } @@ -368,19 +354,13 @@ GitlabModelImporter >> configureReaderForProject: reader [ { #category : #'private - configure reader' } GitlabModelImporter >> configureReaderForRelease: reader [ - reader mapInstVarsFor: GLHRelease . - - - reader for: GLHRelease do: [ :mapping | - - (mapping mapInstVar: #author) valueSchema: GLHUser . - ]. - - + super configureReaderForRelease: reader. + + reader - for: #ArrayOfReleases - customDo: [ :customMappting | - customMappting listOfElementSchema: GLHRelease ]. + for: GLHRelease + do: [ :mapping | (mapping mapInstVar: #author) valueSchema: GLHUser ]. + ] { #category : #'private - configure reader' } @@ -411,13 +391,8 @@ GitlabModelImporter >> configureReaderForTag: reader [ { #category : #'private - configure reader' } GitlabModelImporter >> configureReaderForUser: reader [ - reader mapInstVarsFor: GLHUser. - - reader - for: #ArrayOfUser - customDo: [ :customMappting | - customMappting listOfElementSchema: GLHUser ]. - + super configureReaderForUser: reader. + ] { #category : #private } @@ -1871,36 +1846,19 @@ GitlabModelImporter >> parseMergeRequestsResult: result [ ] { #category : #'private - parsing' } -GitlabModelImporter >> parseNoteJson: results [ - | reader | - - "Créer un lecteur JSON" - reader := NeoJSONReader on: results readStream. - - "Définir le mapping pour l'objet GLHNote" - reader for: GLHNote do: [ :mapping | - mapping mapInstVars: #(id noteable_id attachment system confidential internal - noteable_iid resolvable imported imported_from - author body project_id noteable_type). - - (mapping mapInstVar: #created_at) valueSchema: DateAndTime. - (mapping mapInstVar: #updated_at) valueSchema: DateAndTime. - ]. - - "Corriger la conversion des dates" - reader for: DateAndTime customDo: [ :mapping | - mapping decoder: [ :string | DateAndTime readFrom: string readStream ] ]. +GitlabModelImporter >> parseNoteJson: results [ - reader - for: #ArrayOfNote - customDo: [ :customMappting | - customMappting listOfElementSchema: GLHNote ]. - ^ reader nextAs: #ArrayOfNote - - "Retourner la Note" - "^ reader nextAs: GLHNote" + | reader | + "Créer un lecteur JSON" + reader := generalReader on: results readStream. + "Corriger la conversion des dates" + "reader for: DateAndTime customDo: [ :mapping | + mapping decoder: [ :string | + DateAndTime readFrom: string readStream ] ]." + + ^ reader nextAs: #ArrayOfNote ] { #category : #'private - parsing' } diff --git a/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st b/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st index cdd817ba..1b606c60 100644 --- a/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st +++ b/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st @@ -274,9 +274,7 @@ GitModelImporter >> configureReaderForMergeRequest: reader [ reader mapInstVarsFor: GLHMergeRequest. - reader - for: #ArrayOfMergeRequest - customDo: [ :customMappting | + reader for: #ArrayOfMergeRequest customDo: [ :customMappting | customMappting listOfElementSchema: GLHMergeRequest ] ] @@ -291,6 +289,17 @@ GitModelImporter >> configureReaderForMilestone: reader [ customMappting listOfElementSchema: GLHMilestone ] ] +{ #category : #'private - configure reader' } +GitModelImporter >> configureReaderForNote: reader [ + + reader mapInstVarsFor: GLHNote . + + reader + for: #ArrayOfNote + customDo: [ :customMappting | + customMappting listOfElementSchema: GLHNote ] +] + { #category : #'private - configure reader' } GitModelImporter >> configureReaderForPipeline: reader [ @@ -343,7 +352,8 @@ GitModelImporter >> configureReaderForUser: reader [ reader for: #ArrayOfUser customDo: [ :customMappting | - customMappting listOfElementSchema: GLHUser ] + customMappting listOfElementSchema: GLHUser ]. + ] { #category : #utils } @@ -600,6 +610,7 @@ GitModelImporter >> initReader [ generalReader := NeoJSONReader new. "will be reuse for all reader next" + "indique ce que doit faire le reader lorsqu'il parse une DateAndTime object" generalReader for: DateAndTime customDo: [ :mapping | mapping decoder: [ :string | string ifNil: [ nil ] ifNotNil: [ DateAndTime fromString: string ] ] ]. @@ -616,7 +627,8 @@ GitModelImporter >> initReader [ self configureReaderForBranch: generalReader. self configureReaderForIssue: generalReader. self configureReaderForMilestone: generalReader. - self configureReaderForProject: generalReader. + self configureReaderForNote: generalReader. + self configureReaderForProject: generalReader ] { #category : #initialization } From eac073bef4cb3cd05cda2d6d79c6dbba65e7ecd6 Mon Sep 17 00:00:00 2001 From: HLAD Nicolas Date: Tue, 23 Sep 2025 14:48:23 +0200 Subject: [PATCH 25/52] stabilized job reader --- .../GLHApiMock.class.st | 5 + .../GitlabCommitsMock.class.st | 22 ++- .../GitlabJobsMock.class.st | 167 ++++++++++++++++ .../GitlabModelImporterTest.class.st | 181 +++++++++++++++++- .../GitlabModelImporter.class.st | 45 +++-- .../GitModelImporter.class.st | 27 +-- 6 files changed, 411 insertions(+), 36 deletions(-) create mode 100644 src/GitLabHealth-Model-Importer-Tests/GitlabJobsMock.class.st diff --git a/src/GitLabHealth-Model-Importer-Tests/GLHApiMock.class.st b/src/GitLabHealth-Model-Importer-Tests/GLHApiMock.class.st index c7e073a2..370c45e4 100644 --- a/src/GitLabHealth-Model-Importer-Tests/GLHApiMock.class.st +++ b/src/GitLabHealth-Model-Importer-Tests/GLHApiMock.class.st @@ -9,6 +9,11 @@ GLHApiMock >> commits [ ^GitlabCommitsMock new. ] +{ #category : #accessing } +GLHApiMock >> jobs [ + ^ GitlabJobsMock new +] + { #category : #accessing } GLHApiMock >> mergeRequests [ diff --git a/src/GitLabHealth-Model-Importer-Tests/GitlabCommitsMock.class.st b/src/GitLabHealth-Model-Importer-Tests/GitlabCommitsMock.class.st index c7f39777..4604f5fc 100644 --- a/src/GitLabHealth-Model-Importer-Tests/GitlabCommitsMock.class.st +++ b/src/GitLabHealth-Model-Importer-Tests/GitlabCommitsMock.class.st @@ -6,6 +6,26 @@ Class { { #category : #api } GitlabCommitsMock >> diffOf: commitSha inProject: projectId uniDiff: unidiff [ + commitSha = 'createError' ifTrue: [ - ^ '{"message":"500 Internal Server Error"}' ] + ^ '{"message":"500 Internal Server Error"}' ]. + ^ '[]' +] + +{ #category : #api } +GitlabCommitsMock >> get: aString inProject: anUndefinedObject [ + ^ '{ + "author_email": "admin@example.com", + "author_name": "Administrator", + "created_at": "2015-12-24T16:51:14.000+01:00", + "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", + "message": "Test the CI integration.", + "short_id": "0ff3ae19", + "title": "Test the CI integration." + }' +] + +{ #category : #accessing } +GitlabCommitsMock >> readStream [ + self shouldBeImplemented. ] diff --git a/src/GitLabHealth-Model-Importer-Tests/GitlabJobsMock.class.st b/src/GitLabHealth-Model-Importer-Tests/GitlabJobsMock.class.st new file mode 100644 index 00000000..69932059 --- /dev/null +++ b/src/GitLabHealth-Model-Importer-Tests/GitlabJobsMock.class.st @@ -0,0 +1,167 @@ +Class { + #name : #GitlabJobsMock, + #superclass : #Object, + #category : #'GitLabHealth-Model-Importer-Tests' +} + +{ #category : #api } +GitlabJobsMock >> getAllForPipeline: anInteger inProject: anInteger2 [ + + ^ { '[ + { + "commit": { + "author_email": "admin@example.com", + "author_name": "Administrator", + "created_at": "2015-12-24T16:51:14.000+01:00", + "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", + "message": "Test the CI integration.", + "short_id": "0ff3ae19", + "title": "Test the CI integration." + }, + "coverage": null, + "archived": false, + "source": "push", + "allow_failure": false, + "created_at": "2015-12-24T15:51:21.802Z", + "started_at": "2015-12-24T17:54:27.722Z", + "finished_at": "2015-12-24T17:54:27.895Z", + "erased_at": null, + "duration": 0.173, + "queued_duration": 0.010, + "artifacts_file": { + "filename": "artifacts.zip", + "size": 1000 + }, + "artifacts": [ + {"file_type": "archive", "size": 1000, "filename": "artifacts.zip", "file_format": "zip"}, + {"file_type": "metadata", "size": 186, "filename": "metadata.gz", "file_format": "gzip"}, + {"file_type": "trace", "size": 1500, "filename": "job.log", "file_format": "raw"}, + {"file_type": "junit", "size": 750, "filename": "junit.xml.gz", "file_format": "gzip"} + ], + "artifacts_expire_at": "2016-01-23T17:54:27.895Z", + "tag_list": [ + "docker runner", "ubuntu18" + ], + "id": 7, + "name": "teaspoon", + "pipeline": { + "id": 6, + "project_id": 1, + "ref": "main", + "sha": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", + "status": "pending" + }, + "ref": "main", + "runner": { + "id": 32, + "description": "", + "ip_address": null, + "active": true, + "paused": false, + "is_shared": true, + "runner_type": "instance_type", + "name": null, + "online": false, + "status": "offline" + }, + "runner_manager": { + "id": 1, + "system_id": "s_89e5e9956577", + "version": "16.11.1", + "revision": "535ced5f", + "platform": "linux", + "architecture": "amd64", + "created_at": "2024-05-01T10:12:02.507Z", + "contacted_at": "2024-05-07T06:30:09.355Z", + "ip_address": "127.0.0.1", + "status": "offline" + }, + "stage": "test", + "status": "failed", + "failure_reason": "script_failure", + "tag": false, + "web_url": "https://example.com/foo/bar/-/jobs/7", + "project": { + "ci_job_token_scope_enabled": false + }, + "user": { + "id": 123, + "name": "Administrator", + "username": "root", + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", + "web_url": "http://gitlab.dev/root", + "created_at": "2015-12-21T13:14:24.077Z", + "bio": null, + "location": null, + "public_email": "", + "linkedin": "", + "twitter": "", + "website_url": "", + "organization": "" + } + }, + { + "commit": { + "author_email": "admin@example.com", + "author_name": "Administrator", + "created_at": "2015-12-24T16:51:14.000+01:00", + "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", + "message": "Test the CI integration.", + "short_id": "0ff3ae19", + "title": "Test the CI integration." + }, + "coverage": null, + "archived": false, + "source": "push", + "allow_failure": false, + "created_at": "2015-12-24T15:51:21.727Z", + "started_at": "2015-12-24T17:54:24.729Z", + "finished_at": "2015-12-24T17:54:24.921Z", + "erased_at": null, + "duration": 0.192, + "queued_duration": 0.023, + "artifacts_expire_at": "2016-01-23T17:54:24.921Z", + "tag_list": [ + "docker runner", "win10-2004" + ], + "id": 6, + "name": "rspec:other", + "pipeline": { + "id": 6, + "project_id": 1, + "ref": "main", + "sha": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", + "status": "pending" + }, + "ref": "main", + "artifacts": [], + "runner": null, + "runner_manager": null, + "stage": "test", + "status": "failed", + "failure_reason": "stuck_or_timeout_failure", + "tag": false, + "web_url": "https://example.com/foo/bar/-/jobs/6", + "project": { + "ci_job_token_scope_enabled": false + }, + "user": { + "id": 123, + "name": "Administrator", + "username": "root", + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", + "web_url": "http://gitlab.dev/root", + "created_at": "2015-12-21T13:14:24.077Z", + "bio": null, + "location": null, + "public_email": "", + "linkedin": "", + "twitter": "", + "website_url": "", + "organization": "" + } + } +]'} +] diff --git a/src/GitLabHealth-Model-Importer-Tests/GitlabModelImporterTest.class.st b/src/GitLabHealth-Model-Importer-Tests/GitlabModelImporterTest.class.st index 353f1704..7352c31f 100644 --- a/src/GitLabHealth-Model-Importer-Tests/GitlabModelImporterTest.class.st +++ b/src/GitLabHealth-Model-Importer-Tests/GitlabModelImporterTest.class.st @@ -17,6 +17,168 @@ GitlabModelImporterTest >> gitlabDiffData [ ^ '[{"b_mode":"100644","diff":"@@ -80,5 +80,10 @@ test test test {\r test test test(@test test[] test) test test, test {\r \ttest test(test.test(test), test.test_test, test);\r }\r+ \r+ @test(\"/testAvisMandtestement\")\r+ test test testAvisMandtestement(@test test[] test) test test, test {\r+ \ttest test(test.testAvisMandtestement(test), test.test_test, test);\r+ }\r \r }\r\\ test test test test test test\r","new_path":"@@ -80,5 +80,10 @@ test test test {\r test test test(@test test[] test) test test, test {\r \ttest test(test.test(test), test.test_test, test);\r }\r+ \r+ @test(\"/testAvisMandtestement\")\r+ test test testAvisMandtestement(@test test[] test) test test, test {\r+ \ttest test(test.testAvisMandtestement(test), test.test_test, test);\r+ }\r \r }\r\\ test test test test test test\r","a_mode":"100644","old_path":"@@ -80,5 +80,10 @@ test test test {\r test test test(@test test[] test) test test, test {\r \ttest test(test.test(test), test.test_test, test);\r }\r+ \r+ @test(\"/testAvisMandtestement\")\r+ test test testAvisMandtestement(@test test[] test) test test, test {\r+ \ttest test(test.testAvisMandtestement(test), test.test_test, test);\r+ }\r \r }\r\\ test test test test test test\r","new_file":false,"deleted_file":false,"renamed_file":false},{"b_mode":"100644","diff":"@@ -11,6 +11,7 @@ import org.springframework.stereotype.Service;\n import fr.bl.avenir.gf.rest.ecompta.edition.enums.TypeBordereauVolet;\n import fr.bl.avenir.gf.rest.ecompta.edition.enums.TypeReportEnumeration;\n import fr.bl.avenir.gf.rest.ecompta.edition.service.avis.ServiceImprimerAvis;\n+import fr.bl.avenir.gf.rest.ecompta.edition.service.avismandatement.ServiceImprimerAvisMandatement;\n import fr.bl.avenir.gf.rest.ecompta.edition.service.bordereau.ServiceImprimerBordereauMandat;\n import fr.bl.avenir.gf.rest.ecompta.edition.service.bordereau.ServiceImprimerBordereauTitre;\n import fr.magnus.reftechnique.transverse.EntiteRelationnelle;\n@@ -26,12 +27,12 @@ public class EditionService {\n \n @Autowired\n ServiceImprimerBordereauMandat serviceImprimerBordereauMandat;\n- \n @Autowired\n ServiceImprimerBordereauTitre serviceImprimerBordereauTitre;\n- \n @Autowired\n ServiceImprimerAvis serviceImprimerAvis;\n+ @Autowired\n+ ServiceImprimerAvis serviceImprimerAvisMandatement;\n \n public byte[] imprimerBordereauMandatVolet1( TableauAbstract[] jsonData) throws JRException, ParseException {\n Map params = new HashMap<>();\n@@ -85,6 +86,10 @@ public class EditionService {\n \treturn serviceImprimerAvis.imprimerFichier(jsonData, params, TypeReportEnumeration.AVIS_SOMMES_A_PAYER_SANS_EXP);\n }\n \t\n- \n+ public byte[] imprimerAvisMandatement(TableauAbstract[] jsonData) throws JRException, ParseException {\n+ \treturn serviceImprimerAvisMandatement.imprimerFichier(jsonData, null, TypeReportEnumeration.AVIS_MANDATEMENT);\n+ }\n+ \n+ \n \n }\n\\ No newline at end of file\n","new_path":"@@ -11,6 +11,7 @@ import org.springframework.stereotype.Service;\n import fr.bl.avenir.gf.rest.ecompta.edition.enums.TypeBordereauVolet;\n import fr.bl.avenir.gf.rest.ecompta.edition.enums.TypeReportEnumeration;\n import fr.bl.avenir.gf.rest.ecompta.edition.service.avis.ServiceImprimerAvis;\n+import fr.bl.avenir.gf.rest.ecompta.edition.service.avismandatement.ServiceImprimerAvisMandatement;\n import fr.bl.avenir.gf.rest.ecompta.edition.service.bordereau.ServiceImprimerBordereauMandat;\n import fr.bl.avenir.gf.rest.ecompta.edition.service.bordereau.ServiceImprimerBordereauTitre;\n import fr.magnus.reftechnique.transverse.EntiteRelationnelle;\n@@ -26,12 +27,12 @@ public class EditionService {\n \n @Autowired\n ServiceImprimerBordereauMandat serviceImprimerBordereauMandat;\n- \n @Autowired\n ServiceImprimerBordereauTitre serviceImprimerBordereauTitre;\n- \n @Autowired\n ServiceImprimerAvis serviceImprimerAvis;\n+ @Autowired\n+ ServiceImprimerAvis serviceImprimerAvisMandatement;\n \n public byte[] imprimerBordereauMandatVolet1( TableauAbstract[] jsonData) throws JRException, ParseException {\n Map params = new HashMap<>();\n@@ -85,6 +86,10 @@ public class EditionService {\n \treturn serviceImprimerAvis.imprimerFichier(jsonData, params, TypeReportEnumeration.AVIS_SOMMES_A_PAYER_SANS_EXP);\n }\n \t\n- \n+ public byte[] imprimerAvisMandatement(TableauAbstract[] jsonData) throws JRException, ParseException {\n+ \treturn serviceImprimerAvisMandatement.imprimerFichier(jsonData, null, TypeReportEnumeration.AVIS_MANDATEMENT);\n+ }\n+ \n+ \n \n }\n\\ No newline at end of file\n","a_mode":"100644","old_path":"@@ -11,6 +11,7 @@ import org.springframework.stereotype.Service;\n import fr.bl.avenir.gf.rest.ecompta.edition.enums.TypeBordereauVolet;\n import fr.bl.avenir.gf.rest.ecompta.edition.enums.TypeReportEnumeration;\n import fr.bl.avenir.gf.rest.ecompta.edition.service.avis.ServiceImprimerAvis;\n+import fr.bl.avenir.gf.rest.ecompta.edition.service.avismandatement.ServiceImprimerAvisMandatement;\n import fr.bl.avenir.gf.rest.ecompta.edition.service.bordereau.ServiceImprimerBordereauMandat;\n import fr.bl.avenir.gf.rest.ecompta.edition.service.bordereau.ServiceImprimerBordereauTitre;\n import fr.magnus.reftechnique.transverse.EntiteRelationnelle;\n@@ -26,12 +27,12 @@ public class EditionService {\n \n @Autowired\n ServiceImprimerBordereauMandat serviceImprimerBordereauMandat;\n- \n @Autowired\n ServiceImprimerBordereauTitre serviceImprimerBordereauTitre;\n- \n @Autowired\n ServiceImprimerAvis serviceImprimerAvis;\n+ @Autowired\n+ ServiceImprimerAvis serviceImprimerAvisMandatement;\n \n public byte[] imprimerBordereauMandatVolet1( TableauAbstract[] jsonData) throws JRException, ParseException {\n Map params = new HashMap<>();\n@@ -85,6 +86,10 @@ public class EditionService {\n \treturn serviceImprimerAvis.imprimerFichier(jsonData, params, TypeReportEnumeration.AVIS_SOMMES_A_PAYER_SANS_EXP);\n }\n \t\n- \n+ public byte[] imprimerAvisMandatement(TableauAbstract[] jsonData) throws JRException, ParseException {\n+ \treturn serviceImprimerAvisMandatement.imprimerFichier(jsonData, null, TypeReportEnumeration.AVIS_MANDATEMENT);\n+ }\n+ \n+ \n \n }\n\\ No newline at end of file\n","new_file":false,"deleted_file":false,"renamed_file":false},{"b_mode":"100644","diff":"@@ -0,0 +1,25 @@\n+package fr.bl.avenir.gf.rest.ecompta.edition.dto.avismandatement;\n+\n+import lombok.Getter;\n+import lombok.NoArgsConstructor;\n+import lombok.Setter;\n+\n+@NoArgsConstructor\n+@Getter\n+@Setter\n+public class DTOAvisMandatement {\n+\tprivate String collectiviteLogo;\n+\tprivate String collectiviteNom;\n+\tprivate String collectiviteAdresse;\n+\tprivate String collectiviteSignataire;\n+\tprivate String collectiviteSignature;\n+\tprivate String collectiviteTampon;\n+\tprivate String tiersNom;\n+\tprivate String tiersAdresse;\n+\tprivate String texteCourrier;\n+\tprivate String pieceJustificative;\n+\tprivate String pieceJustificativePjIdUnique;\n+\tprivate String observation;\n+\tprivate String comptableAssignataire;\n+\tprivate String contexte;\n+}\n","new_path":"@@ -0,0 +1,25 @@\n+package fr.bl.avenir.gf.rest.ecompta.edition.dto.avismandatement;\n+\n+import lombok.Getter;\n+import lombok.NoArgsConstructor;\n+import lombok.Setter;\n+\n+@NoArgsConstructor\n+@Getter\n+@Setter\n+public class DTOAvisMandatement {\n+\tprivate String collectiviteLogo;\n+\tprivate String collectiviteNom;\n+\tprivate String collectiviteAdresse;\n+\tprivate String collectiviteSignataire;\n+\tprivate String collectiviteSignature;\n+\tprivate String collectiviteTampon;\n+\tprivate String tiersNom;\n+\tprivate String tiersAdresse;\n+\tprivate String texteCourrier;\n+\tprivate String pieceJustificative;\n+\tprivate String pieceJustificativePjIdUnique;\n+\tprivate String observation;\n+\tprivate String comptableAssignataire;\n+\tprivate String contexte;\n+}\n","a_mode":"0","old_path":"@@ -0,0 +1,25 @@\n+package fr.bl.avenir.gf.rest.ecompta.edition.dto.avismandatement;\n+\n+import lombok.Getter;\n+import lombok.NoArgsConstructor;\n+import lombok.Setter;\n+\n+@NoArgsConstructor\n+@Getter\n+@Setter\n+public class DTOAvisMandatement {\n+\tprivate String collectiviteLogo;\n+\tprivate String collectiviteNom;\n+\tprivate String collectiviteAdresse;\n+\tprivate String collectiviteSignataire;\n+\tprivate String collectiviteSignature;\n+\tprivate String collectiviteTampon;\n+\tprivate String tiersNom;\n+\tprivate String tiersAdresse;\n+\tprivate String texteCourrier;\n+\tprivate String pieceJustificative;\n+\tprivate String pieceJustificativePjIdUnique;\n+\tprivate String observation;\n+\tprivate String comptableAssignataire;\n+\tprivate String contexte;\n+}\n","new_file":true,"deleted_file":false,"renamed_file":false},{"b_mode":"100644","diff":"@@ -34,7 +34,6 @@ public class TypeReportEnumeration extends EnumerationAbstract {\n public static final TypeReportEnumeration TITRE_VOLET2 = new TypeReportEnumeration(6, \"Bordereau de titres Volet 2\", JASPER_REPORT_BORDEREAU_TITRE);\n public static final TypeReportEnumeration TITRE_VOLET3 = new TypeReportEnumeration(7, \"Bordereau de titres Volet 3\", JASPER_REPORT_BORDEREAU_TITRE);\n public static final TypeReportEnumeration TITRE = new TypeReportEnumeration(8, \"Bordereau de titres\", JASPER_REPORT_BORDEREAU_TITRE);\n- private JasperReport jasperReport;\n \n \t// --- AVIS\n private static final String JASPER_AVIS_REPOSITORY = \"/jasper/avis/\";\n@@ -44,7 +43,13 @@ public class TypeReportEnumeration extends EnumerationAbstract {\n public static final TypeReportEnumeration AVIS_SOMMES_A_PAYER = new TypeReportEnumeration(9, \"Avis des sommes à payer\", JASPER_REPORT_AVIS);\n public static final TypeReportEnumeration AVIS_SOMMES_A_PAYER_SANS_EXP = new TypeReportEnumeration(10, \"Avis des sommes à payer sans expéditeur\", JASPER_REPORT_AVIS);\n \n+ // --- AVIS MANDATEMENT\n+ private static final String JASPER_AVIS_MANDATEMENT_REPOSITORY = \"/jasper/avismandatement/\";\n+ private static final String[] JASPER_AVIS_MANDATEMENT_REPORTS = new String[] {\"avisMandatement.jrxml\"};\n+ private static final JasperReport JASPER_REPORT_AVIS_MANDATEMENT = getJasperReport(JASPER_AVIS_MANDATEMENT_REPOSITORY, JASPER_AVIS_MANDATEMENT_REPORTS);\n+ public static final TypeReportEnumeration AVIS_MANDATEMENT= new TypeReportEnumeration(9, \"Avis mandatement\", JASPER_REPORT_AVIS_MANDATEMENT);\n \n+ private JasperReport jasperReport;\n public JasperReport getJasperReport() {\n return jasperReport;\n }\n","new_path":"@@ -34,7 +34,6 @@ public class TypeReportEnumeration extends EnumerationAbstract {\n public static final TypeReportEnumeration TITRE_VOLET2 = new TypeReportEnumeration(6, \"Bordereau de titres Volet 2\", JASPER_REPORT_BORDEREAU_TITRE);\n public static final TypeReportEnumeration TITRE_VOLET3 = new TypeReportEnumeration(7, \"Bordereau de titres Volet 3\", JASPER_REPORT_BORDEREAU_TITRE);\n public static final TypeReportEnumeration TITRE = new TypeReportEnumeration(8, \"Bordereau de titres\", JASPER_REPORT_BORDEREAU_TITRE);\n- private JasperReport jasperReport;\n \n \t// --- AVIS\n private static final String JASPER_AVIS_REPOSITORY = \"/jasper/avis/\";\n@@ -44,7 +43,13 @@ public class TypeReportEnumeration extends EnumerationAbstract {\n public static final TypeReportEnumeration AVIS_SOMMES_A_PAYER = new TypeReportEnumeration(9, \"Avis des sommes à payer\", JASPER_REPORT_AVIS);\n public static final TypeReportEnumeration AVIS_SOMMES_A_PAYER_SANS_EXP = new TypeReportEnumeration(10, \"Avis des sommes à payer sans expéditeur\", JASPER_REPORT_AVIS);\n \n+ // --- AVIS MANDATEMENT\n+ private static final String JASPER_AVIS_MANDATEMENT_REPOSITORY = \"/jasper/avismandatement/\";\n+ private static final String[] JASPER_AVIS_MANDATEMENT_REPORTS = new String[] {\"avisMandatement.jrxml\"};\n+ private static final JasperReport JASPER_REPORT_AVIS_MANDATEMENT = getJasperReport(JASPER_AVIS_MANDATEMENT_REPOSITORY, JASPER_AVIS_MANDATEMENT_REPORTS);\n+ public static final TypeReportEnumeration AVIS_MANDATEMENT= new TypeReportEnumeration(9, \"Avis mandatement\", JASPER_REPORT_AVIS_MANDATEMENT);\n \n+ private JasperReport jasperReport;\n public JasperReport getJasperReport() {\n return jasperReport;\n }\n","a_mode":"100644","old_path":"@@ -34,7 +34,6 @@ public class TypeReportEnumeration extends EnumerationAbstract {\n public static final TypeReportEnumeration TITRE_VOLET2 = new TypeReportEnumeration(6, \"Bordereau de titres Volet 2\", JASPER_REPORT_BORDEREAU_TITRE);\n public static final TypeReportEnumeration TITRE_VOLET3 = new TypeReportEnumeration(7, \"Bordereau de titres Volet 3\", JASPER_REPORT_BORDEREAU_TITRE);\n public static final TypeReportEnumeration TITRE = new TypeReportEnumeration(8, \"Bordereau de titres\", JASPER_REPORT_BORDEREAU_TITRE);\n- private JasperReport jasperReport;\n \n \t// --- AVIS\n private static final String JASPER_AVIS_REPOSITORY = \"/jasper/avis/\";\n@@ -44,7 +43,13 @@ public class TypeReportEnumeration extends EnumerationAbstract {\n public static final TypeReportEnumeration AVIS_SOMMES_A_PAYER = new TypeReportEnumeration(9, \"Avis des sommes à payer\", JASPER_REPORT_AVIS);\n public static final TypeReportEnumeration AVIS_SOMMES_A_PAYER_SANS_EXP = new TypeReportEnumeration(10, \"Avis des sommes à payer sans expéditeur\", JASPER_REPORT_AVIS);\n \n+ // --- AVIS MANDATEMENT\n+ private static final String JASPER_AVIS_MANDATEMENT_REPOSITORY = \"/jasper/avismandatement/\";\n+ private static final String[] JASPER_AVIS_MANDATEMENT_REPORTS = new String[] {\"avisMandatement.jrxml\"};\n+ private static final JasperReport JASPER_REPORT_AVIS_MANDATEMENT = getJasperReport(JASPER_AVIS_MANDATEMENT_REPOSITORY, JASPER_AVIS_MANDATEMENT_REPORTS);\n+ public static final TypeReportEnumeration AVIS_MANDATEMENT= new TypeReportEnumeration(9, \"Avis mandatement\", JASPER_REPORT_AVIS_MANDATEMENT);\n \n+ private JasperReport jasperReport;\n public JasperReport getJasperReport() {\n return jasperReport;\n }\n","new_file":false,"deleted_file":false,"renamed_file":false},{"b_mode":"100644","diff":"@@ -0,0 +1,7 @@\n+package fr.bl.avenir.gf.rest.ecompta.edition.service.avismandatement;\n+\n+import fr.bl.avenir.gf.rest.ecompta.edition.service.ServiceImprimer;\n+\n+public interface ServiceImprimerAvisMandatement extends ServiceImprimer {\n+\t\n+}\n","new_path":"@@ -0,0 +1,7 @@\n+package fr.bl.avenir.gf.rest.ecompta.edition.service.avismandatement;\n+\n+import fr.bl.avenir.gf.rest.ecompta.edition.service.ServiceImprimer;\n+\n+public interface ServiceImprimerAvisMandatement extends ServiceImprimer {\n+\t\n+}\n","a_mode":"0","old_path":"@@ -0,0 +1,7 @@\n+package fr.bl.avenir.gf.rest.ecompta.edition.service.avismandatement;\n+\n+import fr.bl.avenir.gf.rest.ecompta.edition.service.ServiceImprimer;\n+\n+public interface ServiceImprimerAvisMandatement extends ServiceImprimer {\n+\t\n+}\n","new_file":true,"deleted_file":false,"renamed_file":false},{"b_mode":"100644","diff":"@@ -0,0 +1,33 @@\n+package fr.bl.avenir.gf.rest.ecompta.edition.service.avismandatement.impl;\n+\n+import java.text.ParseException;\n+import java.util.List;\n+import java.util.Map;\n+\n+import org.springframework.stereotype.Service;\n+\n+import fr.bl.avenir.gf.rest.ecompta.edition.dto.avismandatement.DTOAvisMandatement;\n+import fr.bl.avenir.gf.rest.ecompta.edition.service.avismandatement.ServiceImprimerAvisMandatement;\n+import fr.bl.avenir.gf.rest.ecompta.edition.service.impl.ServiceImprimerImpl;\n+import fr.magnus.reftechnique.transverse.EntiteRelationnelle;\n+import fr.magnus.reftechnique.transverse.tableau.TableauAbstract;\n+\n+@Service(\"ServiceImprimerAvisMandatement\")\n+public class ServiceImprimerAvisMandatementImpl extends ServiceImprimerImpl implements ServiceImprimerAvisMandatement{\n+\n+ @Override\n+\tpublic List getListDonnee(TableauAbstract[] tableauEntiteRelationnelles, Map params) throws ParseException {\n+\n+ List dtoAvisMandatementList = null;\n+ \n+ if (tableauEntiteRelationnelles!= null && tableauEntiteRelationnelles.length == 2) {\n+ TableauAbstract tabDonnee = tableauEntiteRelationnelles[0];\n+// Collections.sort(dtoAvisMandatementList, Comparator.comparing(DTOAvis::getBordereauNumero)\n+// .thenComparing(DTOAvis::getTitreNumeroPiece)\n+// .thenComparing(DTOAvis::getTiers1)\n+// \t.thenComparing(DTOAvis::getImputationComplete));\n+ }\n+ return dtoAvisMandatementList;\t\t\n+\t}\n+\n+}\n","new_path":"@@ -0,0 +1,33 @@\n+package fr.bl.avenir.gf.rest.ecompta.edition.service.avismandatement.impl;\n+\n+import java.text.ParseException;\n+import java.util.List;\n+import java.util.Map;\n+\n+import org.springframework.stereotype.Service;\n+\n+import fr.bl.avenir.gf.rest.ecompta.edition.dto.avismandatement.DTOAvisMandatement;\n+import fr.bl.avenir.gf.rest.ecompta.edition.service.avismandatement.ServiceImprimerAvisMandatement;\n+import fr.bl.avenir.gf.rest.ecompta.edition.service.impl.ServiceImprimerImpl;\n+import fr.magnus.reftechnique.transverse.EntiteRelationnelle;\n+import fr.magnus.reftechnique.transverse.tableau.TableauAbstract;\n+\n+@Service(\"ServiceImprimerAvisMandatement\")\n+public class ServiceImprimerAvisMandatementImpl extends ServiceImprimerImpl implements ServiceImprimerAvisMandatement{\n+\n+ @Override\n+\tpublic List getListDonnee(TableauAbstract[] tableauEntiteRelationnelles, Map params) throws ParseException {\n+\n+ List dtoAvisMandatementList = null;\n+ \n+ if (tableauEntiteRelationnelles!= null && tableauEntiteRelationnelles.length == 2) {\n+ TableauAbstract tabDonnee = tableauEntiteRelationnelles[0];\n+// Collections.sort(dtoAvisMandatementList, Comparator.comparing(DTOAvis::getBordereauNumero)\n+// .thenComparing(DTOAvis::getTitreNumeroPiece)\n+// .thenComparing(DTOAvis::getTiers1)\n+// \t.thenComparing(DTOAvis::getImputationComplete));\n+ }\n+ return dtoAvisMandatementList;\t\t\n+\t}\n+\n+}\n","a_mode":"0","old_path":"@@ -0,0 +1,33 @@\n+package fr.bl.avenir.gf.rest.ecompta.edition.service.avismandatement.impl;\n+\n+import java.text.ParseException;\n+import java.util.List;\n+import java.util.Map;\n+\n+import org.springframework.stereotype.Service;\n+\n+import fr.bl.avenir.gf.rest.ecompta.edition.dto.avismandatement.DTOAvisMandatement;\n+import fr.bl.avenir.gf.rest.ecompta.edition.service.avismandatement.ServiceImprimerAvisMandatement;\n+import fr.bl.avenir.gf.rest.ecompta.edition.service.impl.ServiceImprimerImpl;\n+import fr.magnus.reftechnique.transverse.EntiteRelationnelle;\n+import fr.magnus.reftechnique.transverse.tableau.TableauAbstract;\n+\n+@Service(\"ServiceImprimerAvisMandatement\")\n+public class ServiceImprimerAvisMandatementImpl extends ServiceImprimerImpl implements ServiceImprimerAvisMandatement{\n+\n+ @Override\n+\tpublic List getListDonnee(TableauAbstract[] tableauEntiteRelationnelles, Map params) throws ParseException {\n+\n+ List dtoAvisMandatementList = null;\n+ \n+ if (tableauEntiteRelationnelles!= null && tableauEntiteRelationnelles.length == 2) {\n+ TableauAbstract tabDonnee = tableauEntiteRelationnelles[0];\n+// Collections.sort(dtoAvisMandatementList, Comparator.comparing(DTOAvis::getBordereauNumero)\n+// .thenComparing(DTOAvis::getTitreNumeroPiece)\n+// .thenComparing(DTOAvis::getTiers1)\n+// \t.thenComparing(DTOAvis::getImputationComplete));\n+ }\n+ return dtoAvisMandatementList;\t\t\n+\t}\n+\n+}\n","new_file":true,"deleted_file":false,"renamed_file":false},{"b_mode":"100644","diff":"@@ -1,8 +1,6 @@\n package fr.bl.avenir.gf.rest.ecompta.edition.service.impl;\n \n import java.math.BigDecimal;\n-import java.nio.file.Path;\n-import java.nio.file.Paths;\n import java.text.ParseException;\n import java.text.SimpleDateFormat;\n import java.util.ArrayList;\n@@ -58,14 +56,11 @@ public abstract class ServiceImprimerImpl implements ServiceImprimer {\n return getListDonnee(tableauEntiteRelationnelles, params);\n }\n \n- protected void mappingDtoEnvironnementFromJson(\n- TableauAbstract environnement,\n- Map params) {\n+ protected void mappingDtoEnvironnementFromJson(TableauAbstract environnement, Map params) {\n if (environnement != null && environnement.getLigneCount() > 0) {\n EntiteRelationnelle entiteRelationnelle = environnement.getDonnees().get(0);\n params.putAll(entiteRelationnelle.getData());\n }\n-\n }\n \n protected List mappingDtoOrdonnancementListFromJson(TableauAbstract ordonnancementJSon) {\n","new_path":"@@ -1,8 +1,6 @@\n package fr.bl.avenir.gf.rest.ecompta.edition.service.impl;\n \n import java.math.BigDecimal;\n-import java.nio.file.Path;\n-import java.nio.file.Paths;\n import java.text.ParseException;\n import java.text.SimpleDateFormat;\n import java.util.ArrayList;\n@@ -58,14 +56,11 @@ public abstract class ServiceImprimerImpl implements ServiceImprimer {\n return getListDonnee(tableauEntiteRelationnelles, params);\n }\n \n- protected void mappingDtoEnvironnementFromJson(\n- TableauAbstract environnement,\n- Map params) {\n+ protected void mappingDtoEnvironnementFromJson(TableauAbstract environnement, Map params) {\n if (environnement != null && environnement.getLigneCount() > 0) {\n EntiteRelationnelle entiteRelationnelle = environnement.getDonnees().get(0);\n params.putAll(entiteRelationnelle.getData());\n }\n-\n }\n \n protected List mappingDtoOrdonnancementListFromJson(TableauAbstract ordonnancementJSon) {\n","a_mode":"100644","old_path":"@@ -1,8 +1,6 @@\n package fr.bl.avenir.gf.rest.ecompta.edition.service.impl;\n \n import java.math.BigDecimal;\n-import java.nio.file.Path;\n-import java.nio.file.Paths;\n import java.text.ParseException;\n import java.text.SimpleDateFormat;\n import java.util.ArrayList;\n@@ -58,14 +56,11 @@ public abstract class ServiceImprimerImpl implements ServiceImprimer {\n return getListDonnee(tableauEntiteRelationnelles, params);\n }\n \n- protected void mappingDtoEnvironnementFromJson(\n- TableauAbstract environnement,\n- Map params) {\n+ protected void mappingDtoEnvironnementFromJson(TableauAbstract environnement, Map params) {\n if (environnement != null && environnement.getLigneCount() > 0) {\n EntiteRelationnelle entiteRelationnelle = environnement.getDonnees().get(0);\n params.putAll(entiteRelationnelle.getData());\n }\n-\n }\n \n protected List mappingDtoOrdonnancementListFromJson(TableauAbstract ordonnancementJSon) {\n","new_file":false,"deleted_file":false,"renamed_file":false},{"b_mode":"100644","diff":"@@ -0,0 +1,177 @@\n+\n+\n+\n+\t\n+\t\n+\t\n+\t\n+\t\n+\t\n+\t\n+\t\n+\t\n+\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\n+\n+\t\n+\t\n+\t\n+\t\n+\t\n+\t\n+\t\n+\t\n+\t\n+\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\n+\t\n+\n","a_mode":"0","old_path":"@@ -0,0 +1,177 @@\n+\n+\n+\n+\t\n+\t\n+\t\n+\t\n+\t\n+\t\n+\t\n+\t\n+\t\n+\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\n+\t\n+\n","new_file":true,"deleted_file":false,"renamed_file":false}]' ] +{ #category : #json } +GitlabModelImporterTest >> jobsJson [ + + ^ '[ + { + "commit": { + "author_email": "admin@example.com", + "author_name": "Administrator", + "created_at": "2015-12-24T16:51:14.000+01:00", + "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", + "message": "Test the CI integration.", + "short_id": "0ff3ae19", + "title": "Test the CI integration." + }, + "coverage": null, + "archived": false, + "source": "push", + "allow_failure": false, + "created_at": "2015-12-24T15:51:21.802Z", + "started_at": "2015-12-24T17:54:27.722Z", + "finished_at": "2015-12-24T17:54:27.895Z", + "erased_at": null, + "duration": 0.173, + "queued_duration": 0.010, + "artifacts_file": { + "filename": "artifacts.zip", + "size": 1000 + }, + "artifacts": [ + {"file_type": "archive", "size": 1000, "filename": "artifacts.zip", "file_format": "zip"}, + {"file_type": "metadata", "size": 186, "filename": "metadata.gz", "file_format": "gzip"}, + {"file_type": "trace", "size": 1500, "filename": "job.log", "file_format": "raw"}, + {"file_type": "junit", "size": 750, "filename": "junit.xml.gz", "file_format": "gzip"} + ], + "artifacts_expire_at": "2016-01-23T17:54:27.895Z", + "tag_list": [ + "docker runner", "ubuntu18" + ], + "id": 7, + "name": "teaspoon", + "pipeline": { + "id": 6, + "project_id": 1, + "ref": "main", + "sha": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", + "status": "pending" + }, + "ref": "main", + "runner": { + "id": 32, + "description": "", + "ip_address": null, + "active": true, + "paused": false, + "is_shared": true, + "runner_type": "instance_type", + "name": null, + "online": false, + "status": "offline" + }, + "runner_manager": { + "id": 1, + "system_id": "s_89e5e9956577", + "version": "16.11.1", + "revision": "535ced5f", + "platform": "linux", + "architecture": "amd64", + "created_at": "2024-05-01T10:12:02.507Z", + "contacted_at": "2024-05-07T06:30:09.355Z", + "ip_address": "127.0.0.1", + "status": "offline" + }, + "stage": "test", + "status": "failed", + "failure_reason": "script_failure", + "tag": false, + "web_url": "https://example.com/foo/bar/-/jobs/7", + "project": { + "ci_job_token_scope_enabled": false + }, + "user": { + "id": 123, + "name": "Administrator", + "username": "root", + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", + "web_url": "http://gitlab.dev/root", + "created_at": "2015-12-21T13:14:24.077Z", + "bio": null, + "location": null, + "public_email": "", + "linkedin": "", + "twitter": "", + "website_url": "", + "organization": "" + } + }, + { + "commit": { + "author_email": "admin@example.com", + "author_name": "Administrator", + "created_at": "2015-12-24T16:51:14.000+01:00", + "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", + "message": "Test the CI integration.", + "short_id": "0ff3ae19", + "title": "Test the CI integration." + }, + "coverage": null, + "archived": false, + "source": "push", + "allow_failure": false, + "created_at": "2015-12-24T15:51:21.727Z", + "started_at": "2015-12-24T17:54:24.729Z", + "finished_at": "2015-12-24T17:54:24.921Z", + "erased_at": null, + "duration": 0.192, + "queued_duration": 0.023, + "artifacts_expire_at": "2016-01-23T17:54:24.921Z", + "tag_list": [ + "docker runner", "win10-2004" + ], + "id": 6, + "name": "rspec:other", + "pipeline": { + "id": 6, + "project_id": 1, + "ref": "main", + "sha": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", + "status": "pending" + }, + "ref": "main", + "artifacts": [], + "runner": null, + "runner_manager": null, + "stage": "test", + "status": "failed", + "failure_reason": "stuck_or_timeout_failure", + "tag": false, + "web_url": "https://example.com/foo/bar/-/jobs/6", + "project": { + "ci_job_token_scope_enabled": false + }, + "user": { + "id": 123, + "name": "Administrator", + "username": "root", + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", + "web_url": "http://gitlab.dev/root", + "created_at": "2015-12-21T13:14:24.077Z", + "bio": null, + "location": null, + "public_email": "", + "linkedin": "", + "twitter": "", + "website_url": "", + "organization": "" + } + } +]' +] + { #category : #running } GitlabModelImporterTest >> setUp [ @@ -99,6 +261,23 @@ GitlabModelImporterTest >> testImportDiffOfMergeRequest [ self assert: (model allWithType: GLHDiff) size equals: 3 ] +{ #category : #tests } +GitlabModelImporterTest >> testImportJobsOf [ + + | json jobsArray job | + json := self jobsJson. + + jobsArray := importer importJobsOf: (GLHPipeline new + id: 12; + project: (GLHProject new id: 12; repository: GLHRepository new); + yourself). + + job := jobsArray first. + + self assert: jobsArray size equals: 2. + self assert: job name equals: 'teaspoon' +] + { #category : #tests } GitlabModelImporterTest >> testImportUserAlreadyInModel [ @@ -195,7 +374,7 @@ GitlabModelImporterTest >> testParseNote [ ] { #category : #tests } -GitlabModelImporterTest >> testParseUserResult [ +GitlabModelImporterTest >> testimportUser [ | user | user := importer importUser: 123. diff --git a/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st b/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st index 3d242e26..c4f6c4a2 100644 --- a/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st +++ b/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st @@ -244,6 +244,26 @@ GitlabModelImporter >> configureReaderForGroup: reader [ (mapping mapInstVar: #projects) valueSchema: #ArrayOfProject ] ] +{ #category : #'private - configure reader' } +GitlabModelImporter >> configureReaderForJob: reader [ + + super configureReaderForJob: reader. + + "reader for: GLHJob do: [ :mapping | + + mapping + mapProperty: #user + getter: [ :object | #ignore ] + setter: [ :object :value | + object user: (self importUser: (value at: #id)) ]. + + mapping + mapProperty: #duration + getter: [ :object | #ignore ] + setter: [ :object :value | + value ifNotNil: [ object duration: value seconds ] ] ]" +] + { #category : #'private - configure reader' } GitlabModelImporter >> configureReaderForMergeRequest: reader [ "declare quil y a un array a mapper" @@ -1807,35 +1827,18 @@ GitlabModelImporter >> parseGroupResult: aResult [ GitlabModelImporter >> parseJobsResult: result ofProject: aProject [ | reader | - reader := NeoJSONReader on: result readStream. - reader for: GLHJob do: [ :mapping | - mapping mapInstVars: #( id allow_failure web_url name ). - - mapping - mapProperty: #user - getter: [ :object | #ignore ] - setter: [ :object :value | - object user: (self importUser: (value at: #id)) ]. - + reader := generalReader on: result readStream. + "reader for: GLHJob do: [ :mapping | mapping mapProperty: #commit getter: [ :object | #ignore ] setter: [ :object :value | value ifNotNil: [ object commit: - (self importCommit: (value at: #id) ofProject: aProject) ] ]. + (self importCommit: (value at: #id) ofProject: aProject) ] ] ]." - mapping - mapProperty: #duration - getter: [ :object | #ignore ] - setter: [ :object :value | - value ifNotNil: [ object duration: value seconds ] ] ]. - reader - for: #ArrayOfGLHJob - customDo: [ :customMappting | - customMappting listOfElementSchema: GLHJob ]. - ^ reader nextAs: #ArrayOfGLHJob + ^ reader nextAs: #ArrayOfJob ] { #category : #'private - parsing' } diff --git a/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st b/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st index 1b606c60..1613c67b 100644 --- a/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st +++ b/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st @@ -269,6 +269,15 @@ GitModelImporter >> configureReaderForIssue: reader [ customMappting listOfElementSchema: GLHIssue ] ] +{ #category : #'private - configure reader' } +GitModelImporter >> configureReaderForJob: reader [ + + reader mapInstVarsFor: GLHJob . + + reader for: #ArrayOfJob customDo: [ :customMappting | + customMappting listOfElementSchema: GLHJob ] +] + { #category : #'private - configure reader' } GitModelImporter >> configureReaderForMergeRequest: reader [ @@ -607,6 +616,7 @@ GitModelImporter >> importUserByUsername: username [ { #category : #'private - configure reader' } GitModelImporter >> initReader [ + | configurators | generalReader := NeoJSONReader new. "will be reuse for all reader next" @@ -615,20 +625,11 @@ GitModelImporter >> initReader [ mapping decoder: [ :string | string ifNil: [ nil ] ifNotNil: [ DateAndTime fromString: string ] ] ]. + configurators := self class selectors select: [ :m | + m beginsWith: #configureReaderFor ]. - self configureReaderForCommit: generalReader. - self configureReaderForGroup: generalReader. - self configureReaderForDiff: generalReader. - self configureReaderForMergeRequest: generalReader. - self configureReaderForPipeline: generalReader. - self configureReaderForTag: generalReader. - self configureReaderForRelease: generalReader. - self configureReaderForUser: generalReader. - self configureReaderForBranch: generalReader. - self configureReaderForIssue: generalReader. - self configureReaderForMilestone: generalReader. - self configureReaderForNote: generalReader. - self configureReaderForProject: generalReader + configurators do: [ :configureReader | + self perform: configureReader with: generalReader ] ] { #category : #initialization } From 9221e4a4efc26973fb59b9b31070cb4c7353243f Mon Sep 17 00:00:00 2001 From: HLAD Nicolas Date: Tue, 23 Sep 2025 15:28:16 +0200 Subject: [PATCH 26/52] fix job import (gitlab) --- .../GitlabModelImporter.class.st | 84 +++++++++++++++---- 1 file changed, 69 insertions(+), 15 deletions(-) diff --git a/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st b/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st index c4f6c4a2..dd26d4b9 100644 --- a/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st +++ b/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st @@ -120,6 +120,27 @@ GitlabModelImporter >> completeImportedCommit: aCommit [ ^ aCommit ] +{ #category : #'import - jobs' } +GitlabModelImporter >> completeImportedJob: aGLHJob [ + + aGLHJob commit ifNil: [ + |commit| + commit := self + importCommit: + (aGLHJob cacheAt: #commitID ifAbsent: [ '' ]) + ofProject: aGLHJob pipeline project. + aGLHJob commit: commit. ]. + + aGLHJob user ifNil: [ + |user| + user := self importUser: (aGLHJob cacheAt: #userID ifAbsent: [ '' ]). + aGLHJob user: user. + ]. + + + ^ aGLHJob +] + { #category : #'import - pipelines' } GitlabModelImporter >> completeImportedPipeline: aGLHPipeline [ |result parsedResult| @@ -249,19 +270,39 @@ GitlabModelImporter >> configureReaderForJob: reader [ super configureReaderForJob: reader. - "reader for: GLHJob do: [ :mapping | - - mapping + reader + for: GLHJob + do: [ :mapping | "(mapping mapInstVar: #user) valueSchema: GLHUser. + (mapping mapInstVar: #pipeline) valueSchema: GLHPipeline." + mapping + mapProperty: #user + getter: [ ] + setter: [ :job :rawUser | + job cacheAt: #userID put: (rawUser at: #id) ]. + + mapping + mapProperty: #pipeline + getter: [ ] + setter: [ :job :rawPipeline | + job cacheAt: #pipelineID put: (rawPipeline at: #id) ]. + + mapping + mapProperty: #commit + getter: [ ] + setter: [ :job :rawCommit | + job cacheAt: #commitID put: (rawCommit at: #id) ]. + + "mapping mapProperty: #user getter: [ :object | #ignore ] setter: [ :object :value | - object user: (self importUser: (value at: #id)) ]. + object user: (self importUser: (value at: #id)) ]." - mapping - mapProperty: #duration - getter: [ :object | #ignore ] - setter: [ :object :value | - value ifNotNil: [ object duration: value seconds ] ] ]" + mapping + mapProperty: #duration + getter: [ :object | #ignore ] + setter: [ :object :value | + value ifNotNil: [ object duration: value seconds ] ] ] ] { #category : #'private - configure reader' } @@ -1034,10 +1075,15 @@ GitlabModelImporter >> importJobsOf: aPipeline [ "jobsOfProject: aPipeline project id ofPipelines: aPipeline id." jobs := (results collect: [ :jobsJson | - self parseJobsResult: jobsJson ofProject: aPipeline project ]) - flattened. - jobs do: [ :job | aPipeline addJob: job ]. - self glhModel addAll: jobs. + self parseJobsResult: jobsJson ]) flattened. + + + jobs := self glhModel addAll: jobs unless: self blockOnIdEquality. + jobs := aPipeline jobs addAll: jobs unless: self blockOnIdEquality. + + + jobs do: [ :job | + self completeImportedJob: job ]. ^ jobs ] @@ -1823,19 +1869,27 @@ GitlabModelImporter >> parseGroupResult: aResult [ ^ reader nextAs: GLHGroup ] +{ #category : #parsing } +GitlabModelImporter >> parseJobsResult: result [ + | reader | + reader := generalReader on: result readStream. + + ^ reader nextAs: #ArrayOfJob +] + { #category : #'private - parsing' } GitlabModelImporter >> parseJobsResult: result ofProject: aProject [ | reader | reader := generalReader on: result readStream. - "reader for: GLHJob do: [ :mapping | + reader for: GLHJob do: [ :mapping | mapping mapProperty: #commit getter: [ :object | #ignore ] setter: [ :object :value | value ifNotNil: [ object commit: - (self importCommit: (value at: #id) ofProject: aProject) ] ] ]." + (self importCommit: (value at: #id) ofProject: aProject) ] ] ]. ^ reader nextAs: #ArrayOfJob From 270cd252b3f0c260b6ef7e9a0b3c4dd61ee8487a Mon Sep 17 00:00:00 2001 From: HLAD Nicolas Date: Tue, 23 Sep 2025 17:01:46 +0200 Subject: [PATCH 27/52] add tests --- .../GLHApiMock.class.st | 35 ++ .../GitlabBranchesMock.class.st | 40 +++ .../GitlabCommitsMock.class.st | 89 ++++- .../GitlabGroupMock.class.st | 183 ++++++++++ .../GitlabMergeRequestsMock.class.st | 250 +++++++++++++ .../GitlabModelImporterTest.class.st | 231 +++++++++++- .../GitlabNotesMock.class.st | 60 ++++ .../GitlabPipelinesMock.class.st | 82 +++++ .../GitlabProjectsMock.class.st | 329 ++++++++++++++++++ .../GitlabReleasesMock.class.st | 124 +++++++ .../GitlabTagMock.class.st | 39 +++ .../GitlabModelImporter.class.st | 124 +++---- .../GitModelImporter.class.st | 5 +- 13 files changed, 1481 insertions(+), 110 deletions(-) create mode 100644 src/GitLabHealth-Model-Importer-Tests/GitlabBranchesMock.class.st create mode 100644 src/GitLabHealth-Model-Importer-Tests/GitlabGroupMock.class.st create mode 100644 src/GitLabHealth-Model-Importer-Tests/GitlabNotesMock.class.st create mode 100644 src/GitLabHealth-Model-Importer-Tests/GitlabPipelinesMock.class.st create mode 100644 src/GitLabHealth-Model-Importer-Tests/GitlabProjectsMock.class.st create mode 100644 src/GitLabHealth-Model-Importer-Tests/GitlabReleasesMock.class.st create mode 100644 src/GitLabHealth-Model-Importer-Tests/GitlabTagMock.class.st diff --git a/src/GitLabHealth-Model-Importer-Tests/GLHApiMock.class.st b/src/GitLabHealth-Model-Importer-Tests/GLHApiMock.class.st index 370c45e4..bbb0d464 100644 --- a/src/GitLabHealth-Model-Importer-Tests/GLHApiMock.class.st +++ b/src/GitLabHealth-Model-Importer-Tests/GLHApiMock.class.st @@ -4,11 +4,21 @@ Class { #category : #'GitLabHealth-Model-Importer-Tests' } +{ #category : #accessing } +GLHApiMock >> branches [ + ^ GitlabBranchesMock new . +] + { #category : #accessing } GLHApiMock >> commits [ ^GitlabCommitsMock new. ] +{ #category : #accessing } +GLHApiMock >> groups [ + ^ GitlabGroupMock new. +] + { #category : #accessing } GLHApiMock >> jobs [ ^ GitlabJobsMock new @@ -20,17 +30,42 @@ GLHApiMock >> mergeRequests [ ^ GitlabMergeRequestsMock new ] +{ #category : #accessing } +GLHApiMock >> notes [ + ^ GitlabNotesMock new. +] + { #category : #accessing } GLHApiMock >> output: aString [ ^ self ] +{ #category : #accessing } +GLHApiMock >> pipelines [ + ^ GitlabPipelinesMock new +] + +{ #category : #accessing } +GLHApiMock >> projects [ + ^ GitlabProjectsMock new . +] + +{ #category : #accessing } +GLHApiMock >> releases [ + ^ GitlabReleasesMock new. +] + { #category : #accessing } GLHApiMock >> repositories [ ^ GitlabRepositoryMock new ] +{ #category : #accessing } +GLHApiMock >> tags [ + ^GitlabTagMock new +] + { #category : #accessing } GLHApiMock >> users [ ^GitlabUsersMock new diff --git a/src/GitLabHealth-Model-Importer-Tests/GitlabBranchesMock.class.st b/src/GitLabHealth-Model-Importer-Tests/GitlabBranchesMock.class.st new file mode 100644 index 00000000..6c2370aa --- /dev/null +++ b/src/GitLabHealth-Model-Importer-Tests/GitlabBranchesMock.class.st @@ -0,0 +1,40 @@ +Class { + #name : #GitlabBranchesMock, + #superclass : #Object, + #category : #'GitLabHealth-Model-Importer-Tests' +} + +{ #category : #api } +GitlabBranchesMock >> getAllFromProject: anUndefinedObject [ + ^ {'[ + { + "name": "main", + "merged": false, + "protected": true, + "default": true, + "developers_can_push": false, + "developers_can_merge": false, + "can_push": true, + "web_url": "https://gitlab.example.com/my-group/my-project/-/tree/main", + "commit": { + "id": "7b5c3cc8be40ee161ae89a06bba6229da1032a0c", + "short_id": "7b5c3cc", + "created_at": "2024-06-28T03:44:20-07:00", + "parent_ids": [ + "4ad91d3c1144c406e50c7b33bae684bd6837faf8" + ], + "title": "add projects API", + "message": "add projects API", + "author_name": "John Smith", + "author_email": "john@example.com", + "authored_date": "2024-06-27T05:51:39-07:00", + "committer_name": "John Smith", + "committer_email": "john@example.com", + "committed_date": "2024-06-28T03:44:20-07:00", + "trailers": {}, + "extended_trailers": {}, + "web_url": "https://gitlab.example.com/my-group/my-project/-/commit/7b5c3cc8be40ee161ae89a06bba6229da1032a0c" + } + } +]'} +] diff --git a/src/GitLabHealth-Model-Importer-Tests/GitlabCommitsMock.class.st b/src/GitLabHealth-Model-Importer-Tests/GitlabCommitsMock.class.st index 4604f5fc..6d58326f 100644 --- a/src/GitLabHealth-Model-Importer-Tests/GitlabCommitsMock.class.st +++ b/src/GitLabHealth-Model-Importer-Tests/GitlabCommitsMock.class.st @@ -13,19 +13,84 @@ GitlabCommitsMock >> diffOf: commitSha inProject: projectId uniDiff: unidiff [ ] { #category : #api } -GitlabCommitsMock >> get: aString inProject: anUndefinedObject [ +GitlabCommitsMock >> get: aString inProject: anUndefinedObject [ + ^ '{ - "author_email": "admin@example.com", - "author_name": "Administrator", - "created_at": "2015-12-24T16:51:14.000+01:00", - "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", - "message": "Test the CI integration.", - "short_id": "0ff3ae19", - "title": "Test the CI integration." - }' + "id": "6104942438c14ec7bd21c6cd5bd995272b3faff6", + "short_id": "6104942438c", + "title": "Sanitize for network graph", + "author_name": "randx", + "author_email": "user@example.com", + "committer_name": "Dmitriy", + "committer_email": "user@example.com", + "created_at": "2021-09-20T09:06:12.300+03:00", + "message": "Sanitize for network graph", + "committed_date": "2021-09-20T09:06:12.300+03:00", + "authored_date": "2021-09-20T09:06:12.420+03:00", + "parent_ids": [ + "ae1d9fb46aa2b07ee9836d49862ec4e2c46fbbba" + ], + "last_pipeline": { + "id": 8, + "ref": "main", + "sha": "2dc6aa325a317eda67812f05600bdf0fcdc70ab0", + "status": "created" + }, + "stats": { + "additions": 15, + "deletions": 10, + "total": 25 + }, + "status": "running", + "web_url": "https://gitlab.example.com/janedoe/gitlab-foss/-/commit/6104942438c14ec7bd21c6cd5bd995272b3faff6" +}' ] -{ #category : #accessing } -GitlabCommitsMock >> readStream [ - self shouldBeImplemented. +{ #category : #api } +GitlabCommitsMock >> getByPage: anInteger perPage: anInteger2 inProject: anUndefinedObject withParams: aCollection [ + ^ '[ + { + "id": "ed899a2f4b50b4370feeea94676502b42383c746", + "short_id": "ed899a2f4b5", + "title": "Replace sanitize with escape once", + "author_name": "Example User", + "author_email": "user@example.com", + "authored_date": "2021-09-20T11:50:22.001+00:00", + "committer_name": "Administrator", + "committer_email": "admin@example.com", + "committed_date": "2021-09-20T11:50:22.001+00:00", + "created_at": "2021-09-20T11:50:22.001+00:00", + "message": "Replace sanitize with escape once", + "parent_ids": [ + "6104942438c14ec7bd21c6cd5bd995272b3faff6" + ], + "web_url": "https://gitlab.example.com/janedoe/gitlab-foss/-/commit/ed899a2f4b50b4370feeea94676502b42383c746", + "trailers": {}, + "extended_trailers": {} + }, + { + "id": "6104942438c14ec7bd21c6cd5bd995272b3faff6", + "short_id": "6104942438c", + "title": "Sanitize for network graph", + "author_name": "randx", + "author_email": "user@example.com", + "committer_name": "ExampleName", + "committer_email": "user@example.com", + "created_at": "2021-09-20T09:06:12.201+00:00", + "message": "Sanitize for network graph\nCc: John Doe \nCc: Jane Doe ", + "parent_ids": [ + "ae1d9fb46aa2b07ee9836d49862ec4e2c46fbbba" + ], + "web_url": "https://gitlab.example.com/janedoe/gitlab-foss/-/commit/ed899a2f4b50b4370feeea94676502b42383c746", + "trailers": { + "Cc": "Jane Doe " + }, + "extended_trailers": { + "Cc": [ + "John Doe ", + "Jane Doe " + ] + } + } +]' ] diff --git a/src/GitLabHealth-Model-Importer-Tests/GitlabGroupMock.class.st b/src/GitLabHealth-Model-Importer-Tests/GitlabGroupMock.class.st new file mode 100644 index 00000000..b8131d49 --- /dev/null +++ b/src/GitLabHealth-Model-Importer-Tests/GitlabGroupMock.class.st @@ -0,0 +1,183 @@ +Class { + #name : #GitlabGroupMock, + #superclass : #Object, + #category : #'GitLabHealth-Model-Importer-Tests' +} + +{ #category : #api } +GitlabGroupMock >> get: anInteger [ + + ^ '{ + "id": 4, + "name": "Twitter", + "path": "twitter", + "description": "Aliquid qui quis dignissimos distinctio ut commodi voluptas est.", + "visibility": "public", + "avatar_url": null, + "web_url": "https://gitlab.example.com/groups/twitter", + "request_access_enabled": false, + "repository_storage": "default", + "full_name": "Twitter", + "full_path": "twitter", + "runners_token": "ba324ca7b1c77fc20bb9", + "file_template_project_id": 1, + "parent_id": null, + "enabled_git_access_protocol": "all", + "created_at": "2020-01-15T12:36:29.590Z", + "shared_with_groups": [ + { + "group_id": 28, + "group_name": "H5bp", + "group_full_path": "h5bp", + "group_access_level": 20, + "expires_at": null + } + ], + "prevent_sharing_groups_outside_hierarchy": false, + "projects": [ + { + "id": 7, + "description": "Voluptas veniam qui et beatae voluptas doloremque explicabo facilis.", + "default_branch": "main", + "tag_list": [], + "topics": [], + "archived": false, + "visibility": "public", + "ssh_url_to_repo": "git@gitlab.example.com:twitter/typeahead-js.git", + "http_url_to_repo": "https://gitlab.example.com/twitter/typeahead-js.git", + "web_url": "https://gitlab.example.com/twitter/typeahead-js", + "name": "Typeahead.Js", + "name_with_namespace": "Twitter / Typeahead.Js", + "path": "typeahead-js", + "path_with_namespace": "twitter/typeahead-js", + "issues_enabled": true, + "merge_requests_enabled": true, + "wiki_enabled": true, + "jobs_enabled": true, + "snippets_enabled": false, + "container_registry_enabled": true, + "created_at": "2016-06-17T07:47:25.578Z", + "last_activity_at": "2016-06-17T07:47:25.881Z", + "shared_runners_enabled": true, + "creator_id": 1, + "namespace": { + "id": 4, + "name": "Twitter", + "path": "twitter", + "kind": "group" + }, + "avatar_url": null, + "star_count": 0, + "forks_count": 0, + "open_issues_count": 3, + "public_jobs": true, + "shared_with_groups": [], + "request_access_enabled": false + }, + { + "id": 6, + "description": "Aspernatur omnis repudiandae qui voluptatibus eaque.", + "default_branch": "main", + "tag_list": [], + "topics": [], + "archived": false, + "visibility": "internal", + "ssh_url_to_repo": "git@gitlab.example.com:twitter/flight.git", + "http_url_to_repo": "https://gitlab.example.com/twitter/flight.git", + "web_url": "https://gitlab.example.com/twitter/flight", + "name": "Flight", + "name_with_namespace": "Twitter / Flight", + "path": "flight", + "path_with_namespace": "twitter/flight", + "issues_enabled": true, + "merge_requests_enabled": true, + "wiki_enabled": true, + "jobs_enabled": true, + "snippets_enabled": false, + "container_registry_enabled": true, + "created_at": "2016-06-17T07:47:24.661Z", + "last_activity_at": "2016-06-17T07:47:24.838Z", + "shared_runners_enabled": true, + "creator_id": 1, + "namespace": { + "id": 4, + "name": "Twitter", + "path": "twitter", + "kind": "group" + }, + "avatar_url": null, + "star_count": 0, + "forks_count": 0, + "open_issues_count": 8, + "public_jobs": true, + "shared_with_groups": [], + "request_access_enabled": false + } + ], + "shared_projects": [ + { + "id": 8, + "description": "Velit eveniet provident fugiat saepe eligendi autem.", + "default_branch": "main", + "tag_list": [], + "topics": [], + "archived": false, + "visibility": "private", + "ssh_url_to_repo": "git@gitlab.example.com:h5bp/html5-boilerplate.git", + "http_url_to_repo": "https://gitlab.example.com/h5bp/html5-boilerplate.git", + "web_url": "https://gitlab.example.com/h5bp/html5-boilerplate", + "name": "Html5 Boilerplate", + "name_with_namespace": "H5bp / Html5 Boilerplate", + "path": "html5-boilerplate", + "path_with_namespace": "h5bp/html5-boilerplate", + "issues_enabled": true, + "merge_requests_enabled": true, + "wiki_enabled": true, + "jobs_enabled": true, + "snippets_enabled": false, + "container_registry_enabled": true, + "created_at": "2016-06-17T07:47:27.089Z", + "last_activity_at": "2016-06-17T07:47:27.310Z", + "shared_runners_enabled": true, + "creator_id": 1, + "namespace": { + "id": 5, + "name": "H5bp", + "path": "h5bp", + "kind": "group" + }, + "avatar_url": null, + "star_count": 0, + "forks_count": 0, + "open_issues_count": 4, + "public_jobs": true, + "shared_with_groups": [ + { + "group_id": 4, + "group_name": "Twitter", + "group_full_path": "twitter", + "group_access_level": 30, + "expires_at": null + }, + { + "group_id": 3, + "group_name": "Gitlab Org", + "group_full_path": "gitlab-org", + "group_access_level": 10, + "expires_at": "2018-08-14" + } + ] + } + ], + "ip_restriction_ranges": null, + "math_rendering_limits_enabled": true, + "lock_math_rendering_limits_enabled": false +}' +] + +{ #category : #'api - subgroups' } +GitlabGroupMock >> subgroupsOf: anInteger [ + "can't have subgroup otherwise while true block" + ^ { '[ +]' } +] diff --git a/src/GitLabHealth-Model-Importer-Tests/GitlabMergeRequestsMock.class.st b/src/GitLabHealth-Model-Importer-Tests/GitlabMergeRequestsMock.class.st index 765237d1..5158ec7b 100644 --- a/src/GitLabHealth-Model-Importer-Tests/GitlabMergeRequestsMock.class.st +++ b/src/GitLabHealth-Model-Importer-Tests/GitlabMergeRequestsMock.class.st @@ -54,3 +54,253 @@ GitlabMergeRequestsMock >> get: id inProject: projectId [ "merge_user":{ "id": 12 } }' ] + +{ #category : #api } +GitlabMergeRequestsMock >> getAllOfProject: anUndefinedObject [ + ^ { '[ + { + "id": 1, + "iid": 1, + "project_id": 3, + "title": "test1", + "description": "fixed login page css paddings", + "state": "merged", + "imported": false, + "imported_from": "none", + "merged_by": { + "id": 87854, + "name": "Douwe Maan", + "username": "DouweM", + "state": "active", + "avatar_url": "https://gitlab.example.com/uploads/-/system/user/avatar/87854/avatar.png", + "web_url": "https://gitlab.com/DouweM" + }, + "merge_user": { + "id": 87854, + "name": "Douwe Maan", + "username": "DouweM", + "state": "active", + "avatar_url": "https://gitlab.example.com/uploads/-/system/user/avatar/87854/avatar.png", + "web_url": "https://gitlab.com/DouweM" + }, + "merged_at": "2018-09-07T11:16:17.520Z", + "merge_after": "2018-09-07T11:16:00.000Z", + "prepared_at": "2018-09-04T11:16:17.520Z", + "closed_by": null, + "closed_at": null, + "created_at": "2017-04-29T08:46:00Z", + "updated_at": "2017-04-29T08:46:00Z", + "target_branch": "main", + "source_branch": "test1", + "upvotes": 0, + "downvotes": 0, + "author": { + "id": 1, + "name": "Administrator", + "username": "admin", + "state": "active", + "avatar_url": null, + "web_url" : "https://gitlab.example.com/admin" + }, + "assignee": { + "id": 1, + "name": "Administrator", + "username": "admin", + "state": "active", + "avatar_url": null, + "web_url" : "https://gitlab.example.com/admin" + }, + "assignees": [{ + "name": "Miss Monserrate Beier", + "username": "axel.block", + "id": 12, + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon", + "web_url": "https://gitlab.example.com/axel.block" + }], + "reviewers": [{ + "id": 2, + "name": "Sam Bauch", + "username": "kenyatta_oconnell", + "state": "active", + "avatar_url": "https://www.gravatar.com/avatar/956c92487c6f6f7616b536927e22c9a0?s=80&d=identicon", + "web_url": "http://gitlab.example.com//kenyatta_oconnell" + }], + "source_project_id": 2, + "target_project_id": 3, + "labels": [ + "Community contribution", + "Manage" + ], + "draft": false, + "work_in_progress": false, + "milestone": { + "id": 5, + "iid": 1, + "project_id": 3, + "title": "v2.0", + "description": "Assumenda aut placeat expedita exercitationem labore sunt enim earum.", + "state": "closed", + "created_at": "2015-02-02T19:49:26.013Z", + "updated_at": "2015-02-02T19:49:26.013Z", + "due_date": "2018-09-22", + "start_date": "2018-08-08", + "web_url": "https://gitlab.example.com/my-group/my-project/milestones/1" + }, + "merge_when_pipeline_succeeds": true, + "merge_status": "can_be_merged", + "detailed_merge_status": "not_open", + "sha": "8888888888888888888888888888888888888888", + "merge_commit_sha": null, + "squash_commit_sha": null, + "user_notes_count": 1, + "discussion_locked": null, + "should_remove_source_branch": true, + "force_remove_source_branch": false, + "allow_collaboration": false, + "allow_maintainer_to_push": false, + "web_url": "http://gitlab.example.com/my-group/my-project/merge_requests/1", + "references": { + "short": "!1", + "relative": "my-group/my-project!1", + "full": "my-group/my-project!1" + }, + "time_stats": { + "time_estimate": 0, + "total_time_spent": 0, + "human_time_estimate": null, + "human_total_time_spent": null + }, + "squash": false, + "task_completion_status":{ + "count":0, + "completed_count":0 + } + } +]' } +] + +{ #category : #api } +GitlabMergeRequestsMock >> getByPage: anInteger perPage: anInteger2 inProject: anUndefinedObject [ + ^ '[ + { + "id": 1, + "iid": 1, + "project_id": 3, + "title": "test1", + "description": "fixed login page css paddings", + "state": "merged", + "imported": false, + "imported_from": "none", + "merged_by": { + "id": 87854, + "name": "Douwe Maan", + "username": "DouweM", + "state": "active", + "avatar_url": "https://gitlab.example.com/uploads/-/system/user/avatar/87854/avatar.png", + "web_url": "https://gitlab.com/DouweM" + }, + "merge_user": { + "id": 87854, + "name": "Douwe Maan", + "username": "DouweM", + "state": "active", + "avatar_url": "https://gitlab.example.com/uploads/-/system/user/avatar/87854/avatar.png", + "web_url": "https://gitlab.com/DouweM" + }, + "merged_at": "2018-09-07T11:16:17.520Z", + "merge_after": "2018-09-07T11:16:00.000Z", + "prepared_at": "2018-09-04T11:16:17.520Z", + "closed_by": null, + "closed_at": null, + "created_at": "2017-04-29T08:46:00Z", + "updated_at": "2017-04-29T08:46:00Z", + "target_branch": "main", + "source_branch": "test1", + "upvotes": 0, + "downvotes": 0, + "author": { + "id": 1, + "name": "Administrator", + "username": "admin", + "state": "active", + "avatar_url": null, + "web_url" : "https://gitlab.example.com/admin" + }, + "assignee": { + "id": 1, + "name": "Administrator", + "username": "admin", + "state": "active", + "avatar_url": null, + "web_url" : "https://gitlab.example.com/admin" + }, + "assignees": [{ + "name": "Miss Monserrate Beier", + "username": "axel.block", + "id": 12, + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon", + "web_url": "https://gitlab.example.com/axel.block" + }], + "reviewers": [{ + "id": 2, + "name": "Sam Bauch", + "username": "kenyatta_oconnell", + "state": "active", + "avatar_url": "https://www.gravatar.com/avatar/956c92487c6f6f7616b536927e22c9a0?s=80&d=identicon", + "web_url": "http://gitlab.example.com//kenyatta_oconnell" + }], + "source_project_id": 2, + "target_project_id": 3, + "labels": [ + "Community contribution", + "Manage" + ], + "draft": false, + "work_in_progress": false, + "milestone": { + "id": 5, + "iid": 1, + "project_id": 3, + "title": "v2.0", + "description": "Assumenda aut placeat expedita exercitationem labore sunt enim earum.", + "state": "closed", + "created_at": "2015-02-02T19:49:26.013Z", + "updated_at": "2015-02-02T19:49:26.013Z", + "due_date": "2018-09-22", + "start_date": "2018-08-08", + "web_url": "https://gitlab.example.com/my-group/my-project/milestones/1" + }, + "merge_when_pipeline_succeeds": true, + "merge_status": "can_be_merged", + "detailed_merge_status": "not_open", + "sha": "8888888888888888888888888888888888888888", + "merge_commit_sha": null, + "squash_commit_sha": null, + "user_notes_count": 1, + "discussion_locked": null, + "should_remove_source_branch": true, + "force_remove_source_branch": false, + "allow_collaboration": false, + "allow_maintainer_to_push": false, + "web_url": "http://gitlab.example.com/my-group/my-project/merge_requests/1", + "references": { + "short": "!1", + "relative": "my-group/my-project!1", + "full": "my-group/my-project!1" + }, + "time_stats": { + "time_estimate": 0, + "total_time_spent": 0, + "human_time_estimate": null, + "human_total_time_spent": null + }, + "squash": false, + "task_completion_status":{ + "count":0, + "completed_count":0 + } + } +]' +] diff --git a/src/GitLabHealth-Model-Importer-Tests/GitlabModelImporterTest.class.st b/src/GitLabHealth-Model-Importer-Tests/GitlabModelImporterTest.class.st index 7352c31f..bd2bbef6 100644 --- a/src/GitLabHealth-Model-Importer-Tests/GitlabModelImporterTest.class.st +++ b/src/GitLabHealth-Model-Importer-Tests/GitlabModelImporterTest.class.st @@ -12,7 +12,7 @@ Class { #category : #'GitLabHealth-Model-Importer-Tests' } -{ #category : #test } +{ #category : #json } GitlabModelImporterTest >> gitlabDiffData [ ^ '[{"b_mode":"100644","diff":"@@ -80,5 +80,10 @@ test test test {\r test test test(@test test[] test) test test, test {\r \ttest test(test.test(test), test.test_test, test);\r }\r+ \r+ @test(\"/testAvisMandtestement\")\r+ test test testAvisMandtestement(@test test[] test) test test, test {\r+ \ttest test(test.testAvisMandtestement(test), test.test_test, test);\r+ }\r \r }\r\\ test test test test test test\r","new_path":"@@ -80,5 +80,10 @@ test test test {\r test test test(@test test[] test) test test, test {\r \ttest test(test.test(test), test.test_test, test);\r }\r+ \r+ @test(\"/testAvisMandtestement\")\r+ test test testAvisMandtestement(@test test[] test) test test, test {\r+ \ttest test(test.testAvisMandtestement(test), test.test_test, test);\r+ }\r \r }\r\\ test test test test test test\r","a_mode":"100644","old_path":"@@ -80,5 +80,10 @@ test test test {\r test test test(@test test[] test) test test, test {\r \ttest test(test.test(test), test.test_test, test);\r }\r+ \r+ @test(\"/testAvisMandtestement\")\r+ test test testAvisMandtestement(@test test[] test) test test, test {\r+ \ttest test(test.testAvisMandtestement(test), test.test_test, test);\r+ }\r \r }\r\\ test test test test test test\r","new_file":false,"deleted_file":false,"renamed_file":false},{"b_mode":"100644","diff":"@@ -11,6 +11,7 @@ import org.springframework.stereotype.Service;\n import fr.bl.avenir.gf.rest.ecompta.edition.enums.TypeBordereauVolet;\n import fr.bl.avenir.gf.rest.ecompta.edition.enums.TypeReportEnumeration;\n import fr.bl.avenir.gf.rest.ecompta.edition.service.avis.ServiceImprimerAvis;\n+import fr.bl.avenir.gf.rest.ecompta.edition.service.avismandatement.ServiceImprimerAvisMandatement;\n import fr.bl.avenir.gf.rest.ecompta.edition.service.bordereau.ServiceImprimerBordereauMandat;\n import fr.bl.avenir.gf.rest.ecompta.edition.service.bordereau.ServiceImprimerBordereauTitre;\n import fr.magnus.reftechnique.transverse.EntiteRelationnelle;\n@@ -26,12 +27,12 @@ public class EditionService {\n \n @Autowired\n ServiceImprimerBordereauMandat serviceImprimerBordereauMandat;\n- \n @Autowired\n ServiceImprimerBordereauTitre serviceImprimerBordereauTitre;\n- \n @Autowired\n ServiceImprimerAvis serviceImprimerAvis;\n+ @Autowired\n+ ServiceImprimerAvis serviceImprimerAvisMandatement;\n \n public byte[] imprimerBordereauMandatVolet1( TableauAbstract[] jsonData) throws JRException, ParseException {\n Map params = new HashMap<>();\n@@ -85,6 +86,10 @@ public class EditionService {\n \treturn serviceImprimerAvis.imprimerFichier(jsonData, params, TypeReportEnumeration.AVIS_SOMMES_A_PAYER_SANS_EXP);\n }\n \t\n- \n+ public byte[] imprimerAvisMandatement(TableauAbstract[] jsonData) throws JRException, ParseException {\n+ \treturn serviceImprimerAvisMandatement.imprimerFichier(jsonData, null, TypeReportEnumeration.AVIS_MANDATEMENT);\n+ }\n+ \n+ \n \n }\n\\ No newline at end of file\n","new_path":"@@ -11,6 +11,7 @@ import org.springframework.stereotype.Service;\n import fr.bl.avenir.gf.rest.ecompta.edition.enums.TypeBordereauVolet;\n import fr.bl.avenir.gf.rest.ecompta.edition.enums.TypeReportEnumeration;\n import fr.bl.avenir.gf.rest.ecompta.edition.service.avis.ServiceImprimerAvis;\n+import fr.bl.avenir.gf.rest.ecompta.edition.service.avismandatement.ServiceImprimerAvisMandatement;\n import fr.bl.avenir.gf.rest.ecompta.edition.service.bordereau.ServiceImprimerBordereauMandat;\n import fr.bl.avenir.gf.rest.ecompta.edition.service.bordereau.ServiceImprimerBordereauTitre;\n import fr.magnus.reftechnique.transverse.EntiteRelationnelle;\n@@ -26,12 +27,12 @@ public class EditionService {\n \n @Autowired\n ServiceImprimerBordereauMandat serviceImprimerBordereauMandat;\n- \n @Autowired\n ServiceImprimerBordereauTitre serviceImprimerBordereauTitre;\n- \n @Autowired\n ServiceImprimerAvis serviceImprimerAvis;\n+ @Autowired\n+ ServiceImprimerAvis serviceImprimerAvisMandatement;\n \n public byte[] imprimerBordereauMandatVolet1( TableauAbstract[] jsonData) throws JRException, ParseException {\n Map params = new HashMap<>();\n@@ -85,6 +86,10 @@ public class EditionService {\n \treturn serviceImprimerAvis.imprimerFichier(jsonData, params, TypeReportEnumeration.AVIS_SOMMES_A_PAYER_SANS_EXP);\n }\n \t\n- \n+ public byte[] imprimerAvisMandatement(TableauAbstract[] jsonData) throws JRException, ParseException {\n+ \treturn serviceImprimerAvisMandatement.imprimerFichier(jsonData, null, TypeReportEnumeration.AVIS_MANDATEMENT);\n+ }\n+ \n+ \n \n }\n\\ No newline at end of file\n","a_mode":"100644","old_path":"@@ -11,6 +11,7 @@ import org.springframework.stereotype.Service;\n import fr.bl.avenir.gf.rest.ecompta.edition.enums.TypeBordereauVolet;\n import fr.bl.avenir.gf.rest.ecompta.edition.enums.TypeReportEnumeration;\n import fr.bl.avenir.gf.rest.ecompta.edition.service.avis.ServiceImprimerAvis;\n+import fr.bl.avenir.gf.rest.ecompta.edition.service.avismandatement.ServiceImprimerAvisMandatement;\n import fr.bl.avenir.gf.rest.ecompta.edition.service.bordereau.ServiceImprimerBordereauMandat;\n import fr.bl.avenir.gf.rest.ecompta.edition.service.bordereau.ServiceImprimerBordereauTitre;\n import fr.magnus.reftechnique.transverse.EntiteRelationnelle;\n@@ -26,12 +27,12 @@ public class EditionService {\n \n @Autowired\n ServiceImprimerBordereauMandat serviceImprimerBordereauMandat;\n- \n @Autowired\n ServiceImprimerBordereauTitre serviceImprimerBordereauTitre;\n- \n @Autowired\n ServiceImprimerAvis serviceImprimerAvis;\n+ @Autowired\n+ ServiceImprimerAvis serviceImprimerAvisMandatement;\n \n public byte[] imprimerBordereauMandatVolet1( TableauAbstract[] jsonData) throws JRException, ParseException {\n Map params = new HashMap<>();\n@@ -85,6 +86,10 @@ public class EditionService {\n \treturn serviceImprimerAvis.imprimerFichier(jsonData, params, TypeReportEnumeration.AVIS_SOMMES_A_PAYER_SANS_EXP);\n }\n \t\n- \n+ public byte[] imprimerAvisMandatement(TableauAbstract[] jsonData) throws JRException, ParseException {\n+ \treturn serviceImprimerAvisMandatement.imprimerFichier(jsonData, null, TypeReportEnumeration.AVIS_MANDATEMENT);\n+ }\n+ \n+ \n \n }\n\\ No newline at end of file\n","new_file":false,"deleted_file":false,"renamed_file":false},{"b_mode":"100644","diff":"@@ -0,0 +1,25 @@\n+package fr.bl.avenir.gf.rest.ecompta.edition.dto.avismandatement;\n+\n+import lombok.Getter;\n+import lombok.NoArgsConstructor;\n+import lombok.Setter;\n+\n+@NoArgsConstructor\n+@Getter\n+@Setter\n+public class DTOAvisMandatement {\n+\tprivate String collectiviteLogo;\n+\tprivate String collectiviteNom;\n+\tprivate String collectiviteAdresse;\n+\tprivate String collectiviteSignataire;\n+\tprivate String collectiviteSignature;\n+\tprivate String collectiviteTampon;\n+\tprivate String tiersNom;\n+\tprivate String tiersAdresse;\n+\tprivate String texteCourrier;\n+\tprivate String pieceJustificative;\n+\tprivate String pieceJustificativePjIdUnique;\n+\tprivate String observation;\n+\tprivate String comptableAssignataire;\n+\tprivate String contexte;\n+}\n","new_path":"@@ -0,0 +1,25 @@\n+package fr.bl.avenir.gf.rest.ecompta.edition.dto.avismandatement;\n+\n+import lombok.Getter;\n+import lombok.NoArgsConstructor;\n+import lombok.Setter;\n+\n+@NoArgsConstructor\n+@Getter\n+@Setter\n+public class DTOAvisMandatement {\n+\tprivate String collectiviteLogo;\n+\tprivate String collectiviteNom;\n+\tprivate String collectiviteAdresse;\n+\tprivate String collectiviteSignataire;\n+\tprivate String collectiviteSignature;\n+\tprivate String collectiviteTampon;\n+\tprivate String tiersNom;\n+\tprivate String tiersAdresse;\n+\tprivate String texteCourrier;\n+\tprivate String pieceJustificative;\n+\tprivate String pieceJustificativePjIdUnique;\n+\tprivate String observation;\n+\tprivate String comptableAssignataire;\n+\tprivate String contexte;\n+}\n","a_mode":"0","old_path":"@@ -0,0 +1,25 @@\n+package fr.bl.avenir.gf.rest.ecompta.edition.dto.avismandatement;\n+\n+import lombok.Getter;\n+import lombok.NoArgsConstructor;\n+import lombok.Setter;\n+\n+@NoArgsConstructor\n+@Getter\n+@Setter\n+public class DTOAvisMandatement {\n+\tprivate String collectiviteLogo;\n+\tprivate String collectiviteNom;\n+\tprivate String collectiviteAdresse;\n+\tprivate String collectiviteSignataire;\n+\tprivate String collectiviteSignature;\n+\tprivate String collectiviteTampon;\n+\tprivate String tiersNom;\n+\tprivate String tiersAdresse;\n+\tprivate String texteCourrier;\n+\tprivate String pieceJustificative;\n+\tprivate String pieceJustificativePjIdUnique;\n+\tprivate String observation;\n+\tprivate String comptableAssignataire;\n+\tprivate String contexte;\n+}\n","new_file":true,"deleted_file":false,"renamed_file":false},{"b_mode":"100644","diff":"@@ -34,7 +34,6 @@ public class TypeReportEnumeration extends EnumerationAbstract {\n public static final TypeReportEnumeration TITRE_VOLET2 = new TypeReportEnumeration(6, \"Bordereau de titres Volet 2\", JASPER_REPORT_BORDEREAU_TITRE);\n public static final TypeReportEnumeration TITRE_VOLET3 = new TypeReportEnumeration(7, \"Bordereau de titres Volet 3\", JASPER_REPORT_BORDEREAU_TITRE);\n public static final TypeReportEnumeration TITRE = new TypeReportEnumeration(8, \"Bordereau de titres\", JASPER_REPORT_BORDEREAU_TITRE);\n- private JasperReport jasperReport;\n \n \t// --- AVIS\n private static final String JASPER_AVIS_REPOSITORY = \"/jasper/avis/\";\n@@ -44,7 +43,13 @@ public class TypeReportEnumeration extends EnumerationAbstract {\n public static final TypeReportEnumeration AVIS_SOMMES_A_PAYER = new TypeReportEnumeration(9, \"Avis des sommes à payer\", JASPER_REPORT_AVIS);\n public static final TypeReportEnumeration AVIS_SOMMES_A_PAYER_SANS_EXP = new TypeReportEnumeration(10, \"Avis des sommes à payer sans expéditeur\", JASPER_REPORT_AVIS);\n \n+ // --- AVIS MANDATEMENT\n+ private static final String JASPER_AVIS_MANDATEMENT_REPOSITORY = \"/jasper/avismandatement/\";\n+ private static final String[] JASPER_AVIS_MANDATEMENT_REPORTS = new String[] {\"avisMandatement.jrxml\"};\n+ private static final JasperReport JASPER_REPORT_AVIS_MANDATEMENT = getJasperReport(JASPER_AVIS_MANDATEMENT_REPOSITORY, JASPER_AVIS_MANDATEMENT_REPORTS);\n+ public static final TypeReportEnumeration AVIS_MANDATEMENT= new TypeReportEnumeration(9, \"Avis mandatement\", JASPER_REPORT_AVIS_MANDATEMENT);\n \n+ private JasperReport jasperReport;\n public JasperReport getJasperReport() {\n return jasperReport;\n }\n","new_path":"@@ -34,7 +34,6 @@ public class TypeReportEnumeration extends EnumerationAbstract {\n public static final TypeReportEnumeration TITRE_VOLET2 = new TypeReportEnumeration(6, \"Bordereau de titres Volet 2\", JASPER_REPORT_BORDEREAU_TITRE);\n public static final TypeReportEnumeration TITRE_VOLET3 = new TypeReportEnumeration(7, \"Bordereau de titres Volet 3\", JASPER_REPORT_BORDEREAU_TITRE);\n public static final TypeReportEnumeration TITRE = new TypeReportEnumeration(8, \"Bordereau de titres\", JASPER_REPORT_BORDEREAU_TITRE);\n- private JasperReport jasperReport;\n \n \t// --- AVIS\n private static final String JASPER_AVIS_REPOSITORY = \"/jasper/avis/\";\n@@ -44,7 +43,13 @@ public class TypeReportEnumeration extends EnumerationAbstract {\n public static final TypeReportEnumeration AVIS_SOMMES_A_PAYER = new TypeReportEnumeration(9, \"Avis des sommes à payer\", JASPER_REPORT_AVIS);\n public static final TypeReportEnumeration AVIS_SOMMES_A_PAYER_SANS_EXP = new TypeReportEnumeration(10, \"Avis des sommes à payer sans expéditeur\", JASPER_REPORT_AVIS);\n \n+ // --- AVIS MANDATEMENT\n+ private static final String JASPER_AVIS_MANDATEMENT_REPOSITORY = \"/jasper/avismandatement/\";\n+ private static final String[] JASPER_AVIS_MANDATEMENT_REPORTS = new String[] {\"avisMandatement.jrxml\"};\n+ private static final JasperReport JASPER_REPORT_AVIS_MANDATEMENT = getJasperReport(JASPER_AVIS_MANDATEMENT_REPOSITORY, JASPER_AVIS_MANDATEMENT_REPORTS);\n+ public static final TypeReportEnumeration AVIS_MANDATEMENT= new TypeReportEnumeration(9, \"Avis mandatement\", JASPER_REPORT_AVIS_MANDATEMENT);\n \n+ private JasperReport jasperReport;\n public JasperReport getJasperReport() {\n return jasperReport;\n }\n","a_mode":"100644","old_path":"@@ -34,7 +34,6 @@ public class TypeReportEnumeration extends EnumerationAbstract {\n public static final TypeReportEnumeration TITRE_VOLET2 = new TypeReportEnumeration(6, \"Bordereau de titres Volet 2\", JASPER_REPORT_BORDEREAU_TITRE);\n public static final TypeReportEnumeration TITRE_VOLET3 = new TypeReportEnumeration(7, \"Bordereau de titres Volet 3\", JASPER_REPORT_BORDEREAU_TITRE);\n public static final TypeReportEnumeration TITRE = new TypeReportEnumeration(8, \"Bordereau de titres\", JASPER_REPORT_BORDEREAU_TITRE);\n- private JasperReport jasperReport;\n \n \t// --- AVIS\n private static final String JASPER_AVIS_REPOSITORY = \"/jasper/avis/\";\n@@ -44,7 +43,13 @@ public class TypeReportEnumeration extends EnumerationAbstract {\n public static final TypeReportEnumeration AVIS_SOMMES_A_PAYER = new TypeReportEnumeration(9, \"Avis des sommes à payer\", JASPER_REPORT_AVIS);\n public static final TypeReportEnumeration AVIS_SOMMES_A_PAYER_SANS_EXP = new TypeReportEnumeration(10, \"Avis des sommes à payer sans expéditeur\", JASPER_REPORT_AVIS);\n \n+ // --- AVIS MANDATEMENT\n+ private static final String JASPER_AVIS_MANDATEMENT_REPOSITORY = \"/jasper/avismandatement/\";\n+ private static final String[] JASPER_AVIS_MANDATEMENT_REPORTS = new String[] {\"avisMandatement.jrxml\"};\n+ private static final JasperReport JASPER_REPORT_AVIS_MANDATEMENT = getJasperReport(JASPER_AVIS_MANDATEMENT_REPOSITORY, JASPER_AVIS_MANDATEMENT_REPORTS);\n+ public static final TypeReportEnumeration AVIS_MANDATEMENT= new TypeReportEnumeration(9, \"Avis mandatement\", JASPER_REPORT_AVIS_MANDATEMENT);\n \n+ private JasperReport jasperReport;\n public JasperReport getJasperReport() {\n return jasperReport;\n }\n","new_file":false,"deleted_file":false,"renamed_file":false},{"b_mode":"100644","diff":"@@ -0,0 +1,7 @@\n+package fr.bl.avenir.gf.rest.ecompta.edition.service.avismandatement;\n+\n+import fr.bl.avenir.gf.rest.ecompta.edition.service.ServiceImprimer;\n+\n+public interface ServiceImprimerAvisMandatement extends ServiceImprimer {\n+\t\n+}\n","new_path":"@@ -0,0 +1,7 @@\n+package fr.bl.avenir.gf.rest.ecompta.edition.service.avismandatement;\n+\n+import fr.bl.avenir.gf.rest.ecompta.edition.service.ServiceImprimer;\n+\n+public interface ServiceImprimerAvisMandatement extends ServiceImprimer {\n+\t\n+}\n","a_mode":"0","old_path":"@@ -0,0 +1,7 @@\n+package fr.bl.avenir.gf.rest.ecompta.edition.service.avismandatement;\n+\n+import fr.bl.avenir.gf.rest.ecompta.edition.service.ServiceImprimer;\n+\n+public interface ServiceImprimerAvisMandatement extends ServiceImprimer {\n+\t\n+}\n","new_file":true,"deleted_file":false,"renamed_file":false},{"b_mode":"100644","diff":"@@ -0,0 +1,33 @@\n+package fr.bl.avenir.gf.rest.ecompta.edition.service.avismandatement.impl;\n+\n+import java.text.ParseException;\n+import java.util.List;\n+import java.util.Map;\n+\n+import org.springframework.stereotype.Service;\n+\n+import fr.bl.avenir.gf.rest.ecompta.edition.dto.avismandatement.DTOAvisMandatement;\n+import fr.bl.avenir.gf.rest.ecompta.edition.service.avismandatement.ServiceImprimerAvisMandatement;\n+import fr.bl.avenir.gf.rest.ecompta.edition.service.impl.ServiceImprimerImpl;\n+import fr.magnus.reftechnique.transverse.EntiteRelationnelle;\n+import fr.magnus.reftechnique.transverse.tableau.TableauAbstract;\n+\n+@Service(\"ServiceImprimerAvisMandatement\")\n+public class ServiceImprimerAvisMandatementImpl extends ServiceImprimerImpl implements ServiceImprimerAvisMandatement{\n+\n+ @Override\n+\tpublic List getListDonnee(TableauAbstract[] tableauEntiteRelationnelles, Map params) throws ParseException {\n+\n+ List dtoAvisMandatementList = null;\n+ \n+ if (tableauEntiteRelationnelles!= null && tableauEntiteRelationnelles.length == 2) {\n+ TableauAbstract tabDonnee = tableauEntiteRelationnelles[0];\n+// Collections.sort(dtoAvisMandatementList, Comparator.comparing(DTOAvis::getBordereauNumero)\n+// .thenComparing(DTOAvis::getTitreNumeroPiece)\n+// .thenComparing(DTOAvis::getTiers1)\n+// \t.thenComparing(DTOAvis::getImputationComplete));\n+ }\n+ return dtoAvisMandatementList;\t\t\n+\t}\n+\n+}\n","new_path":"@@ -0,0 +1,33 @@\n+package fr.bl.avenir.gf.rest.ecompta.edition.service.avismandatement.impl;\n+\n+import java.text.ParseException;\n+import java.util.List;\n+import java.util.Map;\n+\n+import org.springframework.stereotype.Service;\n+\n+import fr.bl.avenir.gf.rest.ecompta.edition.dto.avismandatement.DTOAvisMandatement;\n+import fr.bl.avenir.gf.rest.ecompta.edition.service.avismandatement.ServiceImprimerAvisMandatement;\n+import fr.bl.avenir.gf.rest.ecompta.edition.service.impl.ServiceImprimerImpl;\n+import fr.magnus.reftechnique.transverse.EntiteRelationnelle;\n+import fr.magnus.reftechnique.transverse.tableau.TableauAbstract;\n+\n+@Service(\"ServiceImprimerAvisMandatement\")\n+public class ServiceImprimerAvisMandatementImpl extends ServiceImprimerImpl implements ServiceImprimerAvisMandatement{\n+\n+ @Override\n+\tpublic List getListDonnee(TableauAbstract[] tableauEntiteRelationnelles, Map params) throws ParseException {\n+\n+ List dtoAvisMandatementList = null;\n+ \n+ if (tableauEntiteRelationnelles!= null && tableauEntiteRelationnelles.length == 2) {\n+ TableauAbstract tabDonnee = tableauEntiteRelationnelles[0];\n+// Collections.sort(dtoAvisMandatementList, Comparator.comparing(DTOAvis::getBordereauNumero)\n+// .thenComparing(DTOAvis::getTitreNumeroPiece)\n+// .thenComparing(DTOAvis::getTiers1)\n+// \t.thenComparing(DTOAvis::getImputationComplete));\n+ }\n+ return dtoAvisMandatementList;\t\t\n+\t}\n+\n+}\n","a_mode":"0","old_path":"@@ -0,0 +1,33 @@\n+package fr.bl.avenir.gf.rest.ecompta.edition.service.avismandatement.impl;\n+\n+import java.text.ParseException;\n+import java.util.List;\n+import java.util.Map;\n+\n+import org.springframework.stereotype.Service;\n+\n+import fr.bl.avenir.gf.rest.ecompta.edition.dto.avismandatement.DTOAvisMandatement;\n+import fr.bl.avenir.gf.rest.ecompta.edition.service.avismandatement.ServiceImprimerAvisMandatement;\n+import fr.bl.avenir.gf.rest.ecompta.edition.service.impl.ServiceImprimerImpl;\n+import fr.magnus.reftechnique.transverse.EntiteRelationnelle;\n+import fr.magnus.reftechnique.transverse.tableau.TableauAbstract;\n+\n+@Service(\"ServiceImprimerAvisMandatement\")\n+public class ServiceImprimerAvisMandatementImpl extends ServiceImprimerImpl implements ServiceImprimerAvisMandatement{\n+\n+ @Override\n+\tpublic List getListDonnee(TableauAbstract[] tableauEntiteRelationnelles, Map params) throws ParseException {\n+\n+ List dtoAvisMandatementList = null;\n+ \n+ if (tableauEntiteRelationnelles!= null && tableauEntiteRelationnelles.length == 2) {\n+ TableauAbstract tabDonnee = tableauEntiteRelationnelles[0];\n+// Collections.sort(dtoAvisMandatementList, Comparator.comparing(DTOAvis::getBordereauNumero)\n+// .thenComparing(DTOAvis::getTitreNumeroPiece)\n+// .thenComparing(DTOAvis::getTiers1)\n+// \t.thenComparing(DTOAvis::getImputationComplete));\n+ }\n+ return dtoAvisMandatementList;\t\t\n+\t}\n+\n+}\n","new_file":true,"deleted_file":false,"renamed_file":false},{"b_mode":"100644","diff":"@@ -1,8 +1,6 @@\n package fr.bl.avenir.gf.rest.ecompta.edition.service.impl;\n \n import java.math.BigDecimal;\n-import java.nio.file.Path;\n-import java.nio.file.Paths;\n import java.text.ParseException;\n import java.text.SimpleDateFormat;\n import java.util.ArrayList;\n@@ -58,14 +56,11 @@ public abstract class ServiceImprimerImpl implements ServiceImprimer {\n return getListDonnee(tableauEntiteRelationnelles, params);\n }\n \n- protected void mappingDtoEnvironnementFromJson(\n- TableauAbstract environnement,\n- Map params) {\n+ protected void mappingDtoEnvironnementFromJson(TableauAbstract environnement, Map params) {\n if (environnement != null && environnement.getLigneCount() > 0) {\n EntiteRelationnelle entiteRelationnelle = environnement.getDonnees().get(0);\n params.putAll(entiteRelationnelle.getData());\n }\n-\n }\n \n protected List mappingDtoOrdonnancementListFromJson(TableauAbstract ordonnancementJSon) {\n","new_path":"@@ -1,8 +1,6 @@\n package fr.bl.avenir.gf.rest.ecompta.edition.service.impl;\n \n import java.math.BigDecimal;\n-import java.nio.file.Path;\n-import java.nio.file.Paths;\n import java.text.ParseException;\n import java.text.SimpleDateFormat;\n import java.util.ArrayList;\n@@ -58,14 +56,11 @@ public abstract class ServiceImprimerImpl implements ServiceImprimer {\n return getListDonnee(tableauEntiteRelationnelles, params);\n }\n \n- protected void mappingDtoEnvironnementFromJson(\n- TableauAbstract environnement,\n- Map params) {\n+ protected void mappingDtoEnvironnementFromJson(TableauAbstract environnement, Map params) {\n if (environnement != null && environnement.getLigneCount() > 0) {\n EntiteRelationnelle entiteRelationnelle = environnement.getDonnees().get(0);\n params.putAll(entiteRelationnelle.getData());\n }\n-\n }\n \n protected List mappingDtoOrdonnancementListFromJson(TableauAbstract ordonnancementJSon) {\n","a_mode":"100644","old_path":"@@ -1,8 +1,6 @@\n package fr.bl.avenir.gf.rest.ecompta.edition.service.impl;\n \n import java.math.BigDecimal;\n-import java.nio.file.Path;\n-import java.nio.file.Paths;\n import java.text.ParseException;\n import java.text.SimpleDateFormat;\n import java.util.ArrayList;\n@@ -58,14 +56,11 @@ public abstract class ServiceImprimerImpl implements ServiceImprimer {\n return getListDonnee(tableauEntiteRelationnelles, params);\n }\n \n- protected void mappingDtoEnvironnementFromJson(\n- TableauAbstract environnement,\n- Map params) {\n+ protected void mappingDtoEnvironnementFromJson(TableauAbstract environnement, Map params) {\n if (environnement != null && environnement.getLigneCount() > 0) {\n EntiteRelationnelle entiteRelationnelle = environnement.getDonnees().get(0);\n params.putAll(entiteRelationnelle.getData());\n }\n-\n }\n \n protected List mappingDtoOrdonnancementListFromJson(TableauAbstract ordonnancementJSon) {\n","new_file":false,"deleted_file":false,"renamed_file":false},{"b_mode":"100644","diff":"@@ -0,0 +1,177 @@\n+\n+\n+\n+\t\n+\t\n+\t\n+\t\n+\t\n+\t\n+\t\n+\t\n+\t\n+\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\n+\n+\t\n+\t\n+\t\n+\t\n+\t\n+\t\n+\t\n+\t\n+\t\n+\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\n+\t\n+\n","a_mode":"0","old_path":"@@ -0,0 +1,177 @@\n+\n+\n+\n+\t\n+\t\n+\t\n+\t\n+\t\n+\t\n+\t\n+\t\n+\t\n+\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\t\t\n+\t\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\n+\t\n+\n","new_file":true,"deleted_file":false,"renamed_file":false}]' ] @@ -190,7 +190,57 @@ GitlabModelImporterTest >> setUp [ importer repoApi: GLHApiMock new ] -{ #category : #tests } +{ #category : #'tests - repositories' } +GitlabModelImporterTest >> testCompleteImportsOfRepository [ + + | element project | + project := GLHProject new + name: 'testProject'; + repository: GLHRepository new; + yourself. + element := importer completeImportsOfRepository: project repository. + + self assert: element isNotNil. + self assert: element class equals: GLHRepository. + + self assert: element project isNotNil. + self assert: element project equals: project. + + self assert: element branches isNotNil. + self assert: element branches anyOne class equals: GLHBranch. + +] + +{ #category : #'tests - branches' } +GitlabModelImporterTest >> testImportBranchesOf [ + + | branches branch | + branches := importer importBranchesOf: (GLHProject new + repository: GLHRepository new; + yourself). + + self assert: branches isEmptyOrNil not. + + branch := branches first. + self assert: branch class equals: GLHBranch . + +] + +{ #category : #'tests - commits' } +GitlabModelImporterTest >> testImportCommitOfProject [ + + | commit | + commit := importer importCommit: 123 ofProject: (GLHProject new + repository: GLHRepository new; + yourself). + + self assert: commit isNotNil. + self assert: commit class equals: GLHCommit. + self assert: commit repository class equals: GLHRepository. + self assert: commit repository project class equals: GLHProject . +] + +{ #category : #'tests - commits' } GitlabModelImporterTest >> testImportCommitsFromTagToTagNoCommits [ | tag1 tag2 hostUrl gitlabApi projectId result client gitlabRepositories from to params | @@ -236,7 +286,7 @@ GitlabModelImporterTest >> testImportCommitsFromTagToTagNoCommits [ self assert: result isEmpty ] -{ #category : #tests } +{ #category : #'test - diffs' } GitlabModelImporterTest >> testImportDiffOfCommitWithServerRaiseError [ | commit repo project | @@ -250,7 +300,7 @@ GitlabModelImporterTest >> testImportDiffOfCommitWithServerRaiseError [ self assert: commit diffs isEmpty ] -{ #category : #tests } +{ #category : #'test - diffs' } GitlabModelImporterTest >> testImportDiffOfMergeRequest [ | mr | @@ -261,7 +311,19 @@ GitlabModelImporterTest >> testImportDiffOfMergeRequest [ self assert: (model allWithType: GLHDiff) size equals: 3 ] -{ #category : #tests } +{ #category : #'tests - groups' } +GitlabModelImporterTest >> testImportGroup [ + + | collection element | + collection := importer importGroup: 123. + + self assert: collection class equals: GLHGroup. + + element := collection projects first. + self assert: element class equals: GLHProject. +] + +{ #category : #'tests - jobs' } GitlabModelImporterTest >> testImportJobsOf [ | json jobsArray job | @@ -278,7 +340,154 @@ GitlabModelImporterTest >> testImportJobsOf [ self assert: job name equals: 'teaspoon' ] -{ #category : #tests } +{ #category : #'tests - commits' } +GitlabModelImporterTest >> testImportLatestCommitsOfProject [ + + | commits commit| + commits := importer importLatestCommitsOfProject: (GLHProject new + repository: GLHRepository new; + yourself). + + self assert: commits isEmptyOrNil not . + + commit := commits first. + self assert: commit class equals: GLHCommit. + self assert: commit repository class equals: GLHRepository. + self assert: commit repository project class equals: GLHProject . +] + +{ #category : #'tests - merge-requests' } +GitlabModelImporterTest >> testImportLatestMergeRequestsOfProject [ + + | collection element | + collection := importer importLatestMergeRequestsOfProject: + (GLHProject new + repository: GLHRepository new; + yourself). + + self assert: collection isCollection. + element := collection first. + self assert: element class equals: GLHMergeRequest. + self assert: element project class equals: GLHProject. +] + +{ #category : #'tests - pipelines' } +GitlabModelImporterTest >> testImportLatestPipelinesOfProject [ + + | collection element | + collection := importer importLatestPipelinesOfProject: (GLHProject new + repository: GLHRepository new; + yourself). + + self assert: collection isEmptyOrNil not. + self assert: collection isCollection. + + element := collection first. + self assert: element class equals: GLHPipeline . + self assert: element project isNotNil. + self assert: element project class equals: GLHProject + +] + +{ #category : #'tests - releases' } +GitlabModelImporterTest >> testImportLatestReleaseOfProject [ + + | element | + element := importer importLatestReleaseOfProject: + (GLHProject new + repository: GLHRepository new; + yourself). + + self deny: element isCollection. + self assert: element class equals: GLHRelease. + self assert: element project isNotNil +] + +{ #category : #'tests - merge-requests' } +GitlabModelImporterTest >> testImportMergeRequestsOfProject [ + + | collection element | + collection := importer importMergeRequestsOfProject: (GLHProject new + repository: GLHRepository new; + yourself). + + self assert: collection isCollection. + element := collection first. + self assert: element class equals: GLHMergeRequest. + self assert: element project class equals: GLHProject. + self assert: element diffs isCollection. + self assert: element diffs first class equals: GLHDiff. + self assert: element mergeRequestCommit class equals: GLHCommit . + +] + +{ #category : #'tests - notes' } +GitlabModelImporterTest >> testImportNotesOfMergeRequest [ + + | collection element | + collection := importer importNotesOfMergeRequest: + (GLHMergeRequest new + project: (GLHProject new id: 123); + yourself). + + self assert: collection isCollection. + element := collection first. + self assert: element class equals: GLHNote. + self assert: element mergeRequest isNotNil. + +] + +{ #category : #'tests - projects' } +GitlabModelImporterTest >> testImportProject [ + + | element | + element := importer importProject: 123. + + self assert: element isNotNil. + self assert: element class equals: GLHProject . + self assert: element repository class equals: GLHRepository. + +] + +{ #category : #'tests - projects' } +GitlabModelImporterTest >> testImportProjects [ + + | collection element | + collection := importer importProjects. + + self deny: collection isEmptyOrNil. + self assert: collection isCollection. + element := collection first. + + self assert: element isNotNil. + self assert: element class equals: GLHProject. + self assert: element repository isNil. +] + +{ #category : #'tests - tags' } +GitlabModelImporterTest >> testImportTagsForProject [ + + | collection element | + collection := importer importTagsForProject: (GLHProject new + repository: GLHRepository new; + yourself). + + self assert: collection isCollection. + element := collection first. + self assert: element class equals: GLHTag. + + self assert: element commit isNotNil. + self assert: element commit class equals: GLHCommit . + + self assert: element repository isNotNil. + self assert: element repository class equals: GLHRepository. + + self assert: element repository project isNotNil. + self assert: element repository project class equals: GLHProject. + +] + +{ #category : #'tests - users' } GitlabModelImporterTest >> testImportUserAlreadyInModel [ | user | @@ -289,14 +498,14 @@ GitlabModelImporterTest >> testImportUserAlreadyInModel [ self assert: (importer importUser: 12) equals: user ] -{ #category : #tests } +{ #category : #'tests - errors' } GitlabModelImporterTest >> testIsServerError [ self assert: (importer isServerError: '{"message":"500 Internal Server Error"}') ] -{ #category : #test } +{ #category : #'test - diffs' } GitlabModelImporterTest >> testNewParseDiffResultGitlab [ | parseRes | @@ -306,7 +515,7 @@ GitlabModelImporterTest >> testNewParseDiffResultGitlab [ self assert: parseRes size equals: 8 ] -{ #category : #tests } +{ #category : #'test - diffs' } GitlabModelImporterTest >> testParseDiffString [ | diff diffRange | @@ -339,7 +548,7 @@ GitlabModelImporterTest >> testParseDiffString [ equals: 2 ] -{ #category : #tests } +{ #category : #'tests - notes' } GitlabModelImporterTest >> testParseNote [ | jsonNote notesArray note | @@ -373,7 +582,7 @@ GitlabModelImporterTest >> testParseNote [ ] -{ #category : #tests } +{ #category : #'tests - users' } GitlabModelImporterTest >> testimportUser [ | user | diff --git a/src/GitLabHealth-Model-Importer-Tests/GitlabNotesMock.class.st b/src/GitLabHealth-Model-Importer-Tests/GitlabNotesMock.class.st new file mode 100644 index 00000000..2ea84af1 --- /dev/null +++ b/src/GitLabHealth-Model-Importer-Tests/GitlabNotesMock.class.st @@ -0,0 +1,60 @@ +Class { + #name : #GitlabNotesMock, + #superclass : #Object, + #category : #'GitLabHealth-Model-Importer-Tests' +} + +{ #category : #'api - get' } +GitlabNotesMock >> allInMergeRequest: anUndefinedObject ofProject: anInteger [ + + ^ {'[ + { + "id": 302, + "body": "closed", + "author": { + "id": 1, + "username": "pipin", + "email": "admin@example.com", + "name": "Pip", + "state": "active", + "created_at": "2013-09-30T13:46:01Z" + }, + "created_at": "2013-10-02T09:22:45Z", + "updated_at": "2013-10-02T10:22:45Z", + "system": true, + "noteable_id": 377, + "noteable_type": "Issue", + "project_id": 5, + "noteable_iid": 377, + "resolvable": false, + "confidential": false, + "internal": false, + "imported": false, + "imported_from": "none" + }, + { + "id": 305, + "body": "Text of the comment\r\n", + "author": { + "id": 1, + "username": "pipin", + "email": "admin@example.com", + "name": "Pip", + "state": "active", + "created_at": "2013-09-30T13:46:01Z" + }, + "created_at": "2013-10-02T09:56:03Z", + "updated_at": "2013-10-02T09:56:03Z", + "system": true, + "noteable_id": 121, + "noteable_type": "Issue", + "project_id": 5, + "noteable_iid": 121, + "resolvable": false, + "confidential": true, + "internal": true, + "imported": false, + "imported_from": "none" + } +]'} +] diff --git a/src/GitLabHealth-Model-Importer-Tests/GitlabPipelinesMock.class.st b/src/GitLabHealth-Model-Importer-Tests/GitlabPipelinesMock.class.st new file mode 100644 index 00000000..5c816db5 --- /dev/null +++ b/src/GitLabHealth-Model-Importer-Tests/GitlabPipelinesMock.class.st @@ -0,0 +1,82 @@ +Class { + #name : #GitlabPipelinesMock, + #superclass : #Object, + #category : #'GitLabHealth-Model-Importer-Tests' +} + +{ #category : #api } +GitlabPipelinesMock >> get: anInteger inProject: anInteger2 [ + ^ '{ + "id": 287, + "iid": 144, + "project_id": 21, + "name": "Build pipeline", + "sha": "50f0acb76a40e34a4ff304f7347dcc6587da8a14", + "ref": "main", + "status": "success", + "source": "push", + "created_at": "2022-09-21T01:05:07.200Z", + "updated_at": "2022-09-21T01:05:50.185Z", + "web_url": "http://127.0.0.1:3000/test-group/test-project/-/pipelines/287", + "before_sha": "8a24fb3c5877a6d0b611ca41fc86edc174593e2b", + "tag": false, + "yaml_errors": null, + "user": { + "id": 1, + "username": "root", + "name": "Administrator", + "state": "active", + "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", + "web_url": "http://127.0.0.1:3000/root" + }, + "started_at": "2022-09-21T01:05:14.197Z", + "finished_at": "2022-09-21T01:05:50.175Z", + "committed_at": null, + "duration": 34, + "queued_duration": 6, + "coverage": null, + "detailed_status": { + "icon": "status_success", + "text": "passed", + "label": "passed", + "group": "success", + "tooltip": "passed", + "has_details": false, + "details_path": "/test-group/test-project/-/pipelines/287", + "illustration": null, + "favicon": "/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png" + } +}' +] + +{ #category : #api } +GitlabPipelinesMock >> getByPage: anInteger perPage: anInteger2 inProject: anInteger3 [ + ^ '[ + { + "id": 47, + "iid": 12, + "project_id": 1, + "status": "pending", + "source": "push", + "ref": "new-pipeline", + "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", + "name": "Build pipeline", + "web_url": "https://example.com/foo/bar/pipelines/47", + "created_at": "2016-08-11T11:28:34.085Z", + "updated_at": "2016-08-11T11:32:35.169Z" + }, + { + "id": 48, + "iid": 13, + "project_id": 1, + "status": "pending", + "source": "web", + "ref": "new-pipeline", + "sha": "eb94b618fb5865b26e80fdd8ae531b7a63ad851a", + "name": "Build pipeline", + "web_url": "https://example.com/foo/bar/pipelines/48", + "created_at": "2016-08-12T10:06:04.561Z", + "updated_at": "2016-08-12T10:09:56.223Z" + } +]' +] diff --git a/src/GitLabHealth-Model-Importer-Tests/GitlabProjectsMock.class.st b/src/GitLabHealth-Model-Importer-Tests/GitlabProjectsMock.class.st new file mode 100644 index 00000000..0945180a --- /dev/null +++ b/src/GitLabHealth-Model-Importer-Tests/GitlabProjectsMock.class.st @@ -0,0 +1,329 @@ +Class { + #name : #GitlabProjectsMock, + #superclass : #Object, + #category : #'GitLabHealth-Model-Importer-Tests' +} + +{ #category : #accessing } +GitlabProjectsMock >> all [ + ^ { '[ + { + "id": 4, + "description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", + "description_html": "

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

", + "name": "Diaspora Client", + "name_with_namespace": "Diaspora / Diaspora Client", + "path": "diaspora-client", + "path_with_namespace": "diaspora/diaspora-client", + "created_at": "2013-09-30T13:46:02Z", + "updated_at": "2013-09-30T13:46:02Z", + "default_branch": "main", + "tag_list": [ + "example", + "disapora client" + ], + "topics": [ + "example", + "disapora client" + ], + "ssh_url_to_repo": "git@gitlab.example.com:diaspora/diaspora-client.git", + "http_url_to_repo": "https://gitlab.example.com/diaspora/diaspora-client.git", + "web_url": "https://gitlab.example.com/diaspora/diaspora-client", + "readme_url": "https://gitlab.example.com/diaspora/diaspora-client/blob/main/README.md", + "avatar_url": "https://gitlab.example.com/uploads/project/avatar/4/uploads/avatar.png", + "forks_count": 0, + "star_count": 0, + "last_activity_at": "2022-06-24T17:11:26.841Z", + "namespace": { + "id": 3, + "name": "Diaspora", + "path": "diaspora", + "kind": "group", + "full_path": "diaspora", + "parent_id": null, + "avatar_url": "https://gitlab.example.com/uploads/project/avatar/6/uploads/avatar.png", + "web_url": "https://gitlab.example.com/diaspora" + }, + "container_registry_image_prefix": "registry.gitlab.example.com/diaspora/diaspora-client", + "_links": { + "self": "https://gitlab.example.com/api/v4/projects/4", + "issues": "https://gitlab.example.com/api/v4/projects/4/issues", + "merge_requests": "https://gitlab.example.com/api/v4/projects/4/merge_requests", + "repo_branches": "https://gitlab.example.com/api/v4/projects/4/repository/branches", + "labels": "https://gitlab.example.com/api/v4/projects/4/labels", + "events": "https://gitlab.example.com/api/v4/projects/4/events", + "members": "https://gitlab.example.com/api/v4/projects/4/members", + "cluster_agents": "https://gitlab.example.com/api/v4/projects/4/cluster_agents" + }, + "packages_enabled": true, + "package_registry_access_level": "enabled", + "empty_repo": false, + "archived": false, + "visibility": "public", + "resolve_outdated_diff_discussions": false, + "container_expiration_policy": { + "cadence": "1month", + "enabled": true, + "keep_n": 1, + "older_than": "14d", + "name_regex": "", + "name_regex_keep": ".*-main", + "next_run_at": "2022-06-25T17:11:26.865Z" + }, + "issues_enabled": true, + "merge_requests_enabled": true, + "wiki_enabled": true, + "jobs_enabled": true, + "snippets_enabled": true, + "container_registry_enabled": true, + "service_desk_enabled": true, + "can_create_merge_request_in": true, + "issues_access_level": "enabled", + "repository_access_level": "enabled", + "merge_requests_access_level": "enabled", + "forking_access_level": "enabled", + "wiki_access_level": "enabled", + "builds_access_level": "enabled", + "snippets_access_level": "enabled", + "pages_access_level": "enabled", + "analytics_access_level": "enabled", + "container_registry_access_level": "enabled", + "security_and_compliance_access_level": "private", + "emails_disabled": null, + "emails_enabled": null, + "shared_runners_enabled": true, + "group_runners_enabled": true, + "lfs_enabled": true, + "creator_id": 1, + "import_url": null, + "import_type": null, + "import_status": "none", + "import_error": null, + "open_issues_count": 0, + "ci_default_git_depth": 20, + "ci_forward_deployment_enabled": true, + "ci_forward_deployment_rollback_allowed": true, + "ci_allow_fork_pipelines_to_run_in_parent_project": true, + "ci_id_token_sub_claim_components": ["project_path", "ref_type", "ref"], + "ci_job_token_scope_enabled": false, + "ci_separated_caches": true, + "ci_restrict_pipeline_cancellation_role": "developer", + "ci_pipeline_variables_minimum_override_role": "maintainer", + "ci_push_repository_for_job_token_allowed": false, + "public_jobs": true, + "build_timeout": 3600, + "auto_cancel_pending_pipelines": "enabled", + "ci_config_path": "", + "shared_with_groups": [], + "only_allow_merge_if_pipeline_succeeds": false, + "allow_merge_on_skipped_pipeline": null, + "allow_pipeline_trigger_approve_deployment": false, + "restrict_user_defined_variables": false, + "request_access_enabled": true, + "only_allow_merge_if_all_discussions_are_resolved": false, + "remove_source_branch_after_merge": true, + "printing_merge_request_link_enabled": true, + "merge_method": "merge", + "squash_option": "default_off", + "enforce_auth_checks_on_uploads": true, + "suggestion_commit_message": null, + "merge_commit_template": null, + "squash_commit_template": null, + "issue_branch_template": "gitlab/%{id}-%{title}", + "auto_devops_enabled": false, + "auto_devops_deploy_strategy": "continuous", + "autoclose_referenced_issues": true, + "keep_latest_artifact": true, + "runner_token_expiration_interval": null, + "external_authorization_classification_label": "", + "requirements_enabled": false, + "requirements_access_level": "enabled", + "security_and_compliance_enabled": false, + "secret_push_protection_enabled": false, + "compliance_frameworks": [], + "warn_about_potentially_unwanted_characters": true, + "permissions": { + "project_access": null, + "group_access": null + } + } +]' } +] + +{ #category : #api } +GitlabProjectsMock >> get: anInteger [ + ^ '{ + "id": 3, + "description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", + "description_html": "

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

", + "default_branch": "main", + "visibility": "private", + "ssh_url_to_repo": "git@example.com:diaspora/diaspora-project-site.git", + "http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git", + "web_url": "http://example.com/diaspora/diaspora-project-site", + "readme_url": "http://example.com/diaspora/diaspora-project-site/blob/main/README.md", + "tag_list": [ + "example", + "disapora project" + ], + "topics": [ + "example", + "disapora project" + ], + "owner": { + "id": 3, + "name": "Diaspora", + "created_at": "2013-09-30T13:46:02Z" + }, + "name": "Diaspora Project Site", + "name_with_namespace": "Diaspora / Diaspora Project Site", + "path": "diaspora-project-site", + "path_with_namespace": "diaspora/diaspora-project-site", + "issues_enabled": true, + "open_issues_count": 1, + "merge_requests_enabled": true, + "jobs_enabled": true, + "wiki_enabled": true, + "snippets_enabled": false, + "can_create_merge_request_in": true, + "resolve_outdated_diff_discussions": false, + "container_registry_enabled": false, + "container_registry_access_level": "disabled", + "security_and_compliance_access_level": "disabled", + "container_expiration_policy": { + "cadence": "7d", + "enabled": false, + "keep_n": null, + "older_than": null, + "name_regex": null, + "name_regex_delete": null, + "name_regex_keep": null, + "next_run_at": "2020-01-07T21:42:58.658Z" + }, + "created_at": "2013-09-30T13:46:02Z", + "updated_at": "2013-09-30T13:46:02Z", + "last_activity_at": "2013-09-30T13:46:02Z", + "creator_id": 3, + "namespace": { + "id": 3, + "name": "Diaspora", + "path": "diaspora", + "kind": "group", + "full_path": "diaspora", + "avatar_url": "http://localhost:3000/uploads/group/avatar/3/foo.jpg", + "web_url": "http://localhost:3000/groups/diaspora" + }, + "import_url": null, + "import_type": null, + "import_status": "none", + "import_error": null, + "permissions": { + "project_access": { + "access_level": 10, + "notification_level": 3 + }, + "group_access": { + "access_level": 50, + "notification_level": 3 + } + }, + "archived": false, + "avatar_url": "http://example.com/uploads/project/avatar/3/uploads/avatar.png", + "license_url": "http://example.com/diaspora/diaspora-client/blob/main/LICENSE", + "license": { + "key": "lgpl-3.0", + "name": "GNU Lesser General Public License v3.0", + "nickname": "GNU LGPLv3", + "html_url": "http://choosealicense.com/licenses/lgpl-3.0/", + "source_url": "http://www.gnu.org/licenses/lgpl-3.0.txt" + }, + "shared_runners_enabled": true, + "group_runners_enabled": true, + "forks_count": 0, + "star_count": 0, + "runners_token": "b8bc4a7a29eb76ea83cf79e4908c2b", + "ci_default_git_depth": 50, + "ci_forward_deployment_enabled": true, + "ci_forward_deployment_rollback_allowed": true, + "ci_allow_fork_pipelines_to_run_in_parent_project": true, + "ci_id_token_sub_claim_components": ["project_path", "ref_type", "ref"], + "ci_separated_caches": true, + "ci_restrict_pipeline_cancellation_role": "developer", + "ci_pipeline_variables_minimum_override_role": "maintainer", + "ci_push_repository_for_job_token_allowed": false, + "public_jobs": true, + "shared_with_groups": [ + { + "group_id": 4, + "group_name": "Twitter", + "group_full_path": "twitter", + "group_access_level": 30 + }, + { + "group_id": 3, + "group_name": "Gitlab Org", + "group_full_path": "gitlab-org", + "group_access_level": 10 + } + ], + "repository_storage": "default", + "only_allow_merge_if_pipeline_succeeds": false, + "allow_merge_on_skipped_pipeline": false, + "allow_pipeline_trigger_approve_deployment": false, + "restrict_user_defined_variables": false, + "only_allow_merge_if_all_discussions_are_resolved": false, + "remove_source_branch_after_merge": false, + "printing_merge_requests_link_enabled": true, + "request_access_enabled": false, + "merge_method": "merge", + "squash_option": "default_on", + "auto_devops_enabled": true, + "auto_devops_deploy_strategy": "continuous", + "approvals_before_merge": 0, + "mirror": false, + "mirror_user_id": 45, + "mirror_trigger_builds": false, + "only_mirror_protected_branches": false, + "mirror_overwrites_diverged_branches": false, + "external_authorization_classification_label": null, + "packages_enabled": true, + "service_desk_enabled": false, + "service_desk_address": null, + "autoclose_referenced_issues": true, + "suggestion_commit_message": null, + "enforce_auth_checks_on_uploads": true, + "merge_commit_template": null, + "squash_commit_template": null, + "issue_branch_template": "gitlab/%{id}-%{title}", + "marked_for_deletion_at": "2020-04-03", + "marked_for_deletion_on": "2020-04-03", + "compliance_frameworks": [ "sox" ], + "warn_about_potentially_unwanted_characters": true, + "secret_push_protection_enabled": false, + "statistics": { + "commit_count": 37, + "storage_size": 1038090, + "repository_size": 1038090, + "wiki_size" : 0, + "lfs_objects_size": 0, + "job_artifacts_size": 0, + "pipeline_artifacts_size": 0, + "packages_size": 0, + "snippets_size": 0, + "uploads_size": 0, + "container_registry_size": 0 + }, + "container_registry_image_prefix": "registry.example.com/diaspora/diaspora-client", + "_links": { + "self": "http://example.com/api/v4/projects", + "issues": "http://example.com/api/v4/projects/1/issues", + "merge_requests": "http://example.com/api/v4/projects/1/merge_requests", + "repo_branches": "http://example.com/api/v4/projects/1/repository_branches", + "labels": "http://example.com/api/v4/projects/1/labels", + "events": "http://example.com/api/v4/projects/1/events", + "members": "http://example.com/api/v4/projects/1/members", + "cluster_agents": "http://example.com/api/v4/projects/1/cluster_agents" + }, + "spp_repository_pipeline_access": false +}' +] diff --git a/src/GitLabHealth-Model-Importer-Tests/GitlabReleasesMock.class.st b/src/GitLabHealth-Model-Importer-Tests/GitlabReleasesMock.class.st new file mode 100644 index 00000000..cb9fc8a6 --- /dev/null +++ b/src/GitLabHealth-Model-Importer-Tests/GitlabReleasesMock.class.st @@ -0,0 +1,124 @@ +Class { + #name : #GitlabReleasesMock, + #superclass : #Object, + #category : #'GitLabHealth-Model-Importer-Tests' +} + +{ #category : #get } +GitlabReleasesMock >> getLatestOfProject: anUndefinedObject [ + + ^ '{ + "tag_name":"v0.1", + "description":"## CHANGELOG\r\n\r\n- Remove limit of 100 when searching repository code. !8671\r\n- Show error message when attempting to reopen an MR and there is an open MR for the same branch. !16447 (Akos Gyimesi)\r\n- Fix a bug where internal email pattern wasn''t respected. !22516", + "name":"Awesome app v0.1 alpha", + "created_at":"2019-01-03T01:55:18.203Z", + "released_at":"2019-01-03T01:55:18.203Z", + "author":{ + "id":1, + "name":"Administrator", + "username":"root", + "state":"active", + "avatar_url":"https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon", + "web_url":"https://gitlab.example.com/root" + }, + "commit":{ + "id":"f8d3d94cbd347e924aa7b715845e439d00e80ca4", + "short_id":"f8d3d94c", + "title":"Initial commit", + "created_at":"2019-01-03T01:53:28.000Z", + "parent_ids":[ + + ], + "message":"Initial commit", + "author_name":"Administrator", + "author_email":"admin@example.com", + "authored_date":"2019-01-03T01:53:28.000Z", + "committer_name":"Administrator", + "committer_email":"admin@example.com", + "committed_date":"2019-01-03T01:53:28.000Z" + }, + "milestones": [ + { + "id":51, + "iid":1, + "project_id":24, + "title":"v1.0-rc", + "description":"Voluptate fugiat possimus quis quod aliquam expedita.", + "state":"closed", + "created_at":"2019-07-12T19:45:44.256Z", + "updated_at":"2019-07-12T19:45:44.256Z", + "due_date":"2019-08-16", + "start_date":"2019-07-30", + "web_url":"https://gitlab.example.com/root/awesome-app/-/milestones/1", + "issue_stats": { + "total": 98, + "closed": 76 + } + }, + { + "id":52, + "iid":2, + "project_id":24, + "title":"v1.0", + "description":"Voluptate fugiat possimus quis quod aliquam expedita.", + "state":"closed", + "created_at":"2019-07-16T14:00:12.256Z", + "updated_at":"2019-07-16T14:00:12.256Z", + "due_date":"2019-08-16", + "start_date":"2019-07-30", + "web_url":"https://gitlab.example.com/root/awesome-app/-/milestones/2", + "issue_stats": { + "total": 24, + "closed": 21 + } + } + ], + "commit_path":"/root/awesome-app/commit/588440f66559714280628a4f9799f0c4eb880a4a", + "tag_path":"/root/awesome-app/-/tags/v0.11.1", + "assets":{ + "count":5, + "sources":[ + { + "format":"zip", + "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.zip" + }, + { + "format":"tar.gz", + "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar.gz" + }, + { + "format":"tar.bz2", + "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar.bz2" + }, + { + "format":"tar", + "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar" + } + ], + "links":[ + { + "id":3, + "name":"hoge", + "url":"https://gitlab.example.com/root/awesome-app/-/tags/v0.11.1/binaries/linux-amd64", + "link_type":"other" + } + ] + }, + "evidences":[ + { + "sha": "760d6cdfb0879c3ffedec13af470e0f71cf52c6cde4d", + "filepath": "https://gitlab.example.com/root/awesome-app/-/releases/v0.1/evidence.json", + "collected_at": "2019-07-16T14:00:12.256Z" + } + ], + "_links": { + "closed_issues_url": "https://gitlab.example.com/root/awesome-app/-/issues?release_tag=v0.1&scope=all&state=closed", + "closed_merge_requests_url": "https://gitlab.example.com/root/awesome-app/-/merge_requests?release_tag=v0.1&scope=all&state=closed", + "edit_url": "https://gitlab.example.com/root/awesome-app/-/releases/v0.1/edit", + "merged_merge_requests_url": "https://gitlab.example.com/root/awesome-app/-/merge_requests?release_tag=v0.1&scope=all&state=merged", + "opened_issues_url": "https://gitlab.example.com/root/awesome-app/-/issues?release_tag=v0.1&scope=all&state=opened", + "opened_merge_requests_url": "https://gitlab.example.com/root/awesome-app/-/merge_requests?release_tag=v0.1&scope=all&state=opened", + "self": "https://gitlab.example.com/root/awesome-app/-/releases/v0.1" + } +}' +] diff --git a/src/GitLabHealth-Model-Importer-Tests/GitlabTagMock.class.st b/src/GitLabHealth-Model-Importer-Tests/GitlabTagMock.class.st new file mode 100644 index 00000000..4869dec8 --- /dev/null +++ b/src/GitLabHealth-Model-Importer-Tests/GitlabTagMock.class.st @@ -0,0 +1,39 @@ +Class { + #name : #GitlabTagMock, + #superclass : #Object, + #category : #'GitLabHealth-Model-Importer-Tests' +} + +{ #category : #api } +GitlabTagMock >> getAllOfProject: anUndefinedObject [ + + ^ {'[ + { + "commit": { + "id": "2695effb5807a22ff3d138d593fd856244e155e7", + "short_id": "2695effb", + "title": "Initial commit", + "created_at": "2017-07-26T11:08:53.000+02:00", + "parent_ids": [ + "2a4b78934375d7f53875269ffd4f45fd83a84ebe" + ], + "message": "Initial commit", + "author_name": "John Smith", + "author_email": "john@example.com", + "authored_date": "2012-05-28T04:42:42-07:00", + "committer_name": "Jack Smith", + "committer_email": "jack@example.com", + "committed_date": "2012-05-28T04:42:42-07:00" + }, + "release": { + "tag_name": "1.0.0", + "description": "Amazing release. Wow" + }, + "name": "v1.0.0", + "target": "2695effb5807a22ff3d138d593fd856244e155e7", + "message": null, + "protected": true, + "created_at": "2017-07-26T11:08:53.000+02:00" + } +]'} +] diff --git a/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st b/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st index dd26d4b9..aea4e0c1 100644 --- a/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st +++ b/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st @@ -91,7 +91,7 @@ GitlabModelImporter >> completeImportProject: aGLHProject [ importedProject repository: GLHRepository new. self glhModel add: importedProject repository. - self importRepository: importedProject repository. + self completeImportsOfRepository: importedProject repository. withInitialMergeRequest ifTrue: [ @@ -189,7 +189,7 @@ GitlabModelImporter >> completeImportedProject: aGLHProject [ importedProject repository: GLHRepository new. self glhModel add: importedProject repository. - self importRepository: importedProject repository. + self completeImportsOfRepository: importedProject repository. withInitialMergeRequest ifTrue: [ @@ -203,6 +203,27 @@ GitlabModelImporter >> completeImportedProject: aGLHProject [ ] +{ #category : #'import - repositories' } +GitlabModelImporter >> completeImportsOfRepository: aGLHRepository [ + + | branches | + [ + ('import the repository of project ' , aGLHRepository project name) + recordInfo. + branches := self importBranchesOf: aGLHRepository project. + self withFiles ifTrue: [ + branches do: [ :branch | self importFilesOfBranch: branch ] ] ] + on: NeoJSONParseError + do: [ + self inform: aGLHRepository project name , ' has no repository' ]. + + withInitialCommits ifTrue: [ + aGLHRepository branches do: [ :branch | + self importCommitsOfBranch: branch ] ]. + + ^ aGLHRepository +] + { #category : #'private - configure reader' } GitlabModelImporter >> configureReaderForBranch: reader [ @@ -219,11 +240,9 @@ GitlabModelImporter >> configureReaderForBranch: reader [ GitlabModelImporter >> configureReaderForCommit: reader [ super configureReaderForCommit: reader. - + reader for: GLHCommit do: [ :mapping | - mapping mapInstVars: - #( id short_id title author_name author_email committer_name - committer_email message web_url ). + (mapping mapInstVar: #authored_date) valueSchema: DateAndTime. (mapping mapInstVar: #committed_date) valueSchema: DateAndTime. (mapping mapInstVar: #created_at) valueSchema: DateAndTime. @@ -237,9 +256,7 @@ GitlabModelImporter >> configureReaderForCommit: reader [ reader for: #ArrayOfIds - customDo: [ :mapping | mapping decoder: [ :string | string ] ]. - - + customDo: [ :mapping | mapping decoder: [ :string | string ] ] ] { #category : #'private - configure reader' } @@ -1153,7 +1170,7 @@ GitlabModelImporter >> importLatestReleaseOfProject: aGLHProject [ ^ foundRelease. ] -{ #category : #'import - merge-requests' } +{ #category : #'import - commits' } GitlabModelImporter >> importMergeRequestCommits: aGLPHEMergeRequest [ | commits result | @@ -1169,7 +1186,7 @@ GitlabModelImporter >> importMergeRequestCommits: aGLPHEMergeRequest [ ^ commits ] -{ #category : #'import - merge-requests' } +{ #category : #'import - commits' } GitlabModelImporter >> importMergeRequestMergeCommits: aGLPHEMergeRequest [ | foundCommits | @@ -1512,25 +1529,6 @@ GitlabModelImporter >> importProjectsSince: since [ foundProject addAll: newlyFoundProjects ]. ] -{ #category : #'import - repositories' } -GitlabModelImporter >> importRepository: aGLHRepository [ - - | branches | - [ - ('import the repository of project ' , aGLHRepository project name) - recordInfo. - branches := self importBranchesOf: aGLHRepository project. - self withFiles ifTrue: [ - branches do: [ :branch | self importFilesOfBranch: branch ] ] ] - on: NeoJSONParseError - do: [ - self inform: aGLHRepository project name , ' has no repository' ]. - - withInitialCommits ifTrue: [ - aGLHRepository branches do: [ :branch | - self importCommitsOfBranch: branch ] ] -] - { #category : #'import - commits' } GitlabModelImporter >> importSZZFromCommit: aCommit [ @@ -1720,7 +1718,6 @@ GitlabModelImporter >> parseBranchesResult: result [ | reader | reader := generalReader on: result readStream. - ^ reader nextAs: #ArrayOfBranch ] @@ -1728,6 +1725,7 @@ GitlabModelImporter >> parseBranchesResult: result [ GitlabModelImporter >> parseBranchesResult: result ofProject: aGLHProject [ | reader | + self flag: 'WARNING: do not use the importer inside a parsing process. do it after using a object cached on the sub elemnt id'. self deprecated: 'Use parseBranchesResult: instead of current one' on: '23 September 2025' @@ -1761,30 +1759,7 @@ GitlabModelImporter >> parseBranchesResult: result ofProject: aGLHProject [ GitlabModelImporter >> parseCommitResult: result [ | reader | - reader := NeoJSONReader on: result readStream. - - reader for: GLHCommit do: [ :mapping | - mapping mapInstVars: - #( id short_id title author_name author_email committer_name - committer_email message web_url ). - (mapping mapInstVar: #authored_date) valueSchema: DateAndTime. - (mapping mapInstVar: #committed_date) valueSchema: DateAndTime. - (mapping mapInstVar: #created_at) valueSchema: DateAndTime. - (mapping mapInstVar: #parent_ids) valueSchema: #ArrayOfIds. - mapping - mapProperty: 'stats' - getter: [ :el | "Not used" ] - setter: [ :commit :value | - commit deletions: (value at: #deletions). - commit additions: (value at: #additions) ] ]. - - reader for: DateAndTime customDo: [ :mapping | - mapping decoder: [ :string | DateAndTime fromString: string ] ]. - - reader - for: #ArrayOfIds - customDo: [ :mapping | mapping decoder: [ :string | string ] ]. - + reader := generalReader on: result readStream. ^ reader nextAs: GLHCommit ] @@ -1793,34 +1768,7 @@ GitlabModelImporter >> parseCommitResult: result [ GitlabModelImporter >> parseCommitsResult: result [ | reader | - reader := NeoJSONReader on: result readStream. - - reader for: GLHCommit do: [ :mapping | - mapping mapInstVars: - #( id short_id title author_name author_email committer_name - committer_email message web_url ). - (mapping mapInstVar: #authored_date) valueSchema: DateAndTime. - (mapping mapInstVar: #committed_date) valueSchema: DateAndTime. - (mapping mapInstVar: #created_at) valueSchema: DateAndTime. - (mapping mapInstVar: #parent_ids) valueSchema: #ArrayOfIds. - mapping - mapProperty: 'stats' - getter: [ :el | "Not used" ] - setter: [ :commit :value | - commit deletions: (value at: #deletions). - commit additions: (value at: #additions) ] ]. - - reader for: DateAndTime customDo: [ :mapping | - mapping decoder: [ :string | DateAndTime fromString: string ] ]. - - reader - for: #ArrayOfIds - customDo: [ :mapping | mapping decoder: [ :string | string ] ]. - - reader - for: #ArrayOfCommit - customDo: [ :customMappting | - customMappting listOfElementSchema: GLHCommit ]. + reader := generalReader on: result readStream. ^ reader nextAs: #ArrayOfCommit ] @@ -1869,7 +1817,7 @@ GitlabModelImporter >> parseGroupResult: aResult [ ^ reader nextAs: GLHGroup ] -{ #category : #parsing } +{ #category : #'private - parsing' } GitlabModelImporter >> parseJobsResult: result [ | reader | reader := generalReader on: result readStream. @@ -1881,6 +1829,12 @@ GitlabModelImporter >> parseJobsResult: result [ GitlabModelImporter >> parseJobsResult: result ofProject: aProject [ | reader | + self + deprecated: 'Use parseJobsResult: instead of current one' + on: '23 September 2025' + in: + 'Pharo-12.0.0+SNAPSHOT.build.1571.sha.cf5fcd22e66957962c97dffc58b0393b7f368147 (64 Bit)'. + reader := generalReader on: result readStream. reader for: GLHJob do: [ :mapping | mapping @@ -2023,7 +1977,7 @@ GitlabModelImporter >> partiallyImportProject: aProjectID [ projectResult repository: GLHRepository new. self glhModel add: projectResult repository. - self importRepository: projectResult repository. + self completeImportsOfRepository: projectResult repository. ^ projectResult ] diff --git a/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st b/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st index 1613c67b..b6de6f47 100644 --- a/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st +++ b/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st @@ -580,7 +580,7 @@ GitModelImporter >> importProjectsOfUser: aGLHUser [ self subclassResponsibility ] -{ #category : #'as yet unclassified' } +{ #category : #'import - commits' } GitModelImporter >> importRefCommitOfBranch: aGLHBranch [ |commit| commit := self @@ -636,11 +636,12 @@ GitModelImporter >> initReader [ GitModelImporter >> initialize [ super initialize. + self withFiles: false. self withCommitsSince: (Date today - 1 week) asDateAndTime. userCatalogue := GLHUserCatalogueV2 new anImporter: self; yourself. - + self initReader ] From c085574807f5b0cc1f49dc617da383b7fff0f083 Mon Sep 17 00:00:00 2001 From: HLAD Nicolas Date: Tue, 23 Sep 2025 17:24:03 +0200 Subject: [PATCH 28/52] more tests and bug fix --- .../GitlabModelImporterTest.class.st | 37 +++++++++++ .../GitlabPipelinesMock.class.st | 6 ++ .../GitlabModelImporter.class.st | 64 ++++++++++++++----- 3 files changed, 92 insertions(+), 15 deletions(-) diff --git a/src/GitLabHealth-Model-Importer-Tests/GitlabModelImporterTest.class.st b/src/GitLabHealth-Model-Importer-Tests/GitlabModelImporterTest.class.st index bd2bbef6..1a4571d6 100644 --- a/src/GitLabHealth-Model-Importer-Tests/GitlabModelImporterTest.class.st +++ b/src/GitLabHealth-Model-Importer-Tests/GitlabModelImporterTest.class.st @@ -437,6 +437,43 @@ GitlabModelImporterTest >> testImportNotesOfMergeRequest [ ] +{ #category : #'tests - pipelines' } +GitlabModelImporterTest >> testImportPipelineOfProject [ + + | element | + element := importer importPipeline: 123 OfProject: + (GLHProject new + repository: GLHRepository new; + yourself). + + self assert: element class equals: GLHPipeline. + self assert: element project isNotNil. + self assert: element project class equals: GLHProject +] + +{ #category : #'tests - pipelines' } +GitlabModelImporterTest >> testImportPipelinesOfMergeRequest [ + + | collection element | + collection := importer importPipelinesOfMergeRequest: + (GLHMergeRequest new + project: (GLHProject new id:123); + iid: 123; + yourself). + + self assert: collection isEmptyOrNil not. + self assert: collection isCollection. + + element := collection first. + self assert: element class equals: GLHPipeline. + self assert: element project isNotNil. + self assert: element project class equals: GLHProject. + + self assert: element mergeResquest isNotNil. + self assert: element mergeResquest class equals: GLHMergeRequest. + +] + { #category : #'tests - projects' } GitlabModelImporterTest >> testImportProject [ diff --git a/src/GitLabHealth-Model-Importer-Tests/GitlabPipelinesMock.class.st b/src/GitLabHealth-Model-Importer-Tests/GitlabPipelinesMock.class.st index 5c816db5..61e190ed 100644 --- a/src/GitLabHealth-Model-Importer-Tests/GitlabPipelinesMock.class.st +++ b/src/GitLabHealth-Model-Importer-Tests/GitlabPipelinesMock.class.st @@ -80,3 +80,9 @@ GitlabPipelinesMock >> getByPage: anInteger perPage: anInteger2 inProject: anInt } ]' ] + +{ #category : #api } +GitlabPipelinesMock >> getByPage: anInteger perPage: anInteger2 inProject: anInteger3 forMergerRequestIid: anInteger4 [ + ^self getByPage: anInteger perPage: anInteger2 inProject: nil + +] diff --git a/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st b/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st index aea4e0c1..c09fdb0b 100644 --- a/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st +++ b/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st @@ -1220,19 +1220,18 @@ GitlabModelImporter >> importMergeRequestMergeCommits: aGLPHEMergeRequest [ ] { #category : #'import - pipelines' } -GitlabModelImporter >> importMergeRequestPipelines: aGLHMergeRequest [ +GitlabModelImporter >> importMergeRequestPipelines: aGLHMergeRequest [ "default limit to one page with last 100 pipelines" - - |results parseResults| - - results := self repoApi pipelines getByPage: 1 perPage: 100 inProject: aGLHMergeRequest project id forMergerRequestIid: aGLHMergeRequest iid. - - parseResults := self parsePipelinesResult: results. - - parseResults := glhModel addAll: parseResults unless: self blockOnIdEquality. - parseResults := aGLHMergeRequest pipelines addAll: parseResults unless: self blockOnIdEquality. - ^ parseResults collect: [ :pip | self completeImportedPipeline: pip ] . - + + | results parseResults | + self + deprecated: + 'Use importPipelinesOfMergeRequest: instead of current one' + on: '23 September 2025' + in: + 'Pharo-12.0.0+SNAPSHOT.build.1571.sha.cf5fcd22e66957962c97dffc58b0393b7f368147 (64 Bit)'. + + ^ self importPipelinesOfMergeRequest: aGLHMergeRequest. ] { #category : #'import - merge-requests' } @@ -1420,8 +1419,7 @@ GitlabModelImporter >> importPipeline: pipelineId OfProject: aGLHProject [ ('Search pipelines of: ' , aGLHProject id printString) recordInfo. result := self repoApi pipelines get: pipelineId inProject: aGLHProject id. - result isString ifTrue: [ ^ self parsePipelineResult: result ]. - + pipeline := self parsePipelineResult: result. pipeline := self glhModel add: pipeline unless: self blockOnIdEquality . @@ -1430,10 +1428,46 @@ GitlabModelImporter >> importPipeline: pipelineId OfProject: aGLHProject [ ^ self completeImportedPipeline: pipeline. ] +{ #category : #'import - pipelines' } +GitlabModelImporter >> importPipelinesOfMergeRequest: aGLHMergeRequest [ + "default limit to one page with last 100 pipelines" + + | results parseResults | + results := self repoApi pipelines + getByPage: 1 + perPage: 100 + inProject: aGLHMergeRequest project id + forMergerRequestIid: aGLHMergeRequest iid. + + parseResults := self parsePipelinesResult: results. + + parseResults do: [ :pipeline | + pipeline project: aGLHMergeRequest project. + ]. + + parseResults := glhModel + addAll: parseResults + unless: self blockOnIdEquality. + parseResults := aGLHMergeRequest pipelines + addAll: parseResults + unless: self blockOnIdEquality. + + + ^ parseResults collect: [ :pip | self completeImportedPipeline: pip ] +] + { #category : #'import - pipelines' } GitlabModelImporter >> importPipelinesOfProject: aGLHProject [ - self flag: 'WARNING: this import ALL the pipelines at ones. Prefered ImportLatestPipleinesOfProject: for faster performance (if possible)'. + self + deprecated: + 'Use importAllPipelinesOfProject: instead of current one' + on: '23 September 2025' + in: + 'Pharo-12.0.0+SNAPSHOT.build.1571.sha.cf5fcd22e66957962c97dffc58b0393b7f368147 (64 Bit)'. + + self flag: + 'WARNING: this import ALL the pipelines at ones. Prefered ImportLatestPipleinesOfProject: for faster performance (if possible)'. ^ self importAllPipelinesOfProject: aGLHProject ] From 25a2f603834fc20990a3988ceee2f526a9b50394 Mon Sep 17 00:00:00 2001 From: HLAD Nicolas Date: Tue, 23 Sep 2025 17:30:49 +0200 Subject: [PATCH 29/52] tipo corrections --- .../GLHMetamodelGenerator.class.st | 4 ++-- .../GitlabModelImporterTest.class.st | 4 ++-- .../GitlabModelImporter.class.st | 2 +- src/GitLabHealth-Model/GLHPipeline.class.st | 14 +++++++------- src/GitLabHealth-Model/GLHUser.class.st | 11 ++++++----- 5 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/GitLabHealth-Model-Generator/GLHMetamodelGenerator.class.st b/src/GitLabHealth-Model-Generator/GLHMetamodelGenerator.class.st index b25e5165..5ffd7613 100644 --- a/src/GitLabHealth-Model-Generator/GLHMetamodelGenerator.class.st +++ b/src/GitLabHealth-Model-Generator/GLHMetamodelGenerator.class.st @@ -464,9 +464,9 @@ GLHMetamodelGenerator >> mergeRequestsRelations [ (mergeRequest property: #assignee) *- (user property: #currentlyAssignedMergeRequest). (mergeRequest property: #reviewers) - *-* (user property: #reviewedMergeResquest). + *-* (user property: #reviewedMergeRequest). (mergeRequest property: #pipelines) - <>-* (pipeline property: #mergeResquest). + <>-* (pipeline property: #mergeRequest). (mergeRequest property: #mergedCommit) - (commit property: #commitedMergeRequest). (mergeRequest property: #mergeRequestCommit) diff --git a/src/GitLabHealth-Model-Importer-Tests/GitlabModelImporterTest.class.st b/src/GitLabHealth-Model-Importer-Tests/GitlabModelImporterTest.class.st index 1a4571d6..4d077ec7 100644 --- a/src/GitLabHealth-Model-Importer-Tests/GitlabModelImporterTest.class.st +++ b/src/GitLabHealth-Model-Importer-Tests/GitlabModelImporterTest.class.st @@ -469,8 +469,8 @@ GitlabModelImporterTest >> testImportPipelinesOfMergeRequest [ self assert: element project isNotNil. self assert: element project class equals: GLHProject. - self assert: element mergeResquest isNotNil. - self assert: element mergeResquest class equals: GLHMergeRequest. + self assert: element mergeRequest isNotNil. + self assert: element mergeRequest class equals: GLHMergeRequest. ] diff --git a/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st b/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st index c09fdb0b..515eb44e 100644 --- a/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st +++ b/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st @@ -469,7 +469,7 @@ GitlabModelImporter >> configureReaderForTag: reader [ { #category : #'private - configure reader' } GitlabModelImporter >> configureReaderForUser: reader [ - super configureReaderForUser: reader. + super configureReaderForUser: reader ] diff --git a/src/GitLabHealth-Model/GLHPipeline.class.st b/src/GitLabHealth-Model/GLHPipeline.class.st index 1eb5c1bf..1bf98deb 100644 --- a/src/GitLabHealth-Model/GLHPipeline.class.st +++ b/src/GitLabHealth-Model/GLHPipeline.class.st @@ -59,7 +59,7 @@ Class { '#jobs => FMMany type: #GLHJob opposite: #pipeline', '#user => FMOne type: #GLHUser opposite: #launchedPipelines', '#project => FMOne type: #GLHProject opposite: #pipelines', - '#mergeResquest => FMOne type: #GLHMergeRequest opposite: #pipelines' + '#mergeRequest' ], #category : #'GitLabHealth-Model-Entities' } @@ -163,26 +163,26 @@ GLHPipeline >> jobsGroup [ ] { #category : #accessing } -GLHPipeline >> mergeResquest [ +GLHPipeline >> mergeRequest [ "Relation named: #mergeResquest type: #GLHMergeRequest opposite: #pipelines" - ^ mergeResquest + ^ mergeRequest ] { #category : #accessing } -GLHPipeline >> mergeResquest: anObject [ +GLHPipeline >> mergeRequest: anObject [ - mergeResquest := anObject + mergeRequest := anObject ] { #category : #navigation } -GLHPipeline >> mergeResquestGroup [ +GLHPipeline >> mergeRequestGroup [ - ^ MooseSpecializedGroup with: self mergeResquest + ^ MooseSpecializedGroup with: self mergeRequest ] { #category : #accessing } diff --git a/src/GitLabHealth-Model/GLHUser.class.st b/src/GitLabHealth-Model/GLHUser.class.st index 889e8660..fcd11b79 100644 --- a/src/GitLabHealth-Model/GLHUser.class.st +++ b/src/GitLabHealth-Model/GLHUser.class.st @@ -110,7 +110,8 @@ Class { '#assignedMergeRequests => FMMany type: #GLHMergeRequest opposite: #assignees', '#currentlyAssignedMergeRequest => FMMany type: #GLHMergeRequest opposite: #assignee', '#reviewedMergeResquest => FMMany type: #GLHMergeRequest opposite: #reviewers', - '#createdMilestone => FMOne type: #GLHMilestone opposite: #author' + '#createdMilestone => FMOne type: #GLHMilestone opposite: #author', + '#reviewedMergeRequest' ], #category : #'GitLabHealth-Model-Entities' } @@ -197,9 +198,9 @@ GLHUser >> addRelease: anObject [ ] { #category : #adding } -GLHUser >> addReviewedMergeResquest: anObject [ +GLHUser >> addReviewedMergeRequest: anObject [ - ^ self reviewedMergeResquest add: anObject + ^ self reviewedMergeRequest add: anObject ] { #category : #adding } @@ -714,7 +715,7 @@ GLHUser >> releasesGroup [ ] { #category : #accessing } -GLHUser >> reviewedMergeResquest [ +GLHUser >> reviewedMergeRequest [ "Relation named: #reviewedMergeResquest type: #GLHMergeRequest opposite: #reviewers" @@ -722,7 +723,7 @@ GLHUser >> reviewedMergeResquest [ ] { #category : #accessing } -GLHUser >> reviewedMergeResquest: anObject [ +GLHUser >> reviewedMergeRequest: anObject [ reviewedMergeResquest value: anObject From d4c950f2bf37ea85f2fb17ae8897362c83079065 Mon Sep 17 00:00:00 2001 From: HLAD Nicolas Date: Tue, 23 Sep 2025 17:32:06 +0200 Subject: [PATCH 30/52] implement tipo correct in model --- src/GitLabHealth-Model/GLHJob.class.st | 2 +- src/GitLabHealth-Model/GLHMergeRequest.class.st | 12 ++++++------ src/GitLabHealth-Model/GLHPipeline.class.st | 8 ++++---- src/GitLabHealth-Model/GLHUser.class.st | 13 ++++++------- 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/GitLabHealth-Model/GLHJob.class.st b/src/GitLabHealth-Model/GLHJob.class.st index b50f9f3d..bed62ed5 100644 --- a/src/GitLabHealth-Model/GLHJob.class.st +++ b/src/GitLabHealth-Model/GLHJob.class.st @@ -20,8 +20,8 @@ A CI Job | `allow_failure` | `Boolean` | nil | | | `duration` | `Object` | nil | | | `id` | `Number` | nil | | -| `name` | `String` | nil | | | `name` | `String` | nil | Basic name of the entity, not full reference.| +| `name` | `String` | nil | | | `ref` | `String` | nil | | | `web_url` | `String` | nil | | diff --git a/src/GitLabHealth-Model/GLHMergeRequest.class.st b/src/GitLabHealth-Model/GLHMergeRequest.class.st index 99a9b6a2..00141b14 100644 --- a/src/GitLabHealth-Model/GLHMergeRequest.class.st +++ b/src/GitLabHealth-Model/GLHMergeRequest.class.st @@ -13,7 +13,7 @@ a gitlab merge request ### Children | Relation | Origin | Opposite | Type | Comment | |---| -| `pipelines` | `GLHMergeRequest` | `mergeResquest` | `GLHPipeline` | | +| `pipelines` | `GLHMergeRequest` | `mergeRequest` | `GLHPipeline` | | ### Other | Relation | Origin | Opposite | Type | Comment | @@ -29,7 +29,7 @@ a gitlab merge request | `mergedCommit` | `GLHMergeRequest` | `commitedMergeRequest` | `GLHCommit` | | | `merged_by` | `GLHMergeRequest` | `mergerOfMergeRequests` | `GLHUser` | | | `note` | `GLHMergeRequest` | `mergeRequest` | `GLHNote` | | -| `reviewers` | `GLHMergeRequest` | `reviewedMergeResquest` | `GLHUser` | | +| `reviewers` | `GLHMergeRequest` | `reviewedMergeRequest` | `GLHUser` | | | `squashCommit` | `GLHMergeRequest` | `squashedMergeRequest` | `GLHCommit` | | @@ -158,8 +158,8 @@ Class { '#merged_by => FMOne type: #GLHUser opposite: #mergerOfMergeRequests', '#assignees => FMMany type: #GLHUser opposite: #assignedMergeRequests', '#assignee => FMOne type: #GLHUser opposite: #currentlyAssignedMergeRequest', - '#reviewers => FMMany type: #GLHUser opposite: #reviewedMergeResquest', - '#pipelines => FMMany type: #GLHPipeline opposite: #mergeResquest', + '#reviewers => FMMany type: #GLHUser opposite: #reviewedMergeRequest', + '#pipelines => FMMany type: #GLHPipeline opposite: #mergeRequest', '#mergedCommit => FMOne type: #GLHCommit opposite: #commitedMergeRequest', '#mergeRequestCommit => FMOne type: #GLHCommit opposite: #commitedMergeRequest', '#squashCommit => FMOne type: #GLHCommit opposite: #squashedMergeRequest', @@ -729,7 +729,7 @@ GLHMergeRequest >> note: anObject [ { #category : #accessing } GLHMergeRequest >> pipelines [ - "Relation named: #pipelines type: #GLHPipeline opposite: #mergeResquest" + "Relation named: #pipelines type: #GLHPipeline opposite: #mergeRequest" @@ -845,7 +845,7 @@ GLHMergeRequest >> references_short: anObject [ { #category : #accessing } GLHMergeRequest >> reviewers [ - "Relation named: #reviewers type: #GLHUser opposite: #reviewedMergeResquest" + "Relation named: #reviewers type: #GLHUser opposite: #reviewedMergeRequest" diff --git a/src/GitLabHealth-Model/GLHPipeline.class.st b/src/GitLabHealth-Model/GLHPipeline.class.st index 1bf98deb..0c1a2e51 100644 --- a/src/GitLabHealth-Model/GLHPipeline.class.st +++ b/src/GitLabHealth-Model/GLHPipeline.class.st @@ -7,7 +7,7 @@ A GitLab Pipeline execution ### Parents | Relation | Origin | Opposite | Type | Comment | |---| -| `mergeResquest` | `GLHPipeline` | `pipelines` | `GLHMergeRequest` | | +| `mergeRequest` | `GLHPipeline` | `pipelines` | `GLHMergeRequest` | | | `project` | `GLHPipeline` | `pipelines` | `GLHProject` | | ### Children @@ -59,7 +59,7 @@ Class { '#jobs => FMMany type: #GLHJob opposite: #pipeline', '#user => FMOne type: #GLHUser opposite: #launchedPipelines', '#project => FMOne type: #GLHProject opposite: #pipelines', - '#mergeRequest' + '#mergeRequest => FMOne type: #GLHMergeRequest opposite: #pipelines' ], #category : #'GitLabHealth-Model-Entities' } @@ -164,7 +164,7 @@ GLHPipeline >> jobsGroup [ { #category : #accessing } GLHPipeline >> mergeRequest [ - "Relation named: #mergeResquest type: #GLHMergeRequest opposite: #pipelines" + "Relation named: #mergeRequest type: #GLHMergeRequest opposite: #pipelines" @@ -181,7 +181,7 @@ GLHPipeline >> mergeRequest: anObject [ { #category : #navigation } GLHPipeline >> mergeRequestGroup [ - + ^ MooseSpecializedGroup with: self mergeRequest ] diff --git a/src/GitLabHealth-Model/GLHUser.class.st b/src/GitLabHealth-Model/GLHUser.class.st index fcd11b79..fbd051dd 100644 --- a/src/GitLabHealth-Model/GLHUser.class.st +++ b/src/GitLabHealth-Model/GLHUser.class.st @@ -30,7 +30,7 @@ A GitLab User | `currentlyAssignedMergeRequest` | `GLHUser` | `assignee` | `GLHMergeRequest` | | | `launchedPipelines` | `GLHUser` | `user` | `GLHPipeline` | | | `mergerOfMergeRequests` | `GLHUser` | `merged_by` | `GLHMergeRequest` | | -| `reviewedMergeResquest` | `GLHUser` | `reviewers` | `GLHMergeRequest` | | +| `reviewedMergeRequest` | `GLHUser` | `reviewers` | `GLHMergeRequest` | | | `usedMerges` | `GLHUser` | `merge_user` | `GLHMergeRequest` | | @@ -109,9 +109,8 @@ Class { '#mergerOfMergeRequests => FMMany type: #GLHMergeRequest opposite: #merged_by', '#assignedMergeRequests => FMMany type: #GLHMergeRequest opposite: #assignees', '#currentlyAssignedMergeRequest => FMMany type: #GLHMergeRequest opposite: #assignee', - '#reviewedMergeResquest => FMMany type: #GLHMergeRequest opposite: #reviewers', - '#createdMilestone => FMOne type: #GLHMilestone opposite: #author', - '#reviewedMergeRequest' + '#reviewedMergeRequest => FMMany type: #GLHMergeRequest opposite: #reviewers', + '#createdMilestone => FMOne type: #GLHMilestone opposite: #author' ], #category : #'GitLabHealth-Model-Entities' } @@ -716,17 +715,17 @@ GLHUser >> releasesGroup [ { #category : #accessing } GLHUser >> reviewedMergeRequest [ - "Relation named: #reviewedMergeResquest type: #GLHMergeRequest opposite: #reviewers" + "Relation named: #reviewedMergeRequest type: #GLHMergeRequest opposite: #reviewers" - ^ reviewedMergeResquest + ^ reviewedMergeRequest ] { #category : #accessing } GLHUser >> reviewedMergeRequest: anObject [ - reviewedMergeResquest value: anObject + reviewedMergeRequest value: anObject ] { #category : #accessing } From 90749213ff0aa6f61c4bd807d48a8b134b796fee Mon Sep 17 00:00:00 2001 From: HLAD Nicolas Date: Wed, 24 Sep 2025 11:38:24 +0200 Subject: [PATCH 31/52] update reader configurator for github --- .../GithubModelImporter.class.st | 40 ++++--------------- 1 file changed, 7 insertions(+), 33 deletions(-) diff --git a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st index 402f9bca..5b9dd7e4 100644 --- a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st +++ b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st @@ -168,20 +168,13 @@ GithubModelImporter >> configureReaderForMergeRequest: reader [ { #category : #'private - configure reader' } GithubModelImporter >> configureReaderForProject: reader [ - " reader mapInstVarsFor: GLHProject. " + super configureReaderForProject: reader. + reader for: GLHProject do: [ :mapping | - mapping mapInstVar: #name to: #name. - mapping mapInstVar: #description to: #description. - mapping mapInstVar: #id to: #id. - mapping mapInstVar: #archived to: #archived. mapping mapInstVar: #web_url to: #html_url. - mapping mapInstVar: #topics to: #topics ]. + ]. - reader - for: #ArrayOfProject - customDo: [ :customMappting | - customMappting listOfElementSchema: GLHProject ] ] { #category : #private } @@ -682,18 +675,9 @@ GithubModelImporter >> parsePipelinesResult: pipelineOverview [ GithubModelImporter >> parseProjectResult: aResult [ | reader | -" reader := NeoJSONReader on: aResult readStream. - reader for: GLHProject do: [ :mapping | - mapping mapInstVar: #name to: #name. - mapping mapInstVar: #description to: #description. - mapping mapInstVar: #id to: #id. - mapping mapInstVar: #archived to: #archived. - mapping mapInstVar: #web_url to: #html_url. - mapping mapInstVar: #topics to: #topics ]. - ^ reader nextAs: GLHProject" - + reader := generalReader on: aResult readStream. - + ^ reader nextAs: GLHProject ] @@ -701,18 +685,8 @@ GithubModelImporter >> parseProjectResult: aResult [ GithubModelImporter >> parseUserResult: result [ | reader | - reader := NeoJSONReader on: result readStream. - reader for: GLHUser do: [ :mapping | - mapping mapInstVar: #id to: #id. - mapping mapInstVar: #public_email to: #email. - mapping mapInstVar: #username to: #login. - mapping mapInstVar: #bio to: #bio. - mapping mapInstVar: #organization to: #company. - mapping mapInstVar: #followers to: #followers. - mapping mapInstVar: #following to: #following. - mapping mapInstVar: #web_url to: #html_url. - mapping mapInstVar: #name to: #name. - mapping mapInstVar: #avatar_url to: #avatar_url ]. + reader := generalReader on: result readStream. + ^ reader nextAs: GLHUser ] From 20f79a2d6f7cd45c751a6be14b2964a4529a1765 Mon Sep 17 00:00:00 2001 From: HLAD Nicolas Date: Wed, 24 Sep 2025 12:02:23 +0200 Subject: [PATCH 32/52] add tests for user in github importer --- .../GithubApiMock.class.st | 15 + ...ss.st => GithubModelImporterTest.class.st} | 634 +++++++++--------- .../GithubUsersMock.class.st | 43 ++ .../package.st | 2 +- .../GithubModelImporter.class.st | 14 + ...GLPHModelImporterMergeRequestTest.class.st | 2 +- ...piMock.class.st => GitlabApiMock.class.st} | 28 +- .../GitlabModelImporterTest.class.st | 2 +- 8 files changed, 414 insertions(+), 326 deletions(-) create mode 100644 src/GitHubHealth-Model-Importer-Tests/GithubApiMock.class.st rename src/GitHubHealth-Model-Importer-Tests/{GHModelImporterTest.class.st => GithubModelImporterTest.class.st} (94%) create mode 100644 src/GitHubHealth-Model-Importer-Tests/GithubUsersMock.class.st rename src/GitLabHealth-Model-Importer-Tests/{GLHApiMock.class.st => GitlabApiMock.class.st} (66%) diff --git a/src/GitHubHealth-Model-Importer-Tests/GithubApiMock.class.st b/src/GitHubHealth-Model-Importer-Tests/GithubApiMock.class.st new file mode 100644 index 00000000..a63d05f0 --- /dev/null +++ b/src/GitHubHealth-Model-Importer-Tests/GithubApiMock.class.st @@ -0,0 +1,15 @@ +Class { + #name : #GithubApiMock, + #superclass : #Object, + #category : #'GitHubHealth-Model-Importer-Tests' +} + +{ #category : #accessing } +GithubApiMock >> output: aString [ + ^ self +] + +{ #category : #accessing } +GithubApiMock >> users [ + ^ GithubUsersMock new +] diff --git a/src/GitHubHealth-Model-Importer-Tests/GHModelImporterTest.class.st b/src/GitHubHealth-Model-Importer-Tests/GithubModelImporterTest.class.st similarity index 94% rename from src/GitHubHealth-Model-Importer-Tests/GHModelImporterTest.class.st rename to src/GitHubHealth-Model-Importer-Tests/GithubModelImporterTest.class.st index d8ee080b..01977560 100644 --- a/src/GitHubHealth-Model-Importer-Tests/GHModelImporterTest.class.st +++ b/src/GitHubHealth-Model-Importer-Tests/GithubModelImporterTest.class.st @@ -1,309 +1,325 @@ -" -A GHModelImporterTest is a test class for testing the behavior of GHModelImporter -" -Class { - #name : #GHModelImporterTest, - #superclass : #TestCase, - #instVars : [ - 'importer' - ], - #category : #'GitHubHealth-Model-Importer-Tests' -} - -{ #category : #running } -GHModelImporterTest >> setUp [ - super setUp. - - importer := GithubModelImporter new -] - -{ #category : #tests } -GHModelImporterTest >> testParseCommitsResult [ - "we remove the id of author entries to not trigger the call to import user" - - | commits | - commits := importer parseCommitsResult: '[ - { - "sha": "f5ac58f4afe4632b0a26d1e968439c78962da289", - "node_id": "C_kwDOAmR199oAKGY1YWM1OGY0YWZlNDYzMmIwYTI2ZDFlOTY4NDM5Yzc4OTYyZGEyODk", - "commit": { - "author": { - "name": "Clotilde Toullec", - "email": "39184695+ClotildeToullec@users.noreply.github.com", - "date": "2024-09-09T14:32:48Z" - }, - "committer": { - "name": "GitHub", - "email": "noreply@github.com", - "date": "2024-09-09T14:32:48Z" - }, - "message": "Update test-and-release.yml", - "tree": { - "sha": "d6163cb0d50d0e6fe149e3c92b22b13cf2c253f1", - "url": "https://api.github.com/repos/moosetechnology/Moose/git/trees/d6163cb0d50d0e6fe149e3c92b22b13cf2c253f1" - }, - "url": "https://api.github.com/repos/moosetechnology/Moose/git/commits/f5ac58f4afe4632b0a26d1e968439c78962da289", - "comment_count": 0, - "verification": { - "verified": true, - "reason": "valid", - "signature": "-----BEGIN PGP SIGNATURE-----\n\nwsFcBAABCAAQBQJm3wcQCRC1aQ7uu5UhlAAAQ7kQAJOUaDn2VQd1VHl7LbmYSF/R\nTaV6o9Ck1RzeZQRKKhIeofERpItb726h8IPtDh7AcS7c97D0+Opv3c8x7GXvgfzi\ne+XhZ2FErra11pd1AXW1bZwlCEp2KhBEkTXEhKZK8Yg18z/1/hGR3gE27P1qBU7N\nm6pGDVPapdKVmljbteCGprUGcDe9uKqg9sj1YONXNDVm7pAYSrQXOnqfUKm/sFDm\n3wdLVr+U0jshg4Obhy+kxPHqNCxEFCPov4SxUJ0Fx6L4Gg90K4qQ3GwiuSUbwNGP\nAbopNPdNfcWlK2Zzez1e2GiaSwBjhcADkSQ1aGveINuE34KAe/yYd1BRuIW7BtDK\nc+qSGD98KyfNNxPBwv/JyPh76CvDghexgz8+j3PKE+SQkwPHKfJjHbB3Ool4RwY2\npeHU1E1mj0O29a+y6iUcYGyRXkAzBC+B86PJ5QC7dQvklLHZfX2uIFw3tr2ZlunC\nbjhLN7Vnor6BPocSLPdPanOrZXDmoy6grUhyNSgvCuoiRZ9HoG3NREn4GLEFIjLd\nNKxnS8Zim8QQnd2lvvunz7Gge6mfwWLGMIX4MPC3BQUYhZ6i2nx7vqIID0cEyWlj\n6K+tUj/MJkgj0EcnBL8HC1AIiJeJk9hTBdOHrJj3/kvM/0HIrAg+PQEdK0y2iYLp\nxXqau3U95zTp2792mpVc\n=n2IL\n-----END PGP SIGNATURE-----\n", - "payload": "tree d6163cb0d50d0e6fe149e3c92b22b13cf2c253f1\nparent eb31d04f01254d0caf7c7a5b03546e3f6a5c3d58\nauthor Clotilde Toullec <39184695+ClotildeToullec@users.noreply.github.com> 1725892368 +0200\ncommitter GitHub 1725892368 +0200\n\nUpdate test-and-release.yml" - } - }, - "url": "https://api.github.com/repos/moosetechnology/Moose/commits/f5ac58f4afe4632b0a26d1e968439c78962da289", - "html_url": "https://github.com/moosetechnology/Moose/commit/f5ac58f4afe4632b0a26d1e968439c78962da289", - "comments_url": "https://api.github.com/repos/moosetechnology/Moose/commits/f5ac58f4afe4632b0a26d1e968439c78962da289/comments", - "author": { - "login": "ClotildeToullec", - "node_id": "MDQ6VXNlcjM5MTg0Njk1", - "avatar_url": "https://avatars.githubusercontent.com/u/39184695?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/ClotildeToullec", - "html_url": "https://github.com/ClotildeToullec", - "followers_url": "https://api.github.com/users/ClotildeToullec/followers", - "following_url": "https://api.github.com/users/ClotildeToullec/following{/other_user}", - "gists_url": "https://api.github.com/users/ClotildeToullec/gists{/gist_id}", - "starred_url": "https://api.github.com/users/ClotildeToullec/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/ClotildeToullec/subscriptions", - "organizations_url": "https://api.github.com/users/ClotildeToullec/orgs", - "repos_url": "https://api.github.com/users/ClotildeToullec/repos", - "events_url": "https://api.github.com/users/ClotildeToullec/events{/privacy}", - "received_events_url": "https://api.github.com/users/ClotildeToullec/received_events", - "type": "User", - "site_admin": false - }, - "committer": { - "login": "web-flow", - "id": 19864447, - "node_id": "MDQ6VXNlcjE5ODY0NDQ3", - "avatar_url": "https://avatars.githubusercontent.com/u/19864447?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/web-flow", - "html_url": "https://github.com/web-flow", - "followers_url": "https://api.github.com/users/web-flow/followers", - "following_url": "https://api.github.com/users/web-flow/following{/other_user}", - "gists_url": "https://api.github.com/users/web-flow/gists{/gist_id}", - "starred_url": "https://api.github.com/users/web-flow/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/web-flow/subscriptions", - "organizations_url": "https://api.github.com/users/web-flow/orgs", - "repos_url": "https://api.github.com/users/web-flow/repos", - "events_url": "https://api.github.com/users/web-flow/events{/privacy}", - "received_events_url": "https://api.github.com/users/web-flow/received_events", - "type": "User", - "site_admin": false - }, - "parents": [ - { - "sha": "eb31d04f01254d0caf7c7a5b03546e3f6a5c3d58", - "url": "https://api.github.com/repos/moosetechnology/Moose/commits/eb31d04f01254d0caf7c7a5b03546e3f6a5c3d58", - "html_url": "https://github.com/moosetechnology/Moose/commit/eb31d04f01254d0caf7c7a5b03546e3f6a5c3d58" - } - ] - }, - { - "sha": "eb31d04f01254d0caf7c7a5b03546e3f6a5c3d58", - "node_id": "C_kwDOAmR199oAKGViMzFkMDRmMDEyNTRkMGNhZjdjN2E1YjAzNTQ2ZTNmNmE1YzNkNTg", - "commit": { - "author": { - "name": "Clotilde Toullec", - "email": "39184695+ClotildeToullec@users.noreply.github.com", - "date": "2024-09-09T14:23:04Z" - }, - "committer": { - "name": "GitHub", - "email": "noreply@github.com", - "date": "2024-09-09T14:23:04Z" - }, - "message": "Update release.yml", - "tree": { - "sha": "2603616f5508d52a14de694ebfd36a4fe3d92c32", - "url": "https://api.github.com/repos/moosetechnology/Moose/git/trees/2603616f5508d52a14de694ebfd36a4fe3d92c32" - }, - "url": "https://api.github.com/repos/moosetechnology/Moose/git/commits/eb31d04f01254d0caf7c7a5b03546e3f6a5c3d58", - "comment_count": 0, - "verification": { - "verified": true, - "reason": "valid", - "signature": "-----BEGIN PGP SIGNATURE-----\n\nwsFcBAABCAAQBQJm3wTJCRC1aQ7uu5UhlAAAMVsQADtx9h/p+gZpgOZfWwGUgV1O\nk8HSuq+Q1Z/OMg22+zvTYw77qS7ni+jFn34XYGpZECbMybTobqT8bRWvKGaoyhE3\n054OutXJLRhh/6Siy1AI9Bcr/huLWHzQ0faU4M4mO+SS/RQF1yfqCNzyDFfafWEU\nxnlf1CpdknoWAAjN2kaNBXvBBmTBOPZQ5mP+j7Mi2U4DvoG/2NpB9QhkjE0zdw0Z\nddApTKCe4QkrtFfLTJ3NJuWoCoNif+8leyfAsE4iqonZvhUKly/9EdZuhR8QgbrE\nunDk9RF9IoZDR4b1Sz/qY+ajd1IXqYNRQg0Aihb5DDzQY8tZsZRmrlSKw/xqwTOf\nOy5rO9MWSGHFqnRbWZfgzWYgE/w0pvbL3Z9ahsYbHJaWcxSX9BcfV1KbN5ygm9Bx\nlDUr8D2scOrmr+Eg4LdmJxtZB6eEJfPA34H/PY5IZvQDkbFyzPJm4IUfRRFmEwLy\nx1JmE/bVBl1q0YaLiDW856y5yAAkYfRlkHVhqgya6kfaWEHNMl4r0od8M4PbNF9F\n/Qx4VNqQH+u+iThn8l9BDA0B2NrPu5rUyz+SAo/OjRuBoVv+yiYBaevLzkuLOhkL\noUxYduwo9bT2imkiOvKEAsXpNPjuraf6gHUkY9OxinnEp6AWe/qyqc5duhFSJuzC\nAVA3RPqe7kvwqnWKurpZ\n=bDEh\n-----END PGP SIGNATURE-----\n", - "payload": "tree 2603616f5508d52a14de694ebfd36a4fe3d92c32\nparent cfa833e9c504fe1f27c93fca016a5006cc300206\nauthor Clotilde Toullec <39184695+ClotildeToullec@users.noreply.github.com> 1725891784 +0200\ncommitter GitHub 1725891784 +0200\n\nUpdate release.yml" - } - }, - "url": "https://api.github.com/repos/moosetechnology/Moose/commits/eb31d04f01254d0caf7c7a5b03546e3f6a5c3d58F", - "html_url": "https://github.com/moosetechnology/Moose/commit/eb31d04f01254d0caf7c7a5b03546e3f6a5c3d58", - "comments_url": "https://api.github.com/repos/moosetechnology/Moose/commits/eb31d04f01254d0caf7c7a5b03546e3f6a5c3d58/comments", - "author": { - "login": "ClotildeToullec", - "node_id": "MDQ6VXNlcjM5MTg0Njk1", - "avatar_url": "https://avatars.githubusercontent.com/u/39184695?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/ClotildeToullec", - "html_url": "https://github.com/ClotildeToullec", - "followers_url": "https://api.github.com/users/ClotildeToullec/followers", - "following_url": "https://api.github.com/users/ClotildeToullec/following{/other_user}", - "gists_url": "https://api.github.com/users/ClotildeToullec/gists{/gist_id}", - "starred_url": "https://api.github.com/users/ClotildeToullec/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/ClotildeToullec/subscriptions", - "organizations_url": "https://api.github.com/users/ClotildeToullec/orgs", - "repos_url": "https://api.github.com/users/ClotildeToullec/repos", - "events_url": "https://api.github.com/users/ClotildeToullec/events{/privacy}", - "received_events_url": "https://api.github.com/users/ClotildeToullec/received_events", - "type": "User", - "site_admin": false - }, - "committer": { - "login": "web-flow", - "id": 19864447, - "node_id": "MDQ6VXNlcjE5ODY0NDQ3", - "avatar_url": "https://avatars.githubusercontent.com/u/19864447?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/web-flow", - "html_url": "https://github.com/web-flow", - "followers_url": "https://api.github.com/users/web-flow/followers", - "following_url": "https://api.github.com/users/web-flow/following{/other_user}", - "gists_url": "https://api.github.com/users/web-flow/gists{/gist_id}", - "starred_url": "https://api.github.com/users/web-flow/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/web-flow/subscriptions", - "organizations_url": "https://api.github.com/users/web-flow/orgs", - "repos_url": "https://api.github.com/users/web-flow/repos", - "events_url": "https://api.github.com/users/web-flow/events{/privacy}", - "received_events_url": "https://api.github.com/users/web-flow/received_events", - "type": "User", - "site_admin": false - }, - "parents": [ - { - "sha": "cfa833e9c504fe1f27c93fca016a5006cc300206", - "url": "https://api.github.com/repos/moosetechnology/Moose/commits/cfa833e9c504fe1f27c93fca016a5006cc300206", - "html_url": "https://github.com/moosetechnology/Moose/commit/cfa833e9c504fe1f27c93fca016a5006cc300206" - } - ] - } -]'. - - self assert: commits size equals: 2. - self - assert: commits first message - equals: 'Update test-and-release.yml'. - self assert: commits second message equals: 'Update release.yml'. - self assert: commits first authored_date isNotNil. - self assert: commits first committed_date isNotNil -] - -{ #category : #tests } -GHModelImporterTest >> testParseCommitsResultWithSomeNullValue [ - "we remove the id of author entries to not trigger the call to import user" - - | commits | - commits := importer parseCommitsResult: '[ -{ - "sha": "f566f11d4bb045e5ab762fb430655f3d218bd784", - "node_id": "C_kwDOCCsKwdoAKGY1NjZmMTFkNGJiMDQ1ZTVhYjc2MmZiNDMwNjU1ZjNkMjE4YmQ3ODQ", - "commit": { - "author": { - "name": "anquetil", - "email": "nicolas.anquetil@inria.fr", - "date": "2024-02-22T14:09:56Z" - }, - "committer": { - "name": "anquetil", - "email": "nicolas.anquetil@inria.fr", - "date": "2024-02-22T14:09:56Z" - }, - "message": "A generator for a copy visitor (ie. a visitor that creates a copy of an AST", - "tree": { - "sha": "29b55107b0378ae3668b984a688d1e1cbd6062d4", - "url": "https://api.github.com/repos/moosetechnology/FAST/git/trees/29b55107b0378ae3668b984a688d1e1cbd6062d4" - }, - "url": "https://api.github.com/repos/moosetechnology/FAST/git/commits/f566f11d4bb045e5ab762fb430655f3d218bd784", - "comment_count": 0, - "verification": { - "verified": false, - "reason": "unsigned", - "signature": null, - "payload": null - } - }, - "url": "https://api.github.com/repos/moosetechnology/FAST/commits/f566f11d4bb045e5ab762fb430655f3d218bd784", - "html_url": "https://github.com/moosetechnology/FAST/commit/f566f11d4bb045e5ab762fb430655f3d218bd784", - "comments_url": "https://api.github.com/repos/moosetechnology/FAST/commits/f566f11d4bb045e5ab762fb430655f3d218bd784/comments", - "author": null, - "committer": null, - "parents": [ - { - "sha": "bfd5bfcb6cafe10be0cf58ff5eb22d26df809eaa", - "url": "https://api.github.com/repos/moosetechnology/FAST/commits/bfd5bfcb6cafe10be0cf58ff5eb22d26df809eaa", - "html_url": "https://github.com/moosetechnology/FAST/commit/bfd5bfcb6cafe10be0cf58ff5eb22d26df809eaa" - } - ] - } -]'. - - self assert: commits size equals: 1 -] - -{ #category : #test } -GHModelImporterTest >> testParsePipelinesResult [ - - | project | - project := importer parsePipelinesResult: '{ - "total_count": 1, - "workflow_runs": [ - { - "id": 7482814798, - "conclusion": "success", - "run_started_at": "2024-01-11T00:00:00" - }]}'. - - self assert: project workflow_runs size equals: 1. - - self assert: project workflow_runs anyOne status equals: 'success'. - self - assert: project workflow_runs anyOne runDate - equals: (DateAndTime year: 2024 month: 01 day: 11) -] - -{ #category : #tests } -GHModelImporterTest >> testParseUserResult [ - - | user | - user := importer parseUserResult: '{ - "login": "ClotildeToullec", - "id": 39184695, - "node_id": "MDQ6VXNlcjM5MTg0Njk1", - "avatar_url": "https://avatars.githubusercontent.com/u/39184695?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/ClotildeToullec", - "html_url": "https://github.com/ClotildeToullec", - "followers_url": "https://api.github.com/users/ClotildeToullec/followers", - "following_url": "https://api.github.com/users/ClotildeToullec/following{/other_user}", - "gists_url": "https://api.github.com/users/ClotildeToullec/gists{/gist_id}", - "starred_url": "https://api.github.com/users/ClotildeToullec/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/ClotildeToullec/subscriptions", - "organizations_url": "https://api.github.com/users/ClotildeToullec/orgs", - "repos_url": "https://api.github.com/users/ClotildeToullec/repos", - "events_url": "https://api.github.com/users/ClotildeToullec/events{/privacy}", - "received_events_url": "https://api.github.com/users/ClotildeToullec/received_events", - "type": "User", - "site_admin": false, - "name": "Clotilde Toullec", - "company": "Inria", - "blog": "", - "location": "Villeneuve d''Ascq", - "email": null, - "hireable": null, - "bio": "Software engineer at Inria Lille, France\r\nMaintainer and developer of @moosetechnology ", - "twitter_username": null, - "public_repos": 35, - "public_gists": 0, - "followers": 11, - "following": 2, - "created_at": "2018-05-11T07:52:42Z", - "updated_at": "2024-08-26T08:29:32Z" -} -'. - - self assert: user name equals: 'Clotilde Toullec'. - - self assert: user id equals: 39184695 -] +" +A GithubModelImporterTest is a test class for testing the behavior of GithubModelImporter +" +Class { + #name : #GithubModelImporterTest, + #superclass : #TestCase, + #instVars : [ + 'importer', + 'model' + ], + #category : #'GitHubHealth-Model-Importer-Tests' +} + +{ #category : #running } +GithubModelImporterTest >> setUp [ + + super setUp. + + importer := GithubModelImporter new. + model := GLHModel new. + importer glhModel: model. + importer repoApi: GithubApiMock new +] + +{ #category : #'tests - users' } +GithubModelImporterTest >> testImportUser [ + + | element | + element := importer importUser: 123. + + self assert: element isNotNil. + self assert: element class equals: GLHUser. + +] + +{ #category : #'tests - parsing' } +GithubModelImporterTest >> testParseCommitsResult [ + "we remove the id of author entries to not trigger the call to import user" + + | commits | + commits := importer parseCommitsResult: '[ + { + "sha": "f5ac58f4afe4632b0a26d1e968439c78962da289", + "node_id": "C_kwDOAmR199oAKGY1YWM1OGY0YWZlNDYzMmIwYTI2ZDFlOTY4NDM5Yzc4OTYyZGEyODk", + "commit": { + "author": { + "name": "Clotilde Toullec", + "email": "39184695+ClotildeToullec@users.noreply.github.com", + "date": "2024-09-09T14:32:48Z" + }, + "committer": { + "name": "GitHub", + "email": "noreply@github.com", + "date": "2024-09-09T14:32:48Z" + }, + "message": "Update test-and-release.yml", + "tree": { + "sha": "d6163cb0d50d0e6fe149e3c92b22b13cf2c253f1", + "url": "https://api.github.com/repos/moosetechnology/Moose/git/trees/d6163cb0d50d0e6fe149e3c92b22b13cf2c253f1" + }, + "url": "https://api.github.com/repos/moosetechnology/Moose/git/commits/f5ac58f4afe4632b0a26d1e968439c78962da289", + "comment_count": 0, + "verification": { + "verified": true, + "reason": "valid", + "signature": "-----BEGIN PGP SIGNATURE-----\n\nwsFcBAABCAAQBQJm3wcQCRC1aQ7uu5UhlAAAQ7kQAJOUaDn2VQd1VHl7LbmYSF/R\nTaV6o9Ck1RzeZQRKKhIeofERpItb726h8IPtDh7AcS7c97D0+Opv3c8x7GXvgfzi\ne+XhZ2FErra11pd1AXW1bZwlCEp2KhBEkTXEhKZK8Yg18z/1/hGR3gE27P1qBU7N\nm6pGDVPapdKVmljbteCGprUGcDe9uKqg9sj1YONXNDVm7pAYSrQXOnqfUKm/sFDm\n3wdLVr+U0jshg4Obhy+kxPHqNCxEFCPov4SxUJ0Fx6L4Gg90K4qQ3GwiuSUbwNGP\nAbopNPdNfcWlK2Zzez1e2GiaSwBjhcADkSQ1aGveINuE34KAe/yYd1BRuIW7BtDK\nc+qSGD98KyfNNxPBwv/JyPh76CvDghexgz8+j3PKE+SQkwPHKfJjHbB3Ool4RwY2\npeHU1E1mj0O29a+y6iUcYGyRXkAzBC+B86PJ5QC7dQvklLHZfX2uIFw3tr2ZlunC\nbjhLN7Vnor6BPocSLPdPanOrZXDmoy6grUhyNSgvCuoiRZ9HoG3NREn4GLEFIjLd\nNKxnS8Zim8QQnd2lvvunz7Gge6mfwWLGMIX4MPC3BQUYhZ6i2nx7vqIID0cEyWlj\n6K+tUj/MJkgj0EcnBL8HC1AIiJeJk9hTBdOHrJj3/kvM/0HIrAg+PQEdK0y2iYLp\nxXqau3U95zTp2792mpVc\n=n2IL\n-----END PGP SIGNATURE-----\n", + "payload": "tree d6163cb0d50d0e6fe149e3c92b22b13cf2c253f1\nparent eb31d04f01254d0caf7c7a5b03546e3f6a5c3d58\nauthor Clotilde Toullec <39184695+ClotildeToullec@users.noreply.github.com> 1725892368 +0200\ncommitter GitHub 1725892368 +0200\n\nUpdate test-and-release.yml" + } + }, + "url": "https://api.github.com/repos/moosetechnology/Moose/commits/f5ac58f4afe4632b0a26d1e968439c78962da289", + "html_url": "https://github.com/moosetechnology/Moose/commit/f5ac58f4afe4632b0a26d1e968439c78962da289", + "comments_url": "https://api.github.com/repos/moosetechnology/Moose/commits/f5ac58f4afe4632b0a26d1e968439c78962da289/comments", + "author": { + "login": "ClotildeToullec", + "node_id": "MDQ6VXNlcjM5MTg0Njk1", + "avatar_url": "https://avatars.githubusercontent.com/u/39184695?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/ClotildeToullec", + "html_url": "https://github.com/ClotildeToullec", + "followers_url": "https://api.github.com/users/ClotildeToullec/followers", + "following_url": "https://api.github.com/users/ClotildeToullec/following{/other_user}", + "gists_url": "https://api.github.com/users/ClotildeToullec/gists{/gist_id}", + "starred_url": "https://api.github.com/users/ClotildeToullec/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/ClotildeToullec/subscriptions", + "organizations_url": "https://api.github.com/users/ClotildeToullec/orgs", + "repos_url": "https://api.github.com/users/ClotildeToullec/repos", + "events_url": "https://api.github.com/users/ClotildeToullec/events{/privacy}", + "received_events_url": "https://api.github.com/users/ClotildeToullec/received_events", + "type": "User", + "site_admin": false + }, + "committer": { + "login": "web-flow", + "id": 19864447, + "node_id": "MDQ6VXNlcjE5ODY0NDQ3", + "avatar_url": "https://avatars.githubusercontent.com/u/19864447?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/web-flow", + "html_url": "https://github.com/web-flow", + "followers_url": "https://api.github.com/users/web-flow/followers", + "following_url": "https://api.github.com/users/web-flow/following{/other_user}", + "gists_url": "https://api.github.com/users/web-flow/gists{/gist_id}", + "starred_url": "https://api.github.com/users/web-flow/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/web-flow/subscriptions", + "organizations_url": "https://api.github.com/users/web-flow/orgs", + "repos_url": "https://api.github.com/users/web-flow/repos", + "events_url": "https://api.github.com/users/web-flow/events{/privacy}", + "received_events_url": "https://api.github.com/users/web-flow/received_events", + "type": "User", + "site_admin": false + }, + "parents": [ + { + "sha": "eb31d04f01254d0caf7c7a5b03546e3f6a5c3d58", + "url": "https://api.github.com/repos/moosetechnology/Moose/commits/eb31d04f01254d0caf7c7a5b03546e3f6a5c3d58", + "html_url": "https://github.com/moosetechnology/Moose/commit/eb31d04f01254d0caf7c7a5b03546e3f6a5c3d58" + } + ] + }, + { + "sha": "eb31d04f01254d0caf7c7a5b03546e3f6a5c3d58", + "node_id": "C_kwDOAmR199oAKGViMzFkMDRmMDEyNTRkMGNhZjdjN2E1YjAzNTQ2ZTNmNmE1YzNkNTg", + "commit": { + "author": { + "name": "Clotilde Toullec", + "email": "39184695+ClotildeToullec@users.noreply.github.com", + "date": "2024-09-09T14:23:04Z" + }, + "committer": { + "name": "GitHub", + "email": "noreply@github.com", + "date": "2024-09-09T14:23:04Z" + }, + "message": "Update release.yml", + "tree": { + "sha": "2603616f5508d52a14de694ebfd36a4fe3d92c32", + "url": "https://api.github.com/repos/moosetechnology/Moose/git/trees/2603616f5508d52a14de694ebfd36a4fe3d92c32" + }, + "url": "https://api.github.com/repos/moosetechnology/Moose/git/commits/eb31d04f01254d0caf7c7a5b03546e3f6a5c3d58", + "comment_count": 0, + "verification": { + "verified": true, + "reason": "valid", + "signature": "-----BEGIN PGP SIGNATURE-----\n\nwsFcBAABCAAQBQJm3wTJCRC1aQ7uu5UhlAAAMVsQADtx9h/p+gZpgOZfWwGUgV1O\nk8HSuq+Q1Z/OMg22+zvTYw77qS7ni+jFn34XYGpZECbMybTobqT8bRWvKGaoyhE3\n054OutXJLRhh/6Siy1AI9Bcr/huLWHzQ0faU4M4mO+SS/RQF1yfqCNzyDFfafWEU\nxnlf1CpdknoWAAjN2kaNBXvBBmTBOPZQ5mP+j7Mi2U4DvoG/2NpB9QhkjE0zdw0Z\nddApTKCe4QkrtFfLTJ3NJuWoCoNif+8leyfAsE4iqonZvhUKly/9EdZuhR8QgbrE\nunDk9RF9IoZDR4b1Sz/qY+ajd1IXqYNRQg0Aihb5DDzQY8tZsZRmrlSKw/xqwTOf\nOy5rO9MWSGHFqnRbWZfgzWYgE/w0pvbL3Z9ahsYbHJaWcxSX9BcfV1KbN5ygm9Bx\nlDUr8D2scOrmr+Eg4LdmJxtZB6eEJfPA34H/PY5IZvQDkbFyzPJm4IUfRRFmEwLy\nx1JmE/bVBl1q0YaLiDW856y5yAAkYfRlkHVhqgya6kfaWEHNMl4r0od8M4PbNF9F\n/Qx4VNqQH+u+iThn8l9BDA0B2NrPu5rUyz+SAo/OjRuBoVv+yiYBaevLzkuLOhkL\noUxYduwo9bT2imkiOvKEAsXpNPjuraf6gHUkY9OxinnEp6AWe/qyqc5duhFSJuzC\nAVA3RPqe7kvwqnWKurpZ\n=bDEh\n-----END PGP SIGNATURE-----\n", + "payload": "tree 2603616f5508d52a14de694ebfd36a4fe3d92c32\nparent cfa833e9c504fe1f27c93fca016a5006cc300206\nauthor Clotilde Toullec <39184695+ClotildeToullec@users.noreply.github.com> 1725891784 +0200\ncommitter GitHub 1725891784 +0200\n\nUpdate release.yml" + } + }, + "url": "https://api.github.com/repos/moosetechnology/Moose/commits/eb31d04f01254d0caf7c7a5b03546e3f6a5c3d58F", + "html_url": "https://github.com/moosetechnology/Moose/commit/eb31d04f01254d0caf7c7a5b03546e3f6a5c3d58", + "comments_url": "https://api.github.com/repos/moosetechnology/Moose/commits/eb31d04f01254d0caf7c7a5b03546e3f6a5c3d58/comments", + "author": { + "login": "ClotildeToullec", + "node_id": "MDQ6VXNlcjM5MTg0Njk1", + "avatar_url": "https://avatars.githubusercontent.com/u/39184695?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/ClotildeToullec", + "html_url": "https://github.com/ClotildeToullec", + "followers_url": "https://api.github.com/users/ClotildeToullec/followers", + "following_url": "https://api.github.com/users/ClotildeToullec/following{/other_user}", + "gists_url": "https://api.github.com/users/ClotildeToullec/gists{/gist_id}", + "starred_url": "https://api.github.com/users/ClotildeToullec/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/ClotildeToullec/subscriptions", + "organizations_url": "https://api.github.com/users/ClotildeToullec/orgs", + "repos_url": "https://api.github.com/users/ClotildeToullec/repos", + "events_url": "https://api.github.com/users/ClotildeToullec/events{/privacy}", + "received_events_url": "https://api.github.com/users/ClotildeToullec/received_events", + "type": "User", + "site_admin": false + }, + "committer": { + "login": "web-flow", + "id": 19864447, + "node_id": "MDQ6VXNlcjE5ODY0NDQ3", + "avatar_url": "https://avatars.githubusercontent.com/u/19864447?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/web-flow", + "html_url": "https://github.com/web-flow", + "followers_url": "https://api.github.com/users/web-flow/followers", + "following_url": "https://api.github.com/users/web-flow/following{/other_user}", + "gists_url": "https://api.github.com/users/web-flow/gists{/gist_id}", + "starred_url": "https://api.github.com/users/web-flow/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/web-flow/subscriptions", + "organizations_url": "https://api.github.com/users/web-flow/orgs", + "repos_url": "https://api.github.com/users/web-flow/repos", + "events_url": "https://api.github.com/users/web-flow/events{/privacy}", + "received_events_url": "https://api.github.com/users/web-flow/received_events", + "type": "User", + "site_admin": false + }, + "parents": [ + { + "sha": "cfa833e9c504fe1f27c93fca016a5006cc300206", + "url": "https://api.github.com/repos/moosetechnology/Moose/commits/cfa833e9c504fe1f27c93fca016a5006cc300206", + "html_url": "https://github.com/moosetechnology/Moose/commit/cfa833e9c504fe1f27c93fca016a5006cc300206" + } + ] + } +]'. + + self assert: commits size equals: 2. + self + assert: commits first message + equals: 'Update test-and-release.yml'. + self assert: commits second message equals: 'Update release.yml'. + self assert: commits first authored_date isNotNil. + self assert: commits first committed_date isNotNil +] + +{ #category : #'tests - parsing' } +GithubModelImporterTest >> testParseCommitsResultWithSomeNullValue [ + "we remove the id of author entries to not trigger the call to import user" + + | commits | + commits := importer parseCommitsResult: '[ +{ + "sha": "f566f11d4bb045e5ab762fb430655f3d218bd784", + "node_id": "C_kwDOCCsKwdoAKGY1NjZmMTFkNGJiMDQ1ZTVhYjc2MmZiNDMwNjU1ZjNkMjE4YmQ3ODQ", + "commit": { + "author": { + "name": "anquetil", + "email": "nicolas.anquetil@inria.fr", + "date": "2024-02-22T14:09:56Z" + }, + "committer": { + "name": "anquetil", + "email": "nicolas.anquetil@inria.fr", + "date": "2024-02-22T14:09:56Z" + }, + "message": "A generator for a copy visitor (ie. a visitor that creates a copy of an AST", + "tree": { + "sha": "29b55107b0378ae3668b984a688d1e1cbd6062d4", + "url": "https://api.github.com/repos/moosetechnology/FAST/git/trees/29b55107b0378ae3668b984a688d1e1cbd6062d4" + }, + "url": "https://api.github.com/repos/moosetechnology/FAST/git/commits/f566f11d4bb045e5ab762fb430655f3d218bd784", + "comment_count": 0, + "verification": { + "verified": false, + "reason": "unsigned", + "signature": null, + "payload": null + } + }, + "url": "https://api.github.com/repos/moosetechnology/FAST/commits/f566f11d4bb045e5ab762fb430655f3d218bd784", + "html_url": "https://github.com/moosetechnology/FAST/commit/f566f11d4bb045e5ab762fb430655f3d218bd784", + "comments_url": "https://api.github.com/repos/moosetechnology/FAST/commits/f566f11d4bb045e5ab762fb430655f3d218bd784/comments", + "author": null, + "committer": null, + "parents": [ + { + "sha": "bfd5bfcb6cafe10be0cf58ff5eb22d26df809eaa", + "url": "https://api.github.com/repos/moosetechnology/FAST/commits/bfd5bfcb6cafe10be0cf58ff5eb22d26df809eaa", + "html_url": "https://github.com/moosetechnology/FAST/commit/bfd5bfcb6cafe10be0cf58ff5eb22d26df809eaa" + } + ] + } +]'. + + self assert: commits size equals: 1 +] + +{ #category : #'tests - parsing' } +GithubModelImporterTest >> testParsePipelinesResult [ + + | project | + project := importer parsePipelinesResult: '{ + "total_count": 1, + "workflow_runs": [ + { + "id": 7482814798, + "conclusion": "success", + "run_started_at": "2024-01-11T00:00:00" + }]}'. + + self assert: project workflow_runs size equals: 1. + + self assert: project workflow_runs anyOne status equals: 'success'. + self + assert: project workflow_runs anyOne runDate + equals: (DateAndTime year: 2024 month: 01 day: 11) +] + +{ #category : #'tests - parsing' } +GithubModelImporterTest >> testParseUserResult [ + + | user | + user := importer parseUserResult: '{ + "login": "ClotildeToullec", + "id": 39184695, + "node_id": "MDQ6VXNlcjM5MTg0Njk1", + "avatar_url": "https://avatars.githubusercontent.com/u/39184695?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/ClotildeToullec", + "html_url": "https://github.com/ClotildeToullec", + "followers_url": "https://api.github.com/users/ClotildeToullec/followers", + "following_url": "https://api.github.com/users/ClotildeToullec/following{/other_user}", + "gists_url": "https://api.github.com/users/ClotildeToullec/gists{/gist_id}", + "starred_url": "https://api.github.com/users/ClotildeToullec/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/ClotildeToullec/subscriptions", + "organizations_url": "https://api.github.com/users/ClotildeToullec/orgs", + "repos_url": "https://api.github.com/users/ClotildeToullec/repos", + "events_url": "https://api.github.com/users/ClotildeToullec/events{/privacy}", + "received_events_url": "https://api.github.com/users/ClotildeToullec/received_events", + "type": "User", + "site_admin": false, + "name": "Clotilde Toullec", + "company": "Inria", + "blog": "", + "location": "Villeneuve d''Ascq", + "email": null, + "hireable": null, + "bio": "Software engineer at Inria Lille, France\r\nMaintainer and developer of @moosetechnology ", + "twitter_username": null, + "public_repos": 35, + "public_gists": 0, + "followers": 11, + "following": 2, + "created_at": "2018-05-11T07:52:42Z", + "updated_at": "2024-08-26T08:29:32Z" +} +'. + + self assert: user name equals: 'Clotilde Toullec'. + + self assert: user id equals: 39184695 +] diff --git a/src/GitHubHealth-Model-Importer-Tests/GithubUsersMock.class.st b/src/GitHubHealth-Model-Importer-Tests/GithubUsersMock.class.st new file mode 100644 index 00000000..85e5cb55 --- /dev/null +++ b/src/GitHubHealth-Model-Importer-Tests/GithubUsersMock.class.st @@ -0,0 +1,43 @@ +Class { + #name : #GithubUsersMock, + #superclass : #Object, + #category : #'GitHubHealth-Model-Importer-Tests' +} + +{ #category : #'as yet unclassified' } +GithubUsersMock >> getUserId: anInteger [ + ^ '{ + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false, + "name": "monalisa octocat", + "company": "GitHub", + "blog": "https://github.com/blog", + "location": "San Francisco", + "email": "octocat@github.com", + "hireable": false, + "bio": "There once was...", + "twitter_username": "monatheoctocat", + "public_repos": 2, + "public_gists": 1, + "followers": 20, + "following": 0, + "created_at": "2008-01-14T04:33:35Z", + "updated_at": "2008-01-14T04:33:35Z" +}' +] diff --git a/src/GitHubHealth-Model-Importer-Tests/package.st b/src/GitHubHealth-Model-Importer-Tests/package.st index 9c0b5b71..5cc38a96 100644 --- a/src/GitHubHealth-Model-Importer-Tests/package.st +++ b/src/GitHubHealth-Model-Importer-Tests/package.st @@ -1 +1 @@ -Package { #name : #'GitHubHealth-Model-Importer-Tests' } +Package { #name : #'GitHubHealth-Model-Importer-Tests' } diff --git a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st index 5b9dd7e4..aa3da507 100644 --- a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st +++ b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st @@ -177,6 +177,20 @@ GithubModelImporter >> configureReaderForProject: reader [ ] +{ #category : #'private - configure reader' } +GithubModelImporter >> configureReaderForUser: reader [ + super configureReaderForUser: reader. + + + reader for: GLHUser do: [ :mapping | + mapping mapInstVar: #public_email to: #email. + mapping mapInstVar: #username to: #login. + mapping mapInstVar: #bio to: #bio. + mapping mapInstVar: #organization to: #company. + mapping mapInstVar: #web_url to: #html_url. + ]. +] + { #category : #private } GithubModelImporter >> convertApiFileAsFile: aAPIFile [ diff --git a/src/GitLabHealth-Model-Importer-Tests/GLPHModelImporterMergeRequestTest.class.st b/src/GitLabHealth-Model-Importer-Tests/GLPHModelImporterMergeRequestTest.class.st index 0824f298..20353f0f 100644 --- a/src/GitLabHealth-Model-Importer-Tests/GLPHModelImporterMergeRequestTest.class.st +++ b/src/GitLabHealth-Model-Importer-Tests/GLPHModelImporterMergeRequestTest.class.st @@ -16,7 +16,7 @@ GLPHModelImporterMergeRequestTest >> setUp [ super setUp. glhImporter := GitlabModelImporter new. - glhImporter repoApi: GLHApiMock new. + glhImporter repoApi: GitlabApiMock new. glhModel := GLHModel new. glhImporter glhModel: glhModel. gitlabMergeData := '[ diff --git a/src/GitLabHealth-Model-Importer-Tests/GLHApiMock.class.st b/src/GitLabHealth-Model-Importer-Tests/GitlabApiMock.class.st similarity index 66% rename from src/GitLabHealth-Model-Importer-Tests/GLHApiMock.class.st rename to src/GitLabHealth-Model-Importer-Tests/GitlabApiMock.class.st index bbb0d464..257cf853 100644 --- a/src/GitLabHealth-Model-Importer-Tests/GLHApiMock.class.st +++ b/src/GitLabHealth-Model-Importer-Tests/GitlabApiMock.class.st @@ -1,72 +1,72 @@ Class { - #name : #GLHApiMock, + #name : #GitlabApiMock, #superclass : #Object, #category : #'GitLabHealth-Model-Importer-Tests' } { #category : #accessing } -GLHApiMock >> branches [ +GitlabApiMock >> branches [ ^ GitlabBranchesMock new . ] { #category : #accessing } -GLHApiMock >> commits [ +GitlabApiMock >> commits [ ^GitlabCommitsMock new. ] { #category : #accessing } -GLHApiMock >> groups [ +GitlabApiMock >> groups [ ^ GitlabGroupMock new. ] { #category : #accessing } -GLHApiMock >> jobs [ +GitlabApiMock >> jobs [ ^ GitlabJobsMock new ] { #category : #accessing } -GLHApiMock >> mergeRequests [ +GitlabApiMock >> mergeRequests [ ^ GitlabMergeRequestsMock new ] { #category : #accessing } -GLHApiMock >> notes [ +GitlabApiMock >> notes [ ^ GitlabNotesMock new. ] { #category : #accessing } -GLHApiMock >> output: aString [ +GitlabApiMock >> output: aString [ ^ self ] { #category : #accessing } -GLHApiMock >> pipelines [ +GitlabApiMock >> pipelines [ ^ GitlabPipelinesMock new ] { #category : #accessing } -GLHApiMock >> projects [ +GitlabApiMock >> projects [ ^ GitlabProjectsMock new . ] { #category : #accessing } -GLHApiMock >> releases [ +GitlabApiMock >> releases [ ^ GitlabReleasesMock new. ] { #category : #accessing } -GLHApiMock >> repositories [ +GitlabApiMock >> repositories [ ^ GitlabRepositoryMock new ] { #category : #accessing } -GLHApiMock >> tags [ +GitlabApiMock >> tags [ ^GitlabTagMock new ] { #category : #accessing } -GLHApiMock >> users [ +GitlabApiMock >> users [ ^GitlabUsersMock new ] diff --git a/src/GitLabHealth-Model-Importer-Tests/GitlabModelImporterTest.class.st b/src/GitLabHealth-Model-Importer-Tests/GitlabModelImporterTest.class.st index 4d077ec7..f1c68a81 100644 --- a/src/GitLabHealth-Model-Importer-Tests/GitlabModelImporterTest.class.st +++ b/src/GitLabHealth-Model-Importer-Tests/GitlabModelImporterTest.class.st @@ -187,7 +187,7 @@ GitlabModelImporterTest >> setUp [ importer := GitlabModelImporter new. model := GLHModel new. importer glhModel: model. - importer repoApi: GLHApiMock new + importer repoApi: GitlabApiMock new ] { #category : #'tests - repositories' } From cac95cf673db8337ef8bc22ea2bdf0d984c2bb88 Mon Sep 17 00:00:00 2001 From: HLAD Nicolas Date: Wed, 24 Sep 2025 15:38:12 +0200 Subject: [PATCH 33/52] adding tests to github --- .../GithubActionsMock.class.st | 38 +++ .../GithubApiMock.class.st | 20 ++ .../GithubBranchesMock.class.st | 30 ++ .../GithubCommitsMock.class.st | 196 ++++++++++++ .../GithubModelImporterTest.class.st | 29 +- .../GithubOrganizationsMock.class.st | 212 +++++++++++++ .../GithubModelImporter.class.st | 125 ++++++-- .../GitlabModelImporterTest.class.st | 74 +---- .../GitlabModelImporter.class.st | 12 - .../GitModelImporter.class.st | 10 +- .../TGitModelImporterTest.trait.st | 288 ++++++++++++++++++ 11 files changed, 921 insertions(+), 113 deletions(-) create mode 100644 src/GitHubHealth-Model-Importer-Tests/GithubActionsMock.class.st create mode 100644 src/GitHubHealth-Model-Importer-Tests/GithubBranchesMock.class.st create mode 100644 src/GitHubHealth-Model-Importer-Tests/GithubCommitsMock.class.st create mode 100644 src/GitHubHealth-Model-Importer-Tests/GithubOrganizationsMock.class.st create mode 100644 src/GitProjectHealth-Model-Importer/TGitModelImporterTest.trait.st diff --git a/src/GitHubHealth-Model-Importer-Tests/GithubActionsMock.class.st b/src/GitHubHealth-Model-Importer-Tests/GithubActionsMock.class.st new file mode 100644 index 00000000..cf36c519 --- /dev/null +++ b/src/GitHubHealth-Model-Importer-Tests/GithubActionsMock.class.st @@ -0,0 +1,38 @@ +Class { + #name : #GithubActionsMock, + #superclass : #Object, + #category : #'GitHubHealth-Model-Importer-Tests' +} + +{ #category : #'as yet unclassified' } +GithubActionsMock >> getLatestForRepo: aString ofOwner: aString2 [ + ^ '{ + "total_count": 2, + "workflows": [ + { + "id": 161335, + "node_id": "MDg6V29ya2Zsb3cxNjEzMzU=", + "name": "CI", + "path": ".github/workflows/blank.yaml", + "state": "active", + "created_at": "2020-01-08T23:48:37.000-08:00", + "updated_at": "2020-01-08T23:50:21.000-08:00", + "url": "https://api.github.com/repos/octo-org/octo-repo/actions/workflows/161335", + "html_url": "https://github.com/octo-org/octo-repo/blob/master/.github/workflows/161335", + "badge_url": "https://github.com/octo-org/octo-repo/workflows/CI/badge.svg" + }, + { + "id": 269289, + "node_id": "MDE4OldvcmtmbG93IFNlY29uZGFyeTI2OTI4OQ==", + "name": "Linter", + "path": ".github/workflows/linter.yaml", + "state": "active", + "created_at": "2020-01-08T23:48:37.000-08:00", + "updated_at": "2020-01-08T23:50:21.000-08:00", + "url": "https://api.github.com/repos/octo-org/octo-repo/actions/workflows/269289", + "html_url": "https://github.com/octo-org/octo-repo/blob/master/.github/workflows/269289", + "badge_url": "https://github.com/octo-org/octo-repo/workflows/Linter/badge.svg" + } + ] +}' +] diff --git a/src/GitHubHealth-Model-Importer-Tests/GithubApiMock.class.st b/src/GitHubHealth-Model-Importer-Tests/GithubApiMock.class.st index a63d05f0..da8fe637 100644 --- a/src/GitHubHealth-Model-Importer-Tests/GithubApiMock.class.st +++ b/src/GitHubHealth-Model-Importer-Tests/GithubApiMock.class.st @@ -4,6 +4,26 @@ Class { #category : #'GitHubHealth-Model-Importer-Tests' } +{ #category : #actions } +GithubApiMock >> actions [ + ^ GithubActionsMock new +] + +{ #category : #accessing } +GithubApiMock >> branches [ + ^ GithubBranchesMock new +] + +{ #category : #accessing } +GithubApiMock >> commits [ + ^ GithubCommitsMock new. +] + +{ #category : #organizations } +GithubApiMock >> organizations [ + ^ GithubOrganizationsMock new +] + { #category : #accessing } GithubApiMock >> output: aString [ ^ self diff --git a/src/GitHubHealth-Model-Importer-Tests/GithubBranchesMock.class.st b/src/GitHubHealth-Model-Importer-Tests/GithubBranchesMock.class.st new file mode 100644 index 00000000..18d72e94 --- /dev/null +++ b/src/GitHubHealth-Model-Importer-Tests/GithubBranchesMock.class.st @@ -0,0 +1,30 @@ +Class { + #name : #GithubBranchesMock, + #superclass : #Object, + #category : #'GitHubHealth-Model-Importer-Tests' +} + +{ #category : #'as yet unclassified' } +GithubBranchesMock >> getAllForRepo: aString ofOwner: aString2 [ + + ^ {'[ + { + "name": "master", + "commit": { + "sha": "c5b97d5ae6c19d5c5df71a34c7fbeeda2479ccbc", + "url": "https://api.github.com/repos/octocat/Hello-World/commits/c5b97d5ae6c19d5c5df71a34c7fbeeda2479ccbc" + }, + "protected": true, + "protection": { + "required_status_checks": { + "enforcement_level": "non_admins", + "contexts": [ + "ci-test", + "linter" + ] + } + }, + "protection_url": "https://api.github.com/repos/octocat/hello-world/branches/master/protection" + } +]'} +] diff --git a/src/GitHubHealth-Model-Importer-Tests/GithubCommitsMock.class.st b/src/GitHubHealth-Model-Importer-Tests/GithubCommitsMock.class.st new file mode 100644 index 00000000..f3ca3ccb --- /dev/null +++ b/src/GitHubHealth-Model-Importer-Tests/GithubCommitsMock.class.st @@ -0,0 +1,196 @@ +Class { + #name : #GithubCommitsMock, + #superclass : #Object, + #category : #'GitHubHealth-Model-Importer-Tests' +} + +{ #category : #api } +GithubCommitsMock >> get: anInteger inProject: anUndefinedObject [ + + ^ '{ + "url": "https://api.github.com/repos/octocat/Hello-World/commits/6dcb09b5b57875f334f61aebed695e2e4193db5e", + "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e", + "node_id": "MDY6Q29tbWl0NmRjYjA5YjViNTc4NzVmMzM0ZjYxYWViZWQ2OTVlMmU0MTkzZGI1ZQ==", + "html_url": "https://github.com/octocat/Hello-World/commit/6dcb09b5b57875f334f61aebed695e2e4193db5e", + "comments_url": "https://api.github.com/repos/octocat/Hello-World/commits/6dcb09b5b57875f334f61aebed695e2e4193db5e/comments", + "commit": { + "url": "https://api.github.com/repos/octocat/Hello-World/git/commits/6dcb09b5b57875f334f61aebed695e2e4193db5e", + "author": { + "name": "Monalisa Octocat", + "email": "mona@github.com", + "date": "2011-04-14T16:00:49Z" + }, + "committer": { + "name": "Monalisa Octocat", + "email": "mona@github.com", + "date": "2011-04-14T16:00:49Z" + }, + "message": "Fix all the bugs", + "tree": { + "url": "https://api.github.com/repos/octocat/Hello-World/tree/6dcb09b5b57875f334f61aebed695e2e4193db5e", + "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e" + }, + "comment_count": 0, + "verification": { + "verified": false, + "reason": "unsigned", + "signature": null, + "payload": null, + "verified_at": null + } + }, + "author": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "committer": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "parents": [ + { + "url": "https://api.github.com/repos/octocat/Hello-World/commits/6dcb09b5b57875f334f61aebed695e2e4193db5e", + "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e" + } + ], + "stats": { + "additions": 104, + "deletions": 4, + "total": 108 + }, + "files": [ + { + "filename": "file1.txt", + "additions": 10, + "deletions": 2, + "changes": 12, + "status": "modified", + "raw_url": "https://github.com/octocat/Hello-World/raw/7ca483543807a51b6079e54ac4cc392bc29ae284/file1.txt", + "blob_url": "https://github.com/octocat/Hello-World/blob/7ca483543807a51b6079e54ac4cc392bc29ae284/file1.txt", + "patch": "@@ -29,7 +29,7 @@\n....." + } + ] +}' +] + +{ #category : #'as yet unclassified' } +GithubCommitsMock >> getForRepo: aString ofOwner: aString2 withParms: aCollection [ + ^ self getLatestForRepo: nil ofOwner: nil +] + +{ #category : #'as yet unclassified' } +GithubCommitsMock >> getLatestForRepo: aString ofOwner: aString2 [ + ^ '[ + { + "url": "https://api.github.com/repos/octocat/Hello-World/commits/6dcb09b5b57875f334f61aebed695e2e4193db5e", + "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e", + "node_id": "MDY6Q29tbWl0NmRjYjA5YjViNTc4NzVmMzM0ZjYxYWViZWQ2OTVlMmU0MTkzZGI1ZQ==", + "html_url": "https://github.com/octocat/Hello-World/commit/6dcb09b5b57875f334f61aebed695e2e4193db5e", + "comments_url": "https://api.github.com/repos/octocat/Hello-World/commits/6dcb09b5b57875f334f61aebed695e2e4193db5e/comments", + "commit": { + "url": "https://api.github.com/repos/octocat/Hello-World/git/commits/6dcb09b5b57875f334f61aebed695e2e4193db5e", + "author": { + "name": "Monalisa Octocat", + "email": "support@github.com", + "date": "2011-04-14T16:00:49Z" + }, + "committer": { + "name": "Monalisa Octocat", + "email": "support@github.com", + "date": "2011-04-14T16:00:49Z" + }, + "message": "Fix all the bugs", + "tree": { + "url": "https://api.github.com/repos/octocat/Hello-World/tree/6dcb09b5b57875f334f61aebed695e2e4193db5e", + "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e" + }, + "comment_count": 0, + "verification": { + "verified": false, + "reason": "unsigned", + "signature": null, + "payload": null, + "verified_at": null + } + }, + "author": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "committer": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "parents": [ + { + "url": "https://api.github.com/repos/octocat/Hello-World/commits/6dcb09b5b57875f334f61aebed695e2e4193db5e", + "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e" + } + ] + } +]' +] diff --git a/src/GitHubHealth-Model-Importer-Tests/GithubModelImporterTest.class.st b/src/GitHubHealth-Model-Importer-Tests/GithubModelImporterTest.class.st index 01977560..e6bd2832 100644 --- a/src/GitHubHealth-Model-Importer-Tests/GithubModelImporterTest.class.st +++ b/src/GitHubHealth-Model-Importer-Tests/GithubModelImporterTest.class.st @@ -4,10 +4,8 @@ A GithubModelImporterTest is a test class for testing the behavior of GithubMode Class { #name : #GithubModelImporterTest, #superclass : #TestCase, - #instVars : [ - 'importer', - 'model' - ], + #traits : 'TGitModelImporterTest', + #classTraits : 'TGitModelImporterTest classTrait', #category : #'GitHubHealth-Model-Importer-Tests' } @@ -15,22 +13,19 @@ Class { GithubModelImporterTest >> setUp [ super setUp. - + "first set the local importer" importer := GithubModelImporter new. + importer repoApi: GithubApiMock new. + + "than set up the model in super" model := GLHModel new. importer glhModel: model. - importer repoApi: GithubApiMock new -] - -{ #category : #'tests - users' } -GithubModelImporterTest >> testImportUser [ - - | element | - element := importer importUser: 123. - - self assert: element isNotNil. - self assert: element class equals: GLHUser. - + + defaultProject := (GLHProject new + name: 'myProject'; + group: (GLHGroup new name: 'itsGroup'); + repository: GLHRepository new; + yourself). ] { #category : #'tests - parsing' } diff --git a/src/GitHubHealth-Model-Importer-Tests/GithubOrganizationsMock.class.st b/src/GitHubHealth-Model-Importer-Tests/GithubOrganizationsMock.class.st new file mode 100644 index 00000000..29cc722b --- /dev/null +++ b/src/GitHubHealth-Model-Importer-Tests/GithubOrganizationsMock.class.st @@ -0,0 +1,212 @@ +Class { + #name : #GithubOrganizationsMock, + #superclass : #Object, + #category : #'GitHubHealth-Model-Importer-Tests' +} + +{ #category : #api } +GithubOrganizationsMock >> get: anInteger [ + ^ '{ + "login": "github", + "id": 1, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjE=", + "url": "https://api.github.com/orgs/github", + "repos_url": "https://api.github.com/orgs/github/repos", + "events_url": "https://api.github.com/orgs/github/events", + "hooks_url": "https://api.github.com/orgs/github/hooks", + "issues_url": "https://api.github.com/orgs/github/issues", + "members_url": "https://api.github.com/orgs/github/members{/member}", + "public_members_url": "https://api.github.com/orgs/github/public_members{/member}", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "description": "A great organization", + "name": "github", + "company": "GitHub", + "blog": "https://github.com/blog", + "location": "San Francisco", + "email": "octocat@github.com", + "twitter_username": "github", + "is_verified": true, + "has_organization_projects": true, + "has_repository_projects": true, + "public_repos": 2, + "public_gists": 1, + "followers": 20, + "following": 0, + "html_url": "https://github.com/octocat", + "created_at": "2008-01-14T04:33:35Z", + "type": "Organization", + "total_private_repos": 100, + "owned_private_repos": 100, + "private_gists": 81, + "disk_usage": 10000, + "collaborators": 8, + "billing_email": "mona@github.com", + "plan": { + "name": "Medium", + "space": 400, + "private_repos": 20, + "filled_seats": 4, + "seats": 5 + }, + "default_repository_permission": "read", + "default_repository_branch": "main", + "members_can_create_repositories": true, + "two_factor_requirement_enabled": true, + "members_allowed_repository_creation_type": "all", + "members_can_create_public_repositories": false, + "members_can_create_private_repositories": false, + "members_can_create_internal_repositories": false, + "members_can_create_pages": true, + "members_can_create_public_pages": true, + "members_can_create_private_pages": true, + "members_can_delete_repositories": true, + "members_can_change_repo_visibility": true, + "members_can_invite_outside_collaborators": true, + "members_can_delete_issues": false, + "display_commenter_full_name_setting_enabled": false, + "readers_can_create_discussions": true, + "members_can_create_teams": true, + "members_can_view_dependency_insights": true, + "members_can_fork_private_repositories": false, + "web_commit_signoff_required": false, + "updated_at": "2014-03-03T18:58:10Z", + "deploy_keys_enabled_for_repositories": false, + "dependency_graph_enabled_for_new_repositories": false, + "dependabot_alerts_enabled_for_new_repositories": false, + "dependabot_security_updates_enabled_for_new_repositories": false, + "advanced_security_enabled_for_new_repositories": false, + "secret_scanning_enabled_for_new_repositories": false, + "secret_scanning_push_protection_enabled_for_new_repositories": false, + "secret_scanning_push_protection_custom_link": "https://github.com/octo-org/octo-repo/blob/main/im-blocked.md", + "secret_scanning_push_protection_custom_link_enabled": false +}' +] + +{ #category : #get } +GithubOrganizationsMock >> getRepositoriesOfOrganization: aString [ + ^ self getRepositoriesOfOrganization: nil perPage: nil page: nil +] + +{ #category : #get } +GithubOrganizationsMock >> getRepositoriesOfOrganization: aString perPage: anInteger page: anInteger3 [ + ^ '[ + { + "id": 1296269, + "node_id": "MDEwOlJlcG9zaXRvcnkxMjk2MjY5", + "name": "Hello-World", + "full_name": "octocat/Hello-World", + "owner": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/octocat/Hello-World", + "description": "This your first repo!", + "fork": false, + "url": "https://api.github.com/repos/octocat/Hello-World", + "archive_url": "https://api.github.com/repos/octocat/Hello-World/{archive_format}{/ref}", + "assignees_url": "https://api.github.com/repos/octocat/Hello-World/assignees{/user}", + "blobs_url": "https://api.github.com/repos/octocat/Hello-World/git/blobs{/sha}", + "branches_url": "https://api.github.com/repos/octocat/Hello-World/branches{/branch}", + "collaborators_url": "https://api.github.com/repos/octocat/Hello-World/collaborators{/collaborator}", + "comments_url": "https://api.github.com/repos/octocat/Hello-World/comments{/number}", + "commits_url": "https://api.github.com/repos/octocat/Hello-World/commits{/sha}", + "compare_url": "https://api.github.com/repos/octocat/Hello-World/compare/{base}...{head}", + "contents_url": "https://api.github.com/repos/octocat/Hello-World/contents/{+path}", + "contributors_url": "https://api.github.com/repos/octocat/Hello-World/contributors", + "deployments_url": "https://api.github.com/repos/octocat/Hello-World/deployments", + "downloads_url": "https://api.github.com/repos/octocat/Hello-World/downloads", + "events_url": "https://api.github.com/repos/octocat/Hello-World/events", + "forks_url": "https://api.github.com/repos/octocat/Hello-World/forks", + "git_commits_url": "https://api.github.com/repos/octocat/Hello-World/git/commits{/sha}", + "git_refs_url": "https://api.github.com/repos/octocat/Hello-World/git/refs{/sha}", + "git_tags_url": "https://api.github.com/repos/octocat/Hello-World/git/tags{/sha}", + "git_url": "git:github.com/octocat/Hello-World.git", + "issue_comment_url": "https://api.github.com/repos/octocat/Hello-World/issues/comments{/number}", + "issue_events_url": "https://api.github.com/repos/octocat/Hello-World/issues/events{/number}", + "issues_url": "https://api.github.com/repos/octocat/Hello-World/issues{/number}", + "keys_url": "https://api.github.com/repos/octocat/Hello-World/keys{/key_id}", + "labels_url": "https://api.github.com/repos/octocat/Hello-World/labels{/name}", + "languages_url": "https://api.github.com/repos/octocat/Hello-World/languages", + "merges_url": "https://api.github.com/repos/octocat/Hello-World/merges", + "milestones_url": "https://api.github.com/repos/octocat/Hello-World/milestones{/number}", + "notifications_url": "https://api.github.com/repos/octocat/Hello-World/notifications{?since,all,participating}", + "pulls_url": "https://api.github.com/repos/octocat/Hello-World/pulls{/number}", + "releases_url": "https://api.github.com/repos/octocat/Hello-World/releases{/id}", + "ssh_url": "git@github.com:octocat/Hello-World.git", + "stargazers_url": "https://api.github.com/repos/octocat/Hello-World/stargazers", + "statuses_url": "https://api.github.com/repos/octocat/Hello-World/statuses/{sha}", + "subscribers_url": "https://api.github.com/repos/octocat/Hello-World/subscribers", + "subscription_url": "https://api.github.com/repos/octocat/Hello-World/subscription", + "tags_url": "https://api.github.com/repos/octocat/Hello-World/tags", + "teams_url": "https://api.github.com/repos/octocat/Hello-World/teams", + "trees_url": "https://api.github.com/repos/octocat/Hello-World/git/trees{/sha}", + "clone_url": "https://github.com/octocat/Hello-World.git", + "mirror_url": "git:git.example.com/octocat/Hello-World", + "hooks_url": "https://api.github.com/repos/octocat/Hello-World/hooks", + "svn_url": "https://svn.github.com/octocat/Hello-World", + "homepage": "https://github.com", + "language": null, + "forks_count": 9, + "stargazers_count": 80, + "watchers_count": 80, + "size": 108, + "default_branch": "master", + "open_issues_count": 0, + "is_template": false, + "topics": [ + "octocat", + "atom", + "electron", + "api" + ], + "has_issues": true, + "has_projects": true, + "has_wiki": true, + "has_pages": false, + "has_downloads": true, + "has_discussions": false, + "archived": false, + "disabled": false, + "visibility": "public", + "pushed_at": "2011-01-26T19:06:43Z", + "created_at": "2011-01-26T19:01:12Z", + "updated_at": "2011-01-26T19:14:43Z", + "permissions": { + "admin": false, + "push": false, + "pull": true + }, + "security_and_analysis": { + "advanced_security": { + "status": "enabled" + }, + "secret_scanning": { + "status": "enabled" + }, + "secret_scanning_push_protection": { + "status": "disabled" + }, + "secret_scanning_non_provider_patterns": { + "status": "disabled" + } + } + } +]' +] diff --git a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st index aa3da507..f3c5e832 100644 --- a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st +++ b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st @@ -119,7 +119,7 @@ GithubModelImporter >> configureReaderForCommit: reader [ value at: #id ifPresent: [ :authorId | - glhCommit commitCreator: (self importUser: authorId) ] ] ]. + glhCommit cacheAt: #authorID put: ( value at: #id) ] ] ]. mapping mapProperty: #committer @@ -138,6 +138,16 @@ GithubModelImporter >> configureReaderForCommit: reader [ parents collect: [ :parent | parent at: #sha ] ] ] ] +{ #category : #'private - configure reader' } +GithubModelImporter >> configureReaderForGroup: reader [ + + super configureReaderForGroup: reader. + + reader + for: GLHGroup + do: [ :mapping | mapping mapInstVar: #web_url to: #html_url ] +] + { #category : #'private - configure reader' } GithubModelImporter >> configureReaderForMergeRequest: reader [ " reader mapInstVarsFor: GLHProject. " @@ -166,6 +176,20 @@ GithubModelImporter >> configureReaderForMergeRequest: reader [ ] +{ #category : #'private - configure reader' } +GithubModelImporter >> configureReaderForPipeline: reader [ + + super configureReaderForPipeline: reader. + + "reader for: GLHPipeline do: [ :mapping | + mapping + mapInstVar: #status to: #conclusion; + mapProperty: #run_started_at + getter: [ :object | #ignore ] + setter: [ :object :value | + object runDate: (DateAndTime fromString: value) ] ]" +] + { #category : #'private - configure reader' } GithubModelImporter >> configureReaderForProject: reader [ @@ -239,7 +263,9 @@ GithubModelImporter >> importBranchesOf: aGLHProject [ unless: self blockForBranchEquality. self withFiles ifTrue: [ - branches do: [ :branch | self importFilesOfBranch: branch ] ] + branches do: [ :branch | self importFilesOfBranch: branch ] ]. + + ^branches. ] { #category : #'import - commits' } @@ -406,6 +432,29 @@ GithubModelImporter >> importGroup: aGroupName [ ^ groupResult ] +{ #category : #'import - commits' } +GithubModelImporter >> importLatestCommitsOfProject: aGLHProject [ + "limited to the last 50 commits" + + | results parsedResults | + results := self repoApi commits + getLatestForRepo: aGLHProject name + ofOwner: aGLHProject group name. + parsedResults := self parseCommitsResult: results. + parsedResults := self glhModel + addAll: parsedResults + unless: self blockOnIdEquality. + + aGLHProject repository commits + addAll: parsedResults + unless: self blockOnIdEquality. + + self withCommitDiffs ifTrue: [ + parsedResults do: [ :commit | self importDiffOfCommit: commit ] ]. + + ^ parsedResults +] + { #category : #'import - merge-requests' } GithubModelImporter >> importLatestMergeRequestsOfProject: aGLHProject [ @@ -460,7 +509,7 @@ GithubModelImporter >> importProject: aProjectName ofGroup: aGroupName [ | result projectResult group | group := self ensureGroupNamed: aGroupName. - result := self repoApi organization: aGroupName repo: aProjectName. + result := self repoApi organizations getRepository: aProjectName ofOrganization: aGroupName . projectResult := self parseProjectResult: result. projectResult group: group. self glhModel add: projectResult. @@ -525,6 +574,55 @@ GithubModelImporter >> importUser: userID [ unless: [ :current :new | current id = new id ] ] +{ #category : #'import - users' } +GithubModelImporter >> importUserByUsername: anUsername [ + + | dicUsername resultUser | + dicUsername := ((self glhModel allWithType: GLHUser) collect: [ :user | + user username -> user ]) asSet asDictionary. + + dicUsername addAll: self userCatalogue collectUsernames. + + + resultUser := dicUsername + at: anUsername + ifAbsent: [ "thus we have to import this new user" + | userId searchResult | + ('Import user with username: ' + , anUsername printString) recordInfo. + + searchResult := self repoApi users getUsername: anUsername. + + (searchResult class = Dictionary and: [ + (searchResult at: #status) includesSubstring: + '404' ]) + ifTrue: [ "if the result is an 403 error we fake a new user" + self glhModel + add: (GLHUser new + username: anUsername; + name: anUsername; + yourself) + unless: [ :nu :ou | nu username = ou username ] ] + ifFalse: [ + searchResult + ifEmpty: [ "results can be empty thus we force a new user with the info we have " + self glhModel + add: (GLHUser new + username: anUsername; + name: anUsername; + yourself) + unless: [ :nu :ou | nu username = ou username ] ] + ifNotEmpty: [ "because we may already have the researched user, we look by ID in the model" + userId := searchResult first at: #id. + (self glhModel allWithType: GLHUser) + detect: [ :user | user id = userId ] + ifNone: [ self importUser: userId ] ] ] ]. + + self userCatalogue addUser: resultUser withName: anUsername. + + ^ resultUser +] + { #category : #initialization } GithubModelImporter >> initReader [ @@ -627,9 +725,8 @@ GithubModelImporter >> parseFileTreeResult: aResult [ GithubModelImporter >> parseGroupResult: aResult [ | reader | - reader := NeoJSONReader on: aResult readStream. - reader for: GLHGroup do: [ :mapping | - mapping mapInstVar: #web_url to: #html_url ]. + reader := generalReader on: aResult readStream. + ^ reader nextAs: GLHGroup ] @@ -663,24 +760,12 @@ GithubModelImporter >> parseMergeRequestsResult: response [ GithubModelImporter >> parsePipelinesResult: pipelineOverview [ | reader | - reader := NeoJSONReader on: pipelineOverview readStream. + reader := generalReader on: pipelineOverview readStream. reader for: GHAPIPipelineOverview do: [ :mapping | mapping mapInstVar: #total_count to: #total_count. - (mapping mapInstVar: #workflow_runs) valueSchema: #ArrayOfPipeline ]. - - reader - for: #ArrayOfPipeline - customDo: [ :customMappting | - customMappting listOfElementSchema: GLHPipeline ]. + (mapping mapInstVar: #workflow_runs to: #workflows) valueSchema: #ArrayOfPipeline ]. - reader for: GLHPipeline do: [ :mapping | - mapping - mapInstVar: #status to: #conclusion; - mapProperty: #run_started_at - getter: [ :object | #ignore ] - setter: [ :object :value | - object runDate: (DateAndTime fromString: value) ] ]. ^ reader nextAs: GHAPIPipelineOverview ] diff --git a/src/GitLabHealth-Model-Importer-Tests/GitlabModelImporterTest.class.st b/src/GitLabHealth-Model-Importer-Tests/GitlabModelImporterTest.class.st index f1c68a81..31ed9014 100644 --- a/src/GitLabHealth-Model-Importer-Tests/GitlabModelImporterTest.class.st +++ b/src/GitLabHealth-Model-Importer-Tests/GitlabModelImporterTest.class.st @@ -4,9 +4,9 @@ The test suite for `GLHModelImporter` but not using remote API Class { #name : #GitlabModelImporterTest, #superclass : #TestCase, + #traits : 'TGitModelImporterTest', + #classTraits : 'TGitModelImporterTest classTrait', #instVars : [ - 'importer', - 'model', 'diffs' ], #category : #'GitLabHealth-Model-Importer-Tests' @@ -184,10 +184,16 @@ GitlabModelImporterTest >> setUp [ super setUp. + "first set the local importer" importer := GitlabModelImporter new. + importer repoApi: GitlabApiMock new. + + "than set up the model in super" model := GLHModel new. importer glhModel: model. - importer repoApi: GitlabApiMock new + defaultProject := (GLHProject new + repository: GLHRepository new; + yourself). ] { #category : #'tests - repositories' } @@ -195,7 +201,7 @@ GitlabModelImporterTest >> testCompleteImportsOfRepository [ | element project | project := GLHProject new - name: 'testProject'; + name: 'testProject'; repository: GLHRepository new; yourself. element := importer completeImportsOfRepository: project repository. @@ -207,37 +213,7 @@ GitlabModelImporterTest >> testCompleteImportsOfRepository [ self assert: element project equals: project. self assert: element branches isNotNil. - self assert: element branches anyOne class equals: GLHBranch. - -] - -{ #category : #'tests - branches' } -GitlabModelImporterTest >> testImportBranchesOf [ - - | branches branch | - branches := importer importBranchesOf: (GLHProject new - repository: GLHRepository new; - yourself). - - self assert: branches isEmptyOrNil not. - - branch := branches first. - self assert: branch class equals: GLHBranch . - -] - -{ #category : #'tests - commits' } -GitlabModelImporterTest >> testImportCommitOfProject [ - - | commit | - commit := importer importCommit: 123 ofProject: (GLHProject new - repository: GLHRepository new; - yourself). - - self assert: commit isNotNil. - self assert: commit class equals: GLHCommit. - self assert: commit repository class equals: GLHRepository. - self assert: commit repository project class equals: GLHProject . + self assert: element branches anyOne class equals: GLHBranch ] { #category : #'tests - commits' } @@ -311,18 +287,6 @@ GitlabModelImporterTest >> testImportDiffOfMergeRequest [ self assert: (model allWithType: GLHDiff) size equals: 3 ] -{ #category : #'tests - groups' } -GitlabModelImporterTest >> testImportGroup [ - - | collection element | - collection := importer importGroup: 123. - - self assert: collection class equals: GLHGroup. - - element := collection projects first. - self assert: element class equals: GLHProject. -] - { #category : #'tests - jobs' } GitlabModelImporterTest >> testImportJobsOf [ @@ -340,22 +304,6 @@ GitlabModelImporterTest >> testImportJobsOf [ self assert: job name equals: 'teaspoon' ] -{ #category : #'tests - commits' } -GitlabModelImporterTest >> testImportLatestCommitsOfProject [ - - | commits commit| - commits := importer importLatestCommitsOfProject: (GLHProject new - repository: GLHRepository new; - yourself). - - self assert: commits isEmptyOrNil not . - - commit := commits first. - self assert: commit class equals: GLHCommit. - self assert: commit repository class equals: GLHRepository. - self assert: commit repository project class equals: GLHProject . -] - { #category : #'tests - merge-requests' } GitlabModelImporterTest >> testImportLatestMergeRequestsOfProject [ diff --git a/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st b/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st index 515eb44e..a6a7dfaf 100644 --- a/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st +++ b/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st @@ -934,18 +934,6 @@ GitlabModelImporter >> importContributedProjectsOfUser: aGLHUser [ ^ projects ] -{ #category : #'import - users' } -GitlabModelImporter >> importCreatorOfCommit: aCommit [ - - aCommit commitCreator ifNil: [ - aCommit commitCreator: - (self importUserByUsername: aCommit author_name) ]. - self userCatalogue - addUser: aCommit commitCreator - withProject: aCommit repository project id. - ^ aCommit commitCreator -] - { #category : #'import - commits' } GitlabModelImporter >> importDiffOfCommit: aCommit [ diff --git a/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st b/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st index b6de6f47..db6f247e 100644 --- a/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st +++ b/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st @@ -438,7 +438,14 @@ GitModelImporter >> importContributedProjectsOfUser: aGLHUser [ { #category : #'import - users' } GitModelImporter >> importCreatorOfCommit: aGLHCommit [ - self subclassResponsibility + + aGLHCommit commitCreator ifNil: [ + aGLHCommit commitCreator: + (self importUserByUsername: aGLHCommit author_name) ]. + self userCatalogue + addUser: aGLHCommit commitCreator + withProject: aGLHCommit repository project id. + ^ aGLHCommit commitCreator ] { #category : #'import - diffs' } @@ -485,6 +492,7 @@ GitModelImporter >> importJobsOf: aGLHPipeline [ { #category : #'import - commits' } GitModelImporter >> importLatestCommitsOfProject: aGLHProject [ "limited to the last 50 commits" + self subclassResponsibility ] diff --git a/src/GitProjectHealth-Model-Importer/TGitModelImporterTest.trait.st b/src/GitProjectHealth-Model-Importer/TGitModelImporterTest.trait.st new file mode 100644 index 00000000..8d180b91 --- /dev/null +++ b/src/GitProjectHealth-Model-Importer/TGitModelImporterTest.trait.st @@ -0,0 +1,288 @@ +Trait { + #name : #TGitModelImporterTest, + #instVars : [ + 'importer', + 'model', + 'defaultProject' + ], + #category : #'GitProjectHealth-Model-Importer' +} + +{ #category : #'accessing - method dictionary' } +TGitModelImporterTest classSide >> addAndClassifySelector: selector withMethod: compiledMethod inProtocol: aProtocol [ + "When a new methods is added, I add it to the localMethodDict and also propagate the changes to my users" + + self localMethodDict at: selector put: compiledMethod. + + super addAndClassifySelector: selector withMethod: compiledMethod inProtocol: aProtocol. + + TraitChange addSelector: selector on: self +] + +{ #category : #querying } +TGitModelImporterTest classSide >> allTraits [ + + ^ self traitComposition allTraits +] + +{ #category : #initialization } +TGitModelImporterTest classSide >> doRebuildMethodDictionary [ + + | selectors removedSelectors modified | + "During the creation of the class or after a change in the traitComposition, the whole method dictionary is calculated. + If I return true, my users should be updated""1. I recreate the local methodDict" + modified := false. + self methodDict valuesDo: [ :m | m traitSource ifNil: [ self localMethodDict at: m selector put: m ] ]. + + "2. I filter the selectors from the trait composition, rejecting the ones that are locally defined. + And then I install the methods in myself. The trait composition only install the method if it is needed." + selectors := self traitComposition selectors reject: [ :e | self localMethodDict includesKey: e ]. + selectors do: [ :e | modified := modified | (self traitComposition installSelector: e into: self replacing: false) ]. + + "3. I handle the methods that I have and they are no more in the traitComposition." + removedSelectors := self methodDict keys reject: [ :aSelector | (selectors includes: aSelector) or: [ self localMethodDict includesKey: aSelector ] ]. + modified := modified | removedSelectors isNotEmpty. + removedSelectors do: [ :aSelector | + self methodDict removeKey: aSelector. + self removeFromProtocols: aSelector ]. + + ^ modified +] + +{ #category : #testing } +TGitModelImporterTest classSide >> findOriginClassOf: aMethod [ + + "I return the myself or the trait that has the original implementation of a method. + If the method is an alias, the returned class includes the original aliased method" + + + (aMethod hasProperty: #traitSource) + ifTrue: [ ^ aMethod traitSource innerClass ]. + + (self includesLocalSelector: aMethod selector) + ifTrue: [ ^ self ]. + + ^ (self traitComposition traitDefining: aMethod selector ifNone: [ ^ self ]) innerClass +] + +{ #category : #testing } +TGitModelImporterTest classSide >> findOriginMethodOf: aMethod [ + + "I return the original method for a aMethod. + If this is a local method, the original method is itself. + If it cames from a trait composition I look for the method in the trait composition. + First I try with the trait stored in the traitSource. + If it is an aliased or conflicting method, the method is look up in the whole trait composition" + + + (self includesLocalSelector: aMethod selector) + ifTrue: [ ^ aMethod ]. + + (aMethod hasProperty: #traitSource) + ifTrue: [ |newSelector| + newSelector := self traitComposition originSelectorOf: aMethod selector. + ^ aMethod traitSource compiledMethodAt: newSelector ifAbsent: [aMethod] ]. + + ^ (self traitComposition traitDefining: aMethod selector ifNone: [ self ]) + compiledMethodAt: aMethod selector ifAbsent: [ ^ aMethod ] +] + +{ #category : #testing } +TGitModelImporterTest classSide >> hasTraitComposition [ + + ^ self traitComposition isEmpty not +] + +{ #category : #testing } +TGitModelImporterTest classSide >> includesLocalSelector: aSymbol [ + + ^ self isLocalSelector: aSymbol +] + +{ #category : #testing } +TGitModelImporterTest classSide >> includesTrait: aTrait [ + + + ^ self traitComposition includesTrait: aTrait +] + +{ #category : #testing } +TGitModelImporterTest classSide >> isAliasSelector: aSymbol [ + "Return true if the selector aSymbol is an alias defined + in my or in another composition somewhere deeper in + the tree of traits compositions." + + ^ self traitComposition isAliasSelector: aSymbol +] + +{ #category : #testing } +TGitModelImporterTest classSide >> isLocalAliasSelector: aSymbol [ + "Return true if the selector aSymbol is an alias defined + in my trait composition." + + ^ self traitComposition isLocalAliasSelector: aSymbol +] + +{ #category : #testing } +TGitModelImporterTest classSide >> isLocalSelector: aSelector [ + + ^ self localMethodDict includesKey: aSelector +] + +{ #category : #accessing } +TGitModelImporterTest classSide >> localMethodDict [ + "The local methodDict is in the metaclass. In this way I do not have to recompile the methods during the bootstrap when we don't have a compiler." + ^ self class baseLocalMethods +] + +{ #category : #accessing } +TGitModelImporterTest classSide >> localMethodDict: aMethodDictionary [ + ^ self class baseLocalMethods: aMethodDictionary +] + +{ #category : #accessing } +TGitModelImporterTest classSide >> localMethods [ + "returns the methods of classes excluding the ones of the traits that the class uses" + + ^ self localMethodDict values +] + +{ #category : #'accessing - method dictionary' } +TGitModelImporterTest classSide >> localSelectors [ + + ^ self localMethodDict keys +] + +{ #category : #categories } +TGitModelImporterTest classSide >> recategorizeSelector: selector from: oldProtocol to: newProtocol [ + "When a method is recategorized I have to classify the method, but also recategorize the aliases pointing to it" + + | originalProtocol | + "If it is nil is because it is a removal. It will removed when the method is removed." + newProtocol ifNil: [ ^ self ]. + + originalProtocol := (self protocolOfSelector: selector) ifNil: [ ^ self ]. + originalProtocol name = oldProtocol name ifTrue: [ self classify: selector under: newProtocol name ]. + + (self traitComposition reverseAlias: selector) do: [ :selectorAlias | + self recategorizeSelector: selectorAlias from: oldProtocol to: newProtocol. + self notifyOfRecategorizedSelector: selectorAlias from: oldProtocol to: newProtocol ] +] + +{ #category : #recompilation } +TGitModelImporterTest classSide >> recompile: selector from: oldClass [ + + super recompile: selector from: oldClass. + TraitChange addSelector: selector on: self +] + +{ #category : #'trait-composition' } +TGitModelImporterTest classSide >> removeFromComposition: aTrait [ + + self setTraitComposition: (self traitComposition copyWithoutTrait: aTrait asTraitComposition) +] + +{ #category : #removing } +TGitModelImporterTest classSide >> removeSelector: aSelector [ + + "When a selector is removed it should be notified to my users. + Check the class TraitChange for more details" + + super removeSelector: aSelector. + self localMethodDict removeKey: aSelector ifAbsent: [ ]. + + TraitChange removeSelector: aSelector on: self +] + +{ #category : #accessing } +TGitModelImporterTest classSide >> traitComposition [ + "My trait composition is in my class. So I do not need to recompile the methods when installing them during bootstrap" + ^ self class baseComposition +] + +{ #category : #accessing } +TGitModelImporterTest classSide >> traitComposition: aComposition [ + + aComposition asTraitComposition allTraits do: [ :aMaybeTrait | + aMaybeTrait isTrait ifFalse: [ + self error: 'All the members of the trait composition should be traits' ]]. + + self class baseComposition: aComposition +] + +{ #category : #accessing } +TGitModelImporterTest classSide >> traitCompositionString [ + ^ self traitComposition asString +] + +{ #category : #accessing } +TGitModelImporterTest classSide >> traits [ + + ^ self traitComposition traits +] + +{ #category : #accessing } +TGitModelImporterTest >> defaultProject [ + ^ defaultProject +] + +{ #category : #'tests - branches' } +TGitModelImporterTest >> testImportBranchesOf [ + + | collection element | + collection := importer importBranchesOf: self defaultProject. + + self assert: collection isCollection. + + element := collection first. + self assert: element class equals: GLHBranch +] + +{ #category : #'tests - commits' } +TGitModelImporterTest >> testImportCommitOfProject [ + + | commit | + commit := importer importCommit: 123 ofProject: self defaultProject. + + self assert: commit isNotNil. + self assert: commit class equals: GLHCommit. + self assert: commit repository class equals: GLHRepository. + self assert: commit repository project class equals: GLHProject +] + +{ #category : #'tests - groups' } +TGitModelImporterTest >> testImportGroup [ + + | collection element | + collection := importer importGroup: 123. + + self assert: collection class equals: GLHGroup. + + element := collection projects first. + self assert: element class equals: GLHProject. +] + +{ #category : #'tests - commits' } +TGitModelImporterTest >> testImportLatestCommitsOfProject [ + + | commits commit | + commits := importer importLatestCommitsOfProject: self defaultProject . + + self assert: commits isEmptyOrNil not. + + commit := commits first. + self assert: commit class equals: GLHCommit. + self assert: commit repository class equals: GLHRepository. + self assert: commit repository project class equals: GLHProject +] + +{ #category : #'tests - users' } +TGitModelImporterTest >> testImportUser [ + + | element | + element := importer importUser: 123. + + self assert: element isNotNil. + self assert: element class equals: GLHUser. + +] From 4860609457a4deccb5abf33247ded7650414672a Mon Sep 17 00:00:00 2001 From: HLAD Nicolas Date: Wed, 24 Sep 2025 16:09:46 +0200 Subject: [PATCH 34/52] fix tests --- .../GithubActionsMock.class.st | 248 ++++++++++++++++-- .../GithubModelImporterTest.class.st | 15 +- .../GithubModelImporter.class.st | 22 +- 3 files changed, 245 insertions(+), 40 deletions(-) diff --git a/src/GitHubHealth-Model-Importer-Tests/GithubActionsMock.class.st b/src/GitHubHealth-Model-Importer-Tests/GithubActionsMock.class.st index cf36c519..b4735bd3 100644 --- a/src/GitHubHealth-Model-Importer-Tests/GithubActionsMock.class.st +++ b/src/GitHubHealth-Model-Importer-Tests/GithubActionsMock.class.st @@ -5,33 +5,231 @@ Class { } { #category : #'as yet unclassified' } -GithubActionsMock >> getLatestForRepo: aString ofOwner: aString2 [ +GithubActionsMock >> getLatestForRepo: aString ofOwner: aString2 [ + "https://docs.github.com/en/rest/actions/workflow-runs?apiVersion=2022-11-28#list-workflow-runs-for-a-repository" + ^ '{ - "total_count": 2, - "workflows": [ - { - "id": 161335, - "node_id": "MDg6V29ya2Zsb3cxNjEzMzU=", - "name": "CI", - "path": ".github/workflows/blank.yaml", - "state": "active", - "created_at": "2020-01-08T23:48:37.000-08:00", - "updated_at": "2020-01-08T23:50:21.000-08:00", - "url": "https://api.github.com/repos/octo-org/octo-repo/actions/workflows/161335", - "html_url": "https://github.com/octo-org/octo-repo/blob/master/.github/workflows/161335", - "badge_url": "https://github.com/octo-org/octo-repo/workflows/CI/badge.svg" - }, + "total_count": 1, + "workflow_runs": [ { - "id": 269289, - "node_id": "MDE4OldvcmtmbG93IFNlY29uZGFyeTI2OTI4OQ==", - "name": "Linter", - "path": ".github/workflows/linter.yaml", - "state": "active", - "created_at": "2020-01-08T23:48:37.000-08:00", - "updated_at": "2020-01-08T23:50:21.000-08:00", - "url": "https://api.github.com/repos/octo-org/octo-repo/actions/workflows/269289", - "html_url": "https://github.com/octo-org/octo-repo/blob/master/.github/workflows/269289", - "badge_url": "https://github.com/octo-org/octo-repo/workflows/Linter/badge.svg" + "id": 30433642, + "name": "Build", + "node_id": "MDEyOldvcmtmbG93IFJ1bjI2OTI4OQ==", + "check_suite_id": 42, + "check_suite_node_id": "MDEwOkNoZWNrU3VpdGU0Mg==", + "head_branch": "master", + "head_sha": "acb5820ced9479c074f688cc328bf03f341a511d", + "path": ".github/workflows/build.yml@main", + "run_number": 562, + "event": "push", + "display_title": "Update README.md", + "status": "queued", + "conclusion": null, + "workflow_id": 159038, + "url": "https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642", + "html_url": "https://github.com/octo-org/octo-repo/actions/runs/30433642", + "pull_requests": [], + "created_at": "2020-01-22T19:33:08Z", + "updated_at": "2020-01-22T19:33:08Z", + "actor": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "run_attempt": 1, + "run_started_at": "2020-01-22T19:33:08Z", + "triggering_actor": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "jobs_url": "https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/jobs", + "logs_url": "https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/logs", + "check_suite_url": "https://api.github.com/repos/octo-org/octo-repo/check-suites/414944374", + "artifacts_url": "https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/artifacts", + "cancel_url": "https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/cancel", + "rerun_url": "https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/rerun", + "workflow_url": "https://api.github.com/repos/octo-org/octo-repo/actions/workflows/159038", + "head_commit": { + "id": "acb5820ced9479c074f688cc328bf03f341a511d", + "tree_id": "d23f6eedb1e1b9610bbc754ddb5197bfe7271223", + "message": "Create linter.yaml", + "timestamp": "2020-01-22T19:33:05Z", + "author": { + "name": "Octo Cat", + "email": "octocat@github.com" + }, + "committer": { + "name": "GitHub", + "email": "noreply@github.com" + } + }, + "repository": { + "id": 1296269, + "node_id": "MDEwOlJlcG9zaXRvcnkxMjk2MjY5", + "name": "Hello-World", + "full_name": "octocat/Hello-World", + "owner": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/octocat/Hello-World", + "description": "This your first repo!", + "fork": false, + "url": "https://api.github.com/repos/octocat/Hello-World", + "archive_url": "https://api.github.com/repos/octocat/Hello-World/{archive_format}{/ref}", + "assignees_url": "https://api.github.com/repos/octocat/Hello-World/assignees{/user}", + "blobs_url": "https://api.github.com/repos/octocat/Hello-World/git/blobs{/sha}", + "branches_url": "https://api.github.com/repos/octocat/Hello-World/branches{/branch}", + "collaborators_url": "https://api.github.com/repos/octocat/Hello-World/collaborators{/collaborator}", + "comments_url": "https://api.github.com/repos/octocat/Hello-World/comments{/number}", + "commits_url": "https://api.github.com/repos/octocat/Hello-World/commits{/sha}", + "compare_url": "https://api.github.com/repos/octocat/Hello-World/compare/{base}...{head}", + "contents_url": "https://api.github.com/repos/octocat/Hello-World/contents/{+path}", + "contributors_url": "https://api.github.com/repos/octocat/Hello-World/contributors", + "deployments_url": "https://api.github.com/repos/octocat/Hello-World/deployments", + "downloads_url": "https://api.github.com/repos/octocat/Hello-World/downloads", + "events_url": "https://api.github.com/repos/octocat/Hello-World/events", + "forks_url": "https://api.github.com/repos/octocat/Hello-World/forks", + "git_commits_url": "https://api.github.com/repos/octocat/Hello-World/git/commits{/sha}", + "git_refs_url": "https://api.github.com/repos/octocat/Hello-World/git/refs{/sha}", + "git_tags_url": "https://api.github.com/repos/octocat/Hello-World/git/tags{/sha}", + "git_url": "git:github.com/octocat/Hello-World.git", + "issue_comment_url": "https://api.github.com/repos/octocat/Hello-World/issues/comments{/number}", + "issue_events_url": "https://api.github.com/repos/octocat/Hello-World/issues/events{/number}", + "issues_url": "https://api.github.com/repos/octocat/Hello-World/issues{/number}", + "keys_url": "https://api.github.com/repos/octocat/Hello-World/keys{/key_id}", + "labels_url": "https://api.github.com/repos/octocat/Hello-World/labels{/name}", + "languages_url": "https://api.github.com/repos/octocat/Hello-World/languages", + "merges_url": "https://api.github.com/repos/octocat/Hello-World/merges", + "milestones_url": "https://api.github.com/repos/octocat/Hello-World/milestones{/number}", + "notifications_url": "https://api.github.com/repos/octocat/Hello-World/notifications{?since,all,participating}", + "pulls_url": "https://api.github.com/repos/octocat/Hello-World/pulls{/number}", + "releases_url": "https://api.github.com/repos/octocat/Hello-World/releases{/id}", + "ssh_url": "git@github.com:octocat/Hello-World.git", + "stargazers_url": "https://api.github.com/repos/octocat/Hello-World/stargazers", + "statuses_url": "https://api.github.com/repos/octocat/Hello-World/statuses/{sha}", + "subscribers_url": "https://api.github.com/repos/octocat/Hello-World/subscribers", + "subscription_url": "https://api.github.com/repos/octocat/Hello-World/subscription", + "tags_url": "https://api.github.com/repos/octocat/Hello-World/tags", + "teams_url": "https://api.github.com/repos/octocat/Hello-World/teams", + "trees_url": "https://api.github.com/repos/octocat/Hello-World/git/trees{/sha}", + "hooks_url": "http://api.github.com/repos/octocat/Hello-World/hooks" + }, + "head_repository": { + "id": 217723378, + "node_id": "MDEwOlJlcG9zaXRvcnkyMTc3MjMzNzg=", + "name": "octo-repo", + "full_name": "octo-org/octo-repo", + "private": true, + "owner": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "html_url": "https://github.com/octo-org/octo-repo", + "description": null, + "fork": false, + "url": "https://api.github.com/repos/octo-org/octo-repo", + "forks_url": "https://api.github.com/repos/octo-org/octo-repo/forks", + "keys_url": "https://api.github.com/repos/octo-org/octo-repo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/octo-org/octo-repo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/octo-org/octo-repo/teams", + "hooks_url": "https://api.github.com/repos/octo-org/octo-repo/hooks", + "issue_events_url": "https://api.github.com/repos/octo-org/octo-repo/issues/events{/number}", + "events_url": "https://api.github.com/repos/octo-org/octo-repo/events", + "assignees_url": "https://api.github.com/repos/octo-org/octo-repo/assignees{/user}", + "branches_url": "https://api.github.com/repos/octo-org/octo-repo/branches{/branch}", + "tags_url": "https://api.github.com/repos/octo-org/octo-repo/tags", + "blobs_url": "https://api.github.com/repos/octo-org/octo-repo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/octo-org/octo-repo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/octo-org/octo-repo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/octo-org/octo-repo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/octo-org/octo-repo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/octo-org/octo-repo/languages", + "stargazers_url": "https://api.github.com/repos/octo-org/octo-repo/stargazers", + "contributors_url": "https://api.github.com/repos/octo-org/octo-repo/contributors", + "subscribers_url": "https://api.github.com/repos/octo-org/octo-repo/subscribers", + "subscription_url": "https://api.github.com/repos/octo-org/octo-repo/subscription", + "commits_url": "https://api.github.com/repos/octo-org/octo-repo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/octo-org/octo-repo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/octo-org/octo-repo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/octo-org/octo-repo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/octo-org/octo-repo/contents/{+path}", + "compare_url": "https://api.github.com/repos/octo-org/octo-repo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/octo-org/octo-repo/merges", + "archive_url": "https://api.github.com/repos/octo-org/octo-repo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/octo-org/octo-repo/downloads", + "issues_url": "https://api.github.com/repos/octo-org/octo-repo/issues{/number}", + "pulls_url": "https://api.github.com/repos/octo-org/octo-repo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/octo-org/octo-repo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/octo-org/octo-repo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/octo-org/octo-repo/labels{/name}", + "releases_url": "https://api.github.com/repos/octo-org/octo-repo/releases{/id}", + "deployments_url": "https://api.github.com/repos/octo-org/octo-repo/deployments" + } } ] }' diff --git a/src/GitHubHealth-Model-Importer-Tests/GithubModelImporterTest.class.st b/src/GitHubHealth-Model-Importer-Tests/GithubModelImporterTest.class.st index e6bd2832..7a8e1472 100644 --- a/src/GitHubHealth-Model-Importer-Tests/GithubModelImporterTest.class.st +++ b/src/GitHubHealth-Model-Importer-Tests/GithubModelImporterTest.class.st @@ -257,21 +257,14 @@ GithubModelImporterTest >> testParseCommitsResultWithSomeNullValue [ GithubModelImporterTest >> testParsePipelinesResult [ | project | - project := importer parsePipelinesResult: '{ - "total_count": 1, - "workflow_runs": [ - { - "id": 7482814798, - "conclusion": "success", - "run_started_at": "2024-01-11T00:00:00" - }]}'. + project := importer parsePipelinesResult: (GithubActionsMock new getLatestForRepo: nil ofOwner: nil). self assert: project workflow_runs size equals: 1. - self assert: project workflow_runs anyOne status equals: 'success'. + self assert: project workflow_runs anyOne status equals: 'queued'. self - assert: project workflow_runs anyOne runDate - equals: (DateAndTime year: 2024 month: 01 day: 11) + assert: project workflow_runs anyOne runDate asDate printString + equals: (Date year: 2020 month: 01 day: 22) printString ] { #category : #'tests - parsing' } diff --git a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st index f3c5e832..618ca707 100644 --- a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st +++ b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st @@ -181,13 +181,27 @@ GithubModelImporter >> configureReaderForPipeline: reader [ super configureReaderForPipeline: reader. - "reader for: GLHPipeline do: [ :mapping | + reader for: GLHPipeline do: [ :mapping | + "mapping mapInstVar: #status to: #conclusion." + + mapping + mapProperty: #status + getter: [ :object | #ignore ] + setter: [ :object :value | + (object status isNil and: [value isNotNil]) ifTrue: [ object status: value ]. + ]. + + mapping + mapProperty: #conclusion + getter: [ :object | #ignore ] + setter: [ :object :value | + (object status isNil and: [value isNotNil]) ifTrue: [ object status: value ]. ]. + mapping - mapInstVar: #status to: #conclusion; mapProperty: #run_started_at getter: [ :object | #ignore ] setter: [ :object :value | - object runDate: (DateAndTime fromString: value) ] ]" + object runDate: (DateAndTime fromString: value) ] ] ] { #category : #'private - configure reader' } @@ -764,7 +778,7 @@ GithubModelImporter >> parsePipelinesResult: pipelineOverview [ reader for: GHAPIPipelineOverview do: [ :mapping | mapping mapInstVar: #total_count to: #total_count. - (mapping mapInstVar: #workflow_runs to: #workflows) valueSchema: #ArrayOfPipeline ]. + (mapping mapInstVar: #workflow_runs) valueSchema: #ArrayOfPipeline ]. ^ reader nextAs: GHAPIPipelineOverview From 1459c681089a07d280cf3b74f93743fe3427e060 Mon Sep 17 00:00:00 2001 From: HLAD Nicolas Date: Thu, 25 Sep 2025 14:25:33 +0200 Subject: [PATCH 35/52] fix commit diff load for github import --- .../GithubApiMock.class.st | 6 + .../GithubCommitsMock.class.st | 5 + .../GithubPullRequestsMock.class.st | 530 ++++++++++++++++++ .../GithubModelImporter.class.st | 88 ++- .../GitlabModelImporterTest.class.st | 33 -- .../GitModelImporter.class.st | 25 + .../TGitModelImporterTest.trait.st | 30 + 7 files changed, 661 insertions(+), 56 deletions(-) create mode 100644 src/GitHubHealth-Model-Importer-Tests/GithubPullRequestsMock.class.st diff --git a/src/GitHubHealth-Model-Importer-Tests/GithubApiMock.class.st b/src/GitHubHealth-Model-Importer-Tests/GithubApiMock.class.st index da8fe637..c50bba87 100644 --- a/src/GitHubHealth-Model-Importer-Tests/GithubApiMock.class.st +++ b/src/GitHubHealth-Model-Importer-Tests/GithubApiMock.class.st @@ -29,6 +29,12 @@ GithubApiMock >> output: aString [ ^ self ] +{ #category : #ressources } +GithubApiMock >> pullRequests [ + + ^ GithubPullRequestsMock new +] + { #category : #accessing } GithubApiMock >> users [ ^ GithubUsersMock new diff --git a/src/GitHubHealth-Model-Importer-Tests/GithubCommitsMock.class.st b/src/GitHubHealth-Model-Importer-Tests/GithubCommitsMock.class.st index f3ca3ccb..75d4d7b2 100644 --- a/src/GitHubHealth-Model-Importer-Tests/GithubCommitsMock.class.st +++ b/src/GitHubHealth-Model-Importer-Tests/GithubCommitsMock.class.st @@ -105,6 +105,11 @@ GithubCommitsMock >> get: anInteger inProject: anUndefinedObject [ }' ] +{ #category : #'as yet unclassified' } +GithubCommitsMock >> getCommit: aString ForRepo: aString2 ofOwner: aString3 [ + ^ self get: nil inProject: nil +] + { #category : #'as yet unclassified' } GithubCommitsMock >> getForRepo: aString ofOwner: aString2 withParms: aCollection [ ^ self getLatestForRepo: nil ofOwner: nil diff --git a/src/GitHubHealth-Model-Importer-Tests/GithubPullRequestsMock.class.st b/src/GitHubHealth-Model-Importer-Tests/GithubPullRequestsMock.class.st new file mode 100644 index 00000000..664d0523 --- /dev/null +++ b/src/GitHubHealth-Model-Importer-Tests/GithubPullRequestsMock.class.st @@ -0,0 +1,530 @@ +Class { + #name : #GithubPullRequestsMock, + #superclass : #Object, + #category : #'GitHubHealth-Model-Importer-Tests' +} + +{ #category : #'as yet unclassified' } +GithubPullRequestsMock >> getLatestForRepo: aString ofOwner: aString2 [ + ^ '[ + { + "url": "https://api.github.com/repos/octocat/Hello-World/pulls/1347", + "id": 1, + "node_id": "MDExOlB1bGxSZXF1ZXN0MQ==", + "html_url": "https://github.com/octocat/Hello-World/pull/1347", + "diff_url": "https://github.com/octocat/Hello-World/pull/1347.diff", + "patch_url": "https://github.com/octocat/Hello-World/pull/1347.patch", + "issue_url": "https://api.github.com/repos/octocat/Hello-World/issues/1347", + "commits_url": "https://api.github.com/repos/octocat/Hello-World/pulls/1347/commits", + "review_comments_url": "https://api.github.com/repos/octocat/Hello-World/pulls/1347/comments", + "review_comment_url": "https://api.github.com/repos/octocat/Hello-World/pulls/comments{/number}", + "comments_url": "https://api.github.com/repos/octocat/Hello-World/issues/1347/comments", + "statuses_url": "https://api.github.com/repos/octocat/Hello-World/statuses/6dcb09b5b57875f334f61aebed695e2e4193db5e", + "number": 1347, + "state": "open", + "locked": true, + "title": "Amazing new feature", + "user": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "body": "Please pull these awesome changes in!", + "labels": [ + { + "id": 208045946, + "node_id": "MDU6TGFiZWwyMDgwNDU5NDY=", + "url": "https://api.github.com/repos/octocat/Hello-World/labels/bug", + "name": "bug", + "description": "Something isn''t working", + "color": "f29513", + "default": true + } + ], + "milestone": { + "url": "https://api.github.com/repos/octocat/Hello-World/milestones/1", + "html_url": "https://github.com/octocat/Hello-World/milestones/v1.0", + "labels_url": "https://api.github.com/repos/octocat/Hello-World/milestones/1/labels", + "id": 1002604, + "node_id": "MDk6TWlsZXN0b25lMTAwMjYwNA==", + "number": 1, + "state": "open", + "title": "v1.0", + "description": "Tracking milestone for version 1.0", + "creator": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "open_issues": 4, + "closed_issues": 8, + "created_at": "2011-04-10T20:09:31Z", + "updated_at": "2014-03-03T18:58:10Z", + "closed_at": "2013-02-12T13:22:01Z", + "due_on": "2012-10-09T23:39:01Z" + }, + "active_lock_reason": "too heated", + "created_at": "2011-01-26T19:01:12Z", + "updated_at": "2011-01-26T19:01:12Z", + "closed_at": "2011-01-26T19:01:12Z", + "merged_at": "2011-01-26T19:01:12Z", + "merge_commit_sha": "e5bd3914e2e596debea16f433f57875b5b90bcd6", + "assignee": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "assignees": [ + { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + { + "login": "hubot", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/hubot_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/hubot", + "html_url": "https://github.com/hubot", + "followers_url": "https://api.github.com/users/hubot/followers", + "following_url": "https://api.github.com/users/hubot/following{/other_user}", + "gists_url": "https://api.github.com/users/hubot/gists{/gist_id}", + "starred_url": "https://api.github.com/users/hubot/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/hubot/subscriptions", + "organizations_url": "https://api.github.com/users/hubot/orgs", + "repos_url": "https://api.github.com/users/hubot/repos", + "events_url": "https://api.github.com/users/hubot/events{/privacy}", + "received_events_url": "https://api.github.com/users/hubot/received_events", + "type": "User", + "site_admin": true + } + ], + "requested_reviewers": [ + { + "login": "other_user", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/other_user_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/other_user", + "html_url": "https://github.com/other_user", + "followers_url": "https://api.github.com/users/other_user/followers", + "following_url": "https://api.github.com/users/other_user/following{/other_user}", + "gists_url": "https://api.github.com/users/other_user/gists{/gist_id}", + "starred_url": "https://api.github.com/users/other_user/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/other_user/subscriptions", + "organizations_url": "https://api.github.com/users/other_user/orgs", + "repos_url": "https://api.github.com/users/other_user/repos", + "events_url": "https://api.github.com/users/other_user/events{/privacy}", + "received_events_url": "https://api.github.com/users/other_user/received_events", + "type": "User", + "site_admin": false + } + ], + "requested_teams": [ + { + "id": 1, + "node_id": "MDQ6VGVhbTE=", + "url": "https://api.github.com/teams/1", + "html_url": "https://github.com/orgs/github/teams/justice-league", + "name": "Justice League", + "slug": "justice-league", + "description": "A great team.", + "privacy": "closed", + "permission": "admin", + "notification_setting": "notifications_enabled", + "members_url": "https://api.github.com/teams/1/members{/member}", + "repositories_url": "https://api.github.com/teams/1/repos", + "parent": null + } + ], + "head": { + "label": "octocat:new-topic", + "ref": "new-topic", + "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e", + "user": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "repo": { + "id": 1296269, + "node_id": "MDEwOlJlcG9zaXRvcnkxMjk2MjY5", + "name": "Hello-World", + "full_name": "octocat/Hello-World", + "owner": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/octocat/Hello-World", + "description": "This your first repo!", + "fork": false, + "url": "https://api.github.com/repos/octocat/Hello-World", + "archive_url": "https://api.github.com/repos/octocat/Hello-World/{archive_format}{/ref}", + "assignees_url": "https://api.github.com/repos/octocat/Hello-World/assignees{/user}", + "blobs_url": "https://api.github.com/repos/octocat/Hello-World/git/blobs{/sha}", + "branches_url": "https://api.github.com/repos/octocat/Hello-World/branches{/branch}", + "collaborators_url": "https://api.github.com/repos/octocat/Hello-World/collaborators{/collaborator}", + "comments_url": "https://api.github.com/repos/octocat/Hello-World/comments{/number}", + "commits_url": "https://api.github.com/repos/octocat/Hello-World/commits{/sha}", + "compare_url": "https://api.github.com/repos/octocat/Hello-World/compare/{base}...{head}", + "contents_url": "https://api.github.com/repos/octocat/Hello-World/contents/{+path}", + "contributors_url": "https://api.github.com/repos/octocat/Hello-World/contributors", + "deployments_url": "https://api.github.com/repos/octocat/Hello-World/deployments", + "downloads_url": "https://api.github.com/repos/octocat/Hello-World/downloads", + "events_url": "https://api.github.com/repos/octocat/Hello-World/events", + "forks_url": "https://api.github.com/repos/octocat/Hello-World/forks", + "git_commits_url": "https://api.github.com/repos/octocat/Hello-World/git/commits{/sha}", + "git_refs_url": "https://api.github.com/repos/octocat/Hello-World/git/refs{/sha}", + "git_tags_url": "https://api.github.com/repos/octocat/Hello-World/git/tags{/sha}", + "git_url": "git:github.com/octocat/Hello-World.git", + "issue_comment_url": "https://api.github.com/repos/octocat/Hello-World/issues/comments{/number}", + "issue_events_url": "https://api.github.com/repos/octocat/Hello-World/issues/events{/number}", + "issues_url": "https://api.github.com/repos/octocat/Hello-World/issues{/number}", + "keys_url": "https://api.github.com/repos/octocat/Hello-World/keys{/key_id}", + "labels_url": "https://api.github.com/repos/octocat/Hello-World/labels{/name}", + "languages_url": "https://api.github.com/repos/octocat/Hello-World/languages", + "merges_url": "https://api.github.com/repos/octocat/Hello-World/merges", + "milestones_url": "https://api.github.com/repos/octocat/Hello-World/milestones{/number}", + "notifications_url": "https://api.github.com/repos/octocat/Hello-World/notifications{?since,all,participating}", + "pulls_url": "https://api.github.com/repos/octocat/Hello-World/pulls{/number}", + "releases_url": "https://api.github.com/repos/octocat/Hello-World/releases{/id}", + "ssh_url": "git@github.com:octocat/Hello-World.git", + "stargazers_url": "https://api.github.com/repos/octocat/Hello-World/stargazers", + "statuses_url": "https://api.github.com/repos/octocat/Hello-World/statuses/{sha}", + "subscribers_url": "https://api.github.com/repos/octocat/Hello-World/subscribers", + "subscription_url": "https://api.github.com/repos/octocat/Hello-World/subscription", + "tags_url": "https://api.github.com/repos/octocat/Hello-World/tags", + "teams_url": "https://api.github.com/repos/octocat/Hello-World/teams", + "trees_url": "https://api.github.com/repos/octocat/Hello-World/git/trees{/sha}", + "clone_url": "https://github.com/octocat/Hello-World.git", + "mirror_url": "git:git.example.com/octocat/Hello-World", + "hooks_url": "https://api.github.com/repos/octocat/Hello-World/hooks", + "svn_url": "https://svn.github.com/octocat/Hello-World", + "homepage": "https://github.com", + "language": null, + "forks_count": 9, + "stargazers_count": 80, + "watchers_count": 80, + "size": 108, + "default_branch": "master", + "open_issues_count": 0, + "is_template": true, + "topics": [ + "octocat", + "atom", + "electron", + "api" + ], + "has_issues": true, + "has_projects": true, + "has_wiki": true, + "has_pages": false, + "has_downloads": true, + "archived": false, + "disabled": false, + "visibility": "public", + "pushed_at": "2011-01-26T19:06:43Z", + "created_at": "2011-01-26T19:01:12Z", + "updated_at": "2011-01-26T19:14:43Z", + "permissions": { + "admin": false, + "push": false, + "pull": true + }, + "allow_rebase_merge": true, + "template_repository": null, + "temp_clone_token": "ABTLWHOULUVAXGTRYU7OC2876QJ2O", + "allow_squash_merge": true, + "allow_auto_merge": false, + "delete_branch_on_merge": true, + "allow_merge_commit": true, + "subscribers_count": 42, + "network_count": 0, + "license": { + "key": "mit", + "name": "MIT License", + "url": "https://api.github.com/licenses/mit", + "spdx_id": "MIT", + "node_id": "MDc6TGljZW5zZW1pdA==", + "html_url": "https://github.com/licenses/mit" + }, + "forks": 1, + "open_issues": 1, + "watchers": 1 + } + }, + "base": { + "label": "octocat:master", + "ref": "master", + "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e", + "user": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "repo": { + "id": 1296269, + "node_id": "MDEwOlJlcG9zaXRvcnkxMjk2MjY5", + "name": "Hello-World", + "full_name": "octocat/Hello-World", + "owner": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/octocat/Hello-World", + "description": "This your first repo!", + "fork": false, + "url": "https://api.github.com/repos/octocat/Hello-World", + "archive_url": "https://api.github.com/repos/octocat/Hello-World/{archive_format}{/ref}", + "assignees_url": "https://api.github.com/repos/octocat/Hello-World/assignees{/user}", + "blobs_url": "https://api.github.com/repos/octocat/Hello-World/git/blobs{/sha}", + "branches_url": "https://api.github.com/repos/octocat/Hello-World/branches{/branch}", + "collaborators_url": "https://api.github.com/repos/octocat/Hello-World/collaborators{/collaborator}", + "comments_url": "https://api.github.com/repos/octocat/Hello-World/comments{/number}", + "commits_url": "https://api.github.com/repos/octocat/Hello-World/commits{/sha}", + "compare_url": "https://api.github.com/repos/octocat/Hello-World/compare/{base}...{head}", + "contents_url": "https://api.github.com/repos/octocat/Hello-World/contents/{+path}", + "contributors_url": "https://api.github.com/repos/octocat/Hello-World/contributors", + "deployments_url": "https://api.github.com/repos/octocat/Hello-World/deployments", + "downloads_url": "https://api.github.com/repos/octocat/Hello-World/downloads", + "events_url": "https://api.github.com/repos/octocat/Hello-World/events", + "forks_url": "https://api.github.com/repos/octocat/Hello-World/forks", + "git_commits_url": "https://api.github.com/repos/octocat/Hello-World/git/commits{/sha}", + "git_refs_url": "https://api.github.com/repos/octocat/Hello-World/git/refs{/sha}", + "git_tags_url": "https://api.github.com/repos/octocat/Hello-World/git/tags{/sha}", + "git_url": "git:github.com/octocat/Hello-World.git", + "issue_comment_url": "https://api.github.com/repos/octocat/Hello-World/issues/comments{/number}", + "issue_events_url": "https://api.github.com/repos/octocat/Hello-World/issues/events{/number}", + "issues_url": "https://api.github.com/repos/octocat/Hello-World/issues{/number}", + "keys_url": "https://api.github.com/repos/octocat/Hello-World/keys{/key_id}", + "labels_url": "https://api.github.com/repos/octocat/Hello-World/labels{/name}", + "languages_url": "https://api.github.com/repos/octocat/Hello-World/languages", + "merges_url": "https://api.github.com/repos/octocat/Hello-World/merges", + "milestones_url": "https://api.github.com/repos/octocat/Hello-World/milestones{/number}", + "notifications_url": "https://api.github.com/repos/octocat/Hello-World/notifications{?since,all,participating}", + "pulls_url": "https://api.github.com/repos/octocat/Hello-World/pulls{/number}", + "releases_url": "https://api.github.com/repos/octocat/Hello-World/releases{/id}", + "ssh_url": "git@github.com:octocat/Hello-World.git", + "stargazers_url": "https://api.github.com/repos/octocat/Hello-World/stargazers", + "statuses_url": "https://api.github.com/repos/octocat/Hello-World/statuses/{sha}", + "subscribers_url": "https://api.github.com/repos/octocat/Hello-World/subscribers", + "subscription_url": "https://api.github.com/repos/octocat/Hello-World/subscription", + "tags_url": "https://api.github.com/repos/octocat/Hello-World/tags", + "teams_url": "https://api.github.com/repos/octocat/Hello-World/teams", + "trees_url": "https://api.github.com/repos/octocat/Hello-World/git/trees{/sha}", + "clone_url": "https://github.com/octocat/Hello-World.git", + "mirror_url": "git:git.example.com/octocat/Hello-World", + "hooks_url": "https://api.github.com/repos/octocat/Hello-World/hooks", + "svn_url": "https://svn.github.com/octocat/Hello-World", + "homepage": "https://github.com", + "language": null, + "forks_count": 9, + "stargazers_count": 80, + "watchers_count": 80, + "size": 108, + "default_branch": "master", + "open_issues_count": 0, + "is_template": true, + "topics": [ + "octocat", + "atom", + "electron", + "api" + ], + "has_issues": true, + "has_projects": true, + "has_wiki": true, + "has_pages": false, + "has_downloads": true, + "archived": false, + "disabled": false, + "visibility": "public", + "pushed_at": "2011-01-26T19:06:43Z", + "created_at": "2011-01-26T19:01:12Z", + "updated_at": "2011-01-26T19:14:43Z", + "permissions": { + "admin": false, + "push": false, + "pull": true + }, + "allow_rebase_merge": true, + "template_repository": null, + "temp_clone_token": "ABTLWHOULUVAXGTRYU7OC2876QJ2O", + "allow_squash_merge": true, + "allow_auto_merge": false, + "delete_branch_on_merge": true, + "allow_merge_commit": true, + "subscribers_count": 42, + "network_count": 0, + "license": { + "key": "mit", + "name": "MIT License", + "url": "https://api.github.com/licenses/mit", + "spdx_id": "MIT", + "node_id": "MDc6TGljZW5zZW1pdA==", + "html_url": "https://github.com/licenses/mit" + }, + "forks": 1, + "open_issues": 1, + "watchers": 1 + } + }, + "_links": { + "self": { + "href": "https://api.github.com/repos/octocat/Hello-World/pulls/1347" + }, + "html": { + "href": "https://github.com/octocat/Hello-World/pull/1347" + }, + "issue": { + "href": "https://api.github.com/repos/octocat/Hello-World/issues/1347" + }, + "comments": { + "href": "https://api.github.com/repos/octocat/Hello-World/issues/1347/comments" + }, + "review_comments": { + "href": "https://api.github.com/repos/octocat/Hello-World/pulls/1347/comments" + }, + "review_comment": { + "href": "https://api.github.com/repos/octocat/Hello-World/pulls/comments{/number}" + }, + "commits": { + "href": "https://api.github.com/repos/octocat/Hello-World/pulls/1347/commits" + }, + "statuses": { + "href": "https://api.github.com/repos/octocat/Hello-World/statuses/6dcb09b5b57875f334f61aebed695e2e4193db5e" + } + }, + "author_association": "OWNER", + "auto_merge": null, + "draft": false + } +]' +] diff --git a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st index 618ca707..c0744ab0 100644 --- a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st +++ b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st @@ -119,7 +119,7 @@ GithubModelImporter >> configureReaderForCommit: reader [ value at: #id ifPresent: [ :authorId | - glhCommit cacheAt: #authorID put: ( value at: #id) ] ] ]. + glhCommit cacheAt: #authorID put: (value at: #id) ] ] ]. mapping mapProperty: #committer @@ -128,7 +128,11 @@ GithubModelImporter >> configureReaderForCommit: reader [ value ifNotNil: [ glhCommit committer_name: (value at: #login) ] ]. (mapping mapInstVar: #parent_ids to: #parents) valueSchema: - #ArrayOfId ]. + #ArrayOfId. + + (mapping mapInstVar: #diffs to: #files) valueSchema: #ArrayOfDiff. + + ]. reader for: DateAndTime customDo: [ :mapping | mapping decoder: [ :string | DateAndTime fromString: string ] ]. @@ -138,6 +142,17 @@ GithubModelImporter >> configureReaderForCommit: reader [ parents collect: [ :parent | parent at: #sha ] ] ] ] +{ #category : #'private - configure reader' } +GithubModelImporter >> configureReaderForDiff: reader [ + + super configureReaderForDiff: reader. + + reader for: GLHDiff do: [ :mapping | + mapping mapInstVar: #new_path to: #filename. + mapping mapInstVar: #old_path to: #filename. + mapping mapInstVar: #diffString to: #patch. ] +] + { #category : #'private - configure reader' } GithubModelImporter >> configureReaderForGroup: reader [ @@ -370,25 +385,36 @@ GithubModelImporter >> importCreatorOfCommit: aGLHCommit [ ^ creator ] -{ #category : #'import - commits' } +{ #category : #'import - diffs' } GithubModelImporter >> importDiffOfCommit: aGLHCommit [ - | result diffsResult | + | result diffs | aGLHCommit diffs ifNotEmpty: [ 'Diff already importer: ' , aGLHCommit short_id printString recordInfo. ^ aGLHCommit diffs ]. ('Import diff of commit: ' , aGLHCommit short_id printString) recordInfo. - result := self repoApi - commit: aGLHCommit id - ofOrganisation: aGLHCommit repository project group name - ofProject: aGLHCommit repository project name. - diffsResult := self parseDiffresult: result. + + result := self repoApi commits + getCommit: aGLHCommit id + ForRepo: aGLHCommit repository project name + ofOwner: aGLHCommit repository project group name. + + diffs := (self parseCommitResult: result) diffs. + + diffs do: [ :diff | + self parseDiffString: diff. + ]. + + diffs := aGLHCommit diffs + addAll: diffs + unless: self blockForDiffRangeEquality. + diffs := glhModel + addAll: diffs + unless: self blockForDiffRangeEquality. ^ aGLHCommit diffs - addAll: diffsResult - unless: self blockForDiffEquality ] { #category : #'import - files' } @@ -455,6 +481,8 @@ GithubModelImporter >> importLatestCommitsOfProject: aGLHProject [ getLatestForRepo: aGLHProject name ofOwner: aGLHProject group name. parsedResults := self parseCommitsResult: results. + + parsedResults := self glhModel addAll: parsedResults unless: self blockOnIdEquality. @@ -464,7 +492,10 @@ GithubModelImporter >> importLatestCommitsOfProject: aGLHProject [ unless: self blockOnIdEquality. self withCommitDiffs ifTrue: [ - parsedResults do: [ :commit | self importDiffOfCommit: commit ] ]. + parsedResults do: [ :commit | + self importDiffOfCommit: commit. + + ] ]. ^ parsedResults ] @@ -492,16 +523,28 @@ GithubModelImporter >> importLatestPullRequestsOfProject: aGLHProject [ ] { #category : #'import - merge-requests' } -GithubModelImporter >> importMergeRequestsOfProject: aProject [ - |response mergeRequests| - response := self repoApi - mergeRequestsOfRepo: aProject group name - ofProject: aProject name. - mergeRequests := self parseMergeRequestsResult: response. +GithubModelImporter >> importMergeRequestsOfProject: aGLHProject [ + + | response mergeRequests | + response := self repoApi pullRequests + getLatestForRepo: aGLHProject name + ofOwner: aGLHProject group name. + mergeRequests := self parseMergeRequestsResult: response. + + mergeRequests := aGLHProject mergeRequests + addAll: mergeRequests + unless: self blockOnIdEquality. + + "gets it related commits" + aGLHProject mergeRequests do: [ :mr | + self importMergeRequestMergeCommits: mr ]. + + + self withCommitDiffs ifTrue: [ + aGLHProject mergeRequests do: [ :mr | + self importDiffOfMergeRequest: mr ] ]. - mergeRequests := aProject mergeRequests addAll:mergeRequests unless: self blockOnIdEquality. ^ mergeRequests - ] { #category : #'import - pipelines' } @@ -649,9 +692,8 @@ GithubModelImporter >> initialize [ super initialize. self repoApi: GithubApi new. self repoApi output: 'json'. - self withCommitDiffs: false. - withFiles := false. - + self withCommitDiffs: true. + withFiles := false ] { #category : #parsing } diff --git a/src/GitLabHealth-Model-Importer-Tests/GitlabModelImporterTest.class.st b/src/GitLabHealth-Model-Importer-Tests/GitlabModelImporterTest.class.st index 31ed9014..2fcb6f89 100644 --- a/src/GitLabHealth-Model-Importer-Tests/GitlabModelImporterTest.class.st +++ b/src/GitLabHealth-Model-Importer-Tests/GitlabModelImporterTest.class.st @@ -304,21 +304,6 @@ GitlabModelImporterTest >> testImportJobsOf [ self assert: job name equals: 'teaspoon' ] -{ #category : #'tests - merge-requests' } -GitlabModelImporterTest >> testImportLatestMergeRequestsOfProject [ - - | collection element | - collection := importer importLatestMergeRequestsOfProject: - (GLHProject new - repository: GLHRepository new; - yourself). - - self assert: collection isCollection. - element := collection first. - self assert: element class equals: GLHMergeRequest. - self assert: element project class equals: GLHProject. -] - { #category : #'tests - pipelines' } GitlabModelImporterTest >> testImportLatestPipelinesOfProject [ @@ -351,24 +336,6 @@ GitlabModelImporterTest >> testImportLatestReleaseOfProject [ self assert: element project isNotNil ] -{ #category : #'tests - merge-requests' } -GitlabModelImporterTest >> testImportMergeRequestsOfProject [ - - | collection element | - collection := importer importMergeRequestsOfProject: (GLHProject new - repository: GLHRepository new; - yourself). - - self assert: collection isCollection. - element := collection first. - self assert: element class equals: GLHMergeRequest. - self assert: element project class equals: GLHProject. - self assert: element diffs isCollection. - self assert: element diffs first class equals: GLHDiff. - self assert: element mergeRequestCommit class equals: GLHCommit . - -] - { #category : #'tests - notes' } GitlabModelImporterTest >> testImportNotesOfMergeRequest [ diff --git a/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st b/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st index db6f247e..7721da29 100644 --- a/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st +++ b/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st @@ -518,6 +518,31 @@ GitModelImporter >> importMergeRequestCommits: mergeRequest [ { #category : #'import - merge-requests' } GitModelImporter >> importMergeRequestMergeCommits: aGLHMergeRequest [ + | foundCommits | + foundCommits := OrderedCollection new. + + ('Import commit sha of MR: ' , aGLHMergeRequest iid printString) + recordInfo. + "the founds commits are added to the model during their respective import" + aGLHMergeRequest mergeRequestCommit: ((self importCommit: aGLHMergeRequest sha ofProject: aGLHMergeRequest project + ) ifNotNil: [ :commit | + foundCommits add: commit ]). + + ('Import commit merge_commit_sha of MR: ' + , aGLHMergeRequest iid printString) recordInfo. + aGLHMergeRequest mergedCommit: ((self + importCommit: aGLHMergeRequest merge_commit_sha ofProject: aGLHMergeRequest project ) ifNotNil: [ :commit | + foundCommits add: commit ]). + + ('Import commit squash_commit_sha of MR: ' + , aGLHMergeRequest iid printString) recordInfo. + aGLHMergeRequest squashCommit: ((self + importCommit: aGLHMergeRequest squash_commit_sha ofProject: aGLHMergeRequest project) ifNotNil: [ :commit | + foundCommits add: commit ]). + + + self chainsCommitsFrom: foundCommits. + ^ foundCommits ] { #category : #'import - merge-requests' } diff --git a/src/GitProjectHealth-Model-Importer/TGitModelImporterTest.trait.st b/src/GitProjectHealth-Model-Importer/TGitModelImporterTest.trait.st index 8d180b91..cf033c2b 100644 --- a/src/GitProjectHealth-Model-Importer/TGitModelImporterTest.trait.st +++ b/src/GitProjectHealth-Model-Importer/TGitModelImporterTest.trait.st @@ -276,6 +276,36 @@ TGitModelImporterTest >> testImportLatestCommitsOfProject [ self assert: commit repository project class equals: GLHProject ] +{ #category : #'tests - merge-requests' } +TGitModelImporterTest >> testImportLatestMergeRequestsOfProject [ + + | collection element | + collection := importer importLatestMergeRequestsOfProject: + self defaultProject. + + self assert: collection isCollection. + element := collection first. + self assert: element class equals: GLHMergeRequest. + self assert: element project class equals: GLHProject. + + +] + +{ #category : #'tests - merge-requests' } +TGitModelImporterTest >> testImportMergeRequestsOfProject [ + + | collection element | + collection := importer importMergeRequestsOfProject: self defaultProject . + + self assert: collection isCollection. + element := collection first. + self assert: element class equals: GLHMergeRequest. + self assert: element project class equals: GLHProject. + self assert: element diffs isCollection. + self assert: element diffs first class equals: GLHDiff. + self assert: element mergeRequestCommit class equals: GLHCommit +] + { #category : #'tests - users' } TGitModelImporterTest >> testImportUser [ From db91cdc35c0dec9a1d5de1e5acee36ffa476ef07 Mon Sep 17 00:00:00 2001 From: HLAD Nicolas Date: Thu, 25 Sep 2025 16:48:08 +0200 Subject: [PATCH 36/52] fix merge request github --- .../GithubModelImporter.class.st | 50 +++++++++++++++++++ .../GitModelImporter.class.st | 25 +--------- 2 files changed, 51 insertions(+), 24 deletions(-) diff --git a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st index c0744ab0..4b133941 100644 --- a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st +++ b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st @@ -417,6 +417,23 @@ GithubModelImporter >> importDiffOfCommit: aGLHCommit [ ^ aGLHCommit diffs ] +{ #category : #'import - merge-requests' } +GithubModelImporter >> importDiffOfMergeRequest: aGLHMergeRequest [ + |diffsResult| + + diffsResult := self importDiffOfCommit: aGLHMergeRequest mergedCommit. + + diffsResult := aGLHMergeRequest diffs + addAll: diffsResult + unless: self blockForDiffEquality. + self glhModel + addAll: diffsResult + unless: self blockForDiffEquality. + + aGLHMergeRequest diffs do: [ :diff | self importDiffRangesForDiff: diff ]. + ^ aGLHMergeRequest diffs. +] + { #category : #'import - files' } GithubModelImporter >> importDirectoryFiles: aDirectoryFile OfBranch: aBranch [ @@ -522,6 +539,39 @@ GithubModelImporter >> importLatestPullRequestsOfProject: aGLHProject [ ^ self importLatestMergeRequestsOfProject: aGLHProject ] +{ #category : #'import - merge-requests' } +GithubModelImporter >> importMergeRequestMergeCommits: aGLHMergeRequest [ + + | foundCommits | + foundCommits := OrderedCollection new. + + ('Import commit sha of MR: ' , aGLHMergeRequest iid printString) + recordInfo. + "the founds commits are added to the model during their respective import" + aGLHMergeRequest mergeRequestCommit: ((self + importCommit: aGLHMergeRequest sha + ofProject: aGLHMergeRequest project) ifNotNil: [ :commit | + foundCommits add: commit ]). + + ('Import commit merge_commit_sha of MR: ' + , aGLHMergeRequest iid printString) recordInfo. + aGLHMergeRequest mergedCommit: ((self + importCommit: aGLHMergeRequest merge_commit_sha + ofProject: aGLHMergeRequest project) ifNotNil: [ :commit | + foundCommits add: commit ]). + + ('Import commit squash_commit_sha of MR: ' + , aGLHMergeRequest iid printString) recordInfo. + aGLHMergeRequest squashCommit: ((self + importCommit: aGLHMergeRequest squash_commit_sha + ofProject: aGLHMergeRequest project) ifNotNil: [ :commit | + foundCommits add: commit ]). + + + self chainsCommitsFrom: foundCommits. + ^ foundCommits +] + { #category : #'import - merge-requests' } GithubModelImporter >> importMergeRequestsOfProject: aGLHProject [ diff --git a/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st b/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st index 7721da29..3401fbac 100644 --- a/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st +++ b/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st @@ -518,31 +518,8 @@ GitModelImporter >> importMergeRequestCommits: mergeRequest [ { #category : #'import - merge-requests' } GitModelImporter >> importMergeRequestMergeCommits: aGLHMergeRequest [ - | foundCommits | - foundCommits := OrderedCollection new. - ('Import commit sha of MR: ' , aGLHMergeRequest iid printString) - recordInfo. - "the founds commits are added to the model during their respective import" - aGLHMergeRequest mergeRequestCommit: ((self importCommit: aGLHMergeRequest sha ofProject: aGLHMergeRequest project - ) ifNotNil: [ :commit | - foundCommits add: commit ]). - - ('Import commit merge_commit_sha of MR: ' - , aGLHMergeRequest iid printString) recordInfo. - aGLHMergeRequest mergedCommit: ((self - importCommit: aGLHMergeRequest merge_commit_sha ofProject: aGLHMergeRequest project ) ifNotNil: [ :commit | - foundCommits add: commit ]). - - ('Import commit squash_commit_sha of MR: ' - , aGLHMergeRequest iid printString) recordInfo. - aGLHMergeRequest squashCommit: ((self - importCommit: aGLHMergeRequest squash_commit_sha ofProject: aGLHMergeRequest project) ifNotNil: [ :commit | - foundCommits add: commit ]). - - - self chainsCommitsFrom: foundCommits. - ^ foundCommits + self subclassResponsibility ] { #category : #'import - merge-requests' } From ad07bdc1fa749d97327ba53584550aededc357a8 Mon Sep 17 00:00:00 2001 From: HLAD Nicolas Date: Fri, 26 Sep 2025 10:40:12 +0200 Subject: [PATCH 37/52] fix pipeline github import --- .../GithubActionsMock.class.st | 486 ++++++++++++++++++ .../GithubModelImporterTest.class.st | 17 +- .../GHAPIPipelineOverview.class.st | 15 +- .../GithubModelImporter.class.st | 107 +++- .../GitlabModelImporterTest.class.st | 61 +-- .../GitlabModelImporter.class.st | 15 +- .../GitModelImporter.class.st | 16 +- .../TGitModelImporterTest.trait.st | 39 +- 8 files changed, 676 insertions(+), 80 deletions(-) diff --git a/src/GitHubHealth-Model-Importer-Tests/GithubActionsMock.class.st b/src/GitHubHealth-Model-Importer-Tests/GithubActionsMock.class.st index b4735bd3..97fe9265 100644 --- a/src/GitHubHealth-Model-Importer-Tests/GithubActionsMock.class.st +++ b/src/GitHubHealth-Model-Importer-Tests/GithubActionsMock.class.st @@ -4,6 +4,235 @@ Class { #category : #'GitHubHealth-Model-Importer-Tests' } +{ #category : #get } +GithubActionsMock >> getAllRunsForRepo: aGLHProject ofOwner: aString withParms: aCollection [ + ^ '{ + "total_count": 1, + "workflow_runs": [ + { + "id": 30433642, + "name": "Build", + "node_id": "MDEyOldvcmtmbG93IFJ1bjI2OTI4OQ==", + "check_suite_id": 42, + "check_suite_node_id": "MDEwOkNoZWNrU3VpdGU0Mg==", + "head_branch": "master", + "head_sha": "acb5820ced9479c074f688cc328bf03f341a511d", + "path": ".github/workflows/build.yml@main", + "run_number": 562, + "event": "push", + "display_title": "Update README.md", + "status": "queued", + "conclusion": null, + "workflow_id": 159038, + "url": "https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642", + "html_url": "https://github.com/octo-org/octo-repo/actions/runs/30433642", + "pull_requests": [], + "created_at": "2020-01-22T19:33:08Z", + "updated_at": "2020-01-22T19:33:08Z", + "actor": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "run_attempt": 1, + "run_started_at": "2020-01-22T19:33:08Z", + "triggering_actor": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "jobs_url": "https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/jobs", + "logs_url": "https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/logs", + "check_suite_url": "https://api.github.com/repos/octo-org/octo-repo/check-suites/414944374", + "artifacts_url": "https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/artifacts", + "cancel_url": "https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/cancel", + "rerun_url": "https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/rerun", + "workflow_url": "https://api.github.com/repos/octo-org/octo-repo/actions/workflows/159038", + "head_commit": { + "id": "acb5820ced9479c074f688cc328bf03f341a511d", + "tree_id": "d23f6eedb1e1b9610bbc754ddb5197bfe7271223", + "message": "Create linter.yaml", + "timestamp": "2020-01-22T19:33:05Z", + "author": { + "name": "Octo Cat", + "email": "octocat@github.com" + }, + "committer": { + "name": "GitHub", + "email": "noreply@github.com" + } + }, + "repository": { + "id": 1296269, + "node_id": "MDEwOlJlcG9zaXRvcnkxMjk2MjY5", + "name": "Hello-World", + "full_name": "octocat/Hello-World", + "owner": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/octocat/Hello-World", + "description": "This your first repo!", + "fork": false, + "url": "https://api.github.com/repos/octocat/Hello-World", + "archive_url": "https://api.github.com/repos/octocat/Hello-World/{archive_format}{/ref}", + "assignees_url": "https://api.github.com/repos/octocat/Hello-World/assignees{/user}", + "blobs_url": "https://api.github.com/repos/octocat/Hello-World/git/blobs{/sha}", + "branches_url": "https://api.github.com/repos/octocat/Hello-World/branches{/branch}", + "collaborators_url": "https://api.github.com/repos/octocat/Hello-World/collaborators{/collaborator}", + "comments_url": "https://api.github.com/repos/octocat/Hello-World/comments{/number}", + "commits_url": "https://api.github.com/repos/octocat/Hello-World/commits{/sha}", + "compare_url": "https://api.github.com/repos/octocat/Hello-World/compare/{base}...{head}", + "contents_url": "https://api.github.com/repos/octocat/Hello-World/contents/{+path}", + "contributors_url": "https://api.github.com/repos/octocat/Hello-World/contributors", + "deployments_url": "https://api.github.com/repos/octocat/Hello-World/deployments", + "downloads_url": "https://api.github.com/repos/octocat/Hello-World/downloads", + "events_url": "https://api.github.com/repos/octocat/Hello-World/events", + "forks_url": "https://api.github.com/repos/octocat/Hello-World/forks", + "git_commits_url": "https://api.github.com/repos/octocat/Hello-World/git/commits{/sha}", + "git_refs_url": "https://api.github.com/repos/octocat/Hello-World/git/refs{/sha}", + "git_tags_url": "https://api.github.com/repos/octocat/Hello-World/git/tags{/sha}", + "git_url": "git:github.com/octocat/Hello-World.git", + "issue_comment_url": "https://api.github.com/repos/octocat/Hello-World/issues/comments{/number}", + "issue_events_url": "https://api.github.com/repos/octocat/Hello-World/issues/events{/number}", + "issues_url": "https://api.github.com/repos/octocat/Hello-World/issues{/number}", + "keys_url": "https://api.github.com/repos/octocat/Hello-World/keys{/key_id}", + "labels_url": "https://api.github.com/repos/octocat/Hello-World/labels{/name}", + "languages_url": "https://api.github.com/repos/octocat/Hello-World/languages", + "merges_url": "https://api.github.com/repos/octocat/Hello-World/merges", + "milestones_url": "https://api.github.com/repos/octocat/Hello-World/milestones{/number}", + "notifications_url": "https://api.github.com/repos/octocat/Hello-World/notifications{?since,all,participating}", + "pulls_url": "https://api.github.com/repos/octocat/Hello-World/pulls{/number}", + "releases_url": "https://api.github.com/repos/octocat/Hello-World/releases{/id}", + "ssh_url": "git@github.com:octocat/Hello-World.git", + "stargazers_url": "https://api.github.com/repos/octocat/Hello-World/stargazers", + "statuses_url": "https://api.github.com/repos/octocat/Hello-World/statuses/{sha}", + "subscribers_url": "https://api.github.com/repos/octocat/Hello-World/subscribers", + "subscription_url": "https://api.github.com/repos/octocat/Hello-World/subscription", + "tags_url": "https://api.github.com/repos/octocat/Hello-World/tags", + "teams_url": "https://api.github.com/repos/octocat/Hello-World/teams", + "trees_url": "https://api.github.com/repos/octocat/Hello-World/git/trees{/sha}", + "hooks_url": "http://api.github.com/repos/octocat/Hello-World/hooks" + }, + "head_repository": { + "id": 217723378, + "node_id": "MDEwOlJlcG9zaXRvcnkyMTc3MjMzNzg=", + "name": "octo-repo", + "full_name": "octo-org/octo-repo", + "private": true, + "owner": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "html_url": "https://github.com/octo-org/octo-repo", + "description": null, + "fork": false, + "url": "https://api.github.com/repos/octo-org/octo-repo", + "forks_url": "https://api.github.com/repos/octo-org/octo-repo/forks", + "keys_url": "https://api.github.com/repos/octo-org/octo-repo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/octo-org/octo-repo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/octo-org/octo-repo/teams", + "hooks_url": "https://api.github.com/repos/octo-org/octo-repo/hooks", + "issue_events_url": "https://api.github.com/repos/octo-org/octo-repo/issues/events{/number}", + "events_url": "https://api.github.com/repos/octo-org/octo-repo/events", + "assignees_url": "https://api.github.com/repos/octo-org/octo-repo/assignees{/user}", + "branches_url": "https://api.github.com/repos/octo-org/octo-repo/branches{/branch}", + "tags_url": "https://api.github.com/repos/octo-org/octo-repo/tags", + "blobs_url": "https://api.github.com/repos/octo-org/octo-repo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/octo-org/octo-repo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/octo-org/octo-repo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/octo-org/octo-repo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/octo-org/octo-repo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/octo-org/octo-repo/languages", + "stargazers_url": "https://api.github.com/repos/octo-org/octo-repo/stargazers", + "contributors_url": "https://api.github.com/repos/octo-org/octo-repo/contributors", + "subscribers_url": "https://api.github.com/repos/octo-org/octo-repo/subscribers", + "subscription_url": "https://api.github.com/repos/octo-org/octo-repo/subscription", + "commits_url": "https://api.github.com/repos/octo-org/octo-repo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/octo-org/octo-repo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/octo-org/octo-repo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/octo-org/octo-repo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/octo-org/octo-repo/contents/{+path}", + "compare_url": "https://api.github.com/repos/octo-org/octo-repo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/octo-org/octo-repo/merges", + "archive_url": "https://api.github.com/repos/octo-org/octo-repo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/octo-org/octo-repo/downloads", + "issues_url": "https://api.github.com/repos/octo-org/octo-repo/issues{/number}", + "pulls_url": "https://api.github.com/repos/octo-org/octo-repo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/octo-org/octo-repo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/octo-org/octo-repo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/octo-org/octo-repo/labels{/name}", + "releases_url": "https://api.github.com/repos/octo-org/octo-repo/releases{/id}", + "deployments_url": "https://api.github.com/repos/octo-org/octo-repo/deployments" + } + } + ] +}' +] + { #category : #'as yet unclassified' } GithubActionsMock >> getLatestForRepo: aString ofOwner: aString2 [ "https://docs.github.com/en/rest/actions/workflow-runs?apiVersion=2022-11-28#list-workflow-runs-for-a-repository" @@ -234,3 +463,260 @@ GithubActionsMock >> getLatestForRepo: aString ofOwner: aString2 [ ] }' ] + +{ #category : #get } +GithubActionsMock >> getRun: anInteger forRepo: aString ofOwner: aString3 [ + ^'{ + "id": 30433642, + "name": "Build", + "node_id": "MDEyOldvcmtmbG93IFJ1bjI2OTI4OQ==", + "check_suite_id": 42, + "check_suite_node_id": "MDEwOkNoZWNrU3VpdGU0Mg==", + "head_branch": "main", + "head_sha": "acb5820ced9479c074f688cc328bf03f341a511d", + "path": ".github/workflows/build.yml@main", + "run_number": 562, + "event": "push", + "display_title": "Update README.md", + "status": "queued", + "conclusion": null, + "workflow_id": 159038, + "url": "https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642", + "html_url": "https://github.com/octo-org/octo-repo/actions/runs/30433642", + "pull_requests": [], + "created_at": "2020-01-22T19:33:08Z", + "updated_at": "2020-01-22T19:33:08Z", + "actor": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "run_attempt": 1, + "referenced_workflows": [ + { + "path": "octocat/Hello-World/.github/workflows/deploy.yml@main", + "sha": "86e8bc9ecf7d38b1ed2d2cfb8eb87ba9b35b01db", + "ref": "refs/heads/main" + }, + { + "path": "octo-org/octo-repo/.github/workflows/report.yml@v2", + "sha": "79e9790903e1c3373b1a3e3a941d57405478a232", + "ref": "refs/tags/v2" + }, + { + "path": "octo-org/octo-repo/.github/workflows/secure.yml@1595d4b6de6a9e9751fb270a41019ce507d4099e", + "sha": "1595d4b6de6a9e9751fb270a41019ce507d4099e" + } + ], + "run_started_at": "2020-01-22T19:33:08Z", + "triggering_actor": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "jobs_url": "https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/jobs", + "logs_url": "https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/logs", + "check_suite_url": "https://api.github.com/repos/octo-org/octo-repo/check-suites/414944374", + "artifacts_url": "https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/artifacts", + "cancel_url": "https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/cancel", + "rerun_url": "https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/rerun", + "previous_attempt_url": "https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/attempts/1", + "workflow_url": "https://api.github.com/repos/octo-org/octo-repo/actions/workflows/159038", + "head_commit": { + "id": "acb5820ced9479c074f688cc328bf03f341a511d", + "tree_id": "d23f6eedb1e1b9610bbc754ddb5197bfe7271223", + "message": "Create linter.yaml", + "timestamp": "2020-01-22T19:33:05Z", + "author": { + "name": "Octo Cat", + "email": "octocat@github.com" + }, + "committer": { + "name": "GitHub", + "email": "noreply@github.com" + } + }, + "repository": { + "id": 1296269, + "node_id": "MDEwOlJlcG9zaXRvcnkxMjk2MjY5", + "name": "Hello-World", + "full_name": "octocat/Hello-World", + "owner": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/octocat/Hello-World", + "description": "This your first repo!", + "fork": false, + "url": "https://api.github.com/repos/octocat/Hello-World", + "archive_url": "https://api.github.com/repos/octocat/Hello-World/{archive_format}{/ref}", + "assignees_url": "https://api.github.com/repos/octocat/Hello-World/assignees{/user}", + "blobs_url": "https://api.github.com/repos/octocat/Hello-World/git/blobs{/sha}", + "branches_url": "https://api.github.com/repos/octocat/Hello-World/branches{/branch}", + "collaborators_url": "https://api.github.com/repos/octocat/Hello-World/collaborators{/collaborator}", + "comments_url": "https://api.github.com/repos/octocat/Hello-World/comments{/number}", + "commits_url": "https://api.github.com/repos/octocat/Hello-World/commits{/sha}", + "compare_url": "https://api.github.com/repos/octocat/Hello-World/compare/{base}...{head}", + "contents_url": "https://api.github.com/repos/octocat/Hello-World/contents/{+path}", + "contributors_url": "https://api.github.com/repos/octocat/Hello-World/contributors", + "deployments_url": "https://api.github.com/repos/octocat/Hello-World/deployments", + "downloads_url": "https://api.github.com/repos/octocat/Hello-World/downloads", + "events_url": "https://api.github.com/repos/octocat/Hello-World/events", + "forks_url": "https://api.github.com/repos/octocat/Hello-World/forks", + "git_commits_url": "https://api.github.com/repos/octocat/Hello-World/git/commits{/sha}", + "git_refs_url": "https://api.github.com/repos/octocat/Hello-World/git/refs{/sha}", + "git_tags_url": "https://api.github.com/repos/octocat/Hello-World/git/tags{/sha}", + "git_url": "git:github.com/octocat/Hello-World.git", + "issue_comment_url": "https://api.github.com/repos/octocat/Hello-World/issues/comments{/number}", + "issue_events_url": "https://api.github.com/repos/octocat/Hello-World/issues/events{/number}", + "issues_url": "https://api.github.com/repos/octocat/Hello-World/issues{/number}", + "keys_url": "https://api.github.com/repos/octocat/Hello-World/keys{/key_id}", + "labels_url": "https://api.github.com/repos/octocat/Hello-World/labels{/name}", + "languages_url": "https://api.github.com/repos/octocat/Hello-World/languages", + "merges_url": "https://api.github.com/repos/octocat/Hello-World/merges", + "milestones_url": "https://api.github.com/repos/octocat/Hello-World/milestones{/number}", + "notifications_url": "https://api.github.com/repos/octocat/Hello-World/notifications{?since,all,participating}", + "pulls_url": "https://api.github.com/repos/octocat/Hello-World/pulls{/number}", + "releases_url": "https://api.github.com/repos/octocat/Hello-World/releases{/id}", + "ssh_url": "git@github.com:octocat/Hello-World.git", + "stargazers_url": "https://api.github.com/repos/octocat/Hello-World/stargazers", + "statuses_url": "https://api.github.com/repos/octocat/Hello-World/statuses/{sha}", + "subscribers_url": "https://api.github.com/repos/octocat/Hello-World/subscribers", + "subscription_url": "https://api.github.com/repos/octocat/Hello-World/subscription", + "tags_url": "https://api.github.com/repos/octocat/Hello-World/tags", + "teams_url": "https://api.github.com/repos/octocat/Hello-World/teams", + "trees_url": "https://api.github.com/repos/octocat/Hello-World/git/trees{/sha}", + "hooks_url": "http://api.github.com/repos/octocat/Hello-World/hooks" + }, + "head_repository": { + "id": 217723378, + "node_id": "MDEwOlJlcG9zaXRvcnkyMTc3MjMzNzg=", + "name": "octo-repo", + "full_name": "octo-org/octo-repo", + "private": true, + "owner": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "html_url": "https://github.com/octo-org/octo-repo", + "description": null, + "fork": false, + "url": "https://api.github.com/repos/octo-org/octo-repo", + "forks_url": "https://api.github.com/repos/octo-org/octo-repo/forks", + "keys_url": "https://api.github.com/repos/octo-org/octo-repo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/octo-org/octo-repo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/octo-org/octo-repo/teams", + "hooks_url": "https://api.github.com/repos/octo-org/octo-repo/hooks", + "issue_events_url": "https://api.github.com/repos/octo-org/octo-repo/issues/events{/number}", + "events_url": "https://api.github.com/repos/octo-org/octo-repo/events", + "assignees_url": "https://api.github.com/repos/octo-org/octo-repo/assignees{/user}", + "branches_url": "https://api.github.com/repos/octo-org/octo-repo/branches{/branch}", + "tags_url": "https://api.github.com/repos/octo-org/octo-repo/tags", + "blobs_url": "https://api.github.com/repos/octo-org/octo-repo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/octo-org/octo-repo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/octo-org/octo-repo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/octo-org/octo-repo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/octo-org/octo-repo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/octo-org/octo-repo/languages", + "stargazers_url": "https://api.github.com/repos/octo-org/octo-repo/stargazers", + "contributors_url": "https://api.github.com/repos/octo-org/octo-repo/contributors", + "subscribers_url": "https://api.github.com/repos/octo-org/octo-repo/subscribers", + "subscription_url": "https://api.github.com/repos/octo-org/octo-repo/subscription", + "commits_url": "https://api.github.com/repos/octo-org/octo-repo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/octo-org/octo-repo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/octo-org/octo-repo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/octo-org/octo-repo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/octo-org/octo-repo/contents/{+path}", + "compare_url": "https://api.github.com/repos/octo-org/octo-repo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/octo-org/octo-repo/merges", + "archive_url": "https://api.github.com/repos/octo-org/octo-repo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/octo-org/octo-repo/downloads", + "issues_url": "https://api.github.com/repos/octo-org/octo-repo/issues{/number}", + "pulls_url": "https://api.github.com/repos/octo-org/octo-repo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/octo-org/octo-repo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/octo-org/octo-repo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/octo-org/octo-repo/labels{/name}", + "releases_url": "https://api.github.com/repos/octo-org/octo-repo/releases{/id}", + "deployments_url": "https://api.github.com/repos/octo-org/octo-repo/deployments" + } +}' +] + +{ #category : #get } +GithubActionsMock >> getWorkflow: anInteger forRepo: aString ofOwner: aString3 [ + ^ '{ + "id": 161335, + "node_id": "MDg6V29ya2Zsb3cxNjEzMzU=", + "name": "CI", + "path": ".github/workflows/blank.yaml", + "state": "active", + "created_at": "2020-01-08T23:48:37.000-08:00", + "updated_at": "2020-01-08T23:50:21.000-08:00", + "url": "https://api.github.com/repos/octo-org/octo-repo/actions/workflows/161335", + "html_url": "https://github.com/octo-org/octo-repo/blob/master/.github/workflows/161335", + "badge_url": "https://github.com/octo-org/octo-repo/workflows/CI/badge.svg" +}' +] diff --git a/src/GitHubHealth-Model-Importer-Tests/GithubModelImporterTest.class.st b/src/GitHubHealth-Model-Importer-Tests/GithubModelImporterTest.class.st index 7a8e1472..83068a76 100644 --- a/src/GitHubHealth-Model-Importer-Tests/GithubModelImporterTest.class.st +++ b/src/GitHubHealth-Model-Importer-Tests/GithubModelImporterTest.class.st @@ -20,12 +20,17 @@ GithubModelImporterTest >> setUp [ "than set up the model in super" model := GLHModel new. importer glhModel: model. - - defaultProject := (GLHProject new - name: 'myProject'; - group: (GLHGroup new name: 'itsGroup'); - repository: GLHRepository new; - yourself). + + defaultProject := GLHProject new + name: 'myProject'; + group: (GLHGroup new name: 'itsGroup'); + repository: GLHRepository new; + yourself. + + defaultMergeRequestOrPipeline := GLHMergeRequest new + name: 'myPipeline'; + sha: '30433642'; + project: defaultProject; yourself. ] { #category : #'tests - parsing' } diff --git a/src/GitHubHealth-Model-Importer/GHAPIPipelineOverview.class.st b/src/GitHubHealth-Model-Importer/GHAPIPipelineOverview.class.st index 684778de..a000162d 100644 --- a/src/GitHubHealth-Model-Importer/GHAPIPipelineOverview.class.st +++ b/src/GitHubHealth-Model-Importer/GHAPIPipelineOverview.class.st @@ -3,11 +3,24 @@ Class { #superclass : #Object, #instVars : [ 'total_count', - 'workflow_runs' + 'workflow_runs', + 'jobs' ], #category : #'GitHubHealth-Model-Importer' } +{ #category : #accessing } +GHAPIPipelineOverview >> jobs [ + + ^ jobs +] + +{ #category : #accessing } +GHAPIPipelineOverview >> jobs: anObject [ + + jobs := anObject +] + { #category : #accessing } GHAPIPipelineOverview >> total_count [ diff --git a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st index 4b133941..4661aa92 100644 --- a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st +++ b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st @@ -163,6 +163,12 @@ GithubModelImporter >> configureReaderForGroup: reader [ do: [ :mapping | mapping mapInstVar: #web_url to: #html_url ] ] +{ #category : #'private - configure reader' } +GithubModelImporter >> configureReaderForJob: reader [ + super configureReaderForJob: reader. + +] + { #category : #'private - configure reader' } GithubModelImporter >> configureReaderForMergeRequest: reader [ " reader mapInstVarsFor: GLHProject. " @@ -196,27 +202,32 @@ GithubModelImporter >> configureReaderForPipeline: reader [ super configureReaderForPipeline: reader. - reader for: GLHPipeline do: [ :mapping | - "mapping mapInstVar: #status to: #conclusion." - - mapping - mapProperty: #status - getter: [ :object | #ignore ] - setter: [ :object :value | - (object status isNil and: [value isNotNil]) ifTrue: [ object status: value ]. - ]. - - mapping - mapProperty: #conclusion - getter: [ :object | #ignore ] - setter: [ :object :value | - (object status isNil and: [value isNotNil]) ifTrue: [ object status: value ]. ]. - - mapping - mapProperty: #run_started_at - getter: [ :object | #ignore ] - setter: [ :object :value | - object runDate: (DateAndTime fromString: value) ] ] + reader + for: GLHPipeline + do: [ :mapping | "mapping mapInstVar: #status to: #conclusion." + + (mapping mapInstVar: #created_at) valueSchema: DateAndTime. + (mapping mapInstVar: #updated_at) valueSchema: DateAndTime. + + mapping + mapProperty: #status + getter: [ :object | #ignore ] + setter: [ :object :value | + (object status isNil and: [ value isNotNil ]) ifTrue: [ + object status: value ] ]. + + mapping + mapProperty: #conclusion + getter: [ :object | #ignore ] + setter: [ :object :value | + (object status isNil and: [ value isNotNil ]) ifTrue: [ + object status: value ] ]. + + mapping + mapProperty: #run_started_at + getter: [ :object | #ignore ] + setter: [ :object :value | + object runDate: (DateAndTime fromString: value) ] ] ] { #category : #'private - configure reader' } @@ -597,6 +608,46 @@ GithubModelImporter >> importMergeRequestsOfProject: aGLHProject [ ^ mergeRequests ] +{ #category : #'import - pipelines' } +GithubModelImporter >> importPipeline: aPipelineId OfProject: aGLHProject [ + + "import specific actions' run " + | reponse result | + aGLHProject pipelines + detect: [ :p | p id = aPipelineId ] + ifFound: [ :p | ^ p ] + ifNone: [ ]. + + reponse := self repoApi actions + getRun: aPipelineId + forRepo: aGLHProject name + ofOwner: aGLHProject group name. + result := self parsePipelineResult: reponse. + + result := self glhModel add: result unless: self blockOnIdEquality. + result := aGLHProject pipelines + add: result + unless: self blockOnIdEquality. + + ^ result +] + +{ #category : #'import - pipelines' } +GithubModelImporter >> importPipelinesOfMergeRequest: aGLHMergeRequest [ + |result pipelines| + result := self repoApi actions getAllRunsForRepo: aGLHMergeRequest project name ofOwner: aGLHMergeRequest project group name withParms: { #event->'pull_request' . #head_sha -> aGLHMergeRequest sha } asDictionary . + + + pipelines := (self parsePipelinesResult: result) workflow_runs . + + pipelines := glhModel addAll: pipelines unless: self blockOnIdEquality. + pipelines := aGLHMergeRequest pipelines addAll: pipelines unless: self blockOnIdEquality. + + aGLHMergeRequest project pipelines addAll: pipelines unless: self blockOnIdEquality. + + ^ pipelines +] + { #category : #'import - pipelines' } GithubModelImporter >> importPipelinesOfProject: project [ @@ -862,15 +913,27 @@ GithubModelImporter >> parseMergeRequestsResult: response [ ^ result ] +{ #category : #parsing } +GithubModelImporter >> parsePipelineResult: result [ + + | reader | + reader := generalReader on: result readStream. + ^ reader nextAs: GLHPipeline . + +] + { #category : #parsing } GithubModelImporter >> parsePipelinesResult: pipelineOverview [ + "in github, Actions runs (pipeline) are returns in an overview objects" + | reader | reader := generalReader on: pipelineOverview readStream. reader for: GHAPIPipelineOverview do: [ :mapping | mapping mapInstVar: #total_count to: #total_count. - (mapping mapInstVar: #workflow_runs) valueSchema: #ArrayOfPipeline ]. + (mapping mapInstVar: #workflow_runs) valueSchema: #ArrayOfPipeline. + (mapping mapInstVar: #jobs) valueSchema: #ArrayOfJob ]. ^ reader nextAs: GHAPIPipelineOverview diff --git a/src/GitLabHealth-Model-Importer-Tests/GitlabModelImporterTest.class.st b/src/GitLabHealth-Model-Importer-Tests/GitlabModelImporterTest.class.st index 2fcb6f89..6acf2959 100644 --- a/src/GitLabHealth-Model-Importer-Tests/GitlabModelImporterTest.class.st +++ b/src/GitLabHealth-Model-Importer-Tests/GitlabModelImporterTest.class.st @@ -191,9 +191,13 @@ GitlabModelImporterTest >> setUp [ "than set up the model in super" model := GLHModel new. importer glhModel: model. - defaultProject := (GLHProject new - repository: GLHRepository new; - yourself). + defaultProject := GLHProject new + repository: GLHRepository new; + yourself. + defaultMergeRequestOrPipeline := (GLHMergeRequest new + project: (GLHProject new id: 123); + iid: 123; + yourself). ] { #category : #'tests - repositories' } @@ -288,16 +292,18 @@ GitlabModelImporterTest >> testImportDiffOfMergeRequest [ ] { #category : #'tests - jobs' } -GitlabModelImporterTest >> testImportJobsOf [ +GitlabModelImporterTest >> testImportJobsOfPipeline [ | json jobsArray job | json := self jobsJson. - jobsArray := importer importJobsOf: (GLHPipeline new - id: 12; - project: (GLHProject new id: 12; repository: GLHRepository new); - yourself). - + jobsArray := importer importJobsOfPipeline: (GLHPipeline new + id: 12; + project: (GLHProject new + id: 12; + repository: GLHRepository new); + yourself). + job := jobsArray first. self assert: jobsArray size equals: 2. @@ -352,43 +358,6 @@ GitlabModelImporterTest >> testImportNotesOfMergeRequest [ ] -{ #category : #'tests - pipelines' } -GitlabModelImporterTest >> testImportPipelineOfProject [ - - | element | - element := importer importPipeline: 123 OfProject: - (GLHProject new - repository: GLHRepository new; - yourself). - - self assert: element class equals: GLHPipeline. - self assert: element project isNotNil. - self assert: element project class equals: GLHProject -] - -{ #category : #'tests - pipelines' } -GitlabModelImporterTest >> testImportPipelinesOfMergeRequest [ - - | collection element | - collection := importer importPipelinesOfMergeRequest: - (GLHMergeRequest new - project: (GLHProject new id:123); - iid: 123; - yourself). - - self assert: collection isEmptyOrNil not. - self assert: collection isCollection. - - element := collection first. - self assert: element class equals: GLHPipeline. - self assert: element project isNotNil. - self assert: element project class equals: GLHProject. - - self assert: element mergeRequest isNotNil. - self assert: element mergeRequest class equals: GLHMergeRequest. - -] - { #category : #'tests - projects' } GitlabModelImporterTest >> testImportProject [ diff --git a/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st b/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st index a6a7dfaf..f206190d 100644 --- a/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st +++ b/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st @@ -1073,6 +1073,18 @@ GitlabModelImporter >> importGroup: aGroupID [ { #category : #'import - jobs' } GitlabModelImporter >> importJobsOf: aPipeline [ + + self + deprecated: 'Use importJobsOfPipeline: instead of current one' + on: '26 September 2025' + in: + 'Pharo-12.0.0+SNAPSHOT.build.1571.sha.cf5fcd22e66957962c97dffc58b0393b7f368147 (64 Bit)'. + ^ self importJobsOfPipeline: aPipeline. +] + +{ #category : #'import - jobs' } +GitlabModelImporter >> importJobsOfPipeline: aPipeline [ + | jobs results | results := self repoApi jobs getAllForPipeline: aPipeline id @@ -1087,8 +1099,7 @@ GitlabModelImporter >> importJobsOf: aPipeline [ jobs := aPipeline jobs addAll: jobs unless: self blockOnIdEquality. - jobs do: [ :job | - self completeImportedJob: job ]. + jobs do: [ :job | self completeImportedJob: job ]. ^ jobs ] diff --git a/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st b/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st index 3401fbac..cfc7e49f 100644 --- a/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st +++ b/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st @@ -486,7 +486,19 @@ GitModelImporter >> importIssuesOfProject: aGLHProject [ { #category : #'import - jobs' } GitModelImporter >> importJobsOf: aGLHPipeline [ - self subclassResponsibility + + self + deprecated: 'Use importJobsOfPipeline: instead of current one' + on: '26 September 2025' + in: + 'Pharo-12.0.0+SNAPSHOT.build.1571.sha.cf5fcd22e66957962c97dffc58b0393b7f368147 (64 Bit)'. + self subclassResponsibility +] + +{ #category : #'import - jobs' } +GitModelImporter >> importJobsOfPipeline: aGLHPipeline [ + + self subclassResponsibility ] { #category : #'import - commits' } @@ -555,7 +567,7 @@ GitModelImporter >> importNotesOfMergeRequest: mergeRequest [ { #category : #'import - pipelines' } GitModelImporter >> importPipeline: aPipelineId OfProject: aGLHProject [ - self subclassResponsibility + ^ self subclassResponsibility ] { #category : #'import - merge-requests' } diff --git a/src/GitProjectHealth-Model-Importer/TGitModelImporterTest.trait.st b/src/GitProjectHealth-Model-Importer/TGitModelImporterTest.trait.st index cf033c2b..cb8b059f 100644 --- a/src/GitProjectHealth-Model-Importer/TGitModelImporterTest.trait.st +++ b/src/GitProjectHealth-Model-Importer/TGitModelImporterTest.trait.st @@ -3,7 +3,8 @@ Trait { #instVars : [ 'importer', 'model', - 'defaultProject' + 'defaultProject', + 'defaultMergeRequestOrPipeline' ], #category : #'GitProjectHealth-Model-Importer' } @@ -221,6 +222,12 @@ TGitModelImporterTest classSide >> traits [ ^ self traitComposition traits ] +{ #category : #accessing } +TGitModelImporterTest >> defaultMergeRequestOrPipeline [ + + ^ defaultMergeRequestOrPipeline +] + { #category : #accessing } TGitModelImporterTest >> defaultProject [ ^ defaultProject @@ -306,6 +313,36 @@ TGitModelImporterTest >> testImportMergeRequestsOfProject [ self assert: element mergeRequestCommit class equals: GLHCommit ] +{ #category : #'tests - pipelines' } +TGitModelImporterTest >> testImportPipelineOfProject [ + + | element | + element := importer importPipeline: 123 OfProject: self defaultProject . + + self assert: element class equals: GLHPipeline. + self assert: element project isNotNil. + self assert: element project class equals: GLHProject +] + +{ #category : #'tests - pipelines' } +TGitModelImporterTest >> testImportPipelinesOfMergeRequest [ + + | collection element | + collection := importer importPipelinesOfMergeRequest: + self defaultMergeRequestOrPipeline. + + self assert: collection isEmptyOrNil not. + self assert: collection isCollection. + + element := collection first. + self assert: element class equals: GLHPipeline. + self assert: element project isNotNil. + self assert: element project class equals: GLHProject. + + self assert: element mergeRequest isNotNil. + self assert: element mergeRequest class equals: GLHMergeRequest +] + { #category : #'tests - users' } TGitModelImporterTest >> testImportUser [ From a6cc94005eca500e37e27fed37da910e15297088 Mon Sep 17 00:00:00 2001 From: HLAD Nicolas Date: Fri, 26 Sep 2025 10:55:59 +0200 Subject: [PATCH 38/52] fix tests --- .../GithubModelImporterTest.class.st | 11 ++++++++--- .../GitlabModelImporterTest.class.st | 9 +++++---- .../TGitModelImporterTest.trait.st | 7 +++++-- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/GitHubHealth-Model-Importer-Tests/GithubModelImporterTest.class.st b/src/GitHubHealth-Model-Importer-Tests/GithubModelImporterTest.class.st index 83068a76..04f22c85 100644 --- a/src/GitHubHealth-Model-Importer-Tests/GithubModelImporterTest.class.st +++ b/src/GitHubHealth-Model-Importer-Tests/GithubModelImporterTest.class.st @@ -28,9 +28,14 @@ GithubModelImporterTest >> setUp [ yourself. defaultMergeRequestOrPipeline := GLHMergeRequest new - name: 'myPipeline'; - sha: '30433642'; - project: defaultProject; yourself. + name: 'myPipeline'; + sha: '30433642'; + project: (GLHProject new + name: 'myProject'; + group: (GLHGroup new name: 'itsGroup'); + repository: GLHRepository new; + yourself); + yourself ] { #category : #'tests - parsing' } diff --git a/src/GitLabHealth-Model-Importer-Tests/GitlabModelImporterTest.class.st b/src/GitLabHealth-Model-Importer-Tests/GitlabModelImporterTest.class.st index 6acf2959..1aaa0ef7 100644 --- a/src/GitLabHealth-Model-Importer-Tests/GitlabModelImporterTest.class.st +++ b/src/GitLabHealth-Model-Importer-Tests/GitlabModelImporterTest.class.st @@ -194,10 +194,11 @@ GitlabModelImporterTest >> setUp [ defaultProject := GLHProject new repository: GLHRepository new; yourself. - defaultMergeRequestOrPipeline := (GLHMergeRequest new - project: (GLHProject new id: 123); - iid: 123; - yourself). + + defaultMergeRequestOrPipeline := GLHMergeRequest new + project: (GLHProject new id: 123); + iid: 123; + yourself ] { #category : #'tests - repositories' } diff --git a/src/GitProjectHealth-Model-Importer/TGitModelImporterTest.trait.st b/src/GitProjectHealth-Model-Importer/TGitModelImporterTest.trait.st index cb8b059f..72d797a7 100644 --- a/src/GitProjectHealth-Model-Importer/TGitModelImporterTest.trait.st +++ b/src/GitProjectHealth-Model-Importer/TGitModelImporterTest.trait.st @@ -225,7 +225,7 @@ TGitModelImporterTest classSide >> traits [ { #category : #accessing } TGitModelImporterTest >> defaultMergeRequestOrPipeline [ - ^ defaultMergeRequestOrPipeline + ^ defaultMergeRequestOrPipeline ] { #category : #accessing } @@ -302,7 +302,10 @@ TGitModelImporterTest >> testImportLatestMergeRequestsOfProject [ TGitModelImporterTest >> testImportMergeRequestsOfProject [ | collection element | - collection := importer importMergeRequestsOfProject: self defaultProject . + + + collection := importer importMergeRequestsOfProject: + self defaultProject. self assert: collection isCollection. element := collection first. From 2506204031dff1e27577d5483614984332cb14b4 Mon Sep 17 00:00:00 2001 From: HLAD Nicolas Date: Fri, 26 Sep 2025 12:11:47 +0200 Subject: [PATCH 39/52] add duration to job pipeline import --- .../GithubModelImporter.class.st | 59 ++++++++++++++++++- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st index 4661aa92..c7c61062 100644 --- a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st +++ b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st @@ -165,8 +165,36 @@ GithubModelImporter >> configureReaderForGroup: reader [ { #category : #'private - configure reader' } GithubModelImporter >> configureReaderForJob: reader [ + super configureReaderForJob: reader. - + + reader for: GLHJob do: [ :mapping | + + mapping mapInstVar: #web_url to: #html_url. + + mapping + mapProperty: #pipeline + getter: [ ] + setter: [ :job :rawPipeline | + job cacheAt: #pipelineID put: (rawPipeline at: #head_sha) ]. + + mapping + mapProperty: #commit + getter: [ ] + setter: [ :job :rawCommit | + job cacheAt: #commitID put: (rawCommit at: #id) ]. + + mapping + mapProperty: #completed_at + getter: [ :object | #ignore ] + setter: [ :job :value | + value ifNotNil: [ job cacheAt: #completed_at put: (value asDateAndTime ) ] ]. + + mapping + mapProperty: #started_at + getter: [ :object | #ignore ] + setter: [ :job :value | + value ifNotNil: [ job cacheAt: #started_at put: (value asDateAndTime ) ] ] ] ] { #category : #'private - configure reader' } @@ -500,6 +528,31 @@ GithubModelImporter >> importGroup: aGroupName [ ^ groupResult ] +{ #category : #'import - jobs' } +GithubModelImporter >> importJobsOfPipeline: aGLHPipeline [ + + | result jobs | + result := self repoApi actions + getAllJobsForRun: aGLHPipeline id + forRepo: aGLHPipeline project name + ofOwner: aGLHPipeline project group name. + + jobs := (self parsePipelinesResult: result) jobs. + + jobs do: [ :job | + |stop start| + stop := job cacheAt: #completed_at ifAbsent: [ nil ]. + start := job cacheAt: #started_at ifAbsent: [ nil ]. + job duration: (stop - start) asDuration . + ]. + + jobs := glhModel addAll: jobs unless: self blockOnIdEquality. + aGLHPipeline jobs addAll: jobs unless: self blockOnIdEquality. + + + ^ aGLHPipeline jobs +] + { #category : #'import - commits' } GithubModelImporter >> importLatestCommitsOfProject: aGLHProject [ "limited to the last 50 commits" @@ -640,10 +693,12 @@ GithubModelImporter >> importPipelinesOfMergeRequest: aGLHMergeRequest [ pipelines := (self parsePipelinesResult: result) workflow_runs . + pipelines := aGLHMergeRequest project pipelines addAll: pipelines unless: self blockOnIdEquality. + pipelines := glhModel addAll: pipelines unless: self blockOnIdEquality. pipelines := aGLHMergeRequest pipelines addAll: pipelines unless: self blockOnIdEquality. - aGLHMergeRequest project pipelines addAll: pipelines unless: self blockOnIdEquality. + ^ pipelines ] From b764c83b9f06441430039fab630f34be4a6e410b Mon Sep 17 00:00:00 2001 From: Benoit Verhaeghe Date: Fri, 26 Sep 2025 14:21:06 +0200 Subject: [PATCH 40/52] fix baseline --- src/BaselineOfGitLabHealth/BaselineOfGitLabHealth.class.st | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/BaselineOfGitLabHealth/BaselineOfGitLabHealth.class.st b/src/BaselineOfGitLabHealth/BaselineOfGitLabHealth.class.st index ff8f5af6..5f353c40 100644 --- a/src/BaselineOfGitLabHealth/BaselineOfGitLabHealth.class.st +++ b/src/BaselineOfGitLabHealth/BaselineOfGitLabHealth.class.st @@ -99,8 +99,8 @@ BaselineOfGitLabHealth >> defineGroups: spec [ 'GitLabHealth-Model-Importer' 'GitLabHealth-Model-Importer-Tests' 'GitHubHealth-Model-Importer-Tests' 'GitLabHealth-Model-Analysis' 'GitLabHealth-Model-Analysis-Tests' - 'GitLabHealth-Visualization' - 'GitLabProjectHealth-Model-Importer' + 'GitLabHealth-Visualization' 'GitLabProjectHealth-Model-Importer' + 'GitProjectHealth-Model-Importer-Tests' 'BitBucketHealth-Model-Importer' 'BitBucketHealth-Model-Importer-Tests' ). spec group: 'default' with: #( 'Core' ) From d95e51102029aa182ed136f4810b2fc1244e4b21 Mon Sep 17 00:00:00 2001 From: HLAD Nicolas Date: Fri, 26 Sep 2025 15:27:09 +0200 Subject: [PATCH 41/52] deprecated importBranch to importBranchsOfProject --- .../BitBucketModelImporter.class.st | 26 ++++++++++++ .../GithubModelImporter.class.st | 40 ++++++++++++++++++- .../GitlabModelImporter.class.st | 38 ++++++++++++++++-- .../GitModelImporter.class.st | 6 +++ 4 files changed, 105 insertions(+), 5 deletions(-) diff --git a/src/BitBucketHealth-Model-Importer/BitBucketModelImporter.class.st b/src/BitBucketHealth-Model-Importer/BitBucketModelImporter.class.st index fce27c07..212f06ef 100644 --- a/src/BitBucketHealth-Model-Importer/BitBucketModelImporter.class.st +++ b/src/BitBucketHealth-Model-Importer/BitBucketModelImporter.class.st @@ -189,6 +189,32 @@ BitBucketModelImporter >> importAndLoadLatestsCommitsOfProject: aGLHProject [ { #category : #'import - branches' } BitBucketModelImporter >> importBranchesOf: aGLHProject [ + | branches glhBranches | + self + deprecated: 'Use importBranchesOfProject: instead of current one' + on: '26 September 2025' + in: + 'Pharo-12.0.0+SNAPSHOT.build.1571.sha.cf5fcd22e66957962c97dffc58b0393b7f368147 (64 Bit)'. + branches := self repoApi branches + allWithParams: { } asDictionary + inRepository: aGLHProject id + ofProject: aGLHProject group id. + glhBranches := branches collect: [ :branch | + self + parseBranchIntoGLHBranch: branch + ofProject: aGLHProject ]. + + glhBranches do: [ :glhBranch | + aGLHProject repository addBranch: glhBranch ]. + + self glhModel addAll: glhBranches unless: self blockForBranchEquality. + + ^ glhBranches +] + +{ #category : #'import - branches' } +BitBucketModelImporter >> importBranchesOfProject: aGLHProject [ + | branches glhBranches | branches := self repoApi branches allWithParams: { } asDictionary diff --git a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st index c7c61062..4fb9998e 100644 --- a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st +++ b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st @@ -310,6 +310,11 @@ GithubModelImporter >> importBranchesOf: aGLHProject [ "add the pipeline (actions runs) in the project" | branchesResults foundBranches branches | + self + deprecated: 'Use importBranchesOfProject: instead of current one' + on: '26 September 2025' + in: + 'Pharo-12.0.0+SNAPSHOT.build.1571.sha.cf5fcd22e66957962c97dffc58b0393b7f368147 (64 Bit)'. branchesResults := self repoApi branches getAllForRepo: aGLHProject name ofOwner: aGLHProject group name. @@ -332,8 +337,39 @@ GithubModelImporter >> importBranchesOf: aGLHProject [ self withFiles ifTrue: [ branches do: [ :branch | self importFilesOfBranch: branch ] ]. - - ^branches. + + ^ branches +] + +{ #category : #'import - repositories' } +GithubModelImporter >> importBranchesOfProject: aGLHProject [ + "add the pipeline (actions runs) in the project" + + | branchesResults foundBranches branches | + branchesResults := self repoApi branches + getAllForRepo: aGLHProject name + ofOwner: aGLHProject group name. + + foundBranches := (branchesResults collect: [ :branchesResult | + self parseBranchesResult: branchesResult ]) + flattened. + + + "WARNING: always add branch first into repository, than into model !" + branches := aGLHProject repository branches + addAll: foundBranches + unless: self blockOnNameEquality. + + "branch HEAD commit is not imported by default. use branch ref (sha) to import it specifically" + + branches := self glhModel + addAll: branches + unless: self blockForBranchEquality. + + self withFiles ifTrue: [ + branches do: [ :branch | self importFilesOfBranch: branch ] ]. + + ^ branches ] { #category : #'import - commits' } diff --git a/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st b/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st index f206190d..100edecc 100644 --- a/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st +++ b/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st @@ -607,13 +607,45 @@ GitlabModelImporter >> importBranchesOf: aGLHProject [ | resultBranches branches foundBranches | "aGLHProject repository branches removeAll " + self + deprecated: 'Use importBranchesOfProject: instead of current one' + on: '26 September 2025' + in: + 'Pharo-12.0.0+SNAPSHOT.build.1571.sha.cf5fcd22e66957962c97dffc58b0393b7f368147 (64 Bit)'. resultBranches := self repoApi branches getAllFromProject: aGLHProject id. foundBranches := (resultBranches collect: [ :branchesJson | - self - parseBranchesResult: branchesJson - ]) flattened. + self parseBranchesResult: branchesJson ]) + flattened. + + 'import the branches of project ' recordInfo. + + "WARNING: always add branch first into repository, than into model !" + branches := aGLHProject repository branches + addAll: foundBranches + unless: self blockOnNameEquality. + + + branches := self glhModel + addAll: branches + unless: self blockForBranchEquality. + + "WARNING : branch must load its HEAD commit (ref) in a second time " + ^ branches +] + +{ #category : #'import - branches' } +GitlabModelImporter >> importBranchesOfProject: aGLHProject [ + + | resultBranches branches foundBranches | + "aGLHProject repository branches removeAll " + resultBranches := self repoApi branches getAllFromProject: + aGLHProject id. + + foundBranches := (resultBranches collect: [ :branchesJson | + self parseBranchesResult: branchesJson ]) + flattened. 'import the branches of project ' recordInfo. diff --git a/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st b/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st index cfc7e49f..e911d6c5 100644 --- a/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st +++ b/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st @@ -412,6 +412,12 @@ GitModelImporter >> importBranchesOf: aGLHProject [ ^ self subclassResponsibility ] +{ #category : #'import - repositories' } +GitModelImporter >> importBranchesOfProject: aGLHProject [ + + ^ self subclassResponsibility +] + { #category : #'import - commits' } GitModelImporter >> importCommit: aCommitID ofProject: aGLHProject [ From 4d7d1c74fd8f8fbd366712d1c6e88ca2a0801dfd Mon Sep 17 00:00:00 2001 From: HLAD Nicolas Date: Fri, 26 Sep 2025 16:53:03 +0200 Subject: [PATCH 42/52] fix relation for issues --- .../GithubModelImporter.class.st | 83 +++++++++++++++++++ .../GLHMetamodelGenerator.class.st | 5 +- .../GitModelImporter.class.st | 17 +++- 3 files changed, 99 insertions(+), 6 deletions(-) diff --git a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st index 4fb9998e..b3f27602 100644 --- a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st +++ b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st @@ -163,6 +163,45 @@ GithubModelImporter >> configureReaderForGroup: reader [ do: [ :mapping | mapping mapInstVar: #web_url to: #html_url ] ] +{ #category : #'private - configure reader' } +GithubModelImporter >> configureReaderForIssue: reader [ + + super configureReaderForIssue: reader. + + reader + for: GLHIssue + do: [ :mapping | "mapping mapInstVar: #status to: #conclusion." + (mapping mapInstVar: #created_at) valueSchema: DateAndTime. + (mapping mapInstVar: #updated_at) valueSchema: DateAndTime. + mapping mapInstVar: #name to: #title. + mapping mapInstVar: #description to: #body. + + + mapping + mapProperty: #assignees + getter: [ :object | #ignore ] + setter: [ :issue :values | + values do: [ :item | + issue + cacheAt: #assigneesID + ifPresent: [ :v | v add: (item at: #id) ] + ifAbsentPut: [ + Set new + add: (item at: #id); + yourself ] ] ]. + + + mapping + mapProperty: #user + getter: [ :object | #ignore ] + setter: [ :issue :value | + value ifNotNil: [ + value + at: #id + ifPresent: [ :authorId | + issue cacheAt: #authorID put: (value at: #id) ] ] ] ] +] + { #category : #'private - configure reader' } GithubModelImporter >> configureReaderForJob: reader [ @@ -564,6 +603,44 @@ GithubModelImporter >> importGroup: aGroupName [ ^ groupResult ] +{ #category : #'import - issues' } +GithubModelImporter >> importIssuesOfProject: aGLHProject [ + + | results issues foundIssues | + results := self repoApi issues + getAllForRepo: aGLHProject name + ofOwner: aGLHProject group name + withParms: Dictionary new. + foundIssues := (results collect: [ :result | + self parseIssuesResult: result ]) flattened. + + + issues := OrderedCollection new. + issues := foundIssues collect: [ :issue | + + issue author: + (self importUser: (issue cacheAt: #authorID ifAbsent: [ '' ])). + + issue assignees + addAll: + ((issue cacheAt: #assigneesID ifAbsent: [ { } ]) collect: [ + :assigneeID | self importUser: assigneeID ]) + unless: self blockOnIdEquality. + issue. + + ]. + + + issues := aGLHProject issue + addAll: issues + unless: self blockOnIdEquality. + + glhModel addAll: issues unless: self blockOnIdEquality. + + + ^ aGLHProject issue +] + { #category : #'import - jobs' } GithubModelImporter >> importJobsOfPipeline: aGLHPipeline [ @@ -978,6 +1055,12 @@ GithubModelImporter >> parseGroupResult: aResult [ ^ reader nextAs: GLHGroup ] +{ #category : #parsing } +GithubModelImporter >> parseIssuesResult: result [ + + ^ (generalReader on: result readStream) nextAs: #ArrayOfIssue +] + { #category : #parsing } GithubModelImporter >> parseMergeRequestsResult: response [ diff --git a/src/GitLabHealth-Model-Generator/GLHMetamodelGenerator.class.st b/src/GitLabHealth-Model-Generator/GLHMetamodelGenerator.class.st index 5ffd7613..64d64f73 100644 --- a/src/GitLabHealth-Model-Generator/GLHMetamodelGenerator.class.st +++ b/src/GitLabHealth-Model-Generator/GLHMetamodelGenerator.class.st @@ -367,10 +367,9 @@ GLHMetamodelGenerator >> issueProperties [ { #category : #issues } GLHMetamodelGenerator >> issueRelations [ - (issue property: #project) *-<> (project property: #issue). + issue *-<> project. (issue property: #assignees) <>-* (user property: #assignedIssue). - (issue property: #author) <>- (user property: #createdIssue). - + (issue property: #author) *-<> (user property: #createdIssue) ] { #category : #jobs } diff --git a/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st b/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st index e911d6c5..165980f4 100644 --- a/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st +++ b/src/GitProjectHealth-Model-Importer/GitModelImporter.class.st @@ -261,7 +261,7 @@ GitModelImporter >> configureReaderForGroup: reader [ { #category : #'private - configure reader' } GitModelImporter >> configureReaderForIssue: reader [ - reader mapInstVarsFor: GLHIssue. + reader mapInstVarsFor: GLHIssue . reader for: #ArrayOfIssue @@ -409,6 +409,12 @@ GitModelImporter >> importAuthorOfCommit: aGLHCommit [ { #category : #'import - repositories' } GitModelImporter >> importBranchesOf: aGLHProject [ + self + deprecated: 'Use importBranchesOfProject: instead of current one' + on: '26 September 2025' + in: + 'Pharo-12.0.0+SNAPSHOT.build.1571.sha.cf5fcd22e66957962c97dffc58b0393b7f368147 (64 Bit)'. + ^ self subclassResponsibility ] @@ -653,8 +659,8 @@ GitModelImporter >> initReader [ mapping decoder: [ :string | string ifNil: [ nil ] ifNotNil: [ DateAndTime fromString: string ] ] ]. - configurators := self class selectors select: [ :m | - m beginsWith: #configureReaderFor ]. + configurators := (self class allSelectors select: [ :m | + m beginsWith: #configureReaderFor ]) asSet. configurators do: [ :configureReader | self perform: configureReader with: generalReader ] @@ -729,6 +735,11 @@ GitModelImporter >> parseDiffString: aDiff [ ^ aDiff diffRanges ] +{ #category : #parsing } +GitModelImporter >> parseIssuesResult: aString [ + self subclassResponsibility +] + { #category : #accessing } GitModelImporter >> repoApi [ From ad307d73e9ad4ca45be11ec710e6e3a89ad2124c Mon Sep 17 00:00:00 2001 From: HLAD Nicolas Date: Fri, 26 Sep 2025 16:53:59 +0200 Subject: [PATCH 43/52] regenerate metamodel --- src/GitLabHealth-Model/GLHIssue.class.st | 11 ++++---- src/GitLabHealth-Model/GLHProject.class.st | 22 +++++++-------- src/GitLabHealth-Model/GLHUser.class.st | 17 +++++++----- .../GLHCommit.extension.st | 20 -------------- .../GLHMergeRequest.extension.st | 27 ------------------- .../GPJCModel.class.st | 16 +++++------ .../JPIssue.extension.st | 10 +++---- src/GitProject-JiraConnector-Model/package.st | 2 +- 8 files changed, 41 insertions(+), 84 deletions(-) delete mode 100644 src/GitProject-JiraConnector-Model/GLHCommit.extension.st delete mode 100644 src/GitProject-JiraConnector-Model/GLHMergeRequest.extension.st diff --git a/src/GitLabHealth-Model/GLHIssue.class.st b/src/GitLabHealth-Model/GLHIssue.class.st index 20a52a29..2d6fc7bb 100644 --- a/src/GitLabHealth-Model/GLHIssue.class.st +++ b/src/GitLabHealth-Model/GLHIssue.class.st @@ -7,14 +7,14 @@ an Issues help collaboration within a team to plan, track, and deliver work ### Parents | Relation | Origin | Opposite | Type | Comment | |---| +| `author` | `GLHIssue` | `createdIssue` | `GLHUser` | | | `milestone` | `GLHIssue` | `issue` | `GLHMilestone` | | -| `project` | `GLHIssue` | `issue` | `GLHProject` | | +| `project` | `GLHIssue` | `issues` | `GLHProject` | | ### Children | Relation | Origin | Opposite | Type | Comment | |---| | `assignees` | `GLHIssue` | `assignedIssue` | `GLHUser` | | -| `author` | `GLHIssue` | `createdIssue` | `GLHUser` | | ## Properties @@ -27,8 +27,8 @@ an Issues help collaboration within a team to plan, track, and deliver work | `description` | `String` | nil | | | `due_date` | `Object` | nil | | | `id` | `Number` | nil | | -| `name` | `String` | nil | | | `name` | `String` | nil | Basic name of the entity, not full reference.| +| `name` | `String` | nil | | | `state` | `String` | nil | | | `updated_at` | `Object` | nil | | @@ -47,7 +47,7 @@ Class { '#updated_at => FMProperty', '#closed_at => FMProperty', '#due_date => FMProperty', - '#project => FMOne type: #GLHProject opposite: #issue', + '#project => FMOne type: #GLHProject opposite: #issues', '#assignees => FMMany type: #GLHUser opposite: #assignedIssue', '#author => FMOne type: #GLHUser opposite: #createdIssue', '#milestone => FMOne type: #GLHMilestone opposite: #issue' @@ -98,6 +98,7 @@ GLHIssue >> author [ "Relation named: #author type: #GLHUser opposite: #createdIssue" + ^ author ] @@ -224,7 +225,7 @@ GLHIssue >> name: anObject [ { #category : #accessing } GLHIssue >> project [ - "Relation named: #project type: #GLHProject opposite: #issue" + "Relation named: #project type: #GLHProject opposite: #issues" diff --git a/src/GitLabHealth-Model/GLHProject.class.st b/src/GitLabHealth-Model/GLHProject.class.st index 2acb8fc9..26cecc34 100644 --- a/src/GitLabHealth-Model/GLHProject.class.st +++ b/src/GitLabHealth-Model/GLHProject.class.st @@ -12,7 +12,7 @@ A GitLab Project ### Children | Relation | Origin | Opposite | Type | Comment | |---| -| `issue` | `GLHProject` | `project` | `GLHIssue` | | +| `issues` | `GLHProject` | `project` | `GLHIssue` | | | `mergeRequests` | `GLHProject` | `project` | `GLHMergeRequest` | | | `milestone` | `GLHProject` | `project` | `GLHMilestone` | | | `pipelines` | `GLHProject` | `project` | `GLHPipeline` | | @@ -63,7 +63,7 @@ Class { '#contributors => FMMany type: #GLHUser opposite: #contributedProjects', '#repository => FMOne type: #GLHRepository opposite: #project', '#releases => FMMany type: #GLHRelease opposite: #project', - '#issue => FMMany type: #GLHIssue opposite: #project', + '#issues => FMMany type: #GLHIssue opposite: #project', '#mergeRequests => FMMany type: #GLHMergeRequest opposite: #project', '#milestone => FMMany type: #GLHMilestone opposite: #project' ], @@ -88,7 +88,7 @@ GLHProject >> addContributor: anObject [ { #category : #adding } GLHProject >> addIssue: anObject [ - ^ self issue add: anObject + ^ self issues add: anObject ] { #category : #adding } @@ -240,26 +240,26 @@ GLHProject >> id: anObject [ ] { #category : #accessing } -GLHProject >> issue [ - "Relation named: #issue type: #GLHIssue opposite: #project" +GLHProject >> issues [ + "Relation named: #issues type: #GLHIssue opposite: #project" - ^ issue + ^ issues ] { #category : #accessing } -GLHProject >> issue: anObject [ +GLHProject >> issues: anObject [ - issue value: anObject + issues value: anObject ] { #category : #navigation } -GLHProject >> issueGroup [ +GLHProject >> issuesGroup [ - - ^ MooseSpecializedGroup withAll: self issue asSet + + ^ MooseSpecializedGroup withAll: self issues asSet ] { #category : #accessing } diff --git a/src/GitLabHealth-Model/GLHUser.class.st b/src/GitLabHealth-Model/GLHUser.class.st index fbd051dd..d6648af4 100644 --- a/src/GitLabHealth-Model/GLHUser.class.st +++ b/src/GitLabHealth-Model/GLHUser.class.st @@ -8,13 +8,13 @@ A GitLab User | Relation | Origin | Opposite | Type | Comment | |---| | `assignedIssue` | `GLHUser` | `assignees` | `GLHIssue` | | -| `createdIssue` | `GLHUser` | `author` | `GLHIssue` | | | `createdMilestone` | `GLHUser` | `author` | `GLHMilestone` | | ### Children | Relation | Origin | Opposite | Type | Comment | |---| | `commits` | `GLHUser` | `commitCreator` | `GLHCommit` | | +| `createdIssue` | `GLHUser` | `author` | `GLHIssue` | | | `jobs` | `GLHUser` | `user` | `GLHJob` | | | `releases` | `GLHUser` | `author` | `GLHRelease` | | @@ -51,8 +51,8 @@ A GitLab User | `job_title` | `String` | nil | | | `linkedin` | `String` | nil | | | `location` | `String` | nil | | -| `name` | `String` | nil | | | `name` | `String` | nil | Basic name of the entity, not full reference.| +| `name` | `String` | nil | | | `organization` | `String` | nil | | | `pronouns` | `String` | nil | | | `public_email` | `String` | nil | | @@ -101,7 +101,7 @@ Class { '#contributedProjects => FMMany type: #GLHProject opposite: #contributors', '#releases => FMMany type: #GLHRelease opposite: #author', '#assignedIssue => FMOne type: #GLHIssue opposite: #assignees', - '#createdIssue => FMOne type: #GLHIssue opposite: #author', + '#createdIssue => FMMany type: #GLHIssue opposite: #author', '#createdMergeRequests => FMMany type: #GLHMergeRequest opposite: #author', '#approcheMergeRequests => FMMany type: #GLHMergeRequest opposite: #approved_by', '#usedMerges => FMMany type: #GLHMergeRequest opposite: #merge_user', @@ -154,6 +154,12 @@ GLHUser >> addContributedProject: anObject [ ^ self contributedProjects add: anObject ] +{ #category : #adding } +GLHUser >> addCreatedIssue: anObject [ + + ^ self createdIssue add: anObject +] + { #category : #adding } GLHUser >> addCreatedMergeRequest: anObject [ @@ -376,7 +382,6 @@ GLHUser >> createdIssue [ "Relation named: #createdIssue type: #GLHIssue opposite: #author" - ^ createdIssue ] @@ -385,14 +390,14 @@ GLHUser >> createdIssue [ GLHUser >> createdIssue: anObject [ - createdIssue := anObject + createdIssue value: anObject ] { #category : #navigation } GLHUser >> createdIssueGroup [ - ^ MooseSpecializedGroup with: self createdIssue + ^ MooseSpecializedGroup withAll: self createdIssue asSet ] { #category : #accessing } diff --git a/src/GitProject-JiraConnector-Model/GLHCommit.extension.st b/src/GitProject-JiraConnector-Model/GLHCommit.extension.st deleted file mode 100644 index 5cb60994..00000000 --- a/src/GitProject-JiraConnector-Model/GLHCommit.extension.st +++ /dev/null @@ -1,20 +0,0 @@ -Extension { #name : 'GLHCommit' } - -{ #category : '*GitProject-JiraConnector-Model-accessing' } -GLHCommit >> jiraIssue [ - "Relation named: #jiraIssue type: #JPIssue opposite: #commits" - - - - - - - ^ self attributeAt: #jiraIssue ifAbsent: [ nil ] -] - -{ #category : '*GitProject-JiraConnector-Model-accessing' } -GLHCommit >> jiraIssue: anObject [ - - - self attributeAt: #jiraIssue put: (FMMultivalueLink on: self update: #commits from: self jiraIssue to: anObject). -] diff --git a/src/GitProject-JiraConnector-Model/GLHMergeRequest.extension.st b/src/GitProject-JiraConnector-Model/GLHMergeRequest.extension.st deleted file mode 100644 index de5fbc45..00000000 --- a/src/GitProject-JiraConnector-Model/GLHMergeRequest.extension.st +++ /dev/null @@ -1,27 +0,0 @@ -Extension { #name : 'GLHMergeRequest' } - -{ #category : '*GitProject-JiraConnector-Model-accessing' } -GLHMergeRequest >> jiraIssue [ - "Relation named: #jiraIssue type: #JPIssue opposite: #mergeRequest" - - - - - - - ^ self attributeAt: #jiraIssue ifAbsent: [ nil ] -] - -{ #category : '*GitProject-JiraConnector-Model-accessing' } -GLHMergeRequest >> jiraIssue: anObject [ - - - (self attributeAt: #jiraIssue ifAbsentPut: [nil]) == anObject ifTrue: [ ^ anObject ]. - anObject ifNil: [ | otherSide | - otherSide := self jiraIssue. - self attributeAt: #jiraIssue put: anObject. - otherSide mergeRequest: nil ] - ifNotNil: [ - self attributeAt: #jiraIssue put: anObject. - anObject mergeRequest: self ] -] diff --git a/src/GitProject-JiraConnector-Model/GPJCModel.class.st b/src/GitProject-JiraConnector-Model/GPJCModel.class.st index e37f5b9a..0a974fcd 100644 --- a/src/GitProject-JiraConnector-Model/GPJCModel.class.st +++ b/src/GitProject-JiraConnector-Model/GPJCModel.class.st @@ -1,20 +1,18 @@ Class { - #name : 'GPJCModel', - #superclass : 'MooseModel', - #traits : 'GLHTEntityCreator + JPTEntityCreator', - #classTraits : 'GLHTEntityCreator classTrait + JPTEntityCreator classTrait', - #category : 'GitProject-JiraConnector-Model-Model', - #package : 'GitProject-JiraConnector-Model', - #tag : 'Model' + #name : #GPJCModel, + #superclass : #MooseModel, + #traits : 'JPTEntityCreator', + #classTraits : 'JPTEntityCreator classTrait', + #category : #'GitProject-JiraConnector-Model-Model' } -{ #category : 'accessing' } +{ #category : #accessing } GPJCModel class >> allSubmetamodelsPackagesNames [ ^ #(#'Moose-Query' #'JiraPharoAPI-Model' #'GitLabHealth-Model' #'Famix-Traits') ] -{ #category : 'meta' } +{ #category : #meta } GPJCModel class >> annotation [ diff --git a/src/GitProject-JiraConnector-Model/JPIssue.extension.st b/src/GitProject-JiraConnector-Model/JPIssue.extension.st index cf35aaca..9b4b769a 100644 --- a/src/GitProject-JiraConnector-Model/JPIssue.extension.st +++ b/src/GitProject-JiraConnector-Model/JPIssue.extension.st @@ -1,6 +1,6 @@ -Extension { #name : 'JPIssue' } +Extension { #name : #JPIssue } -{ #category : '*GitProject-JiraConnector-Model-accessing' } +{ #category : #'*GitProject-JiraConnector-Model-accessing' } JPIssue >> commits [ "Relation named: #commits type: #GLHCommit opposite: #jiraIssue" @@ -12,14 +12,14 @@ JPIssue >> commits [ ^ self attributeAt: #commits ifAbsentPut: [ FMMultivalueLink on: self opposite: #jiraIssue: ] ] -{ #category : '*GitProject-JiraConnector-Model-accessing' } +{ #category : #'*GitProject-JiraConnector-Model-accessing' } JPIssue >> commits: anObject [ self commits value: anObject ] -{ #category : '*GitProject-JiraConnector-Model-accessing' } +{ #category : #'*GitProject-JiraConnector-Model-accessing' } JPIssue >> mergeRequest [ "Relation named: #mergeRequest type: #GLHMergeRequest opposite: #jiraIssue" @@ -31,7 +31,7 @@ JPIssue >> mergeRequest [ ^ self attributeAt: #mergeRequest ifAbsent: [ nil ] ] -{ #category : '*GitProject-JiraConnector-Model-accessing' } +{ #category : #'*GitProject-JiraConnector-Model-accessing' } JPIssue >> mergeRequest: anObject [ diff --git a/src/GitProject-JiraConnector-Model/package.st b/src/GitProject-JiraConnector-Model/package.st index 9b69c19b..1ab2344b 100644 --- a/src/GitProject-JiraConnector-Model/package.st +++ b/src/GitProject-JiraConnector-Model/package.st @@ -1 +1 @@ -Package { #name : 'GitProject-JiraConnector-Model' } +Package { #name : #'GitProject-JiraConnector-Model' } From 677096ed65fd8f849a4e76fd1249323f5bc94665 Mon Sep 17 00:00:00 2001 From: HLAD Nicolas Date: Fri, 26 Sep 2025 16:55:34 +0200 Subject: [PATCH 44/52] add issue to github import --- src/GitHubHealth-Model-Importer/GithubModelImporter.class.st | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st index b3f27602..2f0037cc 100644 --- a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st +++ b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st @@ -631,14 +631,14 @@ GithubModelImporter >> importIssuesOfProject: aGLHProject [ ]. - issues := aGLHProject issue + issues := aGLHProject issues addAll: issues unless: self blockOnIdEquality. glhModel addAll: issues unless: self blockOnIdEquality. - ^ aGLHProject issue + ^ aGLHProject issues ] { #category : #'import - jobs' } From d1f96fd431a77b8664cc82b0d34d413e3acbb10a Mon Sep 17 00:00:00 2001 From: nhlad Date: Fri, 26 Sep 2025 16:57:41 +0200 Subject: [PATCH 45/52] Update src/GitHubHealth-Model-Importer/GithubModelImporter.class.st Co-authored-by: Benoit Verhaeghe --- src/GitHubHealth-Model-Importer/GithubModelImporter.class.st | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st index 2f0037cc..2fa6576c 100644 --- a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st +++ b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st @@ -344,7 +344,7 @@ GithubModelImporter >> ensureGroupNamed: aGroupName [ ifNone: [ self glhModel newGroupNamed: aGroupName ] ] -{ #category : #'import - repositories' } +{ #category : #'import - branches' } GithubModelImporter >> importBranchesOf: aGLHProject [ "add the pipeline (actions runs) in the project" From 33d7c187202f98d3661f7e695d91ec45d7fcb72d Mon Sep 17 00:00:00 2001 From: nhlad Date: Fri, 26 Sep 2025 16:58:36 +0200 Subject: [PATCH 46/52] Update src/GitHubHealth-Model-Importer/GithubModelImporter.class.st Co-authored-by: Benoit Verhaeghe --- src/GitHubHealth-Model-Importer/GithubModelImporter.class.st | 1 - 1 file changed, 1 deletion(-) diff --git a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st index 2fa6576c..127a9bb6 100644 --- a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st +++ b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st @@ -238,7 +238,6 @@ GithubModelImporter >> configureReaderForJob: reader [ { #category : #'private - configure reader' } GithubModelImporter >> configureReaderForMergeRequest: reader [ - " reader mapInstVarsFor: GLHProject. " super configureReaderForMergeRequest: reader. From 4b4c10894c8a99815ed91f7dda4863257894611a Mon Sep 17 00:00:00 2001 From: nhlad Date: Fri, 26 Sep 2025 16:58:51 +0200 Subject: [PATCH 47/52] Update src/GitHubHealth-Model-Importer/GithubModelImporter.class.st Co-authored-by: Benoit Verhaeghe --- src/GitHubHealth-Model-Importer/GithubModelImporter.class.st | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st index 127a9bb6..6373acc5 100644 --- a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st +++ b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st @@ -523,7 +523,7 @@ GithubModelImporter >> importDiffOfCommit: aGLHCommit [ diffs := aGLHCommit diffs addAll: diffs unless: self blockForDiffRangeEquality. - diffs := glhModel + glhModel addAll: diffs unless: self blockForDiffRangeEquality. From 827a2a85effa94bdca8c040892efea4c972dc8fb Mon Sep 17 00:00:00 2001 From: nhlad Date: Fri, 26 Sep 2025 16:59:02 +0200 Subject: [PATCH 48/52] Update src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st Co-authored-by: Benoit Verhaeghe --- src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st b/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st index 100edecc..f5ab39d5 100644 --- a/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st +++ b/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st @@ -1076,7 +1076,7 @@ GitlabModelImporter >> importFilesOfBranch: aBranch [ thenCollect: [ :file | self importDirectoryFiles: file OfBranch: aBranch ]. - ^files. + ^ files ] { #category : #'import - groups' } From 7d9073a9020563fca632d9773f52b188bf53bb54 Mon Sep 17 00:00:00 2001 From: nhlad Date: Fri, 26 Sep 2025 16:59:12 +0200 Subject: [PATCH 49/52] Update src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st Co-authored-by: Benoit Verhaeghe --- src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st b/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st index f5ab39d5..a0006833 100644 --- a/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st +++ b/src/GitLabHealth-Model-Importer/GitlabModelImporter.class.st @@ -1048,7 +1048,7 @@ GitlabModelImporter >> importDirectoryFiles: aDirectoryFile OfBranch: aBranch [ { #category : #'import - file' } GitlabModelImporter >> importFileWithPath: aPath ofProject: aGLHProject inBranch: aBranch [ - self flag: 'imported file need need to be store inside the model'. + self flag: 'imported file need to be store inside the model'. ^ self repoApi repositories getRawFile: aPath ofProject: aGLHProject id withParams: {#ref -> aBranch name} asDictionary . ] From 18803e5b5444115fec897ea316320ecc2a91dafd Mon Sep 17 00:00:00 2001 From: nhlad Date: Fri, 26 Sep 2025 16:59:40 +0200 Subject: [PATCH 50/52] Update src/GitHubHealth-Model-Importer/GithubModelImporter.class.st Co-authored-by: Benoit Verhaeghe --- src/GitHubHealth-Model-Importer/GithubModelImporter.class.st | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st index 6373acc5..f22ac0aa 100644 --- a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st +++ b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st @@ -700,10 +700,10 @@ GithubModelImporter >> importLatestMergeRequestsOfProject: aGLHProject [ results := self repoApi pullRequests getLatestForRepo: aGLHProject name ofOwner: aGLHProject group name. parsedResults := self parseMergeRequestsResult: results. - parsedResults := glhModel + parsedResults := aGLHProject mergeRequests addAll: parsedResults unless: self blockOnIdEquality. - parsedResults := aGLHProject mergeRequests + parsedResults := glhModel addAll: parsedResults unless: self blockOnIdEquality. ^ parsedResults From 4c9c4027aaef85a2f49c61785045e9a3ef7bd9fc Mon Sep 17 00:00:00 2001 From: nhlad Date: Fri, 26 Sep 2025 17:00:04 +0200 Subject: [PATCH 51/52] Update src/GitHubHealth-Model-Importer/GithubModelImporter.class.st Co-authored-by: Benoit Verhaeghe --- src/GitHubHealth-Model-Importer/GithubModelImporter.class.st | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st index f22ac0aa..9cedd63d 100644 --- a/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st +++ b/src/GitHubHealth-Model-Importer/GithubModelImporter.class.st @@ -544,7 +544,7 @@ GithubModelImporter >> importDiffOfMergeRequest: aGLHMergeRequest [ unless: self blockForDiffEquality. aGLHMergeRequest diffs do: [ :diff | self importDiffRangesForDiff: diff ]. - ^ aGLHMergeRequest diffs. + ^ aGLHMergeRequest diffs ] { #category : #'import - files' } From 47f5f84273413670af759f9921dbdcc0a84cdb7f Mon Sep 17 00:00:00 2001 From: HLAD Nicolas Date: Wed, 1 Oct 2025 09:30:47 +0200 Subject: [PATCH 52/52] re-add jira to commit connection --- .../GLHCommit.extension.st | 20 ++++++++++++++ .../GLHMergeRequest.extension.st | 27 +++++++++++++++++++ .../GPJCModel.class.st | 4 +-- 3 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 src/GitProject-JiraConnector-Model/GLHCommit.extension.st create mode 100644 src/GitProject-JiraConnector-Model/GLHMergeRequest.extension.st diff --git a/src/GitProject-JiraConnector-Model/GLHCommit.extension.st b/src/GitProject-JiraConnector-Model/GLHCommit.extension.st new file mode 100644 index 00000000..b06d3468 --- /dev/null +++ b/src/GitProject-JiraConnector-Model/GLHCommit.extension.st @@ -0,0 +1,20 @@ +Extension { #name : #GLHCommit } + +{ #category : #'*GitProject-JiraConnector-Model-accessing' } +GLHCommit >> jiraIssue [ + "Relation named: #jiraIssue type: #JPIssue opposite: #commits" + + + + + + + ^ self attributeAt: #jiraIssue ifAbsent: [ nil ] +] + +{ #category : #'*GitProject-JiraConnector-Model-accessing' } +GLHCommit >> jiraIssue: anObject [ + + + self attributeAt: #jiraIssue put: (FMMultivalueLink on: self update: #commits from: self jiraIssue to: anObject). +] diff --git a/src/GitProject-JiraConnector-Model/GLHMergeRequest.extension.st b/src/GitProject-JiraConnector-Model/GLHMergeRequest.extension.st new file mode 100644 index 00000000..481e8502 --- /dev/null +++ b/src/GitProject-JiraConnector-Model/GLHMergeRequest.extension.st @@ -0,0 +1,27 @@ +Extension { #name : #GLHMergeRequest } + +{ #category : #'*GitProject-JiraConnector-Model-accessing' } +GLHMergeRequest >> jiraIssue [ + "Relation named: #jiraIssue type: #JPIssue opposite: #mergeRequest" + + + + + + + ^ self attributeAt: #jiraIssue ifAbsent: [ nil ] +] + +{ #category : #'*GitProject-JiraConnector-Model-accessing' } +GLHMergeRequest >> jiraIssue: anObject [ + + + (self attributeAt: #jiraIssue ifAbsentPut: [nil]) == anObject ifTrue: [ ^ anObject ]. + anObject ifNil: [ | otherSide | + otherSide := self jiraIssue. + self attributeAt: #jiraIssue put: anObject. + otherSide mergeRequest: nil ] + ifNotNil: [ + self attributeAt: #jiraIssue put: anObject. + anObject mergeRequest: self ] +] diff --git a/src/GitProject-JiraConnector-Model/GPJCModel.class.st b/src/GitProject-JiraConnector-Model/GPJCModel.class.st index 0a974fcd..11843ad3 100644 --- a/src/GitProject-JiraConnector-Model/GPJCModel.class.st +++ b/src/GitProject-JiraConnector-Model/GPJCModel.class.st @@ -1,8 +1,8 @@ Class { #name : #GPJCModel, #superclass : #MooseModel, - #traits : 'JPTEntityCreator', - #classTraits : 'JPTEntityCreator classTrait', + #traits : 'GLHTEntityCreator + JPTEntityCreator', + #classTraits : 'GLHTEntityCreator classTrait + JPTEntityCreator classTrait', #category : #'GitProject-JiraConnector-Model-Model' }