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 2022/10/11 08:11:27 UTC

[incubator-devlake] branch main updated: feat(tapd): status mapping

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 5c78bbf5 feat(tapd): status mapping
5c78bbf5 is described below

commit 5c78bbf5cf7dbcdf56c7bcd88ccc1584e6e7f788
Author: Yingchu Chen <yi...@merico.dev>
AuthorDate: Tue Oct 11 15:08:00 2022 +0800

    feat(tapd): status mapping
    
    closes #3208
---
 plugins/tapd/api/swagger.go           | 56 +++++++++++++++++------------------
 plugins/tapd/tasks/bug_extractor.go   | 18 +++++++----
 plugins/tapd/tasks/shared.go          | 21 +++++++++++++
 plugins/tapd/tasks/story_extractor.go | 26 +++++++++-------
 plugins/tapd/tasks/task_data.go       | 12 +++++---
 5 files changed, 83 insertions(+), 50 deletions(-)

diff --git a/plugins/tapd/api/swagger.go b/plugins/tapd/api/swagger.go
index 867d25a8..573550a9 100644
--- a/plugins/tapd/api/swagger.go
+++ b/plugins/tapd/api/swagger.go
@@ -17,27 +17,6 @@ limitations under the License.
 
 package api
 
-type CodeTransformationRules struct {
-	PrType               string `mapstructure:"prType" json:"prType"`
-	PrComponent          string `mapstructure:"prComponent" json:"prComponent"`
-	PrBodyClosePattern   string `mapstructure:"prBodyClosePattern" json:"prBodyClosePattern"`
-	IssueSeverity        string `mapstructure:"issueSeverity" json:"issueSeverity"`
-	IssuePriority        string `mapstructure:"issuePriority" json:"issuePriority"`
-	IssueComponent       string `mapstructure:"issueComponent" json:"issueComponent"`
-	IssueTypeBug         string `mapstructure:"issueTypeBug" json:"issueTypeBug"`
-	IssueTypeIncident    string `mapstructure:"issueTypeIncident" json:"issueTypeIncident"`
-	IssueTypeRequirement string `mapstructure:"issueTypeRequirement" json:"issueTypeRequirement"`
-}
-
-type TicketTransformationRules struct {
-	EpicKeyField               string `json:"epicKeyField"`
-	StoryPointField            string `json:"storyPointField"`
-	RemotelinkCommitShaPattern string `json:"remotelinkCommitShaPattern"`
-	TypeMappings               map[string]struct {
-		StandardType string `json:"standardType"`
-	} `json:"typeMappings"`
-}
-
 // @Summary blueprints setting for tapd
 // @Description blueprint setting for tapd
 // @Tags plugins/tapd
