You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@devlake.apache.org by ly...@apache.org on 2024/07/17 11:27:45 UTC

(incubator-devlake) 01/12: feat(jira): collector account from issue changelog items as much as possible

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

lynwee pushed a commit to branch 10-cp
in repository https://gitbox.apache.org/repos/asf/incubator-devlake.git

commit 0ff0799ab793ecfc00613704370132aa36f89591
Author: d4x1 <15...@qq.com>
AuthorDate: Tue Jul 9 15:30:37 2024 +0800

    feat(jira): collector account from issue changelog items as much as possible
---
 backend/plugins/jira/models/issue_changelog.go     | 20 ++++----
 ...9_add_tmp_account_id_to_issue_changelog_item.go | 49 ++++++++++++++++++++
 .../jira/models/migrationscripts/register.go       |  1 +
 .../plugins/jira/tasks/apiv2models/changelog.go    | 54 ++++++++++++++--------
 .../jira/tasks/issue_changelog_convertor.go        | 26 +++++++++--
 .../jira/tasks/issue_changelog_extractor.go        |  5 +-
 6 files changed, 120 insertions(+), 35 deletions(-)

diff --git a/backend/plugins/jira/models/issue_changelog.go b/backend/plugins/jira/models/issue_changelog.go
index e1dbfe871..927c47e67 100644
--- a/backend/plugins/jira/models/issue_changelog.go
+++ b/backend/plugins/jira/models/issue_changelog.go
@@ -40,15 +40,17 @@ type JiraIssueChangelogItems struct {
 	common.NoPKModel
 
 	// collected fields
-	ConnectionId uint64 `gorm:"primaryKey"`
-	ChangelogId  uint64 `gorm:"primaryKey"`
-	Field        string `gorm:"primaryKey"`
-	FieldType    string
-	FieldId      string
-	FromValue    string
-	FromString   string
-	ToValue      string
-	ToString     string
+	ConnectionId     uint64 `gorm:"primaryKey"`
+	ChangelogId      uint64 `gorm:"primaryKey"`
+	Field            string `gorm:"primaryKey"`
+	FieldType        string
+	FieldId          string
+	FromValue        string
+	FromString       string
+	ToValue          string
+	ToString         string
+	TmpFromAccountId string
+	TmpToAccountId   string
 }
 
 func (JiraIssueChangelogs) TableName() string {
diff --git a/backend/plugins/jira/models/migrationscripts/20240709_add_tmp_account_id_to_issue_changelog_item.go b/backend/plugins/jira/models/migrationscripts/20240709_add_tmp_account_id_to_issue_changelog_item.go
new file mode 100644
index 000000000..594ec38f2
--- /dev/null
+++ b/backend/plugins/jira/models/migrationscripts/20240709_add_tmp_account_id_to_issue_changelog_item.go
@@ -0,0 +1,49 @@
+/*
+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 migrationscripts
+
+import (
+	"github.com/apache/incubator-devlake/core/context"
+	"github.com/apache/incubator-devlake/core/errors"
+	"github.com/apache/incubator-devlake/core/plugin"
+)
+
+var _ plugin.MigrationScript = (*addTmpAccountIdToJiraIssueChangelogItem)(nil)
+
+type jiraIssueChangelogItems20240709 struct {
+	TmpFromAccountId string
+	TmpToAccountId   string
+}
+
+func (jiraIssueChangelogItems20240709) TableName() string {
+	return "_tool_jira_issue_changelogs"
+}
+
+type addTmpAccountIdToJiraIssueChangelogItem struct{}
+
+func (script *addTmpAccountIdToJiraIssueChangelogItem) Up(basicRes context.BasicRes) errors.Error {
+	return basicRes.GetDal().AutoMigrate(&jiraIssueChangelogItems20240709{})
+}
+
+func (*addTmpAccountIdToJiraIssueChangelogItem) Version() uint64 {
+	return 20240709134200
+}
+
+func (*addTmpAccountIdToJiraIssueChangelogItem) Name() string {
+	return "add TmpFromAccountId and TmpToAccountId to _tool_jira_issue_changelogs"
+}
diff --git a/backend/plugins/jira/models/migrationscripts/register.go b/backend/plugins/jira/models/migrationscripts/register.go
index be88eda7d..4507c5841 100644
--- a/backend/plugins/jira/models/migrationscripts/register.go
+++ b/backend/plugins/jira/models/migrationscripts/register.go
@@ -49,5 +49,6 @@ func All() []plugin.MigrationScript {
 		new(addFilterJQL),
 		new(addWorklogToIssue),
 		new(addSubtaskToIssue),
+		new(addTmpAccountIdToJiraIssueChangelogItem),
 	}
 }
diff --git a/backend/plugins/jira/tasks/apiv2models/changelog.go b/backend/plugins/jira/tasks/apiv2models/changelog.go
index d3dee330d..5c5c2c2a6 100644
--- a/backend/plugins/jira/tasks/apiv2models/changelog.go
+++ b/backend/plugins/jira/tasks/apiv2models/changelog.go
@@ -46,38 +46,54 @@ func (c Changelog) ToToolLayer(connectionId, issueId uint64, issueUpdated *time.
 }
 
 type ChangelogItem struct {
-	Field      string `json:"field"`
-	Fieldtype  string `json:"fieldtype"`
+	Field     string `json:"field"`
+	Fieldtype string `json:"fieldtype"`
+	FieldId   string `json:"fieldId"`
+
 	FromValue  string `json:"from"`
 	FromString string `json:"fromString"`
-	ToValue    string `json:"to"`
-	ToString   string `json:"toString"`
+
+	ToValue  string `json:"to"`
+	ToString string `json:"toString"`
+
+	TmpFromAccountId string `json:"tmpFromAccountId,omitempty"`
+	TmpToAccountId   string `json:"tmpToAccountId,omitempty"`
 }
 
 func (c ChangelogItem) ToToolLayer(connectionId, changelogId uint64) *models.JiraIssueChangelogItems {
 	item := &models.JiraIssueChangelogItems{
-		ConnectionId: connectionId,
-		ChangelogId:  changelogId,
-		Field:        c.Field,
-		FieldType:    c.Fieldtype,
-		FromValue:    c.FromValue,
-		FromString:   c.FromString,
-		ToValue:      c.ToValue,
-		ToString:     c.ToString,
+		ConnectionId:     connectionId,
+		ChangelogId:      changelogId,
+		Field:            c.Field,
+		FieldType:        c.Fieldtype,
+		FromValue:        c.FromValue,
+		FromString:       c.FromString,
+		ToValue:          c.ToValue,
+		ToString:         c.ToString,
+		TmpFromAccountId: c.TmpFromAccountId,
+		TmpToAccountId:   c.TmpToAccountId,
 	}
 	return item
 }
 
 func (c ChangelogItem) ExtractUser(connectionId uint64) []*models.JiraAccount {
-	if c.Field != "assignee" {
-		return nil
-	}
 	var result []*models.JiraAccount
-	if c.FromValue != "" {
-		result = append(result, &models.JiraAccount{ConnectionId: connectionId, AccountId: c.FromValue})
+	// if `tmpFromAccountId` or `tmpToAccountId` is not empty, then this change log item stands for changes about accounts.
+	if c.TmpFromAccountId != "" {
+		// User `from` firstly
+		if c.FromValue != "" {
+			result = append(result, &models.JiraAccount{ConnectionId: connectionId, AccountId: c.FromValue})
+		} else {
+			result = append(result, &models.JiraAccount{ConnectionId: connectionId, AccountId: c.TmpFromAccountId})
+		}
 	}
-	if c.ToValue != "" {
-		result = append(result, &models.JiraAccount{ConnectionId: connectionId, AccountId: c.ToValue})
+	if c.TmpToAccountId != "" {
+		// User `to` firstly
+		if c.ToValue != "" {
+			result = append(result, &models.JiraAccount{ConnectionId: connectionId, AccountId: c.ToValue})
+		} else {
+			result = append(result, &models.JiraAccount{ConnectionId: connectionId, AccountId: c.TmpToAccountId})
+		}
 	}
 	return result
 }
diff --git a/backend/plugins/jira/tasks/issue_changelog_convertor.go b/backend/plugins/jira/tasks/issue_changelog_convertor.go
index d1db33467..e575c2356 100644
--- a/backend/plugins/jira/tasks/issue_changelog_convertor.go
+++ b/backend/plugins/jira/tasks/issue_changelog_convertor.go
@@ -119,15 +119,15 @@ func ConvertIssueChangelogs(subtaskCtx plugin.SubTaskContext) errors.Error {
 				OriginalToValue:   row.ToString,
 				CreatedDate:       row.Created,
 			}
-			if row.Field == "assignee" {
+			switch row.Field {
+			case "assignee":
 				if row.ToValue != "" {
 					changelog.OriginalToValue = accountIdGen.Generate(connectionId, row.ToValue)
 				}
 				if row.FromValue != "" {
 					changelog.OriginalFromValue = accountIdGen.Generate(connectionId, row.FromValue)
 				}
-			}
-			if row.Field == "Sprint" {
+			case "Sprint":
 				changelog.OriginalFromValue, err = convertIds(row.FromValue, connectionId, sprintIdGenerator)
 				if err != nil {
 					return nil, err
@@ -136,8 +136,7 @@ func ConvertIssueChangelogs(subtaskCtx plugin.SubTaskContext) errors.Error {
 				if err != nil {
 					return nil, err
 				}
-			}
-			if row.Field == "status" {
+			case "status":
 				if fromStatus, ok := statusMap[row.FromValue]; ok {
 					changelog.OriginalFromValue = fromStatus.Name
 					changelog.FromValue = getStdStatus(fromStatus.StatusCategory)
@@ -146,7 +145,24 @@ func ConvertIssueChangelogs(subtaskCtx plugin.SubTaskContext) errors.Error {
 					changelog.OriginalToValue = toStatus.Name
 					changelog.ToValue = getStdStatus(toStatus.StatusCategory)
 				}
+			default:
+				// process other account-like fields
+				if row.TmpFromAccountId != "" {
+					if row.FromValue != "" {
+						changelog.OriginalFromValue = accountIdGen.Generate(connectionId, row.FromValue)
+					} else {
+						changelog.OriginalFromValue = accountIdGen.Generate(connectionId, row.TmpFromAccountId)
+					}
+				}
+				if row.TmpToAccountId != "" {
+					if row.ToValue != "" {
+						changelog.OriginalToValue = accountIdGen.Generate(connectionId, row.ToValue)
+					} else {
+						changelog.OriginalToValue = accountIdGen.Generate(connectionId, row.TmpToAccountId)
+					}
+				}
 			}
+
 			return []interface{}{changelog}, nil
 
 		},
diff --git a/backend/plugins/jira/tasks/issue_changelog_extractor.go b/backend/plugins/jira/tasks/issue_changelog_extractor.go
index 66d9247a6..f333f82c2 100644
--- a/backend/plugins/jira/tasks/issue_changelog_extractor.go
+++ b/backend/plugins/jira/tasks/issue_changelog_extractor.go
@@ -69,7 +69,7 @@ func ExtractIssueChangelogs(subtaskCtx plugin.SubTaskContext) errors.Error {
 			cl, user := changelog.ToToolLayer(connectionId, input.IssueId, &input.UpdateTime)
 			// this is crucial for incremental update
 			cl.IssueUpdated = &input.UpdateTime
-			// collect changelog / user inforation
+			// collect changelog / user information
 			result = append(result, cl)
 			if user != nil {
 				result = append(result, user)
@@ -77,7 +77,8 @@ func ExtractIssueChangelogs(subtaskCtx plugin.SubTaskContext) errors.Error {
 			// collect changelog_items
 			for _, item := range changelog.Items {
 				result = append(result, item.ToToolLayer(connectionId, changelog.ID))
-				for _, u := range item.ExtractUser(connectionId) {
+				extractedUsersFromChangelogItem := item.ExtractUser(connectionId)
+				for _, u := range extractedUsersFromChangelogItem {
 					if u != nil && u.AccountId != "" {
 						result = append(result, u)
 					}