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 628e35833 fix(bitbucket): default empty entities to all domain types 
in makeScopesV200 (#8750)
628e35833 is described below

commit 628e35833e3a9a1e37db147c09791c657f616081
Author: Spiff Azeta <[email protected]>
AuthorDate: Fri Mar 6 08:04:27 2026 +0100

    fix(bitbucket): default empty entities to all domain types in 
makeScopesV200 (#8750)
    
    When scopeConfig.Entities is empty (common when no entities are
    explicitly selected in the UI), makeScopesV200 produced zero scopes,
    leaving project_mapping with no repo rows. This adds the same
    empty-entities default applied to GitLab in #8743.
    
    Closes #8748
---
 backend/plugins/bitbucket/api/blueprint_v200.go    |   5 +
 .../plugins/bitbucket/api/blueprint_v200_test.go   | 153 +++++++++++++++++++++
 2 files changed, 158 insertions(+)

diff --git a/backend/plugins/bitbucket/api/blueprint_v200.go 
b/backend/plugins/bitbucket/api/blueprint_v200.go
index 0e2477e80..6fedb0df2 100644
--- a/backend/plugins/bitbucket/api/blueprint_v200.go
+++ b/backend/plugins/bitbucket/api/blueprint_v200.go
@@ -154,6 +154,11 @@ func makeScopesV200(
                scope, scopeConfig := scopeDetail.Scope, scopeDetail.ScopeConfig
                id := idgen.Generate(connection.ID, scope.BitbucketId)
 
+               // 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_CROSS) {
diff --git a/backend/plugins/bitbucket/api/blueprint_v200_test.go 
b/backend/plugins/bitbucket/api/blueprint_v200_test.go
new file mode 100644
index 000000000..cd46decc2
--- /dev/null
+++ b/backend/plugins/bitbucket/api/blueprint_v200_test.go
@@ -0,0 +1,153 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package api
+
+import (
+       "testing"
+
+       mockplugin "github.com/apache/incubator-devlake/mocks/core/plugin"
+
+       "github.com/apache/incubator-devlake/core/models/common"
+       "github.com/apache/incubator-devlake/core/plugin"
+       "github.com/apache/incubator-devlake/helpers/pluginhelper/api"
+       "github.com/apache/incubator-devlake/helpers/srvhelper"
+       "github.com/apache/incubator-devlake/plugins/bitbucket/models"
+       "github.com/stretchr/testify/assert"
+)
+
+func mockBitbucketPlugin(t *testing.T) {
+       mockMeta := mockplugin.NewPluginMeta(t)
+       
mockMeta.On("RootPkgPath").Return("github.com/apache/incubator-devlake/plugins/bitbucket")
+       mockMeta.On("Name").Return("dummy").Maybe()
+       err := plugin.RegisterPlugin("bitbucket", mockMeta)
+       assert.Equal(t, err, nil)
+}
+
+func TestMakeScopes(t *testing.T) {
+       mockBitbucketPlugin(t)
+
+       const connectionId uint64 = 1
+       const bitbucketId = "owner/repo"
+       const expectDomainScopeId = "bitbucket:BitbucketRepo:1:owner/repo"
+
+       actualScopes, err := makeScopesV200(
+               []*srvhelper.ScopeDetail[models.BitbucketRepo, 
models.BitbucketScopeConfig]{
+                       {
+                               Scope: models.BitbucketRepo{
+                                       Scope: common.Scope{
+                                               ConnectionId: connectionId,
+                                       },
+                                       BitbucketId: bitbucketId,
+                               },
+                               ScopeConfig: &models.BitbucketScopeConfig{
+                                       ScopeConfig: common.ScopeConfig{
+                                               Entities: 
[]string{plugin.DOMAIN_TYPE_CODE, plugin.DOMAIN_TYPE_TICKET, 
plugin.DOMAIN_TYPE_CICD},
+                                       },
+                               },
+                       },
+               },
+               &models.BitbucketConnection{
+                       BaseConnection: api.BaseConnection{
+                               Model: common.Model{
+                                       ID: connectionId,
+                               },
+                       },
+               },
+       )
+       assert.Nil(t, err)
+       assert.Equal(t, 3, len(actualScopes))
+       assert.Equal(t, expectDomainScopeId, actualScopes[0].ScopeId())
+       assert.Equal(t, expectDomainScopeId, actualScopes[1].ScopeId())
+       assert.Equal(t, expectDomainScopeId, actualScopes[2].ScopeId())
+}
+
+func TestMakeScopesWithEmptyEntities(t *testing.T) {
+       mockBitbucketPlugin(t)
+
+       const connectionId uint64 = 1
+       const bitbucketId = "owner/repo"
+       const expectDomainScopeId = "bitbucket:BitbucketRepo:1:owner/repo"
+
+       actualScopes, err := makeScopesV200(
+               []*srvhelper.ScopeDetail[models.BitbucketRepo, 
models.BitbucketScopeConfig]{
+                       {
+                               Scope: models.BitbucketRepo{
+                                       Scope: common.Scope{
+                                               ConnectionId: connectionId,
+                                       },
+                                       BitbucketId: bitbucketId,
+                               },
+                               ScopeConfig: &models.BitbucketScopeConfig{
+                                       ScopeConfig: common.ScopeConfig{
+                                               Entities: []string{},
+                                       },
+                               },
+                       },
+               },
+               &models.BitbucketConnection{
+                       BaseConnection: api.BaseConnection{
+                               Model: common.Model{
+                                       ID: connectionId,
+                               },
+                       },
+               },
+       )
+       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, expectDomainScopeId, actualScopes[0].ScopeId())
+}
+
+func TestMakeScopesWithCrossEntity(t *testing.T) {
+       mockBitbucketPlugin(t)
+
+       const connectionId uint64 = 1
+       const bitbucketId = "owner/repo"
+       const expectDomainScopeId = "bitbucket:BitbucketRepo:1:owner/repo"
+
+       actualScopes, err := makeScopesV200(
+               []*srvhelper.ScopeDetail[models.BitbucketRepo, 
models.BitbucketScopeConfig]{
+                       {
+                               Scope: models.BitbucketRepo{
+                                       Scope: common.Scope{
+                                               ConnectionId: connectionId,
+                                       },
+                                       BitbucketId: bitbucketId,
+                               },
+                               ScopeConfig: &models.BitbucketScopeConfig{
+                                       ScopeConfig: common.ScopeConfig{
+                                               Entities: 
[]string{plugin.DOMAIN_TYPE_CROSS, plugin.DOMAIN_TYPE_TICKET},
+                                       },
+                               },
+                       },
+               },
+               &models.BitbucketConnection{
+                       BaseConnection: api.BaseConnection{
+                               Model: common.Model{
+                                       ID: connectionId,
+                               },
+                       },
+               },
+       )
+       assert.Nil(t, err)
+       // CROSS entity should trigger repo scope creation, plus ticket = board 
scope
+       assert.Equal(t, 2, len(actualScopes))
+       assert.Equal(t, expectDomainScopeId, actualScopes[0].ScopeId())
+       assert.Equal(t, "repos", actualScopes[0].TableName())
+       assert.Equal(t, "boards", actualScopes[1].TableName())
+}

Reply via email to