in backend/plugins/tapd/tasks/story_changelog_extractor.go [39:137]
func ExtractStoryChangelog(taskCtx plugin.SubTaskContext) errors.Error {
logger := taskCtx.GetLogger()
rawDataSubTaskArgs, data := CreateRawDataSubTaskArgs(taskCtx, RAW_STORY_CHANGELOG_TABLE)
extractor, err := api.NewApiExtractor(api.ApiExtractorArgs{
RawDataSubTaskArgs: *rawDataSubTaskArgs,
Extract: func(row *api.RawData) ([]interface{}, errors.Error) {
var storyChangelogBody struct {
WorkitemChange models.TapdStoryChangelog
}
results := make([]interface{}, 0, 2)
err := errors.Convert(json.Unmarshal(row.Data, &storyChangelogBody))
if err != nil {
return nil, err
}
storyChangelog := storyChangelogBody.WorkitemChange
storyChangelog.ConnectionId = data.Options.ConnectionId
for _, fc := range storyChangelog.FieldChanges {
if fc.IsStepChange {
// ignore step change
// https://github.com/apache/incubator-devlake/issues/8355#issuecomment-2756726463
continue
}
var item models.TapdStoryChangelogItem
var valueAfterMap interface{}
var valueBeforeMap interface{}
if fc.ValueAfterParsed == nil {
if err = errors.Convert(json.Unmarshal(fc.ValueAfter, &valueAfterMap)); err != nil {
return nil, err
}
} else {
if err = errors.Convert(json.Unmarshal(fc.ValueAfterParsed, &valueAfterMap)); err != nil {
return nil, err
}
}
if fc.ValueBeforeParsed == nil {
if err = errors.Convert(json.Unmarshal(fc.ValueBefore, &valueBeforeMap)); err != nil {
return nil, err
}
} else {
if err = errors.Convert(json.Unmarshal(fc.ValueBeforeParsed, &valueBeforeMap)); err != nil {
return nil, err
}
}
switch valueAfterMap.(type) {
case map[string]interface{}:
for k, v := range valueAfterMap.(map[string]interface{}) {
item.ConnectionId = data.Options.ConnectionId
item.ChangelogId = storyChangelog.Id
item.Field = k
item.ValueAfterParsed = cast.ToString(v)
switch v := valueBeforeMap.(type) {
case map[string]interface{}:
value := v[k]
item.ValueBeforeParsed = cast.ToString(value)
default:
item.ValueBeforeParsed = cast.ToString(valueBeforeMap)
}
err = convertUnicode(&item)
if err != nil {
logger.Error(err, "convert unicode: %s, err: %s", item, err)
}
results = append(results, &item)
}
default:
item.ConnectionId = data.Options.ConnectionId
item.ChangelogId = storyChangelog.Id
item.Field = fc.Field
item.ValueAfterParsed = cast.ToString(valueAfterMap)
// as ValueAfterParsed is string, valueBeforeMap is always string
item.ValueBeforeParsed = cast.ToString(valueBeforeMap)
}
err = convertUnicode(&item)
if err != nil {
logger.Error(err, "convert unicode: %s, err: %s", item, err)
}
if item.Field == "iteration_id" {
// some users' tapd will not return iteration_id_from/iteration_id_to
iterationFrom, iterationTo, err := parseIterationChangelog(taskCtx, item.ValueBeforeParsed, item.ValueAfterParsed)
if err != nil {
return nil, err
}
item.IterationIdFrom = iterationFrom
item.IterationIdTo = iterationTo
}
results = append(results, &item)
}
results = append(results, &storyChangelog)
return results, nil
},
})
if err != nil {
return err
}
return extractor.Execute()
}