@@ -53,10 +32,11 @@ type TapdBlueprintSetting []struct {
 		ConnectionID int    `json:"connectionId"`
 		Scope        []struct {
 			Options struct {
-				WorkspaceId uint64   `mapstruct:"workspaceId"`
-				CompanyId   uint64   `mapstruct:"companyId"`
-				Tasks       []string `mapstruct:"tasks,omitempty"`
-				Since       string
+				WorkspaceId         uint64   `mapstruct:"workspaceId"`
+				CompanyId           uint64   `mapstruct:"companyId"`
+				Tasks               []string `mapstruct:"tasks,omitempty"`
+				Since               string
+				TransformationRules TransformationRules `json:"transformationRules"`
 			} `json:"options"`
 			Entities []string `json:"entities"`
 		} `json:"scope"`
@@ -75,9 +55,27 @@ type TapdPipelinePlan [][]struct {
 	Plugin   string   `json:"plugin"`
 	Subtasks []string `json:"subtasks"`
 	Options  struct {
-		WorkspaceId uint64   `mapstruct:"workspaceId"`
-		CompanyId   uint64   `mapstruct:"companyId"`
-		Tasks       []string `mapstruct:"tasks,omitempty"`
-		Since       string
+		ConnectionId        uint64   `mapstruct:"connectionId"`
+		WorkspaceId         uint64   `mapstruct:"workspaceId"`
+		CompanyId           uint64   `mapstruct:"companyId"`
+		Tasks               []string `mapstruct:"tasks,omitempty"`
+		Since               string
+		TransformationRules TransformationRules `json:"transformationRules"`
 	} `json:"options"`
 }
+
+type TransformationRules struct {
+	TypeMappings   TypeMappings   `json:"typeMappings"`
+	StatusMappings StatusMappings `json:"statusMappings"`
+}
+type TypeMapping struct {
+	StandardType string `json:"standardType"`
+}
+
+type StatusMappings struct {
+	TodoStatus       []string `json:"todoStatus"`
+	InProgressStatus []string `json:"inprogressStatus"`
+	DoneStatus       []string `json:"doneStatus"`
+}
+
+type TypeMappings map[string]TypeMapping
diff --git a/plugins/tapd/tasks/bug_extractor.go b/plugins/tapd/tasks/bug_extractor.go
index 444b1c32..7b48300d 100644
--- a/plugins/tapd/tasks/bug_extractor.go
+++ b/plugins/tapd/tasks/bug_extractor.go
@@ -52,14 +52,14 @@ func ExtractBugs(taskCtx core.SubTaskContext) errors.Error {
 		return err
 	}
 
-	statusMap := make(map[string]string, len(statusList))
-	lastStatusMap := make(map[string]bool, len(statusList))
+	statusLanguageMap := make(map[string]string, len(statusList))
+	statusLastStepMap := make(map[string]bool, len(statusList))
 	for _, v := range statusList {
-		statusMap[v.EnglishName] = v.ChineseName
-		lastStatusMap[v.ChineseName] = v.IsLastStep
+		statusLanguageMap[v.EnglishName] = v.ChineseName
+		statusLastStepMap[v.ChineseName] = v.IsLastStep
 	}
 	getStdStatus := func(statusKey string) string {
-		if lastStatusMap[statusKey] {
+		if statusLastStepMap[statusKey] {
 			return ticket.DONE
 		} else if statusKey == "新建" {
 			return ticket.TODO
@@ -67,6 +67,7 @@ func ExtractBugs(taskCtx core.SubTaskContext) errors.Error {
 			return ticket.IN_PROGRESS
 		}
 	}
+	customStatusMap := getStatusMapping(data)
 
 	extractor, err := helper.NewApiExtractor(helper.ApiExtractorArgs{
 		RawDataSubTaskArgs: *rawDataSubTaskArgs,
@@ -81,10 +82,15 @@ func ExtractBugs(taskCtx core.SubTaskContext) errors.Error {
 			}
 			toolL := bugBody.Bug
 
-			toolL.Status = statusMap[toolL.Status]
+			toolL.Status = statusLanguageMap[toolL.Status]
 			toolL.ConnectionId = data.Options.ConnectionId
 			toolL.Type = "BUG"
 			toolL.StdType = "BUG"
+			if len(customStatusMap) != 0 {
+				toolL.StdStatus = customStatusMap[toolL.Status]
+			} else {
+				toolL.StdStatus = getStdStatus(toolL.Status)
+			}
 			toolL.StdStatus = getStdStatus(toolL.Status)
 			toolL.Url = fmt.Sprintf("https://www.tapd.cn/%d/prong/stories/view/%d", toolL.WorkspaceId, toolL.Id)
 			if strings.Contains(toolL.CurrentOwner, ";") {
diff --git a/plugins/tapd/tasks/shared.go b/plugins/tapd/tasks/shared.go
index 42fbb6d0..b8839cd9 100644
--- a/plugins/tapd/tasks/shared.go
+++ b/plugins/tapd/tasks/shared.go
@@ -22,6 +22,7 @@ import (
 	goerror "errors"
 	"fmt"
 	"github.com/apache/incubator-devlake/errors"
+	"github.com/apache/incubator-devlake/models/domainlayer/ticket"
 	"gorm.io/gorm"
 	"io"
 	"net/http"
@@ -42,6 +43,8 @@ type Data struct {
 	Count int `json:"count"`
 }
 
+var statusMapping map[string]string
+
 var UserIdGen *didgen.DomainIdGenerator
 var WorkspaceIdGen *didgen.DomainIdGenerator
 var IssueIdGen *didgen.DomainIdGenerator
@@ -165,3 +168,21 @@ func getTypeMappings(data *TapdTaskData, db dal.Dal, system string) (*typeMappin
 		stdTypeMappings: stdTypeMappings,
 	}, nil
 }
+
+func getStatusMapping(data *TapdTaskData) map[string]string {
+	if len(statusMapping) != 0 {
+		return statusMapping
+	}
+	statusMapping = make(map[string]string)
+	mapping := data.Options.TransformationRules.StatusMappings
+	for _, v := range mapping.DoneStatus {
+		statusMapping[v] = ticket.DONE
+	}
+	for _, v := range mapping.InProgressStatus {
+		statusMapping[v] = ticket.IN_PROGRESS
+	}
+	for _, v := range mapping.TodoStatus {
+		statusMapping[v] = ticket.TODO
+	}
+	return statusMapping
+}
diff --git a/plugins/tapd/tasks/story_extractor.go b/plugins/tapd/tasks/story_extractor.go
index 9ddcd519..d3788740 100644
--- a/plugins/tapd/tasks/story_extractor.go
+++ b/plugins/tapd/tasks/story_extractor.go
@@ -52,14 +52,14 @@ func ExtractStories(taskCtx core.SubTaskContext) errors.Error {
 		return err
 	}
 
-	statusMap := make(map[string]string, len(statusList))
-	lastStatusMap := make(map[string]bool, len(statusList))
+	statusLanguageMap := make(map[string]string, len(statusList))
+	statusLastStepMap := make(map[string]bool, len(statusList))
 	for _, v := range statusList {
-		statusMap[v.EnglishName] = v.ChineseName
-		lastStatusMap[v.ChineseName] = v.IsLastStep
+		statusLanguageMap[v.EnglishName] = v.ChineseName
+		statusLastStepMap[v.ChineseName] = v.IsLastStep
 	}
 	getStdStatus := func(statusKey string) string {
-		if lastStatusMap[statusKey] {
+		if statusLastStepMap[statusKey] {
 			return ticket.DONE
 		} else if statusKey == "草稿" {
 			return ticket.TODO
@@ -67,8 +67,8 @@ func ExtractStories(taskCtx core.SubTaskContext) errors.Error {
 			return ticket.IN_PROGRESS
 		}
 	}
-
-	mappings, err := getTypeMappings(data, db, "story")
+	customStatusMap := getStatusMapping(data)
+	typeMap, err := getTypeMappings(data, db, "story")
 
 	extractor, err := helper.NewApiExtractor(helper.ApiExtractorArgs{
 		RawDataSubTaskArgs: *rawDataSubTaskArgs,
@@ -82,13 +82,17 @@ func ExtractStories(taskCtx core.SubTaskContext) errors.Error {
 				return nil, err
 			}
 			toolL := storyBody.Story
-			toolL.Status = statusMap[toolL.Status]
-			toolL.StdStatus = getStdStatus(toolL.Status)
+			toolL.Status = statusLanguageMap[toolL.Status]
+			if len(customStatusMap) != 0 {
+				toolL.StdStatus = customStatusMap[toolL.Status]
+			} else {
+				toolL.StdStatus = getStdStatus(toolL.Status)
+			}
 
 			toolL.ConnectionId = data.Options.ConnectionId
 
-			toolL.Type = mappings.typeIdMappings[toolL.WorkitemTypeId]
-			toolL.StdType = mappings.stdTypeMappings[toolL.Type]
+			toolL.Type = typeMap.typeIdMappings[toolL.WorkitemTypeId]
+			toolL.StdType = typeMap.stdTypeMappings[toolL.Type]
 			if toolL.StdType == "" {
 				toolL.StdType = "REQUIREMENT"
 			}
diff --git a/plugins/tapd/tasks/task_data.go b/plugins/tapd/tasks/task_data.go
index 2b0ea74e..9174bd7d 100644
--- a/plugins/tapd/tasks/task_data.go
+++ b/plugins/tapd/tasks/task_data.go
@@ -44,11 +44,15 @@ type TypeMapping struct {
 	StandardType string `json:"standardType"`
 }
 
+type StatusMappings struct {
+	TodoStatus       []string `json:"todoStatus"`
+	InProgressStatus []string `json:"inprogressStatus"`
+	DoneStatus       []string `json:"doneStatus"`
+}
+
 type TypeMappings map[string]TypeMapping
 
 type TransformationRules struct {
-	EpicKeyField               string       `json:"epicKeyField"`
-	StoryPointField            string       `json:"storyPointField"`
-	RemotelinkCommitShaPattern string       `json:"remotelinkCommitShaPattern"`
-	TypeMappings               TypeMappings `json:"typeMappings"`
+	TypeMappings   TypeMappings   `json:"typeMappings"`
+	StatusMappings StatusMappings `json:"statusMappings"`
 }