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

warren 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 b133b1e38 Bamboo blueprint (#4446)
b133b1e38 is described below

commit b133b1e38d60006b850ac0ed7be4d28aaa294c5f
Author: mappjzc <[email protected]>
AuthorDate: Mon Feb 20 13:36:53 2023 +0800

    Bamboo blueprint (#4446)
    
    * feat: bamboo blueprint
    
    Add bamboo blueprint.
    
    Nddtfjiang <[email protected]>
    
    * fix: fix for merge
    
    fix for merge
    
    Nddtfjiang <[email protected]>
---
 backend/plugins/bamboo/api/blueprint_V200_test.go  | 163 ++++++++++++++++++
 backend/plugins/bamboo/api/blueprint_v200.go       | 190 +++++++++++++++++++++
 backend/plugins/bamboo/impl/impl.go                |  46 ++++-
 backend/plugins/bamboo/models/project.go           |  47 ++++-
 .../plugins/bamboo/models/{project.go => share.go} |  20 +--
 .../models/{project.go => transformation_rule.go}  |  20 +--
 backend/plugins/bamboo/tasks/project_extractor.go  |  19 +--
 backend/plugins/bamboo/tasks/projects_convertor.go |   3 +-
 backend/plugins/bamboo/tasks/shared.go             |   3 +-
 backend/plugins/bamboo/tasks/task_data.go          |   4 +
 10 files changed, 459 insertions(+), 56 deletions(-)

diff --git a/backend/plugins/bamboo/api/blueprint_V200_test.go 
b/backend/plugins/bamboo/api/blueprint_V200_test.go
new file mode 100644
index 000000000..3622b93c2
--- /dev/null
+++ b/backend/plugins/bamboo/api/blueprint_V200_test.go
@@ -0,0 +1,163 @@
+/*
+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"
+
+       mockdal "github.com/apache/incubator-devlake/mocks/core/dal"
+       mockplugin "github.com/apache/incubator-devlake/mocks/core/plugin"
+
+       "github.com/apache/incubator-devlake/core/errors"
+       "github.com/apache/incubator-devlake/core/models/common"
+       "github.com/apache/incubator-devlake/core/models/domainlayer/devops"
+       "github.com/apache/incubator-devlake/core/plugin"
+       helper "github.com/apache/incubator-devlake/helpers/pluginhelper/api"
+       "github.com/apache/incubator-devlake/helpers/unithelper"
+       "github.com/apache/incubator-devlake/plugins/bamboo/models"
+       "github.com/go-playground/validator/v10"
+       "github.com/stretchr/testify/assert"
+       "github.com/stretchr/testify/mock"
+)
+
+func TestMakeDataSourcePipelinePlanV200(t *testing.T) {
+       const testConnectionID uint64 = 1
+       const testTransformationRuleId uint64 = 2
+       const testKey string = "TEST"
+       const testBambooEndPoint string = 
"http://mail.nddtf.com:8085/rest/api/latest/";
+       const testLink string = 
"http://mail.nddtf.com:8085/rest/api/latest/project/TEST";
+       const testUser string = "username"
+       const testPass string = "password"
+       const testName string = "bamboo-test"
+       const testTransformationRuleName string = "bamboo transformation rule"
+       const testProxy string = ""
+
+       syncPolicy := &plugin.BlueprintSyncPolicy{}
+       bpScopes := []*plugin.BlueprintScopeV200{
+               {
+                       Entities: []string{plugin.DOMAIN_TYPE_CICD},
+                       Id:       testKey,
+                       Name:     testName,
+               },
+       }
+
+       var testBambooProject = &models.BambooProject{
+               ConnectionId: testConnectionID,
+               ProjectKey:   testKey,
+               Name:         testName,
+               Href:         testLink,
+
+               TransformationRuleId: testTransformationRuleId,
+       }
+
+       var testTransformationRule = &models.BambooTransformationRule{
+               Model: common.Model{
+                       ID: testTransformationRuleId,
+               },
+               Name: testTransformationRuleName,
+       }
+
+       var testBambooConnection = &models.BambooConnection{
+               BaseConnection: helper.BaseConnection{
+                       Name: testName,
+                       Model: common.Model{
+                               ID: testConnectionID,
+                       },
+               },
+               BambooConn: models.BambooConn{
+                       RestConnection: helper.RestConnection{
+                               Endpoint:         testBambooEndPoint,
+                               Proxy:            testProxy,
+                               RateLimitPerHour: 0,
+                       },
+                       BasicAuth: helper.BasicAuth{
+                               Username: testUser,
+                               Password: testPass,
+                       },
+               },
+       }
+
+       var expectRepoId = "bamboo:BambooProject:1:TEST"
+
+       var testSubTaskMeta = []plugin.SubTaskMeta{}
+
+       var expectPlans = plugin.PipelinePlan{
+               {
+                       {
+                               Plugin:   "bamboo",
+                               Subtasks: []string{},
+                               Options: map[string]interface{}{
+                                       "connectionId":         uint64(1),
+                                       "projectKey":           testKey,
+                                       "transformationRuleId": 
testTransformationRuleId,
+                               },
+                       },
+               },
+       }
+
+       expectCicdScope := devops.NewCicdScope(expectRepoId, testName)
+       expectCicdScope.Description = ""
+       expectCicdScope.Url = ""
+
+       var err errors.Error
+
+       // register bamboo plugin for NewDomainIdGenerator
+       mockMeta := mockplugin.NewPluginMeta(t)
+       
mockMeta.On("RootPkgPath").Return("github.com/apache/incubator-devlake/plugins/bamboo")
+       err = plugin.RegisterPlugin("bamboo", mockMeta)
+       assert.Equal(t, err, nil)
+
+       // Refresh Global Variables and set the sql mock
+       basicRes = unithelper.DummyBasicRes(func(mockDal *mockdal.Dal) {
+               mockDal.On("First", mock.Anything, mock.Anything).Run(func(args 
mock.Arguments) {
+                       dst := args.Get(0).(*models.BambooConnection)
+                       *dst = *testBambooConnection
+               }).Return(nil).Once()
+
+               mockDal.On("First", mock.Anything, mock.Anything).Run(func(args 
mock.Arguments) {
+                       dst := args.Get(0).(*models.BambooProject)
+                       *dst = *testBambooProject
+               }).Return(nil).Twice()
+
+               mockDal.On("First", mock.Anything, mock.Anything).Run(func(args 
mock.Arguments) {
+                       dst := args.Get(0).(*models.BambooTransformationRule)
+                       *dst = *testTransformationRule
+               }).Return(nil).Once()
+       })
+       connectionHelper = helper.NewConnectionHelper(
+               basicRes,
+               validator.New(),
+       )
+
+       plans, scopes, err := MakePipelinePlanV200(testSubTaskMeta, 
testConnectionID, bpScopes, syncPolicy)
+       assert.Equal(t, err, nil)
+
+       assert.Equal(t, expectPlans, plans)
+
+       // ignore CreatedDate UpdatedDate  CreatedAt UpdatedAt checking
+       expectCicdScope.CreatedDate = scopes[0].(*devops.CicdScope).CreatedDate
+       expectCicdScope.UpdatedDate = scopes[0].(*devops.CicdScope).UpdatedDate
+       expectCicdScope.CreatedAt = scopes[0].(*devops.CicdScope).CreatedAt
+       expectCicdScope.UpdatedAt = scopes[0].(*devops.CicdScope).UpdatedAt
+
+       var expectScopes = []plugin.Scope{
+               expectCicdScope,
+       }
+
+       assert.Equal(t, expectScopes, scopes)
+}
diff --git a/backend/plugins/bamboo/api/blueprint_v200.go 
b/backend/plugins/bamboo/api/blueprint_v200.go
new file mode 100644
index 000000000..1ce6d404f
--- /dev/null
+++ b/backend/plugins/bamboo/api/blueprint_v200.go
@@ -0,0 +1,190 @@
+/*
+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 (
+       "encoding/json"
+       "fmt"
+       "io"
+       "net/http"
+
+       "github.com/apache/incubator-devlake/plugins/bamboo/models"
+
+       "github.com/apache/incubator-devlake/core/errors"
+       "github.com/apache/incubator-devlake/core/utils"
+
+       "github.com/apache/incubator-devlake/core/dal"
+       "github.com/apache/incubator-devlake/core/models/domainlayer/devops"
+       "github.com/apache/incubator-devlake/core/models/domainlayer/didgen"
+       plugin "github.com/apache/incubator-devlake/core/plugin"
+       helper "github.com/apache/incubator-devlake/helpers/pluginhelper/api"
+       aha 
"github.com/apache/incubator-devlake/helpers/pluginhelper/api/apihelperabstract"
+)
+
+func MakePipelinePlanV200(
+       subtaskMetas []plugin.SubTaskMeta,
+       connectionId uint64,
+       scope []*plugin.BlueprintScopeV200,
+       syncPolicy *plugin.BlueprintSyncPolicy,
+) (plugin.PipelinePlan, []plugin.Scope, errors.Error) {
+       var err errors.Error
+       connection := new(models.BambooConnection)
+       err1 := connectionHelper.FirstById(connection, connectionId)
+       if err1 != nil {
+               return nil, nil, errors.Default.Wrap(err1, fmt.Sprintf("error 
on get connection by id[%d]", connectionId))
+       }
+
+       sc, err := makeScopeV200(connectionId, scope)
+       if err != nil {
+               return nil, nil, err
+       }
+
+       pp, err := makePipelinePlanV200(subtaskMetas, scope, connection, 
syncPolicy)
+       if err != nil {
+               return nil, nil, err
+       }
+
+       return pp, sc, nil
+}
+
+func makeScopeV200(connectionId uint64, scopes []*plugin.BlueprintScopeV200) 
([]plugin.Scope, errors.Error) {
+       sc := make([]plugin.Scope, 0, len(scopes))
+
+       for _, scope := range scopes {
+               id := 
didgen.NewDomainIdGenerator(&models.BambooProject{}).Generate(connectionId, 
scope.Id)
+
+               // get project from db
+               BambooProject, err := 
GetprojectByConnectionIdAndscopeId(connectionId, scope.Id)
+               if err != nil {
+                       return nil, err
+               }
+
+               // add cicd_scope to scopes
+               if utils.StringsContains(scope.Entities, 
plugin.DOMAIN_TYPE_CICD) {
+                       scopeCICD := devops.NewCicdScope(id, BambooProject.Name)
+
+                       sc = append(sc, scopeCICD)
+               }
+       }
+
+       return sc, nil
+}
+
+func makePipelinePlanV200(
+       subtaskMetas []plugin.SubTaskMeta,
+       scopes []*plugin.BlueprintScopeV200,
+       connection *models.BambooConnection, syncPolicy 
*plugin.BlueprintSyncPolicy,
+) (plugin.PipelinePlan, errors.Error) {
+       plans := make(plugin.PipelinePlan, 0, len(scopes))
+       for _, scope := range scopes {
+               var stage plugin.PipelineStage
+               var err errors.Error
+               // get project
+               project, err := 
GetprojectByConnectionIdAndscopeId(connection.ID, scope.Id)
+               if err != nil {
+                       return nil, err
+               }
+
+               // get transformationRuleId
+               transformationRules, err := 
GetTransformationRuleByproject(project)
+               if err != nil {
+                       return nil, err
+               }
+
+               // bamboo main part
+               options := make(map[string]interface{})
+               options["connectionId"] = connection.ID
+               options["projectKey"] = scope.Id
+               options["transformationRuleId"] = transformationRules.ID
+
+               // construct subtasks
+               subtasks, err := helper.MakePipelinePlanSubtasks(subtaskMetas, 
scope.Entities)
+               if err != nil {
+                       return nil, err
+               }
+
+               stage = append(stage, &plugin.PipelineTask{
+                       Plugin:   "bamboo",
+                       Subtasks: subtasks,
+                       Options:  options,
+               })
+
+               plans = append(plans, stage)
+       }
+       return plans, nil
+}
+
+// GetprojectByConnectionIdAndscopeId get tbe project by the connectionId and 
the scopeId
+func GetprojectByConnectionIdAndscopeId(connectionId uint64, scopeId string) 
(*models.BambooProject, errors.Error) {
+       key := scopeId
+       project := &models.BambooProject{}
+       db := basicRes.GetDal()
+       err := db.First(project, dal.Where("connection_id = ? AND key = ?", 
connectionId, key))
+       if err != nil {
+               if db.IsErrorNotFound(err) {
+                       return nil, errors.Default.Wrap(err, fmt.Sprintf("can 
not find project by connection [%d] scope [%s]", connectionId, scopeId))
+               }
+               return nil, errors.Default.Wrap(err, fmt.Sprintf("fail to find 
project by connection [%d] scope [%s]", connectionId, scopeId))
+       }
+
+       return project, nil
+}
+
+// GetTransformationRuleByproject get the GetTransformationRule by project
+func GetTransformationRuleByproject(project *models.BambooProject) 
(*models.BambooTransformationRule, errors.Error) {
+       transformationRules := &models.BambooTransformationRule{}
+       transformationRuleId := project.TransformationRuleId
+       if transformationRuleId != 0 {
+               db := basicRes.GetDal()
+               err := db.First(transformationRules, dal.Where("id = ?", 
transformationRuleId))
+               if err != nil {
+                       if db.IsErrorNotFound(err) {
+                               return nil, errors.Default.Wrap(err, 
fmt.Sprintf("can not find transformationRules by transformationRuleId [%d]", 
transformationRuleId))
+                       }
+                       return nil, errors.Default.Wrap(err, fmt.Sprintf("fail 
to find transformationRules by transformationRuleId [%d]", 
transformationRuleId))
+               }
+       } else {
+               transformationRules.ID = 0
+       }
+
+       return transformationRules, nil
+}
+
+func GetApiProject(
+       projectKey string,
+       apiClient aha.ApiClientAbstract,
+) (*models.ApiBambooProject, errors.Error) {
+       projectRes := &models.ApiBambooProject{}
+       res, err := apiClient.Get(fmt.Sprintf("project/%s.json", projectKey), 
nil, nil)
+       if err != nil {
+               return nil, err
+       }
+       defer res.Body.Close()
+       if res.StatusCode != http.StatusOK {
+               return nil, 
errors.HttpStatus(res.StatusCode).New(fmt.Sprintf("unexpected status code when 
requesting project detail from %s", res.Request.URL.String()))
+       }
+       body, err := errors.Convert01(io.ReadAll(res.Body))
+       if err != nil {
+               return nil, err
+       }
+       err = errors.Convert(json.Unmarshal(body, projectRes))
+       if err != nil {
+               return nil, err
+       }
+       return projectRes, nil
+}
diff --git a/backend/plugins/bamboo/impl/impl.go 
b/backend/plugins/bamboo/impl/impl.go
index f8347c0b7..2680319c0 100644
--- a/backend/plugins/bamboo/impl/impl.go
+++ b/backend/plugins/bamboo/impl/impl.go
@@ -64,8 +64,7 @@ func (p Bamboo) TransformationRule() interface{} {
 }
 
 func (p Bamboo) MakeDataSourcePipelinePlanV200(connectionId uint64, scopes 
[]*plugin.BlueprintScopeV200, syncPolicy plugin.BlueprintSyncPolicy) 
(plugin.PipelinePlan, []plugin.Scope, errors.Error) {
-       //return api.MakePipelinePlanV200(p.SubTaskMetas(), connectionId, 
scopes, &syncPolicy)
-       return nil, nil, nil
+       return api.MakePipelinePlanV200(p.SubTaskMetas(), connectionId, scopes, 
&syncPolicy)
 }
 
 func (p Bamboo) GetTablesInfo() []dal.Tabler {
@@ -89,6 +88,9 @@ func (p Bamboo) SubTaskMetas() []plugin.SubTaskMeta {
 }
 
 func (p Bamboo) PrepareTaskData(taskCtx plugin.TaskContext, options 
map[string]interface{}) (interface{}, errors.Error) {
+       logger := taskCtx.GetLogger()
+       logger.Debug("%v", options)
+
        op, err := tasks.DecodeAndValidateTaskOptions(options)
        if err != nil {
                return nil, err
@@ -108,6 +110,43 @@ func (p Bamboo) PrepareTaskData(taskCtx 
plugin.TaskContext, options map[string]i
                return nil, errors.Default.Wrap(err, "unable to get Bamboo API 
client instance")
        }
 
+       if op.ProjectKey != "" {
+               var scope *models.BambooProject
+               // support v100 & advance mode
+               // If we still cannot find the record in db, we have to request 
from remote server and save it to db
+               db := taskCtx.GetDal()
+               err = db.First(&scope, dal.Where("connection_id = ? AND key = 
?", op.ConnectionId, op.ProjectKey))
+               if err != nil && db.IsErrorNotFound(err) {
+                       apiProject, err := api.GetApiProject(op.ProjectKey, 
apiClient)
+                       if err != nil {
+                               return nil, err
+                       }
+                       logger.Debug(fmt.Sprintf("Current project: %s", 
apiProject.Key))
+                       scope.Convert(apiProject)
+                       scope.ConnectionId = op.ConnectionId
+                       err = taskCtx.GetDal().CreateIfNotExist(&scope)
+                       if err != nil {
+                               return nil, err
+                       }
+               }
+               if err != nil {
+                       return nil, errors.Default.Wrap(err, fmt.Sprintf("fail 
to find project: %s", op.ProjectKey))
+               }
+       }
+
+       if op.BambooTransformationRule == nil && op.TransformationRuleId != 0 {
+               var transformationRule models.BambooTransformationRule
+               db := taskCtx.GetDal()
+               err = db.First(&transformationRule, dal.Where("id = ?", 
op.TransformationRuleId))
+               if err != nil {
+                       if db.IsErrorNotFound(err) {
+                               return nil, errors.Default.Wrap(err, 
fmt.Sprintf("can not find transformationRules by transformationRuleId [%d]", 
op.TransformationRuleId))
+                       }
+                       return nil, errors.Default.Wrap(err, fmt.Sprintf("fail 
to find transformationRules by transformationRuleId [%d]", 
op.TransformationRuleId))
+               }
+               op.BambooTransformationRule = &transformationRule
+       }
+
        return &tasks.BambooTaskData{
                Options:   op,
                ApiClient: apiClient,
@@ -141,8 +180,7 @@ func (p Bamboo) ApiResources() 
map[string]map[string]plugin.ApiResourceHandler {
 }
 
 func (p Bamboo) MakePipelinePlan(connectionId uint64, scope 
[]*plugin.BlueprintScopeV100) (plugin.PipelinePlan, errors.Error) {
-       //return api.MakePipelinePlan(p.SubTaskMetas(), connectionId, scope)
-       return nil, nil
+       return nil, errors.Default.New("Bamboo don't support blueprint v100")
 }
 
 func (p Bamboo) Close(taskCtx plugin.TaskContext) errors.Error {
diff --git a/backend/plugins/bamboo/models/project.go 
b/backend/plugins/bamboo/models/project.go
index 7da7ba561..c621aa8bc 100644
--- a/backend/plugins/bamboo/models/project.go
+++ b/backend/plugins/bamboo/models/project.go
@@ -19,17 +19,46 @@ package models
 
 import "github.com/apache/incubator-devlake/core/models/common"
 
+type ApiBambooProject struct {
+       Key         string            `json:"key"`
+       Expand      string            `json:"expand"`
+       Name        string            `json:"name"`
+       Description string            `json:"description"`
+       Link        ApiBambooLink     `json:"link"`
+       Plans       ApiBambooSizeData `json:"plans"`
+}
+
+type ApiBambooProjects struct {
+       ApiBambooSizeData
+       Expand   string             `json:"expand"`
+       Link     ApiBambooLink      `json:"link"`
+       Projects []ApiBambooProject `json:"project"`
+}
+
+type ApiBambooProjectResponse struct {
+       Expand   string            `json:"expand"`
+       Link     ApiBambooLink     `json:"link"`
+       Projects ApiBambooProjects `json:"projects"`
+}
+
 type BambooProject struct {
-       ConnectionId uint64 `gorm:"primaryKey"`
-       ProjectKey   string `gorm:"primaryKey;type:varchar(100)"`
-       Expand       string `json:"expand"`
-       Name         string `gorm:"index;type:varchar(100)"`
-       Description  string `json:"description"`
-       Href         string `json:"link"`
-       Rel          string `gorm:"type:varchar(100)"`
-       common.NoPKModel
+       ConnectionId         uint64 `json:"connectionId" 
mapstructure:"connectionId" gorm:"primaryKey"`
+       ProjectKey           string `json:"projectKey" 
gorm:"primaryKey;type:varchar(256)"`
+       TransformationRuleId uint64 `json:"transformationRuleId,omitempty" 
mapstructure:"transformationRuleId"`
+       Name                 string `json:"name" gorm:"index;type:varchar(256)"`
+       Description          string `json:"description"`
+       Href                 string `json:"link"`
+       Rel                  string `json:"rel" gorm:"type:varchar(100)"`
+       common.NoPKModel     `json:"-" mapstructure:"-"`
+}
+
+func (b *BambooProject) Convert(apiProject *ApiBambooProject) {
+       b.ProjectKey = apiProject.Key
+       b.Name = apiProject.Name
+       b.Description = apiProject.Description
+       b.Href = apiProject.Link.Href
 }
 
-func (BambooProject) TableName() string {
+func (b *BambooProject) TableName() string {
        return "_tool_bamboo_projects"
 }
diff --git a/backend/plugins/bamboo/models/project.go 
b/backend/plugins/bamboo/models/share.go
similarity index 60%
copy from backend/plugins/bamboo/models/project.go
copy to backend/plugins/bamboo/models/share.go
index 7da7ba561..77ab6c2e6 100644
--- a/backend/plugins/bamboo/models/project.go
+++ b/backend/plugins/bamboo/models/share.go
@@ -17,19 +17,13 @@ limitations under the License.
 
 package models
 
-import "github.com/apache/incubator-devlake/core/models/common"
-
-type BambooProject struct {
-       ConnectionId uint64 `gorm:"primaryKey"`
-       ProjectKey   string `gorm:"primaryKey;type:varchar(100)"`
-       Expand       string `json:"expand"`
-       Name         string `gorm:"index;type:varchar(100)"`
-       Description  string `json:"description"`
-       Href         string `json:"link"`
-       Rel          string `gorm:"type:varchar(100)"`
-       common.NoPKModel
+type ApiBambooLink struct {
+       Href string `json:"href"`
+       Rel  string `json:"rel"`
 }
 
-func (BambooProject) TableName() string {
-       return "_tool_bamboo_projects"
+type ApiBambooSizeData struct {
+       Size       int `json:"size"`
+       StartIndex int `json:"start-index"`
+       MaxResult  int `json:"max-result"`
 }
diff --git a/backend/plugins/bamboo/models/project.go 
b/backend/plugins/bamboo/models/transformation_rule.go
similarity index 61%
copy from backend/plugins/bamboo/models/project.go
copy to backend/plugins/bamboo/models/transformation_rule.go
index 7da7ba561..4d48d5f19 100644
--- a/backend/plugins/bamboo/models/project.go
+++ b/backend/plugins/bamboo/models/transformation_rule.go
@@ -17,19 +17,15 @@ limitations under the License.
 
 package models
 
-import "github.com/apache/incubator-devlake/core/models/common"
+import (
+       "github.com/apache/incubator-devlake/core/models/common"
+)
 
-type BambooProject struct {
-       ConnectionId uint64 `gorm:"primaryKey"`
-       ProjectKey   string `gorm:"primaryKey;type:varchar(100)"`
-       Expand       string `json:"expand"`
-       Name         string `gorm:"index;type:varchar(100)"`
-       Description  string `json:"description"`
-       Href         string `json:"link"`
-       Rel          string `gorm:"type:varchar(100)"`
-       common.NoPKModel
+type BambooTransformationRule struct {
+       common.Model
+       Name string `gorm:"type:varchar(255);index:idx_name_gitlab,unique" 
validate:"required" mapstructure:"name" json:"name"`
 }
 
-func (BambooProject) TableName() string {
-       return "_tool_bamboo_projects"
+func (t BambooTransformationRule) TableName() string {
+       return "_tool_bamboo_transformation_rules"
 }
diff --git a/backend/plugins/bamboo/tasks/project_extractor.go 
b/backend/plugins/bamboo/tasks/project_extractor.go
index 7263ea14e..4423a6402 100644
--- a/backend/plugins/bamboo/tasks/project_extractor.go
+++ b/backend/plugins/bamboo/tasks/project_extractor.go
@@ -19,6 +19,7 @@ package tasks
 
 import (
        "encoding/json"
+
        "github.com/apache/incubator-devlake/core/errors"
        "github.com/apache/incubator-devlake/core/plugin"
        helper "github.com/apache/incubator-devlake/helpers/pluginhelper/api"
@@ -34,7 +35,7 @@ func ExtractProject(taskCtx plugin.SubTaskContext) 
errors.Error {
                RawDataSubTaskArgs: *rawDataSubTaskArgs,
 
                Extract: func(resData *helper.RawData) ([]interface{}, 
errors.Error) {
-                       res := &ApiProject{}
+                       res := &models.ApiBambooProject{}
                        err := errors.Convert(json.Unmarshal(resData.Data, res))
                        if err != nil {
                                return nil, err
@@ -60,9 +61,8 @@ var ExtractProjectMeta = plugin.SubTaskMeta{
 }
 
 // Convert the API response to our DB model instance
-func ConvertProject(bambooApiProject *ApiProject) *models.BambooProject {
+func ConvertProject(bambooApiProject *models.ApiBambooProject) 
*models.BambooProject {
        bambooProject := &models.BambooProject{
-               Expand:      bambooApiProject.Expand,
                ProjectKey:  bambooApiProject.Key,
                Name:        bambooApiProject.Name,
                Description: bambooApiProject.Description,
@@ -72,19 +72,6 @@ func ConvertProject(bambooApiProject *ApiProject) 
*models.BambooProject {
        return bambooProject
 }
 
-type ApiProject struct {
-       Expand      string  `json:"expand"`
-       Key         string  `json:"key"`
-       Name        string  `json:"name"`
-       Description string  `json:"description"`
-       Link        ApiLink `json:"link"`
-       //Plans       []ApiPlan `json:"plans"`
-}
-type ApiLink struct {
-       Href string `json:"href"`
-       Rel  string `json:"rel"`
-}
-
 //type ApiProject struct {
 //     ProjectKey         string `json:"key"`
 //     Name        string `json:"name"`
diff --git a/backend/plugins/bamboo/tasks/projects_convertor.go 
b/backend/plugins/bamboo/tasks/projects_convertor.go
index 3de31efda..0db91aad3 100644
--- a/backend/plugins/bamboo/tasks/projects_convertor.go
+++ b/backend/plugins/bamboo/tasks/projects_convertor.go
@@ -18,9 +18,10 @@ limitations under the License.
 package tasks
 
 import (
-       "github.com/apache/incubator-devlake/core/models/domainlayer/devops"
        "reflect"
 
+       "github.com/apache/incubator-devlake/core/models/domainlayer/devops"
+
        "github.com/apache/incubator-devlake/core/dal"
        "github.com/apache/incubator-devlake/core/errors"
        "github.com/apache/incubator-devlake/core/models/domainlayer"
diff --git a/backend/plugins/bamboo/tasks/shared.go 
b/backend/plugins/bamboo/tasks/shared.go
index 97f96278a..3e89bc80d 100644
--- a/backend/plugins/bamboo/tasks/shared.go
+++ b/backend/plugins/bamboo/tasks/shared.go
@@ -18,10 +18,11 @@ limitations under the License.
 package tasks
 
 import (
+       "net/http"
+
        "github.com/apache/incubator-devlake/core/errors"
        "github.com/apache/incubator-devlake/core/plugin"
        "github.com/apache/incubator-devlake/helpers/pluginhelper/api"
-       "net/http"
 )
 
 func CreateRawDataSubTaskArgs(taskCtx plugin.SubTaskContext, rawTable string) 
(*api.RawDataSubTaskArgs, *BambooTaskData) {
diff --git a/backend/plugins/bamboo/tasks/task_data.go 
b/backend/plugins/bamboo/tasks/task_data.go
index 48528e9e9..5e2fe4392 100644
--- a/backend/plugins/bamboo/tasks/task_data.go
+++ b/backend/plugins/bamboo/tasks/task_data.go
@@ -20,6 +20,7 @@ package tasks
 import (
        "github.com/apache/incubator-devlake/core/errors"
        helper "github.com/apache/incubator-devlake/helpers/pluginhelper/api"
+       "github.com/apache/incubator-devlake/plugins/bamboo/models"
 )
 
 type BambooApiParams struct {
@@ -36,6 +37,9 @@ type BambooOptions struct {
        ProjectKey       string   `json:"projectKey"`
        CreatedDateAfter string   `json:"createdDateAfter" 
mapstructure:"createdDateAfter,omitempty"`
        Tasks            []string `json:"tasks,omitempty"`
+
+       TransformationRuleId             uint64 
`mapstructure:"transformationRuleId" json:"transformationRuleId"`
+       *models.BambooTransformationRule `mapstructure:"transformationRules" 
json:"transformationRules"`
 }
 
 type BambooTaskData struct {

Reply via email to