blob: d48704836499bb4095f1006b0fd64cf421ec0e1d [file] [log] [blame]
package tasks
import (
"encoding/json"
"github.com/apache/incubator-devlake/plugins/core"
"github.com/apache/incubator-devlake/plugins/gitlab/models"
"github.com/apache/incubator-devlake/plugins/helper"
)
var ExtractApiIssuesMeta = core.SubTaskMeta{
Name: "extractApiIssues",
EntryPoint: ExtractApiIssues,
EnabledByDefault: true,
Description: "Extract raw Issues data into tool layer table gitlab_issues",
}
type IssuesResponse struct {
ProjectId int `json:"project_id"`
Milestone struct {
Due_date string
Project_id int
State string
Description string
Iid int
Id int
Title string
CreatedAt helper.Iso8601Time
UpdatedAt helper.Iso8601Time
}
Author struct {
State string
WebUrl string
AvatarUrl string
Username string
Id int
Name string
}
Description string
State string
Iid int
Assignees []struct {
AvatarUrl string
WebUrl string
State string
Username string
Id int
Name string
}
Assignee *struct {
AvatarUrl string
WebUrl string
State string
Username string
Id int
Name string
}
Type string
Labels []string `json:"labels"`
UpVotes int
DownVotes int
MergeRequestsCount int
Id int `json:"id"`
Title string
GitlabUpdatedAt helper.Iso8601Time `json:"updated_at"`
GitlabCreatedAt helper.Iso8601Time `json:"created_at"`
GitlabClosedAt *helper.Iso8601Time `json:"closed_at"`
ClosedBy struct {
State string
WebUrl string
AvatarUrl string
Username string
Id int
Name string
}
UserNotesCount int
DueDate helper.Iso8601Time
WebUrl string `json:"web_url"`
References struct {
Short string
Relative string
Full string
}
TimeStats struct {
TimeEstimate int64
TotalTimeSpent int64
HumanTimeEstimate string
HumanTotalTimeSpent string
}
HasTasks bool
TaskStatus string
Confidential bool
DiscussionLocked bool
IssueType string
Serverity string
Links struct {
Self string `json:"url"`
Notes string
AwardEmoji string
Project string
}
TaskCompletionStatus struct {
Count int
CompletedCount int
}
}
func ExtractApiIssues(taskCtx core.SubTaskContext) error {
data := taskCtx.GetData().(*GitlabTaskData)
extractor, err := helper.NewApiExtractor(helper.ApiExtractorArgs{
RawDataSubTaskArgs: helper.RawDataSubTaskArgs{
Ctx: taskCtx,
/*
This struct will be JSONEncoded and stored into database along with raw data itself, to identity minimal
set of data to be process, for example, we process JiraIssues by Board
*/
Params: GitlabApiParams{
ProjectId: data.Options.ProjectId,
},
/*
Table store raw data
*/
Table: RAW_ISSUE_TABLE,
},
Extract: func(row *helper.RawData) ([]interface{}, error) {
body := &IssuesResponse{}
err := json.Unmarshal(row.Data, body)
if err != nil {
return nil, err
}
// need to extract 2 kinds of entities here
if body.ProjectId == 0 {
return nil, nil
}
//If this is not Issue, ignore
if body.IssueType != "ISSUE" && body.Type != "ISSUE" {
return nil, nil
}
results := make([]interface{}, 0, 2)
gitlabIssue, err := convertGitlabIssue(body, data.Options.ProjectId)
if err != nil {
return nil, err
}
for _, label := range body.Labels {
results = append(results, &models.GitlabIssueLabel{
IssueId: gitlabIssue.GitlabId,
LabelName: label,
})
}
results = append(results, gitlabIssue)
return results, nil
},
})
if err != nil {
return err
}
return extractor.Execute()
}
func convertGitlabIssue(issue *IssuesResponse, projectId int) (*models.GitlabIssue, error) {
gitlabIssue := &models.GitlabIssue{
GitlabId: issue.Id,
ProjectId: projectId,
Number: issue.Iid,
State: issue.State,
Title: issue.Title,
Body: issue.Description,
Url: issue.Links.Self,
ClosedAt: helper.Iso8601TimeToTime(issue.GitlabClosedAt),
GitlabCreatedAt: issue.GitlabCreatedAt.ToTime(),
GitlabUpdatedAt: issue.GitlabUpdatedAt.ToTime(),
TimeEstimate: issue.TimeStats.TimeEstimate,
TotalTimeSpent: issue.TimeStats.TotalTimeSpent,
}
if issue.Assignee != nil {
gitlabIssue.AssigneeId = issue.Assignee.Id
gitlabIssue.AssigneeName = issue.Assignee.Username
}
if issue.GitlabClosedAt != nil {
gitlabIssue.LeadTimeMinutes = uint(issue.GitlabClosedAt.ToTime().Sub(issue.GitlabCreatedAt.ToTime()).Minutes())
}
return gitlabIssue, nil
}