You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@devlake.apache.org by wa...@apache.org on 2022/06/23 14:05:58 UTC

[incubator-devlake] branch main updated (047bf281 -> 75f12569)

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

warren pushed a change to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-devlake.git


    from 047bf281 test(gitlab): refresh test data
     new 43707f88 feat: project,board,issue
     new 75f12569 fix: fix e2e error

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../e2e/board_test.go}                             |  66 ++++----
 plugins/jira/e2e/issue_test.go                     | 149 +++++++++++++++++
 .../story_bug_test.go => jira/e2e/project_test.go} |  47 +++---
 .../jira/e2e/raw_tables/_raw_jira_api_boards.csv   |   2 +
 .../jira/e2e/raw_tables/_raw_jira_api_issues.csv   |  31 ++++
 .../jira/e2e/raw_tables/_raw_jira_api_projects.csv |  13 ++
 .../snapshot_tables/_tool_jira_board_issues.csv    |  31 ++++
 .../jira/e2e/snapshot_tables/_tool_jira_boards.csv |   2 +
 .../jira/e2e/snapshot_tables/_tool_jira_issues.csv |  31 ++++
 .../e2e/snapshot_tables/_tool_jira_projects.csv    |  13 ++
 plugins/jira/e2e/snapshot_tables/board_issues.csv  |  31 ++++
 plugins/jira/e2e/snapshot_tables/boards.csv        |   2 +
 plugins/jira/e2e/snapshot_tables/issues.csv        |  31 ++++
 plugins/jira/{jira.go => impl/impl.go}             |  79 ++++-----
 plugins/jira/jira.go                               | 181 +--------------------
 plugins/jira/tasks/board_collector.go              |   7 +
 plugins/jira/tasks/board_convertor.go              |   7 +
 plugins/jira/tasks/board_extractor.go              |   6 +
 plugins/jira/tasks/changelog_collector.go          |   7 +
 plugins/jira/tasks/changelog_convertor.go          |   7 +
 plugins/jira/tasks/changelog_extractor.go          |   7 +
 plugins/jira/tasks/issue_collector.go              |   7 +
 plugins/jira/tasks/issue_commit_convertor.go       |   7 +
 plugins/jira/tasks/issue_convertor.go              |   7 +
 plugins/jira/tasks/issue_extractor.go              |   7 +
 plugins/jira/tasks/issue_repo_commit_convertor.go  |   7 +
 plugins/jira/tasks/project_collector.go            |   7 +
 plugins/jira/tasks/project_extractor.go            |   7 +
 plugins/jira/tasks/remotelink_collector.go         |   7 +
 plugins/jira/tasks/remotelink_extractor.go         |   7 +
 plugins/jira/tasks/sprint_collector.go             |   7 +
 plugins/jira/tasks/sprint_convertor.go             |   7 +
 plugins/jira/tasks/sprint_extractor.go             |   7 +
 plugins/jira/tasks/sprint_issues_convertor.go      |   7 +
 plugins/jira/tasks/status_collector.go             |   7 +
 plugins/jira/tasks/status_extractor.go             |   7 +
 plugins/jira/tasks/user_collector.go               |   7 +
 plugins/jira/tasks/user_convertor.go               |   7 +
 plugins/jira/tasks/user_extractor.go               |   7 +
 plugins/jira/tasks/worklog_collector.go            |   7 +
 plugins/jira/tasks/worklog_convertor.go            |   7 +
 plugins/jira/tasks/worklog_extractor.go            |   7 +
 42 files changed, 603 insertions(+), 294 deletions(-)
 copy plugins/{tapd/e2e/sub_workspace_test.go => jira/e2e/board_test.go} (51%)
 create mode 100644 plugins/jira/e2e/issue_test.go
 copy plugins/{tapd/e2e/story_bug_test.go => jira/e2e/project_test.go} (55%)
 create mode 100644 plugins/jira/e2e/raw_tables/_raw_jira_api_boards.csv
 create mode 100644 plugins/jira/e2e/raw_tables/_raw_jira_api_issues.csv
 create mode 100644 plugins/jira/e2e/raw_tables/_raw_jira_api_projects.csv
 create mode 100644 plugins/jira/e2e/snapshot_tables/_tool_jira_board_issues.csv
 create mode 100644 plugins/jira/e2e/snapshot_tables/_tool_jira_boards.csv
 create mode 100644 plugins/jira/e2e/snapshot_tables/_tool_jira_issues.csv
 create mode 100644 plugins/jira/e2e/snapshot_tables/_tool_jira_projects.csv
 create mode 100644 plugins/jira/e2e/snapshot_tables/board_issues.csv
 create mode 100644 plugins/jira/e2e/snapshot_tables/boards.csv
 create mode 100644 plugins/jira/e2e/snapshot_tables/issues.csv
 copy plugins/jira/{jira.go => impl/impl.go} (52%)


[incubator-devlake] 02/02: fix: fix e2e error

Posted by wa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 75f125698670136fa9399d3e52f9850b2c35ceb1
Author: zhangliang <li...@merico.dev>
AuthorDate: Thu Jun 23 21:23:29 2022 +0800

    fix: fix e2e error
---
 plugins/jira/e2e/issue_test.go | 2 --
 1 file changed, 2 deletions(-)

