You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@devlake.apache.org by kl...@apache.org on 2022/12/26 10:00:43 UTC

[incubator-devlake] branch main updated: fix(plugins): modify dora and refdiff (#4026)

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 e71353806 fix(plugins): modify dora and refdiff (#4026)
e71353806 is described below

commit e71353806bbf210d1158c81dc1e9c888812bf229
Author: Warren Chen <yi...@merico.dev>
AuthorDate: Mon Dec 26 18:00:37 2022 +0800

    fix(plugins): modify dora and refdiff (#4026)
---
 plugins/dora/e2e/env_enricher_test.go              |  62 --------
 .../dora/e2e/snapshot_tables/enrich_cicd_tasks.csv |  19 ---
 plugins/dora/impl/impl.go                          |   2 +
 .../dora/tasks/change_lead_time_calculator_old.go  | 164 +++++++++++++++++++++
 plugins/dora/tasks/cicd_task_env_enricher.go       |  54 +------
 .../dora/tasks/incident_deploy_connector_old.go    | 109 ++++++++++++++
 plugins/dora/tasks/task_data.go                    |   2 +
 plugins/github/api/blueprint.go                    |  52 ++++---
 plugins/github/api/blueprint_test.go               |  11 +-
 plugins/gitlab/api/blueprint.go                    |  55 +++----
 plugins/gitlab/api/blueprint_test.go               |  11 +-
 plugins/jenkins/api/blueprint_v100.go              |  12 +-
 plugins/jenkins/api/blueprint_v100_test.go         |   7 +-
 services/blueprint_makeplan_v100.go                |   2 +-
 14 files changed, 349 insertions(+), 213 deletions(-)

diff --git a/plugins/dora/e2e/env_enricher_test.go b/plugins/dora/e2e/env_enricher_test.go
deleted file mode 100644
index c3a077b90..000000000
--- a/plugins/dora/e2e/env_enricher_test.go
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
-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 e2e
-
-import (
-	"github.com/apache/incubator-devlake/models/domainlayer/crossdomain"
-	"testing"
-
-	"github.com/apache/incubator-devlake/helpers/e2ehelper"
-	"github.com/apache/incubator-devlake/models/domainlayer/devops"
-	"github.com/apache/incubator-devlake/plugins/dora/impl"
-	"github.com/apache/incubator-devlake/plugins/dora/tasks"
-)
-
-func TestEnrichEnvDataFlow(t *testing.T) {
-	var plugin impl.Dora
-	dataflowTester := e2ehelper.NewDataFlowTester(t, "dora", plugin)
-
-	taskData := &tasks.DoraTaskData{
-		Options: &tasks.DoraOptions{
-			ProjectName: "project1",
-			TransformationRules: tasks.TransformationRules{
-				ProductionPattern: "(?i)deploy",
-				StagingPattern:    "(?i)stag",
-				TestingPattern:    "(?i)test",
-			},
-		},
-	}
-
-	// import raw data table
-	dataflowTester.ImportCsvIntoTabler("./raw_tables/project_mapping.csv", &crossdomain.ProjectMapping{})
-	dataflowTester.ImportCsvIntoTabler("./raw_tables/cicd_tasks_for_enrich_env.csv", &devops.CICDTask{})
-
-	// verify enrich with repoId
-	dataflowTester.Subtask(tasks.EnrichTaskEnvMeta, taskData)
-	dataflowTester.VerifyTable(
-		&devops.CICDTask{},
-		"./snapshot_tables/enrich_cicd_tasks.csv",
-		[]string{
-			"id",
-			"name",
-			"environment",
-			"type",
-			"cicd_scope_id",
-		},
-	)
-}
diff --git a/plugins/dora/e2e/snapshot_tables/enrich_cicd_tasks.csv b/plugins/dora/e2e/snapshot_tables/enrich_cicd_tasks.csv
deleted file mode 100644
index ee52b8d1d..000000000
--- a/plugins/dora/e2e/snapshot_tables/enrich_cicd_tasks.csv
+++ /dev/null
@@ -1,19 +0,0 @@
-id,name,environment,type,cicd_scope_id
-task10,deployxIG,PRODUCTION,DEPLOYMENT,cicd1
-task11,deploya,PRODUCTION,DEPLOYMENT,cicd1
-task12,deployc,PRODUCTION,DEPLOYMENT,cicd2
-task13,deploy,PRODUCTION,DEPLOYMENT,cicd1
-task14,deployp0;,PRODUCTION,DEPLOYMENT,cicd1
-task15,deployY{,PRODUCTION,DEPLOYMENT,cicd2
-task16,deploy8',PRODUCTION,DEPLOYMENT,cicd1
-task17,deployKd%,PRODUCTION,DEPLOYMENT,cicd1
-task19,deploy1,PRODUCTION,DEPLOYMENT,cicd1
-task21,deploy^^.,PRODUCTION,DEPLOYMENT,cicd1
-task22,deploy,PRODUCTION,DEPLOYMENT,cicd1
-task23,deploy,PRODUCTION,DEPLOYMENT,cicd1
-task24,deploym,PRODUCTION,DEPLOYMENT,cicd1
-task25,deploy$p<,,,cicd3
-task26,deployb>@,PRODUCTION,DEPLOYMENT,cicd2
-task27,deployKfn,PRODUCTION,DEPLOYMENT,cicd2
-task28,deployl?,,DEPLOYMENT,cicd3
-task29,deployUb,PRODUCTION,DEPLOYMENT,cicd2
diff --git a/plugins/dora/impl/impl.go b/plugins/dora/impl/impl.go
index 82fdf870e..cd8064362 100644
--- a/plugins/dora/impl/impl.go
+++ b/plugins/dora/impl/impl.go
@@ -85,6 +85,8 @@ func (plugin Dora) SubTaskMetas() []core.SubTaskMeta {
 		tasks.EnrichTaskEnvMeta,
 		tasks.CalculateChangeLeadTimeMeta,
 		tasks.ConnectIncidentToDeploymentMeta,
+		tasks.CalculateChangeLeadTimeOldMeta,
+		tasks.ConnectIncidentToDeploymentOldMeta,
 	}
 }
 
diff --git a/plugins/dora/tasks/change_lead_time_calculator_old.go b/plugins/dora/tasks/change_lead_time_calculator_old.go
new file mode 100644
index 000000000..1fa9795af
--- /dev/null
+++ b/plugins/dora/tasks/change_lead_time_calculator_old.go
@@ -0,0 +1,164 @@
+/*
+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/models/domainlayer/crossdomain"
+	"github.com/apache/incubator-devlake/models/domainlayer/devops"
+	"reflect"
+	"time"
+
+	"github.com/apache/incubator-devlake/errors"
+	"github.com/apache/incubator-devlake/models/domainlayer/code"
+	"github.com/apache/incubator-devlake/plugins/core"
+	"github.com/apache/incubator-devlake/plugins/core/dal"
+	"github.com/apache/incubator-devlake/plugins/helper"
+)
+
+// CalculateChangeLeadTimeOldMeta will be removed in v0.17
+// DEPRECATED
+func CalculateChangeLeadTimeOld(taskCtx core.SubTaskContext) errors.Error {
+	db := taskCtx.GetDal()
+	log := taskCtx.GetLogger()
+	clauses := []dal.Clause{
+		dal.From(&code.PullRequest{}),
+		dal.Where("merged_date IS NOT NULL"),
+	}
+	cursor, err := db.Cursor(clauses...)
+	if err != nil {
+		return err
+	}
+	defer cursor.Close()
+
+	enricher, err := helper.NewDataConverter(helper.DataConverterArgs{
+		RawDataSubTaskArgs: helper.RawDataSubTaskArgs{
+			Ctx:    taskCtx,
+			Params: DoraApiParams{
+				// TODO
+			},
+			Table: "pull_requests",
+		},
+		BatchSize:    100,
+		InputRowType: reflect.TypeOf(code.PullRequest{}),
+		Input:        cursor,
+		Convert: func(inputRow interface{}) ([]interface{}, errors.Error) {
+			pr := inputRow.(*code.PullRequest)
+			firstCommit, err := getFirstCommit(pr.Id, db)
+			if err != nil {
+				return nil, err
+			}
+			projectPrMetric := &crossdomain.ProjectPrMetric{}
+			projectPrMetric.Id = pr.Id
+			projectPrMetric.ProjectName = "DEFAULT_PROJECT_NAME"
+			if err != nil {
+				return nil, err
+			}
+			if firstCommit != nil {
+				codingTime := int64(pr.CreatedDate.Sub(firstCommit.AuthoredDate).Seconds())
+				if codingTime/60 == 0 && codingTime%60 > 0 {
+					codingTime = 1
+				} else {
+					codingTime = codingTime / 60
+				}
+				projectPrMetric.PrCodingTime = processNegativeValue(codingTime)
+				projectPrMetric.FirstCommitSha = firstCommit.Sha
+			}
+			firstReview, err := getFirstReview(pr.Id, pr.AuthorId, db)
+			if err != nil {
+				return nil, err
+			}
+			if firstReview != nil {
+				projectPrMetric.PrPickupTime = processNegativeValue(int64(firstReview.CreatedDate.Sub(pr.CreatedDate).Minutes()))
+				projectPrMetric.PrReviewTime = processNegativeValue(int64(pr.MergedDate.Sub(firstReview.CreatedDate).Minutes()))
+				projectPrMetric.FirstReviewId = firstReview.ReviewId
+			}
+			deployment, err := getDeploymentOld(devops.PRODUCTION, *pr.MergedDate, db)
+			if err != nil {
+				return nil, err
+			}
+			if deployment != nil && deployment.FinishedDate != nil {
+				timespan := deployment.FinishedDate.Sub(*pr.MergedDate)
+				projectPrMetric.PrDeployTime = processNegativeValue(int64(timespan.Minutes()))
+				projectPrMetric.DeploymentId = deployment.Id
+			} else {
+				log.Debug("deploy time of pr %v is nil\n", pr.PullRequestKey)
+			}
+			projectPrMetric.PrCycleTime = nil
+			var result int64
+			if projectPrMetric.PrCodingTime != nil {
+				result += *projectPrMetric.PrCodingTime
+			}
+			if projectPrMetric.PrPickupTime != nil {
+				result += *projectPrMetric.PrPickupTime
+			}
+			if projectPrMetric.PrReviewTime != nil {
+				result += *projectPrMetric.PrReviewTime
+			}
+			if projectPrMetric.PrDeployTime != nil {
+				result += *projectPrMetric.PrDeployTime
+			}
+			if result > 0 {
+				projectPrMetric.PrCycleTime = &result
+			}
+			return []interface{}{projectPrMetric}, nil
+		},
+	})
+	if err != nil {
+		return err
+	}
+
+	return enricher.Execute()
+}
+
+func getDeploymentOld(environment string, mergeDate time.Time, db dal.Dal) (*devops.CICDTask, errors.Error) {
+	// ignore environment at this point because detecting it by name is obviously not engouh
+	// take https://github.com/apache/incubator-devlake/actions/workflows/build.yml for example
+	// one can not distingush testing/production by looking at the job name solely.
+	cicdTask := &devops.CICDTask{}
+	cicdTaskClauses := []dal.Clause{
+		dal.From(&devops.CICDTask{}),
+		dal.Where(`
+			type = ?
+			AND cicd_tasks.result = ?
+			AND cicd_tasks.started_date > ?`,
+			"DEPLOYMENT",
+			"SUCCESS",
+			mergeDate,
+		),
+		dal.Orderby("cicd_tasks.started_date ASC"),
+		dal.Limit(1),
+	}
+	err := db.First(cicdTask, cicdTaskClauses...)
+	if db.IsErrorNotFound(err) {
+		return nil, nil
+	}
+	if err != nil {
+		return nil, err
+	}
+	return cicdTask, nil
+}
+
+// CalculateChangeLeadTimeOldMeta will be removed in v0.17
+// DEPRECATED
+var CalculateChangeLeadTimeOldMeta = core.SubTaskMeta{
+	Name:             "calculateChangeLeadTimeOld",
+	EntryPoint:       CalculateChangeLeadTimeOld,
+	EnabledByDefault: false,
+	Description:      "Calculate change lead time",
+	DomainTypes:      []string{core.DOMAIN_TYPE_CICD, core.DOMAIN_TYPE_CODE},
+}
diff --git a/plugins/dora/tasks/cicd_task_env_enricher.go b/plugins/dora/tasks/cicd_task_env_enricher.go
index 1fcd5add8..fbb53cdbe 100644
--- a/plugins/dora/tasks/cicd_task_env_enricher.go
+++ b/plugins/dora/tasks/cicd_task_env_enricher.go
@@ -18,16 +18,12 @@ limitations under the License.
 package tasks
 
 import (
-	"reflect"
-	"regexp"
-
 	"github.com/apache/incubator-devlake/errors"
-	"github.com/apache/incubator-devlake/models/domainlayer/devops"
 	"github.com/apache/incubator-devlake/plugins/core"
-	"github.com/apache/incubator-devlake/plugins/core/dal"
-	"github.com/apache/incubator-devlake/plugins/helper"
 )
 
+// EnrichTaskEnvMeta will be removed in v0.17
+// DEPRECATED
 var EnrichTaskEnvMeta = core.SubTaskMeta{
 	Name:             "EnrichTaskEnv",
 	EntryPoint:       EnrichTasksEnv,
@@ -37,49 +33,5 @@ var EnrichTaskEnvMeta = core.SubTaskMeta{
 }
 
 func EnrichTasksEnv(taskCtx core.SubTaskContext) (err errors.Error) {
-	db := taskCtx.GetDal()
-	data := taskCtx.GetData().(*DoraTaskData)
-	projectName := data.Options.ProjectName
-
-	productionNamePattern := data.Options.ProductionPattern
-	productionNameRegexp, err := errors.Convert01(regexp.Compile(productionNamePattern))
-	if err != nil {
-		return err
-	}
-
-	cursor, err := db.Cursor(
-		dal.From(`cicd_tasks ct`),
-		dal.Join("left join project_mapping pm on pm.row_id = ct.cicd_scope_id"),
-		dal.Where(`pm.project_name = ? and pm.table = ?`, projectName, "cicd_scopes"),
-	)
-
-	if err != nil {
-		return err
-	}
-
-	defer cursor.Close()
-	converter, err := helper.NewDataConverter(helper.DataConverterArgs{
-		RawDataSubTaskArgs: helper.RawDataSubTaskArgs{
-			Ctx: taskCtx,
-			Params: DoraApiParams{
-				ProjectName: projectName,
-			},
-			Table: "cicd_tasks",
-		},
-		InputRowType: reflect.TypeOf(devops.CICDTask{}),
-		Input:        cursor,
-		Convert: func(inputRow interface{}) ([]interface{}, errors.Error) {
-			cicdTask := inputRow.(*devops.CICDTask)
-			if productionNamePattern == "" || productionNameRegexp.FindString(cicdTask.Name) != "" {
-				cicdTask.Environment = devops.PRODUCTION
-				return []interface{}{cicdTask}, nil
-			}
-			return nil, nil
-		},
-	})
-	if err != nil {
-		return err
-	}
-
-	return converter.Execute()
+	return nil
 }
diff --git a/plugins/dora/tasks/incident_deploy_connector_old.go b/plugins/dora/tasks/incident_deploy_connector_old.go
new file mode 100644
index 000000000..18a0f2e93
--- /dev/null
+++ b/plugins/dora/tasks/incident_deploy_connector_old.go
@@ -0,0 +1,109 @@
+/*
+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 (
+	"reflect"
+
+	"github.com/apache/incubator-devlake/models/domainlayer"
+	"github.com/apache/incubator-devlake/models/domainlayer/crossdomain"
+
+	"github.com/apache/incubator-devlake/errors"
+	"github.com/apache/incubator-devlake/models/domainlayer/devops"
+	"github.com/apache/incubator-devlake/models/domainlayer/ticket"
+	"github.com/apache/incubator-devlake/plugins/core"
+	"github.com/apache/incubator-devlake/plugins/core/dal"
+	"github.com/apache/incubator-devlake/plugins/helper"
+)
+
+// ConnectIncidentToDeploymentOldMeta will be removed in v0.17
+// DEPRECATED
+var ConnectIncidentToDeploymentOldMeta = core.SubTaskMeta{
+	Name:             "connectIncidentToDeploymentOld",
+	EntryPoint:       ConnectIncidentToDeploymentOld,
+	EnabledByDefault: false,
+	Description:      "Connect incident issue to deployment",
+	DomainTypes:      []string{core.DOMAIN_TYPE_CICD},
+}
+
+// ConnectIncidentToDeploymentOld will be removed in v0.17
+// DEPRECATED
+func ConnectIncidentToDeploymentOld(taskCtx core.SubTaskContext) errors.Error {
+	db := taskCtx.GetDal()
+	issue := &ticket.Issue{}
+	// select all issues belongs to the board
+	clauses := []dal.Clause{
+		dal.From(issue),
+		dal.Where(
+			"issues.type = ?", "INCIDENT",
+		),
+	}
+	cursor, err := db.Cursor(clauses...)
+	if err != nil {
+		return err
+	}
+	defer cursor.Close()
+
+	enricher, err := helper.NewDataConverter(helper.DataConverterArgs{
+		RawDataSubTaskArgs: helper.RawDataSubTaskArgs{
+			Ctx:    taskCtx,
+			Params: DoraApiParams{
+				// TODO
+			},
+			Table: "issues",
+		},
+		InputRowType: reflect.TypeOf(ticket.Issue{}),
+		Input:        cursor,
+		Convert: func(inputRow interface{}) ([]interface{}, errors.Error) {
+			issueToBeUpdate := inputRow.(*ticket.Issue)
+			cicdTask := &devops.CICDTask{}
+			cicdTakClauses := []dal.Clause{
+				dal.From(cicdTask),
+				dal.Join("left join cicd_pipeline_commits on cicd_tasks.pipeline_id = cicd_pipeline_commits.pipeline_id"),
+				dal.Where(
+					`cicd_tasks.finished_date < ? 
+								and cicd_tasks.result = ? and cicd_tasks.environment = ?`,
+					issueToBeUpdate.CreatedDate, "SUCCESS", devops.PRODUCTION,
+				),
+				dal.Orderby("cicd_tasks.finished_date DESC"),
+			}
+			err = db.First(cicdTask, cicdTakClauses...)
+			if err != nil {
+				if db.IsErrorNotFound(err) {
+					return nil, nil
+				} else {
+					return nil, err
+				}
+			}
+			projectIssueMetric := &crossdomain.ProjectIssueMetric{
+				DomainEntity: domainlayer.DomainEntity{
+					Id: issue.Id,
+				},
+				ProjectName: "DEFAULT_PROJECT_NAME",
+			}
+			projectIssueMetric.DeploymentId = cicdTask.Id
+
+			return []interface{}{projectIssueMetric}, nil
+		},
+	})
+	if err != nil {
+		return err
+	}
+
+	return enricher.Execute()
+}
diff --git a/plugins/dora/tasks/task_data.go b/plugins/dora/tasks/task_data.go
index 16ce528af..35e285159 100644
--- a/plugins/dora/tasks/task_data.go
+++ b/plugins/dora/tasks/task_data.go
@@ -36,6 +36,8 @@ type DoraOptions struct {
 	Tasks               []string `json:"tasks,omitempty"`
 	Since               string
 	RepoId              string `json:"repoId"`
+	CicdScopeId         string `json:"cicdScopeId"`
+	BoardId             string `json:"boardId"`
 	Prefix              string `json:"prefix"`
 	ProjectName         string `json:"projectName"`
 	TransformationRules `mapstructure:"transformationRules" json:"transformationRules"`
diff --git a/plugins/github/api/blueprint.go b/plugins/github/api/blueprint.go
index 9f4c54f21..3afd41514 100644
--- a/plugins/github/api/blueprint.go
+++ b/plugins/github/api/blueprint.go
@@ -77,6 +77,20 @@ func makePipelinePlan(subtaskMetas []core.SubTaskMeta, scopeV100s []*core.Bluepr
 				return nil, err
 			}
 		}
+		// construct task options for github
+		options := make(map[string]interface{})
+		err = errors.Convert(json.Unmarshal(scopeElem.Options, &options))
+		if err != nil {
+			return nil, err
+		}
+		options["connectionId"] = connection.ID
+		options["transformationRules"] = transformationRules
+		// make sure task options is valid
+		op, err := tasks.DecodeAndValidateTaskOptions(options)
+		if err != nil {
+			return nil, err
+		}
+
 		// refdiff
 		if refdiffRules, ok := transformationRules["refdiff"]; ok && refdiffRules != nil {
 			// add a new task to next stage
@@ -84,28 +98,21 @@ func makePipelinePlan(subtaskMetas []core.SubTaskMeta, scopeV100s []*core.Bluepr
 			if j == len(plan) {
 				plan = append(plan, nil)
 			}
+			repo, err = MemorizedGetApiRepo(repo, op, apiClient)
+			if err != nil {
+				return nil, err
+			}
+			ops := refdiffRules.(map[string]interface{})
+			ops["repoId"] = didgen.NewDomainIdGenerator(&models.GithubRepo{}).Generate(connection.ID, repo.GithubId)
 			plan[j] = core.PipelineStage{
 				{
 					Plugin:  "refdiff",
-					Options: refdiffRules.(map[string]interface{}),
+					Options: ops,
 				},
 			}
 			// remove it from github transformationRules
 			delete(transformationRules, "refdiff")
 		}
-		// construct task options for github
-		options := make(map[string]interface{})
-		err = errors.Convert(json.Unmarshal(scopeElem.Options, &options))
-		if err != nil {
-			return nil, err
-		}
-		options["connectionId"] = connection.ID
-		options["transformationRules"] = transformationRules
-		// make sure task options is valid
-		op, err := tasks.DecodeAndValidateTaskOptions(options)
-		if err != nil {
-			return nil, err
-		}
 
 		stage := plan[i]
 		if stage == nil {
@@ -124,6 +131,9 @@ func makePipelinePlan(subtaskMetas []core.SubTaskMeta, scopeV100s []*core.Bluepr
 		if err != nil {
 			return nil, err
 		}
+		// This is just to add a dora subtask, then we can add another two subtasks at the end of plans
+		// The only purpose is to adapt old blueprints
+		// DEPRECATED, will be removed in v0.17
 		// dora
 		if productionPattern, ok := transformationRules["productionPattern"]; ok && productionPattern != nil {
 			j := i + 1
@@ -137,25 +147,13 @@ func makePipelinePlan(subtaskMetas []core.SubTaskMeta, scopeV100s []*core.Bluepr
 			if j == len(plan) {
 				plan = append(plan, nil)
 			}
-			repo, err = MemorizedGetApiRepo(repo, op, apiClient)
-			if err != nil {
-				return nil, err
-			}
-
 			plan[j] = core.PipelineStage{
 				{
 					Plugin:   "dora",
 					Subtasks: []string{"EnrichTaskEnv"},
-					Options: map[string]interface{}{
-						"repoId": didgen.NewDomainIdGenerator(&models.GithubRepo{}).Generate(connection.ID, repo.GithubId),
-						"transformationRules": map[string]interface{}{
-							"productionPattern": productionPattern,
-						},
-					},
+					Options:  map[string]interface{}{},
 				},
 			}
-			// remove it from github transformationRules
-			delete(transformationRules, "productionPattern")
 		}
 		plan[i] = stage
 		repo = nil
diff --git a/plugins/github/api/blueprint_test.go b/plugins/github/api/blueprint_test.go
index e83332835..c0ea3f752 100644
--- a/plugins/github/api/blueprint_test.go
+++ b/plugins/github/api/blueprint_test.go
@@ -90,7 +90,8 @@ func TestMakePipelinePlan(t *testing.T) {
 					"owner":        "test",
 					"repo":         "testRepo",
 					"transformationRules": map[string]interface{}{
-						"prType": "hey,man,wasup",
+						"prType":            "hey,man,wasup",
+						"productionPattern": "xxxx",
 					},
 				},
 			},
@@ -107,6 +108,7 @@ func TestMakePipelinePlan(t *testing.T) {
 			{
 				Plugin: "refdiff",
 				Options: map[string]interface{}{
+					"repoId":      "github:GithubRepo:1:12345",
 					"tagsLimit":   float64(10),
 					"tagsOrder":   "reverse semver",
 					"tagsPattern": "pattern",
@@ -117,12 +119,7 @@ func TestMakePipelinePlan(t *testing.T) {
 			{
 				Plugin:   "dora",
 				Subtasks: []string{"EnrichTaskEnv"},
-				Options: map[string]interface{}{
-					"repoId": "github:GithubRepo:1:12345",
-					"transformationRules": map[string]interface{}{
-						"productionPattern": "xxxx",
-					},
-				},
+				Options:  map[string]interface{}{},
 			},
 		},
 	}
diff --git a/plugins/gitlab/api/blueprint.go b/plugins/gitlab/api/blueprint.go
index 636258202..0af308ee2 100644
--- a/plugins/gitlab/api/blueprint.go
+++ b/plugins/gitlab/api/blueprint.go
@@ -79,22 +79,6 @@ func makePipelinePlan(subtaskMetas []core.SubTaskMeta, scope []*core.BlueprintSc
 				return nil, err
 			}
 		}
-		// refdiff
-		if refdiffRules, ok := transformationRules["refdiff"]; ok && refdiffRules != nil {
-			// add a new task to next stage
-			j := i + 1
-			if j == len(plan) {
-				plan = append(plan, nil)
-			}
-			plan[j] = core.PipelineStage{
-				{
-					Plugin:  "refdiff",
-					Options: refdiffRules.(map[string]interface{}),
-				},
-			}
-			// remove it from github transformationRules
-			delete(transformationRules, "refdiff")
-		}
 		// construct task options for github
 		options := make(map[string]interface{})
 		err = errors.Convert(json.Unmarshal(scopeElem.Options, &options))
@@ -116,6 +100,29 @@ func makePipelinePlan(subtaskMetas []core.SubTaskMeta, scope []*core.BlueprintSc
 			return repo, err
 		}
 
+		// refdiff
+		if refdiffRules, ok := transformationRules["refdiff"]; ok && refdiffRules != nil {
+			// add a new task to next stage
+			j := i + 1
+			if j == len(plan) {
+				plan = append(plan, nil)
+			}
+			repo, err = memorizedGetApiRepo()
+			if err != nil {
+				return nil, err
+			}
+			ops := refdiffRules.(map[string]interface{})
+			ops["repoId"] = didgen.NewDomainIdGenerator(&models.GitlabProject{}).Generate(connection.ID, repo.GitlabId)
+			plan[j] = core.PipelineStage{
+				{
+					Plugin:  "refdiff",
+					Options: ops,
+				},
+			}
+			// remove it from github transformationRules
+			delete(transformationRules, "refdiff")
+		}
+
 		// construct subtasks
 		subtasks, err := helper.MakePipelinePlanSubtasks(subtaskMetas, scopeElem.Entities)
 		if err != nil {
@@ -151,6 +158,9 @@ func makePipelinePlan(subtaskMetas []core.SubTaskMeta, scope []*core.BlueprintSc
 				},
 			})
 		}
+		// This is just to add a dora subtask, then we can add another two subtasks at the end of plans
+		// The only purpose is to adapt old blueprints
+		// DEPRECATED, will be removed in v0.17
 		// dora
 		if productionPattern, ok := transformationRules["productionPattern"]; ok && productionPattern != nil {
 			j := i + 1
@@ -170,18 +180,13 @@ func makePipelinePlan(subtaskMetas []core.SubTaskMeta, scope []*core.BlueprintSc
 			}
 			plan[j] = core.PipelineStage{
 				{
-					Plugin:   "dora",
+					Plugin: "dora",
+					// This is just to add a dora subtask, then we can add another two subtasks at the end of plans
+					// The only purpose is to adapt old blueprints
 					Subtasks: []string{"EnrichTaskEnv"},
-					Options: map[string]interface{}{
-						"repoId": didgen.NewDomainIdGenerator(&models.GitlabProject{}).Generate(connection.ID, repo.GitlabId),
-						"transformationRules": map[string]interface{}{
-							"productionPattern": productionPattern,
-						},
-					},
+					Options:  map[string]interface{}{},
 				},
 			}
-			// remove it from github transformationRules
-			delete(transformationRules, "productionPattern")
 		}
 		plan[i] = stage
 		repo = nil
diff --git a/plugins/gitlab/api/blueprint_test.go b/plugins/gitlab/api/blueprint_test.go
index 4fbb255fa..2b0bb1fa1 100644
--- a/plugins/gitlab/api/blueprint_test.go
+++ b/plugins/gitlab/api/blueprint_test.go
@@ -95,7 +95,8 @@ func TestProcessScope(t *testing.T) {
 					"connectionId": uint64(1),
 					"projectId":    float64(12345),
 					"transformationRules": map[string]interface{}{
-						"prType": "hey,man,wasup",
+						"prType":            "hey,man,wasup",
+						"productionPattern": "xxxx",
 					},
 				},
 			},
@@ -112,6 +113,7 @@ func TestProcessScope(t *testing.T) {
 			{
 				Plugin: "refdiff",
 				Options: map[string]interface{}{
+					"repoId":      "gitlab:GitlabProject:1:12345",
 					"tagsLimit":   float64(10),
 					"tagsOrder":   "reverse semver",
 					"tagsPattern": "pattern",
@@ -122,12 +124,7 @@ func TestProcessScope(t *testing.T) {
 			{
 				Plugin:   "dora",
 				Subtasks: []string{"EnrichTaskEnv"},
-				Options: map[string]interface{}{
-					"repoId": "gitlab:GitlabProject:1:12345",
-					"transformationRules": map[string]interface{}{
-						"productionPattern": "xxxx",
-					},
-				},
+				Options:  map[string]interface{}{},
 			},
 		},
 	}
diff --git a/plugins/jenkins/api/blueprint_v100.go b/plugins/jenkins/api/blueprint_v100.go
index e5aa9a57d..417034a62 100644
--- a/plugins/jenkins/api/blueprint_v100.go
+++ b/plugins/jenkins/api/blueprint_v100.go
@@ -130,20 +130,16 @@ func makePipelinePlanV100(subtaskMetas []core.SubTaskMeta, scope []*core.Bluepri
 		if err != nil {
 			return nil, err
 		}
-
+		// This is just to add a dora subtask, then we can add another two subtasks at the end of plans
+		// The only purpose is to adapt old blueprints
+		// DEPRECATED, will be removed in v0.17
 		// Dora part
 		if productionPattern != nil {
-			doraOption := make(map[string]interface{})
-			doraOption["prefix"] = "jenkins"
-			doraRules := make(map[string]interface{})
-			doraRules["productionPattern"] = productionPattern
-			doraOption["transformationRules"] = doraRules
-
 			stageDora := core.PipelineStage{
 				{
 					Plugin:   "dora",
 					Subtasks: []string{"EnrichTaskEnv"},
-					Options:  doraOption,
+					Options:  map[string]interface{}{},
 				},
 			}
 
diff --git a/plugins/jenkins/api/blueprint_v100_test.go b/plugins/jenkins/api/blueprint_v100_test.go
index acb49923e..a6b66e537 100644
--- a/plugins/jenkins/api/blueprint_v100_test.go
+++ b/plugins/jenkins/api/blueprint_v100_test.go
@@ -115,12 +115,7 @@ func TestProcessScope(t *testing.T) {
 			{
 				Plugin:   "dora",
 				Subtasks: []string{"EnrichTaskEnv"},
-				Options: map[string]interface{}{
-					"prefix": "jenkins",
-					"transformationRules": map[string]interface{}{
-						"productionPattern": "(?i)build-and-deploy",
-					},
-				},
+				Options:  map[string]interface{}{},
 			},
 		},
 	}
diff --git a/services/blueprint_makeplan_v100.go b/services/blueprint_makeplan_v100.go
index c32c7f873..c22358139 100644
--- a/services/blueprint_makeplan_v100.go
+++ b/services/blueprint_makeplan_v100.go
@@ -68,7 +68,7 @@ func GeneratePlanJsonV100(settings *models.BlueprintSettings) (core.PipelinePlan
 		plan := core.PipelineStage{
 			&core.PipelineTask{
 				Plugin:   "dora",
-				Subtasks: []string{"calculateChangeLeadTime", "ConnectIncidentToDeployment"},
+				Subtasks: []string{"calculateChangeLeadTimeOld", "connectIncidentToDeploymentOld"},
 				Options:  doraRules,
 			},
 		}