You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@devlake.apache.org by zh...@apache.org on 2022/11/30 06:46:47 UTC
[incubator-devlake] branch main updated: Feat GitHub blueprint v200 (#3819)
This is an automated email from the ASF dual-hosted git repository.
zhangliang2022 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 f6957c258 Feat GitHub blueprint v200 (#3819)
f6957c258 is described below
commit f6957c25876a4eac0d7a21803c2c4e4b8b0c3da1
Author: Warren Chen <yi...@merico.dev>
AuthorDate: Wed Nov 30 14:46:42 2022 +0800
Feat GitHub blueprint v200 (#3819)
* feat(github): implement v200
* feat(github): implement blueprint v200
* feat(github): add comments
* feat(github): add more unit tests
---
plugins/core/plugin_blueprint.go | 5 +-
plugins/github/api/blueprint.go | 139 ++++++++------
.../{blueprint_test.go => blueprint_V200_test.go} | 99 ++++++----
plugins/github/api/blueprint_test.go | 110 +++++++----
plugins/github/api/blueprint_v200.go | 210 +++++++++++++++++++++
plugins/github/impl/impl.go | 4 +
plugins/github/models/repo.go | 28 +--
plugins/github/models/transformation_rule.go | 24 +--
8 files changed, 467 insertions(+), 152 deletions(-)
diff --git a/plugins/core/plugin_blueprint.go b/plugins/core/plugin_blueprint.go
index 3d8ca0583..1226a488a 100644
--- a/plugins/core/plugin_blueprint.go
+++ b/plugins/core/plugin_blueprint.go
@@ -133,8 +133,9 @@ type BlueprintConnectionV200 struct {
// BlueprintScopeV200 contains the `id` and `name` for a specific scope
// transformationRuleId should be deduced by the ScopeId
type BlueprintScopeV200 struct {
- Id string `json:"id"`
- Name string `json:"name"`
+ Id string `json:"id"`
+ Name string `json:"name"`
+ Entities []string `json:"entities"`
}
// MetricPluginBlueprintV200 is similar to the DataSourcePluginBlueprintV200
diff --git a/plugins/github/api/blueprint.go b/plugins/github/api/blueprint.go
index 41b9efa52..4dc771712 100644
--- a/plugins/github/api/blueprint.go
+++ b/plugins/github/api/blueprint.go
@@ -107,70 +107,24 @@ func makePipelinePlan(subtaskMetas []core.SubTaskMeta, scope []*core.BlueprintSc
if err != nil {
return nil, err
}
- memorizedGetApiRepo := func() (*tasks.GithubApiRepo, errors.Error) {
- if repo == nil {
- repo, err = getApiRepo(op, apiClient)
- }
- return repo, err
- }
stage := plan[i]
if stage == nil {
stage = core.PipelineStage{}
}
- // construct github(graphql) task
- if connection.EnableGraphql {
- // FIXME this need fix when 2 plugins merged
- plugin, err := core.GetPlugin(`github_graphql`)
- if err != nil {
- return nil, err
- }
- if pluginGq, ok := plugin.(core.PluginTask); ok {
- subtasks, err := helper.MakePipelinePlanSubtasks(pluginGq.SubTaskMetas(), scopeElem.Entities)
- if err != nil {
- return nil, err
- }
- stage = append(stage, &core.PipelineTask{
- Plugin: "github_graphql",
- Subtasks: subtasks,
- Options: options,
- })
- } else {
- return nil, errors.BadInput.New("plugin github_graphql does not support SubTaskMetas")
- }
- } else {
- subtasks, err := helper.MakePipelinePlanSubtasks(subtaskMetas, scopeElem.Entities)
- if err != nil {
- return nil, err
- }
- stage = append(stage, &core.PipelineTask{
- Plugin: "github",
- Subtasks: subtasks,
- Options: options,
- })
+ stage, err = addGithub(subtaskMetas, connection, scopeElem.Entities, stage, options)
+ if err != nil {
+ return nil, err
}
// collect git data by gitextractor if CODE was requested
- if utils.StringsContains(scopeElem.Entities, core.DOMAIN_TYPE_CODE) {
- // here is the tricky part, we have to obtain the repo id beforehand
- token := strings.Split(connection.Token, ",")[0]
- repo, err = memorizedGetApiRepo()
- if err != nil {
- return nil, err
- }
- cloneUrl, err := errors.Convert01(url.Parse(repo.CloneUrl))
- if err != nil {
- return nil, err
- }
- cloneUrl.User = url.UserPassword("git", token)
- stage = append(stage, &core.PipelineTask{
- Plugin: "gitextractor",
- Options: map[string]interface{}{
- "url": cloneUrl.String(),
- "repoId": didgen.NewDomainIdGenerator(&models.GithubRepo{}).Generate(connection.ID, repo.GithubId),
- "proxy": connection.Proxy,
- },
- })
+ repo, err = memorizedGetApiRepo(repo, op, apiClient)
+ if err != nil {
+ return nil, err
+ }
+ stage, err = addGitex(scopeElem.Entities, connection, repo, stage)
+ if err != nil {
+ return nil, err
}
// dora
if productionPattern, ok := transformationRules["productionPattern"]; ok && productionPattern != nil {
@@ -185,7 +139,7 @@ func makePipelinePlan(subtaskMetas []core.SubTaskMeta, scope []*core.BlueprintSc
if j == len(plan) {
plan = append(plan, nil)
}
- repo, err = memorizedGetApiRepo()
+ repo, err = memorizedGetApiRepo(repo, op, apiClient)
if err != nil {
return nil, err
}
@@ -211,6 +165,66 @@ func makePipelinePlan(subtaskMetas []core.SubTaskMeta, scope []*core.BlueprintSc
return plan, nil
}
+func addGitex(entities []string,
+ connection *models.GithubConnection,
+ repo *tasks.GithubApiRepo,
+ stage core.PipelineStage,
+) (core.PipelineStage, errors.Error) {
+ if utils.StringsContains(entities, core.DOMAIN_TYPE_CODE) {
+ // here is the tricky part, we have to obtain the repo id beforehand
+ token := strings.Split(connection.Token, ",")[0]
+ cloneUrl, err := errors.Convert01(url.Parse(repo.CloneUrl))
+ if err != nil {
+ return nil, err
+ }
+ cloneUrl.User = url.UserPassword("git", token)
+ stage = append(stage, &core.PipelineTask{
+ Plugin: "gitextractor",
+ Options: map[string]interface{}{
+ "url": cloneUrl.String(),
+ "repoId": didgen.NewDomainIdGenerator(&models.GithubRepo{}).Generate(connection.ID, repo.GithubId),
+ "proxy": connection.Proxy,
+ },
+ })
+ }
+ return stage, nil
+}
+
+func addGithub(subtaskMetas []core.SubTaskMeta, connection *models.GithubConnection, entities []string, stage core.PipelineStage, options map[string]interface{}) (core.PipelineStage, errors.Error) {
+ // construct github(graphql) task
+ if connection.EnableGraphql {
+ // FIXME this need fix when 2 plugins merged
+ plugin, err := core.GetPlugin(`github_graphql`)
+ if err != nil {
+ return nil, err
+ }
+ if pluginGq, ok := plugin.(core.PluginTask); ok {
+ subtasks, err := helper.MakePipelinePlanSubtasks(pluginGq.SubTaskMetas(), entities)
+ if err != nil {
+ return nil, err
+ }
+ stage = append(stage, &core.PipelineTask{
+ Plugin: "github_graphql",
+ Subtasks: subtasks,
+ Options: options,
+ })
+ } else {
+ return nil, errors.BadInput.New("plugin github_graphql does not support SubTaskMetas")
+ }
+ } else {
+ subtasks, err := helper.MakePipelinePlanSubtasks(subtaskMetas, entities)
+ if err != nil {
+ return nil, err
+ }
+ stage = append(stage, &core.PipelineTask{
+ Plugin: "github",
+ Subtasks: subtasks,
+ Options: options,
+ })
+ }
+ return stage, nil
+}
+
func getApiRepo(op *tasks.GithubOptions, apiClient helper.ApiClientGetter) (*tasks.GithubApiRepo, errors.Error) {
apiRepo := &tasks.GithubApiRepo{}
res, err := apiClient.Get(fmt.Sprintf("repos/%s/%s", op.Owner, op.Repo), nil, nil)
@@ -231,3 +245,14 @@ func getApiRepo(op *tasks.GithubOptions, apiClient helper.ApiClientGetter) (*tas
}
return apiRepo, nil
}
+
+func memorizedGetApiRepo(repo *tasks.GithubApiRepo, op *tasks.GithubOptions, apiClient helper.ApiClientGetter) (*tasks.GithubApiRepo, errors.Error) {
+ if repo == nil {
+ var err errors.Error
+ repo, err = getApiRepo(op, apiClient)
+ if err != nil {
+ return nil, err
+ }
+ }
+ return repo, nil
+}
diff --git a/plugins/github/api/blueprint_test.go b/plugins/github/api/blueprint_V200_test.go
similarity index 62%
copy from plugins/github/api/blueprint_test.go
copy to plugins/github/api/blueprint_V200_test.go
index 9a35c14d9..ad0f67a3d 100644
--- a/plugins/github/api/blueprint_test.go
+++ b/plugins/github/api/blueprint_V200_test.go
@@ -22,6 +22,9 @@ import (
"encoding/json"
"github.com/apache/incubator-devlake/mocks"
"github.com/apache/incubator-devlake/models/common"
+ "github.com/apache/incubator-devlake/models/domainlayer"
+ "github.com/apache/incubator-devlake/models/domainlayer/code"
+ "github.com/apache/incubator-devlake/models/domainlayer/ticket"
"github.com/apache/incubator-devlake/plugins/core"
"github.com/apache/incubator-devlake/plugins/github/models"
"github.com/apache/incubator-devlake/plugins/github/tasks"
@@ -31,9 +34,10 @@ import (
"io"
"net/http"
"testing"
+ "time"
)
-func TestProcessScope(t *testing.T) {
+func TestMakeDataSourcePipelinePlanV200(t *testing.T) {
connection := &models.GithubConnection{
RestConnection: helper.RestConnection{
BaseConnection: helper.BaseConnection{
@@ -65,32 +69,48 @@ func TestProcessScope(t *testing.T) {
mockMeta.On("RootPkgPath").Return("github.com/apache/incubator-devlake/plugins/github")
err = core.RegisterPlugin("github", mockMeta)
assert.Nil(t, err)
- bs := &core.BlueprintScopeV100{
- Entities: []string{"CODE"},
- Options: json.RawMessage(`{
- "owner": "test",
- "repo": "testRepo"
- }`),
- Transformation: json.RawMessage(`{
- "prType": "hey,man,wasup",
- "refdiff": {
+ bs := &core.BlueprintScopeV200{
+ Entities: []string{"CODE", "TICKET"},
+ Id: "",
+ Name: "",
+ }
+ bpScopes := make([]*core.BlueprintScopeV200, 0)
+ bpScopes = append(bpScopes, bs)
+
+ plan := make(core.PipelinePlan, len(bpScopes))
+ scopes := make([]core.Scope, 0, len(bpScopes))
+ for i, bpScope := range bpScopes {
+ githubRepo := &models.GithubRepo{
+ ConnectionId: 1,
+ GithubId: 12345,
+ Name: "testRepo",
+ OwnerLogin: "test",
+ CreatedDate: time.Time{},
+ }
+
+ transformationRule := &models.TransformationRules{
+ Model: common.Model{
+ ID: 1,
+ },
+ PrType: "hey,man,wasup",
+ ReffdiffRule: json.RawMessage(`{
"tagsPattern": "pattern",
"tagsLimit": 10,
"tagsOrder": "reverse semver"
- },
- "productionPattern": "xxxx"
- }`),
- }
- scopes := make([]*core.BlueprintScopeV100, 0)
- scopes = append(scopes, bs)
- plan, err := makePipelinePlan(nil, scopes, mockApiCLient, connection)
- assert.Nil(t, err)
+ }`),
+ }
+ var scope []core.Scope
+ plan, scope, err = makeDataSourcePipelinePlanV200(nil, i, plan, bpScope, connection, mockApiCLient, githubRepo, transformationRule)
+ assert.Nil(t, err)
+ scopes = append(scopes, scope...)
+ }
expectPlan := core.PipelinePlan{
core.PipelineStage{
{
- Plugin: "github",
- Subtasks: []string{},
+ Plugin: "github",
+ Subtasks: []string{},
+ SkipOnFail: false,
Options: map[string]interface{}{
"connectionId": uint64(1),
"owner": "test",
@@ -101,7 +121,8 @@ func TestProcessScope(t *testing.T) {
},
},
{
- Plugin: "gitextractor",
+ Plugin: "gitextractor",
+ SkipOnFail: false,
Options: map[string]interface{}{
"proxy": "",
"repoId": "github:GithubRepo:1:12345",
@@ -111,7 +132,8 @@ func TestProcessScope(t *testing.T) {
},
core.PipelineStage{
{
- Plugin: "refdiff",
+ Plugin: "refdiff",
+ SkipOnFail: false,
Options: map[string]interface{}{
"tagsLimit": float64(10),
"tagsOrder": "reverse semver",
@@ -119,18 +141,27 @@ func TestProcessScope(t *testing.T) {
},
},
},
- core.PipelineStage{
- {
- Plugin: "dora",
- Subtasks: []string{"EnrichTaskEnv"},
- Options: map[string]interface{}{
- "repoId": "github:GithubRepo:1:12345",
- "transformationRules": map[string]interface{}{
- "productionPattern": "xxxx",
- },
- },
- },
- },
}
assert.Equal(t, expectPlan, plan)
+ expectScopes := make([]core.Scope, 0)
+ scopeRepo := &code.Repo{
+ DomainEntity: domainlayer.DomainEntity{
+ Id: "github:GithubRepo:1:12345",
+ },
+ Name: "test/testRepo",
+ }
+
+ scopeTicket := &ticket.Board{
+ DomainEntity: domainlayer.DomainEntity{
+ Id: "github:GithubRepo:1:12345",
+ },
+ Name: "test/testRepo",
+ Description: "",
+ Url: "",
+ CreatedDate: nil,
+ Type: "",
+ }
+
+ expectScopes = append(expectScopes, scopeRepo, scopeTicket)
+ assert.Equal(t, expectScopes, scopes)
}
diff --git a/plugins/github/api/blueprint_test.go b/plugins/github/api/blueprint_test.go
index 9a35c14d9..8bb4f3df3 100644
--- a/plugins/github/api/blueprint_test.go
+++ b/plugins/github/api/blueprint_test.go
@@ -20,6 +20,7 @@ package api
import (
"bytes"
"encoding/json"
+ "github.com/apache/incubator-devlake/errors"
"github.com/apache/incubator-devlake/mocks"
"github.com/apache/incubator-devlake/models/common"
"github.com/apache/incubator-devlake/plugins/core"
@@ -33,7 +34,32 @@ import (
"testing"
)
-func TestProcessScope(t *testing.T) {
+var bs = &core.BlueprintScopeV100{
+ Entities: []string{"CODE"},
+ Options: json.RawMessage(`{
+ "owner": "test",
+ "repo": "testRepo"
+ }`),
+ Transformation: json.RawMessage(`{
+ "prType": "hey,man,wasup",
+ "refdiff": {
+ "tagsPattern": "pattern",
+ "tagsLimit": 10,
+ "tagsOrder": "reverse semver"
+ },
+ "productionPattern": "xxxx"
+ }`),
+}
+
+var repo = &tasks.GithubApiRepo{
+ GithubId: 12345,
+ CloneUrl: "https://this_is_cloneUrl",
+ CreatedAt: helper.Iso8601Time{},
+}
+
+func TestMakePipelinePlan(t *testing.T) {
+ prepareMockMeta(t)
+ mockApiClient := prepareMockClient(t, repo)
connection := &models.GithubConnection{
RestConnection: helper.RestConnection{
BaseConnection: helper.BaseConnection{
@@ -50,40 +76,9 @@ func TestProcessScope(t *testing.T) {
Token: "123",
},
}
- mockApiCLient := mocks.NewApiClientGetter(t)
- repo := &tasks.GithubApiRepo{
- GithubId: 12345,
- CloneUrl: "https://this_is_cloneUrl",
- }
- js, err := json.Marshal(repo)
- assert.Nil(t, err)
- res := &http.Response{}
- res.Body = io.NopCloser(bytes.NewBuffer(js))
- res.StatusCode = http.StatusOK
- mockApiCLient.On("Get", "repos/test/testRepo", mock.Anything, mock.Anything).Return(res, nil)
- mockMeta := mocks.NewPluginMeta(t)
- mockMeta.On("RootPkgPath").Return("github.com/apache/incubator-devlake/plugins/github")
- err = core.RegisterPlugin("github", mockMeta)
- assert.Nil(t, err)
- bs := &core.BlueprintScopeV100{
- Entities: []string{"CODE"},
- Options: json.RawMessage(`{
- "owner": "test",
- "repo": "testRepo"
- }`),
- Transformation: json.RawMessage(`{
- "prType": "hey,man,wasup",
- "refdiff": {
- "tagsPattern": "pattern",
- "tagsLimit": 10,
- "tagsOrder": "reverse semver"
- },
- "productionPattern": "xxxx"
- }`),
- }
scopes := make([]*core.BlueprintScopeV100, 0)
scopes = append(scopes, bs)
- plan, err := makePipelinePlan(nil, scopes, mockApiCLient, connection)
+ plan, err := makePipelinePlan(nil, scopes, mockApiClient, connection)
assert.Nil(t, err)
expectPlan := core.PipelinePlan{
@@ -134,3 +129,52 @@ func TestProcessScope(t *testing.T) {
}
assert.Equal(t, expectPlan, plan)
}
+
+func TestMemorizedGetApiRepo(t *testing.T) {
+ op := prepareOptions(t, bs)
+ expect := repo
+ repo1, err := memorizedGetApiRepo(repo, op, nil)
+ assert.Nil(t, err)
+ assert.Equal(t, expect, repo1)
+ mockApiClient := prepareMockClient(t, repo)
+ repo2, err := memorizedGetApiRepo(nil, op, mockApiClient)
+ assert.Nil(t, err)
+ assert.NotEqual(t, expect, repo2)
+}
+
+func TestGetApiRepo(t *testing.T) {
+ op := prepareOptions(t, bs)
+ mockClient := prepareMockClient(t, repo)
+ repo1, err := getApiRepo(op, mockClient)
+ assert.Nil(t, err)
+ assert.Equal(t, repo.GithubId, repo1.GithubId)
+}
+
+func prepareMockMeta(t *testing.T) {
+ mockMeta := mocks.NewPluginMeta(t)
+ mockMeta.On("RootPkgPath").Return("github.com/apache/incubator-devlake/plugins/github")
+ err := core.RegisterPlugin("github", mockMeta)
+ assert.Nil(t, err)
+}
+
+func prepareMockClient(t *testing.T, repo *tasks.GithubApiRepo) *mocks.ApiClientGetter {
+ mockApiCLient := mocks.NewApiClientGetter(t)
+ js, err := json.Marshal(repo)
+ assert.Nil(t, err)
+ res := &http.Response{}
+ res.Body = io.NopCloser(bytes.NewBuffer(js))
+ res.StatusCode = http.StatusOK
+ mockApiCLient.On("Get", "repos/test/testRepo", mock.Anything, mock.Anything).Return(res, nil)
+ return mockApiCLient
+}
+
+func prepareOptions(t *testing.T, bs *core.BlueprintScopeV100) *tasks.GithubOptions {
+ options := make(map[string]interface{})
+ err := errors.Convert(json.Unmarshal(bs.Options, &options))
+ assert.Nil(t, err)
+ options["connectionId"] = 1
+ // make sure task options is valid
+ op, err := tasks.DecodeAndValidateTaskOptions(options)
+ assert.Nil(t, err)
+ return op
+}
diff --git a/plugins/github/api/blueprint_v200.go b/plugins/github/api/blueprint_v200.go
new file mode 100644
index 000000000..fdc320d0d
--- /dev/null
+++ b/plugins/github/api/blueprint_v200.go
@@ -0,0 +1,210 @@
+/*
+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 (
+ "context"
+ "encoding/json"
+ goerror "errors"
+ "fmt"
+ "github.com/apache/incubator-devlake/errors"
+ "github.com/apache/incubator-devlake/models/domainlayer"
+ "github.com/apache/incubator-devlake/models/domainlayer/code"
+ "github.com/apache/incubator-devlake/models/domainlayer/devops"
+ "github.com/apache/incubator-devlake/models/domainlayer/didgen"
+ "github.com/apache/incubator-devlake/models/domainlayer/ticket"
+ "github.com/apache/incubator-devlake/plugins/core/dal"
+ "github.com/apache/incubator-devlake/plugins/github/tasks"
+ "github.com/apache/incubator-devlake/utils"
+ "github.com/go-playground/validator/v10"
+ "github.com/mitchellh/mapstructure"
+ "gorm.io/gorm"
+ "strings"
+ "time"
+
+ "github.com/apache/incubator-devlake/plugins/core"
+ "github.com/apache/incubator-devlake/plugins/github/models"
+ "github.com/apache/incubator-devlake/plugins/helper"
+)
+
+func MakeDataSourcePipelinePlanV200(subtaskMetas []core.SubTaskMeta, connectionId uint64, bpScopes []*core.BlueprintScopeV200) (core.PipelinePlan, []core.Scope, errors.Error) {
+ db := basicRes.GetDal()
+ connectionHelper := helper.NewConnectionHelper(basicRes, validator.New())
+ // get the connection info for url
+ connection := &models.GithubConnection{}
+ err := connectionHelper.FirstById(connection, connectionId)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ token := strings.Split(connection.Token, ",")[0]
+ apiClient, err := helper.NewApiClient(
+ context.TODO(),
+ connection.Endpoint,
+ map[string]string{
+ "Authorization": fmt.Sprintf("Bearer %s", token),
+ },
+ 10*time.Second,
+ connection.Proxy,
+ basicRes,
+ )
+ if err != nil {
+ return nil, nil, err
+ }
+
+ plan := make(core.PipelinePlan, 0, len(bpScopes))
+ scopes := make([]core.Scope, 0, len(bpScopes))
+ for i, bpScope := range bpScopes {
+ var githubRepo *models.GithubRepo
+ // get repo from db
+ err = db.First(githubRepo, dal.Where(`id = ?`, bpScope.Id))
+ if err != nil {
+ return nil, nil, err
+ }
+ var transformationRule *models.TransformationRules
+ // get transformation rules from db
+ err = db.First(transformationRule, dal.Where(`id = ?`, githubRepo.TransformationRuleId))
+ if err != nil && goerror.Is(err, gorm.ErrRecordNotFound) {
+ return nil, nil, err
+ }
+ var scope []core.Scope
+ // make pipeline for each bpScope
+ plan, scope, err = makeDataSourcePipelinePlanV200(subtaskMetas, i, plan, bpScope, connection, apiClient, githubRepo, transformationRule)
+ if err != nil {
+ return nil, nil, err
+ }
+ if len(scope) > 0 {
+ scopes = append(scopes, scope...)
+ }
+
+ }
+
+ return plan, scopes, nil
+}
+
+func makeDataSourcePipelinePlanV200(
+ subtaskMetas []core.SubTaskMeta,
+ i int,
+ plan core.PipelinePlan,
+ bpScope *core.BlueprintScopeV200,
+ connection *models.GithubConnection,
+ apiClient helper.ApiClientGetter,
+ githubRepo *models.GithubRepo,
+ transformationRule *models.TransformationRules,
+) (core.PipelinePlan, []core.Scope, errors.Error) {
+ var err errors.Error
+ var stage core.PipelineStage
+ var repo *tasks.GithubApiRepo
+ scopes := make([]core.Scope, 0)
+ // refdiff
+ if transformationRule != nil && transformationRule.ReffdiffRule != nil {
+ // add a new task to next stage
+ j := i + 1
+ if j == len(plan) {
+ plan = append(plan, nil)
+ }
+ refdiffOp := map[string]interface{}{}
+ err = errors.Convert(json.Unmarshal(transformationRule.ReffdiffRule, &refdiffOp))
+ if err != nil {
+ return nil, nil, err
+ }
+ plan[j] = core.PipelineStage{
+ {
+ Plugin: "refdiff",
+ Options: refdiffOp,
+ },
+ }
+ }
+
+ // construct task options for github
+ var options map[string]interface{}
+ err = errors.Convert(mapstructure.Decode(githubRepo, &options))
+ if err != nil {
+ return nil, nil, err
+ }
+ // make sure task options is valid
+ op, err := tasks.DecodeAndValidateTaskOptions(options)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ var transformationRuleMap map[string]interface{}
+ err = errors.Convert(mapstructure.Decode(transformationRule, &transformationRuleMap))
+ if err != nil {
+ return nil, nil, err
+ }
+ options["transformationRules"] = transformationRuleMap
+ stage, err = addGithub(subtaskMetas, connection, bpScope.Entities, stage, options)
+ if err != nil {
+ return nil, nil, err
+ }
+ // add gitex stage and add repo to scopes
+ if utils.StringsContains(bpScope.Entities, core.DOMAIN_TYPE_CODE) {
+ repo, err = memorizedGetApiRepo(repo, op, apiClient)
+ if err != nil {
+ return nil, nil, err
+ }
+ stage, err = addGitex(bpScope.Entities, connection, repo, stage)
+ if err != nil {
+ return nil, nil, err
+ }
+ scopeRepo := &code.Repo{
+ DomainEntity: domainlayer.DomainEntity{
+ Id: didgen.NewDomainIdGenerator(&models.GithubRepo{}).Generate(connection.ID, githubRepo.GithubId),
+ },
+ Name: fmt.Sprintf("%s/%s", githubRepo.OwnerLogin, githubRepo.Name),
+ }
+ if repo.Parent != nil {
+ scopeRepo.ForkedFrom = repo.Parent.HTMLUrl
+ }
+ scopes = append(scopes, scopeRepo)
+ } else if utils.StringsContains(bpScope.Entities, core.DOMAIN_TYPE_CODE_REVIEW) {
+ // if we don't need to collect gitex, we need to add repo to scopes here
+ scopeRepo := &code.Repo{
+ DomainEntity: domainlayer.DomainEntity{
+ Id: didgen.NewDomainIdGenerator(&models.GithubRepo{}).Generate(connection.ID, githubRepo.GithubId),
+ },
+ Name: fmt.Sprintf("%s/%s", githubRepo.OwnerLogin, githubRepo.Name),
+ }
+ scopes = append(scopes, scopeRepo)
+ }
+ // add cicd_scope to scopes
+ if utils.StringsContains(bpScope.Entities, core.DOMAIN_TYPE_CICD) {
+ scopeCICD := &devops.CicdScope{
+ DomainEntity: domainlayer.DomainEntity{
+ Id: didgen.NewDomainIdGenerator(&models.GithubRepo{}).Generate(connection.ID, githubRepo.GithubId),
+ },
+ Name: fmt.Sprintf("%s/%s", githubRepo.OwnerLogin, githubRepo.Name),
+ }
+ scopes = append(scopes, scopeCICD)
+ }
+ // add board to scopes
+ if utils.StringsContains(bpScope.Entities, core.DOMAIN_TYPE_TICKET) {
+ scopeTicket := &ticket.Board{
+ DomainEntity: domainlayer.DomainEntity{
+ Id: didgen.NewDomainIdGenerator(&models.GithubRepo{}).Generate(connection.ID, githubRepo.GithubId),
+ },
+ Name: fmt.Sprintf("%s/%s", githubRepo.OwnerLogin, githubRepo.Name),
+ }
+ scopes = append(scopes, scopeTicket)
+ }
+
+ plan[i] = stage
+
+ return plan, scopes, nil
+}
diff --git a/plugins/github/impl/impl.go b/plugins/github/impl/impl.go
index e8281794d..ae869d2ce 100644
--- a/plugins/github/impl/impl.go
+++ b/plugins/github/impl/impl.go
@@ -245,6 +245,10 @@ func (plugin Github) MakePipelinePlan(connectionId uint64, scope []*core.Bluepri
return api.MakePipelinePlan(plugin.SubTaskMetas(), connectionId, scope)
}
+func (plugin Github) MakeDataSourcePipelinePlanV200(connectionId uint64, scopes []*core.BlueprintScopeV200) (pp core.PipelinePlan, sc []core.Scope, err errors.Error) {
+ return api.MakeDataSourcePipelinePlanV200(plugin.SubTaskMetas(), connectionId, scopes)
+}
+
func (plugin Github) Close(taskCtx core.TaskContext) errors.Error {
data, ok := taskCtx.GetData().(*tasks.GithubTaskData)
if !ok {
diff --git a/plugins/github/models/repo.go b/plugins/github/models/repo.go
index 5ae5516ba..58613375b 100644
--- a/plugins/github/models/repo.go
+++ b/plugins/github/models/repo.go
@@ -23,20 +23,20 @@ import (
)
type GithubRepo struct {
- ConnectionId uint64 `gorm:"primaryKey"`
- GithubId int `gorm:"primaryKey"`
- TransformationRuleId uint64
- Name string `gorm:"type:varchar(255)"`
- HTMLUrl string `gorm:"type:varchar(255)"`
- Description string
- OwnerId int `json:"ownerId"`
- OwnerLogin string `json:"ownerLogin" gorm:"type:varchar(255)"`
- Language string `json:"language" gorm:"type:varchar(255)"`
- ParentGithubId int `json:"parentId"`
- ParentHTMLUrl string `json:"parentHtmlUrl"`
- CreatedDate time.Time `json:"createdDate"`
- UpdatedDate *time.Time `json:"updatedDate"`
- common.NoPKModel
+ ConnectionId uint64 `gorm:"primaryKey" mapstructure:"connectionId,omitempty"`
+ GithubId int `gorm:"primaryKey" mapstructure:"-"`
+ Name string `gorm:"type:varchar(255)" mapstructure:"repo,omitempty"`
+ HTMLUrl string `gorm:"type:varchar(255)" mapstructure:"htmlUrl,omitempty"`
+ Description string `mapstructure:"description,omitempty"`
+ TransformationRuleId uint64 `mapstructure:"transformationRules,omitempty"`
+ OwnerId int `json:"ownerId" mapstructure:"ownerId,omitempty"`
+ OwnerLogin string `json:"ownerLogin" gorm:"type:varchar(255)" mapstructure:"owner,omitempty"`
+ Language string `json:"language" gorm:"type:varchar(255)" mapstructure:"language,omitempty"`
+ ParentGithubId int `json:"parentId" mapstructure:"parentId,omitempty"`
+ ParentHTMLUrl string `json:"parentHtmlUrl" mapstructure:"parentHtmlUrl,omitempty"`
+ CreatedDate time.Time `json:"createdDate" mapstructure:"-"`
+ UpdatedDate *time.Time `json:"updatedDate" mapstructure:"-"`
+ common.NoPKModel `mapstructure:"-"`
}
func (GithubRepo) TableName() string {
diff --git a/plugins/github/models/transformation_rule.go b/plugins/github/models/transformation_rule.go
index f53eece58..16af8bb80 100644
--- a/plugins/github/models/transformation_rule.go
+++ b/plugins/github/models/transformation_rule.go
@@ -24,18 +24,18 @@ import (
)
type TransformationRules struct {
- common.Model
- PrType string `mapstructure:"prType" json:"prType" gorm:"type:varchar(255)"`
- PrComponent string `mapstructure:"prComponent" json:"prComponent" gorm:"type:varchar(255)"`
- PrBodyClosePattern string `mapstructure:"prBodyClosePattern" json:"prBodyClosePattern" gorm:"type:varchar(255)"`
- IssueSeverity string `mapstructure:"issueSeverity" json:"issueSeverity" gorm:"type:varchar(255)"`
- IssuePriority string `mapstructure:"issuePriority" json:"issuePriority" gorm:"type:varchar(255)"`
- IssueComponent string `mapstructure:"issueComponent" json:"issueComponent" gorm:"type:varchar(255)"`
- IssueTypeBug string `mapstructure:"issueTypeBug" json:"issueTypeBug" gorm:"type:varchar(255)"`
- IssueTypeIncident string `mapstructure:"issueTypeIncident" json:"issueTypeIncident" gorm:"type:varchar(255)"`
- IssueTypeRequirement string `mapstructure:"issueTypeRequirement" json:"issueTypeRequirement" gorm:"type:varchar(255)"`
- DeploymentPattern string `mapstructure:"deploymentPattern" json:"deploymentPattern" gorm:"type:varchar(255)"`
- RefdiffRule json.RawMessage `mapstructure:"refdiffRule" json:"refdiffRule"`
+ common.Model `mapstructure:"-"`
+ PrType string `mapstructure:"prType,omitempty" json:"prType" gorm:"type:varchar(255)"`
+ PrComponent string `mapstructure:"prComponent,omitempty" json:"prComponent" gorm:"type:varchar(255)"`
+ PrBodyClosePattern string `mapstructure:"prBodyClosePattern,omitempty" json:"prBodyClosePattern" gorm:"type:varchar(255)"`
+ IssueSeverity string `mapstructure:"issueSeverity,omitempty" json:"issueSeverity" gorm:"type:varchar(255)"`
+ IssuePriority string `mapstructure:"issuePriority,omitempty" json:"issuePriority" gorm:"type:varchar(255)"`
+ IssueComponent string `mapstructure:"issueComponent,omitempty" json:"issueComponent" gorm:"type:varchar(255)"`
+ IssueTypeBug string `mapstructure:"issueTypeBug,omitempty" json:"issueTypeBug" gorm:"type:varchar(255)"`
+ IssueTypeIncident string `mapstructure:"issueTypeIncident,omitempty" json:"issueTypeIncident" gorm:"type:varchar(255)"`
+ IssueTypeRequirement string `mapstructure:"issueTypeRequirement,omitempty" json:"issueTypeRequirement" gorm:"type:varchar(255)"`
+ DeploymentPattern string `mapstructure:"deploymentPattern,omitempty" json:"deploymentPattern" gorm:"type:varchar(255)"`
+ ReffdiffRule json.RawMessage `mapstructure:"-" json:"refdiff"`
}
func (TransformationRules) TableName() string {