diff --git a/plugins/jira/e2e/issue_test.go b/plugins/jira/e2e/issue_test.go
index 767afada..4ea35e9c 100644
--- a/plugins/jira/e2e/issue_test.go
+++ b/plugins/jira/e2e/issue_test.go
@@ -89,8 +89,6 @@ func TestIssueDataFlow(t *testing.T) {
 			"std_story_point",
 			"std_type",
 			"std_status",
-			"created_at",
-			"updated_at",
 			"_raw_data_params",
 			"_raw_data_table",
 			"_raw_data_id",


[incubator-devlake] 01/02: feat: project,board,issue

Posted by wa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 43707f8850ce36233ecfbd5e03eca8a6c4e6c87b
Author: zhangliang <li...@merico.dev>
AuthorDate: Thu Jun 23 21:00:41 2022 +0800

    feat: project,board,issue
---
 plugins/jira/e2e/board_test.go                     |  80 +++++++++
 plugins/jira/e2e/issue_test.go                     | 151 +++++++++++++++++
 plugins/jira/e2e/project_test.go                   |  61 +++++++
 .../jira/e2e/raw_tables/_raw_jira_api_boards.csv   |   2 +
 .../jira/e2e/raw_tables/_raw_jira_api_issues.csv   |  31 ++++
 .../jira/e2e/raw_tables/_raw_jira_api_projects.csv |  13 ++
 .../snapshot_tables/_tool_jira_board_issues.csv    |  31 ++++
 .../jira/e2e/snapshot_tables/_tool_jira_boards.csv |   2 +
 .../jira/e2e/snapshot_tables/_tool_jira_issues.csv |  31 ++++
 .../e2e/snapshot_tables/_tool_jira_projects.csv    |  13 ++
 plugins/jira/e2e/snapshot_tables/board_issues.csv  |  31 ++++
 plugins/jira/e2e/snapshot_tables/boards.csv        |   2 +
 plugins/jira/e2e/snapshot_tables/issues.csv        |  31 ++++
 plugins/jira/{jira.go => impl/impl.go}             |  79 ++++-----
 plugins/jira/jira.go                               | 181 +--------------------
 plugins/jira/tasks/board_collector.go              |   7 +
 plugins/jira/tasks/board_convertor.go              |   7 +
 plugins/jira/tasks/board_extractor.go              |   6 +
 plugins/jira/tasks/changelog_collector.go          |   7 +
 plugins/jira/tasks/changelog_convertor.go          |   7 +
 plugins/jira/tasks/changelog_extractor.go          |   7 +
 plugins/jira/tasks/issue_collector.go              |   7 +
 plugins/jira/tasks/issue_commit_convertor.go       |   7 +
 plugins/jira/tasks/issue_convertor.go              |   7 +
 plugins/jira/tasks/issue_extractor.go              |   7 +
 plugins/jira/tasks/issue_repo_commit_convertor.go  |   7 +
 plugins/jira/tasks/project_collector.go            |   7 +
 plugins/jira/tasks/project_extractor.go            |   7 +
 plugins/jira/tasks/remotelink_collector.go         |   7 +
 plugins/jira/tasks/remotelink_extractor.go         |   7 +
 plugins/jira/tasks/sprint_collector.go             |   7 +
 plugins/jira/tasks/sprint_convertor.go             |   7 +
 plugins/jira/tasks/sprint_extractor.go             |   7 +
 plugins/jira/tasks/sprint_issues_convertor.go      |   7 +
 plugins/jira/tasks/status_collector.go             |   7 +
 plugins/jira/tasks/status_extractor.go             |   7 +
 plugins/jira/tasks/user_collector.go               |   7 +
 plugins/jira/tasks/user_convertor.go               |   7 +
 plugins/jira/tasks/user_extractor.go               |   7 +
 plugins/jira/tasks/worklog_collector.go            |   7 +
 plugins/jira/tasks/worklog_convertor.go            |   7 +
 plugins/jira/tasks/worklog_extractor.go            |   7 +
 42 files changed, 697 insertions(+), 230 deletions(-)

diff --git a/plugins/jira/e2e/board_test.go b/plugins/jira/e2e/board_test.go
new file mode 100644
index 00000000..ef0af874
--- /dev/null
+++ b/plugins/jira/e2e/board_test.go
@@ -0,0 +1,80 @@
+/*
+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 e2e
+
+import (
+	"testing"
+
+	"github.com/apache/incubator-devlake/helpers/e2ehelper"
+	"github.com/apache/incubator-devlake/models/domainlayer/ticket"
+	"github.com/apache/incubator-devlake/plugins/jira/impl"
+	"github.com/apache/incubator-devlake/plugins/jira/models"
+	"github.com/apache/incubator-devlake/plugins/jira/tasks"
+)
+
+func TestBoardDataFlow(t *testing.T) {
+	var plugin impl.Jira
+	dataflowTester := e2ehelper.NewDataFlowTester(t, "jira", plugin)
+
+	taskData := &tasks.JiraTaskData{
+		Options: &tasks.JiraOptions{
+			ConnectionId: 2,
+			BoardId:      8,
+		},
+	}
+
+	// import raw data table
+	dataflowTester.ImportCsvIntoRawTable("./raw_tables/_raw_jira_api_boards.csv", "_raw_jira_api_boards")
+
+	// verify board extraction
+	dataflowTester.FlushTabler(&models.JiraBoard{})
+	dataflowTester.Subtask(tasks.ExtractBoardMeta, taskData)
+	dataflowTester.VerifyTable(
+		models.JiraBoard{},
+		"./snapshot_tables/_tool_jira_boards.csv",
+		[]string{"connection_id", "board_id"},
+		[]string{
+			"connection_id",
+			"board_id",
+			"project_id",
+			"name",
+			"self",
+			"type",
+			"_raw_data_params",
+			"_raw_data_table",
+			"_raw_data_id",
+			"_raw_data_remark",
+		},
+	)
+
+	// verify board conversion
+	dataflowTester.FlushTabler(&ticket.Board{})
+	dataflowTester.Subtask(tasks.ConvertBoardMeta, taskData)
+	dataflowTester.VerifyTable(
+		ticket.Board{},
+		"./snapshot_tables/boards.csv",
+		[]string{"id"},
+		[]string{
+			"id",
+			"name",
+			"description",
+			"url",
+			"created_date",
+		},
+	)
+}
diff --git a/plugins/jira/e2e/issue_test.go b/plugins/jira/e2e/issue_test.go
new file mode 100644
index 00000000..767afada
--- /dev/null
+++ b/plugins/jira/e2e/issue_test.go
@@ -0,0 +1,151 @@
+/*
+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 e2e
+
+import (
+	"testing"
+
+	"github.com/apache/incubator-devlake/helpers/e2ehelper"
+	"github.com/apache/incubator-devlake/models/domainlayer/ticket"
+	"github.com/apache/incubator-devlake/plugins/jira/impl"
+	"github.com/apache/incubator-devlake/plugins/jira/models"
+	"github.com/apache/incubator-devlake/plugins/jira/tasks"
+)
+
+func TestIssueDataFlow(t *testing.T) {
+	var plugin impl.Jira
+	dataflowTester := e2ehelper.NewDataFlowTester(t, "jira", plugin)
+
+	taskData := &tasks.JiraTaskData{
+		Options: &tasks.JiraOptions{
+			ConnectionId: 2,
+			BoardId:      8,
+		},
+	}
+
+	// import raw data table
+	dataflowTester.ImportCsvIntoRawTable("./raw_tables/_raw_jira_api_issues.csv", "_raw_jira_api_issues")
+
+	// verify issue extraction
+	dataflowTester.FlushTabler(&models.JiraIssue{})
+	dataflowTester.FlushTabler(&models.JiraBoardIssue{})
+	dataflowTester.FlushTabler(&models.JiraSprintIssue{})
+	dataflowTester.FlushTabler(&models.JiraChangelog{})
+	dataflowTester.FlushTabler(&models.JiraChangelogItem{})
+	dataflowTester.FlushTabler(&models.JiraWorklog{})
+	dataflowTester.FlushTabler(&models.JiraUser{})
+	dataflowTester.Subtask(tasks.ExtractIssuesMeta, taskData)
+	dataflowTester.VerifyTable(
+		models.JiraIssue{},
+		"./snapshot_tables/_tool_jira_issues.csv",
+		[]string{"connection_id", "issue_id"},
+		[]string{
+			"connection_id",
+			"issue_id",
+			"project_id",
+			"self",
+			"issue_key",
+			"summary",
+			"type",
+			"epic_key",
+			"status_name",
+			"status_key",
+			"story_point",
+			"original_estimate_minutes",
+			"aggregate_estimate_minutes",
+			"remaining_estimate_minutes",
+			"creator_account_id",
+			"creator_account_type",
+			"creator_display_name",
+			"assignee_account_id",
+			"assignee_account_type",
+			"assignee_display_name",
+			"priority_id",
+			"priority_name",
+			"parent_id",
+			"parent_key",
+			"sprint_id",
+			"sprint_name",
+			"resolution_date",
+			"created",
+			"updated",
+			"spent_minutes",
+			"lead_time_minutes",
+			"std_story_point",
+			"std_type",
+			"std_status",
+			"created_at",
+			"updated_at",
+			"_raw_data_params",
+			"_raw_data_table",
+			"_raw_data_id",
+			"_raw_data_remark",
+			"icon_url",
+		},
+	)
+
+	dataflowTester.VerifyTable(
+		models.JiraBoardIssue{},
+		"./snapshot_tables/_tool_jira_board_issues.csv",
+		[]string{"connection_id", "board_id", "issue_id"},
+		[]string{},
+	)
+
+	// verify issue conversion
+	dataflowTester.FlushTabler(&ticket.Issue{})
+	dataflowTester.FlushTabler(&ticket.BoardIssue{})
+	dataflowTester.Subtask(tasks.ConvertIssuesMeta, taskData)
+	dataflowTester.VerifyTable(
+		ticket.Issue{},
+		"./snapshot_tables/issues.csv",
+		[]string{"id"},
+		[]string{
+			"url",
+			"icon_url",
+			"issue_key",
+			"title",
+			"description",
+			"epic_key",
+			"type",
+			"status",
+			"original_status",
+			"story_point",
+			"resolution_date",
+			"created_date",
+			"updated_date",
+			"lead_time_minutes",
+			"parent_issue_id",
+			"priority",
+			"original_estimate_minutes",
+			"time_spent_minutes",
+			"time_remaining_minutes",
+			"creator_id",
+			"creator_name",
+			"assignee_id",
+			"assignee_name",
+			"severity",
+			"component",
+		},
+	)
+	dataflowTester.VerifyTable(
+		ticket.BoardIssue{},
+		"./snapshot_tables/board_issues.csv",
+		[]string{"board_id", "issue_id"},
+		[]string{},
+	)
+}
diff --git a/plugins/jira/e2e/project_test.go b/plugins/jira/e2e/project_test.go
new file mode 100644
index 00000000..3669c0d7
--- /dev/null
+++ b/plugins/jira/e2e/project_test.go
@@ -0,0 +1,61 @@
+/*
+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 e2e
+
+import (
+	"testing"
+
+	"github.com/apache/incubator-devlake/helpers/e2ehelper"
+	"github.com/apache/incubator-devlake/plugins/jira/impl"
+	"github.com/apache/incubator-devlake/plugins/jira/models"
+	"github.com/apache/incubator-devlake/plugins/jira/tasks"
+)
+
+func TestProjectDataFlow(t *testing.T) {
+	var plugin impl.Jira
+	dataflowTester := e2ehelper.NewDataFlowTester(t, "jira", plugin)
+
+	taskData := &tasks.JiraTaskData{
+		Options: &tasks.JiraOptions{
+			ConnectionId: 2,
+			BoardId:      8,
+		},
+	}
+
+	// import raw data table
+	dataflowTester.ImportCsvIntoRawTable("./raw_tables/_raw_jira_api_projects.csv", "_raw_jira_api_projects")
+
+	// verify issue extraction
+	dataflowTester.FlushTabler(&models.JiraProject{})
+	dataflowTester.Subtask(tasks.ExtractProjectsMeta, taskData)
+	dataflowTester.VerifyTable(
+		models.JiraProject{},
+		"./snapshot_tables/_tool_jira_projects.csv",
+		[]string{"connection_id", "id"},
+		[]string{
+			"connection_id",
+			"id",
+			"project_key",
+			"name",
+			"_raw_data_params",
+			"_raw_data_table",
+			"_raw_data_id",
+			"_raw_data_remark",
+		},
+	)
+}
diff --git a/plugins/jira/e2e/raw_tables/_raw_jira_api_boards.csv b/plugins/jira/e2e/raw_tables/_raw_jira_api_boards.csv
new file mode 100644
index 00000000..99f53629
--- /dev/null
+++ b/plugins/jira/e2e/raw_tables/_raw_jira_api_boards.csv
@@ -0,0 +1,2 @@
+"id","params","data","url","input","created_at"
+7,"{""ConnectionId"":2,""BoardId"":8}","{""id"": 8, ""name"": ""迭代开发看板(停用)"", ""self"": ""https://merico.atlassian.net/rest/agile/1.0/board/8"", ""type"": ""scrum"", ""location"": {""name"": ""Enterprise Edition (EE)"", ""avatarURI"": ""https://merico.atlassian.net/rest/api/2/universal_avatar/view/type/project/avatar/10552?size=small"", ""projectId"": 10003, ""projectKey"": ""EE"", ""displayName"": ""Enterprise Edition (EE)"", ""projectName"": ""Enterprise Edition"", ""projectTypeKey"":  [...]
diff --git a/plugins/jira/e2e/raw_tables/_raw_jira_api_issues.csv b/plugins/jira/e2e/raw_tables/_raw_jira_api_issues.csv
new file mode 100644
index 00000000..43386dea
--- /dev/null
+++ b/plugins/jira/e2e/raw_tables/_raw_jira_api_issues.csv
@@ -0,0 +1,31 @@
+"id","params","data","url","input","created_at"
+12441,"{""ConnectionId"":2,""BoardId"":8}","{""id"": ""10063"", ""key"": ""EE-1"", ""self"": ""https://merico.atlassian.net/rest/agile/1.0/issue/10063"", ""expand"": ""operations,versionedRepresentations,editmeta,changelog,renderedFields"", ""fields"": {""epic"": null, ""votes"": {""self"": ""https://merico.atlassian.net/rest/api/2/issue/EE-1/votes"", ""votes"": 0, ""hasVoted"": false}, ""labels"": [], ""sprint"": null, ""status"": {""id"": ""10068"", ""name"": ""已完成"", ""self"": ""https [...]
+12442,"{""ConnectionId"":2,""BoardId"":8}","{""id"": ""10064"", ""key"": ""EE-2"", ""self"": ""https://merico.atlassian.net/rest/agile/1.0/issue/10064"", ""expand"": ""operations,versionedRepresentations,editmeta,changelog,renderedFields"", ""fields"": {""epic"": null, ""votes"": {""self"": ""https://merico.atlassian.net/rest/api/2/issue/EE-2/votes"", ""votes"": 0, ""hasVoted"": false}, ""labels"": [], ""sprint"": null, ""status"": {""id"": ""10068"", ""name"": ""已完成"", ""self"": ""https [...]
+12443,"{""ConnectionId"":2,""BoardId"":8}","{""id"": ""10065"", ""key"": ""EE-3"", ""self"": ""https://merico.atlassian.net/rest/agile/1.0/issue/10065"", ""expand"": ""operations,versionedRepresentations,editmeta,changelog,renderedFields"", ""fields"": {""epic"": null, ""votes"": {""self"": ""https://merico.atlassian.net/rest/api/2/issue/EE-3/votes"", ""votes"": 0, ""hasVoted"": false}, ""labels"": [], ""sprint"": null, ""status"": {""id"": ""10068"", ""name"": ""已完成"", ""self"": ""https [...]
+12444,"{""ConnectionId"":2,""BoardId"":8}","{""id"": ""10066"", ""key"": ""EE-4"", ""self"": ""https://merico.atlassian.net/rest/agile/1.0/issue/10066"", ""expand"": ""operations,versionedRepresentations,editmeta,changelog,renderedFields"", ""fields"": {""epic"": null, ""votes"": {""self"": ""https://merico.atlassian.net/rest/api/2/issue/EE-4/votes"", ""votes"": 0, ""hasVoted"": false}, ""labels"": [], ""sprint"": null, ""status"": {""id"": ""10068"", ""name"": ""已完成"", ""self"": ""https [...]
+12445,"{""ConnectionId"":2,""BoardId"":8}","{""id"": ""10067"", ""key"": ""EE-5"", ""self"": ""https://merico.atlassian.net/rest/agile/1.0/issue/10067"", ""expand"": ""operations,versionedRepresentations,editmeta,changelog,renderedFields"", ""fields"": {""epic"": null, ""votes"": {""self"": ""https://merico.atlassian.net/rest/api/2/issue/EE-5/votes"", ""votes"": 0, ""hasVoted"": false}, ""labels"": [], ""sprint"": null, ""status"": {""id"": ""10068"", ""name"": ""已完成"", ""self"": ""https [...]
+12446,"{""ConnectionId"":2,""BoardId"":8}","{""id"": ""10068"", ""key"": ""EE-6"", ""self"": ""https://merico.atlassian.net/rest/agile/1.0/issue/10068"", ""expand"": ""operations,versionedRepresentations,editmeta,changelog,renderedFields"", ""fields"": {""epic"": null, ""votes"": {""self"": ""https://merico.atlassian.net/rest/api/2/issue/EE-6/votes"", ""votes"": 0, ""hasVoted"": false}, ""labels"": [], ""sprint"": null, ""status"": {""id"": ""10068"", ""name"": ""已完成"", ""self"": ""https [...]
+12447,"{""ConnectionId"":2,""BoardId"":8}","{""id"": ""10070"", ""key"": ""EE-8"", ""self"": ""https://merico.atlassian.net/rest/agile/1.0/issue/10070"", ""expand"": ""operations,versionedRepresentations,editmeta,changelog,renderedFields"", ""fields"": {""epic"": null, ""votes"": {""self"": ""https://merico.atlassian.net/rest/api/2/issue/EE-8/votes"", ""votes"": 0, ""hasVoted"": false}, ""labels"": [], ""sprint"": null, ""status"": {""id"": ""10068"", ""name"": ""已完成"", ""self"": ""https [...]
+12448,"{""ConnectionId"":2,""BoardId"":8}","{""id"": ""10071"", ""key"": ""EE-9"", ""self"": ""https://merico.atlassian.net/rest/agile/1.0/issue/10071"", ""expand"": ""operations,versionedRepresentations,editmeta,changelog,renderedFields"", ""fields"": {""epic"": null, ""votes"": {""self"": ""https://merico.atlassian.net/rest/api/2/issue/EE-9/votes"", ""votes"": 0, ""hasVoted"": false}, ""labels"": [], ""sprint"": null, ""status"": {""id"": ""10068"", ""name"": ""已完成"", ""self"": ""https [...]
+12449,"{""ConnectionId"":2,""BoardId"":8}","{""id"": ""10072"", ""key"": ""EE-10"", ""self"": ""https://merico.atlassian.net/rest/agile/1.0/issue/10072"", ""expand"": ""operations,versionedRepresentations,editmeta,changelog,renderedFields"", ""fields"": {""epic"": null, ""votes"": {""self"": ""https://merico.atlassian.net/rest/api/2/issue/EE-10/votes"", ""votes"": 0, ""hasVoted"": false}, ""labels"": [], ""sprint"": null, ""status"": {""id"": ""10068"", ""name"": ""已完成"", ""self"": ""htt [...]
+12450,"{""ConnectionId"":2,""BoardId"":8}","{""id"": ""10076"", ""key"": ""EE-14"", ""self"": ""https://merico.atlassian.net/rest/agile/1.0/issue/10076"", ""expand"": ""operations,versionedRepresentations,editmeta,changelog,renderedFields"", ""fields"": {""epic"": null, ""votes"": {""self"": ""https://merico.atlassian.net/rest/api/2/issue/EE-14/votes"", ""votes"": 0, ""hasVoted"": false}, ""labels"": [], ""sprint"": null, ""status"": {""id"": ""10068"", ""name"": ""已完成"", ""self"": ""htt [...]
+12451,"{""ConnectionId"":2,""BoardId"":8}","{""id"": ""10077"", ""key"": ""EE-15"", ""self"": ""https://merico.atlassian.net/rest/agile/1.0/issue/10077"", ""expand"": ""operations,versionedRepresentations,editmeta,changelog,renderedFields"", ""fields"": {""epic"": null, ""votes"": {""self"": ""https://merico.atlassian.net/rest/api/2/issue/EE-15/votes"", ""votes"": 0, ""hasVoted"": false}, ""labels"": [], ""sprint"": null, ""status"": {""id"": ""10068"", ""name"": ""已完成"", ""self"": ""htt [...]
+12452,"{""ConnectionId"":2,""BoardId"":8}","{""id"": ""10078"", ""key"": ""EE-16"", ""self"": ""https://merico.atlassian.net/rest/agile/1.0/issue/10078"", ""expand"": ""operations,versionedRepresentations,editmeta,changelog,renderedFields"", ""fields"": {""epic"": null, ""votes"": {""self"": ""https://merico.atlassian.net/rest/api/2/issue/EE-16/votes"", ""votes"": 0, ""hasVoted"": false}, ""labels"": [], ""sprint"": null, ""status"": {""id"": ""10068"", ""name"": ""已完成"", ""self"": ""htt [...]
+12453,"{""ConnectionId"":2,""BoardId"":8}","{""id"": ""10079"", ""key"": ""EE-17"", ""self"": ""https://merico.atlassian.net/rest/agile/1.0/issue/10079"", ""expand"": ""operations,versionedRepresentations,editmeta,changelog,renderedFields"", ""fields"": {""epic"": null, ""votes"": {""self"": ""https://merico.atlassian.net/rest/api/2/issue/EE-17/votes"", ""votes"": 0, ""hasVoted"": false}, ""labels"": [], ""sprint"": null, ""status"": {""id"": ""10068"", ""name"": ""已完成"", ""self"": ""htt [...]
+12454,"{""ConnectionId"":2,""BoardId"":8}","{""id"": ""10081"", ""key"": ""EE-19"", ""self"": ""https://merico.atlassian.net/rest/agile/1.0/issue/10081"", ""expand"": ""operations,versionedRepresentations,editmeta,changelog,renderedFields"", ""fields"": {""epic"": null, ""votes"": {""self"": ""https://merico.atlassian.net/rest/api/2/issue/EE-19/votes"", ""votes"": 0, ""hasVoted"": false}, ""labels"": [], ""sprint"": null, ""status"": {""id"": ""10068"", ""name"": ""已完成"", ""self"": ""htt [...]
+12455,"{""ConnectionId"":2,""BoardId"":8}","{""id"": ""10082"", ""key"": ""EE-20"", ""self"": ""https://merico.atlassian.net/rest/agile/1.0/issue/10082"", ""expand"": ""operations,versionedRepresentations,editmeta,changelog,renderedFields"", ""fields"": {""epic"": null, ""votes"": {""self"": ""https://merico.atlassian.net/rest/api/2/issue/EE-20/votes"", ""votes"": 0, ""hasVoted"": false}, ""labels"": [], ""sprint"": null, ""status"": {""id"": ""10068"", ""name"": ""已完成"", ""self"": ""htt [...]
+12456,"{""ConnectionId"":2,""BoardId"":8}","{""id"": ""10085"", ""key"": ""EE-23"", ""self"": ""https://merico.atlassian.net/rest/agile/1.0/issue/10085"", ""expand"": ""operations,versionedRepresentations,editmeta,changelog,renderedFields"", ""fields"": {""epic"": null, ""votes"": {""self"": ""https://merico.atlassian.net/rest/api/2/issue/EE-23/votes"", ""votes"": 0, ""hasVoted"": false}, ""labels"": [], ""sprint"": null, ""status"": {""id"": ""10068"", ""name"": ""已完成"", ""self"": ""htt [...]
+12457,"{""ConnectionId"":2,""BoardId"":8}","{""id"": ""10086"", ""key"": ""EE-24"", ""self"": ""https://merico.atlassian.net/rest/agile/1.0/issue/10086"", ""expand"": ""operations,versionedRepresentations,editmeta,changelog,renderedFields"", ""fields"": {""epic"": null, ""votes"": {""self"": ""https://merico.atlassian.net/rest/api/2/issue/EE-24/votes"", ""votes"": 0, ""hasVoted"": false}, ""labels"": [], ""sprint"": null, ""status"": {""id"": ""10068"", ""name"": ""已完成"", ""self"": ""htt [...]
+12458,"{""ConnectionId"":2,""BoardId"":8}","{""id"": ""10087"", ""key"": ""EE-25"", ""self"": ""https://merico.atlassian.net/rest/agile/1.0/issue/10087"", ""expand"": ""operations,versionedRepresentations,editmeta,changelog,renderedFields"", ""fields"": {""epic"": null, ""votes"": {""self"": ""https://merico.atlassian.net/rest/api/2/issue/EE-25/votes"", ""votes"": 0, ""hasVoted"": false}, ""labels"": [], ""parent"": {""id"": ""10063"", ""key"": ""EE-1"", ""self"": ""https://merico.atlass [...]
+12459,"{""ConnectionId"":2,""BoardId"":8}","{""id"": ""10088"", ""key"": ""EE-26"", ""self"": ""https://merico.atlassian.net/rest/agile/1.0/issue/10088"", ""expand"": ""operations,versionedRepresentations,editmeta,changelog,renderedFields"", ""fields"": {""epic"": null, ""votes"": {""self"": ""https://merico.atlassian.net/rest/api/2/issue/EE-26/votes"", ""votes"": 0, ""hasVoted"": false}, ""labels"": [], ""parent"": {""id"": ""10063"", ""key"": ""EE-1"", ""self"": ""https://merico.atlass [...]
+12460,"{""ConnectionId"":2,""BoardId"":8}","{""id"": ""10089"", ""key"": ""EE-27"", ""self"": ""https://merico.atlassian.net/rest/agile/1.0/issue/10089"", ""expand"": ""operations,versionedRepresentations,editmeta,changelog,renderedFields"", ""fields"": {""epic"": null, ""votes"": {""self"": ""https://merico.atlassian.net/rest/api/2/issue/EE-27/votes"", ""votes"": 0, ""hasVoted"": false}, ""labels"": [], ""parent"": {""id"": ""10063"", ""key"": ""EE-1"", ""self"": ""https://merico.atlass [...]
+12461,"{""ConnectionId"":2,""BoardId"":8}","{""id"": ""10090"", ""key"": ""EE-28"", ""self"": ""https://merico.atlassian.net/rest/agile/1.0/issue/10090"", ""expand"": ""operations,versionedRepresentations,editmeta,changelog,renderedFields"", ""fields"": {""epic"": null, ""votes"": {""self"": ""https://merico.atlassian.net/rest/api/2/issue/EE-28/votes"", ""votes"": 0, ""hasVoted"": false}, ""labels"": [], ""parent"": {""id"": ""10063"", ""key"": ""EE-1"", ""self"": ""https://merico.atlass [...]
+12462,"{""ConnectionId"":2,""BoardId"":8}","{""id"": ""10091"", ""key"": ""EE-29"", ""self"": ""https://merico.atlassian.net/rest/agile/1.0/issue/10091"", ""expand"": ""operations,versionedRepresentations,editmeta,changelog,renderedFields"", ""fields"": {""epic"": null, ""votes"": {""self"": ""https://merico.atlassian.net/rest/api/2/issue/EE-29/votes"", ""votes"": 0, ""hasVoted"": false}, ""labels"": [], ""parent"": {""id"": ""10064"", ""key"": ""EE-2"", ""self"": ""https://merico.atlass [...]
+12463,"{""ConnectionId"":2,""BoardId"":8}","{""id"": ""10092"", ""key"": ""EE-30"", ""self"": ""https://merico.atlassian.net/rest/agile/1.0/issue/10092"", ""expand"": ""operations,versionedRepresentations,editmeta,changelog,renderedFields"", ""fields"": {""epic"": null, ""votes"": {""self"": ""https://merico.atlassian.net/rest/api/2/issue/EE-30/votes"", ""votes"": 0, ""hasVoted"": false}, ""labels"": [], ""parent"": {""id"": ""10064"", ""key"": ""EE-2"", ""self"": ""https://merico.atlass [...]
+12464,"{""ConnectionId"":2,""BoardId"":8}","{""id"": ""10093"", ""key"": ""EE-31"", ""self"": ""https://merico.atlassian.net/rest/agile/1.0/issue/10093"", ""expand"": ""operations,versionedRepresentations,editmeta,changelog,renderedFields"", ""fields"": {""epic"": null, ""votes"": {""self"": ""https://merico.atlassian.net/rest/api/2/issue/EE-31/votes"", ""votes"": 0, ""hasVoted"": false}, ""labels"": [], ""parent"": {""id"": ""10064"", ""key"": ""EE-2"", ""self"": ""https://merico.atlass [...]
+12465,"{""ConnectionId"":2,""BoardId"":8}","{""id"": ""10094"", ""key"": ""EE-32"", ""self"": ""https://merico.atlassian.net/rest/agile/1.0/issue/10094"", ""expand"": ""operations,versionedRepresentations,editmeta,changelog,renderedFields"", ""fields"": {""epic"": null, ""votes"": {""self"": ""https://merico.atlassian.net/rest/api/2/issue/EE-32/votes"", ""votes"": 0, ""hasVoted"": false}, ""labels"": [], ""parent"": {""id"": ""10064"", ""key"": ""EE-2"", ""self"": ""https://merico.atlass [...]
+12466,"{""ConnectionId"":2,""BoardId"":8}","{""id"": ""10095"", ""key"": ""EE-33"", ""self"": ""https://merico.atlassian.net/rest/agile/1.0/issue/10095"", ""expand"": ""operations,versionedRepresentations,editmeta,changelog,renderedFields"", ""fields"": {""epic"": null, ""votes"": {""self"": ""https://merico.atlassian.net/rest/api/2/issue/EE-33/votes"", ""votes"": 0, ""hasVoted"": false}, ""labels"": [], ""parent"": {""id"": ""10063"", ""key"": ""EE-1"", ""self"": ""https://merico.atlass [...]
+12467,"{""ConnectionId"":2,""BoardId"":8}","{""id"": ""10096"", ""key"": ""EE-34"", ""self"": ""https://merico.atlassian.net/rest/agile/1.0/issue/10096"", ""expand"": ""operations,versionedRepresentations,editmeta,changelog,renderedFields"", ""fields"": {""epic"": null, ""votes"": {""self"": ""https://merico.atlassian.net/rest/api/2/issue/EE-34/votes"", ""votes"": 0, ""hasVoted"": false}, ""labels"": [], ""parent"": {""id"": ""10065"", ""key"": ""EE-3"", ""self"": ""https://merico.atlass [...]
+12468,"{""ConnectionId"":2,""BoardId"":8}","{""id"": ""10097"", ""key"": ""EE-35"", ""self"": ""https://merico.atlassian.net/rest/agile/1.0/issue/10097"", ""expand"": ""operations,versionedRepresentations,editmeta,changelog,renderedFields"", ""fields"": {""epic"": null, ""votes"": {""self"": ""https://merico.atlassian.net/rest/api/2/issue/EE-35/votes"", ""votes"": 0, ""hasVoted"": false}, ""labels"": [], ""parent"": {""id"": ""10065"", ""key"": ""EE-3"", ""self"": ""https://merico.atlass [...]
+12469,"{""ConnectionId"":2,""BoardId"":8}","{""id"": ""10098"", ""key"": ""EE-36"", ""self"": ""https://merico.atlassian.net/rest/agile/1.0/issue/10098"", ""expand"": ""operations,versionedRepresentations,editmeta,changelog,renderedFields"", ""fields"": {""epic"": null, ""votes"": {""self"": ""https://merico.atlassian.net/rest/api/2/issue/EE-36/votes"", ""votes"": 0, ""hasVoted"": false}, ""labels"": [], ""parent"": {""id"": ""10065"", ""key"": ""EE-3"", ""self"": ""https://merico.atlass [...]
+12470,"{""ConnectionId"":2,""BoardId"":8}","{""id"": ""10099"", ""key"": ""EE-37"", ""self"": ""https://merico.atlassian.net/rest/agile/1.0/issue/10099"", ""expand"": ""operations,versionedRepresentations,editmeta,changelog,renderedFields"", ""fields"": {""epic"": null, ""votes"": {""self"": ""https://merico.atlassian.net/rest/api/2/issue/EE-37/votes"", ""votes"": 0, ""hasVoted"": false}, ""labels"": [], ""parent"": {""id"": ""10065"", ""key"": ""EE-3"", ""self"": ""https://merico.atlass [...]
diff --git a/plugins/jira/e2e/raw_tables/_raw_jira_api_projects.csv b/plugins/jira/e2e/raw_tables/_raw_jira_api_projects.csv
new file mode 100644
index 00000000..d72a88a7
--- /dev/null
+++ b/plugins/jira/e2e/raw_tables/_raw_jira_api_projects.csv
@@ -0,0 +1,13 @@
+"id","params","data","url","input","created_at"
+48,"{""ConnectionId"":2,""BoardId"":8}","{""id"": ""10007"", ""key"": ""CC"", ""name"": ""Customer Center"", ""self"": ""https://merico.atlassian.net/rest/api/2/project/10007"", ""style"": ""classic"", ""expand"": ""description,lead,issueTypes,url,projectKeys,permissions,insight"", ""isPrivate"": false, ""avatarUrls"": {""16x16"": ""https://merico.atlassian.net/rest/api/2/universal_avatar/view/type/project/avatar/10417?size=xsmall"", ""24x24"": ""https://merico.atlassian.net/rest/api/2/u [...]
+49,"{""ConnectionId"":2,""BoardId"":8}","{""id"": ""10041"", ""key"": ""DEV"", ""name"": ""DevLake"", ""self"": ""https://merico.atlassian.net/rest/api/2/project/10041"", ""uuid"": ""ffb92ace-fe5b-4883-bda5-c6e74bde0dcf"", ""style"": ""next-gen"", ""expand"": ""description,lead,issueTypes,url,projectKeys,permissions,insight"", ""entityId"": ""ffb92ace-fe5b-4883-bda5-c6e74bde0dcf"", ""isPrivate"": false, ""avatarUrls"": {""16x16"": ""https://merico.atlassian.net/rest/api/2/universal_avata [...]
+50,"{""ConnectionId"":2,""BoardId"":8}","{""id"": ""10033"", ""key"": ""DTM"", ""name"": ""DevStream"", ""self"": ""https://merico.atlassian.net/rest/api/2/project/10033"", ""uuid"": ""e20b4ee7-8d71-45df-b353-5e732dd54bc2"", ""style"": ""next-gen"", ""expand"": ""description,lead,issueTypes,url,projectKeys,permissions,insight"", ""entityId"": ""e20b4ee7-8d71-45df-b353-5e732dd54bc2"", ""isPrivate"": false, ""avatarUrls"": {""16x16"": ""https://merico.atlassian.net/rest/api/2/universal_ava [...]
+51,"{""ConnectionId"":2,""BoardId"":8}","{""id"": ""10038"", ""key"": ""DET"", ""name"": ""dtm-e2e-test-do-not-delete"", ""self"": ""https://merico.atlassian.net/rest/api/2/project/10038"", ""uuid"": ""a09c574a-ee44-4cc6-961d-8fd389702b1d"", ""style"": ""next-gen"", ""expand"": ""description,lead,issueTypes,url,projectKeys,permissions,insight"", ""entityId"": ""a09c574a-ee44-4cc6-961d-8fd389702b1d"", ""isPrivate"": false, ""avatarUrls"": {""16x16"": ""https://merico.atlassian.net/rest/ap [...]
+52,"{""ConnectionId"":2,""BoardId"":8}","{""id"": ""10003"", ""key"": ""EE"", ""name"": ""Enterprise Edition"", ""self"": ""https://merico.atlassian.net/rest/api/2/project/10003"", ""style"": ""classic"", ""expand"": ""description,lead,issueTypes,url,projectKeys,permissions,insight"", ""isPrivate"": false, ""avatarUrls"": {""16x16"": ""https://merico.atlassian.net/rest/api/2/universal_avatar/view/type/project/avatar/10552?size=xsmall"", ""24x24"": ""https://merico.atlassian.net/rest/api/ [...]
+53,"{""ConnectionId"":2,""BoardId"":8}","{""id"": ""10034"", ""key"": ""HEAP"", ""name"": ""heapheap"", ""self"": ""https://merico.atlassian.net/rest/api/2/project/10034"", ""uuid"": ""40d71512-575f-4374-a08f-d19f2660c703"", ""style"": ""next-gen"", ""expand"": ""description,lead,issueTypes,url,projectKeys,permissions,insight"", ""entityId"": ""40d71512-575f-4374-a08f-d19f2660c703"", ""isPrivate"": true, ""avatarUrls"": {""16x16"": ""https://merico.atlassian.net/rest/api/2/universal_avat [...]
+54,"{""ConnectionId"":2,""BoardId"":8}","{""id"": ""10040"", ""key"": ""HEP"", ""name"": ""HEP"", ""self"": ""https://merico.atlassian.net/rest/api/2/project/10040"", ""uuid"": ""69b8db3e-0e74-49b3-898e-5b744b7fb90a"", ""style"": ""next-gen"", ""expand"": ""description,lead,issueTypes,url,projectKeys,permissions,insight"", ""entityId"": ""69b8db3e-0e74-49b3-898e-5b744b7fb90a"", ""isPrivate"": true, ""avatarUrls"": {""16x16"": ""https://merico.atlassian.net/rest/api/2/universal_avatar/vie [...]
+55,"{""ConnectionId"":2,""BoardId"":8}","{""id"": ""10008"", ""key"": ""NX"", ""name"": ""Next"", ""self"": ""https://merico.atlassian.net/rest/api/2/project/10008"", ""style"": ""classic"", ""expand"": ""description,lead,issueTypes,url,projectKeys,permissions,insight"", ""isPrivate"": false, ""avatarUrls"": {""16x16"": ""https://merico.atlassian.net/rest/api/2/universal_avatar/view/type/project/avatar/10408?size=xsmall"", ""24x24"": ""https://merico.atlassian.net/rest/api/2/universal_av [...]
+56,"{""ConnectionId"":2,""BoardId"":8}","{""id"": ""10030"", ""key"": ""OR"", ""name"": ""OSS-Ranking"", ""self"": ""https://merico.atlassian.net/rest/api/2/project/10030"", ""style"": ""classic"", ""expand"": ""description,lead,issueTypes,url,projectKeys,permissions,insight"", ""isPrivate"": false, ""avatarUrls"": {""16x16"": ""https://merico.atlassian.net/rest/api/2/universal_avatar/view/type/project/avatar/10417?size=xsmall"", ""24x24"": ""https://merico.atlassian.net/rest/api/2/unive [...]
+57,"{""ConnectionId"":2,""BoardId"":8}","{""id"": ""10037"", ""key"": ""POTP"", ""name"": ""Product on Track Planning"", ""self"": ""https://merico.atlassian.net/rest/api/2/project/10037"", ""style"": ""classic"", ""expand"": ""description,lead,issueTypes,url,projectKeys,permissions,insight"", ""isPrivate"": false, ""avatarUrls"": {""16x16"": ""https://merico.atlassian.net/rest/api/2/universal_avatar/view/type/project/avatar/10416?size=xsmall"", ""24x24"": ""https://merico.atlassian.net/ [...]
+58,"{""ConnectionId"":2,""BoardId"":8}","{""id"": ""10022"", ""key"": ""ROAD"", ""name"": ""Roadmap"", ""self"": ""https://merico.atlassian.net/rest/api/2/project/10022"", ""uuid"": ""9bcf1ed9-3b5d-4d92-9d8c-5d8e8290e0b0"", ""style"": ""next-gen"", ""expand"": ""description,lead,issueTypes,url,projectKeys,permissions,insight"", ""entityId"": ""9bcf1ed9-3b5d-4d92-9d8c-5d8e8290e0b0"", ""isPrivate"": false, ""avatarUrls"": {""16x16"": ""https://merico.atlassian.net/rest/api/2/universal_avat [...]
+59,"{""ConnectionId"":2,""BoardId"":8}","{""id"": ""10029"", ""key"": ""MERICO"", ""name"": ""思码逸跨团队协作"", ""self"": ""https://merico.atlassian.net/rest/api/2/project/10029"", ""style"": ""classic"", ""expand"": ""description,lead,issueTypes,url,projectKeys,permissions,insight"", ""isPrivate"": false, ""avatarUrls"": {""16x16"": ""https://merico.atlassian.net/rest/api/2/universal_avatar/view/type/project/avatar/10416?size=xsmall"", ""24x24"": ""https://merico.atlassian.net/rest/api/2/univ [...]
diff --git a/plugins/jira/e2e/snapshot_tables/_tool_jira_board_issues.csv b/plugins/jira/e2e/snapshot_tables/_tool_jira_board_issues.csv
new file mode 100644
index 00000000..07e4cb49
--- /dev/null
+++ b/plugins/jira/e2e/snapshot_tables/_tool_jira_board_issues.csv
@@ -0,0 +1,31 @@
+connection_id,board_id,issue_id
+2,8,10063
+2,8,10064
+2,8,10065
+2,8,10066
+2,8,10067
+2,8,10068
+2,8,10070
+2,8,10071
+2,8,10072
+2,8,10076
+2,8,10077
+2,8,10078
+2,8,10079
+2,8,10081
+2,8,10082
+2,8,10085
+2,8,10086
+2,8,10087
+2,8,10088
+2,8,10089
+2,8,10090
+2,8,10091
+2,8,10092
+2,8,10093
+2,8,10094
+2,8,10095
+2,8,10096
+2,8,10097
+2,8,10098
+2,8,10099
diff --git a/plugins/jira/e2e/snapshot_tables/_tool_jira_boards.csv b/plugins/jira/e2e/snapshot_tables/_tool_jira_boards.csv
new file mode 100644
index 00000000..df40de57
--- /dev/null
+++ b/plugins/jira/e2e/snapshot_tables/_tool_jira_boards.csv
@@ -0,0 +1,2 @@
+connection_id,board_id,connection_id,board_id,project_id,name,self,type,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark
+2,8,2,8,10003,迭代开发看板(停用),https://merico.atlassian.net/rest/agile/1.0/board/8,scrum,"{""ConnectionId"":2,""BoardId"":8}",_raw_jira_api_boards,7,
diff --git a/plugins/jira/e2e/snapshot_tables/_tool_jira_issues.csv b/plugins/jira/e2e/snapshot_tables/_tool_jira_issues.csv
new file mode 100644
index 00000000..0d79b9dc
--- /dev/null
+++ b/plugins/jira/e2e/snapshot_tables/_tool_jira_issues.csv
@@ -0,0 +1,31 @@
+connection_id,issue_id,connection_id,issue_id,project_id,self,issue_key,summary,type,epic_key,status_name,status_key,story_point,original_estimate_minutes,aggregate_estimate_minutes,remaining_estimate_minutes,creator_account_id,creator_account_type,creator_display_name,assignee_account_id,assignee_account_type,assignee_display_name,priority_id,priority_name,parent_id,parent_key,sprint_id,sprint_name,resolution_date,created,updated,spent_minutes,lead_time_minutes,std_story_point,std_type, [...]
+2,10063,2,10063,10003,https://merico.atlassian.net/rest/agile/1.0/issue/10063,EE-1,​四个排序图:测试/注释覆盖度、复用度、模块性,故事,,已完成,done,0,0,1260,0,5e9711ba34f7b90c0fbc37d3,,Rankin Zheng,5ecfbd0c730ec90c1999cadf,,Dingding Zhang,3,Medium,0,,0,,2020-06-19T06:31:18.495+00:00,2020-06-12T00:13:13.360+00:00,2021-03-28T08:06:08.713+00:00,0,10458,0,故事,DONE,2022-06-23T12:50:47.748+00:00,2022-06-23T12:50:47.748+00:00,"{""ConnectionId"":2,""BoardId"":8}",_raw_jira_api_issues,12441,,https://merico.atlassian.net/rest [...]
+2,10064,2,10064,10003,https://merico.atlassian.net/rest/agile/1.0/issue/10064,EE-2,​问题堆叠分布排序图,故事,,已完成,done,0,0,840,0,5e9711ba34f7b90c0fbc37d3,,Rankin Zheng,5ecfbd0c730ec90c1999cadf,,Dingding Zhang,3,Medium,0,,0,,2020-06-23T10:20:58.999+00:00,2020-06-12T00:15:36.123+00:00,2021-03-28T08:05:55.016+00:00,0,16445,0,故事,DONE,2022-06-23T12:50:47.748+00:00,2022-06-23T12:50:47.748+00:00,"{""ConnectionId"":2,""BoardId"":8}",_raw_jira_api_issues,12442,,https://merico.atlassian.net/rest/api/2/univers [...]
+2,10065,2,10065,10003,https://merico.atlassian.net/rest/agile/1.0/issue/10065,EE-3,​问题积压图率,故事,,已完成,done,0,0,600,0,5e9711ba34f7b90c0fbc37d3,,Rankin Zheng,5ecfbd0c730ec90c1999cadf,,Dingding Zhang,3,Medium,0,,0,,2020-06-23T10:21:11.996+00:00,2020-06-12T00:15:41.600+00:00,2021-03-28T08:05:55.061+00:00,0,16445,0,故事,DONE,2022-06-23T12:50:47.748+00:00,2022-06-23T12:50:47.748+00:00,"{""ConnectionId"":2,""BoardId"":8}",_raw_jira_api_issues,12443,,https://merico.atlassian.net/rest/api/2/universal_ [...]
+2,10066,2,10066,10003,https://merico.atlassian.net/rest/agile/1.0/issue/10066,EE-4,​问题分布的帕累托图,故事,,已完成,done,0,0,480,0,5e9711ba34f7b90c0fbc37d3,,Rankin Zheng,5ecfbd0c730ec90c1999cadf,,Dingding Zhang,3,Medium,0,,0,,2020-06-23T10:21:23.562+00:00,2020-06-12T00:15:46.144+00:00,2021-03-28T08:06:09.535+00:00,0,16445,0,故事,DONE,2022-06-23T12:50:47.748+00:00,2022-06-23T12:50:47.748+00:00,"{""ConnectionId"":2,""BoardId"":8}",_raw_jira_api_issues,12444,,https://merico.atlassian.net/rest/api/2/univers [...]
+2,10067,2,10067,10003,https://merico.atlassian.net/rest/agile/1.0/issue/10067,EE-5,​通用技术任务,任务,,已完成,done,0,0,360,0,5e9711ba34f7b90c0fbc37d3,,Rankin Zheng,5ecfbd0c730ec90c1999cadf,,Dingding Zhang,3,Medium,0,,0,,2020-06-18T04:06:00.747+00:00,2020-06-12T00:16:44.157+00:00,2021-03-28T08:05:54.622+00:00,0,8869,0,任务,DONE,2022-06-23T12:50:47.748+00:00,2022-06-23T12:50:47.748+00:00,"{""ConnectionId"":2,""BoardId"":8}",_raw_jira_api_issues,12445,,https://merico.atlassian.net/rest/api/2/universal_a [...]
+2,10068,2,10068,10003,https://merico.atlassian.net/rest/agile/1.0/issue/10068,EE-6,​变异系数、生产率的四象限图,故事,,已完成,done,0,0,1680,0,5e9711ba34f7b90c0fbc37d3,,Rankin Zheng,5ecfbd0c2490cf0c09e2e598,,Gerile Tu,3,Medium,0,,0,,2020-06-16T11:56:14.433+00:00,2020-06-12T00:17:26.986+00:00,2021-03-28T08:05:56.750+00:00,0,6458,0,故事,DONE,2022-06-23T12:50:47.748+00:00,2022-06-23T12:50:47.748+00:00,"{""ConnectionId"":2,""BoardId"":8}",_raw_jira_api_issues,12446,,https://merico.atlassian.net/rest/api/2/universa [...]
+2,10070,2,10070,10003,https://merico.atlassian.net/rest/agile/1.0/issue/10070,EE-8,​多团队支持,任务,,已完成,done,0,0,5400,0,5e9711ba34f7b90c0fbc37d3,,Rankin Zheng,5ecfbd0ba04d9c0c220c18d8,,yanghui,3,Medium,0,,0,,2020-07-08T17:11:45.201+00:00,2020-06-12T00:18:58.050+00:00,2021-03-28T08:05:54.576+00:00,0,38452,0,任务,DONE,2022-06-23T12:50:47.748+00:00,2022-06-23T12:50:47.748+00:00,"{""ConnectionId"":2,""BoardId"":8}",_raw_jira_api_issues,12447,,https://merico.atlassian.net/rest/api/2/universal_avatar/ [...]
+2,10071,2,10071,10003,https://merico.atlassian.net/rest/agile/1.0/issue/10071,EE-9,Common backend 拆分,任务,,已完成,done,0,1680,1680,1680,5e9711ba34f7b90c0fbc37d3,,Rankin Zheng,5ecfbd0ba04d9c0c220c18d8,,yanghui,3,Medium,0,,0,,2020-07-08T17:12:05.663+00:00,2020-06-12T00:19:17.336+00:00,2021-03-28T08:06:20.165+00:00,0,38452,0,任务,DONE,2022-06-23T12:50:47.748+00:00,2022-06-23T12:50:47.748+00:00,"{""ConnectionId"":2,""BoardId"":8}",_raw_jira_api_issues,12448,,https://merico.atlassian.net/rest/api/2/ [...]
+2,10072,2,10072,10003,https://merico.atlassian.net/rest/agile/1.0/issue/10072,EE-10,​部署SaaS版本,任务,,已完成,done,0,0,0,0,5e9711ba34f7b90c0fbc37d3,,Rankin Zheng,5ecfbd0ba04d9c0c220c18d8,,yanghui,3,Medium,0,,0,,2020-07-08T17:11:55.247+00:00,2020-06-12T00:19:24.637+00:00,2021-03-28T08:05:54.472+00:00,0,38452,0,任务,DONE,2022-06-23T12:50:47.748+00:00,2022-06-23T12:50:47.748+00:00,"{""ConnectionId"":2,""BoardId"":8}",_raw_jira_api_issues,12449,,https://merico.atlassian.net/rest/api/2/universal_avatar [...]
+2,10076,2,10076,10003,https://merico.atlassian.net/rest/agile/1.0/issue/10076,EE-14,调整​文件夹结构,任务,,已完成,done,0,240,0,0,5e9711ba34f7b90c0fbc37d3,,Rankin Zheng,5ecfbd0a47d31e0c2a15fd87,,yuxiang,3,Medium,0,,0,,2020-06-15T08:59:51.304+00:00,2020-06-12T00:24:25.922+00:00,2021-03-28T08:05:56.152+00:00,600,4835,0,任务,DONE,2022-06-23T12:50:47.748+00:00,2022-06-23T12:50:47.748+00:00,"{""ConnectionId"":2,""BoardId"":8}",_raw_jira_api_issues,12450,,https://merico.atlassian.net/rest/api/2/universal_avat [...]
+2,10077,2,10077,10003,https://merico.atlassian.net/rest/agile/1.0/issue/10077,EE-15,路由权限控制,任务,,已完成,done,0,240,0,0,5e9711ba34f7b90c0fbc37d3,,Rankin Zheng,5ecfbd0a47d31e0c2a15fd87,,yuxiang,3,Medium,0,,0,,2020-06-15T09:00:26.956+00:00,2020-06-12T00:24:39.624+00:00,2021-03-28T08:06:01.995+00:00,480,4835,0,任务,DONE,2022-06-23T12:50:47.748+00:00,2022-06-23T12:50:47.748+00:00,"{""ConnectionId"":2,""BoardId"":8}",_raw_jira_api_issues,12451,,https://merico.atlassian.net/rest/api/2/universal_avatar [...]
+2,10078,2,10078,10003,https://merico.atlassian.net/rest/agile/1.0/issue/10078,EE-16,​优化前端 webpack 开发阶段构建速度,任务,,已完成,done,0,0,0,0,5e9711ba34f7b90c0fbc37d3,,Rankin Zheng,5ecfbd0a47d31e0c2a15fd87,,yuxiang,3,Medium,0,,0,,2020-06-15T09:01:44.159+00:00,2020-06-12T00:24:49.017+00:00,2021-03-28T08:05:55.863+00:00,60,4836,0,任务,DONE,2022-06-23T12:50:47.748+00:00,2022-06-23T12:50:47.748+00:00,"{""ConnectionId"":2,""BoardId"":8}",_raw_jira_api_issues,12452,,https://merico.atlassian.net/rest/api/2/uni [...]
+2,10079,2,10079,10003,https://merico.atlassian.net/rest/agile/1.0/issue/10079,EE-17,​新的错误处理机制,任务,,已完成,done,0,360,240,240,5e9711ba34f7b90c0fbc37d3,,Rankin Zheng,5ecfbd0a47d31e0c2a15fd87,,yuxiang,3,Medium,0,,0,,2020-07-22T07:25:29.104+00:00,2020-06-12T00:24:56.048+00:00,2021-03-28T08:05:54.426+00:00,120,58020,0,任务,DONE,2022-06-23T12:50:47.748+00:00,2022-06-23T12:50:47.748+00:00,"{""ConnectionId"":2,""BoardId"":8}",_raw_jira_api_issues,12453,,https://merico.atlassian.net/rest/api/2/universa [...]
+2,10081,2,10081,10003,https://merico.atlassian.net/rest/agile/1.0/issue/10081,EE-19,​LDAP需要支持TLS和证书,故事,,已完成,done,0,0,0,0,5e9711ba34f7b90c0fbc37d3,,Rankin Zheng,5ecfbd0aaa47a00c1997ea8e,,chao.cheng,3,Medium,0,,0,,2020-06-18T08:34:11.117+00:00,2020-06-12T00:28:00.241+00:00,2021-03-28T08:05:57.326+00:00,0,9126,0,故事,DONE,2022-06-23T12:50:47.748+00:00,2022-06-23T12:50:47.748+00:00,"{""ConnectionId"":2,""BoardId"":8}",_raw_jira_api_issues,12454,,https://merico.atlassian.net/rest/api/2/universa [...]
+2,10082,2,10082,10003,https://merico.atlassian.net/rest/agile/1.0/issue/10082,EE-20,团队首页垂直化,故事,,已完成,done,0,0,0,0,5e9711ba34f7b90c0fbc37d3,,Rankin Zheng,5ecfbd0984083c0c12e5af8f,,lin.hao,3,Medium,0,,0,,2020-06-17T07:25:54.370+00:00,2020-06-12T00:29:43.677+00:00,2021-08-06T06:14:54.647+00:00,0,7616,0,故事,DONE,2022-06-23T12:50:47.748+00:00,2022-06-23T12:50:47.748+00:00,"{""ConnectionId"":2,""BoardId"":8}",_raw_jira_api_issues,12455,,https://merico.atlassian.net/rest/api/2/universal_avatar/vi [...]
+2,10085,2,10085,10003,https://merico.atlassian.net/rest/agile/1.0/issue/10085,EE-23,​批量删除事故,缺陷,,已完成,done,0,0,0,0,5e9711ba34f7b90c0fbc37d3,,Rankin Zheng,5ecfbd0a47d31e0c2a15fd87,,yuxiang,3,Medium,0,,0,,2020-06-15T09:07:56.798+00:00,2020-06-12T00:33:57.204+00:00,2021-03-28T08:05:57.095+00:00,60,4833,0,缺陷,DONE,2022-06-23T12:50:47.748+00:00,2022-06-23T12:50:47.748+00:00,"{""ConnectionId"":2,""BoardId"":8}",_raw_jira_api_issues,12456,,https://merico.atlassian.net/rest/api/2/universal_avatar/v [...]
+2,10086,2,10086,10003,https://merico.atlassian.net/rest/agile/1.0/issue/10086,EE-24,​LDAP支持自定义的证书上传,故事,,已完成,done,0,0,0,0,5e9711ba34f7b90c0fbc37d3,,Rankin Zheng,5ecfbd0aaa47a00c1997ea8e,,chao.cheng,3,Medium,0,,0,,2020-06-12T07:17:28.659+00:00,2020-06-12T00:35:15.489+00:00,2021-03-28T08:05:55.819+00:00,0,402,0,故事,DONE,2022-06-23T12:50:47.748+00:00,2022-06-23T12:50:47.748+00:00,"{""ConnectionId"":2,""BoardId"":8}",_raw_jira_api_issues,12457,,https://merico.atlassian.net/rest/api/2/universal [...]
+2,10087,2,10087,10003,https://merico.atlassian.net/rest/agile/1.0/issue/10087,EE-25,​组件封装及Demo,子任务,,已完成,done,0,240,240,240,5e9711ba34f7b90c0fbc37d3,,Rankin Zheng,5ecfbd0c730ec90c1999cadf,,Dingding Zhang,3,Medium,10063,EE-1,0,,2020-06-18T04:02:22.350+00:00,2020-06-12T00:40:54.210+00:00,2021-03-28T08:05:57.189+00:00,0,8841,0,子任务,DONE,2022-06-23T12:50:47.748+00:00,2022-06-23T12:50:47.748+00:00,"{""ConnectionId"":2,""BoardId"":8}",_raw_jira_api_issues,12458,,https://merico.atlassian.net/rest [...]
+2,10088,2,10088,10003,https://merico.atlassian.net/rest/agile/1.0/issue/10088,EE-26,​定接口,子任务,,已完成,done,0,0,0,0,5e9711ba34f7b90c0fbc37d3,,Rankin Zheng,5ecfbd0a47d31e0c2a15fd87,,yuxiang,3,Medium,10063,EE-1,0,,2020-06-15T09:06:51.438+00:00,2020-06-12T00:41:01.683+00:00,2021-03-28T08:05:55.208+00:00,0,4825,0,子任务,DONE,2022-06-23T12:50:47.748+00:00,2022-06-23T12:50:47.748+00:00,"{""ConnectionId"":2,""BoardId"":8}",_raw_jira_api_issues,12459,,https://merico.atlassian.net/rest/api/2/universal_av [...]
+2,10089,2,10089,10003,https://merico.atlassian.net/rest/agile/1.0/issue/10089,EE-27,​提供后端接口,子任务,,已完成,done,0,660,660,660,5e9711ba34f7b90c0fbc37d3,,Rankin Zheng,5ecfbd0ba04d9c0c220c18d8,,yanghui,3,Medium,10063,EE-1,0,,2020-06-19T06:31:31.662+00:00,2020-06-12T00:41:16.622+00:00,2021-03-28T08:05:55.498+00:00,0,10430,0,子任务,DONE,2022-06-23T12:50:47.748+00:00,2022-06-23T12:50:47.748+00:00,"{""ConnectionId"":2,""BoardId"":8}",_raw_jira_api_issues,12460,,https://merico.atlassian.net/rest/api/2/un [...]
+2,10090,2,10090,10003,https://merico.atlassian.net/rest/agile/1.0/issue/10090,EE-28,​数据填充与联调,子任务,,已完成,done,0,360,360,360,5e9711ba34f7b90c0fbc37d3,,Rankin Zheng,5ecfbd0c730ec90c1999cadf,,Dingding Zhang,3,Medium,10063,EE-1,0,,2020-06-18T04:03:04.637+00:00,2020-06-12T00:41:36.317+00:00,2021-03-28T08:06:05.443+00:00,0,8841,0,子任务,DONE,2022-06-23T12:50:47.748+00:00,2022-06-23T12:50:47.748+00:00,"{""ConnectionId"":2,""BoardId"":8}",_raw_jira_api_issues,12461,,https://merico.atlassian.net/rest/a [...]
+2,10091,2,10091,10003,https://merico.atlassian.net/rest/agile/1.0/issue/10091,EE-29,​组件封装及Demo,子任务,,已完成,done,0,360,360,360,5e9711ba34f7b90c0fbc37d3,,Rankin Zheng,5ecfbd0c730ec90c1999cadf,,Dingding Zhang,3,Medium,10064,EE-2,0,,2020-06-18T04:03:30.760+00:00,2020-06-12T00:48:29.035+00:00,2021-03-28T08:05:55.731+00:00,0,8835,0,子任务,DONE,2022-06-23T12:50:47.748+00:00,2022-06-23T12:50:47.748+00:00,"{""ConnectionId"":2,""BoardId"":8}",_raw_jira_api_issues,12462,,https://merico.atlassian.net/rest [...]
+2,10092,2,10092,10003,https://merico.atlassian.net/rest/agile/1.0/issue/10092,EE-30,​定接口,子任务,,已完成,done,0,0,0,0,5e9711ba34f7b90c0fbc37d3,,Rankin Zheng,5ecfbd0a47d31e0c2a15fd87,,yuxiang,3,Medium,10064,EE-2,0,,2020-06-15T09:06:40.206+00:00,2020-06-12T00:48:39.803+00:00,2021-03-28T08:05:55.159+00:00,0,4818,0,子任务,DONE,2022-06-23T12:50:47.748+00:00,2022-06-23T12:50:47.748+00:00,"{""ConnectionId"":2,""BoardId"":8}",_raw_jira_api_issues,12463,,https://merico.atlassian.net/rest/api/2/universal_av [...]
+2,10093,2,10093,10003,https://merico.atlassian.net/rest/agile/1.0/issue/10093,EE-31,​后端接口,子任务,,已完成,done,0,120,120,120,5e9711ba34f7b90c0fbc37d3,,Rankin Zheng,5ecfbd0ba04d9c0c220c18d8,,yanghui,3,Medium,10064,EE-2,0,,2020-06-19T07:35:31.762+00:00,2020-06-12T00:48:46.751+00:00,2021-03-28T08:05:55.544+00:00,0,10486,0,子任务,DONE,2022-06-23T12:50:47.748+00:00,2022-06-23T12:50:47.748+00:00,"{""ConnectionId"":2,""BoardId"":8}",_raw_jira_api_issues,12464,,https://merico.atlassian.net/rest/api/2/univ [...]
+2,10094,2,10094,10003,https://merico.atlassian.net/rest/agile/1.0/issue/10094,EE-32,​数据填充与联调,子任务,,已完成,done,0,360,360,360,5e9711ba34f7b90c0fbc37d3,,Rankin Zheng,5ecfbd0c730ec90c1999cadf,,Dingding Zhang,3,Medium,10064,EE-2,0,,2020-06-18T04:03:48.818+00:00,2020-06-12T00:48:53.279+00:00,2021-03-28T08:05:55.592+00:00,0,8834,0,子任务,DONE,2022-06-23T12:50:47.748+00:00,2022-06-23T12:50:47.748+00:00,"{""ConnectionId"":2,""BoardId"":8}",_raw_jira_api_issues,12465,,https://merico.atlassian.net/rest/a [...]
+2,10095,2,10095,10003,https://merico.atlassian.net/rest/agile/1.0/issue/10095,EE-33,准备测试用例,子任务,,已完成,done,0,0,0,0,5e9711ba34f7b90c0fbc37d3,,Rankin Zheng,5ecfbd0984083c0c12e5af8f,,lin.hao,3,Medium,10063,EE-1,0,,2020-06-19T06:32:19.340+00:00,2020-06-12T00:50:45.674+00:00,2021-03-28T08:05:55.253+00:00,0,10421,0,子任务,DONE,2022-06-23T12:50:47.748+00:00,2022-06-23T12:50:47.748+00:00,"{""ConnectionId"":2,""BoardId"":8}",_raw_jira_api_issues,12466,,https://merico.atlassian.net/rest/api/2/universal [...]
+2,10096,2,10096,10003,https://merico.atlassian.net/rest/agile/1.0/issue/10096,EE-34,​ 组件封装及Demo,子任务,,已完成,done,0,240,360,360,5e9711ba34f7b90c0fbc37d3,,Rankin Zheng,5ecfbd0c730ec90c1999cadf,,Dingding Zhang,3,Medium,10065,EE-3,0,,2020-06-18T04:04:05.951+00:00,2020-06-12T00:51:57.807+00:00,2021-03-28T08:05:57.232+00:00,0,8832,0,子任务,DONE,2022-06-23T12:50:47.748+00:00,2022-06-23T12:50:47.748+00:00,"{""ConnectionId"":2,""BoardId"":8}",_raw_jira_api_issues,12467,,https://merico.atlassian.net/res [...]
+2,10097,2,10097,10003,https://merico.atlassian.net/rest/agile/1.0/issue/10097,EE-35,定接口,子任务,,已完成,done,0,0,120,120,5e9711ba34f7b90c0fbc37d3,,Rankin Zheng,5ecfbd0a47d31e0c2a15fd87,,yuxiang,3,Medium,10065,EE-3,0,,2020-06-15T09:06:30.942+00:00,2020-06-12T00:52:04.767+00:00,2021-03-28T08:05:55.353+00:00,0,4814,0,子任务,DONE,2022-06-23T12:50:47.748+00:00,2022-06-23T12:50:47.748+00:00,"{""ConnectionId"":2,""BoardId"":8}",_raw_jira_api_issues,12468,,https://merico.atlassian.net/rest/api/2/universal [...]
+2,10098,2,10098,10003,https://merico.atlassian.net/rest/agile/1.0/issue/10098,EE-36,后端接口,子任务,,已完成,done,0,120,120,120,5e9711ba34f7b90c0fbc37d3,,Rankin Zheng,5ecfbd0ba04d9c0c220c18d8,,yanghui,3,Medium,10065,EE-3,0,,2020-06-19T07:35:44.696+00:00,2020-06-12T00:52:12.678+00:00,2021-03-28T08:05:55.685+00:00,0,10483,0,子任务,DONE,2022-06-23T12:50:47.748+00:00,2022-06-23T12:50:47.748+00:00,"{""ConnectionId"":2,""BoardId"":8}",_raw_jira_api_issues,12469,,https://merico.atlassian.net/rest/api/2/unive [...]
+2,10099,2,10099,10003,https://merico.atlassian.net/rest/agile/1.0/issue/10099,EE-37,数据填充与联调 ,子任务,,已完成,done,0,0,0,0,5e9711ba34f7b90c0fbc37d3,,Rankin Zheng,5ecfbd0c730ec90c1999cadf,,Dingding Zhang,3,Medium,10065,EE-3,0,,2020-06-18T04:04:31.261+00:00,2020-06-12T00:52:23.456+00:00,2021-03-28T08:05:55.638+00:00,0,8832,0,子任务,DONE,2022-06-23T12:50:47.748+00:00,2022-06-23T12:50:47.748+00:00,"{""ConnectionId"":2,""BoardId"":8}",_raw_jira_api_issues,12470,,https://merico.atlassian.net/rest/api/2/u [...]
diff --git a/plugins/jira/e2e/snapshot_tables/_tool_jira_projects.csv b/plugins/jira/e2e/snapshot_tables/_tool_jira_projects.csv
new file mode 100644
index 00000000..c21bdfa5
--- /dev/null
+++ b/plugins/jira/e2e/snapshot_tables/_tool_jira_projects.csv
@@ -0,0 +1,13 @@
+connection_id,id,connection_id,id,project_key,name,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark
+2,10003,2,10003,EE,Enterprise Edition,"{""ConnectionId"":2,""BoardId"":8}",_raw_jira_api_projects,52,
+2,10007,2,10007,CC,Customer Center,"{""ConnectionId"":2,""BoardId"":8}",_raw_jira_api_projects,48,
+2,10008,2,10008,NX,Next,"{""ConnectionId"":2,""BoardId"":8}",_raw_jira_api_projects,55,
+2,10022,2,10022,ROAD,Roadmap,"{""ConnectionId"":2,""BoardId"":8}",_raw_jira_api_projects,58,
+2,10029,2,10029,MERICO,思码逸跨团队协作,"{""ConnectionId"":2,""BoardId"":8}",_raw_jira_api_projects,59,
+2,10030,2,10030,OR,OSS-Ranking,"{""ConnectionId"":2,""BoardId"":8}",_raw_jira_api_projects,56,
+2,10033,2,10033,DTM,DevStream,"{""ConnectionId"":2,""BoardId"":8}",_raw_jira_api_projects,50,
+2,10034,2,10034,HEAP,heapheap,"{""ConnectionId"":2,""BoardId"":8}",_raw_jira_api_projects,53,
+2,10037,2,10037,POTP,Product on Track Planning,"{""ConnectionId"":2,""BoardId"":8}",_raw_jira_api_projects,57,
+2,10038,2,10038,DET,dtm-e2e-test-do-not-delete,"{""ConnectionId"":2,""BoardId"":8}",_raw_jira_api_projects,51,
+2,10040,2,10040,HEP,HEP,"{""ConnectionId"":2,""BoardId"":8}",_raw_jira_api_projects,54,
+2,10041,2,10041,DEV,DevLake,"{""ConnectionId"":2,""BoardId"":8}",_raw_jira_api_projects,49,
diff --git a/plugins/jira/e2e/snapshot_tables/board_issues.csv b/plugins/jira/e2e/snapshot_tables/board_issues.csv
new file mode 100644
index 00000000..79e10b4b
--- /dev/null
+++ b/plugins/jira/e2e/snapshot_tables/board_issues.csv
@@ -0,0 +1,31 @@
+board_id,issue_id
+jira:JiraBoard:2:8,jira:JiraIssue:2:10063
+jira:JiraBoard:2:8,jira:JiraIssue:2:10064
+jira:JiraBoard:2:8,jira:JiraIssue:2:10065
+jira:JiraBoard:2:8,jira:JiraIssue:2:10066
+jira:JiraBoard:2:8,jira:JiraIssue:2:10067
+jira:JiraBoard:2:8,jira:JiraIssue:2:10068
+jira:JiraBoard:2:8,jira:JiraIssue:2:10070
+jira:JiraBoard:2:8,jira:JiraIssue:2:10071
+jira:JiraBoard:2:8,jira:JiraIssue:2:10072
+jira:JiraBoard:2:8,jira:JiraIssue:2:10076
+jira:JiraBoard:2:8,jira:JiraIssue:2:10077
+jira:JiraBoard:2:8,jira:JiraIssue:2:10078
+jira:JiraBoard:2:8,jira:JiraIssue:2:10079
+jira:JiraBoard:2:8,jira:JiraIssue:2:10081
+jira:JiraBoard:2:8,jira:JiraIssue:2:10082
+jira:JiraBoard:2:8,jira:JiraIssue:2:10085
+jira:JiraBoard:2:8,jira:JiraIssue:2:10086
+jira:JiraBoard:2:8,jira:JiraIssue:2:10087
+jira:JiraBoard:2:8,jira:JiraIssue:2:10088
+jira:JiraBoard:2:8,jira:JiraIssue:2:10089
+jira:JiraBoard:2:8,jira:JiraIssue:2:10090
+jira:JiraBoard:2:8,jira:JiraIssue:2:10091
+jira:JiraBoard:2:8,jira:JiraIssue:2:10092
+jira:JiraBoard:2:8,jira:JiraIssue:2:10093
+jira:JiraBoard:2:8,jira:JiraIssue:2:10094
+jira:JiraBoard:2:8,jira:JiraIssue:2:10095
+jira:JiraBoard:2:8,jira:JiraIssue:2:10096
+jira:JiraBoard:2:8,jira:JiraIssue:2:10097
+jira:JiraBoard:2:8,jira:JiraIssue:2:10098
+jira:JiraBoard:2:8,jira:JiraIssue:2:10099
diff --git a/plugins/jira/e2e/snapshot_tables/boards.csv b/plugins/jira/e2e/snapshot_tables/boards.csv
new file mode 100644
index 00000000..80891045
--- /dev/null
+++ b/plugins/jira/e2e/snapshot_tables/boards.csv
@@ -0,0 +1,2 @@
+id,id,name,description,url,created_date
+jira:JiraBoard:2:8,jira:JiraBoard:2:8,迭代开发看板(停用),,https://merico.atlassian.net/rest/agile/1.0/board/8,
diff --git a/plugins/jira/e2e/snapshot_tables/issues.csv b/plugins/jira/e2e/snapshot_tables/issues.csv
new file mode 100644
index 00000000..fc50b434
--- /dev/null
+++ b/plugins/jira/e2e/snapshot_tables/issues.csv
@@ -0,0 +1,31 @@
+id,url,icon_url,issue_key,title,description,epic_key,type,status,original_status,story_point,resolution_date,created_date,updated_date,lead_time_minutes,parent_issue_id,priority,original_estimate_minutes,time_spent_minutes,time_remaining_minutes,creator_id,creator_name,assignee_id,assignee_name,severity,component
+jira:JiraIssue:2:10063,https://merico.atlassian.net/browse/EE-1,https://merico.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10315?size=medium,EE-1,​四个排序图:测试/注释覆盖度、复用度、模块性,,,故事,DONE,已完成,0,2020-06-19T06:31:18.495+00:00,2020-06-12T00:13:13.360+00:00,2021-03-28T08:06:08.713+00:00,10458,,Medium,0,0,0,jira:JiraUser:2:5e9711ba34f7b90c0fbc37d3,Rankin Zheng,jira:JiraUser:2:5ecfbd0c730ec90c1999cadf,Dingding Zhang,,
+jira:JiraIssue:2:10064,https://merico.atlassian.net/browse/EE-2,https://merico.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10315?size=medium,EE-2,​问题堆叠分布排序图,,,故事,DONE,已完成,0,2020-06-23T10:20:58.999+00:00,2020-06-12T00:15:36.123+00:00,2021-03-28T08:05:55.016+00:00,16445,,Medium,0,0,0,jira:JiraUser:2:5e9711ba34f7b90c0fbc37d3,Rankin Zheng,jira:JiraUser:2:5ecfbd0c730ec90c1999cadf,Dingding Zhang,,
+jira:JiraIssue:2:10065,https://merico.atlassian.net/browse/EE-3,https://merico.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10315?size=medium,EE-3,​问题积压图率,,,故事,DONE,已完成,0,2020-06-23T10:21:11.996+00:00,2020-06-12T00:15:41.600+00:00,2021-03-28T08:05:55.061+00:00,16445,,Medium,0,0,0,jira:JiraUser:2:5e9711ba34f7b90c0fbc37d3,Rankin Zheng,jira:JiraUser:2:5ecfbd0c730ec90c1999cadf,Dingding Zhang,,
+jira:JiraIssue:2:10066,https://merico.atlassian.net/browse/EE-4,https://merico.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10315?size=medium,EE-4,​问题分布的帕累托图,,,故事,DONE,已完成,0,2020-06-23T10:21:23.562+00:00,2020-06-12T00:15:46.144+00:00,2021-03-28T08:06:09.535+00:00,16445,,Medium,0,0,0,jira:JiraUser:2:5e9711ba34f7b90c0fbc37d3,Rankin Zheng,jira:JiraUser:2:5ecfbd0c730ec90c1999cadf,Dingding Zhang,,
+jira:JiraIssue:2:10067,https://merico.atlassian.net/browse/EE-5,https://merico.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10318?size=medium,EE-5,​通用技术任务,,,任务,DONE,已完成,0,2020-06-18T04:06:00.747+00:00,2020-06-12T00:16:44.157+00:00,2021-03-28T08:05:54.622+00:00,8869,,Medium,0,0,0,jira:JiraUser:2:5e9711ba34f7b90c0fbc37d3,Rankin Zheng,jira:JiraUser:2:5ecfbd0c730ec90c1999cadf,Dingding Zhang,,
+jira:JiraIssue:2:10068,https://merico.atlassian.net/browse/EE-6,https://merico.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10315?size=medium,EE-6,​变异系数、生产率的四象限图,,,故事,DONE,已完成,0,2020-06-16T11:56:14.433+00:00,2020-06-12T00:17:26.986+00:00,2021-03-28T08:05:56.750+00:00,6458,,Medium,0,0,0,jira:JiraUser:2:5e9711ba34f7b90c0fbc37d3,Rankin Zheng,jira:JiraUser:2:5ecfbd0c2490cf0c09e2e598,Gerile Tu,,
+jira:JiraIssue:2:10070,https://merico.atlassian.net/browse/EE-8,https://merico.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10318?size=medium,EE-8,​多团队支持,,,任务,DONE,已完成,0,2020-07-08T17:11:45.201+00:00,2020-06-12T00:18:58.050+00:00,2021-03-28T08:05:54.576+00:00,38452,,Medium,0,0,0,jira:JiraUser:2:5e9711ba34f7b90c0fbc37d3,Rankin Zheng,jira:JiraUser:2:5ecfbd0ba04d9c0c220c18d8,yanghui,,
+jira:JiraIssue:2:10071,https://merico.atlassian.net/browse/EE-9,https://merico.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10318?size=medium,EE-9,Common backend 拆分,,,任务,DONE,已完成,0,2020-07-08T17:12:05.663+00:00,2020-06-12T00:19:17.336+00:00,2021-03-28T08:06:20.165+00:00,38452,,Medium,1680,0,0,jira:JiraUser:2:5e9711ba34f7b90c0fbc37d3,Rankin Zheng,jira:JiraUser:2:5ecfbd0ba04d9c0c220c18d8,yanghui,,
+jira:JiraIssue:2:10072,https://merico.atlassian.net/browse/EE-10,https://merico.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10318?size=medium,EE-10,​部署SaaS版本,,,任务,DONE,已完成,0,2020-07-08T17:11:55.247+00:00,2020-06-12T00:19:24.637+00:00,2021-03-28T08:05:54.472+00:00,38452,,Medium,0,0,0,jira:JiraUser:2:5e9711ba34f7b90c0fbc37d3,Rankin Zheng,jira:JiraUser:2:5ecfbd0ba04d9c0c220c18d8,yanghui,,
+jira:JiraIssue:2:10076,https://merico.atlassian.net/browse/EE-14,https://merico.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10318?size=medium,EE-14,调整​文件夹结构,,,任务,DONE,已完成,0,2020-06-15T08:59:51.304+00:00,2020-06-12T00:24:25.922+00:00,2021-03-28T08:05:56.152+00:00,4835,,Medium,240,600,0,jira:JiraUser:2:5e9711ba34f7b90c0fbc37d3,Rankin Zheng,jira:JiraUser:2:5ecfbd0a47d31e0c2a15fd87,yuxiang,,
+jira:JiraIssue:2:10077,https://merico.atlassian.net/browse/EE-15,https://merico.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10318?size=medium,EE-15,路由权限控制,,,任务,DONE,已完成,0,2020-06-15T09:00:26.956+00:00,2020-06-12T00:24:39.624+00:00,2021-03-28T08:06:01.995+00:00,4835,,Medium,240,480,0,jira:JiraUser:2:5e9711ba34f7b90c0fbc37d3,Rankin Zheng,jira:JiraUser:2:5ecfbd0a47d31e0c2a15fd87,yuxiang,,
+jira:JiraIssue:2:10078,https://merico.atlassian.net/browse/EE-16,https://merico.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10318?size=medium,EE-16,​优化前端 webpack 开发阶段构建速度,,,任务,DONE,已完成,0,2020-06-15T09:01:44.159+00:00,2020-06-12T00:24:49.017+00:00,2021-03-28T08:05:55.863+00:00,4836,,Medium,0,60,0,jira:JiraUser:2:5e9711ba34f7b90c0fbc37d3,Rankin Zheng,jira:JiraUser:2:5ecfbd0a47d31e0c2a15fd87,yuxiang,,
+jira:JiraIssue:2:10079,https://merico.atlassian.net/browse/EE-17,https://merico.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10318?size=medium,EE-17,​新的错误处理机制,,,任务,DONE,已完成,0,2020-07-22T07:25:29.104+00:00,2020-06-12T00:24:56.048+00:00,2021-03-28T08:05:54.426+00:00,58020,,Medium,360,120,0,jira:JiraUser:2:5e9711ba34f7b90c0fbc37d3,Rankin Zheng,jira:JiraUser:2:5ecfbd0a47d31e0c2a15fd87,yuxiang,,
+jira:JiraIssue:2:10081,https://merico.atlassian.net/browse/EE-19,https://merico.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10315?size=medium,EE-19,​LDAP需要支持TLS和证书,,,故事,DONE,已完成,0,2020-06-18T08:34:11.117+00:00,2020-06-12T00:28:00.241+00:00,2021-03-28T08:05:57.326+00:00,9126,,Medium,0,0,0,jira:JiraUser:2:5e9711ba34f7b90c0fbc37d3,Rankin Zheng,jira:JiraUser:2:5ecfbd0aaa47a00c1997ea8e,chao.cheng,,
+jira:JiraIssue:2:10082,https://merico.atlassian.net/browse/EE-20,https://merico.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10315?size=medium,EE-20,团队首页垂直化,,,故事,DONE,已完成,0,2020-06-17T07:25:54.370+00:00,2020-06-12T00:29:43.677+00:00,2021-08-06T06:14:54.647+00:00,7616,,Medium,0,0,0,jira:JiraUser:2:5e9711ba34f7b90c0fbc37d3,Rankin Zheng,jira:JiraUser:2:5ecfbd0984083c0c12e5af8f,lin.hao,,
+jira:JiraIssue:2:10085,https://merico.atlassian.net/browse/EE-23,https://merico.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10303?size=medium,EE-23,​批量删除事故,,,缺陷,DONE,已完成,0,2020-06-15T09:07:56.798+00:00,2020-06-12T00:33:57.204+00:00,2021-03-28T08:05:57.095+00:00,4833,,Medium,0,60,0,jira:JiraUser:2:5e9711ba34f7b90c0fbc37d3,Rankin Zheng,jira:JiraUser:2:5ecfbd0a47d31e0c2a15fd87,yuxiang,,
+jira:JiraIssue:2:10086,https://merico.atlassian.net/browse/EE-24,https://merico.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10315?size=medium,EE-24,​LDAP支持自定义的证书上传,,,故事,DONE,已完成,0,2020-06-12T07:17:28.659+00:00,2020-06-12T00:35:15.489+00:00,2021-03-28T08:05:55.819+00:00,402,,Medium,0,0,0,jira:JiraUser:2:5e9711ba34f7b90c0fbc37d3,Rankin Zheng,jira:JiraUser:2:5ecfbd0aaa47a00c1997ea8e,chao.cheng,,
+jira:JiraIssue:2:10087,https://merico.atlassian.net/browse/EE-25,https://merico.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10316?size=medium,EE-25,​组件封装及Demo,,,子任务,DONE,已完成,0,2020-06-18T04:02:22.350+00:00,2020-06-12T00:40:54.210+00:00,2021-03-28T08:05:57.189+00:00,8841,jira:JiraIssue:2:10063,Medium,240,0,0,jira:JiraUser:2:5e9711ba34f7b90c0fbc37d3,Rankin Zheng,jira:JiraUser:2:5ecfbd0c730ec90c1999cadf,Dingding Zhang,,
+jira:JiraIssue:2:10088,https://merico.atlassian.net/browse/EE-26,https://merico.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10316?size=medium,EE-26,​定接口,,,子任务,DONE,已完成,0,2020-06-15T09:06:51.438+00:00,2020-06-12T00:41:01.683+00:00,2021-03-28T08:05:55.208+00:00,4825,jira:JiraIssue:2:10063,Medium,0,0,0,jira:JiraUser:2:5e9711ba34f7b90c0fbc37d3,Rankin Zheng,jira:JiraUser:2:5ecfbd0a47d31e0c2a15fd87,yuxiang,,
+jira:JiraIssue:2:10089,https://merico.atlassian.net/browse/EE-27,https://merico.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10316?size=medium,EE-27,​提供后端接口,,,子任务,DONE,已完成,0,2020-06-19T06:31:31.662+00:00,2020-06-12T00:41:16.622+00:00,2021-03-28T08:05:55.498+00:00,10430,jira:JiraIssue:2:10063,Medium,660,0,0,jira:JiraUser:2:5e9711ba34f7b90c0fbc37d3,Rankin Zheng,jira:JiraUser:2:5ecfbd0ba04d9c0c220c18d8,yanghui,,
+jira:JiraIssue:2:10090,https://merico.atlassian.net/browse/EE-28,https://merico.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10316?size=medium,EE-28,​数据填充与联调,,,子任务,DONE,已完成,0,2020-06-18T04:03:04.637+00:00,2020-06-12T00:41:36.317+00:00,2021-03-28T08:06:05.443+00:00,8841,jira:JiraIssue:2:10063,Medium,360,0,0,jira:JiraUser:2:5e9711ba34f7b90c0fbc37d3,Rankin Zheng,jira:JiraUser:2:5ecfbd0c730ec90c1999cadf,Dingding Zhang,,
+jira:JiraIssue:2:10091,https://merico.atlassian.net/browse/EE-29,https://merico.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10316?size=medium,EE-29,​组件封装及Demo,,,子任务,DONE,已完成,0,2020-06-18T04:03:30.760+00:00,2020-06-12T00:48:29.035+00:00,2021-03-28T08:05:55.731+00:00,8835,jira:JiraIssue:2:10064,Medium,360,0,0,jira:JiraUser:2:5e9711ba34f7b90c0fbc37d3,Rankin Zheng,jira:JiraUser:2:5ecfbd0c730ec90c1999cadf,Dingding Zhang,,
+jira:JiraIssue:2:10092,https://merico.atlassian.net/browse/EE-30,https://merico.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10316?size=medium,EE-30,​定接口,,,子任务,DONE,已完成,0,2020-06-15T09:06:40.206+00:00,2020-06-12T00:48:39.803+00:00,2021-03-28T08:05:55.159+00:00,4818,jira:JiraIssue:2:10064,Medium,0,0,0,jira:JiraUser:2:5e9711ba34f7b90c0fbc37d3,Rankin Zheng,jira:JiraUser:2:5ecfbd0a47d31e0c2a15fd87,yuxiang,,
+jira:JiraIssue:2:10093,https://merico.atlassian.net/browse/EE-31,https://merico.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10316?size=medium,EE-31,​后端接口,,,子任务,DONE,已完成,0,2020-06-19T07:35:31.762+00:00,2020-06-12T00:48:46.751+00:00,2021-03-28T08:05:55.544+00:00,10486,jira:JiraIssue:2:10064,Medium,120,0,0,jira:JiraUser:2:5e9711ba34f7b90c0fbc37d3,Rankin Zheng,jira:JiraUser:2:5ecfbd0ba04d9c0c220c18d8,yanghui,,
+jira:JiraIssue:2:10094,https://merico.atlassian.net/browse/EE-32,https://merico.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10316?size=medium,EE-32,​数据填充与联调,,,子任务,DONE,已完成,0,2020-06-18T04:03:48.818+00:00,2020-06-12T00:48:53.279+00:00,2021-03-28T08:05:55.592+00:00,8834,jira:JiraIssue:2:10064,Medium,360,0,0,jira:JiraUser:2:5e9711ba34f7b90c0fbc37d3,Rankin Zheng,jira:JiraUser:2:5ecfbd0c730ec90c1999cadf,Dingding Zhang,,
+jira:JiraIssue:2:10095,https://merico.atlassian.net/browse/EE-33,https://merico.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10316?size=medium,EE-33,准备测试用例,,,子任务,DONE,已完成,0,2020-06-19T06:32:19.340+00:00,2020-06-12T00:50:45.674+00:00,2021-03-28T08:05:55.253+00:00,10421,jira:JiraIssue:2:10063,Medium,0,0,0,jira:JiraUser:2:5e9711ba34f7b90c0fbc37d3,Rankin Zheng,jira:JiraUser:2:5ecfbd0984083c0c12e5af8f,lin.hao,,
+jira:JiraIssue:2:10096,https://merico.atlassian.net/browse/EE-34,https://merico.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10316?size=medium,EE-34,​ 组件封装及Demo,,,子任务,DONE,已完成,0,2020-06-18T04:04:05.951+00:00,2020-06-12T00:51:57.807+00:00,2021-03-28T08:05:57.232+00:00,8832,jira:JiraIssue:2:10065,Medium,240,0,0,jira:JiraUser:2:5e9711ba34f7b90c0fbc37d3,Rankin Zheng,jira:JiraUser:2:5ecfbd0c730ec90c1999cadf,Dingding Zhang,,
+jira:JiraIssue:2:10097,https://merico.atlassian.net/browse/EE-35,https://merico.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10316?size=medium,EE-35,定接口,,,子任务,DONE,已完成,0,2020-06-15T09:06:30.942+00:00,2020-06-12T00:52:04.767+00:00,2021-03-28T08:05:55.353+00:00,4814,jira:JiraIssue:2:10065,Medium,0,0,0,jira:JiraUser:2:5e9711ba34f7b90c0fbc37d3,Rankin Zheng,jira:JiraUser:2:5ecfbd0a47d31e0c2a15fd87,yuxiang,,
+jira:JiraIssue:2:10098,https://merico.atlassian.net/browse/EE-36,https://merico.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10316?size=medium,EE-36,后端接口,,,子任务,DONE,已完成,0,2020-06-19T07:35:44.696+00:00,2020-06-12T00:52:12.678+00:00,2021-03-28T08:05:55.685+00:00,10483,jira:JiraIssue:2:10065,Medium,120,0,0,jira:JiraUser:2:5e9711ba34f7b90c0fbc37d3,Rankin Zheng,jira:JiraUser:2:5ecfbd0ba04d9c0c220c18d8,yanghui,,
+jira:JiraIssue:2:10099,https://merico.atlassian.net/browse/EE-37,https://merico.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10316?size=medium,EE-37,数据填充与联调 ,,,子任务,DONE,已完成,0,2020-06-18T04:04:31.261+00:00,2020-06-12T00:52:23.456+00:00,2021-03-28T08:05:55.638+00:00,8832,jira:JiraIssue:2:10065,Medium,0,0,0,jira:JiraUser:2:5e9711ba34f7b90c0fbc37d3,Rankin Zheng,jira:JiraUser:2:5ecfbd0c730ec90c1999cadf,Dingding Zhang,,
diff --git a/plugins/jira/jira.go b/plugins/jira/impl/impl.go
similarity index 52%
copy from plugins/jira/jira.go
copy to plugins/jira/impl/impl.go
index 97abb9d8..582b29a8 100644
--- a/plugins/jira/jira.go
+++ b/plugins/jira/impl/impl.go
@@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-package main // must be main for plugin entry point
+package impl
 
 import (
 	"fmt"
@@ -29,9 +29,7 @@ import (
 	"github.com/apache/incubator-devlake/plugins/jira/models"
 	"github.com/apache/incubator-devlake/plugins/jira/models/migrationscripts"
 	"github.com/apache/incubator-devlake/plugins/jira/tasks"
-	"github.com/apache/incubator-devlake/runner"
 	"github.com/mitchellh/mapstructure"
-	"github.com/spf13/cobra"
 	"github.com/spf13/viper"
 	"gorm.io/gorm"
 )
@@ -55,48 +53,48 @@ func (plugin Jira) Description() string {
 
 func (plugin Jira) SubTaskMetas() []core.SubTaskMeta {
 	return []core.SubTaskMeta{
-		{Name: "collectStatus", EntryPoint: tasks.CollectStatus, EnabledByDefault: true, Description: "collect Jira status"},
-		{Name: "extractStatus", EntryPoint: tasks.ExtractStatus, EnabledByDefault: true, Description: "extract Jira status"},
+		tasks.CollectStatusMeta,
+		tasks.ExtractStatusMeta,
 
-		{Name: "collectProjects", EntryPoint: tasks.CollectProjects, EnabledByDefault: true, Description: "collect Jira projects"},
-		{Name: "extractProjects", EntryPoint: tasks.ExtractProjects, EnabledByDefault: true, Description: "extract Jira projects"},
+		tasks.CollectProjectsMeta,
+		tasks.ExtractProjectsMeta,
 
-		{Name: "collectBoard", EntryPoint: tasks.CollectBoard, EnabledByDefault: true, Description: "collect Jira board"},
-		{Name: "extractBoard", EntryPoint: tasks.ExtractBoard, EnabledByDefault: true, Description: "extract Jira board"},
+		tasks.CollectBoardMeta,
+		tasks.ExtractBoardMeta,
 
-		{Name: "collectIssues", EntryPoint: tasks.CollectIssues, EnabledByDefault: true, Description: "collect Jira issues"},
-		{Name: "extractIssues", EntryPoint: tasks.ExtractIssues, EnabledByDefault: true, Description: "extract Jira issues"},
+		tasks.CollectIssuesMeta,
+		tasks.ExtractIssuesMeta,
 
-		{Name: "collectChangelogs", EntryPoint: tasks.CollectChangelogs, EnabledByDefault: true, Description: "collect Jira change logs"},
-		{Name: "extractChangelogs", EntryPoint: tasks.ExtractChangelogs, EnabledByDefault: true, Description: "extract Jira change logs"},
+		tasks.CollectChangelogsMeta,
+		tasks.ExtractChangelogsMeta,
 
-		{Name: "collectUsers", EntryPoint: tasks.CollectUsers, EnabledByDefault: true, Description: "collect Jira users"},
+		tasks.CollectUsersMeta,
 
-		{Name: "collectWorklogs", EntryPoint: tasks.CollectWorklogs, EnabledByDefault: true, Description: "collect Jira work logs"},
-		{Name: "extractWorklogs", EntryPoint: tasks.ExtractWorklogs, EnabledByDefault: true, Description: "extract Jira work logs"},
+		tasks.CollectWorklogsMeta,
+		tasks.ExtractWorklogsMeta,
 
-		{Name: "collectRemotelinks", EntryPoint: tasks.CollectRemotelinks, EnabledByDefault: true, Description: "collect Jira remote links"},
-		{Name: "extractRemotelinks", EntryPoint: tasks.ExtractRemotelinks, EnabledByDefault: true, Description: "extract Jira remote links"},
+		tasks.CollectRemotelinksMeta,
+		tasks.ExtractRemotelinksMeta,
 
-		{Name: "collectSprints", EntryPoint: tasks.CollectSprints, EnabledByDefault: true, Description: "collect Jira sprints"},
-		{Name: "extractSprints", EntryPoint: tasks.ExtractSprints, EnabledByDefault: true, Description: "extract Jira sprints"},
+		tasks.CollectSprintsMeta,
+		tasks.ExtractSprintsMeta,
 
-		{Name: "convertBoard", EntryPoint: tasks.ConvertBoard, EnabledByDefault: true, Description: "convert Jira board"},
+		tasks.ConvertBoardMeta,
 
-		{Name: "convertIssues", EntryPoint: tasks.ConvertIssues, EnabledByDefault: true, Description: "convert Jira issues"},
+		tasks.ConvertIssuesMeta,
 
-		{Name: "convertWorklogs", EntryPoint: tasks.ConvertWorklogs, EnabledByDefault: true, Description: "convert Jira work logs"},
+		tasks.ConvertWorklogsMeta,
 
-		{Name: "convertChangelogs", EntryPoint: tasks.ConvertChangelogs, EnabledByDefault: true, Description: "convert Jira change logs"},
+		tasks.ConvertChangelogsMeta,
 
-		{Name: "convertSprints", EntryPoint: tasks.ConvertSprints, EnabledByDefault: true, Description: "convert Jira sprints"},
-		{Name: "convertSprintIssues", EntryPoint: tasks.ConvertSprintIssues, EnabledByDefault: true, Description: "convert Jira sprint_issues"},
+		tasks.ConvertSprintsMeta,
+		tasks.ConvertSprintIssuesMeta,
 
-		{Name: "convertIssueCommits", EntryPoint: tasks.ConvertIssueCommits, EnabledByDefault: true, Description: "convert Jira issue commits"},
-		{Name: "convertIssueRepoCommits", EntryPoint: tasks.ConvertIssueRepoCommits, EnabledByDefault: false, Description: "convert Jira issue repo commits"},
+		tasks.ConvertIssueCommitsMeta,
+		tasks.ConvertIssueRepoCommitsMeta,
 
-		{Name: "extractUsers", EntryPoint: tasks.ExtractUsers, EnabledByDefault: true, Description: "extract Jira users"},
-		{Name: "convertUsers", EntryPoint: tasks.ConvertUsers, EnabledByDefault: true, Description: "convert Jira users"},
+		tasks.ExtractUsersMeta,
+		tasks.ConvertUsersMeta,
 	}
 }
 
@@ -198,24 +196,3 @@ func (plugin Jira) ApiResources() map[string]map[string]core.ApiResourceHandler
 		},
 	}
 }
-
-// Export a variable named PluginEntry for Framework to search and load
-var PluginEntry Jira //nolint
-
-// standalone mode for debugging
-func main() {
-	cmd := &cobra.Command{Use: "jira"}
-	connectionId := cmd.Flags().Uint64P("connection", "c", 0, "jira connection id")
-	boardId := cmd.Flags().Uint64P("board", "b", 0, "jira board id")
-	_ = cmd.MarkFlagRequired("connection")
-	_ = cmd.MarkFlagRequired("board")
-	since := cmd.Flags().StringP("since", "s", "", "collect data that are updated after specified time, ie 2006-05-06T07:08:09Z")
-	cmd.Run = func(c *cobra.Command, args []string) {
-		runner.DirectRun(c, args, PluginEntry, map[string]interface{}{
-			"connectionId": *connectionId,
-			"boardId":      *boardId,
-			"since":        *since,
-		})
-	}
-	runner.RunCmd(cmd)
-}
diff --git a/plugins/jira/jira.go b/plugins/jira/jira.go
index 97abb9d8..0cf85de0 100644
--- a/plugins/jira/jira.go
+++ b/plugins/jira/jira.go
@@ -18,189 +18,12 @@ limitations under the License.
 package main // must be main for plugin entry point
 
 import (
-	"fmt"
-	"net/http"
-	"time"
-
-	"github.com/apache/incubator-devlake/migration"
-	"github.com/apache/incubator-devlake/plugins/core"
-	"github.com/apache/incubator-devlake/plugins/helper"
-	"github.com/apache/incubator-devlake/plugins/jira/api"
-	"github.com/apache/incubator-devlake/plugins/jira/models"
-	"github.com/apache/incubator-devlake/plugins/jira/models/migrationscripts"
-	"github.com/apache/incubator-devlake/plugins/jira/tasks"
+	"github.com/apache/incubator-devlake/plugins/jira/impl"
 	"github.com/apache/incubator-devlake/runner"
-	"github.com/mitchellh/mapstructure"
 	"github.com/spf13/cobra"
-	"github.com/spf13/viper"
-	"gorm.io/gorm"
 )
 
-var _ core.PluginMeta = (*Jira)(nil)
-var _ core.PluginInit = (*Jira)(nil)
-var _ core.PluginTask = (*Jira)(nil)
-var _ core.PluginApi = (*Jira)(nil)
-var _ core.Migratable = (*Jira)(nil)
-
-type Jira struct{}
-
-func (plugin Jira) Init(config *viper.Viper, logger core.Logger, db *gorm.DB) error {
-	api.Init(config, logger, db)
-	return nil
-}
-
-func (plugin Jira) Description() string {
-	return "To collect and enrich data from JIRA"
-}
-
-func (plugin Jira) SubTaskMetas() []core.SubTaskMeta {
-	return []core.SubTaskMeta{
-		{Name: "collectStatus", EntryPoint: tasks.CollectStatus, EnabledByDefault: true, Description: "collect Jira status"},
-		{Name: "extractStatus", EntryPoint: tasks.ExtractStatus, EnabledByDefault: true, Description: "extract Jira status"},
-
-		{Name: "collectProjects", EntryPoint: tasks.CollectProjects, EnabledByDefault: true, Description: "collect Jira projects"},
-		{Name: "extractProjects", EntryPoint: tasks.ExtractProjects, EnabledByDefault: true, Description: "extract Jira projects"},
-
-		{Name: "collectBoard", EntryPoint: tasks.CollectBoard, EnabledByDefault: true, Description: "collect Jira board"},
-		{Name: "extractBoard", EntryPoint: tasks.ExtractBoard, EnabledByDefault: true, Description: "extract Jira board"},
-
-		{Name: "collectIssues", EntryPoint: tasks.CollectIssues, EnabledByDefault: true, Description: "collect Jira issues"},
-		{Name: "extractIssues", EntryPoint: tasks.ExtractIssues, EnabledByDefault: true, Description: "extract Jira issues"},
-
-		{Name: "collectChangelogs", EntryPoint: tasks.CollectChangelogs, EnabledByDefault: true, Description: "collect Jira change logs"},
-		{Name: "extractChangelogs", EntryPoint: tasks.ExtractChangelogs, EnabledByDefault: true, Description: "extract Jira change logs"},
-
-		{Name: "collectUsers", EntryPoint: tasks.CollectUsers, EnabledByDefault: true, Description: "collect Jira users"},
-
-		{Name: "collectWorklogs", EntryPoint: tasks.CollectWorklogs, EnabledByDefault: true, Description: "collect Jira work logs"},
-		{Name: "extractWorklogs", EntryPoint: tasks.ExtractWorklogs, EnabledByDefault: true, Description: "extract Jira work logs"},
-
-		{Name: "collectRemotelinks", EntryPoint: tasks.CollectRemotelinks, EnabledByDefault: true, Description: "collect Jira remote links"},
-		{Name: "extractRemotelinks", EntryPoint: tasks.ExtractRemotelinks, EnabledByDefault: true, Description: "extract Jira remote links"},
-
-		{Name: "collectSprints", EntryPoint: tasks.CollectSprints, EnabledByDefault: true, Description: "collect Jira sprints"},
-		{Name: "extractSprints", EntryPoint: tasks.ExtractSprints, EnabledByDefault: true, Description: "extract Jira sprints"},
-
-		{Name: "convertBoard", EntryPoint: tasks.ConvertBoard, EnabledByDefault: true, Description: "convert Jira board"},
-
-		{Name: "convertIssues", EntryPoint: tasks.ConvertIssues, EnabledByDefault: true, Description: "convert Jira issues"},
-
-		{Name: "convertWorklogs", EntryPoint: tasks.ConvertWorklogs, EnabledByDefault: true, Description: "convert Jira work logs"},
-
-		{Name: "convertChangelogs", EntryPoint: tasks.ConvertChangelogs, EnabledByDefault: true, Description: "convert Jira change logs"},
-
-		{Name: "convertSprints", EntryPoint: tasks.ConvertSprints, EnabledByDefault: true, Description: "convert Jira sprints"},
-		{Name: "convertSprintIssues", EntryPoint: tasks.ConvertSprintIssues, EnabledByDefault: true, Description: "convert Jira sprint_issues"},
-
-		{Name: "convertIssueCommits", EntryPoint: tasks.ConvertIssueCommits, EnabledByDefault: true, Description: "convert Jira issue commits"},
-		{Name: "convertIssueRepoCommits", EntryPoint: tasks.ConvertIssueRepoCommits, EnabledByDefault: false, Description: "convert Jira issue repo commits"},
-
-		{Name: "extractUsers", EntryPoint: tasks.ExtractUsers, EnabledByDefault: true, Description: "extract Jira users"},
-		{Name: "convertUsers", EntryPoint: tasks.ConvertUsers, EnabledByDefault: true, Description: "convert Jira users"},
-	}
-}
-
-func (plugin Jira) PrepareTaskData(taskCtx core.TaskContext, options map[string]interface{}) (interface{}, error) {
-	var op tasks.JiraOptions
-	var err error
-	logger := taskCtx.GetLogger()
-	logger.Debug("%v", options)
-	err = mapstructure.Decode(options, &op)
-	if err != nil {
-		return nil, err
-	}
-	if op.ConnectionId == 0 {
-		return nil, fmt.Errorf("connectionId is invalid")
-	}
-	connection := &models.JiraConnection{}
-	connectionHelper := helper.NewConnectionHelper(
-		taskCtx,
-		nil,
-	)
-	if err != nil {
-		return nil, err
-	}
-	err = connectionHelper.FirstById(connection, op.ConnectionId)
-	if err != nil {
-		return nil, err
-	}
-
-	var since time.Time
-	if op.Since != "" {
-		since, err = time.Parse("2006-01-02T15:04:05Z", op.Since)
-		if err != nil {
-			return nil, fmt.Errorf("invalid value for `since`: %w", err)
-		}
-	}
-	jiraApiClient, err := tasks.NewJiraApiClient(taskCtx, connection)
-	if err != nil {
-		return nil, fmt.Errorf("failed to create jira api client: %w", err)
-	}
-	info, code, err := tasks.GetJiraServerInfo(jiraApiClient)
-	if err != nil || code != http.StatusOK || info == nil {
-		return nil, fmt.Errorf("fail to get server info: error:[%s] code:[%d]", err, code)
-	}
-	taskData := &tasks.JiraTaskData{
-		Options:        &op,
-		ApiClient:      jiraApiClient,
-		Connection:     connection,
-		JiraServerInfo: *info,
-	}
-	if !since.IsZero() {
-		taskData.Since = &since
-		logger.Debug("collect data updated since %s", since)
-	}
-	return taskData, nil
-}
-
-func (plugin Jira) RootPkgPath() string {
-	return "github.com/apache/incubator-devlake/plugins/jira"
-}
-
-func (plugin Jira) MigrationScripts() []migration.Script {
-	return []migration.Script{
-		new(migrationscripts.InitSchemas),
-		new(migrationscripts.UpdateSchemas20220505),
-		new(migrationscripts.UpdateSchemas20220507),
-		new(migrationscripts.UpdateSchemas20220518),
-		new(migrationscripts.UpdateSchemas20220525),
-		new(migrationscripts.UpdateSchemas20220526),
-		new(migrationscripts.UpdateSchemas20220527),
-		new(migrationscripts.UpdateSchemas20220601),
-		new(migrationscripts.UpdateSchemas20220614),
-		new(migrationscripts.UpdateSchemas20220615),
-		new(migrationscripts.UpdateSchemas20220616),
-		new(migrationscripts.UpdateSchemas20220620),
-	}
-}
-
-func (plugin Jira) ApiResources() map[string]map[string]core.ApiResourceHandler {
-	return map[string]map[string]core.ApiResourceHandler{
-		"test": {
-			"POST": api.TestConnection,
-		},
-		"echo": {
-			"POST": func(input *core.ApiResourceInput) (*core.ApiResourceOutput, error) {
-				return &core.ApiResourceOutput{Body: input.Body}, nil
-			},
-		},
-		"connections": {
-			"POST": api.PostConnections,
-			"GET":  api.ListConnections,
-		},
-		"connections/:connectionId": {
-			"PATCH":  api.PatchConnection,
-			"DELETE": api.DeleteConnection,
-			"GET":    api.GetConnection,
-		},
-		"connections/:connectionId/proxy/rest/*path": {
-			"GET": api.Proxy,
-		},
-	}
-}
-
-// Export a variable named PluginEntry for Framework to search and load
-var PluginEntry Jira //nolint
+var PluginEntry impl.Jira //nolint
 
 // standalone mode for debugging
 func main() {
diff --git a/plugins/jira/tasks/board_collector.go b/plugins/jira/tasks/board_collector.go
index e2622bf2..2642a43f 100644
--- a/plugins/jira/tasks/board_collector.go
+++ b/plugins/jira/tasks/board_collector.go
@@ -30,6 +30,13 @@ const RAW_BOARD_TABLE = "jira_api_boards"
 
 var _ core.SubTaskEntryPoint = CollectBoard
 
+var CollectBoardMeta = core.SubTaskMeta{
+	Name:             "collectBoard",
+	EntryPoint:       CollectBoard,
+	EnabledByDefault: true,
+	Description:      "collect Jira board",
+}
+
 func CollectBoard(taskCtx core.SubTaskContext) error {
 	data := taskCtx.GetData().(*JiraTaskData)
 	logger := taskCtx.GetLogger()
diff --git a/plugins/jira/tasks/board_convertor.go b/plugins/jira/tasks/board_convertor.go
index e1d05e9f..1fccfd09 100644
--- a/plugins/jira/tasks/board_convertor.go
+++ b/plugins/jira/tasks/board_convertor.go
@@ -29,6 +29,13 @@ import (
 	"github.com/apache/incubator-devlake/plugins/jira/models"
 )
 
+var ConvertBoardMeta = core.SubTaskMeta{
+	Name:             "convertBoard",
+	EntryPoint:       ConvertBoard,
+	EnabledByDefault: true,
+	Description:      "convert Jira board",
+}
+
 func ConvertBoard(taskCtx core.SubTaskContext) error {
 	data := taskCtx.GetData().(*JiraTaskData)
 	logger := taskCtx.GetLogger()
diff --git a/plugins/jira/tasks/board_extractor.go b/plugins/jira/tasks/board_extractor.go
index bb0344f2..cf00fec2 100644
--- a/plugins/jira/tasks/board_extractor.go
+++ b/plugins/jira/tasks/board_extractor.go
@@ -27,6 +27,12 @@ import (
 
 var _ core.SubTaskEntryPoint = ExtractBoard
 
+var ExtractBoardMeta = core.SubTaskMeta{Name: "extractBoard",
+	EntryPoint:       ExtractBoard,
+	EnabledByDefault: true,
+	Description:      "extract Jira board",
+}
+
 func ExtractBoard(taskCtx core.SubTaskContext) error {
 	data := taskCtx.GetData().(*JiraTaskData)
 
diff --git a/plugins/jira/tasks/changelog_collector.go b/plugins/jira/tasks/changelog_collector.go
index d10d7908..09a9175a 100644
--- a/plugins/jira/tasks/changelog_collector.go
+++ b/plugins/jira/tasks/changelog_collector.go
@@ -35,6 +35,13 @@ var _ core.SubTaskEntryPoint = CollectChangelogs
 
 const RAW_CHANGELOG_TABLE = "jira_api_changelogs"
 
+var CollectChangelogsMeta = core.SubTaskMeta{
+	Name:             "collectChangelogs",
+	EntryPoint:       CollectChangelogs,
+	EnabledByDefault: true,
+	Description:      "collect Jira change logs",
+}
+
 func CollectChangelogs(taskCtx core.SubTaskContext) error {
 	data := taskCtx.GetData().(*JiraTaskData)
 	if data.JiraServerInfo.DeploymentType == models.DeploymentServer {
diff --git a/plugins/jira/tasks/changelog_convertor.go b/plugins/jira/tasks/changelog_convertor.go
index 44c5171f..4b6fae3b 100644
--- a/plugins/jira/tasks/changelog_convertor.go
+++ b/plugins/jira/tasks/changelog_convertor.go
@@ -32,6 +32,13 @@ import (
 	"github.com/apache/incubator-devlake/plugins/jira/models"
 )
 
+var ConvertChangelogsMeta = core.SubTaskMeta{
+	Name:             "convertChangelogs",
+	EntryPoint:       ConvertChangelogs,
+	EnabledByDefault: true,
+	Description:      "convert Jira change logs",
+}
+
 type ChangelogItemResult struct {
 	models.JiraChangelogItem
 	IssueId           uint64 `gorm:"index"`
diff --git a/plugins/jira/tasks/changelog_extractor.go b/plugins/jira/tasks/changelog_extractor.go
index 19de1041..f15c9be3 100644
--- a/plugins/jira/tasks/changelog_extractor.go
+++ b/plugins/jira/tasks/changelog_extractor.go
@@ -28,6 +28,13 @@ import (
 
 var _ core.SubTaskEntryPoint = ExtractChangelogs
 
+var ExtractChangelogsMeta = core.SubTaskMeta{
+	Name:             "extractChangelogs",
+	EntryPoint:       ExtractChangelogs,
+	EnabledByDefault: true,
+	Description:      "extract Jira change logs",
+}
+
 func ExtractChangelogs(taskCtx core.SubTaskContext) error {
 	data := taskCtx.GetData().(*JiraTaskData)
 	if data.JiraServerInfo.DeploymentType == models.DeploymentServer {
diff --git a/plugins/jira/tasks/issue_collector.go b/plugins/jira/tasks/issue_collector.go
index e9d23c05..5b64d138 100644
--- a/plugins/jira/tasks/issue_collector.go
+++ b/plugins/jira/tasks/issue_collector.go
@@ -41,6 +41,13 @@ type JiraApiParams struct {
 
 var _ core.SubTaskEntryPoint = CollectIssues
 
+var CollectIssuesMeta = core.SubTaskMeta{
+	Name:             "collectIssues",
+	EntryPoint:       CollectIssues,
+	EnabledByDefault: true,
+	Description:      "collect Jira issues",
+}
+
 func CollectIssues(taskCtx core.SubTaskContext) error {
 	db := taskCtx.GetDal()
 	data := taskCtx.GetData().(*JiraTaskData)
diff --git a/plugins/jira/tasks/issue_commit_convertor.go b/plugins/jira/tasks/issue_commit_convertor.go
index de4e0030..c228859b 100644
--- a/plugins/jira/tasks/issue_commit_convertor.go
+++ b/plugins/jira/tasks/issue_commit_convertor.go
@@ -28,6 +28,13 @@ import (
 	"github.com/apache/incubator-devlake/plugins/jira/models"
 )
 
+var ConvertIssueCommitsMeta = core.SubTaskMeta{
+	Name:             "convertIssueCommits",
+	EntryPoint:       ConvertIssueCommits,
+	EnabledByDefault: true,
+	Description:      "convert Jira issue commits",
+}
+
 func ConvertIssueCommits(taskCtx core.SubTaskContext) error {
 	data := taskCtx.GetData().(*JiraTaskData)
 	db := taskCtx.GetDal()
diff --git a/plugins/jira/tasks/issue_convertor.go b/plugins/jira/tasks/issue_convertor.go
index b7df9133..22a55dcf 100644
--- a/plugins/jira/tasks/issue_convertor.go
+++ b/plugins/jira/tasks/issue_convertor.go
@@ -31,6 +31,13 @@ import (
 	jiraModels "github.com/apache/incubator-devlake/plugins/jira/models"
 )
 
+var ConvertIssuesMeta = core.SubTaskMeta{
+	Name:             "convertIssues",
+	EntryPoint:       ConvertIssues,
+	EnabledByDefault: true,
+	Description:      "convert Jira issues",
+}
+
 func ConvertIssues(taskCtx core.SubTaskContext) error {
 	db := taskCtx.GetDal()
 	data := taskCtx.GetData().(*JiraTaskData)
diff --git a/plugins/jira/tasks/issue_extractor.go b/plugins/jira/tasks/issue_extractor.go
index b86c3946..84cf2abb 100644
--- a/plugins/jira/tasks/issue_extractor.go
+++ b/plugins/jira/tasks/issue_extractor.go
@@ -31,6 +31,13 @@ import (
 
 var _ core.SubTaskEntryPoint = ExtractIssues
 
+var ExtractIssuesMeta = core.SubTaskMeta{
+	Name:             "extractIssues",
+	EntryPoint:       ExtractIssues,
+	EnabledByDefault: true,
+	Description:      "extract Jira issues",
+}
+
 func ExtractIssues(taskCtx core.SubTaskContext) error {
 	data := taskCtx.GetData().(*JiraTaskData)
 	connectionId := data.Options.ConnectionId
diff --git a/plugins/jira/tasks/issue_repo_commit_convertor.go b/plugins/jira/tasks/issue_repo_commit_convertor.go
index 2d47f42e..7de02746 100644
--- a/plugins/jira/tasks/issue_repo_commit_convertor.go
+++ b/plugins/jira/tasks/issue_repo_commit_convertor.go
@@ -29,6 +29,13 @@ import (
 	"github.com/apache/incubator-devlake/plugins/jira/models"
 )
 
+var ConvertIssueRepoCommitsMeta = core.SubTaskMeta{
+	Name:             "convertIssueRepoCommits",
+	EntryPoint:       ConvertIssueRepoCommits,
+	EnabledByDefault: false,
+	Description:      "convert Jira issue repo commits",
+}
+
 // ConvertIssueRepoCommits is to extract issue_repo_commits from jira_issue_commits, nothing difference with
 // issue_commits but added a RepoUrl. This task is needed by EE group.
 func ConvertIssueRepoCommits(taskCtx core.SubTaskContext) error {
diff --git a/plugins/jira/tasks/project_collector.go b/plugins/jira/tasks/project_collector.go
index 287a9595..811acf90 100644
--- a/plugins/jira/tasks/project_collector.go
+++ b/plugins/jira/tasks/project_collector.go
@@ -30,6 +30,13 @@ const RAW_PROJECT_TABLE = "jira_api_projects"
 
 var _ core.SubTaskEntryPoint = CollectProjects
 
+var CollectProjectsMeta = core.SubTaskMeta{
+	Name:             "collectProjects",
+	EntryPoint:       CollectProjects,
+	EnabledByDefault: true,
+	Description:      "collect Jira projects",
+}
+
 func CollectProjects(taskCtx core.SubTaskContext) error {
 	data := taskCtx.GetData().(*JiraTaskData)
 	logger := taskCtx.GetLogger()
diff --git a/plugins/jira/tasks/project_extractor.go b/plugins/jira/tasks/project_extractor.go
index b63fcb92..e37468ca 100644
--- a/plugins/jira/tasks/project_extractor.go
+++ b/plugins/jira/tasks/project_extractor.go
@@ -27,6 +27,13 @@ import (
 
 var _ core.SubTaskEntryPoint = ExtractProjects
 
+var ExtractProjectsMeta = core.SubTaskMeta{
+	Name:             "extractProjects",
+	EntryPoint:       ExtractProjects,
+	EnabledByDefault: true,
+	Description:      "extract Jira projects",
+}
+
 func ExtractProjects(taskCtx core.SubTaskContext) error {
 	data := taskCtx.GetData().(*JiraTaskData)
 	extractor, err := helper.NewApiExtractor(helper.ApiExtractorArgs{
diff --git a/plugins/jira/tasks/remotelink_collector.go b/plugins/jira/tasks/remotelink_collector.go
index 0a558386..77a78f23 100644
--- a/plugins/jira/tasks/remotelink_collector.go
+++ b/plugins/jira/tasks/remotelink_collector.go
@@ -32,6 +32,13 @@ const RAW_REMOTELINK_TABLE = "jira_api_remotelinks"
 
 var _ core.SubTaskEntryPoint = CollectRemotelinks
 
+var CollectRemotelinksMeta = core.SubTaskMeta{
+	Name:             "collectRemotelinks",
+	EntryPoint:       CollectRemotelinks,
+	EnabledByDefault: true,
+	Description:      "collect Jira remote links",
+}
+
 func CollectRemotelinks(taskCtx core.SubTaskContext) error {
 	data := taskCtx.GetData().(*JiraTaskData)
 	db := taskCtx.GetDal()
diff --git a/plugins/jira/tasks/remotelink_extractor.go b/plugins/jira/tasks/remotelink_extractor.go
index 6c73efbc..fc743c78 100644
--- a/plugins/jira/tasks/remotelink_extractor.go
+++ b/plugins/jira/tasks/remotelink_extractor.go
@@ -28,6 +28,13 @@ import (
 	"github.com/apache/incubator-devlake/plugins/jira/tasks/apiv2models"
 )
 
+var ExtractRemotelinksMeta = core.SubTaskMeta{
+	Name:             "extractRemotelinks",
+	EntryPoint:       ExtractRemotelinks,
+	EnabledByDefault: true,
+	Description:      "extract Jira remote links",
+}
+
 func ExtractRemotelinks(taskCtx core.SubTaskContext) error {
 	data := taskCtx.GetData().(*JiraTaskData)
 	connectionId := data.Options.ConnectionId
diff --git a/plugins/jira/tasks/sprint_collector.go b/plugins/jira/tasks/sprint_collector.go
index 07a0e5e0..6f10fb8b 100644
--- a/plugins/jira/tasks/sprint_collector.go
+++ b/plugins/jira/tasks/sprint_collector.go
@@ -31,6 +31,13 @@ const RAW_SPRINT_TABLE = "jira_api_sprints"
 
 var _ core.SubTaskEntryPoint = CollectSprints
 
+var CollectSprintsMeta = core.SubTaskMeta{
+	Name:             "collectSprints",
+	EntryPoint:       CollectSprints,
+	EnabledByDefault: true,
+	Description:      "collect Jira sprints",
+}
+
 func CollectSprints(taskCtx core.SubTaskContext) error {
 	data := taskCtx.GetData().(*JiraTaskData)
 	logger := taskCtx.GetLogger()
diff --git a/plugins/jira/tasks/sprint_convertor.go b/plugins/jira/tasks/sprint_convertor.go
index 432f4302..af0d1c71 100644
--- a/plugins/jira/tasks/sprint_convertor.go
+++ b/plugins/jira/tasks/sprint_convertor.go
@@ -30,6 +30,13 @@ import (
 	"github.com/apache/incubator-devlake/plugins/jira/models"
 )
 
+var ConvertSprintsMeta = core.SubTaskMeta{
+	Name:             "convertSprints",
+	EntryPoint:       ConvertSprints,
+	EnabledByDefault: true,
+	Description:      "convert Jira sprints",
+}
+
 func ConvertSprints(taskCtx core.SubTaskContext) error {
 	data := taskCtx.GetData().(*JiraTaskData)
 	connectionId := data.Options.ConnectionId
diff --git a/plugins/jira/tasks/sprint_extractor.go b/plugins/jira/tasks/sprint_extractor.go
index d3f3c83a..bc9a588a 100644
--- a/plugins/jira/tasks/sprint_extractor.go
+++ b/plugins/jira/tasks/sprint_extractor.go
@@ -28,6 +28,13 @@ import (
 
 var _ core.SubTaskEntryPoint = ExtractSprints
 
+var ExtractSprintsMeta = core.SubTaskMeta{
+	Name:             "extractSprints",
+	EntryPoint:       ExtractSprints,
+	EnabledByDefault: true,
+	Description:      "extract Jira sprints",
+}
+
 func ExtractSprints(taskCtx core.SubTaskContext) error {
 	data := taskCtx.GetData().(*JiraTaskData)
 	extractor, err := helper.NewApiExtractor(helper.ApiExtractorArgs{
diff --git a/plugins/jira/tasks/sprint_issues_convertor.go b/plugins/jira/tasks/sprint_issues_convertor.go
index 49621ec5..c5401bfd 100644
--- a/plugins/jira/tasks/sprint_issues_convertor.go
+++ b/plugins/jira/tasks/sprint_issues_convertor.go
@@ -28,6 +28,13 @@ import (
 	"github.com/apache/incubator-devlake/plugins/jira/models"
 )
 
+var ConvertSprintIssuesMeta = core.SubTaskMeta{
+	Name:             "convertSprintIssues",
+	EntryPoint:       ConvertSprintIssues,
+	EnabledByDefault: true,
+	Description:      "convert Jira sprint_issues",
+}
+
 func ConvertSprintIssues(taskCtx core.SubTaskContext) error {
 	db := taskCtx.GetDal()
 	data := taskCtx.GetData().(*JiraTaskData)
diff --git a/plugins/jira/tasks/status_collector.go b/plugins/jira/tasks/status_collector.go
index 01f4ef1a..da5bd952 100644
--- a/plugins/jira/tasks/status_collector.go
+++ b/plugins/jira/tasks/status_collector.go
@@ -27,6 +27,13 @@ import (
 
 const RAW_STATUS_TABLE = "jira_api_status"
 
+var CollectStatusMeta = core.SubTaskMeta{
+	Name:             "collectStatus",
+	EntryPoint:       CollectStatus,
+	EnabledByDefault: true,
+	Description:      "collect Jira status",
+}
+
 func CollectStatus(taskCtx core.SubTaskContext) error {
 	data := taskCtx.GetData().(*JiraTaskData)
 
diff --git a/plugins/jira/tasks/status_extractor.go b/plugins/jira/tasks/status_extractor.go
index bf68ea92..73362814 100644
--- a/plugins/jira/tasks/status_extractor.go
+++ b/plugins/jira/tasks/status_extractor.go
@@ -26,6 +26,13 @@ import (
 	"github.com/apache/incubator-devlake/plugins/jira/tasks/apiv2models"
 )
 
+var ExtractStatusMeta = core.SubTaskMeta{
+	Name:             "extractStatus",
+	EntryPoint:       ExtractStatus,
+	EnabledByDefault: true,
+	Description:      "extract Jira status",
+}
+
 func ExtractStatus(taskCtx core.SubTaskContext) error {
 	data := taskCtx.GetData().(*JiraTaskData)
 	connectionId := data.Options.ConnectionId
diff --git a/plugins/jira/tasks/user_collector.go b/plugins/jira/tasks/user_collector.go
index e43b0ee4..86bf3e60 100644
--- a/plugins/jira/tasks/user_collector.go
+++ b/plugins/jira/tasks/user_collector.go
@@ -31,6 +31,13 @@ import (
 
 const RAW_USERS_TABLE = "jira_api_users"
 
+var CollectUsersMeta = core.SubTaskMeta{
+	Name:             "collectUsers",
+	EntryPoint:       CollectUsers,
+	EnabledByDefault: true,
+	Description:      "collect Jira users",
+}
+
 func CollectUsers(taskCtx core.SubTaskContext) error {
 	data := taskCtx.GetData().(*JiraTaskData)
 	db := taskCtx.GetDal()
diff --git a/plugins/jira/tasks/user_convertor.go b/plugins/jira/tasks/user_convertor.go
index 843cd578..a163d20e 100644
--- a/plugins/jira/tasks/user_convertor.go
+++ b/plugins/jira/tasks/user_convertor.go
@@ -28,6 +28,13 @@ import (
 	"reflect"
 )
 
+var ConvertUsersMeta = core.SubTaskMeta{
+	Name:             "convertUsers",
+	EntryPoint:       ConvertUsers,
+	EnabledByDefault: true,
+	Description:      "convert Jira users",
+}
+
 func ConvertUsers(taskCtx core.SubTaskContext) error {
 	data := taskCtx.GetData().(*JiraTaskData)
 	connectionId := data.Options.ConnectionId
diff --git a/plugins/jira/tasks/user_extractor.go b/plugins/jira/tasks/user_extractor.go
index 4b21be33..d117e827 100644
--- a/plugins/jira/tasks/user_extractor.go
+++ b/plugins/jira/tasks/user_extractor.go
@@ -27,6 +27,13 @@ import (
 
 var _ core.SubTaskEntryPoint = ExtractUsers
 
+var ExtractUsersMeta = core.SubTaskMeta{
+	Name:             "extractUsers",
+	EntryPoint:       ExtractUsers,
+	EnabledByDefault: true,
+	Description:      "extract Jira users",
+}
+
 func ExtractUsers(taskCtx core.SubTaskContext) error {
 	data := taskCtx.GetData().(*JiraTaskData)
 	extractor, err := helper.NewApiExtractor(helper.ApiExtractorArgs{
diff --git a/plugins/jira/tasks/worklog_collector.go b/plugins/jira/tasks/worklog_collector.go
index e3e1aec6..cdb11eea 100644
--- a/plugins/jira/tasks/worklog_collector.go
+++ b/plugins/jira/tasks/worklog_collector.go
@@ -30,6 +30,13 @@ import (
 
 const RAW_WORKLOGS_TABLE = "jira_api_worklogs"
 
+var CollectWorklogsMeta = core.SubTaskMeta{
+	Name:             "collectWorklogs",
+	EntryPoint:       CollectWorklogs,
+	EnabledByDefault: true,
+	Description:      "collect Jira work logs",
+}
+
 func CollectWorklogs(taskCtx core.SubTaskContext) error {
 	db := taskCtx.GetDal()
 	data := taskCtx.GetData().(*JiraTaskData)
diff --git a/plugins/jira/tasks/worklog_convertor.go b/plugins/jira/tasks/worklog_convertor.go
index 5fd6f21f..2f9385d4 100644
--- a/plugins/jira/tasks/worklog_convertor.go
+++ b/plugins/jira/tasks/worklog_convertor.go
@@ -29,6 +29,13 @@ import (
 	"github.com/apache/incubator-devlake/plugins/jira/models"
 )
 
+var ConvertWorklogsMeta = core.SubTaskMeta{
+	Name:             "convertWorklogs",
+	EntryPoint:       ConvertWorklogs,
+	EnabledByDefault: true,
+	Description:      "convert Jira work logs",
+}
+
 func ConvertWorklogs(taskCtx core.SubTaskContext) error {
 	data := taskCtx.GetData().(*JiraTaskData)
 	db := taskCtx.GetDal()
diff --git a/plugins/jira/tasks/worklog_extractor.go b/plugins/jira/tasks/worklog_extractor.go
index 0f567891..698c9c63 100644
--- a/plugins/jira/tasks/worklog_extractor.go
+++ b/plugins/jira/tasks/worklog_extractor.go
@@ -26,6 +26,13 @@ import (
 
 var _ core.SubTaskEntryPoint = ExtractWorklogs
 
+var ExtractWorklogsMeta = core.SubTaskMeta{
+	Name:             "extractWorklogs",
+	EntryPoint:       ExtractWorklogs,
+	EnabledByDefault: true,
+	Description:      "extract Jira work logs",
+}
+
 func ExtractWorklogs(taskCtx core.SubTaskContext) error {
 	data := taskCtx.GetData().(*JiraTaskData)
 	extractor, err := helper.NewApiExtractor(helper.ApiExtractorArgs{