This is an automated email from the ASF dual-hosted git repository.

klesh pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-devlake.git


The following commit(s) were added to refs/heads/main by this push:
     new a21382acc fix(gitlab): add missing repos scope in project_mapping 
(#8743)
a21382acc is described below

commit a21382accbcccbf7ae7d9e2d3558a07cc4301afc
Author: Spiff Azeta <[email protected]>
AuthorDate: Mon Mar 2 14:11:40 2026 +0100

    fix(gitlab): add missing repos scope in project_mapping (#8743)
    
    GitLab's makeScopeV200 did not create a repos scope when
    scopeConfig.Entities was empty or only contained CROSS. This
    caused project_mapping to have no table='repos' row, breaking
    downstream DORA metrics, PR-issue linking, and all PR dashboard
    panels that join on project_mapping.
    
    The fix aligns GitLab with the GitHub plugin by:
    1. Defaulting empty entities to plugin.DOMAIN_TYPES
    2. Adding DOMAIN_TYPE_CROSS to the repo scope condition
    
    Closes #8742
    
    Co-authored-by: Spiff Azeta <[email protected]>
---
 backend/plugins/gitlab/api/blueprint_V200_test.go | 64 +++++++++++++++++++++++
 backend/plugins/gitlab/api/blueprint_v200.go      |  8 ++-
 2 files changed, 71 insertions(+), 1 deletion(-)

diff --git a/backend/plugins/gitlab/api/blueprint_V200_test.go 
b/backend/plugins/gitlab/api/blueprint_V200_test.go
index 34f1175de..fde792ffd 100644
--- a/backend/plugins/gitlab/api/blueprint_V200_test.go
+++ b/backend/plugins/gitlab/api/blueprint_V200_test.go
@@ -72,6 +72,70 @@ func TestMakeScopes(t *testing.T) {
        assert.Equal(t, actualScopes[2].ScopeId(), expectDomainScopeId)
 }
 
+func TestMakeScopesWithEmptyEntities(t *testing.T) {
+       mockGitlabPlugin(t)
+
+       const connectionId = 1
+       const gitlabProjectId = 37
+       const expectDomainScopeId = "gitlab:GitlabProject:1:37"
+
+       actualScopes, err := makeScopeV200(
+               connectionId,
+               []*srvhelper.ScopeDetail[models.GitlabProject, 
models.GitlabScopeConfig]{
+                       {
+                               Scope: models.GitlabProject{
+                                       Scope: common.Scope{
+                                               ConnectionId: connectionId,
+                                       },
+                                       GitlabId: gitlabProjectId,
+                               },
+                               ScopeConfig: &models.GitlabScopeConfig{
+                                       ScopeConfig: common.ScopeConfig{
+                                               Entities: []string{},
+                                       },
+                               },
+                       },
+               },
+       )
+       assert.Nil(t, err)
+       // empty entities should default to all domain types, producing repo + 
cicd + board scopes
+       assert.Equal(t, 3, len(actualScopes))
+       assert.Equal(t, actualScopes[0].ScopeId(), expectDomainScopeId)
+}
+
+func TestMakeScopesWithCrossEntity(t *testing.T) {
+       mockGitlabPlugin(t)
+
+       const connectionId = 1
+       const gitlabProjectId = 37
+       const expectDomainScopeId = "gitlab:GitlabProject:1:37"
+
+       actualScopes, err := makeScopeV200(
+               connectionId,
+               []*srvhelper.ScopeDetail[models.GitlabProject, 
models.GitlabScopeConfig]{
+                       {
+                               Scope: models.GitlabProject{
+                                       Scope: common.Scope{
+                                               ConnectionId: connectionId,
+                                       },
+                                       GitlabId: gitlabProjectId,
+                               },
+                               ScopeConfig: &models.GitlabScopeConfig{
+                                       ScopeConfig: common.ScopeConfig{
+                                               Entities: 
[]string{plugin.DOMAIN_TYPE_CROSS, plugin.DOMAIN_TYPE_TICKET},
+                                       },
+                               },
+                       },
+               },
+       )
+       assert.Nil(t, err)
+       // CROSS entity should trigger repo scope creation, plus ticket = board 
scope
+       assert.Equal(t, 2, len(actualScopes))
+       assert.Equal(t, actualScopes[0].ScopeId(), expectDomainScopeId)
+       assert.Equal(t, "repos", actualScopes[0].TableName())
+       assert.Equal(t, "boards", actualScopes[1].TableName())
+}
+
 func TestMakeDataSourcePipelinePlanV200(t *testing.T) {
        mockGitlabPlugin(t)
 
diff --git a/backend/plugins/gitlab/api/blueprint_v200.go 
b/backend/plugins/gitlab/api/blueprint_v200.go
index dbe14905d..515e8967f 100644
--- a/backend/plugins/gitlab/api/blueprint_v200.go
+++ b/backend/plugins/gitlab/api/blueprint_v200.go
@@ -78,8 +78,14 @@ func makeScopeV200(
                gitlabProject, scopeConfig := scope.Scope, scope.ScopeConfig
                id := 
didgen.NewDomainIdGenerator(&models.GitlabProject{}).Generate(connectionId, 
gitlabProject.GitlabId)
 
+               // if no entities specified, use all entities enabled by default
+               if len(scopeConfig.Entities) == 0 {
+                       scopeConfig.Entities = plugin.DOMAIN_TYPES
+               }
+
                if utils.StringsContains(scopeConfig.Entities, 
plugin.DOMAIN_TYPE_CODE_REVIEW) ||
-                       utils.StringsContains(scopeConfig.Entities, 
plugin.DOMAIN_TYPE_CODE) {
+                       utils.StringsContains(scopeConfig.Entities, 
plugin.DOMAIN_TYPE_CODE) ||
+                       utils.StringsContains(scopeConfig.Entities, 
plugin.DOMAIN_TYPE_CROSS) {
                        // if we don't need to collect gitex, we need to add 
repo to scopes here
                        scopeRepo := code.NewRepo(id, 
gitlabProject.PathWithNamespace)
 

Reply via email to