You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@devlake.apache.org by ab...@apache.org on 2023/02/08 09:56:04 UTC

[incubator-devlake] branch main updated: feat(sonarqube): add file metrics convertor (#4360)

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

abeizn 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 56d5ec60e feat(sonarqube): add file metrics convertor (#4360)
56d5ec60e is described below

commit 56d5ec60eb20d168f36f52de1ebc2e42b7ecb5b1
Author: Warren Chen <yi...@merico.dev>
AuthorDate: Wed Feb 8 17:55:59 2023 +0800

    feat(sonarqube): add file metrics convertor (#4360)
---
 .../securitytesting/st_file_metrics.go}            | 16 ++--
 .../domainlayer/securitytesting/st_issues.go       |  4 +-
 .../domainlayer/securitytesting/st_projects.go     |  2 +-
 .../20230208_add_security_testing.go               |  3 +-
 .../migrationscripts/archived/st_file_metrics.go}  | 18 ++---
 .../models/migrationscripts/archived/st_issues.go  |  6 +-
 .../migrationscripts/archived/st_projects.go       |  2 +-
 backend/plugins/sonarqube/impl/impl.go             |  1 +
 .../migrationscripts/20230111_add_init_tables.go   |  2 +-
 .../archived/sonarqube_file_metrics.go             |  1 +
 .../migrationscripts/archived/sonarqube_hotspot.go |  2 +-
 .../sonarqube/models/sonarqube_file_metrics.go     |  1 +
 .../sonarqube/tasks/filemetrics_convertor.go       | 93 ++++++++++++++++++++++
 .../sonarqube/tasks/filemetrics_extractor.go       |  1 +
 .../plugins/sonarqube/tasks/hotspots_convertor.go  |  7 +-
 .../plugins/sonarqube/tasks/issues_convertor.go    |  7 +-
 .../plugins/sonarqube/tasks/projects_convertor.go  |  4 +-
 17 files changed, 133 insertions(+), 37 deletions(-)

diff --git a/backend/plugins/sonarqube/models/sonarqube_file_metrics.go b/backend/core/models/domainlayer/securitytesting/st_file_metrics.go
similarity index 84%
copy from backend/plugins/sonarqube/models/sonarqube_file_metrics.go
copy to backend/core/models/domainlayer/securitytesting/st_file_metrics.go
index d32b1fcc5..b51ea665e 100644
--- a/backend/plugins/sonarqube/models/sonarqube_file_metrics.go
+++ b/backend/core/models/domainlayer/securitytesting/st_file_metrics.go
@@ -15,15 +15,16 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-package models
+package securitytesting
 
 import (
-	"github.com/apache/incubator-devlake/core/models/common"
+	"github.com/apache/incubator-devlake/core/models/domainlayer"
 )
 
-type SonarqubeFileMetrics struct {
-	ConnectionId             uint64  `gorm:"primaryKey"`
-	ComponentKey             string  `json:"component_key" gorm:"primaryKey"`
+type StFileMetrics struct {
+	domainlayer.DomainEntity
+	ComponentKey             string
+	Project                  string  `gorm:"index;type:varchar(255)"` //domain project key
 	FileName                 string  `json:"file_name"`
 	FilePath                 string  `json:"file_path"`
 	FileLanguage             string  `json:"file_language"`
@@ -43,9 +44,8 @@ type SonarqubeFileMetrics struct {
 	LinesToCover             int     `json:"lines_to_cover"`
 	DuplicatedLinesDensity   float64 `json:"duplicated_lines_density"`
 	DuplicatedBlocks         int     `json:"duplicated_blocks"`
-	common.NoPKModel
 }
 
-func (SonarqubeFileMetrics) TableName() string {
-	return "_tool_sonarqube_file_metrics"
+func (StFileMetrics) TableName() string {
+	return "st_file_metrics"
 }
diff --git a/backend/core/models/domainlayer/securitytesting/st_issues.go b/backend/core/models/domainlayer/securitytesting/st_issues.go
index 1d99451c4..e45ebe9d9 100644
--- a/backend/core/models/domainlayer/securitytesting/st_issues.go
+++ b/backend/core/models/domainlayer/securitytesting/st_issues.go
@@ -25,11 +25,11 @@ import (
 type StIssue struct {
 	domainlayer.DomainEntity
 	BatchId           string           `json:"batchId" gorm:"type:varchar(100)"` // from collection time
-	Key               string           `json:"key" gorm:"primaryKey"`
+	Project           string           `gorm:"index;type:varchar(255)"`          //domain project key
+	Key               string           `json:"key"`
 	Rule              string           `json:"rule" gorm:"type:varchar(255)"`
 	Severity          string           `json:"severity" gorm:"type:varchar(255)"`
 	Component         string           `json:"component" gorm:"type:varchar(255)"`
-	Project           string           `json:"project" gorm:"type:varchar(255)"`
 	Line              int              `json:"line"`
 	Status            string           `json:"status" gorm:"type:varchar(255)"`
 	Message           string           `json:"message"`
diff --git a/backend/core/models/domainlayer/securitytesting/st_projects.go b/backend/core/models/domainlayer/securitytesting/st_projects.go
index dc98555aa..eec3cb395 100644
--- a/backend/core/models/domainlayer/securitytesting/st_projects.go
+++ b/backend/core/models/domainlayer/securitytesting/st_projects.go
@@ -27,7 +27,7 @@ var _ plugin.Scope = (*StProject)(nil)
 
 type StProject struct {
 	domainlayer.DomainEntity
-	Key              string           `json:"key" gorm:"type:varchar(64);primaryKey"`
+	Key              string           `json:"key" gorm:"type:varchar(64)"`
 	Name             string           `json:"name" gorm:"type:varchar(255)"`
 	Qualifier        string           `json:"qualifier" gorm:"type:varchar(255)"`
 	Visibility       string           `json:"visibility" gorm:"type:varchar(64)"`
diff --git a/backend/core/models/migrationscripts/20230208_add_security_testing.go b/backend/core/models/migrationscripts/20230208_add_security_testing.go
index eb862fde0..481151de9 100644
--- a/backend/core/models/migrationscripts/20230208_add_security_testing.go
+++ b/backend/core/models/migrationscripts/20230208_add_security_testing.go
@@ -31,11 +31,12 @@ func (u *addSecurityTesting) Up(basicRes context.BasicRes) errors.Error {
 		basicRes,
 		&archived.StProject{},
 		&archived.StIssue{},
+		&archived.StFileMetrics{},
 	)
 }
 
 func (*addSecurityTesting) Version() uint64 {
-	return 20230208000002
+	return 20230208000008
 }
 
 func (*addSecurityTesting) Name() string {
diff --git a/backend/plugins/sonarqube/models/sonarqube_file_metrics.go b/backend/core/models/migrationscripts/archived/st_file_metrics.go
similarity index 83%
copy from backend/plugins/sonarqube/models/sonarqube_file_metrics.go
copy to backend/core/models/migrationscripts/archived/st_file_metrics.go
index d32b1fcc5..b93b51f02 100644
--- a/backend/plugins/sonarqube/models/sonarqube_file_metrics.go
+++ b/backend/core/models/migrationscripts/archived/st_file_metrics.go
@@ -15,15 +15,12 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-package models
+package archived
 
-import (
-	"github.com/apache/incubator-devlake/core/models/common"
-)
-
-type SonarqubeFileMetrics struct {
-	ConnectionId             uint64  `gorm:"primaryKey"`
-	ComponentKey             string  `json:"component_key" gorm:"primaryKey"`
+type StFileMetrics struct {
+	DomainEntity
+	ComponentKey             string  `json:"component_key"`
+	Project                  string  `gorm:"index;type:varchar(255)"` //domain project key
 	FileName                 string  `json:"file_name"`
 	FilePath                 string  `json:"file_path"`
 	FileLanguage             string  `json:"file_language"`
@@ -43,9 +40,8 @@ type SonarqubeFileMetrics struct {
 	LinesToCover             int     `json:"lines_to_cover"`
 	DuplicatedLinesDensity   float64 `json:"duplicated_lines_density"`
 	DuplicatedBlocks         int     `json:"duplicated_blocks"`
-	common.NoPKModel
 }
 
-func (SonarqubeFileMetrics) TableName() string {
-	return "_tool_sonarqube_file_metrics"
+func (StFileMetrics) TableName() string {
+	return "st_file_metrics"
 }
diff --git a/backend/core/models/migrationscripts/archived/st_issues.go b/backend/core/models/migrationscripts/archived/st_issues.go
index 1f163d571..1460831be 100644
--- a/backend/core/models/migrationscripts/archived/st_issues.go
+++ b/backend/core/models/migrationscripts/archived/st_issues.go
@@ -23,12 +23,12 @@ import (
 
 type StIssue struct {
 	DomainEntity
-	BatchId           string           `json:"batchId" gorm:"type:varchar(100)"` // from collection time
-	Key               string           `json:"key" gorm:"primaryKey"`
+	BatchId           string `json:"batchId" gorm:"type:varchar(100)"` // from collection time
+	Key               string
+	Project           string           `gorm:"index;type:varchar(255)"` //domain project key
 	Rule              string           `json:"rule" gorm:"type:varchar(255)"`
 	Severity          string           `json:"severity" gorm:"type:varchar(255)"`
 	Component         string           `json:"component" gorm:"type:varchar(255)"`
-	Project           string           `json:"project" gorm:"type:varchar(255)"`
 	Line              int              `json:"line"`
 	Status            string           `json:"status" gorm:"type:varchar(255)"`
 	Message           string           `json:"message"`
diff --git a/backend/core/models/migrationscripts/archived/st_projects.go b/backend/core/models/migrationscripts/archived/st_projects.go
index b9716b491..6646a5c38 100644
--- a/backend/core/models/migrationscripts/archived/st_projects.go
+++ b/backend/core/models/migrationscripts/archived/st_projects.go
@@ -23,7 +23,7 @@ import (
 
 type StProject struct {
 	DomainEntity
-	Key              string           `json:"key" gorm:"type:varchar(64);primaryKey"`
+	Key              string           `json:"key" gorm:"type:varchar(64)"`
 	Name             string           `json:"name" gorm:"type:varchar(255)"`
 	Qualifier        string           `json:"qualifier" gorm:"type:varchar(255)"`
 	Visibility       string           `json:"visibility" gorm:"type:varchar(64)"`
diff --git a/backend/plugins/sonarqube/impl/impl.go b/backend/plugins/sonarqube/impl/impl.go
index ce9d168b0..63d60f6ff 100644
--- a/backend/plugins/sonarqube/impl/impl.go
+++ b/backend/plugins/sonarqube/impl/impl.go
@@ -66,6 +66,7 @@ func (p Sonarqube) SubTaskMetas() []plugin.SubTaskMeta {
 		tasks.ConvertProjectsMeta,
 		tasks.ConvertIssuesMeta,
 		tasks.ConvertHotspotsMeta,
+		tasks.ConvertFileMetricsMeta,
 	}
 }
 
diff --git a/backend/plugins/sonarqube/models/migrationscripts/20230111_add_init_tables.go b/backend/plugins/sonarqube/models/migrationscripts/20230111_add_init_tables.go
index 3bbc09ad6..4dd8e6238 100644
--- a/backend/plugins/sonarqube/models/migrationscripts/20230111_add_init_tables.go
+++ b/backend/plugins/sonarqube/models/migrationscripts/20230111_add_init_tables.go
@@ -40,7 +40,7 @@ func (*addInitTables) Up(basicRes context.BasicRes) errors.Error {
 }
 
 func (*addInitTables) Version() uint64 {
-	return 20230207220016
+	return 20230207220021
 }
 
 func (*addInitTables) Name() string {
diff --git a/backend/plugins/sonarqube/models/migrationscripts/archived/sonarqube_file_metrics.go b/backend/plugins/sonarqube/models/migrationscripts/archived/sonarqube_file_metrics.go
index ef9209018..6f17c2682 100644
--- a/backend/plugins/sonarqube/models/migrationscripts/archived/sonarqube_file_metrics.go
+++ b/backend/plugins/sonarqube/models/migrationscripts/archived/sonarqube_file_metrics.go
@@ -24,6 +24,7 @@ import (
 type SonarqubeFileMetrics struct {
 	ConnectionId             uint64  `gorm:"primaryKey"`
 	ComponentKey             string  `json:"component_key" gorm:"primaryKey"`
+	Project                  string  `json:"project" gorm:"index"`
 	FileName                 string  `json:"file_name"`
 	FilePath                 string  `json:"file_path"`
 	FileLanguage             string  `json:"file_language"`
diff --git a/backend/plugins/sonarqube/models/migrationscripts/archived/sonarqube_hotspot.go b/backend/plugins/sonarqube/models/migrationscripts/archived/sonarqube_hotspot.go
index a94aeac94..f8259b654 100644
--- a/backend/plugins/sonarqube/models/migrationscripts/archived/sonarqube_hotspot.go
+++ b/backend/plugins/sonarqube/models/migrationscripts/archived/sonarqube_hotspot.go
@@ -25,9 +25,9 @@ import (
 type SonarqubeHotspot struct {
 	ConnectionId             uint64           `gorm:"primaryKey"`
 	Key                      string           `json:"key" gorm:"primaryKey"`
+	Project                  string           `json:"project" gorm:"index"`
 	BatchId                  string           `json:"batchId" gorm:"type:varchar(100)"` // from collection time
 	Component                string           `json:"component" gorm:"index"`
-	Project                  string           `json:"project" gorm:"index"`
 	SecurityCategory         string           `json:"securityCategory"`
 	VulnerabilityProbability string           `json:"vulnerabilityProbability"`
 	Status                   string           `json:"status"`
diff --git a/backend/plugins/sonarqube/models/sonarqube_file_metrics.go b/backend/plugins/sonarqube/models/sonarqube_file_metrics.go
index d32b1fcc5..b0718e6e5 100644
--- a/backend/plugins/sonarqube/models/sonarqube_file_metrics.go
+++ b/backend/plugins/sonarqube/models/sonarqube_file_metrics.go
@@ -24,6 +24,7 @@ import (
 type SonarqubeFileMetrics struct {
 	ConnectionId             uint64  `gorm:"primaryKey"`
 	ComponentKey             string  `json:"component_key" gorm:"primaryKey"`
+	Project                  string  `json:"project" gorm:"index"`
 	FileName                 string  `json:"file_name"`
 	FilePath                 string  `json:"file_path"`
 	FileLanguage             string  `json:"file_language"`
diff --git a/backend/plugins/sonarqube/tasks/filemetrics_convertor.go b/backend/plugins/sonarqube/tasks/filemetrics_convertor.go
new file mode 100644
index 000000000..bd0a24af9
--- /dev/null
+++ b/backend/plugins/sonarqube/tasks/filemetrics_convertor.go
@@ -0,0 +1,93 @@
+/*
+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 tasks
+
+import (
+	"github.com/apache/incubator-devlake/core/dal"
+	"github.com/apache/incubator-devlake/core/errors"
+	"github.com/apache/incubator-devlake/core/models/domainlayer"
+	"github.com/apache/incubator-devlake/core/models/domainlayer/didgen"
+	"github.com/apache/incubator-devlake/core/models/domainlayer/securitytesting"
+	"github.com/apache/incubator-devlake/core/plugin"
+	"github.com/apache/incubator-devlake/helpers/pluginhelper/api"
+	sonarqubeModels "github.com/apache/incubator-devlake/plugins/sonarqube/models"
+	"reflect"
+)
+
+var ConvertFileMetricsMeta = plugin.SubTaskMeta{
+	Name:             "convertFileMetrics",
+	EntryPoint:       ConvertFileMetrics,
+	EnabledByDefault: true,
+	Description:      "Convert tool layer table sonarqube_file_metrics into  domain layer table st_file_metrics",
+	DomainTypes:      []string{plugin.DOMAIN_TYPE_SECURITY_TESTING},
+}
+
+func ConvertFileMetrics(taskCtx plugin.SubTaskContext) errors.Error {
+	db := taskCtx.GetDal()
+	rawDataSubTaskArgs, data := CreateRawDataSubTaskArgs(taskCtx, RAW_PROJECTS_TABLE)
+	cursor, err := db.Cursor(dal.From(sonarqubeModels.SonarqubeFileMetrics{}),
+		dal.Where("connection_id = ? and project = ?", data.Options.ConnectionId, data.Options.ProjectKey))
+	if err != nil {
+		return err
+	}
+	defer cursor.Close()
+
+	issueIdGen := didgen.NewDomainIdGenerator(&sonarqubeModels.SonarqubeFileMetrics{})
+	projectIdGen := didgen.NewDomainIdGenerator(&sonarqubeModels.SonarqubeProject{})
+	converter, err := api.NewDataConverter(api.DataConverterArgs{
+		InputRowType:       reflect.TypeOf(sonarqubeModels.SonarqubeFileMetrics{}),
+		Input:              cursor,
+		RawDataSubTaskArgs: *rawDataSubTaskArgs,
+		Convert: func(inputRow interface{}) ([]interface{}, errors.Error) {
+			sonarqubeFileMetric := inputRow.(*sonarqubeModels.SonarqubeFileMetrics)
+			domainFileMetric := &securitytesting.StFileMetrics{
+				DomainEntity: domainlayer.DomainEntity{Id: issueIdGen.Generate(data.Options.ConnectionId, sonarqubeFileMetric.ComponentKey)},
+				ComponentKey: sonarqubeFileMetric.ComponentKey,
+				FileName:     sonarqubeFileMetric.FileName,
+				FilePath:     sonarqubeFileMetric.FilePath,
+				FileLanguage: sonarqubeFileMetric.FileLanguage,
+				Project:      projectIdGen.Generate(data.Options.ConnectionId, sonarqubeFileMetric.Project),
+				//BatchID:                  sonarqubeFileMetric.BatchID,
+				CodeSmells:               sonarqubeFileMetric.CodeSmells,
+				SqaleIndex:               sonarqubeFileMetric.SqaleIndex,
+				SqaleRating:              sonarqubeFileMetric.SqaleRating,
+				Bugs:                     sonarqubeFileMetric.Bugs,
+				ReliabilityRating:        sonarqubeFileMetric.ReliabilityRating,
+				Vulnerabilities:          sonarqubeFileMetric.Vulnerabilities,
+				SecurityRating:           sonarqubeFileMetric.SecurityRating,
+				SecurityHotspots:         sonarqubeFileMetric.SecurityHotspots,
+				SecurityHotspotsReviewed: sonarqubeFileMetric.SecurityHotspotsReviewed,
+				SecurityReviewRating:     sonarqubeFileMetric.SecurityReviewRating,
+				Ncloc:                    sonarqubeFileMetric.Ncloc,
+				Coverage:                 sonarqubeFileMetric.Coverage,
+				LinesToCover:             sonarqubeFileMetric.LinesToCover,
+				DuplicatedLinesDensity:   sonarqubeFileMetric.DuplicatedLinesDensity,
+				DuplicatedBlocks:         sonarqubeFileMetric.DuplicatedBlocks,
+			}
+			return []interface{}{
+				domainFileMetric,
+			}, nil
+		},
+	})
+
+	if err != nil {
+		return err
+	}
+
+	return converter.Execute()
+}
diff --git a/backend/plugins/sonarqube/tasks/filemetrics_extractor.go b/backend/plugins/sonarqube/tasks/filemetrics_extractor.go
index 7f6744cc4..3ff73f8ee 100644
--- a/backend/plugins/sonarqube/tasks/filemetrics_extractor.go
+++ b/backend/plugins/sonarqube/tasks/filemetrics_extractor.go
@@ -46,6 +46,7 @@ func ExtractFilemetrics(taskCtx plugin.SubTaskContext) errors.Error {
 				FileName:     body.Name,
 				FilePath:     body.Path,
 				FileLanguage: body.Language,
+				Project:      data.Options.ProjectKey,
 				//BatchID:                  "",
 			}
 			alphabetMap := map[string]string{
diff --git a/backend/plugins/sonarqube/tasks/hotspots_convertor.go b/backend/plugins/sonarqube/tasks/hotspots_convertor.go
index 7367bffee..02dbd1d09 100644
--- a/backend/plugins/sonarqube/tasks/hotspots_convertor.go
+++ b/backend/plugins/sonarqube/tasks/hotspots_convertor.go
@@ -47,7 +47,8 @@ func ConvertHotspots(taskCtx plugin.SubTaskContext) errors.Error {
 	}
 	defer cursor.Close()
 
-	accountIdGen := didgen.NewDomainIdGenerator(&sonarqubeModels.SonarqubeHotspot{})
+	issueIdGen := didgen.NewDomainIdGenerator(&sonarqubeModels.SonarqubeHotspot{})
+	projectIdGen := didgen.NewDomainIdGenerator(&sonarqubeModels.SonarqubeProject{})
 	converter, err := api.NewDataConverter(api.DataConverterArgs{
 		InputRowType:       reflect.TypeOf(sonarqubeModels.SonarqubeHotspot{}),
 		Input:              cursor,
@@ -55,11 +56,11 @@ func ConvertHotspots(taskCtx plugin.SubTaskContext) errors.Error {
 		Convert: func(inputRow interface{}) ([]interface{}, errors.Error) {
 			sonarqubeHotspot := inputRow.(*sonarqubeModels.SonarqubeHotspot)
 			domainHotspot := &securitytesting.StIssue{
-				DomainEntity:      domainlayer.DomainEntity{Id: accountIdGen.Generate(data.Options.ConnectionId, sonarqubeHotspot.Key)},
+				DomainEntity:      domainlayer.DomainEntity{Id: issueIdGen.Generate(data.Options.ConnectionId, sonarqubeHotspot.Key)},
 				BatchId:           sonarqubeHotspot.BatchId,
 				Key:               sonarqubeHotspot.Key,
 				Component:         sonarqubeHotspot.Component,
-				Project:           sonarqubeHotspot.Project,
+				Project:           projectIdGen.Generate(data.Options.ConnectionId, sonarqubeHotspot.Project),
 				Line:              sonarqubeHotspot.Line,
 				Status:            sonarqubeHotspot.Status,
 				Message:           sonarqubeHotspot.Message,
diff --git a/backend/plugins/sonarqube/tasks/issues_convertor.go b/backend/plugins/sonarqube/tasks/issues_convertor.go
index c942038cc..1df8e094b 100644
--- a/backend/plugins/sonarqube/tasks/issues_convertor.go
+++ b/backend/plugins/sonarqube/tasks/issues_convertor.go
@@ -47,7 +47,8 @@ func ConvertIssues(taskCtx plugin.SubTaskContext) errors.Error {
 	}
 	defer cursor.Close()
 
-	accountIdGen := didgen.NewDomainIdGenerator(&sonarqubeModels.SonarqubeIssue{})
+	issueIdGen := didgen.NewDomainIdGenerator(&sonarqubeModels.SonarqubeIssue{})
+	projectIdGen := didgen.NewDomainIdGenerator(&sonarqubeModels.SonarqubeProject{})
 	converter, err := api.NewDataConverter(api.DataConverterArgs{
 		InputRowType:       reflect.TypeOf(sonarqubeModels.SonarqubeIssue{}),
 		Input:              cursor,
@@ -55,13 +56,13 @@ func ConvertIssues(taskCtx plugin.SubTaskContext) errors.Error {
 		Convert: func(inputRow interface{}) ([]interface{}, errors.Error) {
 			sonarqubeIssue := inputRow.(*sonarqubeModels.SonarqubeIssue)
 			domainIssue := &securitytesting.StIssue{
-				DomainEntity:      domainlayer.DomainEntity{Id: accountIdGen.Generate(data.Options.ConnectionId, sonarqubeIssue.Key)},
+				DomainEntity:      domainlayer.DomainEntity{Id: issueIdGen.Generate(data.Options.ConnectionId, sonarqubeIssue.Key)},
 				BatchId:           sonarqubeIssue.BatchId,
 				Key:               sonarqubeIssue.Key,
 				Rule:              sonarqubeIssue.Rule,
 				Severity:          sonarqubeIssue.Severity,
 				Component:         sonarqubeIssue.Component,
-				Project:           sonarqubeIssue.Project,
+				Project:           projectIdGen.Generate(data.Options.ConnectionId, sonarqubeIssue.Project),
 				Line:              sonarqubeIssue.Line,
 				Status:            sonarqubeIssue.Status,
 				Message:           sonarqubeIssue.Message,
diff --git a/backend/plugins/sonarqube/tasks/projects_convertor.go b/backend/plugins/sonarqube/tasks/projects_convertor.go
index aabe498cb..9cad73f3f 100644
--- a/backend/plugins/sonarqube/tasks/projects_convertor.go
+++ b/backend/plugins/sonarqube/tasks/projects_convertor.go
@@ -47,7 +47,7 @@ func ConvertProjects(taskCtx plugin.SubTaskContext) errors.Error {
 	}
 	defer cursor.Close()
 
-	accountIdGen := didgen.NewDomainIdGenerator(&sonarqubeModels.SonarqubeProject{})
+	projectIdGen := didgen.NewDomainIdGenerator(&sonarqubeModels.SonarqubeProject{})
 	converter, err := api.NewDataConverter(api.DataConverterArgs{
 		InputRowType:       reflect.TypeOf(sonarqubeModels.SonarqubeProject{}),
 		Input:              cursor,
@@ -55,7 +55,7 @@ func ConvertProjects(taskCtx plugin.SubTaskContext) errors.Error {
 		Convert: func(inputRow interface{}) ([]interface{}, errors.Error) {
 			sonarqubeProject := inputRow.(*sonarqubeModels.SonarqubeProject)
 			domainProject := &securitytesting.StProject{
-				DomainEntity:     domainlayer.DomainEntity{Id: accountIdGen.Generate(data.Options.ConnectionId, sonarqubeProject.Key)},
+				DomainEntity:     domainlayer.DomainEntity{Id: projectIdGen.Generate(data.Options.ConnectionId, sonarqubeProject.Key)},
 				Key:              sonarqubeProject.Key,
 				Name:             sonarqubeProject.Name,
 				Qualifier:        sonarqubeProject.Qualifier,