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 8c5fbc1d9 Remove the usage of `TmpFromAccountId` and `TmpToAccountId` 
in Jira issue related data. (#7740)
8c5fbc1d9 is described below

commit 8c5fbc1d90871f556e2795904c69983e6f8fc145
Author: Lynwee <[email protected]>
AuthorDate: Tue Jul 16 11:51:51 2024 +0800

    Remove the usage of `TmpFromAccountId` and `TmpToAccountId` in Jira issue 
related data. (#7740)
    
    * fix(jira): don't use `tmpFromAccountId` and `tmpToAccountId` in issue 
changelogs
    
    * fix(jira): remove all usage of `tmpFromAccountId` and `tmpToAccountId`
    
    * refactor(jira): remove some codes
    
    * fix(jira): fix e2e test
---
 backend/plugins/jira/e2e/changelog_test.go         |  1 +
 .../plugins/jira/tasks/apiv2models/changelog.go    | 14 ++-----
 backend/plugins/jira/tasks/apiv2models/issue.go    |  4 +-
 backend/plugins/jira/tasks/epic_extractor.go       | 42 +++++++++++++++++++-
 .../jira/tasks/issue_changelog_convertor.go        | 45 +++++-----------------
 .../jira/tasks/issue_changelog_extractor.go        |  6 ++-
 backend/plugins/jira/tasks/issue_extractor.go      | 10 +++--
 7 files changed, 68 insertions(+), 54 deletions(-)

diff --git a/backend/plugins/jira/e2e/changelog_test.go 
b/backend/plugins/jira/e2e/changelog_test.go
index 670a7e12f..8f6880f00 100644
--- a/backend/plugins/jira/e2e/changelog_test.go
+++ b/backend/plugins/jira/e2e/changelog_test.go
@@ -38,6 +38,7 @@ func TestIssueChangelogDataFlow(t *testing.T) {
        }
        // import raw data table
        
dataflowTester.ImportCsvIntoRawTable("./raw_tables/_raw_jira_api_issue_changelogs.csv",
 "_raw_jira_api_issue_changelogs")
+       
dataflowTester.ImportCsvIntoTabler("./snapshot_tables/_tool_jira_issue_fields.csv",
 &models.JiraIssueField{})
        dataflowTester.FlushTabler(&models.JiraIssueChangelogs{})
        dataflowTester.FlushTabler(&models.JiraIssueChangelogItems{})
        dataflowTester.FlushTabler(&models.JiraAccount{})
diff --git a/backend/plugins/jira/tasks/apiv2models/changelog.go 
b/backend/plugins/jira/tasks/apiv2models/changelog.go
index 5c5c2c2a6..1ad6b9825 100644
--- a/backend/plugins/jira/tasks/apiv2models/changelog.go
+++ b/backend/plugins/jira/tasks/apiv2models/changelog.go
@@ -76,23 +76,15 @@ func (c ChangelogItem) ToToolLayer(connectionId, 
changelogId uint64) *models.Jir
        return item
 }
 
-func (c ChangelogItem) ExtractUser(connectionId uint64) []*models.JiraAccount {
+func (c ChangelogItem) ExtractUser(connectionId uint64, userFieldMaps 
map[string]struct{}) []*models.JiraAccount {
        var result []*models.JiraAccount
-       // if `tmpFromAccountId` or `tmpToAccountId` is not empty, then this 
change log item stands for changes about accounts.
-       if c.TmpFromAccountId != "" {
-               // User `from` firstly
+       _, ok := userFieldMaps[c.Field]
+       if c.Field == "assignee" || c.Field == "reporter" || ok {
                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.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/apiv2models/issue.go 
b/backend/plugins/jira/tasks/apiv2models/issue.go
index 8a4417a3d..68b5a26b6 100644
--- a/backend/plugins/jira/tasks/apiv2models/issue.go
+++ b/backend/plugins/jira/tasks/apiv2models/issue.go
@@ -300,7 +300,7 @@ func (i *Issue) SetAllFields(raw json.RawMessage) 
errors.Error {
        return nil
 }
 
-func (i Issue) ExtractEntities(connectionId uint64) ([]uint64, 
*models.JiraIssue, []*models.JiraIssueComment, []*models.JiraWorklog, 
[]*models.JiraIssueChangelogs, []*models.JiraIssueChangelogItems, 
[]*models.JiraAccount) {
+func (i Issue) ExtractEntities(connectionId uint64, userFieldMaps 
map[string]struct{}) ([]uint64, *models.JiraIssue, []*models.JiraIssueComment, 
[]*models.JiraWorklog, []*models.JiraIssueChangelogs, 
[]*models.JiraIssueChangelogItems, []*models.JiraAccount) {
        issue := i.toToolLayer(connectionId)
        var comments []*models.JiraIssueComment
        var worklogs []*models.JiraWorklog
@@ -341,7 +341,7 @@ func (i Issue) ExtractEntities(connectionId uint64) 
([]uint64, *models.JiraIssue
                        }
                        for _, item := range changelog.Items {
                                changelogItems = append(changelogItems, 
item.ToToolLayer(connectionId, changelog.ID))
-                               users = append(users, 
item.ExtractUser(connectionId)...)
+                               users = append(users, 
item.ExtractUser(connectionId, userFieldMaps)...)
                        }
                }
        }
diff --git a/backend/plugins/jira/tasks/epic_extractor.go 
b/backend/plugins/jira/tasks/epic_extractor.go
index 8c3c8eab3..cf1e7f28b 100644
--- a/backend/plugins/jira/tasks/epic_extractor.go
+++ b/backend/plugins/jira/tasks/epic_extractor.go
@@ -18,9 +18,12 @@ limitations under the License.
 package tasks
 
 import (
+       "github.com/apache/incubator-devlake/core/dal"
        "github.com/apache/incubator-devlake/core/errors"
+       "github.com/apache/incubator-devlake/core/log"
        "github.com/apache/incubator-devlake/core/plugin"
        "github.com/apache/incubator-devlake/helpers/pluginhelper/api"
+       "github.com/apache/incubator-devlake/plugins/jira/models"
 )
 
 var _ plugin.SubTaskEntryPoint = ExtractEpics
@@ -44,6 +47,10 @@ func ExtractEpics(taskCtx plugin.SubTaskContext) 
errors.Error {
        if err != nil {
                return err
        }
+       userFieldMap, err := getUserFieldMap(db, connectionId, logger)
+       if err != nil {
+               return err
+       }
        extractor, err := api.NewApiExtractor(api.ApiExtractorArgs{
                RawDataSubTaskArgs: api.RawDataSubTaskArgs{
                        Ctx: taskCtx,
@@ -54,7 +61,7 @@ func ExtractEpics(taskCtx plugin.SubTaskContext) errors.Error 
{
                        Table: RAW_EPIC_TABLE,
                },
                Extract: func(row *api.RawData) ([]interface{}, errors.Error) {
-                       return extractIssues(data, mappings, row)
+                       return extractIssues(data, mappings, row, userFieldMap)
                },
        })
        if err != nil {
@@ -62,3 +69,36 @@ func ExtractEpics(taskCtx plugin.SubTaskContext) 
errors.Error {
        }
        return extractor.Execute()
 }
+
+func getIssueFieldMap(db dal.Dal, connectionId uint64, logger log.Logger) 
(map[string]models.JiraIssueField, errors.Error) {
+       var allIssueFields []models.JiraIssueField
+       if err := db.All(&allIssueFields, dal.Where("connection_id = ?", 
connectionId)); err != nil {
+               return nil, err
+       }
+       issueFieldMap := make(map[string]models.JiraIssueField)
+       for _, v := range allIssueFields {
+               if _, ok := issueFieldMap[v.Name]; ok {
+                       logger.Warn(nil, "filed name %s is duplicated", v.Name)
+                       if v.SchemaType == "user" {
+                               issueFieldMap[v.Name] = v
+                       }
+               } else {
+                       issueFieldMap[v.Name] = v
+               }
+       }
+       return issueFieldMap, nil
+}
+
+func getUserFieldMap(db dal.Dal, connectionId uint64, logger log.Logger) 
(map[string]struct{}, errors.Error) {
+       userFieldMap := make(map[string]struct{})
+       issueFieldMap, err := getIssueFieldMap(db, connectionId, logger)
+       if err != nil {
+               return nil, err
+       }
+       for filedName, issueField := range issueFieldMap {
+               if issueField.SchemaType == "user" {
+                       userFieldMap[filedName] = struct{}{}
+               }
+       }
+       return userFieldMap, nil
+}
diff --git a/backend/plugins/jira/tasks/issue_changelog_convertor.go 
b/backend/plugins/jira/tasks/issue_changelog_convertor.go
index 090674b13..ba8de94f3 100644
--- a/backend/plugins/jira/tasks/issue_changelog_convertor.go
+++ b/backend/plugins/jira/tasks/issue_changelog_convertor.go
@@ -68,17 +68,10 @@ func ConvertIssueChangelogs(subtaskCtx 
plugin.SubTaskContext) errors.Error {
                statusMap[v.ID] = v
        }
 
-       var allIssueFields []models.JiraIssueField
-       if err := db.All(&allIssueFields, dal.Where("connection_id = ?", 
connectionId)); err != nil {
+       issueFieldMap, err := getIssueFieldMap(db, connectionId, logger)
+       if err != nil {
                return err
        }
-       issueFieldMap := make(map[string]models.JiraIssueField)
-       for _, v := range allIssueFields {
-               if _, ok := issueFieldMap[v.Name]; ok {
-                       logger.Warn(nil, "filed name %s is duplicated", v.Name)
-               }
-               issueFieldMap[v.Name] = v
-       }
 
        issueIdGenerator := didgen.NewDomainIdGenerator(&models.JiraIssue{})
        sprintIdGenerator := didgen.NewDomainIdGenerator(&models.JiraSprint{})
@@ -159,16 +152,15 @@ func ConvertIssueChangelogs(subtaskCtx 
plugin.SubTaskContext) errors.Error {
                                        changelog.ToValue = 
getStdStatus(toStatus.StatusCategory)
                                }
                        default:
-                               fromAccountId := 
tryToResolveAccountIdFromAccountLikeField(row.Field, row.TmpFromAccountId, 
row.FromValue, issueFieldMap)
-                               if fromAccountId != "" {
-                                       changelog.OriginalFromValue = 
accountIdGen.Generate(connectionId, fromAccountId)
-                               }
-                               toAccountId := 
tryToResolveAccountIdFromAccountLikeField(row.Field, row.TmpToAccountId, 
row.ToValue, issueFieldMap)
-                               if toAccountId != "" {
-                                       changelog.OriginalToValue = 
accountIdGen.Generate(connectionId, toAccountId)
+                               if v, ok := issueFieldMap[row.FieldId]; ok && 
v.SchemaType == "user" {
+                                       if row.FromValue != "" {
+                                               changelog.OriginalFromValue = 
accountIdGen.Generate(connectionId, row.FromValue)
+                                       }
+                                       if row.ToValue != "" {
+                                               changelog.OriginalToValue = 
accountIdGen.Generate(connectionId, row.ToValue)
+                                       }
                                }
                        }
-
                        return []interface{}{changelog}, nil
 
                },
@@ -181,25 +173,6 @@ func ConvertIssueChangelogs(subtaskCtx 
plugin.SubTaskContext) errors.Error {
        return converter.Execute()
 }
 
-func tryToResolveAccountIdFromAccountLikeField(fieldName string, tmpAccountId 
string, fromOrToValue string, issueFieldMap map[string]models.JiraIssueField) 
string {
-       if tmpAccountId != "" {
-               // process other account-like fields, it works on jira9 and 
jira cloud.
-               if fromOrToValue != "" {
-                       return fromOrToValue
-               } else {
-                       return tmpAccountId
-               }
-       } else {
-               // it works on jira8
-               // notice: field name is not unique, but we cannot fetch field 
id here.
-               if v, ok := issueFieldMap[fieldName]; ok && v.SchemaType == 
"user" {
-                       // field type is account
-                       return fromOrToValue
-               }
-       }
-       return ""
-}
-
 func convertIds(ids string, connectionId uint64, sprintIdGenerator 
*didgen.DomainIdGenerator) (string, errors.Error) {
        ss := strings.Split(ids, ",")
        var resultSlice []string
diff --git a/backend/plugins/jira/tasks/issue_changelog_extractor.go 
b/backend/plugins/jira/tasks/issue_changelog_extractor.go
index f333f82c2..a49142e3f 100644
--- a/backend/plugins/jira/tasks/issue_changelog_extractor.go
+++ b/backend/plugins/jira/tasks/issue_changelog_extractor.go
@@ -43,6 +43,10 @@ func ExtractIssueChangelogs(subtaskCtx 
plugin.SubTaskContext) errors.Error {
                return nil
        }
        connectionId := data.Options.ConnectionId
+       userFieldMap, err := getUserFieldMap(subtaskCtx.GetDal(), connectionId, 
subtaskCtx.GetLogger())
+       if err != nil {
+               return err
+       }
        extractor, err := 
api.NewStatefulApiExtractor(&api.StatefulApiExtractorArgs{
                SubtaskCommonArgs: &api.SubtaskCommonArgs{
                        SubTaskContext: subtaskCtx,
@@ -77,7 +81,7 @@ func ExtractIssueChangelogs(subtaskCtx plugin.SubTaskContext) 
errors.Error {
                        // collect changelog_items
                        for _, item := range changelog.Items {
                                result = append(result, 
item.ToToolLayer(connectionId, changelog.ID))
-                               extractedUsersFromChangelogItem := 
item.ExtractUser(connectionId)
+                               extractedUsersFromChangelogItem := 
item.ExtractUser(connectionId, userFieldMap)
                                for _, u := range 
extractedUsersFromChangelogItem {
                                        if u != nil && u.AccountId != "" {
                                                result = append(result, u)
diff --git a/backend/plugins/jira/tasks/issue_extractor.go 
b/backend/plugins/jira/tasks/issue_extractor.go
index 7dcb6da76..3d097d691 100644
--- a/backend/plugins/jira/tasks/issue_extractor.go
+++ b/backend/plugins/jira/tasks/issue_extractor.go
@@ -58,6 +58,10 @@ func ExtractIssues(subtaskCtx plugin.SubTaskContext) 
errors.Error {
        if err != nil {
                return err
        }
+       userFieldMap, err := getUserFieldMap(db, connectionId, logger)
+       if err != nil {
+               return err
+       }
        extractor, err := 
api.NewStatefulApiExtractor(&api.StatefulApiExtractorArgs{
                SubtaskCommonArgs: &api.SubtaskCommonArgs{
                        SubTaskContext: subtaskCtx,
@@ -69,7 +73,7 @@ func ExtractIssues(subtaskCtx plugin.SubTaskContext) 
errors.Error {
                        SubtaskConfig: mappings,
                },
                Extract: func(row *api.RawData) ([]interface{}, errors.Error) {
-                       return extractIssues(data, mappings, row)
+                       return extractIssues(data, mappings, row, userFieldMap)
                },
        })
        if err != nil {
@@ -78,7 +82,7 @@ func ExtractIssues(subtaskCtx plugin.SubTaskContext) 
errors.Error {
        return extractor.Execute()
 }
 
-func extractIssues(data *JiraTaskData, mappings *typeMappings, row 
*api.RawData) ([]interface{}, errors.Error) {
+func extractIssues(data *JiraTaskData, mappings *typeMappings, row 
*api.RawData, userFieldMaps map[string]struct{}) ([]interface{}, errors.Error) {
        var apiIssue apiv2models.Issue
        err := errors.Convert(json.Unmarshal(row.Data, &apiIssue))
        if err != nil {
@@ -93,7 +97,7 @@ func extractIssues(data *JiraTaskData, mappings 
*typeMappings, row *api.RawData)
        if apiIssue.Fields.Created == nil {
                return results, nil
        }
-       sprints, issue, comments, worklogs, changelogs, changelogItems, users 
:= apiIssue.ExtractEntities(data.Options.ConnectionId)
+       sprints, issue, comments, worklogs, changelogs, changelogItems, users 
:= apiIssue.ExtractEntities(data.Options.ConnectionId, userFieldMaps)
        for _, sprintId := range sprints {
                sprintIssue := &models.JiraSprintIssue{
                        ConnectionId:     data.Options.ConnectionId,

Reply via email to