You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@devlake.apache.org by zh...@apache.org on 2022/08/16 17:04:51 UTC

[incubator-devlake] branch main updated: feat: add a plugin bitbucket (#2458)

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

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


The following commit(s) were added to refs/heads/main by this push:
     new f527fb56 feat: add a plugin bitbucket (#2458)
f527fb56 is described below

commit f527fb568920d0fb5a33e18e34060fa390cc9c21
Author: tsoc <47...@users.noreply.github.com>
AuthorDate: Wed Aug 17 01:04:47 2022 +0800

    feat: add a plugin bitbucket (#2458)
    
    * feat: add bitbucket connection and repo
    
    * fix: fix api/connection.go
    
    * feat: add pr and issues
    
    * feat: add issue_comments and pr_comments
    
    * feat: add accounts
    
    * fix: gofmt account_convertor.go
    
    * fix: fix accountIdGen
    
    * feat: add e2e test
    
    * fix: gofmt fix
    
    * fix: delete snapshot_tables
    
    * fix: ignore created_at updated_at and created_date
    
    * fix: Limit the length of primarykey and index
    
    * refactor: refactor some files
    
    * refactor: refactor some files
    
    * style: gofmt
    
    * feat: add field author_name type in table pullrequests
    
    * fix: change data in raw tables
    
    * fix: fix some bug about bitbucket pr
    
    * feat: add pr headref baseref etc
    
    * feat: add pr headref baseref etc
    
    * fix: change snapshot_tables
    
    * fix: change e2e testdata
    
    * perf: delete additions deleteions in pr,add reviewer,reporter in apipr etc.
    
    * fix: add field body,type in table pr_comments and issue_comments
    
    * perf: change code comments in connection.go
    
    * fix: change ratelimitto let collector faster
    
    * fix: add field issue_key and original_status in table issues
    
    * perf: change e2e testdatas
    
    * perf: convin raw table issue and pr
---
 plugins/bitbucket/api/blueprint.go                 |  151 +++
 plugins/bitbucket/api/connection.go                |  165 +++
 plugins/bitbucket/api/init.go                      |   39 +
 plugins/bitbucket/bitbucket.go                     |   66 +
 plugins/bitbucket/e2e/account_test.go              |   84 ++
 plugins/bitbucket/e2e/comment_test.go              |  169 +++
 plugins/bitbucket/e2e/issue_test.go                |  177 +++
 plugins/bitbucket/e2e/pr_test.go                   |  149 +++
 .../_raw_bitbucket_api_issue_comments.csv          |   29 +
 .../e2e/raw_tables/_raw_bitbucket_api_issues.csv   |   31 +
 .../_raw_bitbucket_api_pull_requests.csv           |   58 +
 .../_raw_bitbucket_api_pullrequest_comments.csv    |   19 +
 .../raw_tables/_raw_bitbucket_api_repositories.csv |    3 +
 plugins/bitbucket/e2e/repo_test.go                 |  138 +++
 .../snapshot_tables/_tool_bitbucket_accounts.csv   |    2 +
 .../_tool_bitbucket_accounts_in_comments.csv       |    2 +
 .../_tool_bitbucket_accounts_in_issue.csv          |    2 +
 .../_tool_bitbucket_accounts_in_pr.csv             |    2 +
 .../_tool_bitbucket_issue_comments.csv             |   29 +
 .../_tool_bitbucket_issue_labels.csv               |    1 +
 .../e2e/snapshot_tables/_tool_bitbucket_issues.csv |   55 +
 .../_tool_bitbucket_pull_request_comments.csv      |   19 +
 .../_tool_bitbucket_pull_requests.csv              |   58 +
 .../e2e/snapshot_tables/_tool_bitbucket_repos.csv  |    2 +
 plugins/bitbucket/e2e/snapshot_tables/accounts.csv |    2 +
 .../bitbucket/e2e/snapshot_tables/board_issues.csv |   31 +
 plugins/bitbucket/e2e/snapshot_tables/boards.csv   |    2 +
 .../e2e/snapshot_tables/issue_comments.csv         |   29 +
 plugins/bitbucket/e2e/snapshot_tables/issues.csv   |   55 +
 .../e2e/snapshot_tables/pull_request_comments.csv  |   21 +
 .../e2e/snapshot_tables/pull_requests.csv          | 1257 ++++++++++++++++++++
 plugins/bitbucket/e2e/snapshot_tables/repos.csv    |    2 +
 plugins/bitbucket/impl/impl.go                     |  125 ++
 plugins/bitbucket/models/account.go                |   39 +
 plugins/bitbucket/models/commit.go                 |   42 +
 plugins/bitbucket/models/connection.go             |   69 ++
 plugins/bitbucket/models/issue.go                  |   52 +
 plugins/bitbucket/models/issue_comment.go          |   40 +
 plugins/bitbucket/models/issue_event.go            |   37 +
 plugins/bitbucket/models/issue_label.go            |   36 +
 .../migrationscripts/20220803_add_init_tables.go   |  101 ++
 .../models/migrationscripts/archived/account.go    |   39 +
 .../models/migrationscripts/archived/commit.go     |   42 +
 .../models/migrationscripts/archived/connection.go |   69 ++
 .../models/migrationscripts/archived/issue.go      |   53 +
 .../migrationscripts/archived/issue_comment.go     |   40 +
 .../migrationscripts/archived/issue_event.go       |   37 +
 .../migrationscripts/archived/issue_label.go       |   36 +
 .../models/migrationscripts/archived/pr.go         |   57 +
 .../models/migrationscripts/archived/pr_comment.go |   41 +
 .../models/migrationscripts/archived/repo.go       |   40 +
 .../migrationscripts/archived/repo_commit.go       |   31 +
 .../models/migrationscripts/archived/user.go       |   33 +
 .../bitbucket/models/migrationscripts/register.go  |   29 +
 plugins/bitbucket/models/pr.go                     |   57 +
 plugins/bitbucket/models/pr_comment.go             |   41 +
 plugins/bitbucket/models/repo.go                   |   40 +
 plugins/bitbucket/models/repo_commit.go            |   31 +
 plugins/bitbucket/models/user.go                   |   35 +
 plugins/bitbucket/tasks/account_convertor.go       |   87 ++
 plugins/bitbucket/tasks/account_extractor.go       |   52 +
 plugins/bitbucket/tasks/api_client.go              |   86 ++
 plugins/bitbucket/tasks/api_common.go              |  137 +++
 plugins/bitbucket/tasks/commit_collector.go        |   56 +
 plugins/bitbucket/tasks/commit_convertor.go        |  103 ++
 plugins/bitbucket/tasks/commit_extractor.go        |  123 ++
 plugins/bitbucket/tasks/issue_collector.go         |   55 +
 plugins/bitbucket/tasks/issue_comment_collector.go |   61 +
 plugins/bitbucket/tasks/issue_comment_convertor.go |   92 ++
 plugins/bitbucket/tasks/issue_comment_extractor.go |  122 ++
 plugins/bitbucket/tasks/issue_convertor.go         |  120 ++
 plugins/bitbucket/tasks/issue_extractor.go         |  179 +++
 plugins/bitbucket/tasks/pr_collector.go            |   58 +
 plugins/bitbucket/tasks/pr_comment_collector.go    |   61 +
 plugins/bitbucket/tasks/pr_comment_convertor.go    |   96 ++
 plugins/bitbucket/tasks/pr_comment_extractor.go    |  124 ++
 plugins/bitbucket/tasks/pr_convertor.go            |  108 ++
 plugins/bitbucket/tasks/pr_extractor.go            |  166 +++
 plugins/bitbucket/tasks/repo_collector.go          |   63 +
 plugins/bitbucket/tasks/repo_convertor.go          |  106 ++
 plugins/bitbucket/tasks/repo_extractor.go          |  126 ++
 plugins/bitbucket/tasks/task_data.go               |   90 ++
 plugins/bitbucket/utils/utils.go                   |  152 +++
 83 files changed, 6564 insertions(+)

diff --git a/plugins/bitbucket/api/blueprint.go b/plugins/bitbucket/api/blueprint.go
new file mode 100644
index 00000000..71951934
--- /dev/null
+++ b/plugins/bitbucket/api/blueprint.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 api
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"net/url"
+	"strings"
+	"time"
+
+	"github.com/apache/incubator-devlake/models/domainlayer/didgen"
+	"github.com/apache/incubator-devlake/plugins/bitbucket/models"
+	"github.com/apache/incubator-devlake/plugins/bitbucket/tasks"
+	"github.com/apache/incubator-devlake/plugins/core"
+	"github.com/apache/incubator-devlake/plugins/helper"
+	"github.com/apache/incubator-devlake/utils"
+)
+
+func MakePipelinePlan(subtaskMetas []core.SubTaskMeta, connectionId uint64, scope []*core.BlueprintScopeV100) (core.PipelinePlan, error) {
+	var err error
+	plan := make(core.PipelinePlan, len(scope))
+	for i, scopeElem := range scope {
+		// handle taskOptions and transformationRules, by dumping them to taskOptions
+		transformationRules := make(map[string]interface{})
+		if len(scopeElem.Transformation) > 0 {
+			err = json.Unmarshal(scopeElem.Transformation, &transformationRules)
+			if err != nil {
+				return nil, err
+			}
+		}
+		// refdiff
+		if refdiffRules, ok := transformationRules["refdiff"]; ok {
+			// add a new task to next stage
+			j := i + 1
+			if j == len(plan) {
+				plan = append(plan, nil)
+			}
+			plan[j] = core.PipelineStage{
+				{
+					Plugin:  "refdiff",
+					Options: refdiffRules.(map[string]interface{}),
+				},
+			}
+			// remove it from bitbucket transformationRules
+			delete(transformationRules, "refdiff")
+		}
+		// construct task options for bitbucket
+		options := make(map[string]interface{})
+		err = json.Unmarshal(scopeElem.Options, &options)
+		if err != nil {
+			return nil, err
+		}
+		options["connectionId"] = connectionId
+		options["transformationRules"] = transformationRules
+		// make sure task options is valid
+		op, err := tasks.DecodeAndValidateTaskOptions(options)
+		if err != nil {
+			return nil, err
+		}
+		// construct subtasks
+		subtasks, err := helper.MakePipelinePlanSubtasks(subtaskMetas, scopeElem.Entities)
+		if err != nil {
+			return nil, err
+		}
+		stage := plan[i]
+		if stage == nil {
+			stage = core.PipelineStage{}
+		}
+		stage = append(stage, &core.PipelineTask{
+			Plugin:   "bitbucket",
+			Subtasks: subtasks,
+			Options:  options,
+		})
+		// collect git data by gitextractor if CODE was requested
+		if utils.StringsContains(scopeElem.Entities, core.DOMAIN_TYPE_CODE) {
+			// here is the tricky part, we have to obtain the repo id beforehand
+			connection := new(models.BitbucketConnection)
+			err = connectionHelper.FirstById(connection, connectionId)
+			if err != nil {
+				return nil, err
+			}
+			token := strings.Split(connection.GetEncodedToken(), ",")[0]
+			apiClient, err := helper.NewApiClient(
+				context.TODO(),
+				connection.Endpoint,
+				map[string]string{
+					"Authorization": fmt.Sprintf("Basic %s", token),
+				},
+				10*time.Second,
+				connection.Proxy,
+				basicRes,
+			)
+			if err != nil {
+				return nil, err
+			}
+			res, err := apiClient.Get(fmt.Sprintf("repositories/%s/%s", op.Owner, op.Repo), nil, nil)
+			if err != nil {
+				return nil, err
+			}
+			defer res.Body.Close()
+			if res.StatusCode != http.StatusOK {
+				return nil, fmt.Errorf(
+					"unexpected status code when requesting repo detail %d %s",
+					res.StatusCode, res.Request.URL.String(),
+				)
+			}
+			body, err := ioutil.ReadAll(res.Body)
+			if err != nil {
+				return nil, err
+			}
+			apiRepo := new(tasks.BitbucketApiRepo)
+			err = json.Unmarshal(body, apiRepo)
+			if err != nil {
+				return nil, err
+			}
+			cloneUrl, err := url.Parse(apiRepo.Links.Clone[0].Href)
+			if err != nil {
+				return nil, err
+			}
+			cloneUrl.User = url.UserPassword("git", token)
+			stage = append(stage, &core.PipelineTask{
+				Plugin: "gitextractor",
+				Options: map[string]interface{}{
+					"url":    cloneUrl.String(),
+					"repoId": didgen.NewDomainIdGenerator(&models.BitbucketRepo{}).Generate(connectionId, apiRepo.BitbucketId),
+				},
+			})
+		}
+		plan[i] = stage
+	}
+	return plan, nil
+}
diff --git a/plugins/bitbucket/api/connection.go b/plugins/bitbucket/api/connection.go
new file mode 100644
index 00000000..5969690c
--- /dev/null
+++ b/plugins/bitbucket/api/connection.go
@@ -0,0 +1,165 @@
+/*
+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 api
+
+import (
+	"context"
+	"fmt"
+	"net/http"
+	"time"
+
+	"github.com/apache/incubator-devlake/plugins/bitbucket/models"
+	"github.com/apache/incubator-devlake/plugins/core"
+	"github.com/apache/incubator-devlake/plugins/helper"
+	"github.com/mitchellh/mapstructure"
+)
+
+// @Summary test bitbucket connection
+// @Description Test bitbucket Connection
+// @Tags plugins/bitbucket
+// @Param body body models.TestConnectionRequest true "json body"
+// @Success 200  {object} shared.ApiBody "Success"
+// @Failure 400  {string} errcode.Error "Bad Request"
+// @Failure 500  {string} errcode.Error "Internel Error"
+// @Router /plugins/bitbucket/test [POST]
+func TestConnection(input *core.ApiResourceInput) (*core.ApiResourceOutput, error) {
+
+	// decode
+	var err error
+	var connection models.TestConnectionRequest
+	err = mapstructure.Decode(input.Body, &connection)
+	if err != nil {
+		return nil, err
+	}
+	// validate
+	err = vld.Struct(connection)
+	if err != nil {
+		return nil, err
+	}
+
+	// test connection
+	apiClient, err := helper.NewApiClient(
+		context.TODO(),
+		connection.Endpoint,
+		map[string]string{
+			"Authorization": fmt.Sprintf("Basic %v", connection.GetEncodedToken()),
+		},
+		3*time.Second,
+		connection.Proxy,
+		basicRes,
+	)
+	if err != nil {
+		return nil, err
+	}
+	res, err := apiClient.Get("user", nil, nil)
+	if err != nil {
+		return nil, err
+	}
+
+	resBody := &models.ApiUserResponse{}
+	err = helper.UnmarshalResponse(res, resBody)
+	if err != nil {
+		return nil, err
+	}
+
+	if res.StatusCode != http.StatusOK {
+		return nil, fmt.Errorf("unexpected status code: %d", res.StatusCode)
+	}
+	return nil, nil
+}
+
+// @Summary create bitbucket connection
+// @Description Create bitbucket connection
+// @Tags plugins/bitbucket
+// @Param body body models.BitbucketConnection true "json body"
+// @Success 200  {object} models.BitbucketConnection
+// @Failure 400  {string} errcode.Error "Bad Request"
+// @Failure 500  {string} errcode.Error "Internel Error"
+// @Router /plugins/bitbucket/connections [POST]
+func PostConnections(input *core.ApiResourceInput) (*core.ApiResourceOutput, error) {
+	// update from request and save to database
+	connection := &models.BitbucketConnection{}
+	err := connectionHelper.Create(connection, input)
+	if err != nil {
+		return nil, err
+	}
+	return &core.ApiResourceOutput{Body: connection, Status: http.StatusOK}, nil
+}
+
+// @Summary patch bitbucket connection
+// @Description Patch bitbucket connection
+// @Tags plugins/bitbucket
+// @Param body body models.BitbucketConnection true "json body"
+// @Success 200  {object} models.BitbucketConnection
+// @Failure 400  {string} errcode.Error "Bad Request"
+// @Failure 500  {string} errcode.Error "Internel Error"
+// @Router /plugins/bitbucket/connections/{connectionId} [PATCH]
+func PatchConnection(input *core.ApiResourceInput) (*core.ApiResourceOutput, error) {
+	connection := &models.BitbucketConnection{}
+	err := connectionHelper.Patch(connection, input)
+	if err != nil {
+		return nil, err
+	}
+	return &core.ApiResourceOutput{Body: connection}, nil
+}
+
+// @Summary delete a bitbucket connection
+// @Description Delete a bitbucket connection
+// @Tags plugins/bitbucket
+// @Success 200  {object} models.BitbucketConnection
+// @Failure 400  {string} errcode.Error "Bad Request"
+// @Failure 500  {string} errcode.Error "Internel Error"
+// @Router /plugins/bitbucket/connections/{connectionId} [DELETE]
+func DeleteConnection(input *core.ApiResourceInput) (*core.ApiResourceOutput, error) {
+	connection := &models.BitbucketConnection{}
+	err := connectionHelper.First(connection, input.Params)
+	if err != nil {
+		return nil, err
+	}
+	err = connectionHelper.Delete(connection)
+	return &core.ApiResourceOutput{Body: connection}, err
+}
+
+// @Summary get all bitbucket connections
+// @Description Get all bitbucket connections
+// @Tags plugins/bitbucket
+// @Success 200  {object} []models.BitbucketConnection
+// @Failure 400  {string} errcode.Error "Bad Request"
+// @Failure 500  {string} errcode.Error "Internel Error"
+// @Router /plugins/bitbucket/connections [GET]
+func ListConnections(input *core.ApiResourceInput) (*core.ApiResourceOutput, error) {
+	var connections []models.BitbucketConnection
+	err := connectionHelper.List(&connections)
+	if err != nil {
+		return nil, err
+	}
+	return &core.ApiResourceOutput{Body: connections, Status: http.StatusOK}, nil
+}
+
+// @Summary get bitbucket connection detail
+// @Description Get bitbucket connection detail
+// @Tags plugins/bitbucket
+// @Success 200  {object} models.BitbucketConnection
+// @Failure 400  {string} errcode.Error "Bad Request"
+// @Failure 500  {string} errcode.Error "Internel Error"
+// @Router /plugins/bitbucket/connections/{connectionId} [GET]
+func GetConnection(input *core.ApiResourceInput) (*core.ApiResourceOutput, error) {
+	connection := &models.BitbucketConnection{}
+	err := connectionHelper.First(connection, input.Params)
+	return &core.ApiResourceOutput{Body: connection}, err
+}
diff --git a/plugins/bitbucket/api/init.go b/plugins/bitbucket/api/init.go
new file mode 100644
index 00000000..6774e148
--- /dev/null
+++ b/plugins/bitbucket/api/init.go
@@ -0,0 +1,39 @@
+/*
+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 api
+
+import (
+	"github.com/apache/incubator-devlake/plugins/core"
+	"github.com/apache/incubator-devlake/plugins/helper"
+	"github.com/go-playground/validator/v10"
+	"github.com/spf13/viper"
+	"gorm.io/gorm"
+)
+
+var vld *validator.Validate
+var connectionHelper *helper.ConnectionApiHelper
+var basicRes core.BasicRes
+
+func Init(config *viper.Viper, logger core.Logger, database *gorm.DB) {
+	basicRes = helper.NewDefaultBasicRes(config, logger, database)
+	vld = validator.New()
+	connectionHelper = helper.NewConnectionHelper(
+		basicRes,
+		vld,
+	)
+}
diff --git a/plugins/bitbucket/bitbucket.go b/plugins/bitbucket/bitbucket.go
new file mode 100644
index 00000000..d80dec18
--- /dev/null
+++ b/plugins/bitbucket/bitbucket.go
@@ -0,0 +1,66 @@
+/*
+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 main // must be main for plugin entry point
+
+import (
+	"github.com/apache/incubator-devlake/plugins/bitbucket/impl"
+	"github.com/apache/incubator-devlake/runner"
+	"github.com/spf13/cobra"
+)
+
+// Export a variable named PluginEntry for Framework to search and load
+var PluginEntry impl.Bitbucket //nolint
+
+// standalone mode for debugging
+func main() {
+	cmd := &cobra.Command{Use: "bitbucket"}
+	connectionId := cmd.Flags().Uint64P("connectionId", "c", 0, "bitbucket connection id")
+	owner := cmd.Flags().StringP("owner", "o", "", "bitbucket owner")
+	repo := cmd.Flags().StringP("repo", "r", "", "bitbucket repo")
+	_ = cmd.MarkFlagRequired("connectionId")
+	_ = cmd.MarkFlagRequired("owner")
+	_ = cmd.MarkFlagRequired("repo")
+
+	prType := cmd.Flags().String("prType", "type/(.*)$", "pr type")
+	prComponent := cmd.Flags().String("prComponent", "component/(.*)$", "pr component")
+	prBodyClosePattern := cmd.Flags().String("prBodyClosePattern", "(?mi)(fix|close|resolve|fixes|closes|resolves|fixed|closed|resolved)[\\s]*.*(((and )?(#|https:\\/\\/api.bitbucket.org\\/2.0\\/%s\\/%s\\/issues\\/)\\d+[ ]*)+)", "pr body close pattern")
+	issueSeverity := cmd.Flags().String("issueSeverity", "severity/(.*)$", "issue severity")
+	issuePriority := cmd.Flags().String("issuePriority", "^(highest|high|medium|low)$", "issue priority")
+	issueComponent := cmd.Flags().String("issueComponent", "component/(.*)$", "issue component")
+	issueTypeBug := cmd.Flags().String("issueTypeBug", "^(bug|failure|error)$", "issue type bug")
+	issueTypeIncident := cmd.Flags().String("issueTypeIncident", "", "issue type incident")
+	issueTypeRequirement := cmd.Flags().String("issueTypeRequirement", "^(feat|feature|proposal|requirement)$", "issue type requirement")
+
+	cmd.Run = func(cmd *cobra.Command, args []string) {
+		runner.DirectRun(cmd, args, PluginEntry, map[string]interface{}{
+			"connectionId":         *connectionId,
+			"owner":                *owner,
+			"repo":                 *repo,
+			"prType":               *prType,
+			"prComponent":          *prComponent,
+			"prBodyClosePattern":   *prBodyClosePattern,
+			"issueSeverity":        *issueSeverity,
+			"issuePriority":        *issuePriority,
+			"issueComponent":       *issueComponent,
+			"issueTypeBug":         *issueTypeBug,
+			"issueTypeIncident":    *issueTypeIncident,
+			"issueTypeRequirement": *issueTypeRequirement,
+		})
+	}
+	runner.RunCmd(cmd)
+}
diff --git a/plugins/bitbucket/e2e/account_test.go b/plugins/bitbucket/e2e/account_test.go
new file mode 100644
index 00000000..cedf5863
--- /dev/null
+++ b/plugins/bitbucket/e2e/account_test.go
@@ -0,0 +1,84 @@
+/*
+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 (
+	"fmt"
+	"github.com/apache/incubator-devlake/models/common"
+	"github.com/apache/incubator-devlake/models/domainlayer/crossdomain"
+	"github.com/apache/incubator-devlake/plugins/bitbucket/models"
+	"testing"
+
+	"github.com/apache/incubator-devlake/helpers/e2ehelper"
+	"github.com/apache/incubator-devlake/plugins/bitbucket/impl"
+	"github.com/apache/incubator-devlake/plugins/bitbucket/tasks"
+)
+
+func TestAccountDataFlow(t *testing.T) {
+	var plugin impl.Bitbucket
+	dataflowTester := e2ehelper.NewDataFlowTester(t, "bitbucket", plugin)
+
+	bitbucketRepository := &models.BitbucketRepo{
+		BitbucketId: "panjf2000/ants",
+	}
+	taskData := &tasks.BitbucketTaskData{
+		Options: &tasks.BitbucketOptions{
+			ConnectionId: 1,
+			Owner:        "panjf2000",
+			Repo:         "ants",
+		},
+		Repo: bitbucketRepository,
+	}
+
+	// import raw data table
+	dataflowTester.ImportCsvIntoRawTable("./raw_tables/_raw_bitbucket_api_issues.csv", "_raw_bitbucket_api_issues")
+	dataflowTester.ImportCsvIntoRawTable("./raw_tables/_raw_bitbucket_api_pull_requests.csv", "_raw_bitbucket_api_pull_requests")
+
+	// verify extraction
+	dataflowTester.FlushTabler(&models.BitbucketAccount{})
+	dataflowTester.FlushTabler(&models.BitbucketIssue{})
+	dataflowTester.FlushTabler(&models.BitbucketPullRequest{})
+	dataflowTester.Subtask(tasks.ExtractApiIssuesMeta, taskData)
+	dataflowTester.Subtask(tasks.ExtractApiPullRequestsMeta, taskData)
+	dataflowTester.VerifyTable(
+		models.BitbucketAccount{},
+		fmt.Sprintf("./snapshot_tables/%s.csv", models.BitbucketAccount{}.TableName()),
+		[]string{
+			"connection_id",
+			"user_name",
+			"account_id",
+			"account_status",
+			"display_name",
+			"avatar_url",
+			"html_url",
+			"uuid",
+			"has2_fa_enabled",
+			"_raw_data_params",
+			"_raw_data_table",
+			"_raw_data_id",
+			"_raw_data_remark",
+		},
+	)
+	// verify converter
+	dataflowTester.FlushTabler(&crossdomain.Account{})
+	dataflowTester.Subtask(tasks.ConvertAccountsMeta, taskData)
+	dataflowTester.VerifyTableWithOptions(&crossdomain.Account{}, e2ehelper.TableOptions{
+		CSVRelPath:  "./snapshot_tables/accounts.csv",
+		IgnoreTypes: []interface{}{common.NoPKModel{}},
+	})
+}
diff --git a/plugins/bitbucket/e2e/comment_test.go b/plugins/bitbucket/e2e/comment_test.go
new file mode 100644
index 00000000..c6a45935
--- /dev/null
+++ b/plugins/bitbucket/e2e/comment_test.go
@@ -0,0 +1,169 @@
+/*
+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 (
+	"fmt"
+	"testing"
+
+	"github.com/apache/incubator-devlake/models/domainlayer/code"
+	"github.com/apache/incubator-devlake/models/domainlayer/ticket"
+	"github.com/apache/incubator-devlake/plugins/bitbucket/models"
+	"github.com/apache/incubator-devlake/plugins/bitbucket/tasks"
+
+	"github.com/apache/incubator-devlake/helpers/e2ehelper"
+	"github.com/apache/incubator-devlake/plugins/bitbucket/impl"
+)
+
+func TestCommentDataFlow(t *testing.T) {
+	var plugin impl.Bitbucket
+	dataflowTester := e2ehelper.NewDataFlowTester(t, "bitbucket", plugin)
+
+	bitbucketRepository := &models.BitbucketRepo{
+		BitbucketId: "panjf2000/ants",
+	}
+	taskData := &tasks.BitbucketTaskData{
+		Options: &tasks.BitbucketOptions{
+			ConnectionId: 1,
+			Owner:        "panjf2000",
+			Repo:         "ants",
+			TransformationRules: models.TransformationRules{
+				PrType:               "type/(.*)$",
+				PrComponent:          "component/(.*)$",
+				PrBodyClosePattern:   "(?mi)(fix|close|resolve|fixes|closes|resolves|fixed|closed|resolved)[\\s]*.*(((and )?(#|https:\\/\\/api.bitbucket.org\\/2.0\\/%s\\/%s\\/issues\\/)\\d+[ ]*)+)",
+				IssueSeverity:        "severity/(.*)$",
+				IssuePriority:        "^(highest|high|medium|low)$",
+				IssueComponent:       "component/(.*)$",
+				IssueTypeBug:         "^(bug|failure|error)$",
+				IssueTypeIncident:    "",
+				IssueTypeRequirement: "^(feat|feature|proposal|requirement)$",
+			},
+		},
+		Repo: bitbucketRepository,
+	}
+
+	// import raw data table
+	dataflowTester.ImportCsvIntoRawTable("./raw_tables/_raw_bitbucket_api_issue_comments.csv", "_raw_bitbucket_api_issue_comments")
+	dataflowTester.ImportCsvIntoRawTable("./raw_tables/_raw_bitbucket_api_pullrequest_comments.csv", "_raw_bitbucket_api_pull_request_comments")
+
+	// verify extraction
+	dataflowTester.FlushTabler(&models.BitbucketIssueComment{})
+	dataflowTester.FlushTabler(&models.BitbucketPrComment{})
+	dataflowTester.FlushTabler(&models.BitbucketAccount{})
+	dataflowTester.Subtask(tasks.ExtractApiIssueCommentsMeta, taskData)
+	dataflowTester.Subtask(tasks.ExtractApiPrCommentsMeta, taskData)
+	dataflowTester.VerifyTable(
+		models.BitbucketIssueComment{},
+		fmt.Sprintf("./snapshot_tables/%s.csv", models.BitbucketIssueComment{}.TableName()),
+		[]string{
+			"connection_id",
+			"bitbucket_id",
+			"issue_id",
+			"author_name",
+			"author_id",
+			"bitbucket_created_at",
+			"bitbucket_updated_at",
+			"type",
+			"_raw_data_params",
+			"_raw_data_table",
+			"_raw_data_id",
+			"_raw_data_remark",
+		},
+	)
+	dataflowTester.VerifyTable(
+		models.BitbucketPrComment{},
+		fmt.Sprintf("./snapshot_tables/%s.csv", models.BitbucketPrComment{}.TableName()),
+		[]string{
+			"connection_id",
+			"bitbucket_id",
+			"pull_request_id",
+			"author_name",
+			"author_id",
+			"bitbucket_created_at",
+			"bitbucket_updated_at",
+			"type",
+			"_raw_data_params",
+			"_raw_data_table",
+			"_raw_data_id",
+			"_raw_data_remark",
+		},
+	)
+	dataflowTester.VerifyTable(
+		models.BitbucketAccount{},
+		"./snapshot_tables/_tool_bitbucket_accounts_in_comments.csv",
+		[]string{
+			"connection_id",
+			"user_name",
+			"account_id",
+			"account_status",
+			"display_name",
+			"avatar_url",
+			"html_url",
+			"uuid",
+			"has2_fa_enabled",
+			"_raw_data_params",
+			"_raw_data_table",
+			"_raw_data_id",
+			"_raw_data_remark",
+		},
+	)
+
+	// verify comment conversion
+	dataflowTester.FlushTabler(&ticket.IssueComment{})
+	dataflowTester.FlushTabler(&code.PullRequestComment{})
+	dataflowTester.Subtask(tasks.ConvertIssueCommentsMeta, taskData)
+	dataflowTester.Subtask(tasks.ConvertPrCommentsMeta, taskData)
+
+	dataflowTester.VerifyTable(
+		ticket.IssueComment{},
+		fmt.Sprintf("./snapshot_tables/%s.csv", ticket.IssueComment{}.TableName()),
+		[]string{
+			"id",
+			"_raw_data_params",
+			"_raw_data_table",
+			"_raw_data_id",
+			"_raw_data_remark",
+			"issue_id",
+			"body",
+			"user_id",
+		},
+	)
+
+	// verify relation in pr and comment conversion
+	dataflowTester.FlushTabler(&code.PullRequestComment{})
+	dataflowTester.Subtask(tasks.ConvertPrCommentsMeta, taskData)
+	dataflowTester.VerifyTable(
+		code.PullRequestComment{},
+		fmt.Sprintf("./snapshot_tables/%s.csv", code.PullRequestComment{}.TableName()),
+		[]string{
+			"id",
+			"_raw_data_params",
+			"_raw_data_table",
+			"_raw_data_id",
+			"_raw_data_remark",
+			"pull_request_id",
+			"body",
+			"user_id",
+			"commit_sha",
+			"position",
+			"type",
+			"review_id",
+			"status",
+		},
+	)
+}
diff --git a/plugins/bitbucket/e2e/issue_test.go b/plugins/bitbucket/e2e/issue_test.go
new file mode 100644
index 00000000..799a9cd1
--- /dev/null
+++ b/plugins/bitbucket/e2e/issue_test.go
@@ -0,0 +1,177 @@
+/*
+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 (
+	"fmt"
+	"testing"
+
+	"github.com/apache/incubator-devlake/models/domainlayer/ticket"
+	"github.com/apache/incubator-devlake/plugins/bitbucket/models"
+
+	"github.com/apache/incubator-devlake/helpers/e2ehelper"
+	"github.com/apache/incubator-devlake/plugins/bitbucket/impl"
+	"github.com/apache/incubator-devlake/plugins/bitbucket/tasks"
+)
+
+func TestIssueDataFlow(t *testing.T) {
+	var plugin impl.Bitbucket
+	dataflowTester := e2ehelper.NewDataFlowTester(t, "bitbucket", plugin)
+
+	bitbucketRepository := &models.BitbucketRepo{
+		BitbucketId: "panjf2000/ants",
+	}
+	taskData := &tasks.BitbucketTaskData{
+		Options: &tasks.BitbucketOptions{
+			ConnectionId: 1,
+			Owner:        "panjf2000",
+			Repo:         "ants",
+			TransformationRules: models.TransformationRules{
+				PrType:               "type/(.*)$",
+				PrComponent:          "component/(.*)$",
+				PrBodyClosePattern:   "(?mi)(fix|close|resolve|fixes|closes|resolves|fixed|closed|resolved)[\\s]*.*(((and )?(#|https:\\/\\/api.bitbucket.org\\/2.0\\/%s\\/%s\\/issues\\/)\\d+[ ]*)+)",
+				IssueSeverity:        "severity/(.*)$",
+				IssuePriority:        "^(highest|high|medium|low)$",
+				IssueComponent:       "component/(.*)$",
+				IssueTypeBug:         "^(bug|failure|error)$",
+				IssueTypeIncident:    "",
+				IssueTypeRequirement: "^(feat|feature|proposal|requirement)$",
+			},
+		},
+		Repo: bitbucketRepository,
+	}
+
+	// import raw data table
+	dataflowTester.ImportCsvIntoRawTable("./raw_tables/_raw_bitbucket_api_issues.csv", "_raw_bitbucket_api_issues")
+
+	// verify issue extraction
+	dataflowTester.FlushTabler(&models.BitbucketIssue{})
+	dataflowTester.FlushTabler(&models.BitbucketIssueLabel{})
+	dataflowTester.FlushTabler(&models.BitbucketAccount{})
+	dataflowTester.Subtask(tasks.ExtractApiIssuesMeta, taskData)
+	dataflowTester.VerifyTable(
+		models.BitbucketIssue{},
+		fmt.Sprintf("./snapshot_tables/%s.csv", models.BitbucketIssue{}.TableName()),
+		[]string{
+			"connection_id",
+			"bitbucket_id",
+			"repo_id",
+			"number",
+			"state",
+			"title",
+			"body",
+			"priority",
+			"type",
+			"author_id",
+			"author_name",
+			"assignee_id",
+			"assignee_name",
+			"milestone_id",
+			"lead_time_minutes",
+			"url",
+			"closed_at",
+			"bitbucket_created_at",
+			"bitbucket_updated_at",
+			"severity",
+			"component",
+			"_raw_data_params",
+			"_raw_data_table",
+			"_raw_data_id",
+			"_raw_data_remark",
+		},
+	)
+	dataflowTester.VerifyTable(
+		models.BitbucketIssueLabel{},
+		fmt.Sprintf("./snapshot_tables/%s.csv", models.BitbucketIssueLabel{}.TableName()),
+		[]string{
+			"connection_id",
+			"issue_id",
+			"label_name",
+			"_raw_data_params",
+			"_raw_data_table",
+			"_raw_data_id",
+			"_raw_data_remark",
+		},
+	)
+	dataflowTester.VerifyTable(
+		models.BitbucketAccount{},
+		"./snapshot_tables/_tool_bitbucket_accounts_in_issue.csv",
+		[]string{
+			"connection_id",
+			"user_name",
+			"account_id",
+			"account_status",
+			"display_name",
+			"avatar_url",
+			"html_url",
+			"uuid",
+			"has2_fa_enabled",
+			"_raw_data_params",
+			"_raw_data_table",
+			"_raw_data_id",
+			"_raw_data_remark",
+		},
+	)
+
+	// verify issue conversion
+	dataflowTester.FlushTabler(&ticket.Issue{})
+	dataflowTester.FlushTabler(&ticket.BoardIssue{})
+	dataflowTester.Subtask(tasks.ConvertIssuesMeta, taskData)
+	dataflowTester.VerifyTable(
+		ticket.Issue{},
+		fmt.Sprintf("./snapshot_tables/%s.csv", ticket.Issue{}.TableName()),
+		[]string{
+			"id",
+			"_raw_data_params",
+			"_raw_data_table",
+			"_raw_data_id",
+			"_raw_data_remark",
+			"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{},
+		fmt.Sprintf("./snapshot_tables/%s.csv", ticket.BoardIssue{}.TableName()),
+		[]string{"board_id", "issue_id"},
+	)
+
+}
diff --git a/plugins/bitbucket/e2e/pr_test.go b/plugins/bitbucket/e2e/pr_test.go
new file mode 100644
index 00000000..9daea3bd
--- /dev/null
+++ b/plugins/bitbucket/e2e/pr_test.go
@@ -0,0 +1,149 @@
+/*
+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 (
+	"fmt"
+	"testing"
+
+	"github.com/apache/incubator-devlake/models/domainlayer/code"
+	"github.com/apache/incubator-devlake/plugins/bitbucket/models"
+
+	"github.com/apache/incubator-devlake/helpers/e2ehelper"
+	"github.com/apache/incubator-devlake/plugins/bitbucket/impl"
+	"github.com/apache/incubator-devlake/plugins/bitbucket/tasks"
+)
+
+func TestPrDataFlow(t *testing.T) {
+	var plugin impl.Bitbucket
+	dataflowTester := e2ehelper.NewDataFlowTester(t, "bitbucket", plugin)
+
+	bitbucketRepository := &models.BitbucketRepo{
+		BitbucketId: "panjf2000/ants",
+	}
+	taskData := &tasks.BitbucketTaskData{
+		Options: &tasks.BitbucketOptions{
+			ConnectionId: 1,
+			Owner:        "panjf2000",
+			Repo:         "ants",
+			TransformationRules: models.TransformationRules{
+				PrType:             "type/(.*)$",
+				PrComponent:        "component/(.*)$",
+				PrBodyClosePattern: "(?mi)(fix|close|resolve|fixes|closes|resolves|fixed|closed|resolved)[\\s]*.*(((and )?(#|https:\\/\\/api.bitbucket.org\\/2.0\\/%s\\/%s\\/issues\\/)\\d+[ ]*)+)",
+			},
+		},
+		Repo: bitbucketRepository,
+	}
+
+	// import raw data table
+	dataflowTester.ImportCsvIntoRawTable("./raw_tables/_raw_bitbucket_api_pull_requests.csv", "_raw_bitbucket_api_pull_requests")
+
+	// verify pr extraction
+	dataflowTester.FlushTabler(&models.BitbucketPullRequest{})
+	dataflowTester.FlushTabler(&models.BitbucketAccount{})
+	dataflowTester.Subtask(tasks.ExtractApiPullRequestsMeta, taskData)
+	dataflowTester.VerifyTable(
+		models.BitbucketPullRequest{},
+		fmt.Sprintf("./snapshot_tables/%s.csv", models.BitbucketPullRequest{}.TableName()),
+		[]string{
+			"connection_id",
+			"bitbucket_id",
+			"repo_id",
+			"number",
+			"state",
+			"title",
+			"bitbucket_created_at",
+			"bitbucket_updated_at",
+			"closed_at",
+			"comment_count",
+			"commits",
+			"merged_at",
+			"body",
+			"type",
+			"component",
+			"merge_commit_sha",
+			"head_ref",
+			"base_ref",
+			"base_commit_sha",
+			"head_commit_sha",
+			"url",
+			"author_name",
+			"author_id",
+			"_raw_data_params",
+			"_raw_data_table",
+			"_raw_data_id",
+			"_raw_data_remark",
+		},
+	)
+
+	dataflowTester.VerifyTable(
+		models.BitbucketAccount{},
+		"./snapshot_tables/_tool_bitbucket_accounts_in_pr.csv",
+		[]string{
+			"connection_id",
+			"user_name",
+			"account_id",
+			"account_status",
+			"display_name",
+			"avatar_url",
+			"html_url",
+			"uuid",
+			"has2_fa_enabled",
+			"_raw_data_params",
+			"_raw_data_table",
+			"_raw_data_id",
+			"_raw_data_remark",
+		},
+	)
+
+	// verify pr conversion
+	dataflowTester.FlushTabler(&code.PullRequest{})
+	dataflowTester.Subtask(tasks.ConvertPullRequestsMeta, taskData)
+	dataflowTester.VerifyTable(
+		code.PullRequest{},
+		fmt.Sprintf("./snapshot_tables/%s.csv", code.PullRequest{}.TableName()),
+		[]string{
+			"id",
+			"_raw_data_params",
+			"_raw_data_table",
+			"_raw_data_id",
+			"_raw_data_remark",
+			"base_repo_id",
+			"head_repo_id",
+			"status",
+			"title",
+			"description",
+			"url",
+			"author_name",
+			"author_id",
+			"parent_pr_id",
+			"pull_request_key",
+			"created_date",
+			"merged_date",
+			"closed_date",
+			"type",
+			"component",
+			"merge_commit_sha",
+			"head_ref",
+			"base_ref",
+			"base_commit_sha",
+			"head_commit_sha",
+		},
+	)
+
+}
diff --git a/plugins/bitbucket/e2e/raw_tables/_raw_bitbucket_api_issue_comments.csv b/plugins/bitbucket/e2e/raw_tables/_raw_bitbucket_api_issue_comments.csv
new file mode 100644
index 00000000..44b43ef9
--- /dev/null
+++ b/plugins/bitbucket/e2e/raw_tables/_raw_bitbucket_api_issue_comments.csv
@@ -0,0 +1,29 @@
+id,params,data,url,input,created_at
+1,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue_comment"", ""id"": 63860152, ""created_on"": ""2022-07-17T07:16:30.352685+00:00"", ""updated_on"": null, ""content"": {""type"": ""rendered"", ""raw"": null, ""markup"": ""markdown"", ""html"": """"}, ""user"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D""}, ""avatar"": {""href"": ""https://secure.grav [...]
+2,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue_comment"", ""id"": 63860153, ""created_on"": ""2022-07-17T07:17:01.991973+00:00"", ""updated_on"": null, ""content"": {""type"": ""rendered"", ""raw"": ""this is a comment test for issue"", ""markup"": ""markdown"", ""html"": ""<p>this is a comment test for issue</p>""}, ""user"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-429 [...]
+3,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue_comment"", ""id"": 63860241, ""created_on"": ""2022-07-17T09:11:42.759529+00:00"", ""updated_on"": null, ""content"": {""type"": ""rendered"", ""raw"": null, ""markup"": ""markdown"", ""html"": """"}, ""user"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D""}, ""avatar"": {""href"": ""https://secure.grav [...]
+4,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue_comment"", ""id"": 63961973, ""created_on"": ""2022-08-12T13:51:25.882209+00:00"", ""updated_on"": null, ""content"": {""type"": ""rendered"", ""raw"": null, ""markup"": ""markdown"", ""html"": """"}, ""user"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D""}, ""avatar"": {""href"": ""https://secure.grav [...]
+5,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue_comment"", ""id"": 63961995, ""created_on"": ""2022-08-12T13:55:58.125226+00:00"", ""updated_on"": null, ""content"": {""type"": ""rendered"", ""raw"": null, ""markup"": ""markdown"", ""html"": """"}, ""user"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D""}, ""avatar"": {""href"": ""https://secure.grav [...]
+6,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue_comment"", ""id"": 63963442, ""created_on"": ""2022-08-13T06:17:23.165014+00:00"", ""updated_on"": null, ""content"": {""type"": ""rendered"", ""raw"": ""gvoeaoivae"", ""markup"": ""markdown"", ""html"": ""<p>gvoeaoivae</p>""}, ""user"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D""}, ""avatar"": {""hr [...]
+7,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue_comment"", ""id"": 63963443, ""created_on"": ""2022-08-13T06:17:28.683792+00:00"", ""updated_on"": null, ""content"": {""type"": ""rendered"", ""raw"": ""vboeaorboaneo"", ""markup"": ""markdown"", ""html"": ""<p>vboeaorboaneo</p>""}, ""user"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D""}, ""avatar"": [...]
+8,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue_comment"", ""id"": 63963444, ""created_on"": ""2022-08-13T06:17:36.685718+00:00"", ""updated_on"": null, ""content"": {""type"": ""rendered"", ""raw"": ""beoiroierbieiaoboere"", ""markup"": ""markdown"", ""html"": ""<p>beoiroierbieiaoboere</p>""}, ""user"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D"" [...]
+9,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue_comment"", ""id"": 63963445, ""created_on"": ""2022-08-13T06:17:42.086856+00:00"", ""updated_on"": null, ""content"": {""type"": ""rendered"", ""raw"": ""boetboenavnin"", ""markup"": ""markdown"", ""html"": ""<p>boetboenavnin</p>""}, ""user"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D""}, ""avatar"": [...]
+10,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue_comment"", ""id"": 63963446, ""created_on"": ""2022-08-13T06:17:47.634459+00:00"", ""updated_on"": null, ""content"": {""type"": ""rendered"", ""raw"": ""bbenoirbnavbeboa"", ""markup"": ""markdown"", ""html"": ""<p>bbenoirbnavbeboa</p>""}, ""user"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D""}, ""av [...]
+11,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue_comment"", ""id"": 63963447, ""created_on"": ""2022-08-13T06:17:55.851366+00:00"", ""updated_on"": null, ""content"": {""type"": ""rendered"", ""raw"": ""lboehoraebow"", ""markup"": ""markdown"", ""html"": ""<p>lboehoraebow</p>""}, ""user"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D""}, ""avatar"":  [...]
+12,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue_comment"", ""id"": 63963449, ""created_on"": ""2022-08-13T06:18:01.927576+00:00"", ""updated_on"": null, ""content"": {""type"": ""rendered"", ""raw"": ""ebeobnoerioaeiow"", ""markup"": ""markdown"", ""html"": ""<p>ebeobnoerioaeiow</p>""}, ""user"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D""}, ""av [...]
+13,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue_comment"", ""id"": 63963450, ""created_on"": ""2022-08-13T06:18:11.146999+00:00"", ""updated_on"": null, ""content"": {""type"": ""rendered"", ""raw"": ""uttrberoiea"", ""markup"": ""markdown"", ""html"": ""<p>uttrberoiea</p>""}, ""user"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D""}, ""avatar"": {" [...]
+14,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue_comment"", ""id"": 63963451, ""created_on"": ""2022-08-13T06:18:19.376928+00:00"", ""updated_on"": null, ""content"": {""type"": ""rendered"", ""raw"": ""obfbdfonwea"", ""markup"": ""markdown"", ""html"": ""<p>obfbdfonwea</p>""}, ""user"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D""}, ""avatar"": {" [...]
+15,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue_comment"", ""id"": 63963452, ""created_on"": ""2022-08-13T06:18:26.505035+00:00"", ""updated_on"": null, ""content"": {""type"": ""rendered"", ""raw"": ""bjeorjboewaonwea"", ""markup"": ""markdown"", ""html"": ""<p>bjeorjboewaonwea</p>""}, ""user"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D""}, ""av [...]
+16,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue_comment"", ""id"": 63963453, ""created_on"": ""2022-08-13T06:18:33.109491+00:00"", ""updated_on"": null, ""content"": {""type"": ""rendered"", ""raw"": ""brtoeorbnqqe"", ""markup"": ""markdown"", ""html"": ""<p>brtoeorbnqqe</p>""}, ""user"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D""}, ""avatar"":  [...]
+17,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue_comment"", ""id"": 63963454, ""created_on"": ""2022-08-13T06:18:39.542749+00:00"", ""updated_on"": null, ""content"": {""type"": ""rendered"", ""raw"": ""mmboeroi"", ""markup"": ""markdown"", ""html"": ""<p>mmboeroi</p>""}, ""user"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D""}, ""avatar"": {""href" [...]
+18,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue_comment"", ""id"": 63963455, ""created_on"": ""2022-08-13T06:18:46.158468+00:00"", ""updated_on"": null, ""content"": {""type"": ""rendered"", ""raw"": ""lqooaqjoe"", ""markup"": ""markdown"", ""html"": ""<p>lqooaqjoe</p>""}, ""user"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D""}, ""avatar"": {""hre [...]
+19,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue_comment"", ""id"": 63963456, ""created_on"": ""2022-08-13T06:18:52.858029+00:00"", ""updated_on"": null, ""content"": {""type"": ""rendered"", ""raw"": ""vajoieiowaeovw"", ""markup"": ""markdown"", ""html"": ""<p>vajoieiowaeovw</p>""}, ""user"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D""}, ""avatar [...]
+20,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue_comment"", ""id"": 63963457, ""created_on"": ""2022-08-13T06:18:58.979282+00:00"", ""updated_on"": null, ""content"": {""type"": ""rendered"", ""raw"": ""ieiojiwea"", ""markup"": ""markdown"", ""html"": ""<p>ieiojiwea</p>""}, ""user"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D""}, ""avatar"": {""hre [...]
+21,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue_comment"", ""id"": 63963458, ""created_on"": ""2022-08-13T06:19:05.666753+00:00"", ""updated_on"": null, ""content"": {""type"": ""rendered"", ""raw"": ""beraowheuovhaewa"", ""markup"": ""markdown"", ""html"": ""<p>beraowheuovhaewa</p>""}, ""user"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D""}, ""av [...]
+22,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue_comment"", ""id"": 63963459, ""created_on"": ""2022-08-13T06:19:15.956726+00:00"", ""updated_on"": null, ""content"": {""type"": ""rendered"", ""raw"": ""oeorjeorb"", ""markup"": ""markdown"", ""html"": ""<p>oeorjeorb</p>""}, ""user"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D""}, ""avatar"": {""hre [...]
+23,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue_comment"", ""id"": 63963460, ""created_on"": ""2022-08-13T06:19:23.294249+00:00"", ""updated_on"": null, ""content"": {""type"": ""rendered"", ""raw"": ""iocowevoanewww"", ""markup"": ""markdown"", ""html"": ""<p>iocowevoanewww</p>""}, ""user"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D""}, ""avatar [...]
+24,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue_comment"", ""id"": 63963461, ""created_on"": ""2022-08-13T06:19:31.457341+00:00"", ""updated_on"": null, ""content"": {""type"": ""rendered"", ""raw"": ""cowoehvowevaobnebiejaiweaw"", ""markup"": ""markdown"", ""html"": ""<p>cowoehvowevaobnebiejaiweaw</p>""}, ""user"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-4297-99b1-2182 [...]
+25,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue_comment"", ""id"": 63963462, ""created_on"": ""2022-08-13T06:19:38.433512+00:00"", ""updated_on"": null, ""content"": {""type"": ""rendered"", ""raw"": ""vbleklawi"", ""markup"": ""markdown"", ""html"": ""<p>vbleklawi</p>""}, ""user"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D""}, ""avatar"": {""hre [...]
+26,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue_comment"", ""id"": 63963463, ""created_on"": ""2022-08-13T06:19:45.160531+00:00"", ""updated_on"": null, ""content"": {""type"": ""rendered"", ""raw"": ""qowjoveawev"", ""markup"": ""markdown"", ""html"": ""<p>qowjoveawev</p>""}, ""user"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D""}, ""avatar"": {" [...]
+27,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue_comment"", ""id"": 63963464, ""created_on"": ""2022-08-13T06:19:54.365641+00:00"", ""updated_on"": null, ""content"": {""type"": ""rendered"", ""raw"": ""ciojboieria"", ""markup"": ""markdown"", ""html"": ""<p>ciojboieria</p>""}, ""user"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D""}, ""avatar"": {" [...]
+28,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue_comment"", ""id"": 63963465, ""created_on"": ""2022-08-13T06:20:01.329125+00:00"", ""updated_on"": null, ""content"": {""type"": ""rendered"", ""raw"": ""cwiwhoervowwwqe"", ""markup"": ""markdown"", ""html"": ""<p>cwiwhoervowwwqe</p>""}, ""user"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D""}, ""avat [...]
diff --git a/plugins/bitbucket/e2e/raw_tables/_raw_bitbucket_api_issues.csv b/plugins/bitbucket/e2e/raw_tables/_raw_bitbucket_api_issues.csv
new file mode 100644
index 00000000..c8cf4d14
--- /dev/null
+++ b/plugins/bitbucket/e2e/raw_tables/_raw_bitbucket_api_issues.csv
@@ -0,0 +1,31 @@
+id,params,data,url,input,created_at
+31,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue"", ""id"": 27, ""repository"": {""type"": ""repository"", ""full_name"": ""panjf2000/ants"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/repositories/panjf2000/ants""}, ""html"": {""href"": ""https://bitbucket.org/panjf2000/ants""}, ""avatar"": {""href"": ""https://bytebucket.org/ravatar/%7Be762bff4-f795-49c6-b9f9-6ea334b6d964%7D?ts=default""}}, ""name"": ""ants"", ""uuid"": ""{e7 [...]
+32,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue"", ""id"": 30, ""repository"": {""type"": ""repository"", ""full_name"": ""panjf2000/ants"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/repositories/panjf2000/ants""}, ""html"": {""href"": ""https://bitbucket.org/panjf2000/ants""}, ""avatar"": {""href"": ""https://bytebucket.org/ravatar/%7Be762bff4-f795-49c6-b9f9-6ea334b6d964%7D?ts=default""}}, ""name"": ""ants"", ""uuid"": ""{e7 [...]
+33,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue"", ""id"": 29, ""repository"": {""type"": ""repository"", ""full_name"": ""panjf2000/ants"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/repositories/panjf2000/ants""}, ""html"": {""href"": ""https://bitbucket.org/panjf2000/ants""}, ""avatar"": {""href"": ""https://bytebucket.org/ravatar/%7Be762bff4-f795-49c6-b9f9-6ea334b6d964%7D?ts=default""}}, ""name"": ""ants"", ""uuid"": ""{e7 [...]
+34,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue"", ""id"": 28, ""repository"": {""type"": ""repository"", ""full_name"": ""panjf2000/ants"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/repositories/panjf2000/ants""}, ""html"": {""href"": ""https://bitbucket.org/panjf2000/ants""}, ""avatar"": {""href"": ""https://bytebucket.org/ravatar/%7Be762bff4-f795-49c6-b9f9-6ea334b6d964%7D?ts=default""}}, ""name"": ""ants"", ""uuid"": ""{e7 [...]
+35,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue"", ""id"": 26, ""repository"": {""type"": ""repository"", ""full_name"": ""panjf2000/ants"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/repositories/panjf2000/ants""}, ""html"": {""href"": ""https://bitbucket.org/panjf2000/ants""}, ""avatar"": {""href"": ""https://bytebucket.org/ravatar/%7Be762bff4-f795-49c6-b9f9-6ea334b6d964%7D?ts=default""}}, ""name"": ""ants"", ""uuid"": ""{e7 [...]
+36,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue"", ""id"": 25, ""repository"": {""type"": ""repository"", ""full_name"": ""panjf2000/ants"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/repositories/panjf2000/ants""}, ""html"": {""href"": ""https://bitbucket.org/panjf2000/ants""}, ""avatar"": {""href"": ""https://bytebucket.org/ravatar/%7Be762bff4-f795-49c6-b9f9-6ea334b6d964%7D?ts=default""}}, ""name"": ""ants"", ""uuid"": ""{e7 [...]
+37,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue"", ""id"": 6, ""repository"": {""type"": ""repository"", ""full_name"": ""panjf2000/ants"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/repositories/panjf2000/ants""}, ""html"": {""href"": ""https://bitbucket.org/panjf2000/ants""}, ""avatar"": {""href"": ""https://bytebucket.org/ravatar/%7Be762bff4-f795-49c6-b9f9-6ea334b6d964%7D?ts=default""}}, ""name"": ""ants"", ""uuid"": ""{e76 [...]
+38,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue"", ""id"": 24, ""repository"": {""type"": ""repository"", ""full_name"": ""panjf2000/ants"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/repositories/panjf2000/ants""}, ""html"": {""href"": ""https://bitbucket.org/panjf2000/ants""}, ""avatar"": {""href"": ""https://bytebucket.org/ravatar/%7Be762bff4-f795-49c6-b9f9-6ea334b6d964%7D?ts=default""}}, ""name"": ""ants"", ""uuid"": ""{e7 [...]
+39,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue"", ""id"": 23, ""repository"": {""type"": ""repository"", ""full_name"": ""panjf2000/ants"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/repositories/panjf2000/ants""}, ""html"": {""href"": ""https://bitbucket.org/panjf2000/ants""}, ""avatar"": {""href"": ""https://bytebucket.org/ravatar/%7Be762bff4-f795-49c6-b9f9-6ea334b6d964%7D?ts=default""}}, ""name"": ""ants"", ""uuid"": ""{e7 [...]
+40,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue"", ""id"": 22, ""repository"": {""type"": ""repository"", ""full_name"": ""panjf2000/ants"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/repositories/panjf2000/ants""}, ""html"": {""href"": ""https://bitbucket.org/panjf2000/ants""}, ""avatar"": {""href"": ""https://bytebucket.org/ravatar/%7Be762bff4-f795-49c6-b9f9-6ea334b6d964%7D?ts=default""}}, ""name"": ""ants"", ""uuid"": ""{e7 [...]
+41,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue"", ""id"": 21, ""repository"": {""type"": ""repository"", ""full_name"": ""panjf2000/ants"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/repositories/panjf2000/ants""}, ""html"": {""href"": ""https://bitbucket.org/panjf2000/ants""}, ""avatar"": {""href"": ""https://bytebucket.org/ravatar/%7Be762bff4-f795-49c6-b9f9-6ea334b6d964%7D?ts=default""}}, ""name"": ""ants"", ""uuid"": ""{e7 [...]
+42,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue"", ""id"": 20, ""repository"": {""type"": ""repository"", ""full_name"": ""panjf2000/ants"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/repositories/panjf2000/ants""}, ""html"": {""href"": ""https://bitbucket.org/panjf2000/ants""}, ""avatar"": {""href"": ""https://bytebucket.org/ravatar/%7Be762bff4-f795-49c6-b9f9-6ea334b6d964%7D?ts=default""}}, ""name"": ""ants"", ""uuid"": ""{e7 [...]
+43,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue"", ""id"": 19, ""repository"": {""type"": ""repository"", ""full_name"": ""panjf2000/ants"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/repositories/panjf2000/ants""}, ""html"": {""href"": ""https://bitbucket.org/panjf2000/ants""}, ""avatar"": {""href"": ""https://bytebucket.org/ravatar/%7Be762bff4-f795-49c6-b9f9-6ea334b6d964%7D?ts=default""}}, ""name"": ""ants"", ""uuid"": ""{e7 [...]
+44,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue"", ""id"": 18, ""repository"": {""type"": ""repository"", ""full_name"": ""panjf2000/ants"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/repositories/panjf2000/ants""}, ""html"": {""href"": ""https://bitbucket.org/panjf2000/ants""}, ""avatar"": {""href"": ""https://bytebucket.org/ravatar/%7Be762bff4-f795-49c6-b9f9-6ea334b6d964%7D?ts=default""}}, ""name"": ""ants"", ""uuid"": ""{e7 [...]
+45,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue"", ""id"": 17, ""repository"": {""type"": ""repository"", ""full_name"": ""panjf2000/ants"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/repositories/panjf2000/ants""}, ""html"": {""href"": ""https://bitbucket.org/panjf2000/ants""}, ""avatar"": {""href"": ""https://bytebucket.org/ravatar/%7Be762bff4-f795-49c6-b9f9-6ea334b6d964%7D?ts=default""}}, ""name"": ""ants"", ""uuid"": ""{e7 [...]
+46,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue"", ""id"": 16, ""repository"": {""type"": ""repository"", ""full_name"": ""panjf2000/ants"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/repositories/panjf2000/ants""}, ""html"": {""href"": ""https://bitbucket.org/panjf2000/ants""}, ""avatar"": {""href"": ""https://bytebucket.org/ravatar/%7Be762bff4-f795-49c6-b9f9-6ea334b6d964%7D?ts=default""}}, ""name"": ""ants"", ""uuid"": ""{e7 [...]
+47,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue"", ""id"": 15, ""repository"": {""type"": ""repository"", ""full_name"": ""panjf2000/ants"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/repositories/panjf2000/ants""}, ""html"": {""href"": ""https://bitbucket.org/panjf2000/ants""}, ""avatar"": {""href"": ""https://bytebucket.org/ravatar/%7Be762bff4-f795-49c6-b9f9-6ea334b6d964%7D?ts=default""}}, ""name"": ""ants"", ""uuid"": ""{e7 [...]
+48,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue"", ""id"": 14, ""repository"": {""type"": ""repository"", ""full_name"": ""panjf2000/ants"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/repositories/panjf2000/ants""}, ""html"": {""href"": ""https://bitbucket.org/panjf2000/ants""}, ""avatar"": {""href"": ""https://bytebucket.org/ravatar/%7Be762bff4-f795-49c6-b9f9-6ea334b6d964%7D?ts=default""}}, ""name"": ""ants"", ""uuid"": ""{e7 [...]
+49,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue"", ""id"": 13, ""repository"": {""type"": ""repository"", ""full_name"": ""panjf2000/ants"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/repositories/panjf2000/ants""}, ""html"": {""href"": ""https://bitbucket.org/panjf2000/ants""}, ""avatar"": {""href"": ""https://bytebucket.org/ravatar/%7Be762bff4-f795-49c6-b9f9-6ea334b6d964%7D?ts=default""}}, ""name"": ""ants"", ""uuid"": ""{e7 [...]
+50,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue"", ""id"": 12, ""repository"": {""type"": ""repository"", ""full_name"": ""panjf2000/ants"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/repositories/panjf2000/ants""}, ""html"": {""href"": ""https://bitbucket.org/panjf2000/ants""}, ""avatar"": {""href"": ""https://bytebucket.org/ravatar/%7Be762bff4-f795-49c6-b9f9-6ea334b6d964%7D?ts=default""}}, ""name"": ""ants"", ""uuid"": ""{e7 [...]
+51,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue"", ""id"": 11, ""repository"": {""type"": ""repository"", ""full_name"": ""panjf2000/ants"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/repositories/panjf2000/ants""}, ""html"": {""href"": ""https://bitbucket.org/panjf2000/ants""}, ""avatar"": {""href"": ""https://bytebucket.org/ravatar/%7Be762bff4-f795-49c6-b9f9-6ea334b6d964%7D?ts=default""}}, ""name"": ""ants"", ""uuid"": ""{e7 [...]
+52,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue"", ""id"": 10, ""repository"": {""type"": ""repository"", ""full_name"": ""panjf2000/ants"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/repositories/panjf2000/ants""}, ""html"": {""href"": ""https://bitbucket.org/panjf2000/ants""}, ""avatar"": {""href"": ""https://bytebucket.org/ravatar/%7Be762bff4-f795-49c6-b9f9-6ea334b6d964%7D?ts=default""}}, ""name"": ""ants"", ""uuid"": ""{e7 [...]
+53,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue"", ""id"": 9, ""repository"": {""type"": ""repository"", ""full_name"": ""panjf2000/ants"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/repositories/panjf2000/ants""}, ""html"": {""href"": ""https://bitbucket.org/panjf2000/ants""}, ""avatar"": {""href"": ""https://bytebucket.org/ravatar/%7Be762bff4-f795-49c6-b9f9-6ea334b6d964%7D?ts=default""}}, ""name"": ""ants"", ""uuid"": ""{e76 [...]
+54,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue"", ""id"": 8, ""repository"": {""type"": ""repository"", ""full_name"": ""panjf2000/ants"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/repositories/panjf2000/ants""}, ""html"": {""href"": ""https://bitbucket.org/panjf2000/ants""}, ""avatar"": {""href"": ""https://bytebucket.org/ravatar/%7Be762bff4-f795-49c6-b9f9-6ea334b6d964%7D?ts=default""}}, ""name"": ""ants"", ""uuid"": ""{e76 [...]
+55,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue"", ""id"": 7, ""repository"": {""type"": ""repository"", ""full_name"": ""panjf2000/ants"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/repositories/panjf2000/ants""}, ""html"": {""href"": ""https://bitbucket.org/panjf2000/ants""}, ""avatar"": {""href"": ""https://bytebucket.org/ravatar/%7Be762bff4-f795-49c6-b9f9-6ea334b6d964%7D?ts=default""}}, ""name"": ""ants"", ""uuid"": ""{e76 [...]
+56,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue"", ""id"": 5, ""repository"": {""type"": ""repository"", ""full_name"": ""panjf2000/ants"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/repositories/panjf2000/ants""}, ""html"": {""href"": ""https://bitbucket.org/panjf2000/ants""}, ""avatar"": {""href"": ""https://bytebucket.org/ravatar/%7Be762bff4-f795-49c6-b9f9-6ea334b6d964%7D?ts=default""}}, ""name"": ""ants"", ""uuid"": ""{e76 [...]
+57,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue"", ""id"": 4, ""repository"": {""type"": ""repository"", ""full_name"": ""panjf2000/ants"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/repositories/panjf2000/ants""}, ""html"": {""href"": ""https://bitbucket.org/panjf2000/ants""}, ""avatar"": {""href"": ""https://bytebucket.org/ravatar/%7Be762bff4-f795-49c6-b9f9-6ea334b6d964%7D?ts=default""}}, ""name"": ""ants"", ""uuid"": ""{e76 [...]
+58,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue"", ""id"": 3, ""repository"": {""type"": ""repository"", ""full_name"": ""panjf2000/ants"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/repositories/panjf2000/ants""}, ""html"": {""href"": ""https://bitbucket.org/panjf2000/ants""}, ""avatar"": {""href"": ""https://bytebucket.org/ravatar/%7Be762bff4-f795-49c6-b9f9-6ea334b6d964%7D?ts=default""}}, ""name"": ""ants"", ""uuid"": ""{e76 [...]
+59,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue"", ""id"": 2, ""repository"": {""type"": ""repository"", ""full_name"": ""panjf2000/ants"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/repositories/panjf2000/ants""}, ""html"": {""href"": ""https://bitbucket.org/panjf2000/ants""}, ""avatar"": {""href"": ""https://bytebucket.org/ravatar/%7Be762bff4-f795-49c6-b9f9-6ea334b6d964%7D?ts=default""}}, ""name"": ""ants"", ""uuid"": ""{e76 [...]
+60,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""issue"", ""id"": 1, ""repository"": {""type"": ""repository"", ""full_name"": ""panjf2000/ants"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/repositories/panjf2000/ants""}, ""html"": {""href"": ""https://bitbucket.org/panjf2000/ants""}, ""avatar"": {""href"": ""https://bytebucket.org/ravatar/%7Be762bff4-f795-49c6-b9f9-6ea334b6d964%7D?ts=default""}}, ""name"": ""ants"", ""uuid"": ""{e76 [...]
diff --git a/plugins/bitbucket/e2e/raw_tables/_raw_bitbucket_api_pull_requests.csv b/plugins/bitbucket/e2e/raw_tables/_raw_bitbucket_api_pull_requests.csv
new file mode 100644
index 00000000..45ad9fe3
--- /dev/null
+++ b/plugins/bitbucket/e2e/raw_tables/_raw_bitbucket_api_pull_requests.csv
@@ -0,0 +1,58 @@
+id,params,data,url,input,created_at
+115,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 2, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 40, ""title"": ""Test016"", ""description"": ""* feat: add test01\n* feat: add test02\n* feat: add test03\n* feat: add test04\n* feat: add test05\n* feat: add test06\n* feat: add test07\n* feat: add test08\n* feat: add test09\n* feat: add test010\n* feat: add test011\n* feat: add test012\n* feat: add test013\n* feat: add test014\n* feat: add t [...]
+116,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 4, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 54, ""title"": ""Bitbuckettest19"", ""description"": ""* feat: add test01\n* feat: add test02\n* feat: add test03\n* feat: add test04\n* feat: add test05\n* feat: add test06\n* feat: add test07\n* feat: add test08\n* feat: add test09\n* feat: add test010\n* feat: add test011\n* feat: add test012\n* feat: add test013\n* feat: add test014\n* fea [...]
+117,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 4, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 42, ""title"": ""Test019"", ""description"": ""* feat: add test01\n* feat: add test02\n* feat: add test03\n* feat: add test04\n* feat: add test05\n* feat: add test06\n* feat: add test07\n* feat: add test08\n* feat: add test09\n* feat: add test010\n* feat: add test011\n* feat: add test012\n* feat: add test013\n* feat: add test014\n* feat: add t [...]
+118,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 3, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 31, ""title"": ""Test020"", ""description"": ""* feat: add test01\n* feat: add test02\n* feat: add test03\n* feat: add test04\n* feat: add test05\n* feat: add test06\n* feat: add test07\n* feat: add test08\n* feat: add test09\n* feat: add test010\n* feat: add test011\n* feat: add test012\n* feat: add test013\n* feat: add test014\n* feat: add t [...]
+119,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 1, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 41, ""title"": ""Test018"", ""description"": ""* feat: add test01\n* feat: add test02\n* feat: add test03\n* feat: add test04\n* feat: add test05\n* feat: add test06\n* feat: add test07\n* feat: add test08\n* feat: add test09\n* feat: add test010\n* feat: add test011\n* feat: add test012\n* feat: add test013\n* feat: add test014\n* feat: add t [...]
+120,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 2, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 44, ""title"": ""Test017"", ""description"": ""* feat: add test01\n* feat: add test02\n* feat: add test03\n* feat: add test04\n* feat: add test05\n* feat: add test06\n* feat: add test07\n* feat: add test08\n* feat: add test09\n* feat: add test010\n* feat: add test011\n* feat: add test012\n* feat: add test013\n* feat: add test014\n* feat: add t [...]
+121,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 2, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 38, ""title"": ""Test029"", ""description"": ""* feat: add test01\n* feat: add test02\n* feat: add test03\n* feat: add test04\n* feat: add test05\n* feat: add test06\n* feat: add test07\n* feat: add test08\n* feat: add test09\n* feat: add test010\n* feat: add test011\n* feat: add test012\n* feat: add test013\n* feat: add test014\n* feat: add t [...]
+122,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 2, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 51, ""title"": ""Bitbuckettest15"", ""description"": ""* feat: add test01\n* feat: add test02\n* feat: add test03\n* feat: add test04\n* feat: add test05\n* feat: add test06\n* feat: add test07\n* feat: add test08\n* feat: add test09\n* feat: add test010\n* feat: add test011\n* feat: add test012\n* feat: add test013\n* feat: add test014\n* fea [...]
+123,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 2, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 57, ""title"": ""Bitbuckettest22"", ""description"": ""* feat: add test01\n* feat: add test02\n* feat: add test03\n* feat: add test04\n* feat: add test05\n* feat: add test06\n* feat: add test07\n* feat: add test08\n* feat: add test09\n* feat: add test010\n* feat: add test011\n* feat: add test012\n* feat: add test013\n* feat: add test014\n* fea [...]
+124,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 0, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 56, ""title"": ""Bitbuckettest25"", ""description"": ""* feat: add test01\n* feat: add test02\n* feat: add test03\n* feat: add test04\n* feat: add test05\n* feat: add test06\n* feat: add test07\n* feat: add test08\n* feat: add test09\n* feat: add test010\n* feat: add test011\n* feat: add test012\n* feat: add test013\n* feat: add test014\n* fea [...]
+125,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 0, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 53, ""title"": ""Bitbuckettest17"", ""description"": ""* feat: add test01\n* feat: add test02\n* feat: add test03\n* feat: add test04\n* feat: add test05\n* feat: add test06\n* feat: add test07\n* feat: add test08\n* feat: add test09\n* feat: add test010\n* feat: add test011\n* feat: add test012\n* feat: add test013\n* feat: add test014\n* fea [...]
+126,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 0, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 55, ""title"": ""Bitbuckettest13"", ""description"": ""* feat: add test01\n* feat: add test02\n* feat: add test03\n* feat: add test04\n* feat: add test05\n* feat: add test06\n* feat: add test07\n* feat: add test08\n* feat: add test09\n* feat: add test010\n* feat: add test011\n* feat: add test012\n* feat: add test013\n* feat: add test014\n* fea [...]
+127,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 0, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 52, ""title"": ""Bitbuckettest16"", ""description"": ""* feat: add test01\n* feat: add test02\n* feat: add test03\n* feat: add test04\n* feat: add test05\n* feat: add test06\n* feat: add test07\n* feat: add test08\n* feat: add test09\n* feat: add test010\n* feat: add test011\n* feat: add test012\n* feat: add test013\n* feat: add test014\n* fea [...]
+128,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 0, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 50, ""title"": ""Bitbuckettest12"", ""description"": ""* feat: add test01\n* feat: add test02\n* feat: add test03\n* feat: add test04\n* feat: add test05\n* feat: add test06\n* feat: add test07\n* feat: add test08\n* feat: add test09\n* feat: add test010\n* feat: add test011\n* feat: add test012\n* feat: add test013\n* feat: add test014\n* fea [...]
+129,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 0, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 49, ""title"": ""Test08"", ""description"": ""* feat: add test01\n* feat: add test02\n* feat: add test03\n* feat: add test04\n* feat: add test05\n* feat: add test06\n* feat: add test07\n* feat: add test08\n\n‌"", ""state"": ""OPEN"", ""merge_commit"": null, ""close_source_branch"": false, ""closed_by"": null, ""author"": {""display_name"": ""t [...]
+130,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 0, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 48, ""title"": ""Test07"", ""description"": ""* feat: add test01\n* feat: add test02\n* feat: add test03\n* feat: add test04\n* feat: add test05\n* feat: add test06\n* feat: add test07\n\n‌"", ""state"": ""OPEN"", ""merge_commit"": null, ""close_source_branch"": false, ""closed_by"": null, ""author"": {""display_name"": ""teoiaoe"", ""links"": [...]
+131,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 0, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 47, ""title"": ""Test06"", ""description"": ""* feat: add test01\n* feat: add test02\n* feat: add test03\n* feat: add test04\n* feat: add test05\n* feat: add test06\n\n‌"", ""state"": ""OPEN"", ""merge_commit"": null, ""close_source_branch"": false, ""closed_by"": null, ""author"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href" [...]
+132,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 0, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 29, ""title"": ""Test03"", ""description"": ""* feat: add test01\n* feat: add test02\n* feat: add test03\n\n‌"", ""state"": ""OPEN"", ""merge_commit"": null, ""close_source_branch"": false, ""closed_by"": null, ""author"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-42 [...]
+133,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 0, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 46, ""title"": ""Test04"", ""description"": ""* feat: add test01\n* feat: add test02\n* feat: add test03\n* feat: add test04\n\n‌"", ""state"": ""OPEN"", ""merge_commit"": null, ""close_source_branch"": false, ""closed_by"": null, ""author"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users [...]
+134,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 0, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 45, ""title"": ""feat: add test01"", ""description"": """", ""state"": ""OPEN"", ""merge_commit"": null, ""close_source_branch"": false, ""closed_by"": null, ""author"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D""}, ""avatar"": {""href"": "" [...]
+135,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 0, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 43, ""title"": ""Test015"", ""description"": ""* feat: add test01\n* feat: add test02\n* feat: add test03\n* feat: add test04\n* feat: add test05\n* feat: add test06\n* feat: add test07\n* feat: add test08\n* feat: add test09\n* feat: add test010\n* feat: add test011\n* feat: add test012\n* feat: add test013\n* feat: add test014\n* feat: add t [...]
+136,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 0, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 39, ""title"": ""Test030"", ""description"": ""* feat: add test01\n* feat: add test02\n* feat: add test03\n* feat: add test04\n* feat: add test05\n* feat: add test06\n* feat: add test07\n* feat: add test08\n* feat: add test09\n* feat: add test010\n* feat: add test011\n* feat: add test012\n* feat: add test013\n* feat: add test014\n* feat: add t [...]
+137,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 0, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 37, ""title"": ""Test028"", ""description"": ""* feat: add test01\n* feat: add test02\n* feat: add test03\n* feat: add test04\n* feat: add test05\n* feat: add test06\n* feat: add test07\n* feat: add test08\n* feat: add test09\n* feat: add test010\n* feat: add test011\n* feat: add test012\n* feat: add test013\n* feat: add test014\n* feat: add t [...]
+138,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 0, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 36, ""title"": ""Test027"", ""description"": ""* feat: add test01\n* feat: add test02\n* feat: add test03\n* feat: add test04\n* feat: add test05\n* feat: add test06\n* feat: add test07\n* feat: add test08\n* feat: add test09\n* feat: add test010\n* feat: add test011\n* feat: add test012\n* feat: add test013\n* feat: add test014\n* feat: add t [...]
+139,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 0, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 35, ""title"": ""Test025"", ""description"": ""* feat: add test01\n* feat: add test02\n* feat: add test03\n* feat: add test04\n* feat: add test05\n* feat: add test06\n* feat: add test07\n* feat: add test08\n* feat: add test09\n* feat: add test010\n* feat: add test011\n* feat: add test012\n* feat: add test013\n* feat: add test014\n* feat: add t [...]
+140,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 0, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 34, ""title"": ""Test024"", ""description"": ""* feat: add test01\n* feat: add test02\n* feat: add test03\n* feat: add test04\n* feat: add test05\n* feat: add test06\n* feat: add test07\n* feat: add test08\n* feat: add test09\n* feat: add test010\n* feat: add test011\n* feat: add test012\n* feat: add test013\n* feat: add test014\n* feat: add t [...]
+141,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 0, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 33, ""title"": ""Test023"", ""description"": ""* feat: add test01\n* feat: add test02\n* feat: add test03\n* feat: add test04\n* feat: add test05\n* feat: add test06\n* feat: add test07\n* feat: add test08\n* feat: add test09\n* feat: add test010\n* feat: add test011\n* feat: add test012\n* feat: add test013\n* feat: add test014\n* feat: add t [...]
+142,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 0, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 32, ""title"": ""Test022"", ""description"": ""* feat: add test01\n* feat: add test02\n* feat: add test03\n* feat: add test04\n* feat: add test05\n* feat: add test06\n* feat: add test07\n* feat: add test08\n* feat: add test09\n* feat: add test010\n* feat: add test011\n* feat: add test012\n* feat: add test013\n* feat: add test014\n* feat: add t [...]
+143,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 0, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 30, ""title"": ""Test05"", ""description"": ""* feat: add test01\n* feat: add test02\n* feat: add test03\n* feat: add test04\n* feat: add test05\n\n‌"", ""state"": ""OPEN"", ""merge_commit"": null, ""close_source_branch"": false, ""closed_by"": null, ""author"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bit [...]
+144,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 0, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 24, ""title"": ""Test17"", ""description"": ""* feat: add git.sh\n* feat: add test001\n* feat: test002\n* feat: add test003\n* feat: add test004\n* feat: add test005\n* feat: add test006\n* feat: add test007\n* feat: add test008\n* feat: add test009\n* feat: add test010\n* feat: add test011\n* feat: add test012\n* feat: add test013\n* feat: ad [...]
+145,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 0, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 23, ""title"": ""Test20"", ""description"": ""* feat: add git.sh\n* feat: add test001\n* feat: test002\n* feat: add test003\n* feat: add test004\n* feat: add test005\n* feat: add test006\n* feat: add test007\n* feat: add test008\n* feat: add test009\n* feat: add test010\n* feat: add test011\n* feat: add test012\n* feat: add test013\n* feat: ad [...]
+146,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 0, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 22, ""title"": ""Test19"", ""description"": ""* feat: add git.sh\n* feat: add test001\n* feat: test002\n* feat: add test003\n* feat: add test004\n* feat: add test005\n* feat: add test006\n* feat: add test007\n* feat: add test008\n* feat: add test009\n* feat: add test010\n* feat: add test011\n* feat: add test012\n* feat: add test013\n* feat: ad [...]
+147,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 0, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 21, ""title"": ""Test18"", ""description"": ""* feat: add git.sh\n* feat: add test001\n* feat: test002\n* feat: add test003\n* feat: add test004\n* feat: add test005\n* feat: add test006\n* feat: add test007\n* feat: add test008\n* feat: add test009\n* feat: add test010\n* feat: add test011\n* feat: add test012\n* feat: add test013\n* feat: ad [...]
+148,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 0, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 20, ""title"": ""Test16"", ""description"": ""* feat: add git.sh\n* feat: add test001\n* feat: test002\n* feat: add test003\n* feat: add test004\n* feat: add test005\n* feat: add test006\n* feat: add test007\n* feat: add test008\n* feat: add test009\n* feat: add test010\n* feat: add test011\n* feat: add test012\n* feat: add test013\n* feat: ad [...]
+149,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 0, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 19, ""title"": ""Test15"", ""description"": ""* feat: add git.sh\n* feat: add test001\n* feat: test002\n* feat: add test003\n* feat: add test004\n* feat: add test005\n* feat: add test006\n* feat: add test007\n* feat: add test008\n* feat: add test009\n* feat: add test010\n* feat: add test011\n* feat: add test012\n* feat: add test013\n* feat: ad [...]
+150,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 0, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 18, ""title"": ""Test14"", ""description"": ""* feat: add git.sh\n* feat: add test001\n* feat: test002\n* feat: add test003\n* feat: add test004\n* feat: add test005\n* feat: add test006\n* feat: add test007\n* feat: add test008\n* feat: add test009\n* feat: add test010\n* feat: add test011\n* feat: add test012\n* feat: add test013\n* feat: ad [...]
+151,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 0, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 17, ""title"": ""Test13"", ""description"": ""* feat: add git.sh\n* feat: add test001\n* feat: test002\n* feat: add test003\n* feat: add test004\n* feat: add test005\n* feat: add test006\n* feat: add test007\n* feat: add test008\n* feat: add test009\n* feat: add test010\n* feat: add test011\n* feat: add test012\n* feat: add test013\n* feat: ad [...]
+152,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 0, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 28, ""title"": ""mergev1"", ""description"": ""merge all v1"", ""state"": ""MERGED"", ""merge_commit"": {""type"": ""commit"", ""hash"": ""c0e12b61e44b"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/repositories/panjf2000/ants/commit/c0e12b61e44b""}, ""html"": {""href"": ""https://bitbucket.org/panjf2000/ants/commits/c0e12 [...]
+153,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 0, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 27, ""title"": ""4"", ""description"": ""* feat: add git.sh\n* feat: add test001\n* feat: test002\n* feat: add test003\n* feat: add test004\n* feat: add test005\n* feat: add test006\n* feat: add test007\n* feat: add test008\n* feat: add test009\n* feat: add test010\n* feat: add test011\n* feat: add test012\n* feat: add test013\n* feat: add bra [...]
+154,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 0, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 26, ""title"": ""2"", ""description"": ""* feat: add git.sh\n* feat: add test001\n* feat: test002\n* feat: add test003\n* feat: add test004\n* feat: add test005\n* feat: add test006\n* feat: add test007\n* feat: add test008\n* feat: add test009\n* feat: add test010\n* feat: add test011\n* feat: add test012\n* feat: add test013\n* feat: add bra [...]
+155,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 0, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 25, ""title"": ""1"", ""description"": ""* feat: add git.sh\n* feat: add test001\n* feat: test002\n* feat: add test003\n* feat: add test004\n* feat: add test005\n* feat: add test006\n* feat: add test007\n* feat: add test008\n* feat: add test009\n* feat: add test010\n* feat: add test011\n* feat: add test012\n* feat: add test013\n* feat: add bra [...]
+156,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 0, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 15, ""title"": ""Test011"", ""description"": ""* feat: add git.sh\n* feat: add test001\n* feat: test002\n* feat: add test003\n* feat: add test004\n* feat: add test005\n* feat: add test006\n* feat: add test007\n* feat: add test008\n* feat: add test009\n* feat: add test010\n* feat: add test011\n\n‌"", ""state"": ""MERGED"", ""merge_commit"": {"" [...]
+157,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 0, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 14, ""title"": ""Test10"", ""description"": ""* feat: add git.sh\n* feat: add test001\n* feat: test002\n* feat: add test003\n* feat: add test004\n* feat: add test005\n* feat: add test006\n* feat: add test007\n* feat: add test008\n* feat: add test009\n* feat: add test010\n* feat: add test011\n* feat: add test012\n* feat: add test013\n* feat: ad [...]
+158,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 0, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 13, ""title"": ""Test8"", ""description"": ""* feat: add git.sh\n* feat: add test001\n* feat: test002\n* feat: add test003\n* feat: add test004\n* feat: add test005\n* feat: add test006\n* feat: add test007\n* feat: add test008\n* feat: add test009\n* feat: add test010\n* feat: add test011\n* feat: add test012\n* feat: add test013\n* feat: add [...]
+159,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 0, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 12, ""title"": ""Test7"", ""description"": ""* feat: add git.sh\n* feat: add test001\n* feat: test002\n* feat: add test003\n* feat: add test004\n* feat: add test005\n* feat: add test006\n* feat: add test007\n* feat: add test008\n* feat: add test009\n* feat: add test010\n* feat: add test011\n* feat: add test012\n* feat: add test013\n* feat: add [...]
+160,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 0, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 11, ""title"": ""Test6"", ""description"": ""* feat: add git.sh\n* feat: add test001\n* feat: test002\n* feat: add test003\n* feat: add test004\n* feat: add test005\n* feat: add test006\n* feat: add test007\n* feat: add test008\n* feat: add test009\n* feat: add test010\n* feat: add test011\n* feat: add test012\n* feat: add test013\n* feat: add [...]
+161,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 0, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 10, ""title"": ""Test007"", ""description"": ""* feat: add git.sh\n* feat: add test001\n* feat: test002\n* feat: add test003\n* feat: add test004\n* feat: add test005\n* feat: add test006\n* feat: add test007\n\n‌"", ""state"": ""MERGED"", ""merge_commit"": {""type"": ""commit"", ""hash"": ""983edbf06740"", ""links"": {""self"": {""href"": ""h [...]
+162,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 0, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 9, ""title"": ""Test006"", ""description"": ""* feat: add git.sh\n* feat: add test001\n* feat: test002\n* feat: add test003\n* feat: add test004\n* feat: add test005\n* feat: add test006\n\n‌"", ""state"": ""MERGED"", ""merge_commit"": {""type"": ""commit"", ""hash"": ""983edbf06740"", ""links"": {""self"": {""href"": ""https://api.bitbucket.o [...]
+163,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 0, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 8, ""title"": ""Test005"", ""description"": ""* feat: add git.sh\n* feat: add test001\n* feat: test002\n* feat: add test003\n* feat: add test004\n* feat: add test005\n\n‌"", ""state"": ""MERGED"", ""merge_commit"": {""type"": ""commit"", ""hash"": ""983edbf06740"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/repositories/p [...]
+164,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 0, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 7, ""title"": ""Test004"", ""description"": ""* feat: add git.sh\n* feat: add test001\n* feat: test002\n* feat: add test003\n* feat: add test004\n\n‌"", ""state"": ""MERGED"", ""merge_commit"": {""type"": ""commit"", ""hash"": ""983edbf06740"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/repositories/panjf2000/ants/commit/ [...]
+165,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 0, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 6, ""title"": ""Test003"", ""description"": ""* feat: add git.sh\n* feat: add test001\n* feat: test002\n* feat: add test003\n\n‌"", ""state"": ""MERGED"", ""merge_commit"": {""type"": ""commit"", ""hash"": ""983edbf06740"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/repositories/panjf2000/ants/commit/983edbf06740""}, ""ht [...]
+166,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 0, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 5, ""title"": ""Test002"", ""description"": ""* feat: add git.sh\n* feat: add test001\n* feat: test002\n\n‌"", ""state"": ""MERGED"", ""merge_commit"": {""type"": ""commit"", ""hash"": ""983edbf06740"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/repositories/panjf2000/ants/commit/983edbf06740""}, ""html"": {""href"": ""ht [...]
+167,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 0, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 4, ""title"": ""Test001"", ""description"": ""* feat: add git.sh\n* feat: add test001\n\n‌"", ""state"": ""MERGED"", ""merge_commit"": {""type"": ""commit"", ""hash"": ""983edbf06740"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/repositories/panjf2000/ants/commit/983edbf06740""}, ""html"": {""href"": ""https://bitbucket.o [...]
+168,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 0, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 3, ""title"": ""Test9"", ""description"": ""* feat: add git.sh\n* feat: add test001\n* feat: test002\n* feat: add test003\n* feat: add test004\n* feat: add test005\n* feat: add test006\n* feat: add test007\n* feat: add test008\n* feat: add test009\n* feat: add test010\n* feat: add test011\n* feat: add test012\n* feat: add test013\n* feat: add  [...]
+169,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 0, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 2, ""title"": ""feat: add git.sh"", ""description"": ""help to git commit faster"", ""state"": ""MERGED"", ""merge_commit"": {""type"": ""commit"", ""hash"": ""983edbf06740"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/repositories/panjf2000/ants/commit/983edbf06740""}, ""html"": {""href"": ""https://bitbucket.org/panjf20 [...]
+170,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 0, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 16, ""title"": ""Test12"", ""description"": ""* feat: add git.sh\n* feat: add test001\n* feat: test002\n* feat: add test003\n* feat: add test004\n* feat: add test005\n* feat: add test006\n* feat: add test007\n* feat: add test008\n* feat: add test009\n* feat: add test010\n* feat: add test011\n* feat: add test012\n* feat: add test013\n* feat: ad [...]
+171,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""comment_count"": 2, ""task_count"": 0, ""type"": ""pullrequest"", ""id"": 1, ""title"": ""feat: add pr test"", ""description"": ""this is a pr test for Bitbucket plugin"", ""state"": ""OPEN"", ""merge_commit"": null, ""close_source_branch"": false, ""closed_by"": null, ""author"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-4297-99b1-21827e0 [...]
\ No newline at end of file
diff --git a/plugins/bitbucket/e2e/raw_tables/_raw_bitbucket_api_pullrequest_comments.csv b/plugins/bitbucket/e2e/raw_tables/_raw_bitbucket_api_pullrequest_comments.csv
new file mode 100644
index 00000000..c88e22af
--- /dev/null
+++ b/plugins/bitbucket/e2e/raw_tables/_raw_bitbucket_api_pullrequest_comments.csv
@@ -0,0 +1,19 @@
+id,params,data,url,input,created_at
+1,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""id"": 323120278, ""created_on"": ""2022-08-12T15:40:01.755214+00:00"", ""updated_on"": ""2022-08-12T15:40:01.755276+00:00"", ""content"": {""type"": ""rendered"", ""raw"": ""baroboerhba"", ""markup"": ""markdown"", ""html"": ""<p>baroboerhba</p>""}, ""user"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D""}, ""avatar"": [...]
+2,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""id"": 323120296, ""created_on"": ""2022-08-12T15:40:07.757075+00:00"", ""updated_on"": ""2022-08-12T15:40:07.757120+00:00"", ""content"": {""type"": ""rendered"", ""raw"": ""bweiwbeanb"", ""markup"": ""markdown"", ""html"": ""<p>bweiwbeanb</p>""}, ""user"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D""}, ""avatar"": { [...]
+3,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""id"": 323120311, ""created_on"": ""2022-08-12T15:40:12.401207+00:00"", ""updated_on"": ""2022-08-12T15:40:12.401282+00:00"", ""content"": {""type"": ""rendered"", ""raw"": ""jbirobsore"", ""markup"": ""markdown"", ""html"": ""<p>jbirobsore</p>""}, ""user"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D""}, ""avatar"": { [...]
+4,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""id"": 323119960, ""created_on"": ""2022-08-12T15:38:26.895025+00:00"", ""updated_on"": ""2022-08-12T15:38:26.895092+00:00"", ""content"": {""type"": ""rendered"", ""raw"": ""regrioteothro"", ""markup"": ""markdown"", ""html"": ""<p>regrioteothro</p>""}, ""user"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D""}, ""avata [...]
+5,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""id"": 323119980, ""created_on"": ""2022-08-12T15:38:31.110923+00:00"", ""updated_on"": ""2022-08-12T15:38:31.110990+00:00"", ""content"": {""type"": ""rendered"", ""raw"": ""goeotbioebhotn"", ""markup"": ""markdown"", ""html"": ""<p>goeotbioebhotn</p>""}, ""user"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D""}, ""ava [...]
+6,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""id"": 323120140, ""created_on"": ""2022-08-12T15:39:27.438543+00:00"", ""updated_on"": ""2022-08-12T15:39:27.438603+00:00"", ""content"": {""type"": ""rendered"", ""raw"": ""evbnoera"", ""markup"": ""markdown"", ""html"": ""<p>evbnoera</p>""}, ""user"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D""}, ""avatar"": {""hr [...]
+7,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""id"": 323120196, ""created_on"": ""2022-08-12T15:39:41.750361+00:00"", ""updated_on"": ""2022-08-12T15:39:41.750414+00:00"", ""content"": {""type"": ""rendered"", ""raw"": ""vobreia"", ""markup"": ""markdown"", ""html"": ""<p>vobreia</p>""}, ""user"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D""}, ""avatar"": {""href [...]
+8,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""id"": 323119842, ""created_on"": ""2022-08-12T15:37:51.356670+00:00"", ""updated_on"": ""2022-08-12T15:37:51.356716+00:00"", ""content"": {""type"": ""rendered"", ""raw"": ""feafoegoaweoir"", ""markup"": ""markdown"", ""html"": ""<p>feafoegoaweoir</p>""}, ""user"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D""}, ""ava [...]
+9,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""id"": 323119856, ""created_on"": ""2022-08-12T15:37:56.276961+00:00"", ""updated_on"": ""2022-08-12T15:37:56.277012+00:00"", ""content"": {""type"": ""rendered"", ""raw"": ""boroehruheorefe"", ""markup"": ""markdown"", ""html"": ""<p>boroehruheorefe</p>""}, ""user"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D""}, ""a [...]
+10,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""id"": 323120091, ""created_on"": ""2022-08-12T15:39:11.612223+00:00"", ""updated_on"": ""2022-08-12T15:39:11.612271+00:00"", ""content"": {""type"": ""rendered"", ""raw"": ""feawrjoiw"", ""markup"": ""markdown"", ""html"": ""<p>feawrjoiw</p>""}, ""user"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D""}, ""avatar"": {" [...]
+11,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""id"": 323120101, ""created_on"": ""2022-08-12T15:39:15.632407+00:00"", ""updated_on"": ""2022-08-12T15:39:15.632461+00:00"", ""content"": {""type"": ""rendered"", ""raw"": ""bbeirobeoiahoa"", ""markup"": ""markdown"", ""html"": ""<p>bbeirobeoiahoa</p>""}, ""user"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D""}, ""av [...]
+12,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""id"": 323119784, ""created_on"": ""2022-08-12T15:37:36.308815+00:00"", ""updated_on"": ""2022-08-12T15:37:36.308866+00:00"", ""content"": {""type"": ""rendered"", ""raw"": ""fejoafefewa"", ""markup"": ""markdown"", ""html"": ""<p>fejoafefewa</p>""}, ""user"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D""}, ""avatar"" [...]
+13,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""id"": 323119790, ""created_on"": ""2022-08-12T15:37:40.769308+00:00"", ""updated_on"": ""2022-08-12T15:37:40.769367+00:00"", ""content"": {""type"": ""rendered"", ""raw"": ""feafeogioehrw"", ""markup"": ""markdown"", ""html"": ""<p>feafeogioehrw</p>""}, ""user"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D""}, ""avat [...]
+14,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""id"": 323119643, ""created_on"": ""2022-08-12T15:36:49.030226+00:00"", ""updated_on"": ""2022-08-12T15:36:49.030284+00:00"", ""content"": {""type"": ""rendered"", ""raw"": ""this is test014"", ""markup"": ""markdown"", ""html"": ""<p>this is test014</p>""}, ""user"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D""}, "" [...]
+15,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""id"": 323119662, ""created_on"": ""2022-08-12T15:36:53.393567+00:00"", ""updated_on"": ""2022-08-12T15:36:53.393609+00:00"", ""content"": {""type"": ""rendered"", ""raw"": ""feafjae"", ""markup"": ""markdown"", ""html"": ""<p>feafjae</p>""}, ""user"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D""}, ""avatar"": {""hre [...]
+16,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""id"": 323119897, ""created_on"": ""2022-08-12T15:38:11.179587+00:00"", ""updated_on"": ""2022-08-12T15:38:11.179637+00:00"", ""content"": {""type"": ""rendered"", ""raw"": ""feajfweofjwvgrea"", ""markup"": ""markdown"", ""html"": ""<p>feajfweofjwvgrea</p>""}, ""user"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D""},  [...]
+17,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""id"": 323119730, ""created_on"": ""2022-08-12T15:37:16.879523+00:00"", ""updated_on"": ""2022-08-12T15:37:16.879578+00:00"", ""content"": {""type"": ""rendered"", ""raw"": ""fejoiafjoej\n\n‌"", ""markup"": ""markdown"", ""html"": ""<p>fejoiafjoej</p>\n<p>‌</p>""}, ""user"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D [...]
+18,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""id"": 323119743, ""created_on"": ""2022-08-12T15:37:21.558078+00:00"", ""updated_on"": ""2022-08-12T15:37:21.558120+00:00"", ""content"": {""type"": ""rendered"", ""raw"": ""fjeafojeoirjgoar"", ""markup"": ""markdown"", ""html"": ""<p>fjeafojeoirjgoar</p>""}, ""user"": {""display_name"": ""teoiaoe"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/users/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D""},  [...]
diff --git a/plugins/bitbucket/e2e/raw_tables/_raw_bitbucket_api_repositories.csv b/plugins/bitbucket/e2e/raw_tables/_raw_bitbucket_api_repositories.csv
new file mode 100644
index 00000000..9ff1bbbf
--- /dev/null
+++ b/plugins/bitbucket/e2e/raw_tables/_raw_bitbucket_api_repositories.csv
@@ -0,0 +1,3 @@
+id,params,data,url,input,created_at
+2,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}","{""type"": ""repository"", ""full_name"": ""panjf2000/ants"", ""links"": {""self"": {""href"": ""https://api.bitbucket.org/2.0/repositories/panjf2000/ants""}, ""html"": {""href"": ""https://bitbucket.org/panjf2000/ants""}, ""avatar"": {""href"": ""https://bytebucket.org/ravatar/%7Be762bff4-f795-49c6-b9f9-6ea334b6d964%7D?ts=default""}, ""pullrequests"": {""href"": ""https://api.bitbucket.org/2.0/repositories/panjf2000/ant [...]
+
diff --git a/plugins/bitbucket/e2e/repo_test.go b/plugins/bitbucket/e2e/repo_test.go
new file mode 100644
index 00000000..2de4bc32
--- /dev/null
+++ b/plugins/bitbucket/e2e/repo_test.go
@@ -0,0 +1,138 @@
+/*
+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 (
+	"fmt"
+	"testing"
+
+	"github.com/apache/incubator-devlake/models/domainlayer/code"
+	"github.com/apache/incubator-devlake/models/domainlayer/ticket"
+	"github.com/apache/incubator-devlake/plugins/bitbucket/models"
+
+	"github.com/apache/incubator-devlake/helpers/e2ehelper"
+	"github.com/apache/incubator-devlake/plugins/bitbucket/impl"
+	"github.com/apache/incubator-devlake/plugins/bitbucket/tasks"
+)
+
+func TestRepoDataFlow(t *testing.T) {
+	var plugin impl.Bitbucket
+	dataflowTester := e2ehelper.NewDataFlowTester(t, "bitbucket", plugin)
+
+	bitbucketRepository := &models.BitbucketRepo{
+		BitbucketId: "panjf2000/ants",
+	}
+	taskData := &tasks.BitbucketTaskData{
+		Options: &tasks.BitbucketOptions{
+			ConnectionId: 1,
+			Owner:        "panjf2000",
+			Repo:         "ants",
+			TransformationRules: models.TransformationRules{
+				PrType:      "type/(.*)$",
+				PrComponent: "component/(.*)$",
+			},
+		},
+		Repo: bitbucketRepository,
+	}
+
+	// import raw data table
+	dataflowTester.ImportCsvIntoRawTable("./raw_tables/_raw_bitbucket_api_repositories.csv", "_raw_bitbucket_api_repositories")
+
+	// verify extraction
+	dataflowTester.FlushTabler(&models.BitbucketRepo{})
+	dataflowTester.FlushTabler(&models.BitbucketAccount{})
+	dataflowTester.Subtask(tasks.ExtractApiRepoMeta, taskData)
+	dataflowTester.VerifyTable(
+		models.BitbucketRepo{},
+		fmt.Sprintf("./snapshot_tables/%s.csv", models.BitbucketRepo{}.TableName()),
+		[]string{
+			"connection_id",
+			"bitbucket_id",
+			"name",
+			"html_url",
+			"description",
+			"owner_id",
+			"language",
+			"created_date",
+			"updated_date",
+			"_raw_data_params",
+			"_raw_data_table",
+			"_raw_data_id",
+			"_raw_data_remark",
+		},
+	)
+	dataflowTester.VerifyTable(
+		models.BitbucketAccount{},
+		fmt.Sprintf("./snapshot_tables/%s.csv", models.BitbucketAccount{}.TableName()),
+		[]string{
+			"connection_id",
+			"user_name",
+			"account_id",
+			"account_status",
+			"display_name",
+			"avatar_url",
+			"html_url",
+			"uuid",
+			"has2_fa_enabled",
+			"_raw_data_params",
+			"_raw_data_table",
+			"_raw_data_id",
+			"_raw_data_remark",
+		},
+	)
+
+	// verify extraction
+	dataflowTester.FlushTabler(&code.Repo{})
+	dataflowTester.FlushTabler(&ticket.Board{})
+	dataflowTester.Subtask(tasks.ConvertRepoMeta, taskData)
+	dataflowTester.VerifyTable(
+		code.Repo{},
+		fmt.Sprintf("./snapshot_tables/%s.csv", code.Repo{}.TableName()),
+		[]string{
+			"id",
+			"_raw_data_params",
+			"_raw_data_table",
+			"_raw_data_id",
+			"_raw_data_remark",
+			"name",
+			"url",
+			"description",
+			"owner_id",
+			"language",
+			"forked_from",
+			"created_date",
+			"updated_date",
+			"deleted",
+		},
+	)
+	dataflowTester.VerifyTable(
+		ticket.Board{},
+		fmt.Sprintf("./snapshot_tables/%s.csv", ticket.Board{}.TableName()),
+		[]string{
+			"id",
+			"_raw_data_params",
+			"_raw_data_table",
+			"_raw_data_id",
+			"_raw_data_remark",
+			"name",
+			"description",
+			"url",
+			"created_date",
+		},
+	)
+}
diff --git a/plugins/bitbucket/e2e/snapshot_tables/_tool_bitbucket_accounts.csv b/plugins/bitbucket/e2e/snapshot_tables/_tool_bitbucket_accounts.csv
new file mode 100644
index 00000000..6665d105
--- /dev/null
+++ b/plugins/bitbucket/e2e/snapshot_tables/_tool_bitbucket_accounts.csv
@@ -0,0 +1,2 @@
+connection_id,account_id,user_name,account_status,display_name,avatar_url,html_url,uuid,has2_fa_enabled,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark
+1,62abf394192edb006fa0e8cf,,,teoiaoe,https://secure.gravatar.com/avatar/d37e5c64cd007c5c20654af064c3f410?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FT-0.png,https://bitbucket.org/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D/,,0,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,171,
diff --git a/plugins/bitbucket/e2e/snapshot_tables/_tool_bitbucket_accounts_in_comments.csv b/plugins/bitbucket/e2e/snapshot_tables/_tool_bitbucket_accounts_in_comments.csv
new file mode 100644
index 00000000..72cc7408
--- /dev/null
+++ b/plugins/bitbucket/e2e/snapshot_tables/_tool_bitbucket_accounts_in_comments.csv
@@ -0,0 +1,2 @@
+connection_id,account_id,user_name,account_status,display_name,avatar_url,html_url,uuid,has2_fa_enabled,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark
+1,62abf394192edb006fa0e8cf,,,teoiaoe,https://secure.gravatar.com/avatar/d37e5c64cd007c5c20654af064c3f410?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FT-0.png,https://bitbucket.org/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D/,,0,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_request_comments,18,
diff --git a/plugins/bitbucket/e2e/snapshot_tables/_tool_bitbucket_accounts_in_issue.csv b/plugins/bitbucket/e2e/snapshot_tables/_tool_bitbucket_accounts_in_issue.csv
new file mode 100644
index 00000000..78ff1746
--- /dev/null
+++ b/plugins/bitbucket/e2e/snapshot_tables/_tool_bitbucket_accounts_in_issue.csv
@@ -0,0 +1,2 @@
+connection_id,account_id,user_name,account_status,display_name,avatar_url,html_url,uuid,has2_fa_enabled,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark
+1,62abf394192edb006fa0e8cf,,,teoiaoe,https://secure.gravatar.com/avatar/d37e5c64cd007c5c20654af064c3f410?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FT-0.png,https://bitbucket.org/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D/,,0,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,60,
diff --git a/plugins/bitbucket/e2e/snapshot_tables/_tool_bitbucket_accounts_in_pr.csv b/plugins/bitbucket/e2e/snapshot_tables/_tool_bitbucket_accounts_in_pr.csv
new file mode 100644
index 00000000..6665d105
--- /dev/null
+++ b/plugins/bitbucket/e2e/snapshot_tables/_tool_bitbucket_accounts_in_pr.csv
@@ -0,0 +1,2 @@
+connection_id,account_id,user_name,account_status,display_name,avatar_url,html_url,uuid,has2_fa_enabled,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark
+1,62abf394192edb006fa0e8cf,,,teoiaoe,https://secure.gravatar.com/avatar/d37e5c64cd007c5c20654af064c3f410?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FT-0.png,https://bitbucket.org/%7B64135f6a-3978-4297-99b1-21827e0faf0b%7D/,,0,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,171,
diff --git a/plugins/bitbucket/e2e/snapshot_tables/_tool_bitbucket_issue_comments.csv b/plugins/bitbucket/e2e/snapshot_tables/_tool_bitbucket_issue_comments.csv
new file mode 100644
index 00000000..400fb799
--- /dev/null
+++ b/plugins/bitbucket/e2e/snapshot_tables/_tool_bitbucket_issue_comments.csv
@@ -0,0 +1,29 @@
+connection_id,bitbucket_id,issue_id,author_name,author_id,bitbucket_created_at,bitbucket_updated_at,type,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark
+1,63860152,1,teoiaoe,62abf394192edb006fa0e8cf,2022-07-17T07:16:30.353+00:00,,issue_comment,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,1,
+1,63860153,1,teoiaoe,62abf394192edb006fa0e8cf,2022-07-17T07:17:01.992+00:00,,issue_comment,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,2,
+1,63860241,1,teoiaoe,62abf394192edb006fa0e8cf,2022-07-17T09:11:42.760+00:00,,issue_comment,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,3,
+1,63961973,6,teoiaoe,62abf394192edb006fa0e8cf,2022-08-12T13:51:25.882+00:00,,issue_comment,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,4,
+1,63961995,28,teoiaoe,62abf394192edb006fa0e8cf,2022-08-12T13:55:58.125+00:00,,issue_comment,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,5,
+1,63963442,27,teoiaoe,62abf394192edb006fa0e8cf,2022-08-13T06:17:23.165+00:00,,issue_comment,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,6,
+1,63963443,27,teoiaoe,62abf394192edb006fa0e8cf,2022-08-13T06:17:28.684+00:00,,issue_comment,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,7,
+1,63963444,27,teoiaoe,62abf394192edb006fa0e8cf,2022-08-13T06:17:36.686+00:00,,issue_comment,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,8,
+1,63963445,27,teoiaoe,62abf394192edb006fa0e8cf,2022-08-13T06:17:42.087+00:00,,issue_comment,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,9,
+1,63963446,27,teoiaoe,62abf394192edb006fa0e8cf,2022-08-13T06:17:47.634+00:00,,issue_comment,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,10,
+1,63963447,27,teoiaoe,62abf394192edb006fa0e8cf,2022-08-13T06:17:55.851+00:00,,issue_comment,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,11,
+1,63963449,27,teoiaoe,62abf394192edb006fa0e8cf,2022-08-13T06:18:01.928+00:00,,issue_comment,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,12,
+1,63963450,27,teoiaoe,62abf394192edb006fa0e8cf,2022-08-13T06:18:11.147+00:00,,issue_comment,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,13,
+1,63963451,27,teoiaoe,62abf394192edb006fa0e8cf,2022-08-13T06:18:19.377+00:00,,issue_comment,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,14,
+1,63963452,27,teoiaoe,62abf394192edb006fa0e8cf,2022-08-13T06:18:26.505+00:00,,issue_comment,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,15,
+1,63963453,27,teoiaoe,62abf394192edb006fa0e8cf,2022-08-13T06:18:33.109+00:00,,issue_comment,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,16,
+1,63963454,27,teoiaoe,62abf394192edb006fa0e8cf,2022-08-13T06:18:39.543+00:00,,issue_comment,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,17,
+1,63963455,27,teoiaoe,62abf394192edb006fa0e8cf,2022-08-13T06:18:46.158+00:00,,issue_comment,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,18,
+1,63963456,27,teoiaoe,62abf394192edb006fa0e8cf,2022-08-13T06:18:52.858+00:00,,issue_comment,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,19,
+1,63963457,27,teoiaoe,62abf394192edb006fa0e8cf,2022-08-13T06:18:58.979+00:00,,issue_comment,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,20,
+1,63963458,27,teoiaoe,62abf394192edb006fa0e8cf,2022-08-13T06:19:05.667+00:00,,issue_comment,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,21,
+1,63963459,27,teoiaoe,62abf394192edb006fa0e8cf,2022-08-13T06:19:15.957+00:00,,issue_comment,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,22,
+1,63963460,27,teoiaoe,62abf394192edb006fa0e8cf,2022-08-13T06:19:23.294+00:00,,issue_comment,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,23,
+1,63963461,27,teoiaoe,62abf394192edb006fa0e8cf,2022-08-13T06:19:31.457+00:00,,issue_comment,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,24,
+1,63963462,27,teoiaoe,62abf394192edb006fa0e8cf,2022-08-13T06:19:38.434+00:00,,issue_comment,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,25,
+1,63963463,27,teoiaoe,62abf394192edb006fa0e8cf,2022-08-13T06:19:45.161+00:00,,issue_comment,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,26,
+1,63963464,27,teoiaoe,62abf394192edb006fa0e8cf,2022-08-13T06:19:54.366+00:00,,issue_comment,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,27,
+1,63963465,27,teoiaoe,62abf394192edb006fa0e8cf,2022-08-13T06:20:01.329+00:00,,issue_comment,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,28,
diff --git a/plugins/bitbucket/e2e/snapshot_tables/_tool_bitbucket_issue_labels.csv b/plugins/bitbucket/e2e/snapshot_tables/_tool_bitbucket_issue_labels.csv
new file mode 100644
index 00000000..fa39feb0
--- /dev/null
+++ b/plugins/bitbucket/e2e/snapshot_tables/_tool_bitbucket_issue_labels.csv
@@ -0,0 +1 @@
+connection_id,issue_id,label_name,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark
diff --git a/plugins/bitbucket/e2e/snapshot_tables/_tool_bitbucket_issues.csv b/plugins/bitbucket/e2e/snapshot_tables/_tool_bitbucket_issues.csv
new file mode 100644
index 00000000..ce4a736f
--- /dev/null
+++ b/plugins/bitbucket/e2e/snapshot_tables/_tool_bitbucket_issues.csv
@@ -0,0 +1,55 @@
+connection_id,bitbucket_id,repo_id,number,state,title,body,priority,type,author_id,author_name,assignee_id,assignee_name,milestone_id,lead_time_minutes,url,closed_at,bitbucket_created_at,bitbucket_updated_at,severity,component,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark
+1,1,panjf2000/ants,1,new,issue test,bitbucket issues test for devants,major,issue,62abf394192edb006fa0e8cf,teoiaoe,62abf394192edb006fa0e8cf,teoiaoe,0,0,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/1,,2022-07-17T07:15:55.959+00:00,2022-07-17T09:11:42.656+00:00,,,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,60,
+1,2,panjf2000/ants,2,new,add bitbucket issue,feafejo,major,issue,62abf394192edb006fa0e8cf,teoiaoe,,,0,0,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/2,,2022-07-28T06:40:08.187+00:00,2022-07-28T06:40:08.187+00:00,,,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,59,
+1,3,panjf2000/ants,3,new,bitbucket test,"efaegjeoaijefioaegrjoeior,af enfaoiee vioea.,,.wew",major,issue,62abf394192edb006fa0e8cf,teoiaoe,,,0,0,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/3,,2022-07-28T06:41:23.334+00:00,2022-07-28T06:41:23.334+00:00,,,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,58,
+1,4,panjf2000/ants,4,new,issue test001,Bitbucket issue test001,major,issue,62abf394192edb006fa0e8cf,teoiaoe,,,0,0,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/4,,2022-08-12T13:39:52.109+00:00,2022-08-12T13:39:52.109+00:00,,,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,57,
+1,5,panjf2000/ants,5,new,issue test002,issue test002,major,issue,62abf394192edb006fa0e8cf,teoiaoe,,,0,0,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/5,,2022-08-12T13:40:32.843+00:00,2022-08-12T13:40:32.843+00:00,,,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,56,
+1,6,panjf2000/ants,6,new,issue test003,issue test 003,major,issue,62abf394192edb006fa0e8cf,teoiaoe,62abf394192edb006fa0e8cf,teoiaoe,0,0,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/6,,2022-08-12T13:40:55.635+00:00,2022-08-12T13:51:25.769+00:00,,,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,37,
+1,7,panjf2000/ants,7,new,issue test004,issue test004,major,issue,62abf394192edb006fa0e8cf,teoiaoe,,,0,0,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/7,,2022-08-12T13:41:21.859+00:00,2022-08-12T13:41:21.859+00:00,,,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,55,
+1,8,panjf2000/ants,8,new,issue test005,issue test005,critical,issue,62abf394192edb006fa0e8cf,teoiaoe,,,0,0,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/8,,2022-08-12T13:41:58.511+00:00,2022-08-12T13:41:58.511+00:00,,,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,54,
+1,9,panjf2000/ants,9,new,issue test006,issue test006,blocker,issue,62abf394192edb006fa0e8cf,teoiaoe,62abf394192edb006fa0e8cf,teoiaoe,0,0,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/9,,2022-08-12T13:42:29.072+00:00,2022-08-12T13:42:29.072+00:00,,,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,53,
+1,10,panjf2000/ants,10,new,issue test007,issue test007,trivial,issue,62abf394192edb006fa0e8cf,teoiaoe,62abf394192edb006fa0e8cf,teoiaoe,0,0,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/10,,2022-08-12T13:43:00.783+00:00,2022-08-12T13:43:00.783+00:00,,,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,52,
+1,11,panjf2000/ants,11,new,issue test008,issue test008,major,issue,62abf394192edb006fa0e8cf,teoiaoe,62abf394192edb006fa0e8cf,teoiaoe,0,0,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/11,,2022-08-12T13:43:26.414+00:00,2022-08-12T13:43:26.414+00:00,,,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,51,
+1,12,panjf2000/ants,12,new,issue test009,issue test009,minor,issue,62abf394192edb006fa0e8cf,teoiaoe,,,0,0,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/12,,2022-08-12T13:44:04.502+00:00,2022-08-12T13:44:04.502+00:00,,,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,50,
+1,13,panjf2000/ants,13,new,issue test010,issue test010,critical,issue,62abf394192edb006fa0e8cf,teoiaoe,,,0,0,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/13,,2022-08-12T13:44:46.508+00:00,2022-08-12T13:44:46.508+00:00,,,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,49,
+1,14,panjf2000/ants,14,new,issue test011,issue test011,blocker,issue,62abf394192edb006fa0e8cf,teoiaoe,62abf394192edb006fa0e8cf,teoiaoe,0,0,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/14,,2022-08-12T13:45:12.810+00:00,2022-08-12T13:45:12.810+00:00,,,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,48,
+1,15,panjf2000/ants,15,new,issue test012,issue test012,minor,issue,62abf394192edb006fa0e8cf,teoiaoe,,,0,0,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/15,,2022-08-12T13:45:41.640+00:00,2022-08-12T13:45:41.640+00:00,,,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,47,
+1,16,panjf2000/ants,16,new,issue test013,issue test013,trivial,issue,62abf394192edb006fa0e8cf,teoiaoe,,,0,0,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/16,,2022-08-12T13:46:06.169+00:00,2022-08-12T13:46:06.169+00:00,,,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,46,
+1,17,panjf2000/ants,17,new,issue test014,issue test014,trivial,issue,62abf394192edb006fa0e8cf,teoiaoe,,,0,0,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/17,,2022-08-12T13:46:39.426+00:00,2022-08-12T13:46:39.426+00:00,,,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,45,
+1,18,panjf2000/ants,18,new,issue test015,issue test015,minor,issue,62abf394192edb006fa0e8cf,teoiaoe,,,0,0,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/18,,2022-08-12T13:47:01.892+00:00,2022-08-12T13:47:01.892+00:00,,,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,44,
+1,19,panjf2000/ants,19,new,issue test016,issue test016,critical,issue,62abf394192edb006fa0e8cf,teoiaoe,62abf394192edb006fa0e8cf,teoiaoe,0,0,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/19,,2022-08-12T13:47:26.928+00:00,2022-08-12T13:47:26.928+00:00,,,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,43,
+1,20,panjf2000/ants,20,new,issue test017,issue test017,blocker,issue,62abf394192edb006fa0e8cf,teoiaoe,62abf394192edb006fa0e8cf,teoiaoe,0,0,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/20,,2022-08-12T13:47:54.126+00:00,2022-08-12T13:47:54.126+00:00,,,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,42,
+1,21,panjf2000/ants,21,new,issue test018,issue test018,trivial,issue,62abf394192edb006fa0e8cf,teoiaoe,,,0,0,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/21,,2022-08-12T13:48:50.020+00:00,2022-08-12T13:48:50.020+00:00,,,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,41,
+1,22,panjf2000/ants,22,new,issue test019,issue test019,minor,issue,62abf394192edb006fa0e8cf,teoiaoe,,,0,0,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/22,,2022-08-12T13:49:23.252+00:00,2022-08-12T13:49:23.252+00:00,,,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,40,
+1,23,panjf2000/ants,23,new,issue test020,issue test020,critical,issue,62abf394192edb006fa0e8cf,teoiaoe,62abf394192edb006fa0e8cf,teoiaoe,0,0,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/23,,2022-08-12T13:49:51.630+00:00,2022-08-12T13:49:51.630+00:00,,,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,39,
+1,24,panjf2000/ants,24,new,issue test021,"issue test021 ijeiawgoeive/faveevaeviaevfejaofejfioejaiofe_veavejiovajgiorejoifjrogiorejieafajejaojoejvgioriovioraivjairobnrnoivaiorjbiorjiojaeiorjvioejroivjaoijeriojiaojioeefjafioejfiojeiofawefwefoiwefiwoiefweefwoefuwhufirfrw._  
+
+```
+``eveaeaeae`jiovjeiojoa oi2j3oij23jovnw3
+```
+
+‌",trivial,issue,62abf394192edb006fa0e8cf,teoiaoe,62abf394192edb006fa0e8cf,teoiaoe,0,0,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/24,,2022-08-12T13:50:57.290+00:00,2022-08-12T13:50:57.290+00:00,,,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,38,
+1,25,panjf2000/ants,25,new,issue 023,"issue test023 ejoafehoafe
+
+q
+
+```c++
+feafefoa
+feafoiehfe
+rvvgeaioehr
+feaofe
+```
+
+| **fefae** |  |  |
+| --- | --- | --- |
+|  |  |  |
+|  |  |  |
+
+‌",critical,issue,62abf394192edb006fa0e8cf,teoiaoe,,,0,0,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/25,,2022-08-12T13:53:49.232+00:00,2022-08-12T13:53:49.232+00:00,,,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,36,
+1,26,panjf2000/ants,26,new,issue test022,issue test022,blocker,issue,62abf394192edb006fa0e8cf,teoiaoe,,,0,0,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/26,,2022-08-12T13:54:28.911+00:00,2022-08-12T13:54:28.911+00:00,,,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,35,
+1,27,panjf2000/ants,27,new,issue test024,"issue test024v  aejnoafoeiogoiae
+
+qwofjeoiwjf",trivial,issue,62abf394192edb006fa0e8cf,teoiaoe,,,0,0,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/27,,2022-08-12T13:55:09.734+00:00,2022-08-13T06:20:01.410+00:00,,,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,31,
+1,28,panjf2000/ants,28,new,issue test025,issue test025,minor,issue,62abf394192edb006fa0e8cf,teoiaoe,,,0,0,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/28,,2022-08-12T13:55:32.410+00:00,2022-08-12T13:55:58.035+00:00,,,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,34,
+1,29,panjf2000/ants,29,new,issue test026,issue test026,critical,issue,62abf394192edb006fa0e8cf,teoiaoe,62abf394192edb006fa0e8cf,teoiaoe,0,0,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/29,,2022-08-12T13:56:26.434+00:00,2022-08-12T13:56:26.434+00:00,,,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,33,
+1,30,panjf2000/ants,30,new,issue test027,issue test027,critical,issue,62abf394192edb006fa0e8cf,teoiaoe,62abf394192edb006fa0e8cf,teoiaoe,0,0,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/30,,2022-08-12T13:56:51.480+00:00,2022-08-12T13:56:51.480+00:00,,,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,32,
diff --git a/plugins/bitbucket/e2e/snapshot_tables/_tool_bitbucket_pull_request_comments.csv b/plugins/bitbucket/e2e/snapshot_tables/_tool_bitbucket_pull_request_comments.csv
new file mode 100644
index 00000000..a4e5de43
--- /dev/null
+++ b/plugins/bitbucket/e2e/snapshot_tables/_tool_bitbucket_pull_request_comments.csv
@@ -0,0 +1,19 @@
+connection_id,bitbucket_id,pull_request_id,author_name,author_id,bitbucket_created_at,bitbucket_updated_at,type,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark
+1,323119643,54,,62abf394192edb006fa0e8cf,2022-08-12T15:36:49.030+00:00,2022-08-12T15:36:49.030+00:00,pullrequest_comment,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_request_comments,14,
+1,323119662,54,,62abf394192edb006fa0e8cf,2022-08-12T15:36:53.394+00:00,2022-08-12T15:36:53.394+00:00,pullrequest_comment,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_request_comments,15,
+1,323119730,57,,62abf394192edb006fa0e8cf,2022-08-12T15:37:16.880+00:00,2022-08-12T15:37:16.880+00:00,pullrequest_comment,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_request_comments,17,
+1,323119743,57,,62abf394192edb006fa0e8cf,2022-08-12T15:37:21.558+00:00,2022-08-12T15:37:21.558+00:00,pullrequest_comment,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_request_comments,18,
+1,323119784,51,,62abf394192edb006fa0e8cf,2022-08-12T15:37:36.309+00:00,2022-08-12T15:37:36.309+00:00,pullrequest_comment,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_request_comments,12,
+1,323119790,51,,62abf394192edb006fa0e8cf,2022-08-12T15:37:40.769+00:00,2022-08-12T15:37:40.769+00:00,pullrequest_comment,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_request_comments,13,
+1,323119842,42,,62abf394192edb006fa0e8cf,2022-08-12T15:37:51.357+00:00,2022-08-12T15:37:51.357+00:00,pullrequest_comment,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_request_comments,8,
+1,323119856,42,,62abf394192edb006fa0e8cf,2022-08-12T15:37:56.277+00:00,2022-08-12T15:37:56.277+00:00,pullrequest_comment,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_request_comments,9,
+1,323119897,54,,62abf394192edb006fa0e8cf,2022-08-12T15:38:11.180+00:00,2022-08-12T15:38:11.180+00:00,pullrequest_comment,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_request_comments,16,
+1,323119960,38,,62abf394192edb006fa0e8cf,2022-08-12T15:38:26.895+00:00,2022-08-12T15:38:26.895+00:00,pullrequest_comment,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_request_comments,4,
+1,323119980,38,,62abf394192edb006fa0e8cf,2022-08-12T15:38:31.111+00:00,2022-08-12T15:38:31.111+00:00,pullrequest_comment,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_request_comments,5,
+1,323120091,44,,62abf394192edb006fa0e8cf,2022-08-12T15:39:11.612+00:00,2022-08-12T15:39:11.612+00:00,pullrequest_comment,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_request_comments,10,
+1,323120101,44,,62abf394192edb006fa0e8cf,2022-08-12T15:39:15.632+00:00,2022-08-12T15:39:15.632+00:00,pullrequest_comment,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_request_comments,11,
+1,323120140,40,,62abf394192edb006fa0e8cf,2022-08-12T15:39:27.439+00:00,2022-08-12T15:39:27.439+00:00,pullrequest_comment,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_request_comments,6,
+1,323120196,41,,62abf394192edb006fa0e8cf,2022-08-12T15:39:41.750+00:00,2022-08-12T15:39:41.750+00:00,pullrequest_comment,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_request_comments,7,
+1,323120278,31,,62abf394192edb006fa0e8cf,2022-08-12T15:40:01.755+00:00,2022-08-12T15:40:01.755+00:00,pullrequest_comment,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_request_comments,1,
+1,323120296,31,,62abf394192edb006fa0e8cf,2022-08-12T15:40:07.757+00:00,2022-08-12T15:40:07.757+00:00,pullrequest_comment,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_request_comments,2,
+1,323120311,31,,62abf394192edb006fa0e8cf,2022-08-12T15:40:12.401+00:00,2022-08-12T15:40:12.401+00:00,pullrequest_comment,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_request_comments,3,
diff --git a/plugins/bitbucket/e2e/snapshot_tables/_tool_bitbucket_pull_requests.csv b/plugins/bitbucket/e2e/snapshot_tables/_tool_bitbucket_pull_requests.csv
new file mode 100644
index 00000000..65160009
--- /dev/null
+++ b/plugins/bitbucket/e2e/snapshot_tables/_tool_bitbucket_pull_requests.csv
@@ -0,0 +1,58 @@
+connection_id,bitbucket_id,repo_id,number,state,title,bitbucket_created_at,bitbucket_updated_at,closed_at,comment_count,commits,merged_at,body,type,component,merge_commit_sha,head_ref,base_ref,base_commit_sha,head_commit_sha,url,author_name,author_id,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark
+1,1,panjf2000/ants,0,OPEN,feat: add pr test,2022-07-12T04:17:03.055+00:00,2022-07-18T05:39:20.730+00:00,,2,0,,,pullrequest,,,test,master,c0e12b61e44b,5e5bccfcc656,https://bitbucket.org/panjf2000/ants/pull-requests/1,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,171,
+1,2,panjf2000/ants,0,MERGED,feat: add git.sh,2022-08-12T13:18:39.132+00:00,2022-08-12T15:03:37.272+00:00,,0,0,,,pullrequest,,983edbf06740,vowehwo,master,0bd83caaf9c7,d4a6789a3751,https://bitbucket.org/panjf2000/ants/pull-requests/2,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,169,
+1,3,panjf2000/ants,0,MERGED,Test9,2022-08-12T14:53:19.796+00:00,2022-08-12T15:03:37.475+00:00,,0,0,,,pullrequest,,983edbf06740,test9,master,0bd83caaf9c7,6557208f4aa6,https://bitbucket.org/panjf2000/ants/pull-requests/3,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,168,
+1,4,panjf2000/ants,0,MERGED,Test001,2022-08-12T14:53:43.845+00:00,2022-08-12T15:03:37.622+00:00,,0,0,,,pullrequest,,983edbf06740,test001,master,0bd83caaf9c7,3bd3b34b2397,https://bitbucket.org/panjf2000/ants/pull-requests/4,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,167,
+1,5,panjf2000/ants,0,MERGED,Test002,2022-08-12T14:53:59.654+00:00,2022-08-12T15:03:37.766+00:00,,0,0,,,pullrequest,,983edbf06740,test002,master,0bd83caaf9c7,904df6924f1e,https://bitbucket.org/panjf2000/ants/pull-requests/5,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,166,
+1,6,panjf2000/ants,0,MERGED,Test003,2022-08-12T14:54:20.308+00:00,2022-08-12T15:03:37.916+00:00,,0,0,,,pullrequest,,983edbf06740,test003,master,0bd83caaf9c7,494b97e9d0b2,https://bitbucket.org/panjf2000/ants/pull-requests/6,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,165,
+1,7,panjf2000/ants,0,MERGED,Test004,2022-08-12T14:54:40.056+00:00,2022-08-12T15:03:38.066+00:00,,0,0,,,pullrequest,,983edbf06740,test004,master,0bd83caaf9c7,db921ce6537c,https://bitbucket.org/panjf2000/ants/pull-requests/7,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,164,
+1,8,panjf2000/ants,0,MERGED,Test005,2022-08-12T14:54:56.506+00:00,2022-08-12T15:03:38.297+00:00,,0,0,,,pullrequest,,983edbf06740,test005,master,0bd83caaf9c7,8a224cc0eaae,https://bitbucket.org/panjf2000/ants/pull-requests/8,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,163,
+1,9,panjf2000/ants,0,MERGED,Test006,2022-08-12T14:55:13.971+00:00,2022-08-12T15:03:38.479+00:00,,0,0,,,pullrequest,,983edbf06740,test006,master,0bd83caaf9c7,8a8f44b997a8,https://bitbucket.org/panjf2000/ants/pull-requests/9,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,162,
+1,10,panjf2000/ants,0,MERGED,Test007,2022-08-12T14:55:28.082+00:00,2022-08-12T15:03:38.628+00:00,,0,0,,,pullrequest,,983edbf06740,test007,master,0bd83caaf9c7,15a1fcb51f0e,https://bitbucket.org/panjf2000/ants/pull-requests/10,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,161,
+1,11,panjf2000/ants,0,MERGED,Test6,2022-08-12T14:55:48.770+00:00,2022-08-12T15:03:38.774+00:00,,0,0,,,pullrequest,,983edbf06740,test6,master,0bd83caaf9c7,bc9a3ddd47ea,https://bitbucket.org/panjf2000/ants/pull-requests/11,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,160,
+1,12,panjf2000/ants,0,MERGED,Test7,2022-08-12T14:56:07.092+00:00,2022-08-12T15:03:38.926+00:00,,0,0,,,pullrequest,,983edbf06740,test7,master,0bd83caaf9c7,dd2cd76d7098,https://bitbucket.org/panjf2000/ants/pull-requests/12,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,159,
+1,13,panjf2000/ants,0,MERGED,Test8,2022-08-12T14:56:30.570+00:00,2022-08-12T15:03:39.074+00:00,,0,0,,,pullrequest,,983edbf06740,test8,master,0bd83caaf9c7,94056215cf46,https://bitbucket.org/panjf2000/ants/pull-requests/13,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,158,
+1,14,panjf2000/ants,0,MERGED,Test10,2022-08-12T14:56:52.550+00:00,2022-08-12T15:03:39.228+00:00,,0,0,,,pullrequest,,983edbf06740,test10,master,0bd83caaf9c7,bc2cf25142e3,https://bitbucket.org/panjf2000/ants/pull-requests/14,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,157,
+1,15,panjf2000/ants,0,MERGED,Test011,2022-08-12T14:57:15.254+00:00,2022-08-12T15:03:39.381+00:00,,0,0,,,pullrequest,,983edbf06740,test011,master,0bd83caaf9c7,5db6b1a9e60c,https://bitbucket.org/panjf2000/ants/pull-requests/15,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,156,
+1,16,panjf2000/ants,0,MERGED,Test12,2022-08-12T14:57:41.230+00:00,2022-08-12T15:03:36.526+00:00,,0,0,,,pullrequest,,983edbf06740,test12,master,0bd83caaf9c7,d1321cb5e4fb,https://bitbucket.org/panjf2000/ants/pull-requests/16,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,170,
+1,17,panjf2000/ants,0,MERGED,Test13,2022-08-12T14:57:59.501+00:00,2022-08-12T15:10:43.032+00:00,,0,0,,,pullrequest,,c0e12b61e44b,test13,master,983edbf06740,3d6d96659c4d,https://bitbucket.org/panjf2000/ants/pull-requests/17,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,151,
+1,18,panjf2000/ants,0,MERGED,Test14,2022-08-12T14:58:16.105+00:00,2022-08-12T15:10:43.206+00:00,,0,0,,,pullrequest,,c0e12b61e44b,test14,master,983edbf06740,8d4896eef3ed,https://bitbucket.org/panjf2000/ants/pull-requests/18,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,150,
+1,19,panjf2000/ants,0,MERGED,Test15,2022-08-12T14:58:33.361+00:00,2022-08-12T15:10:43.322+00:00,,0,0,,,pullrequest,,c0e12b61e44b,test15,master,983edbf06740,daa1cfa7ec0c,https://bitbucket.org/panjf2000/ants/pull-requests/19,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,149,
+1,20,panjf2000/ants,0,MERGED,Test16,2022-08-12T14:59:07.791+00:00,2022-08-12T15:10:43.437+00:00,,0,0,,,pullrequest,,c0e12b61e44b,test16,master,983edbf06740,11f6c86580e2,https://bitbucket.org/panjf2000/ants/pull-requests/20,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,148,
+1,21,panjf2000/ants,0,MERGED,Test18,2022-08-12T14:59:22.874+00:00,2022-08-12T15:10:43.562+00:00,,0,0,,,pullrequest,,c0e12b61e44b,test18,master,983edbf06740,0b958bbfed04,https://bitbucket.org/panjf2000/ants/pull-requests/21,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,147,
+1,22,panjf2000/ants,0,MERGED,Test19,2022-08-12T14:59:39.610+00:00,2022-08-12T15:10:43.684+00:00,,0,0,,,pullrequest,,c0e12b61e44b,test19,master,983edbf06740,d1bb3677810e,https://bitbucket.org/panjf2000/ants/pull-requests/22,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,146,
+1,23,panjf2000/ants,0,MERGED,Test20,2022-08-12T14:59:57.869+00:00,2022-08-12T15:10:43.807+00:00,,0,0,,,pullrequest,,c0e12b61e44b,test20,master,983edbf06740,9d16a2368acd,https://bitbucket.org/panjf2000/ants/pull-requests/23,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,145,
+1,24,panjf2000/ants,0,MERGED,Test17,2022-08-12T15:00:34.399+00:00,2022-08-12T15:10:43.931+00:00,,0,0,,,pullrequest,,c0e12b61e44b,test17,master,983edbf06740,2bfd29a17665,https://bitbucket.org/panjf2000/ants/pull-requests/24,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,144,
+1,25,panjf2000/ants,0,MERGED,1,2022-08-12T15:00:59.503+00:00,2022-08-12T15:03:40.499+00:00,,0,0,,,pullrequest,,983edbf06740,1,master,0bd83caaf9c7,592612c47ff5,https://bitbucket.org/panjf2000/ants/pull-requests/25,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,155,
+1,26,panjf2000/ants,0,MERGED,2,2022-08-12T15:01:18.980+00:00,2022-08-12T15:03:40.646+00:00,,0,0,,,pullrequest,,983edbf06740,2,master,0bd83caaf9c7,05b97cf92b4b,https://bitbucket.org/panjf2000/ants/pull-requests/26,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,154,
+1,27,panjf2000/ants,0,MERGED,4,2022-08-12T15:02:16.840+00:00,2022-08-12T15:03:40.792+00:00,,0,0,,,pullrequest,,983edbf06740,4,master,0bd83caaf9c7,761fdb9244ef,https://bitbucket.org/panjf2000/ants/pull-requests/27,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,153,
+1,28,panjf2000/ants,0,MERGED,mergev1,2022-08-12T15:10:16.367+00:00,2022-08-12T15:10:42.415+00:00,,0,0,,,pullrequest,,c0e12b61e44b,mergev1,master,983edbf06740,581a89006076,https://bitbucket.org/panjf2000/ants/pull-requests/28,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,152,
+1,29,panjf2000/ants,0,OPEN,Test03,2022-08-12T15:21:47.437+00:00,2022-08-12T15:29:13.392+00:00,,0,0,,,pullrequest,,,test03,master,c0e12b61e44b,a3768d182d18,https://bitbucket.org/panjf2000/ants/pull-requests/29,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,132,
+1,30,panjf2000/ants,0,OPEN,Test05,2022-08-12T15:22:17.954+00:00,2022-08-12T15:22:18.488+00:00,,0,0,,,pullrequest,,,test05,master,c0e12b61e44b,91e7a1db9ae0,https://bitbucket.org/panjf2000/ants/pull-requests/30,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,143,
+1,31,panjf2000/ants,0,OPEN,Test020,2022-08-12T15:22:51.303+00:00,2022-08-12T15:40:12.401+00:00,,3,0,,,pullrequest,,,test020,master,c0e12b61e44b,0342bf5351f8,https://bitbucket.org/panjf2000/ants/pull-requests/31,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,118,
+1,32,panjf2000/ants,0,OPEN,Test022,2022-08-12T15:23:06.858+00:00,2022-08-12T15:23:07.539+00:00,,0,0,,,pullrequest,,,test022,master,c0e12b61e44b,d72c46a722d7,https://bitbucket.org/panjf2000/ants/pull-requests/32,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,142,
+1,33,panjf2000/ants,0,OPEN,Test023,2022-08-12T15:23:27.568+00:00,2022-08-12T15:23:28.341+00:00,,0,0,,,pullrequest,,,test023,master,c0e12b61e44b,0a8011c8c0ac,https://bitbucket.org/panjf2000/ants/pull-requests/33,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,141,
+1,34,panjf2000/ants,0,OPEN,Test024,2022-08-12T15:23:42.883+00:00,2022-08-12T15:23:43.529+00:00,,0,0,,,pullrequest,,,test024,master,c0e12b61e44b,bd7e81a581f1,https://bitbucket.org/panjf2000/ants/pull-requests/34,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,140,
+1,35,panjf2000/ants,0,OPEN,Test025,2022-08-12T15:23:58.227+00:00,2022-08-12T15:23:59.023+00:00,,0,0,,,pullrequest,,,test025,master,c0e12b61e44b,a15cb5876414,https://bitbucket.org/panjf2000/ants/pull-requests/35,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,139,
+1,36,panjf2000/ants,0,OPEN,Test027,2022-08-12T15:24:16.607+00:00,2022-08-12T15:24:17.311+00:00,,0,0,,,pullrequest,,,test027,master,c0e12b61e44b,200665f463ff,https://bitbucket.org/panjf2000/ants/pull-requests/36,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,138,
+1,37,panjf2000/ants,0,OPEN,Test028,2022-08-12T15:24:44.626+00:00,2022-08-12T15:24:45.191+00:00,,0,0,,,pullrequest,,,test028,master,c0e12b61e44b,8a9052ac97f4,https://bitbucket.org/panjf2000/ants/pull-requests/37,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,137,
+1,38,panjf2000/ants,0,OPEN,Test029,2022-08-12T15:24:59.520+00:00,2022-08-12T15:38:31.111+00:00,,2,0,,,pullrequest,,,test029,master,c0e12b61e44b,74bddc0541c6,https://bitbucket.org/panjf2000/ants/pull-requests/38,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,121,
+1,39,panjf2000/ants,0,OPEN,Test030,2022-08-12T15:25:14.361+00:00,2022-08-12T15:25:15.090+00:00,,0,0,,,pullrequest,,,test030,master,c0e12b61e44b,f332a9855de1,https://bitbucket.org/panjf2000/ants/pull-requests/39,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,136,
+1,40,panjf2000/ants,0,OPEN,Test016,2022-08-12T15:25:31.596+00:00,2022-08-14T07:38:28.303+00:00,,2,0,,,pullrequest,,,test016,master,c0e12b61e44b,a000a2a9fc11,https://bitbucket.org/panjf2000/ants/pull-requests/40,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,115,
+1,41,panjf2000/ants,0,OPEN,Test018,2022-08-12T15:25:57.607+00:00,2022-08-12T15:39:41.750+00:00,,1,0,,,pullrequest,,,test018,master,c0e12b61e44b,561e4e3ca4cc,https://bitbucket.org/panjf2000/ants/pull-requests/41,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,119,
+1,42,panjf2000/ants,0,OPEN,Test019,2022-08-12T15:26:15.843+00:00,2022-08-14T07:37:37.798+00:00,,4,0,,,pullrequest,,,test019,master,c0e12b61e44b,8597a99eebb3,https://bitbucket.org/panjf2000/ants/pull-requests/42,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,117,
+1,43,panjf2000/ants,0,OPEN,Test015,2022-08-12T15:26:50.905+00:00,2022-08-12T15:27:32.304+00:00,,0,0,,,pullrequest,,,test015,master,c0e12b61e44b,5af2c361263a,https://bitbucket.org/panjf2000/ants/pull-requests/43,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,135,
+1,44,panjf2000/ants,0,OPEN,Test017,2022-08-12T15:27:54.969+00:00,2022-08-12T15:39:15.632+00:00,,2,0,,,pullrequest,,,test017,master,c0e12b61e44b,ee87b0380472,https://bitbucket.org/panjf2000/ants/pull-requests/44,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,120,
+1,45,panjf2000/ants,0,OPEN,feat: add test01,2022-08-12T15:28:43.059+00:00,2022-08-12T15:28:43.627+00:00,,0,0,,,pullrequest,,,test01,master,c0e12b61e44b,63e6acbb60a9,https://bitbucket.org/panjf2000/ants/pull-requests/45,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,134,
+1,46,panjf2000/ants,0,OPEN,Test04,2022-08-12T15:28:57.787+00:00,2022-08-12T15:28:58.392+00:00,,0,0,,,pullrequest,,,test04,master,c0e12b61e44b,33419e166d75,https://bitbucket.org/panjf2000/ants/pull-requests/46,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,133,
+1,47,panjf2000/ants,0,OPEN,Test06,2022-08-12T15:29:31.360+00:00,2022-08-12T15:29:31.922+00:00,,0,0,,,pullrequest,,,test06,master,c0e12b61e44b,f8f9ef467e3a,https://bitbucket.org/panjf2000/ants/pull-requests/47,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,131,
+1,48,panjf2000/ants,0,OPEN,Test07,2022-08-12T15:29:49.045+00:00,2022-08-12T15:29:49.646+00:00,,0,0,,,pullrequest,,,test07,master,c0e12b61e44b,c28f34dde568,https://bitbucket.org/panjf2000/ants/pull-requests/48,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,130,
+1,49,panjf2000/ants,0,OPEN,Test08,2022-08-12T15:30:04.329+00:00,2022-08-12T15:30:04.827+00:00,,0,0,,,pullrequest,,,test08,master,c0e12b61e44b,6b59c8607581,https://bitbucket.org/panjf2000/ants/pull-requests/49,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,129,
+1,50,panjf2000/ants,0,OPEN,Bitbuckettest12,2022-08-12T15:32:46.725+00:00,2022-08-12T15:32:47.488+00:00,,0,0,,,pullrequest,,,bitbuckettest12,master,c0e12b61e44b,deff6927812f,https://bitbucket.org/panjf2000/ants/pull-requests/50,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,128,
+1,51,panjf2000/ants,0,OPEN,Bitbuckettest15,2022-08-12T15:32:59.604+00:00,2022-08-12T15:37:40.769+00:00,,2,0,,,pullrequest,,,bitbuckettest15,master,c0e12b61e44b,5c2c9af70da2,https://bitbucket.org/panjf2000/ants/pull-requests/51,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,122,
+1,52,panjf2000/ants,0,OPEN,Bitbuckettest16,2022-08-12T15:33:13.806+00:00,2022-08-12T15:33:14.346+00:00,,0,0,,,pullrequest,,,bitbuckettest16,master,c0e12b61e44b,7c91d40ffaa3,https://bitbucket.org/panjf2000/ants/pull-requests/52,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,127,
+1,53,panjf2000/ants,0,OPEN,Bitbuckettest17,2022-08-12T15:33:29.075+00:00,2022-08-12T15:34:20.065+00:00,,0,0,,,pullrequest,,,bitbuckettest17,master,c0e12b61e44b,765ab2594451,https://bitbucket.org/panjf2000/ants/pull-requests/53,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,125,
+1,54,panjf2000/ants,0,OPEN,Bitbuckettest19,2022-08-12T15:33:43.689+00:00,2022-08-14T07:38:08.195+00:00,,4,0,,,pullrequest,,,bitbuckettest19,master,c0e12b61e44b,2493b9212fd4,https://bitbucket.org/panjf2000/ants/pull-requests/54,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,116,
+1,55,panjf2000/ants,0,OPEN,Bitbuckettest13,2022-08-12T15:34:03.617+00:00,2022-08-12T15:34:04.159+00:00,,0,0,,,pullrequest,,,bitbuckettest13,master,c0e12b61e44b,9dd8c98115ca,https://bitbucket.org/panjf2000/ants/pull-requests/55,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,126,
+1,56,panjf2000/ants,0,OPEN,Bitbuckettest25,2022-08-12T15:34:37.513+00:00,2022-08-12T15:35:11.960+00:00,,0,0,,,pullrequest,,,bitbuckettest25,master,c0e12b61e44b,d69faf8c90c4,https://bitbucket.org/panjf2000/ants/pull-requests/56,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,124,
+1,57,panjf2000/ants,0,OPEN,Bitbuckettest22,2022-08-12T15:34:55.738+00:00,2022-08-12T15:37:21.558+00:00,,2,0,,,pullrequest,,,bitbuckettest22,master,c0e12b61e44b,2c23b3babf27,https://bitbucket.org/panjf2000/ants/pull-requests/57,teoiaoe,62abf394192edb006fa0e8cf,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,123,
diff --git a/plugins/bitbucket/e2e/snapshot_tables/_tool_bitbucket_repos.csv b/plugins/bitbucket/e2e/snapshot_tables/_tool_bitbucket_repos.csv
new file mode 100644
index 00000000..cd993327
--- /dev/null
+++ b/plugins/bitbucket/e2e/snapshot_tables/_tool_bitbucket_repos.csv
@@ -0,0 +1,2 @@
+connection_id,bitbucket_id,name,html_url,description,owner_id,language,created_date,updated_date,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark
+1,repositories/panjf2000/ants,panjf2000/ants,https://bitbucket.org/panjf2000/ants,,62abf394192edb006fa0e8cf,,2022-06-17T03:27:18.865+00:00,2022-08-12T15:40:12.409+00:00,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_repositories,2,
diff --git a/plugins/bitbucket/e2e/snapshot_tables/accounts.csv b/plugins/bitbucket/e2e/snapshot_tables/accounts.csv
new file mode 100644
index 00000000..8ff11005
--- /dev/null
+++ b/plugins/bitbucket/e2e/snapshot_tables/accounts.csv
@@ -0,0 +1,2 @@
+id,email,full_name,user_name,avatar_url,organization,created_date,status
+bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,teoiaoe,,https://secure.gravatar.com/avatar/d37e5c64cd007c5c20654af064c3f410?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FT-0.png,,,0
diff --git a/plugins/bitbucket/e2e/snapshot_tables/board_issues.csv b/plugins/bitbucket/e2e/snapshot_tables/board_issues.csv
new file mode 100644
index 00000000..35c52148
--- /dev/null
+++ b/plugins/bitbucket/e2e/snapshot_tables/board_issues.csv
@@ -0,0 +1,31 @@
+board_id,issue_id
+bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketIssue:1:1
+bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketIssue:1:10
+bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketIssue:1:11
+bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketIssue:1:12
+bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketIssue:1:13
+bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketIssue:1:14
+bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketIssue:1:15
+bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketIssue:1:16
+bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketIssue:1:17
+bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketIssue:1:18
+bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketIssue:1:19
+bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketIssue:1:2
+bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketIssue:1:20
+bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketIssue:1:21
+bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketIssue:1:22
+bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketIssue:1:23
+bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketIssue:1:24
+bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketIssue:1:25
+bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketIssue:1:26
+bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketIssue:1:27
+bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketIssue:1:28
+bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketIssue:1:29
+bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketIssue:1:3
+bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketIssue:1:30
+bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketIssue:1:4
+bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketIssue:1:5
+bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketIssue:1:6
+bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketIssue:1:7
+bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketIssue:1:8
+bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketIssue:1:9
diff --git a/plugins/bitbucket/e2e/snapshot_tables/boards.csv b/plugins/bitbucket/e2e/snapshot_tables/boards.csv
new file mode 100644
index 00000000..d4cbb227
--- /dev/null
+++ b/plugins/bitbucket/e2e/snapshot_tables/boards.csv
@@ -0,0 +1,2 @@
+id,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark,name,description,url,created_date
+bitbucket:BitbucketRepo:1:repositories/panjf2000/ants,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_repositories,2,,panjf2000/ants,,https://bitbucket.org/panjf2000/ants/issues,2022-06-17T03:27:18.865+00:00
diff --git a/plugins/bitbucket/e2e/snapshot_tables/issue_comments.csv b/plugins/bitbucket/e2e/snapshot_tables/issue_comments.csv
new file mode 100644
index 00000000..c2090b12
--- /dev/null
+++ b/plugins/bitbucket/e2e/snapshot_tables/issue_comments.csv
@@ -0,0 +1,29 @@
+id,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark,issue_id,body,user_id
+bitbucket:BitbucketIssue:1:63860152,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,1,,bitbucket:BitbucketIssue:1:1,,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf
+bitbucket:BitbucketIssue:1:63860153,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,2,,bitbucket:BitbucketIssue:1:1,this is a comment test for issue,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf
+bitbucket:BitbucketIssue:1:63860241,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,3,,bitbucket:BitbucketIssue:1:1,,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf
+bitbucket:BitbucketIssue:1:63961973,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,4,,bitbucket:BitbucketIssue:1:6,,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf
+bitbucket:BitbucketIssue:1:63961995,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,5,,bitbucket:BitbucketIssue:1:28,,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf
+bitbucket:BitbucketIssue:1:63963442,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,6,,bitbucket:BitbucketIssue:1:27,gvoeaoivae,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf
+bitbucket:BitbucketIssue:1:63963443,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,7,,bitbucket:BitbucketIssue:1:27,vboeaorboaneo,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf
+bitbucket:BitbucketIssue:1:63963444,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,8,,bitbucket:BitbucketIssue:1:27,beoiroierbieiaoboere,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf
+bitbucket:BitbucketIssue:1:63963445,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,9,,bitbucket:BitbucketIssue:1:27,boetboenavnin,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf
+bitbucket:BitbucketIssue:1:63963446,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,10,,bitbucket:BitbucketIssue:1:27,bbenoirbnavbeboa,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf
+bitbucket:BitbucketIssue:1:63963447,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,11,,bitbucket:BitbucketIssue:1:27,lboehoraebow,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf
+bitbucket:BitbucketIssue:1:63963449,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,12,,bitbucket:BitbucketIssue:1:27,ebeobnoerioaeiow,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf
+bitbucket:BitbucketIssue:1:63963450,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,13,,bitbucket:BitbucketIssue:1:27,uttrberoiea,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf
+bitbucket:BitbucketIssue:1:63963451,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,14,,bitbucket:BitbucketIssue:1:27,obfbdfonwea,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf
+bitbucket:BitbucketIssue:1:63963452,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,15,,bitbucket:BitbucketIssue:1:27,bjeorjboewaonwea,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf
+bitbucket:BitbucketIssue:1:63963453,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,16,,bitbucket:BitbucketIssue:1:27,brtoeorbnqqe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf
+bitbucket:BitbucketIssue:1:63963454,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,17,,bitbucket:BitbucketIssue:1:27,mmboeroi,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf
+bitbucket:BitbucketIssue:1:63963455,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,18,,bitbucket:BitbucketIssue:1:27,lqooaqjoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf
+bitbucket:BitbucketIssue:1:63963456,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,19,,bitbucket:BitbucketIssue:1:27,vajoieiowaeovw,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf
+bitbucket:BitbucketIssue:1:63963457,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,20,,bitbucket:BitbucketIssue:1:27,ieiojiwea,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf
+bitbucket:BitbucketIssue:1:63963458,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,21,,bitbucket:BitbucketIssue:1:27,beraowheuovhaewa,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf
+bitbucket:BitbucketIssue:1:63963459,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,22,,bitbucket:BitbucketIssue:1:27,oeorjeorb,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf
+bitbucket:BitbucketIssue:1:63963460,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,23,,bitbucket:BitbucketIssue:1:27,iocowevoanewww,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf
+bitbucket:BitbucketIssue:1:63963461,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,24,,bitbucket:BitbucketIssue:1:27,cowoehvowevaobnebiejaiweaw,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf
+bitbucket:BitbucketIssue:1:63963462,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,25,,bitbucket:BitbucketIssue:1:27,vbleklawi,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf
+bitbucket:BitbucketIssue:1:63963463,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,26,,bitbucket:BitbucketIssue:1:27,qowjoveawev,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf
+bitbucket:BitbucketIssue:1:63963464,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,27,,bitbucket:BitbucketIssue:1:27,ciojboieria,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf
+bitbucket:BitbucketIssue:1:63963465,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issue_comments,28,,bitbucket:BitbucketIssue:1:27,cwiwhoervowwwqe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf
diff --git a/plugins/bitbucket/e2e/snapshot_tables/issues.csv b/plugins/bitbucket/e2e/snapshot_tables/issues.csv
new file mode 100644
index 00000000..f8a5e130
--- /dev/null
+++ b/plugins/bitbucket/e2e/snapshot_tables/issues.csv
@@ -0,0 +1,55 @@
+id,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark,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
+bitbucket:BitbucketIssue:1:1,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,60,,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/1,,1,issue test,bitbucket issues test for devants,,issue,TODO,new,0,,2022-07-17T07:15:55.959+00:00,2022-07-17T09:11:42.656+00:00,0,,major,0,0,0,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,teoiaoe,,
+bitbucket:BitbucketIssue:1:10,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,52,,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/10,,10,issue test007,issue test007,,issue,TODO,new,0,,2022-08-12T13:43:00.783+00:00,2022-08-12T13:43:00.783+00:00,0,,trivial,0,0,0,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,teoiaoe,,
+bitbucket:BitbucketIssue:1:11,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,51,,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/11,,11,issue test008,issue test008,,issue,TODO,new,0,,2022-08-12T13:43:26.414+00:00,2022-08-12T13:43:26.414+00:00,0,,major,0,0,0,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,teoiaoe,,
+bitbucket:BitbucketIssue:1:12,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,50,,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/12,,12,issue test009,issue test009,,issue,TODO,new,0,,2022-08-12T13:44:04.502+00:00,2022-08-12T13:44:04.502+00:00,0,,minor,0,0,0,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,teoiaoe,,,,
+bitbucket:BitbucketIssue:1:13,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,49,,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/13,,13,issue test010,issue test010,,issue,TODO,new,0,,2022-08-12T13:44:46.508+00:00,2022-08-12T13:44:46.508+00:00,0,,critical,0,0,0,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,teoiaoe,,,,
+bitbucket:BitbucketIssue:1:14,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,48,,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/14,,14,issue test011,issue test011,,issue,TODO,new,0,,2022-08-12T13:45:12.810+00:00,2022-08-12T13:45:12.810+00:00,0,,blocker,0,0,0,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,teoiaoe,,
+bitbucket:BitbucketIssue:1:15,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,47,,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/15,,15,issue test012,issue test012,,issue,TODO,new,0,,2022-08-12T13:45:41.640+00:00,2022-08-12T13:45:41.640+00:00,0,,minor,0,0,0,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,teoiaoe,,,,
+bitbucket:BitbucketIssue:1:16,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,46,,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/16,,16,issue test013,issue test013,,issue,TODO,new,0,,2022-08-12T13:46:06.169+00:00,2022-08-12T13:46:06.169+00:00,0,,trivial,0,0,0,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,teoiaoe,,,,
+bitbucket:BitbucketIssue:1:17,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,45,,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/17,,17,issue test014,issue test014,,issue,TODO,new,0,,2022-08-12T13:46:39.426+00:00,2022-08-12T13:46:39.426+00:00,0,,trivial,0,0,0,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,teoiaoe,,,,
+bitbucket:BitbucketIssue:1:18,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,44,,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/18,,18,issue test015,issue test015,,issue,TODO,new,0,,2022-08-12T13:47:01.892+00:00,2022-08-12T13:47:01.892+00:00,0,,minor,0,0,0,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,teoiaoe,,,,
+bitbucket:BitbucketIssue:1:19,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,43,,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/19,,19,issue test016,issue test016,,issue,TODO,new,0,,2022-08-12T13:47:26.928+00:00,2022-08-12T13:47:26.928+00:00,0,,critical,0,0,0,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,teoiaoe,,
+bitbucket:BitbucketIssue:1:2,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,59,,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/2,,2,add bitbucket issue,feafejo,,issue,TODO,new,0,,2022-07-28T06:40:08.187+00:00,2022-07-28T06:40:08.187+00:00,0,,major,0,0,0,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,teoiaoe,,,,
+bitbucket:BitbucketIssue:1:20,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,42,,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/20,,20,issue test017,issue test017,,issue,TODO,new,0,,2022-08-12T13:47:54.126+00:00,2022-08-12T13:47:54.126+00:00,0,,blocker,0,0,0,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,teoiaoe,,
+bitbucket:BitbucketIssue:1:21,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,41,,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/21,,21,issue test018,issue test018,,issue,TODO,new,0,,2022-08-12T13:48:50.020+00:00,2022-08-12T13:48:50.020+00:00,0,,trivial,0,0,0,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,teoiaoe,,,,
+bitbucket:BitbucketIssue:1:22,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,40,,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/22,,22,issue test019,issue test019,,issue,TODO,new,0,,2022-08-12T13:49:23.252+00:00,2022-08-12T13:49:23.252+00:00,0,,minor,0,0,0,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,teoiaoe,,,,
+bitbucket:BitbucketIssue:1:23,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,39,,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/23,,23,issue test020,issue test020,,issue,TODO,new,0,,2022-08-12T13:49:51.630+00:00,2022-08-12T13:49:51.630+00:00,0,,critical,0,0,0,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,teoiaoe,,
+bitbucket:BitbucketIssue:1:24,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,38,,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/24,,24,issue test021,"issue test021 ijeiawgoeive/faveevaeviaevfejaofejfioejaiofe_veavejiovajgiorejoifjrogiorejieafajejaojoejvgioriovioraivjairobnrnoivaiorjbiorjiojaeiorjvioejroivjaoijeriojiaojioeefjafioejfiojeiofawefwefoiwefiwoiefweefwoefuwhufirfrw._  
+
+```
+``eveaeaeae`jiovjeiojoa oi2j3oij23jovnw3
+```
+
+‌",,issue,TODO,new,0,,2022-08-12T13:50:57.290+00:00,2022-08-12T13:50:57.290+00:00,0,,trivial,0,0,0,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,teoiaoe,,
+bitbucket:BitbucketIssue:1:25,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,36,,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/25,,25,issue 023,"issue test023 ejoafehoafe
+
+q
+
+```c++
+feafefoa
+feafoiehfe
+rvvgeaioehr
+feaofe
+```
+
+| **fefae** |  |  |
+| --- | --- | --- |
+|  |  |  |
+|  |  |  |
+
+‌",,issue,TODO,new,0,,2022-08-12T13:53:49.232+00:00,2022-08-12T13:53:49.232+00:00,0,,critical,0,0,0,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,teoiaoe,,,,
+bitbucket:BitbucketIssue:1:26,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,35,,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/26,,26,issue test022,issue test022,,issue,TODO,new,0,,2022-08-12T13:54:28.911+00:00,2022-08-12T13:54:28.911+00:00,0,,blocker,0,0,0,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,teoiaoe,,,,
+bitbucket:BitbucketIssue:1:27,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,31,,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/27,,27,issue test024,"issue test024v  aejnoafoeiogoiae
+
+qwofjeoiwjf",,issue,TODO,new,0,,2022-08-12T13:55:09.734+00:00,2022-08-13T06:20:01.410+00:00,0,,trivial,0,0,0,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,teoiaoe,,,,
+bitbucket:BitbucketIssue:1:28,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,34,,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/28,,28,issue test025,issue test025,,issue,TODO,new,0,,2022-08-12T13:55:32.410+00:00,2022-08-12T13:55:58.035+00:00,0,,minor,0,0,0,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,teoiaoe,,,,
+bitbucket:BitbucketIssue:1:29,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,33,,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/29,,29,issue test026,issue test026,,issue,TODO,new,0,,2022-08-12T13:56:26.434+00:00,2022-08-12T13:56:26.434+00:00,0,,critical,0,0,0,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,teoiaoe,,
+bitbucket:BitbucketIssue:1:3,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,58,,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/3,,3,bitbucket test,"efaegjeoaijefioaegrjoeior,af enfaoiee vioea.,,.wew",,issue,TODO,new,0,,2022-07-28T06:41:23.334+00:00,2022-07-28T06:41:23.334+00:00,0,,major,0,0,0,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,teoiaoe,,,,
+bitbucket:BitbucketIssue:1:30,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,32,,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/30,,30,issue test027,issue test027,,issue,TODO,new,0,,2022-08-12T13:56:51.480+00:00,2022-08-12T13:56:51.480+00:00,0,,critical,0,0,0,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,teoiaoe,,
+bitbucket:BitbucketIssue:1:4,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,57,,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/4,,4,issue test001,Bitbucket issue test001,,issue,TODO,new,0,,2022-08-12T13:39:52.109+00:00,2022-08-12T13:39:52.109+00:00,0,,major,0,0,0,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,teoiaoe,,,,
+bitbucket:BitbucketIssue:1:5,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,56,,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/5,,5,issue test002,issue test002,,issue,TODO,new,0,,2022-08-12T13:40:32.843+00:00,2022-08-12T13:40:32.843+00:00,0,,major,0,0,0,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,teoiaoe,,,,
+bitbucket:BitbucketIssue:1:6,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,37,,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/6,,6,issue test003,issue test 003,,issue,TODO,new,0,,2022-08-12T13:40:55.635+00:00,2022-08-12T13:51:25.769+00:00,0,,major,0,0,0,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,teoiaoe,,
+bitbucket:BitbucketIssue:1:7,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,55,,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/7,,7,issue test004,issue test004,,issue,TODO,new,0,,2022-08-12T13:41:21.859+00:00,2022-08-12T13:41:21.859+00:00,0,,major,0,0,0,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,teoiaoe,,,,
+bitbucket:BitbucketIssue:1:8,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,54,,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/8,,8,issue test005,issue test005,,issue,TODO,new,0,,2022-08-12T13:41:58.511+00:00,2022-08-12T13:41:58.511+00:00,0,,critical,0,0,0,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,teoiaoe,,,,
+bitbucket:BitbucketIssue:1:9,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_issues,53,,https://api.bitbucket.org/2.0/repositories/panjf2000/ants/issues/9,,9,issue test006,issue test006,,issue,TODO,new,0,,2022-08-12T13:42:29.072+00:00,2022-08-12T13:42:29.072+00:00,0,,blocker,0,0,0,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,teoiaoe,,
diff --git a/plugins/bitbucket/e2e/snapshot_tables/pull_request_comments.csv b/plugins/bitbucket/e2e/snapshot_tables/pull_request_comments.csv
new file mode 100644
index 00000000..ae71f7c1
--- /dev/null
+++ b/plugins/bitbucket/e2e/snapshot_tables/pull_request_comments.csv
@@ -0,0 +1,21 @@
+id,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark,pull_request_id,body,user_id,commit_sha,position,type,review_id,status
+bitbucket:BitbucketPrComment:1:323119643,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_request_comments,14,,bitbucket:BitbucketPullRequest:1:54,this is test014,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,pullrequest_comment,,
+bitbucket:BitbucketPrComment:1:323119662,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_request_comments,15,,bitbucket:BitbucketPullRequest:1:54,feafjae,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,pullrequest_comment,,
+bitbucket:BitbucketPrComment:1:323119730,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_request_comments,17,,bitbucket:BitbucketPullRequest:1:57,"fejoiafjoej
+
+‌",bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,pullrequest_comment,,
+bitbucket:BitbucketPrComment:1:323119743,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_request_comments,18,,bitbucket:BitbucketPullRequest:1:57,fjeafojeoirjgoar,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,pullrequest_comment,,
+bitbucket:BitbucketPrComment:1:323119784,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_request_comments,12,,bitbucket:BitbucketPullRequest:1:51,fejoafefewa,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,pullrequest_comment,,
+bitbucket:BitbucketPrComment:1:323119790,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_request_comments,13,,bitbucket:BitbucketPullRequest:1:51,feafeogioehrw,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,pullrequest_comment,,
+bitbucket:BitbucketPrComment:1:323119842,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_request_comments,8,,bitbucket:BitbucketPullRequest:1:42,feafoegoaweoir,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,pullrequest_comment,,
+bitbucket:BitbucketPrComment:1:323119856,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_request_comments,9,,bitbucket:BitbucketPullRequest:1:42,boroehruheorefe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,pullrequest_comment,,
+bitbucket:BitbucketPrComment:1:323119897,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_request_comments,16,,bitbucket:BitbucketPullRequest:1:54,feajfweofjwvgrea,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,pullrequest_comment,,
+bitbucket:BitbucketPrComment:1:323119960,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_request_comments,4,,bitbucket:BitbucketPullRequest:1:38,regrioteothro,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,pullrequest_comment,,
+bitbucket:BitbucketPrComment:1:323119980,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_request_comments,5,,bitbucket:BitbucketPullRequest:1:38,goeotbioebhotn,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,pullrequest_comment,,
+bitbucket:BitbucketPrComment:1:323120091,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_request_comments,10,,bitbucket:BitbucketPullRequest:1:44,feawrjoiw,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,pullrequest_comment,,
+bitbucket:BitbucketPrComment:1:323120101,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_request_comments,11,,bitbucket:BitbucketPullRequest:1:44,bbeirobeoiahoa,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,pullrequest_comment,,
+bitbucket:BitbucketPrComment:1:323120140,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_request_comments,6,,bitbucket:BitbucketPullRequest:1:40,evbnoera,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,pullrequest_comment,,
+bitbucket:BitbucketPrComment:1:323120196,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_request_comments,7,,bitbucket:BitbucketPullRequest:1:41,vobreia,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,pullrequest_comment,,
+bitbucket:BitbucketPrComment:1:323120278,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_request_comments,1,,bitbucket:BitbucketPullRequest:1:31,baroboerhba,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,pullrequest_comment,,
+bitbucket:BitbucketPrComment:1:323120296,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_request_comments,2,,bitbucket:BitbucketPullRequest:1:31,bweiwbeanb,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,pullrequest_comment,,
+bitbucket:BitbucketPrComment:1:323120311,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_request_comments,3,,bitbucket:BitbucketPullRequest:1:31,jbirobsore,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,pullrequest_comment,,
diff --git a/plugins/bitbucket/e2e/snapshot_tables/pull_requests.csv b/plugins/bitbucket/e2e/snapshot_tables/pull_requests.csv
new file mode 100644
index 00000000..3b479109
--- /dev/null
+++ b/plugins/bitbucket/e2e/snapshot_tables/pull_requests.csv
@@ -0,0 +1,1257 @@
+id,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark,base_repo_id,head_repo_id,status,title,description,url,author_name,author_id,parent_pr_id,pull_request_key,created_date,merged_date,closed_date,type,component,merge_commit_sha,head_ref,base_ref,base_commit_sha,head_commit_sha
+bitbucket:BitbucketPullRequest:1:1,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,171,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,OPEN,feat: add pr test,this is a pr test for Bitbucket plugin,https://bitbucket.org/panjf2000/ants/pull-requests/1,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-07-12T04:17:03.055+00:00,,,pullrequest,,,test,master,c0e12b61e44b,5e5bccfcc656
+bitbucket:BitbucketPullRequest:1:10,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,161,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,MERGED,Test007,"* feat: add git.sh
+* feat: add test001
+* feat: test002
+* feat: add test003
+* feat: add test004
+* feat: add test005
+* feat: add test006
+* feat: add test007
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/10,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T14:55:28.082+00:00,,,pullrequest,,983edbf06740,test007,master,0bd83caaf9c7,15a1fcb51f0e
+bitbucket:BitbucketPullRequest:1:11,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,160,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,MERGED,Test6,"* feat: add git.sh
+* feat: add test001
+* feat: test002
+* feat: add test003
+* feat: add test004
+* feat: add test005
+* feat: add test006
+* feat: add test007
+* feat: add test008
+* feat: add test009
+* feat: add test010
+* feat: add test011
+* feat: add test012
+* feat: add test013
+* feat: add branchname
+* feat: add 1
+* feat: add 2
+* feat: add 3
+* feat: add 4
+* feat: add 5
+* feat: add test6
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/11,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T14:55:48.770+00:00,,,pullrequest,,983edbf06740,test6,master,0bd83caaf9c7,bc9a3ddd47ea
+bitbucket:BitbucketPullRequest:1:12,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,159,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,MERGED,Test7,"* feat: add git.sh
+* feat: add test001
+* feat: test002
+* feat: add test003
+* feat: add test004
+* feat: add test005
+* feat: add test006
+* feat: add test007
+* feat: add test008
+* feat: add test009
+* feat: add test010
+* feat: add test011
+* feat: add test012
+* feat: add test013
+* feat: add branchname
+* feat: add 1
+* feat: add 2
+* feat: add 3
+* feat: add 4
+* feat: add 5
+* feat: add test6
+* feat: add test7
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/12,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T14:56:07.092+00:00,,,pullrequest,,983edbf06740,test7,master,0bd83caaf9c7,dd2cd76d7098
+bitbucket:BitbucketPullRequest:1:13,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,158,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,MERGED,Test8,"* feat: add git.sh
+* feat: add test001
+* feat: test002
+* feat: add test003
+* feat: add test004
+* feat: add test005
+* feat: add test006
+* feat: add test007
+* feat: add test008
+* feat: add test009
+* feat: add test010
+* feat: add test011
+* feat: add test012
+* feat: add test013
+* feat: add branchname
+* feat: add 1
+* feat: add 2
+* feat: add 3
+* feat: add 4
+* feat: add 5
+* feat: add test6
+* feat: add test7
+* feat: add test8
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/13,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T14:56:30.570+00:00,,,pullrequest,,983edbf06740,test8,master,0bd83caaf9c7,94056215cf46
+bitbucket:BitbucketPullRequest:1:14,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,157,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,MERGED,Test10,"* feat: add git.sh
+* feat: add test001
+* feat: test002
+* feat: add test003
+* feat: add test004
+* feat: add test005
+* feat: add test006
+* feat: add test007
+* feat: add test008
+* feat: add test009
+* feat: add test010
+* feat: add test011
+* feat: add test012
+* feat: add test013
+* feat: add branchname
+* feat: add 1
+* feat: add 2
+* feat: add 3
+* feat: add 4
+* feat: add 5
+* feat: add test6
+* feat: add test7
+* feat: add test8
+* feat: add test9
+* feat: add test10
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/14,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T14:56:52.550+00:00,,,pullrequest,,983edbf06740,test10,master,0bd83caaf9c7,bc2cf25142e3
+bitbucket:BitbucketPullRequest:1:15,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,156,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,MERGED,Test011,"* feat: add git.sh
+* feat: add test001
+* feat: test002
+* feat: add test003
+* feat: add test004
+* feat: add test005
+* feat: add test006
+* feat: add test007
+* feat: add test008
+* feat: add test009
+* feat: add test010
+* feat: add test011
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/15,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T14:57:15.254+00:00,,,pullrequest,,983edbf06740,test011,master,0bd83caaf9c7,5db6b1a9e60c
+bitbucket:BitbucketPullRequest:1:16,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,170,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,MERGED,Test12,"* feat: add git.sh
+* feat: add test001
+* feat: test002
+* feat: add test003
+* feat: add test004
+* feat: add test005
+* feat: add test006
+* feat: add test007
+* feat: add test008
+* feat: add test009
+* feat: add test010
+* feat: add test011
+* feat: add test012
+* feat: add test013
+* feat: add branchname
+* feat: add 1
+* feat: add 2
+* feat: add 3
+* feat: add 4
+* feat: add 5
+* feat: add test6
+* feat: add test7
+* feat: add test8
+* feat: add test9
+* feat: add test10
+* feat: add test11
+* feat: add test12
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/16,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T14:57:41.230+00:00,,,pullrequest,,983edbf06740,test12,master,0bd83caaf9c7,d1321cb5e4fb
+bitbucket:BitbucketPullRequest:1:17,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,151,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,MERGED,Test13,"* feat: add git.sh
+* feat: add test001
+* feat: test002
+* feat: add test003
+* feat: add test004
+* feat: add test005
+* feat: add test006
+* feat: add test007
+* feat: add test008
+* feat: add test009
+* feat: add test010
+* feat: add test011
+* feat: add test012
+* feat: add test013
+* feat: add branchname
+* feat: add 1
+* feat: add 2
+* feat: add 3
+* feat: add 4
+* feat: add 5
+* feat: add test6
+* feat: add test7
+* feat: add test8
+* feat: add test9
+* feat: add test10
+* feat: add test11
+* feat: add test12
+* feat: add test13
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/17,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T14:57:59.501+00:00,,,pullrequest,,c0e12b61e44b,test13,master,983edbf06740,3d6d96659c4d
+bitbucket:BitbucketPullRequest:1:18,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,150,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,MERGED,Test14,"* feat: add git.sh
+* feat: add test001
+* feat: test002
+* feat: add test003
+* feat: add test004
+* feat: add test005
+* feat: add test006
+* feat: add test007
+* feat: add test008
+* feat: add test009
+* feat: add test010
+* feat: add test011
+* feat: add test012
+* feat: add test013
+* feat: add branchname
+* feat: add 1
+* feat: add 2
+* feat: add 3
+* feat: add 4
+* feat: add 5
+* feat: add test6
+* feat: add test7
+* feat: add test8
+* feat: add test9
+* feat: add test10
+* feat: add test11
+* feat: add test12
+* feat: add test13
+* feat: add test14
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/18,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T14:58:16.105+00:00,,,pullrequest,,c0e12b61e44b,test14,master,983edbf06740,8d4896eef3ed
+bitbucket:BitbucketPullRequest:1:19,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,149,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,MERGED,Test15,"* feat: add git.sh
+* feat: add test001
+* feat: test002
+* feat: add test003
+* feat: add test004
+* feat: add test005
+* feat: add test006
+* feat: add test007
+* feat: add test008
+* feat: add test009
+* feat: add test010
+* feat: add test011
+* feat: add test012
+* feat: add test013
+* feat: add branchname
+* feat: add 1
+* feat: add 2
+* feat: add 3
+* feat: add 4
+* feat: add 5
+* feat: add test6
+* feat: add test7
+* feat: add test8
+* feat: add test9
+* feat: add test10
+* feat: add test11
+* feat: add test12
+* feat: add test13
+* feat: add test14
+* feat: add test15
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/19,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T14:58:33.361+00:00,,,pullrequest,,c0e12b61e44b,test15,master,983edbf06740,daa1cfa7ec0c
+bitbucket:BitbucketPullRequest:1:2,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,169,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,MERGED,feat: add git.sh,help to git commit faster,https://bitbucket.org/panjf2000/ants/pull-requests/2,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T13:18:39.132+00:00,,,pullrequest,,983edbf06740,vowehwo,master,0bd83caaf9c7,d4a6789a3751
+bitbucket:BitbucketPullRequest:1:20,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,148,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,MERGED,Test16,"* feat: add git.sh
+* feat: add test001
+* feat: test002
+* feat: add test003
+* feat: add test004
+* feat: add test005
+* feat: add test006
+* feat: add test007
+* feat: add test008
+* feat: add test009
+* feat: add test010
+* feat: add test011
+* feat: add test012
+* feat: add test013
+* feat: add branchname
+* feat: add 1
+* feat: add 2
+* feat: add 3
+* feat: add 4
+* feat: add 5
+* feat: add test6
+* feat: add test7
+* feat: add test8
+* feat: add test9
+* feat: add test10
+* feat: add test11
+* feat: add test12
+* feat: add test13
+* feat: add test14
+* feat: add test15
+* feat: add test16
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/20,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T14:59:07.791+00:00,,,pullrequest,,c0e12b61e44b,test16,master,983edbf06740,11f6c86580e2
+bitbucket:BitbucketPullRequest:1:21,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,147,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,MERGED,Test18,"* feat: add git.sh
+* feat: add test001
+* feat: test002
+* feat: add test003
+* feat: add test004
+* feat: add test005
+* feat: add test006
+* feat: add test007
+* feat: add test008
+* feat: add test009
+* feat: add test010
+* feat: add test011
+* feat: add test012
+* feat: add test013
+* feat: add branchname
+* feat: add 1
+* feat: add 2
+* feat: add 3
+* feat: add 4
+* feat: add 5
+* feat: add test6
+* feat: add test7
+* feat: add test8
+* feat: add test9
+* feat: add test10
+* feat: add test11
+* feat: add test12
+* feat: add test13
+* feat: add test14
+* feat: add test15
+* feat: add test16
+* feat: add test17
+* feat: add test18
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/21,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T14:59:22.874+00:00,,,pullrequest,,c0e12b61e44b,test18,master,983edbf06740,0b958bbfed04
+bitbucket:BitbucketPullRequest:1:22,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,146,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,MERGED,Test19,"* feat: add git.sh
+* feat: add test001
+* feat: test002
+* feat: add test003
+* feat: add test004
+* feat: add test005
+* feat: add test006
+* feat: add test007
+* feat: add test008
+* feat: add test009
+* feat: add test010
+* feat: add test011
+* feat: add test012
+* feat: add test013
+* feat: add branchname
+* feat: add 1
+* feat: add 2
+* feat: add 3
+* feat: add 4
+* feat: add 5
+* feat: add test6
+* feat: add test7
+* feat: add test8
+* feat: add test9
+* feat: add test10
+* feat: add test11
+* feat: add test12
+* feat: add test13
+* feat: add test14
+* feat: add test15
+* feat: add test16
+* feat: add test17
+* feat: add test18
+* feat: add test19
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/22,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T14:59:39.610+00:00,,,pullrequest,,c0e12b61e44b,test19,master,983edbf06740,d1bb3677810e
+bitbucket:BitbucketPullRequest:1:23,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,145,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,MERGED,Test20,"* feat: add git.sh
+* feat: add test001
+* feat: test002
+* feat: add test003
+* feat: add test004
+* feat: add test005
+* feat: add test006
+* feat: add test007
+* feat: add test008
+* feat: add test009
+* feat: add test010
+* feat: add test011
+* feat: add test012
+* feat: add test013
+* feat: add branchname
+* feat: add 1
+* feat: add 2
+* feat: add 3
+* feat: add 4
+* feat: add 5
+* feat: add test6
+* feat: add test7
+* feat: add test8
+* feat: add test9
+* feat: add test10
+* feat: add test11
+* feat: add test12
+* feat: add test13
+* feat: add test14
+* feat: add test15
+* feat: add test16
+* feat: add test17
+* feat: add test18
+* feat: add test19
+* feat: add test20
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/23,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T14:59:57.869+00:00,,,pullrequest,,c0e12b61e44b,test20,master,983edbf06740,9d16a2368acd
+bitbucket:BitbucketPullRequest:1:24,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,144,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,MERGED,Test17,"* feat: add git.sh
+* feat: add test001
+* feat: test002
+* feat: add test003
+* feat: add test004
+* feat: add test005
+* feat: add test006
+* feat: add test007
+* feat: add test008
+* feat: add test009
+* feat: add test010
+* feat: add test011
+* feat: add test012
+* feat: add test013
+* feat: add branchname
+* feat: add 1
+* feat: add 2
+* feat: add 3
+* feat: add 4
+* feat: add 5
+* feat: add test6
+* feat: add test7
+* feat: add test8
+* feat: add test9
+* feat: add test10
+* feat: add test11
+* feat: add test12
+* feat: add test13
+* feat: add test14
+* feat: add test15
+* feat: add test16
+* feat: add test17
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/24,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T15:00:34.399+00:00,,,pullrequest,,c0e12b61e44b,test17,master,983edbf06740,2bfd29a17665
+bitbucket:BitbucketPullRequest:1:25,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,155,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,MERGED,1,"* feat: add git.sh
+* feat: add test001
+* feat: test002
+* feat: add test003
+* feat: add test004
+* feat: add test005
+* feat: add test006
+* feat: add test007
+* feat: add test008
+* feat: add test009
+* feat: add test010
+* feat: add test011
+* feat: add test012
+* feat: add test013
+* feat: add branchname
+* feat: add 1
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/25,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T15:00:59.503+00:00,,,pullrequest,,983edbf06740,1,master,0bd83caaf9c7,592612c47ff5
+bitbucket:BitbucketPullRequest:1:26,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,154,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,MERGED,2,"* feat: add git.sh
+* feat: add test001
+* feat: test002
+* feat: add test003
+* feat: add test004
+* feat: add test005
+* feat: add test006
+* feat: add test007
+* feat: add test008
+* feat: add test009
+* feat: add test010
+* feat: add test011
+* feat: add test012
+* feat: add test013
+* feat: add branchname
+* feat: add 1
+* feat: add 2
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/26,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T15:01:18.980+00:00,,,pullrequest,,983edbf06740,2,master,0bd83caaf9c7,05b97cf92b4b
+bitbucket:BitbucketPullRequest:1:27,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,153,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,MERGED,4,"* feat: add git.sh
+* feat: add test001
+* feat: test002
+* feat: add test003
+* feat: add test004
+* feat: add test005
+* feat: add test006
+* feat: add test007
+* feat: add test008
+* feat: add test009
+* feat: add test010
+* feat: add test011
+* feat: add test012
+* feat: add test013
+* feat: add branchname
+* feat: add 1
+* feat: add 2
+* feat: add 3
+* feat: add 4
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/27,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T15:02:16.840+00:00,,,pullrequest,,983edbf06740,4,master,0bd83caaf9c7,761fdb9244ef
+bitbucket:BitbucketPullRequest:1:28,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,152,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,MERGED,mergev1,merge all v1,https://bitbucket.org/panjf2000/ants/pull-requests/28,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T15:10:16.367+00:00,,,pullrequest,,c0e12b61e44b,mergev1,master,983edbf06740,581a89006076
+bitbucket:BitbucketPullRequest:1:29,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,132,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,OPEN,Test03,"* feat: add test01
+* feat: add test02
+* feat: add test03
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/29,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T15:21:47.437+00:00,,,pullrequest,,,test03,master,c0e12b61e44b,a3768d182d18
+bitbucket:BitbucketPullRequest:1:3,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,168,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,MERGED,Test9,"* feat: add git.sh
+* feat: add test001
+* feat: test002
+* feat: add test003
+* feat: add test004
+* feat: add test005
+* feat: add test006
+* feat: add test007
+* feat: add test008
+* feat: add test009
+* feat: add test010
+* feat: add test011
+* feat: add test012
+* feat: add test013
+* feat: add branchname
+* feat: add 1
+* feat: add 2
+* feat: add 3
+* feat: add 4
+* feat: add 5
+* feat: add test6
+* feat: add test7
+* feat: add test8
+* feat: add test9
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/3,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T14:53:19.796+00:00,,,pullrequest,,983edbf06740,test9,master,0bd83caaf9c7,6557208f4aa6
+bitbucket:BitbucketPullRequest:1:30,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,143,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,OPEN,Test05,"* feat: add test01
+* feat: add test02
+* feat: add test03
+* feat: add test04
+* feat: add test05
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/30,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T15:22:17.954+00:00,,,pullrequest,,,test05,master,c0e12b61e44b,91e7a1db9ae0
+bitbucket:BitbucketPullRequest:1:31,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,118,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,OPEN,Test020,"* feat: add test01
+* feat: add test02
+* feat: add test03
+* feat: add test04
+* feat: add test05
+* feat: add test06
+* feat: add test07
+* feat: add test08
+* feat: add test09
+* feat: add test010
+* feat: add test011
+* feat: add test012
+* feat: add test013
+* feat: add test014
+* feat: add test015
+* feat: add test016
+* feat: add test017
+* feat: add test018
+* feat: add test019
+* feat: add test020
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/31,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T15:22:51.303+00:00,,,pullrequest,,,test020,master,c0e12b61e44b,0342bf5351f8
+bitbucket:BitbucketPullRequest:1:32,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,142,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,OPEN,Test022,"* feat: add test01
+* feat: add test02
+* feat: add test03
+* feat: add test04
+* feat: add test05
+* feat: add test06
+* feat: add test07
+* feat: add test08
+* feat: add test09
+* feat: add test010
+* feat: add test011
+* feat: add test012
+* feat: add test013
+* feat: add test014
+* feat: add test015
+* feat: add test016
+* feat: add test017
+* feat: add test018
+* feat: add test019
+* feat: add test020
+* feat: add test021
+* feat: add test022
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/32,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T15:23:06.858+00:00,,,pullrequest,,,test022,master,c0e12b61e44b,d72c46a722d7
+bitbucket:BitbucketPullRequest:1:33,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,141,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,OPEN,Test023,"* feat: add test01
+* feat: add test02
+* feat: add test03
+* feat: add test04
+* feat: add test05
+* feat: add test06
+* feat: add test07
+* feat: add test08
+* feat: add test09
+* feat: add test010
+* feat: add test011
+* feat: add test012
+* feat: add test013
+* feat: add test014
+* feat: add test015
+* feat: add test016
+* feat: add test017
+* feat: add test018
+* feat: add test019
+* feat: add test020
+* feat: add test021
+* feat: add test022
+* feat: add test023
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/33,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T15:23:27.568+00:00,,,pullrequest,,,test023,master,c0e12b61e44b,0a8011c8c0ac
+bitbucket:BitbucketPullRequest:1:34,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,140,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,OPEN,Test024,"* feat: add test01
+* feat: add test02
+* feat: add test03
+* feat: add test04
+* feat: add test05
+* feat: add test06
+* feat: add test07
+* feat: add test08
+* feat: add test09
+* feat: add test010
+* feat: add test011
+* feat: add test012
+* feat: add test013
+* feat: add test014
+* feat: add test015
+* feat: add test016
+* feat: add test017
+* feat: add test018
+* feat: add test019
+* feat: add test020
+* feat: add test021
+* feat: add test022
+* feat: add test023
+* feat: add test024
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/34,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T15:23:42.883+00:00,,,pullrequest,,,test024,master,c0e12b61e44b,bd7e81a581f1
+bitbucket:BitbucketPullRequest:1:35,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,139,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,OPEN,Test025,"* feat: add test01
+* feat: add test02
+* feat: add test03
+* feat: add test04
+* feat: add test05
+* feat: add test06
+* feat: add test07
+* feat: add test08
+* feat: add test09
+* feat: add test010
+* feat: add test011
+* feat: add test012
+* feat: add test013
+* feat: add test014
+* feat: add test015
+* feat: add test016
+* feat: add test017
+* feat: add test018
+* feat: add test019
+* feat: add test020
+* feat: add test021
+* feat: add test022
+* feat: add test023
+* feat: add test024
+* feat: add test025
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/35,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T15:23:58.227+00:00,,,pullrequest,,,test025,master,c0e12b61e44b,a15cb5876414
+bitbucket:BitbucketPullRequest:1:36,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,138,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,OPEN,Test027,"* feat: add test01
+* feat: add test02
+* feat: add test03
+* feat: add test04
+* feat: add test05
+* feat: add test06
+* feat: add test07
+* feat: add test08
+* feat: add test09
+* feat: add test010
+* feat: add test011
+* feat: add test012
+* feat: add test013
+* feat: add test014
+* feat: add test015
+* feat: add test016
+* feat: add test017
+* feat: add test018
+* feat: add test019
+* feat: add test020
+* feat: add test021
+* feat: add test022
+* feat: add test023
+* feat: add test024
+* feat: add test025
+* feat: add test026
+* feat: add test027
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/36,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T15:24:16.607+00:00,,,pullrequest,,,test027,master,c0e12b61e44b,200665f463ff
+bitbucket:BitbucketPullRequest:1:37,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,137,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,OPEN,Test028,"* feat: add test01
+* feat: add test02
+* feat: add test03
+* feat: add test04
+* feat: add test05
+* feat: add test06
+* feat: add test07
+* feat: add test08
+* feat: add test09
+* feat: add test010
+* feat: add test011
+* feat: add test012
+* feat: add test013
+* feat: add test014
+* feat: add test015
+* feat: add test016
+* feat: add test017
+* feat: add test018
+* feat: add test019
+* feat: add test020
+* feat: add test021
+* feat: add test022
+* feat: add test023
+* feat: add test024
+* feat: add test025
+* feat: add test026
+* feat: add test027
+* feat: add test028
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/37,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T15:24:44.626+00:00,,,pullrequest,,,test028,master,c0e12b61e44b,8a9052ac97f4
+bitbucket:BitbucketPullRequest:1:38,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,121,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,OPEN,Test029,"* feat: add test01
+* feat: add test02
+* feat: add test03
+* feat: add test04
+* feat: add test05
+* feat: add test06
+* feat: add test07
+* feat: add test08
+* feat: add test09
+* feat: add test010
+* feat: add test011
+* feat: add test012
+* feat: add test013
+* feat: add test014
+* feat: add test015
+* feat: add test016
+* feat: add test017
+* feat: add test018
+* feat: add test019
+* feat: add test020
+* feat: add test021
+* feat: add test022
+* feat: add test023
+* feat: add test024
+* feat: add test025
+* feat: add test026
+* feat: add test027
+* feat: add test028
+* feat: add test029
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/38,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T15:24:59.520+00:00,,,pullrequest,,,test029,master,c0e12b61e44b,74bddc0541c6
+bitbucket:BitbucketPullRequest:1:39,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,136,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,OPEN,Test030,"* feat: add test01
+* feat: add test02
+* feat: add test03
+* feat: add test04
+* feat: add test05
+* feat: add test06
+* feat: add test07
+* feat: add test08
+* feat: add test09
+* feat: add test010
+* feat: add test011
+* feat: add test012
+* feat: add test013
+* feat: add test014
+* feat: add test015
+* feat: add test016
+* feat: add test017
+* feat: add test018
+* feat: add test019
+* feat: add test020
+* feat: add test021
+* feat: add test022
+* feat: add test023
+* feat: add test024
+* feat: add test025
+* feat: add test026
+* feat: add test027
+* feat: add test028
+* feat: add test029
+* feat: add test030
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/39,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T15:25:14.361+00:00,,,pullrequest,,,test030,master,c0e12b61e44b,f332a9855de1
+bitbucket:BitbucketPullRequest:1:4,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,167,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,MERGED,Test001,"* feat: add git.sh
+* feat: add test001
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/4,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T14:53:43.845+00:00,,,pullrequest,,983edbf06740,test001,master,0bd83caaf9c7,3bd3b34b2397
+bitbucket:BitbucketPullRequest:1:40,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,115,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,OPEN,Test016,"* feat: add test01
+* feat: add test02
+* feat: add test03
+* feat: add test04
+* feat: add test05
+* feat: add test06
+* feat: add test07
+* feat: add test08
+* feat: add test09
+* feat: add test010
+* feat: add test011
+* feat: add test012
+* feat: add test013
+* feat: add test014
+* feat: add test015
+* feat: add test016
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/40,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T15:25:31.596+00:00,,,pullrequest,,,test016,master,c0e12b61e44b,a000a2a9fc11
+bitbucket:BitbucketPullRequest:1:41,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,119,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,OPEN,Test018,"* feat: add test01
+* feat: add test02
+* feat: add test03
+* feat: add test04
+* feat: add test05
+* feat: add test06
+* feat: add test07
+* feat: add test08
+* feat: add test09
+* feat: add test010
+* feat: add test011
+* feat: add test012
+* feat: add test013
+* feat: add test014
+* feat: add test015
+* feat: add test016
+* feat: add test017
+* feat: add test018
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/41,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T15:25:57.607+00:00,,,pullrequest,,,test018,master,c0e12b61e44b,561e4e3ca4cc
+bitbucket:BitbucketPullRequest:1:42,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,117,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,OPEN,Test019,"* feat: add test01
+* feat: add test02
+* feat: add test03
+* feat: add test04
+* feat: add test05
+* feat: add test06
+* feat: add test07
+* feat: add test08
+* feat: add test09
+* feat: add test010
+* feat: add test011
+* feat: add test012
+* feat: add test013
+* feat: add test014
+* feat: add test015
+* feat: add test016
+* feat: add test017
+* feat: add test018
+* feat: add test019
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/42,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T15:26:15.843+00:00,,,pullrequest,,,test019,master,c0e12b61e44b,8597a99eebb3
+bitbucket:BitbucketPullRequest:1:43,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,135,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,OPEN,Test015,"* feat: add test01
+* feat: add test02
+* feat: add test03
+* feat: add test04
+* feat: add test05
+* feat: add test06
+* feat: add test07
+* feat: add test08
+* feat: add test09
+* feat: add test010
+* feat: add test011
+* feat: add test012
+* feat: add test013
+* feat: add test014
+* feat: add test015
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/43,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T15:26:50.905+00:00,,,pullrequest,,,test015,master,c0e12b61e44b,5af2c361263a
+bitbucket:BitbucketPullRequest:1:44,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,120,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,OPEN,Test017,"* feat: add test01
+* feat: add test02
+* feat: add test03
+* feat: add test04
+* feat: add test05
+* feat: add test06
+* feat: add test07
+* feat: add test08
+* feat: add test09
+* feat: add test010
+* feat: add test011
+* feat: add test012
+* feat: add test013
+* feat: add test014
+* feat: add test015
+* feat: add test016
+* feat: add test017
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/44,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T15:27:54.969+00:00,,,pullrequest,,,test017,master,c0e12b61e44b,ee87b0380472
+bitbucket:BitbucketPullRequest:1:45,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,134,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,OPEN,feat: add test01,,https://bitbucket.org/panjf2000/ants/pull-requests/45,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T15:28:43.059+00:00,,,pullrequest,,,test01,master,c0e12b61e44b,63e6acbb60a9
+bitbucket:BitbucketPullRequest:1:46,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,133,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,OPEN,Test04,"* feat: add test01
+* feat: add test02
+* feat: add test03
+* feat: add test04
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/46,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T15:28:57.787+00:00,,,pullrequest,,,test04,master,c0e12b61e44b,33419e166d75
+bitbucket:BitbucketPullRequest:1:47,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,131,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,OPEN,Test06,"* feat: add test01
+* feat: add test02
+* feat: add test03
+* feat: add test04
+* feat: add test05
+* feat: add test06
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/47,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T15:29:31.360+00:00,,,pullrequest,,,test06,master,c0e12b61e44b,f8f9ef467e3a
+bitbucket:BitbucketPullRequest:1:48,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,130,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,OPEN,Test07,"* feat: add test01
+* feat: add test02
+* feat: add test03
+* feat: add test04
+* feat: add test05
+* feat: add test06
+* feat: add test07
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/48,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T15:29:49.045+00:00,,,pullrequest,,,test07,master,c0e12b61e44b,c28f34dde568
+bitbucket:BitbucketPullRequest:1:49,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,129,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,OPEN,Test08,"* feat: add test01
+* feat: add test02
+* feat: add test03
+* feat: add test04
+* feat: add test05
+* feat: add test06
+* feat: add test07
+* feat: add test08
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/49,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T15:30:04.329+00:00,,,pullrequest,,,test08,master,c0e12b61e44b,6b59c8607581
+bitbucket:BitbucketPullRequest:1:5,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,166,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,MERGED,Test002,"* feat: add git.sh
+* feat: add test001
+* feat: test002
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/5,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T14:53:59.654+00:00,,,pullrequest,,983edbf06740,test002,master,0bd83caaf9c7,904df6924f1e
+bitbucket:BitbucketPullRequest:1:50,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,128,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,OPEN,Bitbuckettest12,"* feat: add test01
+* feat: add test02
+* feat: add test03
+* feat: add test04
+* feat: add test05
+* feat: add test06
+* feat: add test07
+* feat: add test08
+* feat: add test09
+* feat: add test010
+* feat: add test011
+* feat: add test012
+* feat: add test013
+* feat: add test014
+* feat: add test015
+* feat: add test016
+* feat: add test017
+* feat: add test018
+* feat: add test019
+* feat: add test020
+* feat: add test021
+* feat: add test022
+* feat: add test023
+* feat: add test024
+* feat: add test025
+* feat: add test026
+* feat: add test027
+* feat: add test028
+* feat: add test029
+* feat: add test030
+* feat: add bitbucket
+* feat: add bitbucket
+* feat: add bitbuckettest12
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/50,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T15:32:46.725+00:00,,,pullrequest,,,bitbuckettest12,master,c0e12b61e44b,deff6927812f
+bitbucket:BitbucketPullRequest:1:51,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,122,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,OPEN,Bitbuckettest15,"* feat: add test01
+* feat: add test02
+* feat: add test03
+* feat: add test04
+* feat: add test05
+* feat: add test06
+* feat: add test07
+* feat: add test08
+* feat: add test09
+* feat: add test010
+* feat: add test011
+* feat: add test012
+* feat: add test013
+* feat: add test014
+* feat: add test015
+* feat: add test016
+* feat: add test017
+* feat: add test018
+* feat: add test019
+* feat: add test020
+* feat: add test021
+* feat: add test022
+* feat: add test023
+* feat: add test024
+* feat: add test025
+* feat: add test026
+* feat: add test027
+* feat: add test028
+* feat: add test029
+* feat: add test030
+* feat: add bitbucket
+* feat: add bitbucket
+* feat: add bitbuckettest12
+* feat: add bitbuckettest13
+* feat: add bitbuckettest14
+* feat: add bitbuckettest15
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/51,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T15:32:59.604+00:00,,,pullrequest,,,bitbuckettest15,master,c0e12b61e44b,5c2c9af70da2
+bitbucket:BitbucketPullRequest:1:52,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,127,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,OPEN,Bitbuckettest16,"* feat: add test01
+* feat: add test02
+* feat: add test03
+* feat: add test04
+* feat: add test05
+* feat: add test06
+* feat: add test07
+* feat: add test08
+* feat: add test09
+* feat: add test010
+* feat: add test011
+* feat: add test012
+* feat: add test013
+* feat: add test014
+* feat: add test015
+* feat: add test016
+* feat: add test017
+* feat: add test018
+* feat: add test019
+* feat: add test020
+* feat: add test021
+* feat: add test022
+* feat: add test023
+* feat: add test024
+* feat: add test025
+* feat: add test026
+* feat: add test027
+* feat: add test028
+* feat: add test029
+* feat: add test030
+* feat: add bitbucket
+* feat: add bitbucket
+* feat: add bitbuckettest12
+* feat: add bitbuckettest13
+* feat: add bitbuckettest14
+* feat: add bitbuckettest15
+* feat: add bitbuckettest16
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/52,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T15:33:13.806+00:00,,,pullrequest,,,bitbuckettest16,master,c0e12b61e44b,7c91d40ffaa3
+bitbucket:BitbucketPullRequest:1:53,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,125,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,OPEN,Bitbuckettest17,"* feat: add test01
+* feat: add test02
+* feat: add test03
+* feat: add test04
+* feat: add test05
+* feat: add test06
+* feat: add test07
+* feat: add test08
+* feat: add test09
+* feat: add test010
+* feat: add test011
+* feat: add test012
+* feat: add test013
+* feat: add test014
+* feat: add test015
+* feat: add test016
+* feat: add test017
+* feat: add test018
+* feat: add test019
+* feat: add test020
+* feat: add test021
+* feat: add test022
+* feat: add test023
+* feat: add test024
+* feat: add test025
+* feat: add test026
+* feat: add test027
+* feat: add test028
+* feat: add test029
+* feat: add test030
+* feat: add bitbucket
+* feat: add bitbucket
+* feat: add bitbuckettest12
+* feat: add bitbuckettest13
+* feat: add bitbuckettest14
+* feat: add bitbuckettest15
+* feat: add bitbuckettest16
+* feat: add bitbuckettest17
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/53,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T15:33:29.075+00:00,,,pullrequest,,,bitbuckettest17,master,c0e12b61e44b,765ab2594451
+bitbucket:BitbucketPullRequest:1:54,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,116,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,OPEN,Bitbuckettest19,"* feat: add test01
+* feat: add test02
+* feat: add test03
+* feat: add test04
+* feat: add test05
+* feat: add test06
+* feat: add test07
+* feat: add test08
+* feat: add test09
+* feat: add test010
+* feat: add test011
+* feat: add test012
+* feat: add test013
+* feat: add test014
+* feat: add test015
+* feat: add test016
+* feat: add test017
+* feat: add test018
+* feat: add test019
+* feat: add test020
+* feat: add test021
+* feat: add test022
+* feat: add test023
+* feat: add test024
+* feat: add test025
+* feat: add test026
+* feat: add test027
+* feat: add test028
+* feat: add test029
+* feat: add test030
+* feat: add bitbucket
+* feat: add bitbucket
+* feat: add bitbuckettest12
+* feat: add bitbuckettest13
+* feat: add bitbuckettest14
+* feat: add bitbuckettest15
+* feat: add bitbuckettest16
+* feat: add bitbuckettest17
+* feat: add bitbuckettest18
+* feat: add bitbuckettest19
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/54,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T15:33:43.689+00:00,,,pullrequest,,,bitbuckettest19,master,c0e12b61e44b,2493b9212fd4
+bitbucket:BitbucketPullRequest:1:55,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,126,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,OPEN,Bitbuckettest13,"* feat: add test01
+* feat: add test02
+* feat: add test03
+* feat: add test04
+* feat: add test05
+* feat: add test06
+* feat: add test07
+* feat: add test08
+* feat: add test09
+* feat: add test010
+* feat: add test011
+* feat: add test012
+* feat: add test013
+* feat: add test014
+* feat: add test015
+* feat: add test016
+* feat: add test017
+* feat: add test018
+* feat: add test019
+* feat: add test020
+* feat: add test021
+* feat: add test022
+* feat: add test023
+* feat: add test024
+* feat: add test025
+* feat: add test026
+* feat: add test027
+* feat: add test028
+* feat: add test029
+* feat: add test030
+* feat: add bitbucket
+* feat: add bitbucket
+* feat: add bitbuckettest12
+* feat: add bitbuckettest13
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/55,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T15:34:03.617+00:00,,,pullrequest,,,bitbuckettest13,master,c0e12b61e44b,9dd8c98115ca
+bitbucket:BitbucketPullRequest:1:56,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,124,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,OPEN,Bitbuckettest25,"* feat: add test01
+* feat: add test02
+* feat: add test03
+* feat: add test04
+* feat: add test05
+* feat: add test06
+* feat: add test07
+* feat: add test08
+* feat: add test09
+* feat: add test010
+* feat: add test011
+* feat: add test012
+* feat: add test013
+* feat: add test014
+* feat: add test015
+* feat: add test016
+* feat: add test017
+* feat: add test018
+* feat: add test019
+* feat: add test020
+* feat: add test021
+* feat: add test022
+* feat: add test023
+* feat: add test024
+* feat: add test025
+* feat: add test026
+* feat: add test027
+* feat: add test028
+* feat: add test029
+* feat: add test030
+* feat: add bitbucket
+* feat: add bitbucket
+* feat: add bitbuckettest12
+* feat: add bitbuckettest13
+* feat: add bitbuckettest14
+* feat: add bitbuckettest15
+* feat: add bitbuckettest16
+* feat: add bitbuckettest17
+* feat: add bitbuckettest18
+* feat: add bitbuckettest19
+* feat: add bitbuckettest20
+* feat: add bitbuckettest21
+* feat: add bitbuckettest22
+* feat: add bitbuckettest23
+* feat: add bitbuckettest24
+* feat: add bitbuckettest25
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/56,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T15:34:37.513+00:00,,,pullrequest,,,bitbuckettest25,master,c0e12b61e44b,d69faf8c90c4
+bitbucket:BitbucketPullRequest:1:57,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,123,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,OPEN,Bitbuckettest22,"* feat: add test01
+* feat: add test02
+* feat: add test03
+* feat: add test04
+* feat: add test05
+* feat: add test06
+* feat: add test07
+* feat: add test08
+* feat: add test09
+* feat: add test010
+* feat: add test011
+* feat: add test012
+* feat: add test013
+* feat: add test014
+* feat: add test015
+* feat: add test016
+* feat: add test017
+* feat: add test018
+* feat: add test019
+* feat: add test020
+* feat: add test021
+* feat: add test022
+* feat: add test023
+* feat: add test024
+* feat: add test025
+* feat: add test026
+* feat: add test027
+* feat: add test028
+* feat: add test029
+* feat: add test030
+* feat: add bitbucket
+* feat: add bitbucket
+* feat: add bitbuckettest12
+* feat: add bitbuckettest13
+* feat: add bitbuckettest14
+* feat: add bitbuckettest15
+* feat: add bitbuckettest16
+* feat: add bitbuckettest17
+* feat: add bitbuckettest18
+* feat: add bitbuckettest19
+* feat: add bitbuckettest20
+* feat: add bitbuckettest21
+* feat: add bitbuckettest22
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/57,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T15:34:55.738+00:00,,,pullrequest,,,bitbuckettest22,master,c0e12b61e44b,2c23b3babf27
+bitbucket:BitbucketPullRequest:1:6,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,165,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,MERGED,Test003,"* feat: add git.sh
+* feat: add test001
+* feat: test002
+* feat: add test003
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/6,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T14:54:20.308+00:00,,,pullrequest,,983edbf06740,test003,master,0bd83caaf9c7,494b97e9d0b2
+bitbucket:BitbucketPullRequest:1:7,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,164,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,MERGED,Test004,"* feat: add git.sh
+* feat: add test001
+* feat: test002
+* feat: add test003
+* feat: add test004
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/7,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T14:54:40.056+00:00,,,pullrequest,,983edbf06740,test004,master,0bd83caaf9c7,db921ce6537c
+bitbucket:BitbucketPullRequest:1:8,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,163,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,MERGED,Test005,"* feat: add git.sh
+* feat: add test001
+* feat: test002
+* feat: add test003
+* feat: add test004
+* feat: add test005
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/8,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T14:54:56.506+00:00,,,pullrequest,,983edbf06740,test005,master,0bd83caaf9c7,8a224cc0eaae
+bitbucket:BitbucketPullRequest:1:9,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_pull_requests,162,,bitbucket:BitbucketRepo:1:panjf2000/ants,bitbucket:BitbucketRepo:1:panjf2000/ants,MERGED,Test006,"* feat: add git.sh
+* feat: add test001
+* feat: test002
+* feat: add test003
+* feat: add test004
+* feat: add test005
+* feat: add test006
+
+‌",https://bitbucket.org/panjf2000/ants/pull-requests/9,teoiaoe,bitbucket:BitbucketAccount:1:62abf394192edb006fa0e8cf,,0,2022-08-12T14:55:13.971+00:00,,,pullrequest,,983edbf06740,test006,master,0bd83caaf9c7,8a8f44b997a8
diff --git a/plugins/bitbucket/e2e/snapshot_tables/repos.csv b/plugins/bitbucket/e2e/snapshot_tables/repos.csv
new file mode 100644
index 00000000..694cfb95
--- /dev/null
+++ b/plugins/bitbucket/e2e/snapshot_tables/repos.csv
@@ -0,0 +1,2 @@
+id,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark,name,url,description,owner_id,language,forked_from,created_date,updated_date,deleted
+bitbucket:BitbucketRepo:1:repositories/panjf2000/ants,"{""ConnectionId"":1,""Owner"":""panjf2000"",""Repo"":""ants""}",_raw_bitbucket_api_repositories,2,,panjf2000/ants,https://bitbucket.org/panjf2000/ants,,,,,2022-06-17T03:27:18.865+00:00,2022-08-12T15:40:12.409+00:00,0
diff --git a/plugins/bitbucket/impl/impl.go b/plugins/bitbucket/impl/impl.go
new file mode 100644
index 00000000..1c702576
--- /dev/null
+++ b/plugins/bitbucket/impl/impl.go
@@ -0,0 +1,125 @@
+/*
+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 impl
+
+import (
+	"fmt"
+	"github.com/apache/incubator-devlake/migration"
+	"github.com/apache/incubator-devlake/plugins/bitbucket/api"
+	"github.com/apache/incubator-devlake/plugins/bitbucket/models"
+	"github.com/apache/incubator-devlake/plugins/bitbucket/models/migrationscripts"
+	"github.com/apache/incubator-devlake/plugins/bitbucket/tasks"
+	"github.com/apache/incubator-devlake/plugins/core"
+	"github.com/apache/incubator-devlake/plugins/helper"
+	"github.com/spf13/viper"
+	"gorm.io/gorm"
+)
+
+var _ core.PluginMeta = (*Bitbucket)(nil)
+var _ core.PluginInit = (*Bitbucket)(nil)
+var _ core.PluginTask = (*Bitbucket)(nil)
+var _ core.PluginApi = (*Bitbucket)(nil)
+var _ core.Migratable = (*Bitbucket)(nil)
+var _ core.PluginBlueprintV100 = (*Bitbucket)(nil)
+
+type Bitbucket string
+
+func (plugin Bitbucket) Init(config *viper.Viper, logger core.Logger, db *gorm.DB) error {
+	api.Init(config, logger, db)
+	return nil
+}
+
+func (plugin Bitbucket) Description() string {
+	return "To collect and enrich data from Bitbucket"
+}
+
+func (plugin Bitbucket) SubTaskMetas() []core.SubTaskMeta {
+	return []core.SubTaskMeta{
+		tasks.CollectApiRepoMeta,
+		tasks.ExtractApiRepoMeta,
+		tasks.CollectApiPullRequestsMeta,
+		tasks.ExtractApiPullRequestsMeta,
+		tasks.CollectApiIssuesMeta,
+		tasks.ExtractApiIssuesMeta,
+		tasks.CollectApiPrCommentsMeta,
+		tasks.ExtractApiPrCommentsMeta,
+		tasks.CollectApiIssueCommentsMeta,
+		tasks.ExtractApiIssueCommentsMeta,
+		tasks.ConvertRepoMeta,
+		tasks.ConvertAccountsMeta,
+		tasks.ConvertPullRequestsMeta,
+		tasks.ConvertPrCommentsMeta,
+		tasks.ConvertIssuesMeta,
+		tasks.ConvertIssueCommentsMeta,
+	}
+}
+
+func (plugin Bitbucket) PrepareTaskData(taskCtx core.TaskContext, options map[string]interface{}) (interface{}, error) {
+	op, err := tasks.DecodeAndValidateTaskOptions(options)
+	if err != nil {
+		return nil, err
+	}
+	connectionHelper := helper.NewConnectionHelper(
+		taskCtx,
+		nil,
+	)
+	connection := &models.BitbucketConnection{}
+	err = connectionHelper.FirstById(connection, op.ConnectionId)
+	if err != nil {
+		return nil, fmt.Errorf("unable to get bitbucket connection by the given connection ID: %v", err)
+	}
+
+	apiClient, err := tasks.CreateApiClient(taskCtx, connection)
+	if err != nil {
+		return nil, fmt.Errorf("unable to get bitbucket API client instance: %v", err)
+	}
+
+	return &tasks.BitbucketTaskData{
+		Options:   op,
+		ApiClient: apiClient,
+	}, nil
+}
+
+func (plugin Bitbucket) RootPkgPath() string {
+	return "github.com/apache/incubator-devlake/plugins/bitbucket"
+}
+
+func (plugin Bitbucket) MigrationScripts() []migration.Script {
+	return migrationscripts.All()
+}
+
+func (plugin Bitbucket) MakePipelinePlan(connectionId uint64, scope []*core.BlueprintScopeV100) (core.PipelinePlan, error) {
+	return api.MakePipelinePlan(plugin.SubTaskMetas(), connectionId, scope)
+}
+
+func (plugin Bitbucket) ApiResources() map[string]map[string]core.ApiResourceHandler {
+	return map[string]map[string]core.ApiResourceHandler{
+		"test": {
+			"POST": api.TestConnection,
+		},
+		"connections": {
+			"POST": api.PostConnections,
+			"GET":  api.ListConnections,
+		},
+		"connections/:connectionId": {
+			"PATCH":  api.PatchConnection,
+			"DELETE": api.DeleteConnection,
+			"GET":    api.GetConnection,
+		},
+	}
+}
diff --git a/plugins/bitbucket/models/account.go b/plugins/bitbucket/models/account.go
new file mode 100644
index 00000000..83cbaef3
--- /dev/null
+++ b/plugins/bitbucket/models/account.go
@@ -0,0 +1,39 @@
+/*
+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 models
+
+import (
+	"github.com/apache/incubator-devlake/models/common"
+)
+
+type BitbucketAccount struct {
+	ConnectionId  uint64 `gorm:"primaryKey"`
+	AccountId     string `gorm:"primaryKey;type:varchar(255)"`
+	UserName      string `gorm:"type:varchar(255)"`
+	AccountStatus string `gorm:"type:varchar(255)"`
+	DisplayName   string `gorm:"type:varchar(255)"`
+	AvatarUrl     string `gorm:"type:varchar(255)"`
+	HtmlUrl       string `gorm:"type:varchar(255)"`
+	Uuid          string `gorm:"type:varchar(255)"`
+	Has2FaEnabled bool
+	common.NoPKModel
+}
+
+func (BitbucketAccount) TableName() string {
+	return "_tool_bitbucket_accounts"
+}
diff --git a/plugins/bitbucket/models/commit.go b/plugins/bitbucket/models/commit.go
new file mode 100644
index 00000000..4f61c219
--- /dev/null
+++ b/plugins/bitbucket/models/commit.go
@@ -0,0 +1,42 @@
+/*
+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 models
+
+import (
+	"time"
+
+	"github.com/apache/incubator-devlake/models/common"
+)
+
+type BitbucketCommit struct {
+	Sha           string `gorm:"primaryKey;type:varchar(40)"`
+	AuthorId      string `gorm:"type:varchar(255)"`
+	AuthorName    string `gorm:"type:varchar(255)"`
+	AuthorEmail   string `gorm:"type:varchar(255)"`
+	AuthoredDate  time.Time
+	CommittedDate time.Time
+	Message       string
+	Url           string `gorm:"type:varchar(255)"`
+	Additions     int    `gorm:"comment:Added lines of code"`
+	Deletions     int    `gorm:"comment:Deleted lines of code"`
+	common.NoPKModel
+}
+
+func (BitbucketCommit) TableName() string {
+	return "_tool_bitbucket_commits"
+}
diff --git a/plugins/bitbucket/models/connection.go b/plugins/bitbucket/models/connection.go
new file mode 100644
index 00000000..70266995
--- /dev/null
+++ b/plugins/bitbucket/models/connection.go
@@ -0,0 +1,69 @@
+/*
+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 models
+
+import (
+	"github.com/apache/incubator-devlake/plugins/helper"
+)
+
+type EpicResponse struct {
+	Id    int
+	Title string
+	Value string
+}
+
+type TestConnectionRequest struct {
+	Endpoint         string `json:"endpoint"`
+	Proxy            string `json:"proxy"`
+	helper.BasicAuth `mapstructure:",squash"`
+}
+
+type BoardResponse struct {
+	Id    int
+	Title string
+	Value string
+}
+type TransformationRules struct {
+	PrType               string `mapstructure:"prType" json:"prType"`
+	PrComponent          string `mapstructure:"prComponent" json:"prComponent"`
+	PrBodyClosePattern   string `mapstructure:"prBodyClosePattern" json:"prBodyClosePattern"`
+	IssueSeverity        string `mapstructure:"issueSeverity" json:"issueSeverity"`
+	IssuePriority        string `mapstructure:"issuePriority" json:"issuePriority"`
+	IssueComponent       string `mapstructure:"issueComponent" json:"issueComponent"`
+	IssueTypeBug         string `mapstructure:"issueTypeBug" json:"issueTypeBug"`
+	IssueTypeIncident    string `mapstructure:"issueTypeIncident" json:"issueTypeIncident"`
+	IssueTypeRequirement string `mapstructure:"issueTypeRequirement" json:"issueTypeRequirement"`
+}
+
+type ApiUserResponse struct {
+	Username      string `json:"username"`
+	DisplayName   string `json:"display_name"`
+	AccountId     int    `json:"account_id"`
+	Uuid          string `json:"uuid"`
+	AccountStatus string `json:"account_status"`
+}
+
+type BitbucketConnection struct {
+	helper.RestConnection      `mapstructure:",squash"`
+	helper.BasicAuth           `mapstructure:",squash"`
+	RemotelinkCommitShaPattern string `gorm:"type:varchar(255);comment='golang regexp, the first group will be recognized as commit sha, ref https://github.com/google/re2/wiki/Syntax'" json:"remotelinkCommitShaPattern"`
+}
+
+func (BitbucketConnection) TableName() string {
+	return "_tool_bitbucket_connections"
+}
diff --git a/plugins/bitbucket/models/issue.go b/plugins/bitbucket/models/issue.go
new file mode 100644
index 00000000..676c75cd
--- /dev/null
+++ b/plugins/bitbucket/models/issue.go
@@ -0,0 +1,52 @@
+/*
+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 models
+
+import (
+	"github.com/apache/incubator-devlake/models/common"
+	"time"
+)
+
+type BitbucketIssue struct {
+	ConnectionId       uint64 `gorm:"primaryKey"`
+	BitbucketId        int    `gorm:"primaryKey"`
+	RepoId             string `gorm:"index;type:varchar(255)"`
+	Number             int    `gorm:"index;comment:Used in API requests ex. api/issues/<THIS_NUMBER>"`
+	State              string `gorm:"type:varchar(255)"`
+	Title              string `gorm:"type:varchar(255)"`
+	Body               string
+	Priority           string `gorm:"type:varchar(255)"`
+	Type               string `gorm:"type:varchar(100)"`
+	AuthorId           string `gorm:"type:varchar(255)"`
+	AuthorName         string `gorm:"type:varchar(255)"`
+	AssigneeId         string `gorm:"type:varchar(255)"`
+	AssigneeName       string `gorm:"type:varchar(255)"`
+	MilestoneId        int    `gorm:"index"`
+	LeadTimeMinutes    uint
+	Url                string `gorm:"type:varchar(255)"`
+	ClosedAt           *time.Time
+	BitbucketCreatedAt time.Time
+	BitbucketUpdatedAt time.Time `gorm:"index"`
+	Severity           string    `gorm:"type:varchar(255)"`
+	Component          string    `gorm:"type:varchar(255)"`
+	common.NoPKModel
+}
+
+func (BitbucketIssue) TableName() string {
+	return "_tool_bitbucket_issues"
+}
diff --git a/plugins/bitbucket/models/issue_comment.go b/plugins/bitbucket/models/issue_comment.go
new file mode 100644
index 00000000..99c93e67
--- /dev/null
+++ b/plugins/bitbucket/models/issue_comment.go
@@ -0,0 +1,40 @@
+/*
+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 models
+
+import (
+	"github.com/apache/incubator-devlake/models/common"
+	"time"
+)
+
+type BitbucketIssueComment struct {
+	ConnectionId       uint64 `gorm:"primaryKey"`
+	BitbucketId        int    `gorm:"primaryKey"`
+	IssueId            int    `gorm:"index;comment:References the Issue"`
+	AuthorName         string `gorm:"type:varchar(255)"`
+	AuthorId           string `gorm:"type:varchar(255)"`
+	BitbucketCreatedAt time.Time
+	BitbucketUpdatedAt *time.Time
+	Type               string
+	Body               string
+	common.NoPKModel
+}
+
+func (BitbucketIssueComment) TableName() string {
+	return "_tool_bitbucket_issue_comments"
+}
diff --git a/plugins/bitbucket/models/issue_event.go b/plugins/bitbucket/models/issue_event.go
new file mode 100644
index 00000000..112baa37
--- /dev/null
+++ b/plugins/bitbucket/models/issue_event.go
@@ -0,0 +1,37 @@
+/*
+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 models
+
+import (
+	"github.com/apache/incubator-devlake/models/common"
+	"time"
+)
+
+type BitbucketIssueEvent struct {
+	ConnectionId       uint64    `gorm:"primaryKey"`
+	BitbucketId        int       `gorm:"primaryKey"`
+	IssueId            int       `gorm:"index;comment:References the Issue"`
+	Type               string    `gorm:"type:varchar(255);comment:Events that can occur to an issue, ex. assigned, closed, labeled, etc."`
+	AuthorUsername     string    `gorm:"type:varchar(255)"`
+	BitbucketCreatedAt time.Time `gorm:"index"`
+	common.NoPKModel
+}
+
+func (BitbucketIssueEvent) TableName() string {
+	return "_tool_bitbucket_issue_events"
+}
diff --git a/plugins/bitbucket/models/issue_label.go b/plugins/bitbucket/models/issue_label.go
new file mode 100644
index 00000000..1533579e
--- /dev/null
+++ b/plugins/bitbucket/models/issue_label.go
@@ -0,0 +1,36 @@
+/*
+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 models
+
+import (
+	"github.com/apache/incubator-devlake/models/common"
+)
+
+// Please note that Issue Labels can also apply to Pull Requests.
+// Pull Requests are considered Issues in Bitbucket.
+
+type BitbucketIssueLabel struct {
+	ConnectionId uint64 `gorm:"primaryKey"`
+	IssueId      int    `gorm:"primaryKey;autoIncrement:false"`
+	LabelName    string `gorm:"primaryKey;type:varchar(255)"`
+	common.NoPKModel
+}
+
+func (BitbucketIssueLabel) TableName() string {
+	return "_tool_bitbucket_issue_labels"
+}
diff --git a/plugins/bitbucket/models/migrationscripts/20220803_add_init_tables.go b/plugins/bitbucket/models/migrationscripts/20220803_add_init_tables.go
new file mode 100644
index 00000000..039542c7
--- /dev/null
+++ b/plugins/bitbucket/models/migrationscripts/20220803_add_init_tables.go
@@ -0,0 +1,101 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package migrationscripts
+
+import (
+	"context"
+	"github.com/apache/incubator-devlake/config"
+	"github.com/apache/incubator-devlake/plugins/bitbucket/models/migrationscripts/archived"
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+)
+
+type addInitTables struct{}
+
+func (*addInitTables) Up(ctx context.Context, db *gorm.DB) error {
+	err := db.Migrator().DropTable(
+		&archived.BitbucketUser{},
+		&archived.BitbucketRepo{},
+		&archived.BitbucketRepoCommit{},
+		//&archived.BitbucketConnection{},
+		&archived.BitbucketAccount{},
+		&archived.BitbucketCommit{},
+		&archived.BitbucketPullRequest{},
+		&archived.BitbucketIssue{},
+		&archived.BitbucketPrComment{},
+		&archived.BitbucketIssueComment{},
+	)
+
+	if err != nil {
+		return err
+	}
+
+	err = db.Migrator().AutoMigrate(
+		&archived.BitbucketUser{},
+		&archived.BitbucketRepo{},
+		&archived.BitbucketRepoCommit{},
+		&archived.BitbucketConnection{},
+		&archived.BitbucketAccount{},
+		&archived.BitbucketCommit{},
+		&archived.BitbucketPullRequest{},
+		&archived.BitbucketIssue{},
+		&archived.BitbucketPrComment{},
+		&archived.BitbucketIssueComment{},
+	)
+
+	if err != nil {
+		return err
+	}
+
+	v := config.GetConfig()
+	encKey := v.GetString("ENCODE_KEY")
+	endPoint := v.GetString("BITBUCKET_ENDPOINT")
+	bitbucketUsername := v.GetString("BITBUCKET_AUTH_USERNAME")
+	bitbucketAppPassword := v.GetString("BITBUCKET_AUTH_PASSWORD")
+	if encKey == "" || endPoint == "" || bitbucketUsername == "" || bitbucketAppPassword == "" {
+		return nil
+	} else {
+		conn := &archived.BitbucketConnection{}
+		conn.Name = "init bitbucket connection"
+		conn.ID = 1
+		conn.Endpoint = endPoint
+		conn.BasicAuth.Username = bitbucketUsername
+		conn.BasicAuth.Password = bitbucketAppPassword
+		if err != nil {
+			return err
+		}
+		conn.Proxy = v.GetString("BITBUCKET_PROXY")
+		conn.RateLimitPerHour = v.GetInt("BITBUCKET_API_REQUESTS_PER_HOUR")
+
+		err = db.Clauses(clause.OnConflict{DoNothing: true}).Create(conn).Error
+
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
+func (*addInitTables) Version() uint64 {
+	return 20220803220824
+}
+
+func (*addInitTables) Name() string {
+	return "Bitbucket init schema 20220803"
+}
diff --git a/plugins/bitbucket/models/migrationscripts/archived/account.go b/plugins/bitbucket/models/migrationscripts/archived/account.go
new file mode 100644
index 00000000..5d4cfa40
--- /dev/null
+++ b/plugins/bitbucket/models/migrationscripts/archived/account.go
@@ -0,0 +1,39 @@
+/*
+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 archived
+
+import (
+	"github.com/apache/incubator-devlake/models/migrationscripts/archived"
+)
+
+type BitbucketAccount struct {
+	ConnectionId  uint64 `gorm:"primaryKey"`
+	UserName      string `gorm:"type:varchar(255)"`
+	AccountId     string `gorm:"primaryKey;type:varchar(255)"`
+	AccountStatus string `gorm:"type:varchar(255)"`
+	DisplayName   string `gorm:"type:varchar(255)"`
+	AvatarUrl     string `gorm:"type:varchar(255)"`
+	HtmlUrl       string `gorm:"type:varchar(255)"`
+	Uuid          string `gorm:"type:varchar(255)"`
+	Has2FaEnabled bool
+	archived.NoPKModel
+}
+
+func (BitbucketAccount) TableName() string {
+	return "_tool_bitbucket_accounts"
+}
diff --git a/plugins/bitbucket/models/migrationscripts/archived/commit.go b/plugins/bitbucket/models/migrationscripts/archived/commit.go
new file mode 100644
index 00000000..710f432e
--- /dev/null
+++ b/plugins/bitbucket/models/migrationscripts/archived/commit.go
@@ -0,0 +1,42 @@
+/*
+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 archived
+
+import (
+	"time"
+
+	"github.com/apache/incubator-devlake/models/migrationscripts/archived"
+)
+
+type BitbucketCommit struct {
+	Sha           string `gorm:"primaryKey;type:varchar(40)"`
+	AuthorId      string `gorm:"type:varchar(255)"`
+	AuthorName    string `gorm:"type:varchar(255)"`
+	AuthorEmail   string `gorm:"type:varchar(255)"`
+	AuthoredDate  time.Time
+	CommittedDate time.Time
+	Message       string
+	Url           string `gorm:"type:varchar(255)"`
+	Additions     int    `gorm:"comment:Added lines of code"`
+	Deletions     int    `gorm:"comment:Deleted lines of code"`
+	archived.NoPKModel
+}
+
+func (BitbucketCommit) TableName() string {
+	return "_tool_bitbucket_commits"
+}
diff --git a/plugins/bitbucket/models/migrationscripts/archived/connection.go b/plugins/bitbucket/models/migrationscripts/archived/connection.go
new file mode 100644
index 00000000..dae6374d
--- /dev/null
+++ b/plugins/bitbucket/models/migrationscripts/archived/connection.go
@@ -0,0 +1,69 @@
+/*
+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 archived
+
+import (
+	"github.com/apache/incubator-devlake/plugins/helper"
+)
+
+type EpicResponse struct {
+	Id    int
+	Title string
+	Value string
+}
+
+type TestConnectionRequest struct {
+	Endpoint         string `json:"endpoint"`
+	Proxy            string `json:"proxy"`
+	helper.BasicAuth `mapstructure:",squash"`
+}
+
+type BoardResponse struct {
+	Id    int
+	Title string
+	Value string
+}
+type TransformationRules struct {
+	PrType               string `mapstructure:"prType" json:"prType"`
+	PrComponent          string `mapstructure:"prComponent" json:"prComponent"`
+	PrBodyClosePattern   string `mapstructure:"prBodyClosePattern" json:"prBodyClosePattern"`
+	IssueSeverity        string `mapstructure:"issueSeverity" json:"issueSeverity"`
+	IssuePriority        string `mapstructure:"issuePriority" json:"issuePriority"`
+	IssueComponent       string `mapstructure:"issueComponent" json:"issueComponent"`
+	IssueTypeBug         string `mapstructure:"issueTypeBug" json:"issueTypeBug"`
+	IssueTypeIncident    string `mapstructure:"issueTypeIncident" json:"issueTypeIncident"`
+	IssueTypeRequirement string `mapstructure:"issueTypeRequirement" json:"issueTypeRequirement"`
+}
+
+type ApiUserResponse struct {
+	Username      string `json:"username"`
+	DisplayName   string `json:"display_name"`
+	AccountId     int    `json:"account_id"`
+	Uuid          string `json:"uuid"`
+	AccountStatus string `json:"account_status"`
+}
+
+type BitbucketConnection struct {
+	helper.RestConnection      `mapstructure:",squash"`
+	helper.BasicAuth           `mapstructure:",squash"`
+	RemotelinkCommitShaPattern string `gorm:"type:varchar(255);comment='golang regexp, the first group will be recognized as commit sha, ref https://github.com/google/re2/wiki/Syntax'" json:"remotelinkCommitShaPattern"`
+}
+
+func (BitbucketConnection) TableName() string {
+	return "_tool_bitbucket_connections"
+}
diff --git a/plugins/bitbucket/models/migrationscripts/archived/issue.go b/plugins/bitbucket/models/migrationscripts/archived/issue.go
new file mode 100644
index 00000000..b24c0bdf
--- /dev/null
+++ b/plugins/bitbucket/models/migrationscripts/archived/issue.go
@@ -0,0 +1,53 @@
+/*
+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 archived
+
+import (
+	"github.com/apache/incubator-devlake/models/migrationscripts/archived"
+	"time"
+)
+
+type BitbucketIssue struct {
+	ConnectionId       uint64 `gorm:"primaryKey"`
+	BitbucketId        int    `gorm:"primaryKey"`
+	RepoId             string `gorm:"index;type:varchar(255)"`
+	Number             int    `gorm:"index;comment:Used in API requests ex. api/issues/<THIS_NUMBER>"`
+	State              string `gorm:"type:varchar(255)"`
+	Title              string `gorm:"type:varchar(255)"`
+	Body               string
+	Priority           string `gorm:"type:varchar(255)"`
+	Type               string `gorm:"type:varchar(100)"`
+	Status             string `gorm:"type:varchar(255)"`
+	AuthorId           string `gorm:"type:varchar(255)"`
+	AuthorName         string `gorm:"type:varchar(255)"`
+	AssigneeId         string `gorm:"type:varchar(255)"`
+	AssigneeName       string `gorm:"type:varchar(255)"`
+	MilestoneId        int    `gorm:"index"`
+	LeadTimeMinutes    uint
+	Url                string `gorm:"type:varchar(255)"`
+	ClosedAt           *time.Time
+	BitbucketCreatedAt time.Time
+	BitbucketUpdatedAt time.Time `gorm:"index"`
+	Severity           string    `gorm:"type:varchar(255)"`
+	Component          string    `gorm:"type:varchar(255)"`
+	archived.NoPKModel
+}
+
+func (BitbucketIssue) TableName() string {
+	return "_tool_bitbucket_issues"
+}
diff --git a/plugins/bitbucket/models/migrationscripts/archived/issue_comment.go b/plugins/bitbucket/models/migrationscripts/archived/issue_comment.go
new file mode 100644
index 00000000..0112cf74
--- /dev/null
+++ b/plugins/bitbucket/models/migrationscripts/archived/issue_comment.go
@@ -0,0 +1,40 @@
+/*
+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 archived
+
+import (
+	"github.com/apache/incubator-devlake/models/migrationscripts/archived"
+	"time"
+)
+
+type BitbucketIssueComment struct {
+	ConnectionId       uint64 `gorm:"primaryKey"`
+	BitbucketId        int    `gorm:"primaryKey"`
+	IssueId            int    `gorm:"index;comment:References the Issue"`
+	AuthorName         string `gorm:"type:varchar(255)"`
+	AuthorId           string `gorm:"type:varchar(255)"`
+	BitbucketCreatedAt time.Time
+	BitbucketUpdatedAt *time.Time
+	Type               string
+	Body               string
+	archived.NoPKModel
+}
+
+func (BitbucketIssueComment) TableName() string {
+	return "_tool_bitbucket_issue_comments"
+}
diff --git a/plugins/bitbucket/models/migrationscripts/archived/issue_event.go b/plugins/bitbucket/models/migrationscripts/archived/issue_event.go
new file mode 100644
index 00000000..249a62ac
--- /dev/null
+++ b/plugins/bitbucket/models/migrationscripts/archived/issue_event.go
@@ -0,0 +1,37 @@
+/*
+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 archived
+
+import (
+	"github.com/apache/incubator-devlake/models/migrationscripts/archived"
+	"time"
+)
+
+type BitbucketIssueEvent struct {
+	ConnectionId       uint64    `gorm:"primaryKey"`
+	BitbucketId        int       `gorm:"primaryKey"`
+	IssueId            int       `gorm:"index;comment:References the Issue"`
+	Type               string    `gorm:"type:varchar(255);comment:Events that can occur to an issue, ex. assigned, closed, labeled, etc."`
+	AuthorUsername     string    `gorm:"type:varchar(255)"`
+	BitbucketCreatedAt time.Time `gorm:"index"`
+	archived.NoPKModel
+}
+
+func (BitbucketIssueEvent) TableName() string {
+	return "_tool_bitbucket_issue_events"
+}
diff --git a/plugins/bitbucket/models/migrationscripts/archived/issue_label.go b/plugins/bitbucket/models/migrationscripts/archived/issue_label.go
new file mode 100644
index 00000000..518d0051
--- /dev/null
+++ b/plugins/bitbucket/models/migrationscripts/archived/issue_label.go
@@ -0,0 +1,36 @@
+/*
+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 archived
+
+import (
+	"github.com/apache/incubator-devlake/models/migrationscripts/archived"
+)
+
+// Please note that Issue Labels can also apply to Pull Requests.
+// Pull Requests are considered Issues in Bitbucket.
+
+type BitbucketIssueLabel struct {
+	ConnectionId uint64 `gorm:"primaryKey"`
+	IssueId      int    `gorm:"primaryKey;autoIncrement:false"`
+	LabelName    string `gorm:"primaryKey;type:varchar(255)"`
+	archived.NoPKModel
+}
+
+func (BitbucketIssueLabel) TableName() string {
+	return "_tool_bitbucket_issue_labels"
+}
diff --git a/plugins/bitbucket/models/migrationscripts/archived/pr.go b/plugins/bitbucket/models/migrationscripts/archived/pr.go
new file mode 100644
index 00000000..42796cf8
--- /dev/null
+++ b/plugins/bitbucket/models/migrationscripts/archived/pr.go
@@ -0,0 +1,57 @@
+/*
+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 archived
+
+import (
+	"github.com/apache/incubator-devlake/models/migrationscripts/archived"
+	"time"
+)
+
+type BitbucketPullRequest struct {
+	ConnectionId       uint64 `gorm:"primaryKey"`
+	BitbucketId        int    `gorm:"primaryKey"`
+	RepoId             string `gorm:"index;type:varchar(255)"`
+	Number             int    `gorm:"index"` // This number is used in GET requests to the API associated to reviewers / comments / etc.
+	BaseRepoId         string
+	HeadRepoId         string
+	State              string `gorm:"type:varchar(255)"`
+	Title              string
+	Description        string
+	BitbucketCreatedAt time.Time
+	BitbucketUpdatedAt time.Time `gorm:"index"`
+	ClosedAt           *time.Time
+	CommentCount       int
+	Commits            int
+	MergedAt           *time.Time
+	Body               string
+	Type               string `gorm:"type:varchar(255)"`
+	Component          string `gorm:"type:varchar(255)"`
+	MergeCommitSha     string `gorm:"type:varchar(40)"`
+	HeadRef            string `gorm:"type:varchar(255)"`
+	BaseRef            string `gorm:"type:varchar(255)"`
+	BaseCommitSha      string `gorm:"type:varchar(255)"`
+	HeadCommitSha      string `gorm:"type:varchar(255)"`
+	Url                string `gorm:"type:varchar(255)"`
+	AuthorName         string `gorm:"type:varchar(255)"`
+	AuthorId           string `gorm:"type:varchar(255)"`
+	archived.NoPKModel
+}
+
+func (BitbucketPullRequest) TableName() string {
+	return "_tool_bitbucket_pull_requests"
+}
diff --git a/plugins/bitbucket/models/migrationscripts/archived/pr_comment.go b/plugins/bitbucket/models/migrationscripts/archived/pr_comment.go
new file mode 100644
index 00000000..47d89134
--- /dev/null
+++ b/plugins/bitbucket/models/migrationscripts/archived/pr_comment.go
@@ -0,0 +1,41 @@
+/*
+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 archived
+
+import (
+	"time"
+
+	"github.com/apache/incubator-devlake/models/migrationscripts/archived"
+)
+
+type BitbucketPrComment struct {
+	ConnectionId       uint64 `gorm:"primaryKey"`
+	BitbucketId        int    `gorm:"primaryKey"`
+	PullRequestId      int    `gorm:"index"`
+	AuthorId           string `gorm:"type:varchar(255)"`
+	AuthorName         string `gorm:"type:varchar(255)"`
+	BitbucketCreatedAt time.Time
+	BitbucketUpdatedAt *time.Time
+	Type               string `gorm:"comment:if type=null, it is normal comment,if type=diffNote,it is diff comment"`
+	Body               string
+	archived.NoPKModel
+}
+
+func (BitbucketPrComment) TableName() string {
+	return "_tool_bitbucket_pull_request_comments"
+}
diff --git a/plugins/bitbucket/models/migrationscripts/archived/repo.go b/plugins/bitbucket/models/migrationscripts/archived/repo.go
new file mode 100644
index 00000000..9b13e2d7
--- /dev/null
+++ b/plugins/bitbucket/models/migrationscripts/archived/repo.go
@@ -0,0 +1,40 @@
+/*
+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 archived
+
+import (
+	"github.com/apache/incubator-devlake/models/migrationscripts/archived"
+	"time"
+)
+
+type BitbucketRepo struct {
+	ConnectionId uint64 `gorm:"primaryKey"`
+	BitbucketId  string `gorm:"primaryKey;type:varchar(255)"`
+	Name         string `gorm:"type:varchar(255)"`
+	HTMLUrl      string `gorm:"type:varchar(255)"`
+	Description  string
+	OwnerId      string     `json:"ownerId"`
+	Language     string     `json:"language" gorm:"type:varchar(255)"`
+	CreatedDate  time.Time  `json:"createdDate"`
+	UpdatedDate  *time.Time `json:"updatedDate"`
+	archived.NoPKModel
+}
+
+func (BitbucketRepo) TableName() string {
+	return "_tool_bitbucket_repos"
+}
diff --git a/plugins/bitbucket/models/migrationscripts/archived/repo_commit.go b/plugins/bitbucket/models/migrationscripts/archived/repo_commit.go
new file mode 100644
index 00000000..956e0e64
--- /dev/null
+++ b/plugins/bitbucket/models/migrationscripts/archived/repo_commit.go
@@ -0,0 +1,31 @@
+/*
+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 archived
+
+import "github.com/apache/incubator-devlake/models/migrationscripts/archived"
+
+type BitbucketRepoCommit struct {
+	ConnectionId uint64 `gorm:"primaryKey"`
+	RepoId       string `gorm:"primaryKey;type:varchar(255)"`
+	CommitSha    string `gorm:"primaryKey;type:varchar(40)"`
+	archived.NoPKModel
+}
+
+func (BitbucketRepoCommit) TableName() string {
+	return "_tool_bitbucket_repo_commits"
+}
diff --git a/plugins/bitbucket/models/migrationscripts/archived/user.go b/plugins/bitbucket/models/migrationscripts/archived/user.go
new file mode 100644
index 00000000..bf8e3125
--- /dev/null
+++ b/plugins/bitbucket/models/migrationscripts/archived/user.go
@@ -0,0 +1,33 @@
+/*
+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 archived
+
+import "github.com/apache/incubator-devlake/models/migrationscripts/archived"
+
+type BitbucketUser struct {
+	ConnectionId uint64 `gorm:"primaryKey"`
+	UserName     string `json:"username"`
+	DisplayName  string `json:"display_name"`
+	AccountId    string `json:"account_id"`
+
+	archived.NoPKModel
+}
+
+func (BitbucketUser) TableName() string {
+	return "_tool_bitbucket_users"
+}
diff --git a/plugins/bitbucket/models/migrationscripts/register.go b/plugins/bitbucket/models/migrationscripts/register.go
new file mode 100644
index 00000000..c1365f7d
--- /dev/null
+++ b/plugins/bitbucket/models/migrationscripts/register.go
@@ -0,0 +1,29 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package migrationscripts
+
+import (
+	"github.com/apache/incubator-devlake/migration"
+)
+
+// All return all the migration scripts
+func All() []migration.Script {
+	return []migration.Script{
+		new(addInitTables),
+	}
+}
diff --git a/plugins/bitbucket/models/pr.go b/plugins/bitbucket/models/pr.go
new file mode 100644
index 00000000..c30dcaa1
--- /dev/null
+++ b/plugins/bitbucket/models/pr.go
@@ -0,0 +1,57 @@
+/*
+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 models
+
+import (
+	"github.com/apache/incubator-devlake/models/common"
+	"time"
+)
+
+type BitbucketPullRequest struct {
+	ConnectionId       uint64 `gorm:"primaryKey"`
+	BitbucketId        int    `gorm:"primaryKey"`
+	RepoId             string `gorm:"index;type:varchar(255)"`
+	Number             int    `gorm:"index"` // This number is used in GET requests to the API associated to reviewers / comments / etc.
+	BaseRepoId         string
+	HeadRepoId         string
+	State              string `gorm:"type:varchar(255)"`
+	Title              string
+	Description        string
+	BitbucketCreatedAt time.Time
+	BitbucketUpdatedAt time.Time `gorm:"index"`
+	ClosedAt           *time.Time
+	CommentCount       int
+	Commits            int
+	MergedAt           *time.Time
+	Body               string
+	Type               string `gorm:"type:varchar(255)"`
+	Component          string `gorm:"type:varchar(255)"`
+	MergeCommitSha     string `gorm:"type:varchar(40)"`
+	HeadRef            string `gorm:"type:varchar(255)"`
+	BaseRef            string `gorm:"type:varchar(255)"`
+	BaseCommitSha      string `gorm:"type:varchar(255)"`
+	HeadCommitSha      string `gorm:"type:varchar(255)"`
+	Url                string `gorm:"type:varchar(255)"`
+	AuthorName         string `gorm:"type:varchar(255)"`
+	AuthorId           string `gorm:"type:varchar(255)"`
+	common.NoPKModel
+}
+
+func (BitbucketPullRequest) TableName() string {
+	return "_tool_bitbucket_pull_requests"
+}
diff --git a/plugins/bitbucket/models/pr_comment.go b/plugins/bitbucket/models/pr_comment.go
new file mode 100644
index 00000000..e783df3c
--- /dev/null
+++ b/plugins/bitbucket/models/pr_comment.go
@@ -0,0 +1,41 @@
+/*
+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 models
+
+import (
+	"time"
+
+	"github.com/apache/incubator-devlake/models/common"
+)
+
+type BitbucketPrComment struct {
+	ConnectionId       uint64 `gorm:"primaryKey"`
+	BitbucketId        int    `gorm:"primaryKey"`
+	PullRequestId      int    `gorm:"index"`
+	AuthorId           string `gorm:"type:varchar(255)"`
+	AuthorName         string `gorm:"type:varchar(255)"`
+	BitbucketCreatedAt time.Time
+	BitbucketUpdatedAt *time.Time
+	Type               string `gorm:"comment:if type=null, it is normal comment,if type=diffNote,it is diff comment"`
+	Body               string
+	common.NoPKModel
+}
+
+func (BitbucketPrComment) TableName() string {
+	return "_tool_bitbucket_pull_request_comments"
+}
diff --git a/plugins/bitbucket/models/repo.go b/plugins/bitbucket/models/repo.go
new file mode 100644
index 00000000..3dd6c463
--- /dev/null
+++ b/plugins/bitbucket/models/repo.go
@@ -0,0 +1,40 @@
+/*
+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 models
+
+import (
+	"github.com/apache/incubator-devlake/models/common"
+	"time"
+)
+
+type BitbucketRepo struct {
+	ConnectionId uint64 `gorm:"primaryKey"`
+	BitbucketId  string `gorm:"primaryKey;type:varchar(255)"`
+	Name         string `gorm:"type:varchar(255)"`
+	HTMLUrl      string `gorm:"type:varchar(255)"`
+	Description  string
+	OwnerId      string     `json:"ownerId"`
+	Language     string     `json:"language" gorm:"type:varchar(255)"`
+	CreatedDate  time.Time  `json:"createdDate"`
+	UpdatedDate  *time.Time `json:"updatedDate"`
+	common.NoPKModel
+}
+
+func (BitbucketRepo) TableName() string {
+	return "_tool_bitbucket_repos"
+}
diff --git a/plugins/bitbucket/models/repo_commit.go b/plugins/bitbucket/models/repo_commit.go
new file mode 100644
index 00000000..9979b06b
--- /dev/null
+++ b/plugins/bitbucket/models/repo_commit.go
@@ -0,0 +1,31 @@
+/*
+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 models
+
+import "github.com/apache/incubator-devlake/models/common"
+
+type BitbucketRepoCommit struct {
+	ConnectionId uint64 `gorm:"primaryKey"`
+	RepoId       string `gorm:"primaryKey;type:varchar(255)"`
+	CommitSha    string `gorm:"primaryKey;type:varchar(40)"`
+	common.NoPKModel
+}
+
+func (BitbucketRepoCommit) TableName() string {
+	return "_tool_bitbucket_repo_commits"
+}
diff --git a/plugins/bitbucket/models/user.go b/plugins/bitbucket/models/user.go
new file mode 100644
index 00000000..129dfc65
--- /dev/null
+++ b/plugins/bitbucket/models/user.go
@@ -0,0 +1,35 @@
+/*
+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 models
+
+import (
+	"github.com/apache/incubator-devlake/models/common"
+)
+
+type BitbucketUser struct {
+	ConnectionId uint64 `gorm:"primaryKey"`
+	UserName     string `json:"username"`
+	DisplayName  string `json:"display_name"`
+	AccountId    string `json:"account_id"`
+
+	common.NoPKModel
+}
+
+func (BitbucketUser) TableName() string {
+	return "_tool_bitbucket_users"
+}
diff --git a/plugins/bitbucket/tasks/account_convertor.go b/plugins/bitbucket/tasks/account_convertor.go
new file mode 100644
index 00000000..82642764
--- /dev/null
+++ b/plugins/bitbucket/tasks/account_convertor.go
@@ -0,0 +1,87 @@
+/*
+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 tasks
+
+import (
+	"reflect"
+
+	"github.com/apache/incubator-devlake/models/domainlayer/crossdomain"
+
+	"github.com/apache/incubator-devlake/plugins/core/dal"
+
+	"github.com/apache/incubator-devlake/models/domainlayer"
+	"github.com/apache/incubator-devlake/models/domainlayer/didgen"
+	bitbucketModels "github.com/apache/incubator-devlake/plugins/bitbucket/models"
+	"github.com/apache/incubator-devlake/plugins/core"
+	"github.com/apache/incubator-devlake/plugins/helper"
+)
+
+const RAW_ACCOUNT_TABLE = "bitbucket_api_accounts"
+
+var ConvertAccountsMeta = core.SubTaskMeta{
+	Name:             "convertAccounts",
+	EntryPoint:       ConvertAccounts,
+	EnabledByDefault: true,
+	Required:         true,
+	Description:      "Convert tool layer table bitbucket_accounts into  domain layer table accounts",
+	DomainTypes:      []string{core.DOMAIN_TYPE_CROSS},
+}
+
+func ConvertAccounts(taskCtx core.SubTaskContext) error {
+	db := taskCtx.GetDal()
+	data := taskCtx.GetData().(*BitbucketTaskData)
+
+	cursor, err := db.Cursor(dal.From(&bitbucketModels.BitbucketAccount{}))
+	if err != nil {
+		return err
+	}
+	defer cursor.Close()
+
+	accountIdGen := didgen.NewDomainIdGenerator(&bitbucketModels.BitbucketAccount{})
+
+	converter, err := helper.NewDataConverter(helper.DataConverterArgs{
+		InputRowType: reflect.TypeOf(bitbucketModels.BitbucketAccount{}),
+		Input:        cursor,
+		RawDataSubTaskArgs: helper.RawDataSubTaskArgs{
+			Ctx: taskCtx,
+			Params: BitbucketApiParams{
+				ConnectionId: data.Options.ConnectionId,
+				Owner:        data.Options.Owner,
+				Repo:         data.Options.Repo,
+			},
+			Table: RAW_ACCOUNT_TABLE,
+		},
+		Convert: func(inputRow interface{}) ([]interface{}, error) {
+			bitbucketUser := inputRow.(*bitbucketModels.BitbucketAccount)
+			domainUser := &crossdomain.Account{
+				DomainEntity: domainlayer.DomainEntity{Id: accountIdGen.Generate(data.Options.ConnectionId, bitbucketUser.AccountId)},
+				UserName:     bitbucketUser.UserName,
+				FullName:     bitbucketUser.DisplayName,
+				AvatarUrl:    bitbucketUser.AvatarUrl,
+			}
+			return []interface{}{
+				domainUser,
+			}, nil
+		},
+	})
+	if err != nil {
+		return err
+	}
+
+	return converter.Execute()
+}
diff --git a/plugins/bitbucket/tasks/account_extractor.go b/plugins/bitbucket/tasks/account_extractor.go
new file mode 100644
index 00000000..10442e33
--- /dev/null
+++ b/plugins/bitbucket/tasks/account_extractor.go
@@ -0,0 +1,52 @@
+/*
+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 tasks
+
+import (
+	"github.com/apache/incubator-devlake/plugins/bitbucket/models"
+	"time"
+)
+
+type BitbucketAccountResponse struct {
+	UserName      string    `json:"username"`
+	DisplayName   string    `json:"display_name"`
+	AccountId     string    `json:"account_id"`
+	AccountStatus string    `json:"account_status"`
+	CreateOn      time.Time `json:"create_on"`
+	Links         struct {
+		Self       struct{ Href string } `json:"self"`
+		Html       struct{ Href string } `json:"html"`
+		Avatar     struct{ Href string } `json:"avatar"`
+		Followers  struct{ Href string } `json:"followers"`
+		Following  struct{ Href string } `json:"following"`
+		Repository struct{ Href string } `json:"repository"`
+	}
+}
+
+func convertAccount(res *BitbucketAccountResponse, connId uint64) (*models.BitbucketAccount, error) {
+	bitbucketAccount := &models.BitbucketAccount{
+		ConnectionId:  connId,
+		UserName:      res.UserName,
+		DisplayName:   res.DisplayName,
+		AccountId:     res.AccountId,
+		AccountStatus: res.AccountStatus,
+		AvatarUrl:     res.Links.Avatar.Href,
+		HtmlUrl:       res.Links.Html.Href,
+	}
+	return bitbucketAccount, nil
+}
diff --git a/plugins/bitbucket/tasks/api_client.go b/plugins/bitbucket/tasks/api_client.go
new file mode 100644
index 00000000..53c9b706
--- /dev/null
+++ b/plugins/bitbucket/tasks/api_client.go
@@ -0,0 +1,86 @@
+/*
+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 tasks
+
+import (
+	"fmt"
+	"github.com/apache/incubator-devlake/plugins/bitbucket/models"
+	"net/http"
+	"strconv"
+	"time"
+
+	"github.com/apache/incubator-devlake/plugins/core"
+	"github.com/apache/incubator-devlake/plugins/helper"
+)
+
+func CreateApiClient(taskCtx core.TaskContext, connection *models.BitbucketConnection) (*helper.ApiAsyncClient, error) {
+	// load configuration
+	token := connection.GetEncodedToken()
+	// create synchronize api client so we can calculate api rate limit dynamically
+	apiClient, err := helper.NewApiClient(taskCtx.GetContext(), connection.Endpoint, nil, 0, connection.Proxy, taskCtx)
+	if err != nil {
+		return nil, err
+	}
+	// Rotates token on each request.
+	apiClient.SetBeforeFunction(func(req *http.Request) error {
+		req.Header.Set("Authorization", fmt.Sprintf("Basic %v", token))
+		return nil
+	})
+	apiClient.SetAfterFunction(func(res *http.Response) error {
+		if res.StatusCode == http.StatusUnauthorized {
+			return fmt.Errorf("authentication failed, please check your Basic Auth configuration")
+		}
+		return nil
+	})
+
+	// create rate limit calculator
+	rateLimiter := &helper.ApiRateLimitCalculator{
+		UserRateLimitPerHour: connection.RateLimitPerHour,
+		Method:               http.MethodGet,
+		DynamicRateLimit: func(res *http.Response) (int, time.Duration, error) {
+			rateLimitHeader := res.Header.Get("X-Request-Count")
+			if rateLimitHeader == "" {
+				// use default
+				return 0, 0, nil
+			}
+			rateLimit, err := strconv.Atoi(rateLimitHeader)
+			if err != nil {
+				return 0, 0, fmt.Errorf("failed to parse X-Request-Count header: %w", err)
+			}
+
+			return rateLimit, 1 * time.Minute, nil
+		},
+	}
+	asyncApiClient, err := helper.CreateAsyncApiClient(
+		taskCtx,
+		apiClient,
+		rateLimiter,
+	)
+	if err != nil {
+		return nil, err
+	}
+	return asyncApiClient, nil
+}
+
+type BitbucketPagination struct {
+	Values  []interface{} `json:"values"`
+	PageLen int           `json:"pagelen"`
+	Size    int           `json:"size"`
+	Page    int           `json:"page"`
+	Next    string        `json:"next"`
+}
diff --git a/plugins/bitbucket/tasks/api_common.go b/plugins/bitbucket/tasks/api_common.go
new file mode 100644
index 00000000..a626239f
--- /dev/null
+++ b/plugins/bitbucket/tasks/api_common.go
@@ -0,0 +1,137 @@
+/*
+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 tasks
+
+import (
+	"encoding/json"
+	"fmt"
+	"github.com/apache/incubator-devlake/plugins/core"
+	"github.com/apache/incubator-devlake/plugins/core/dal"
+	"github.com/apache/incubator-devlake/plugins/helper"
+	"io/ioutil"
+	"net/http"
+	"net/url"
+	"reflect"
+)
+
+type BitbucketApiParams struct {
+	ConnectionId uint64
+	Owner        string
+	Repo         string
+}
+
+type BitbucketInput struct {
+	BitbucketId int
+}
+
+func CreateRawDataSubTaskArgs(taskCtx core.SubTaskContext, Table string) (*helper.RawDataSubTaskArgs, *BitbucketTaskData) {
+	data := taskCtx.GetData().(*BitbucketTaskData)
+	RawDataSubTaskArgs := &helper.RawDataSubTaskArgs{
+		Ctx: taskCtx,
+		Params: BitbucketApiParams{
+			ConnectionId: data.Options.ConnectionId,
+			Owner:        data.Options.Owner,
+			Repo:         data.Options.Repo,
+		},
+		Table: Table,
+	}
+	return RawDataSubTaskArgs, data
+}
+
+func GetQuery(reqData *helper.RequestData) (url.Values, error) {
+	query := url.Values{}
+	query.Set("state", "all")
+	query.Set("page", fmt.Sprintf("%v", reqData.Pager.Page))
+	query.Set("pagelen", fmt.Sprintf("%v", reqData.Pager.Size))
+
+	return query, nil
+}
+
+func GetTotalPagesFromResponse(res *http.Response, args *helper.ApiCollectorArgs) (int, error) {
+	body := &BitbucketPagination{}
+	err := helper.UnmarshalResponse(res, body)
+	if err != nil {
+		return 0, err
+	}
+	pages := body.Size / args.PageSize
+	if body.Size%args.PageSize > 0 {
+		pages++
+	}
+	return pages, nil
+}
+
+func GetRawMessageFromResponse(res *http.Response) ([]json.RawMessage, error) {
+	var rawMessages struct {
+		Values []json.RawMessage `json:"values"`
+	}
+	if res == nil {
+		return nil, fmt.Errorf("res is nil")
+	}
+	defer res.Body.Close()
+	resBody, err := ioutil.ReadAll(res.Body)
+	if err != nil {
+		return nil, fmt.Errorf("%w %s", err, res.Request.URL.String())
+	}
+
+	err = json.Unmarshal(resBody, &rawMessages)
+	if err != nil {
+		return nil, fmt.Errorf("%w %s %s", err, res.Request.URL.String(), string(resBody))
+	}
+
+	return rawMessages.Values, nil
+}
+
+func GetPullRequestsIterator(taskCtx core.SubTaskContext) (*helper.DalCursorIterator, error) {
+	db := taskCtx.GetDal()
+	data := taskCtx.GetData().(*BitbucketTaskData)
+	clauses := []dal.Clause{
+		dal.Select("bpr.bitbucket_id"),
+		dal.From("_tool_bitbucket_pull_requests bpr"),
+		dal.Where(
+			`bpr.repo_id = ? and bpr.connection_id = ?`,
+			"repositories/"+data.Options.Owner+"/"+data.Options.Repo, data.Options.ConnectionId,
+		),
+	}
+	// construct the input iterator
+	cursor, err := db.Cursor(clauses...)
+	if err != nil {
+		return nil, err
+	}
+
+	return helper.NewDalCursorIterator(db, cursor, reflect.TypeOf(BitbucketInput{}))
+}
+
+func GetIssuesIterator(taskCtx core.SubTaskContext) (*helper.DalCursorIterator, error) {
+	db := taskCtx.GetDal()
+	data := taskCtx.GetData().(*BitbucketTaskData)
+	clauses := []dal.Clause{
+		dal.Select("bpr.bitbucket_id"),
+		dal.From("_tool_bitbucket_issues bpr"),
+		dal.Where(
+			`bpr.repo_id = ? and bpr.connection_id = ?`,
+			"repositories/"+data.Options.Owner+"/"+data.Options.Repo, data.Options.ConnectionId,
+		),
+	}
+	// construct the input iterator
+	cursor, err := db.Cursor(clauses...)
+	if err != nil {
+		return nil, err
+	}
+
+	return helper.NewDalCursorIterator(db, cursor, reflect.TypeOf(BitbucketInput{}))
+}
diff --git a/plugins/bitbucket/tasks/commit_collector.go b/plugins/bitbucket/tasks/commit_collector.go
new file mode 100644
index 00000000..3182115f
--- /dev/null
+++ b/plugins/bitbucket/tasks/commit_collector.go
@@ -0,0 +1,56 @@
+/*
+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 tasks
+
+import (
+	"github.com/apache/incubator-devlake/plugins/helper"
+
+	"github.com/apache/incubator-devlake/plugins/core"
+)
+
+const RAW_COMMIT_TABLE = "bitbucket_api_commits"
+
+var CollectApiCommitsMeta = core.SubTaskMeta{
+	Name:             "collectApiCommits",
+	EntryPoint:       CollectApiCommits,
+	EnabledByDefault: false,
+	Required:         false,
+	Description:      "Collect commits data from Bitbucket api",
+	DomainTypes:      []string{core.DOMAIN_TYPE_CODE},
+}
+
+func CollectApiCommits(taskCtx core.SubTaskContext) error {
+	rawDataSubTaskArgs, data := CreateRawDataSubTaskArgs(taskCtx, RAW_COMMIT_TABLE)
+
+	collector, err := helper.NewApiCollector(helper.ApiCollectorArgs{
+		RawDataSubTaskArgs: *rawDataSubTaskArgs,
+		ApiClient:          data.ApiClient,
+		PageSize:           100,
+		Incremental:        false,
+		UrlTemplate:        "repositories/{{ .Params.Owner }}/{{ .Params.Repo }}/commits",
+		Query:              GetQuery,
+		GetTotalPages:      GetTotalPagesFromResponse,
+		ResponseParser:     GetRawMessageFromResponse,
+	})
+
+	if err != nil {
+		return err
+	}
+
+	return collector.Execute()
+}
diff --git a/plugins/bitbucket/tasks/commit_convertor.go b/plugins/bitbucket/tasks/commit_convertor.go
new file mode 100644
index 00000000..5900e395
--- /dev/null
+++ b/plugins/bitbucket/tasks/commit_convertor.go
@@ -0,0 +1,103 @@
+/*
+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 tasks
+
+import (
+	"reflect"
+
+	"github.com/apache/incubator-devlake/plugins/core/dal"
+
+	"github.com/apache/incubator-devlake/models/domainlayer/code"
+	"github.com/apache/incubator-devlake/models/domainlayer/didgen"
+	bitbucketModels "github.com/apache/incubator-devlake/plugins/bitbucket/models"
+	"github.com/apache/incubator-devlake/plugins/core"
+	"github.com/apache/incubator-devlake/plugins/helper"
+)
+
+var ConvertCommitsMeta = core.SubTaskMeta{
+	Name:             "convertCommits",
+	EntryPoint:       ConvertCommits,
+	EnabledByDefault: false,
+	Required:         false,
+	Description:      "Convert tool layer table bitbucket_commits into  domain layer table commits",
+	DomainTypes:      []string{core.DOMAIN_TYPE_CODE},
+}
+
+func ConvertCommits(taskCtx core.SubTaskContext) error {
+	db := taskCtx.GetDal()
+	data := taskCtx.GetData().(*BitbucketTaskData)
+	repoId := data.Repo.BitbucketId
+
+	cursor, err := db.Cursor(
+		dal.From("_tool_bitbucket_commits gc"),
+		dal.Join(`left join _tool_bitbucket_repo_commits grc on (
+			grc.commit_sha = gc.sha
+		)`),
+		dal.Select("gc.*"),
+		dal.Where("grc.repo_id = ? AND grc.connection_id = ?", repoId, data.Options.ConnectionId),
+	)
+	if err != nil {
+		return err
+	}
+	defer cursor.Close()
+
+	repoDidGen := didgen.NewDomainIdGenerator(&bitbucketModels.BitbucketRepo{})
+	domainRepoId := repoDidGen.Generate(data.Options.ConnectionId, repoId)
+
+	converter, err := helper.NewDataConverter(helper.DataConverterArgs{
+		RawDataSubTaskArgs: helper.RawDataSubTaskArgs{
+			Ctx: taskCtx,
+			Params: BitbucketApiParams{
+				ConnectionId: data.Options.ConnectionId,
+				Owner:        data.Options.Owner,
+				Repo:         data.Options.Repo,
+			},
+			Table: RAW_COMMIT_TABLE,
+		},
+		InputRowType: reflect.TypeOf(bitbucketModels.BitbucketCommit{}),
+		Input:        cursor,
+
+		Convert: func(inputRow interface{}) ([]interface{}, error) {
+			bitbucketCommit := inputRow.(*bitbucketModels.BitbucketCommit)
+			domainCommit := &code.Commit{
+				Sha:           bitbucketCommit.Sha,
+				Message:       bitbucketCommit.Message,
+				Additions:     bitbucketCommit.Additions,
+				Deletions:     bitbucketCommit.Deletions,
+				AuthorId:      bitbucketCommit.AuthorEmail,
+				AuthorName:    bitbucketCommit.AuthorName,
+				AuthorEmail:   bitbucketCommit.AuthorEmail,
+				AuthoredDate:  bitbucketCommit.AuthoredDate,
+				CommittedDate: bitbucketCommit.CommittedDate,
+			}
+			repoCommit := &code.RepoCommit{
+				RepoId:    domainRepoId,
+				CommitSha: domainCommit.Sha,
+			}
+			return []interface{}{
+				domainCommit,
+				repoCommit,
+			}, nil
+		},
+	})
+	if err != nil {
+		return err
+	}
+
+	return converter.Execute()
+}
diff --git a/plugins/bitbucket/tasks/commit_extractor.go b/plugins/bitbucket/tasks/commit_extractor.go
new file mode 100644
index 00000000..d209a4d4
--- /dev/null
+++ b/plugins/bitbucket/tasks/commit_extractor.go
@@ -0,0 +1,123 @@
+/*
+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 tasks
+
+import (
+	"encoding/json"
+	"time"
+
+	"github.com/apache/incubator-devlake/plugins/bitbucket/models"
+	"github.com/apache/incubator-devlake/plugins/core"
+	"github.com/apache/incubator-devlake/plugins/helper"
+)
+
+var ExtractApiCommitsMeta = core.SubTaskMeta{
+	Name:             "extractApiCommits",
+	EntryPoint:       ExtractApiCommits,
+	EnabledByDefault: false,
+	Required:         false,
+	Description:      "Extract raw commit data into tool layer table bitbucket_commits",
+	DomainTypes:      []string{core.DOMAIN_TYPE_CODE},
+}
+
+type CommitsResponse struct {
+	Type string    `json:"type"`
+	Sha  string    `json:"hash"`
+	Date time.Time `json:"date"`
+	//Author *models.BitbucketAccount
+	Message string `json:"message"`
+	Links   struct {
+		Self     struct{ Href string }
+		Html     struct{ Href string }
+		Diff     struct{ Href string }
+		Approve  struct{ Href string }
+		Comments struct{ Href string }
+	} `json:"links"`
+	Parents []struct {
+		Type  string
+		Hash  string
+		Links struct {
+			Self struct{ Href string }
+			Html struct{ Href string }
+		}
+	} `json:"parents"`
+}
+
+func ExtractApiCommits(taskCtx core.SubTaskContext) error {
+	data := taskCtx.GetData().(*BitbucketTaskData)
+
+	extractor, err := helper.NewApiExtractor(helper.ApiExtractorArgs{
+		RawDataSubTaskArgs: helper.RawDataSubTaskArgs{
+			Ctx: taskCtx,
+			/*
+				This struct will be JSONEncoded and stored into database along with raw data itself, to identity minimal
+				set of data to be process, for example, we process JiraCommits by Board
+			*/
+			Params: BitbucketApiParams{
+				ConnectionId: data.Options.ConnectionId,
+				Owner:        data.Options.Owner,
+				Repo:         data.Options.Repo,
+			},
+			/*
+				Table store raw data
+			*/
+			Table: RAW_COMMIT_TABLE,
+		},
+		Extract: func(row *helper.RawData) ([]interface{}, error) {
+			commit := &CommitsResponse{}
+			err := json.Unmarshal(row.Data, commit)
+			if err != nil {
+				return nil, err
+			}
+			if commit.Sha == "" {
+				return nil, nil
+			}
+			results := make([]interface{}, 0, 4)
+
+			bitbucketCommit := &models.BitbucketCommit{
+				Sha:           commit.Sha,
+				Message:       commit.Message,
+				AuthoredDate:  commit.Date,
+				Url:           commit.Links.Self.Href,
+				CommittedDate: commit.Date,
+			}
+
+			//if commit.Author != nil {
+			//	bitbucketCommit.AuthorName = commit.Author.User.DisplayName
+			//	bitbucketCommit.AuthorId = commit.Author.User.AccountId
+			//	results = append(results, commit.Author)
+			//}
+
+			bitbucketRepoCommit := &models.BitbucketRepoCommit{
+				ConnectionId: data.Options.ConnectionId,
+				RepoId:       data.Repo.BitbucketId,
+				CommitSha:    commit.Sha,
+			}
+
+			results = append(results, bitbucketCommit)
+			results = append(results, bitbucketRepoCommit)
+			return results, nil
+		},
+	})
+
+	if err != nil {
+		return err
+	}
+
+	return extractor.Execute()
+}
diff --git a/plugins/bitbucket/tasks/issue_collector.go b/plugins/bitbucket/tasks/issue_collector.go
new file mode 100644
index 00000000..dd08b1ba
--- /dev/null
+++ b/plugins/bitbucket/tasks/issue_collector.go
@@ -0,0 +1,55 @@
+/*
+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 tasks
+
+import (
+	"github.com/apache/incubator-devlake/plugins/helper"
+
+	"github.com/apache/incubator-devlake/plugins/core"
+)
+
+const RAW_ISSUE_TABLE = "bitbucket_api_issues"
+
+var CollectApiIssuesMeta = core.SubTaskMeta{
+	Name:             "collectApiIssues",
+	EntryPoint:       CollectApiIssues,
+	EnabledByDefault: true,
+	Description:      "Collect issues data from Bitbucket api",
+	DomainTypes:      []string{core.DOMAIN_TYPE_TICKET},
+}
+
+func CollectApiIssues(taskCtx core.SubTaskContext) error {
+	rawDataSubTaskArgs, data := CreateRawDataSubTaskArgs(taskCtx, RAW_ISSUE_TABLE)
+
+	collector, err := helper.NewApiCollector(helper.ApiCollectorArgs{
+		RawDataSubTaskArgs: *rawDataSubTaskArgs,
+		ApiClient:          data.ApiClient,
+		PageSize:           100,
+		Incremental:        false,
+		UrlTemplate:        "repositories/{{ .Params.Owner }}/{{ .Params.Repo }}/issues",
+		Query:              GetQuery,
+		GetTotalPages:      GetTotalPagesFromResponse,
+		ResponseParser:     GetRawMessageFromResponse,
+	})
+
+	if err != nil {
+		return err
+	}
+
+	return collector.Execute()
+}
diff --git a/plugins/bitbucket/tasks/issue_comment_collector.go b/plugins/bitbucket/tasks/issue_comment_collector.go
new file mode 100644
index 00000000..c8f40132
--- /dev/null
+++ b/plugins/bitbucket/tasks/issue_comment_collector.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 tasks
+
+import (
+	"github.com/apache/incubator-devlake/plugins/core"
+	"github.com/apache/incubator-devlake/plugins/helper"
+)
+
+const RAW_ISSUE_COMMENTS_TABLE = "bitbucket_api_issue_comments"
+
+var CollectApiIssueCommentsMeta = core.SubTaskMeta{
+	Name:             "collectApiIssueComments",
+	EntryPoint:       CollectApiIssueComments,
+	EnabledByDefault: true,
+	Required:         true,
+	Description:      "Collect issue comments data from bitbucket api",
+	DomainTypes:      []string{core.DOMAIN_TYPE_CODE},
+}
+
+func CollectApiIssueComments(taskCtx core.SubTaskContext) error {
+	rawDataSubTaskArgs, data := CreateRawDataSubTaskArgs(taskCtx, RAW_ISSUE_COMMENTS_TABLE)
+
+	iterator, err := GetIssuesIterator(taskCtx)
+	if err != nil {
+		return err
+	}
+	defer iterator.Close()
+
+	collector, err := helper.NewApiCollector(helper.ApiCollectorArgs{
+		RawDataSubTaskArgs: *rawDataSubTaskArgs,
+		ApiClient:          data.ApiClient,
+		PageSize:           100,
+		Incremental:        false,
+		Input:              iterator,
+		UrlTemplate:        "repositories/{{ .Params.Owner }}/{{ .Params.Repo }}/issues/{{ .Input.BitbucketId }}/comments",
+		Query:              GetQuery,
+		GetTotalPages:      GetTotalPagesFromResponse,
+		ResponseParser:     GetRawMessageFromResponse,
+	})
+	if err != nil {
+		return err
+	}
+
+	return collector.Execute()
+}
diff --git a/plugins/bitbucket/tasks/issue_comment_convertor.go b/plugins/bitbucket/tasks/issue_comment_convertor.go
new file mode 100644
index 00000000..97dc0627
--- /dev/null
+++ b/plugins/bitbucket/tasks/issue_comment_convertor.go
@@ -0,0 +1,92 @@
+/*
+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 tasks
+
+import (
+	"github.com/apache/incubator-devlake/models/domainlayer/ticket"
+	"reflect"
+
+	"github.com/apache/incubator-devlake/models/domainlayer"
+	"github.com/apache/incubator-devlake/models/domainlayer/didgen"
+	bitbucketModels "github.com/apache/incubator-devlake/plugins/bitbucket/models"
+	"github.com/apache/incubator-devlake/plugins/core"
+	"github.com/apache/incubator-devlake/plugins/core/dal"
+	"github.com/apache/incubator-devlake/plugins/helper"
+)
+
+var ConvertIssueCommentsMeta = core.SubTaskMeta{
+	Name:             "convertIssueComments",
+	EntryPoint:       ConvertIssueComments,
+	EnabledByDefault: true,
+	Description:      "ConvertIssueComments data from Bitbucket api",
+	DomainTypes:      []string{core.DOMAIN_TYPE_CODE},
+}
+
+func ConvertIssueComments(taskCtx core.SubTaskContext) error {
+	db := taskCtx.GetDal()
+	data := taskCtx.GetData().(*BitbucketTaskData)
+	repoId := data.Repo.BitbucketId
+
+	cursor, err := db.Cursor(
+		dal.From(&bitbucketModels.BitbucketIssueComment{}),
+		dal.Join("left join _tool_bitbucket_issues "+
+			"on _tool_bitbucket_issues.bitbucket_id = _tool_bitbucket_issue_comments.issue_id"),
+		dal.Where("repo_id = ? and _tool_bitbucket_issues.connection_id = ?", repoId, data.Options.ConnectionId),
+	)
+	if err != nil {
+		return err
+	}
+	defer cursor.Close()
+
+	issueIdGen := didgen.NewDomainIdGenerator(&bitbucketModels.BitbucketIssue{})
+	accountIdGen := didgen.NewDomainIdGenerator(&bitbucketModels.BitbucketAccount{})
+
+	converter, err := helper.NewDataConverter(helper.DataConverterArgs{
+		InputRowType: reflect.TypeOf(bitbucketModels.BitbucketIssueComment{}),
+		Input:        cursor,
+		RawDataSubTaskArgs: helper.RawDataSubTaskArgs{
+			Ctx: taskCtx,
+			Params: BitbucketApiParams{
+				ConnectionId: data.Options.ConnectionId,
+				Owner:        data.Options.Owner,
+				Repo:         data.Options.Repo,
+			},
+			Table: RAW_ISSUE_COMMENTS_TABLE,
+		},
+		Convert: func(inputRow interface{}) ([]interface{}, error) {
+			bitbucketIssueComment := inputRow.(*bitbucketModels.BitbucketIssueComment)
+			domainIssueComment := &ticket.IssueComment{
+				DomainEntity: domainlayer.DomainEntity{
+					Id: issueIdGen.Generate(data.Options.ConnectionId, bitbucketIssueComment.BitbucketId),
+				},
+				IssueId:     issueIdGen.Generate(data.Options.ConnectionId, bitbucketIssueComment.IssueId),
+				UserId:      accountIdGen.Generate(data.Options.ConnectionId, bitbucketIssueComment.AuthorId),
+				CreatedDate: bitbucketIssueComment.CreatedAt,
+				Body:        bitbucketIssueComment.Body,
+			}
+			return []interface{}{
+				domainIssueComment,
+			}, nil
+		},
+	})
+	if err != nil {
+		return err
+	}
+
+	return converter.Execute()
+}
diff --git a/plugins/bitbucket/tasks/issue_comment_extractor.go b/plugins/bitbucket/tasks/issue_comment_extractor.go
new file mode 100644
index 00000000..35042461
--- /dev/null
+++ b/plugins/bitbucket/tasks/issue_comment_extractor.go
@@ -0,0 +1,122 @@
+/*
+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 tasks
+
+import (
+	"encoding/json"
+	"github.com/apache/incubator-devlake/plugins/bitbucket/models"
+	"github.com/apache/incubator-devlake/plugins/core"
+	"github.com/apache/incubator-devlake/plugins/helper"
+	"time"
+)
+
+type BitbucketIssueCommentsResponse struct {
+	Type        string     `json:"type"`
+	BitbucketId int        `json:"id"`
+	CreatedOn   time.Time  `json:"created_on"`
+	UpdatedOn   *time.Time `json:"updated_on"`
+	Content     struct {
+		Type string
+		Raw  string `json:"raw"`
+	} `json:"content"`
+	User  *BitbucketAccountResponse
+	Issue struct {
+		Type       string
+		Id         int
+		Repository *BitbucketApiRepo
+		Links      struct {
+			Self struct {
+				Href string
+			}
+		}
+		Title string
+	}
+	Links struct {
+		Self struct {
+			Href string
+		} `json:"self"`
+		Html struct {
+			Href string
+		} `json:"html"`
+	} `json:"links"`
+}
+
+var ExtractApiIssueCommentsMeta = core.SubTaskMeta{
+	Name:             "extractApiIssueComments",
+	EntryPoint:       ExtractApiIssueComments,
+	EnabledByDefault: true,
+	Required:         true,
+	Description:      "Extract raw issue comments data into tool layer table BitbucketIssueComments",
+	DomainTypes:      []string{core.DOMAIN_TYPE_CODE},
+}
+
+func ExtractApiIssueComments(taskCtx core.SubTaskContext) error {
+	rawDataSubTaskArgs, data := CreateRawDataSubTaskArgs(taskCtx, RAW_ISSUE_COMMENTS_TABLE)
+
+	extractor, err := helper.NewApiExtractor(helper.ApiExtractorArgs{
+		RawDataSubTaskArgs: *rawDataSubTaskArgs,
+		Extract: func(row *helper.RawData) ([]interface{}, error) {
+			issueComment := &BitbucketIssueCommentsResponse{}
+			err := json.Unmarshal(row.Data, issueComment)
+			if err != nil {
+				return nil, err
+			}
+
+			toolIssueComment, err := convertIssueComment(issueComment)
+			toolIssueComment.ConnectionId = data.Options.ConnectionId
+			if err != nil {
+				return nil, err
+			}
+			results := make([]interface{}, 0, 2)
+
+			if issueComment.User != nil {
+				bitbucketUser, err := convertAccount(issueComment.User, data.Options.ConnectionId)
+				if err != nil {
+					return nil, err
+				}
+				toolIssueComment.AuthorId = bitbucketUser.AccountId
+				toolIssueComment.AuthorName = bitbucketUser.DisplayName
+				results = append(results, bitbucketUser)
+			}
+
+			results = append(results, toolIssueComment)
+
+			return results, nil
+		},
+	})
+
+	if err != nil {
+		return err
+	}
+
+	return extractor.Execute()
+}
+
+func convertIssueComment(issueComment *BitbucketIssueCommentsResponse) (*models.BitbucketIssueComment, error) {
+	bitbucketIssueComment := &models.BitbucketIssueComment{
+		BitbucketId:        issueComment.BitbucketId,
+		AuthorId:           issueComment.User.AccountId,
+		IssueId:            issueComment.Issue.Id,
+		AuthorName:         issueComment.User.DisplayName,
+		BitbucketCreatedAt: issueComment.CreatedOn,
+		BitbucketUpdatedAt: issueComment.UpdatedOn,
+		Type:               issueComment.Type,
+		Body:               issueComment.Content.Raw,
+	}
+	return bitbucketIssueComment, nil
+}
diff --git a/plugins/bitbucket/tasks/issue_convertor.go b/plugins/bitbucket/tasks/issue_convertor.go
new file mode 100644
index 00000000..cb928bfb
--- /dev/null
+++ b/plugins/bitbucket/tasks/issue_convertor.go
@@ -0,0 +1,120 @@
+/*
+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 tasks
+
+import (
+	"reflect"
+	"strconv"
+
+	"github.com/apache/incubator-devlake/plugins/core/dal"
+
+	"github.com/apache/incubator-devlake/plugins/core"
+	"github.com/apache/incubator-devlake/plugins/helper"
+
+	"github.com/apache/incubator-devlake/models/domainlayer"
+	"github.com/apache/incubator-devlake/models/domainlayer/didgen"
+	"github.com/apache/incubator-devlake/models/domainlayer/ticket"
+	bitbucketModels "github.com/apache/incubator-devlake/plugins/bitbucket/models"
+)
+
+var ConvertIssuesMeta = core.SubTaskMeta{
+	Name:             "convertIssues",
+	EntryPoint:       ConvertIssues,
+	EnabledByDefault: true,
+	Description:      "Convert tool layer table bitbucket_issues into  domain layer table issues",
+	DomainTypes:      []string{core.DOMAIN_TYPE_TICKET},
+}
+
+func ConvertIssues(taskCtx core.SubTaskContext) error {
+	db := taskCtx.GetDal()
+	data := taskCtx.GetData().(*BitbucketTaskData)
+	repoId := data.Repo.BitbucketId
+
+	issue := &bitbucketModels.BitbucketIssue{}
+	cursor, err := db.Cursor(
+		dal.From(issue),
+		dal.Where("repo_id = ? and connection_id=?", repoId, data.Options.ConnectionId),
+	)
+	if err != nil {
+		return err
+	}
+	defer cursor.Close()
+
+	issueIdGen := didgen.NewDomainIdGenerator(&bitbucketModels.BitbucketIssue{})
+	boardIdGen := didgen.NewDomainIdGenerator(&bitbucketModels.BitbucketRepo{})
+	accountIdGen := didgen.NewDomainIdGenerator(&bitbucketModels.BitbucketAccount{})
+
+	converter, err := helper.NewDataConverter(helper.DataConverterArgs{
+		RawDataSubTaskArgs: helper.RawDataSubTaskArgs{
+			Ctx: taskCtx,
+			Params: BitbucketApiParams{
+				ConnectionId: data.Options.ConnectionId,
+				Owner:        data.Options.Owner,
+				Repo:         data.Options.Repo,
+			},
+			Table: RAW_ISSUE_TABLE,
+		},
+		InputRowType: reflect.TypeOf(bitbucketModels.BitbucketIssue{}),
+		Input:        cursor,
+		Convert: func(inputRow interface{}) ([]interface{}, error) {
+			issue := inputRow.(*bitbucketModels.BitbucketIssue)
+			domainIssue := &ticket.Issue{
+				DomainEntity:    domainlayer.DomainEntity{Id: issueIdGen.Generate(data.Options.ConnectionId, issue.BitbucketId)},
+				IssueKey:        strconv.Itoa(issue.Number),
+				Title:           issue.Title,
+				Description:     issue.Body,
+				Priority:        issue.Priority,
+				Type:            issue.Type,
+				OriginalStatus:  issue.State,
+				LeadTimeMinutes: issue.LeadTimeMinutes,
+				Url:             issue.Url,
+				CreatedDate:     &issue.BitbucketCreatedAt,
+				UpdatedDate:     &issue.BitbucketUpdatedAt,
+				ResolutionDate:  issue.ClosedAt,
+				Severity:        issue.Severity,
+				Component:       issue.Component,
+			}
+			if issue.State == "closed" {
+				domainIssue.Status = ticket.DONE
+			} else {
+				domainIssue.Status = ticket.TODO
+			}
+			if issue.AssigneeName != "" {
+				domainIssue.AssigneeName = issue.AssigneeName
+				domainIssue.AssigneeId = accountIdGen.Generate(data.Options.ConnectionId, issue.AssigneeId)
+			}
+			if issue.AuthorName != "" {
+				domainIssue.CreatorName = issue.AuthorName
+				domainIssue.CreatorId = accountIdGen.Generate(data.Options.ConnectionId, issue.AuthorId)
+			}
+			boardIssue := &ticket.BoardIssue{
+				BoardId: boardIdGen.Generate(data.Options.ConnectionId, repoId),
+				IssueId: domainIssue.Id,
+			}
+			return []interface{}{
+				domainIssue,
+				boardIssue,
+			}, nil
+		},
+	})
+	if err != nil {
+		return err
+	}
+
+	return converter.Execute()
+}
diff --git a/plugins/bitbucket/tasks/issue_extractor.go b/plugins/bitbucket/tasks/issue_extractor.go
new file mode 100644
index 00000000..9d1cd5dc
--- /dev/null
+++ b/plugins/bitbucket/tasks/issue_extractor.go
@@ -0,0 +1,179 @@
+/*
+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 tasks
+
+import (
+	"encoding/json"
+	"regexp"
+	"time"
+
+	"github.com/apache/incubator-devlake/plugins/bitbucket/models"
+	"github.com/apache/incubator-devlake/plugins/core"
+	"github.com/apache/incubator-devlake/plugins/helper"
+)
+
+type IssuesResponse struct {
+	Type        string `json:"type"`
+	BitbucketId int    `json:"id"`
+	Repository  *BitbucketApiRepo
+	Links       struct {
+		Self struct {
+			Href string
+		} `json:"self"`
+		Html struct {
+			Href string
+		} `json:"html"`
+	} `json:"links"`
+	Title   string `json:"title"`
+	Content struct {
+		Type string
+		Raw  string
+	} `json:"content"`
+	Reporter  *BitbucketAccountResponse
+	Assignee  *BitbucketAccountResponse
+	State     string `json:"state"`
+	Kind      string `json:"kind"`
+	Milestone *struct {
+		Id int
+	} `json:"milestone"`
+	Component          string    `json:"component"`
+	Priority           string    `json:"priority"`
+	Votes              int       `json:"votes"`
+	Watches            int       `json:"watches"`
+	BitbucketCreatedAt time.Time `json:"created_on"`
+	BitbucketUpdatedAt time.Time `json:"updated_on"`
+}
+
+type IssueRegexes struct {
+	SeverityRegex        *regexp.Regexp
+	ComponentRegex       *regexp.Regexp
+	PriorityRegex        *regexp.Regexp
+	TypeBugRegex         *regexp.Regexp
+	TypeRequirementRegex *regexp.Regexp
+	TypeIncidentRegex    *regexp.Regexp
+}
+
+var ExtractApiIssuesMeta = core.SubTaskMeta{
+	Name:             "extractApiIssues",
+	EntryPoint:       ExtractApiIssues,
+	EnabledByDefault: true,
+	Description:      "Extract raw Issues data into tool layer table bitbucket_issues",
+	DomainTypes:      []string{core.DOMAIN_TYPE_TICKET},
+}
+
+func ExtractApiIssues(taskCtx core.SubTaskContext) error {
+	data := taskCtx.GetData().(*BitbucketTaskData)
+
+	extractor, err := helper.NewApiExtractor(helper.ApiExtractorArgs{
+		RawDataSubTaskArgs: helper.RawDataSubTaskArgs{
+			Ctx: taskCtx,
+			/*
+				This struct will be JSONEncoded and stored into database along with raw data itself, to identity minimal
+				set of data to be process, for example, we process JiraIssues by Board
+			*/
+			Params: BitbucketApiParams{
+				ConnectionId: data.Options.ConnectionId,
+				Owner:        data.Options.Owner,
+				Repo:         data.Options.Repo,
+			},
+			/*
+				Table store raw data
+			*/
+			Table: RAW_ISSUE_TABLE,
+		},
+		Extract: func(row *helper.RawData) ([]interface{}, error) {
+			body := &IssuesResponse{}
+			err := json.Unmarshal(row.Data, body)
+			if err != nil {
+				return nil, err
+			}
+			// need to extract 2 kinds of entities here
+			if body.BitbucketId == 0 {
+				return nil, nil
+			}
+			//If this is not an issue, ignore
+			if body.Type != "issue" {
+				return nil, nil
+			}
+			results := make([]interface{}, 0, 2)
+
+			bitbucketIssue, err := convertBitbucketIssue(body, data.Options.ConnectionId, data.Repo.BitbucketId)
+			if err != nil {
+				return nil, err
+			}
+
+			results = append(results, bitbucketIssue)
+			if body.Assignee != nil {
+				bitbucketIssue.AssigneeId = body.Assignee.AccountId
+				bitbucketIssue.AssigneeName = body.Assignee.DisplayName
+				relatedUser, err := convertAccount(body.Assignee, data.Options.ConnectionId)
+				if err != nil {
+					return nil, err
+				}
+				results = append(results, relatedUser)
+			}
+			if body.Reporter != nil {
+				bitbucketIssue.AuthorId = body.Reporter.AccountId
+				bitbucketIssue.AuthorName = body.Reporter.DisplayName
+				relatedUser, err := convertAccount(body.Reporter, data.Options.ConnectionId)
+				if err != nil {
+					return nil, err
+				}
+				results = append(results, relatedUser)
+			}
+			return results, nil
+		},
+	})
+	if err != nil {
+		return err
+	}
+
+	return extractor.Execute()
+}
+
+func convertBitbucketIssue(issue *IssuesResponse, connectionId uint64, repositoryId string) (*models.BitbucketIssue, error) {
+	bitbucketIssue := &models.BitbucketIssue{
+		ConnectionId:       connectionId,
+		BitbucketId:        issue.BitbucketId,
+		RepoId:             repositoryId,
+		Number:             issue.BitbucketId,
+		State:              issue.State,
+		Title:              issue.Title,
+		Type:               issue.Type,
+		Body:               issue.Content.Raw,
+		Url:                issue.Links.Self.Href,
+		Priority:           issue.Priority,
+		Component:          issue.Component,
+		BitbucketCreatedAt: issue.BitbucketCreatedAt,
+		BitbucketUpdatedAt: issue.BitbucketUpdatedAt,
+	}
+
+	if issue.Milestone != nil {
+		bitbucketIssue.MilestoneId = issue.Milestone.Id
+	}
+	if issue.Assignee != nil {
+		bitbucketIssue.AssigneeId = issue.Assignee.AccountId
+		bitbucketIssue.AssigneeName = issue.Assignee.DisplayName
+	}
+	if issue.Reporter != nil {
+		bitbucketIssue.AuthorId = issue.Reporter.AccountId
+		bitbucketIssue.AuthorName = issue.Reporter.DisplayName
+	}
+
+	return bitbucketIssue, nil
+}
diff --git a/plugins/bitbucket/tasks/pr_collector.go b/plugins/bitbucket/tasks/pr_collector.go
new file mode 100644
index 00000000..eb0a81b3
--- /dev/null
+++ b/plugins/bitbucket/tasks/pr_collector.go
@@ -0,0 +1,58 @@
+/*
+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 tasks
+
+import (
+	"github.com/apache/incubator-devlake/plugins/helper"
+
+	"github.com/apache/incubator-devlake/plugins/core"
+)
+
+const RAW_PULL_REQUEST_TABLE = "bitbucket_api_pull_requests"
+
+// this struct should be moved to `bitbucket_api_common.go`
+
+var CollectApiPullRequestsMeta = core.SubTaskMeta{
+	Name:             "collectApiPullRequests",
+	EntryPoint:       CollectApiPullRequests,
+	EnabledByDefault: true,
+	Required:         true,
+	Description:      "Collect PullRequests data from Bitbucket api",
+	DomainTypes:      []string{core.DOMAIN_TYPE_CODE},
+}
+
+func CollectApiPullRequests(taskCtx core.SubTaskContext) error {
+	rawDataSubTaskArgs, data := CreateRawDataSubTaskArgs(taskCtx, RAW_PULL_REQUEST_TABLE)
+
+	collector, err := helper.NewApiCollector(helper.ApiCollectorArgs{
+		RawDataSubTaskArgs: *rawDataSubTaskArgs,
+		ApiClient:          data.ApiClient,
+		PageSize:           50,
+		Incremental:        false,
+		UrlTemplate:        "repositories/{{ .Params.Owner }}/{{ .Params.Repo }}/pullrequests",
+		Query:              GetQuery,
+		GetTotalPages:      GetTotalPagesFromResponse,
+		ResponseParser:     GetRawMessageFromResponse,
+	})
+
+	if err != nil {
+		return err
+	}
+
+	return collector.Execute()
+}
diff --git a/plugins/bitbucket/tasks/pr_comment_collector.go b/plugins/bitbucket/tasks/pr_comment_collector.go
new file mode 100644
index 00000000..33bba48c
--- /dev/null
+++ b/plugins/bitbucket/tasks/pr_comment_collector.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 tasks
+
+import (
+	"github.com/apache/incubator-devlake/plugins/core"
+	"github.com/apache/incubator-devlake/plugins/helper"
+)
+
+const RAW_PULL_REQUEST_COMMENTS_TABLE = "bitbucket_api_pull_request_comments"
+
+var CollectApiPrCommentsMeta = core.SubTaskMeta{
+	Name:             "collectApiPullRequestsComments",
+	EntryPoint:       CollectApiPullRequestsComments,
+	EnabledByDefault: true,
+	Required:         true,
+	Description:      "Collect pull requests comments data from bitbucket api",
+	DomainTypes:      []string{core.DOMAIN_TYPE_CODE},
+}
+
+func CollectApiPullRequestsComments(taskCtx core.SubTaskContext) error {
+	rawDataSubTaskArgs, data := CreateRawDataSubTaskArgs(taskCtx, RAW_PULL_REQUEST_COMMENTS_TABLE)
+
+	iterator, err := GetPullRequestsIterator(taskCtx)
+	if err != nil {
+		return err
+	}
+	defer iterator.Close()
+
+	collector, err := helper.NewApiCollector(helper.ApiCollectorArgs{
+		RawDataSubTaskArgs: *rawDataSubTaskArgs,
+		ApiClient:          data.ApiClient,
+		PageSize:           100,
+		Incremental:        false,
+		Input:              iterator,
+		UrlTemplate:        "repositories/{{ .Params.Owner }}/{{ .Params.Repo }}/pullrequests/{{ .Input.BitbucketId }}/comments",
+		Query:              GetQuery,
+		GetTotalPages:      GetTotalPagesFromResponse,
+		ResponseParser:     GetRawMessageFromResponse,
+	})
+	if err != nil {
+		return err
+	}
+
+	return collector.Execute()
+}
diff --git a/plugins/bitbucket/tasks/pr_comment_convertor.go b/plugins/bitbucket/tasks/pr_comment_convertor.go
new file mode 100644
index 00000000..467869ce
--- /dev/null
+++ b/plugins/bitbucket/tasks/pr_comment_convertor.go
@@ -0,0 +1,96 @@
+/*
+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 tasks
+
+import (
+	"reflect"
+
+	"github.com/apache/incubator-devlake/models/domainlayer"
+	"github.com/apache/incubator-devlake/models/domainlayer/code"
+	"github.com/apache/incubator-devlake/models/domainlayer/didgen"
+	bitbucketModels "github.com/apache/incubator-devlake/plugins/bitbucket/models"
+	"github.com/apache/incubator-devlake/plugins/core"
+	"github.com/apache/incubator-devlake/plugins/core/dal"
+	"github.com/apache/incubator-devlake/plugins/helper"
+)
+
+var ConvertPrCommentsMeta = core.SubTaskMeta{
+	Name:             "convertPullRequestComments",
+	EntryPoint:       ConvertPullRequestComments,
+	EnabledByDefault: true,
+	Description:      "ConvertPullRequestComments data from Bitbucket api",
+	DomainTypes:      []string{core.DOMAIN_TYPE_CODE},
+}
+
+func ConvertPullRequestComments(taskCtx core.SubTaskContext) error {
+	db := taskCtx.GetDal()
+	data := taskCtx.GetData().(*BitbucketTaskData)
+	repoId := data.Repo.BitbucketId
+
+	cursor, err := db.Cursor(
+		dal.From(&bitbucketModels.BitbucketPrComment{}),
+		dal.Join("left join _tool_bitbucket_pull_requests "+
+			"on _tool_bitbucket_pull_requests.bitbucket_id = _tool_bitbucket_pull_request_comments.pull_request_id"),
+		dal.Where("repo_id = ? and _tool_bitbucket_pull_requests.connection_id = ?", repoId, data.Options.ConnectionId),
+	)
+	if err != nil {
+		return err
+	}
+	defer cursor.Close()
+
+	domainIdGeneratorComment := didgen.NewDomainIdGenerator(&bitbucketModels.BitbucketPrComment{})
+	prIdGen := didgen.NewDomainIdGenerator(&bitbucketModels.BitbucketPullRequest{})
+	accountIdGen := didgen.NewDomainIdGenerator(&bitbucketModels.BitbucketAccount{})
+
+	converter, err := helper.NewDataConverter(helper.DataConverterArgs{
+		InputRowType: reflect.TypeOf(bitbucketModels.BitbucketPrComment{}),
+		Input:        cursor,
+		RawDataSubTaskArgs: helper.RawDataSubTaskArgs{
+			Ctx: taskCtx,
+			Params: BitbucketApiParams{
+				ConnectionId: data.Options.ConnectionId,
+				Owner:        data.Options.Owner,
+				Repo:         data.Options.Repo,
+			},
+			Table: RAW_PULL_REQUEST_COMMENTS_TABLE,
+		},
+		Convert: func(inputRow interface{}) ([]interface{}, error) {
+			bitbucketPullRequestComment := inputRow.(*bitbucketModels.BitbucketPrComment)
+			domainPrComment := &code.PullRequestComment{
+				DomainEntity: domainlayer.DomainEntity{
+					Id: domainIdGeneratorComment.Generate(data.Options.ConnectionId, bitbucketPullRequestComment.BitbucketId),
+				},
+				PullRequestId: prIdGen.Generate(data.Options.ConnectionId, bitbucketPullRequestComment.PullRequestId),
+				UserId:        accountIdGen.Generate(data.Options.ConnectionId, bitbucketPullRequestComment.AuthorId),
+				CreatedDate:   bitbucketPullRequestComment.CreatedAt,
+				Body:          bitbucketPullRequestComment.Body,
+				Type:          bitbucketPullRequestComment.Type,
+				CommitSha:     "",
+				Position:      0,
+			}
+			return []interface{}{
+				domainPrComment,
+			}, nil
+		},
+	})
+	if err != nil {
+		return err
+	}
+
+	return converter.Execute()
+}
diff --git a/plugins/bitbucket/tasks/pr_comment_extractor.go b/plugins/bitbucket/tasks/pr_comment_extractor.go
new file mode 100644
index 00000000..9acc5100
--- /dev/null
+++ b/plugins/bitbucket/tasks/pr_comment_extractor.go
@@ -0,0 +1,124 @@
+/*
+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 tasks
+
+import (
+	"encoding/json"
+	"github.com/apache/incubator-devlake/plugins/bitbucket/models"
+	"github.com/apache/incubator-devlake/plugins/core"
+	"github.com/apache/incubator-devlake/plugins/helper"
+	"time"
+)
+
+var ExtractApiPrCommentsMeta = core.SubTaskMeta{
+	Name:             "extractApiPullRequestsComments",
+	EntryPoint:       ExtractApiPullRequestsComments,
+	EnabledByDefault: true,
+	Required:         true,
+	Description:      "Extract raw pull requests comments data into tool layer table BitbucketPrComments",
+	DomainTypes:      []string{core.DOMAIN_TYPE_CODE},
+}
+
+type BitbucketPrCommentsResponse struct {
+	BitbucketId int        `json:"id"`
+	CreatedOn   time.Time  `json:"created_on"`
+	UpdatedOn   *time.Time `json:"updated_on"`
+	Content     struct {
+		Type string
+		Raw  string
+	} `json:"content"`
+	User    *BitbucketAccountResponse
+	Deleted bool
+	Type    string `json:"type"`
+	Links   struct {
+		Self struct {
+			Href string
+		} `json:"self"`
+		Html struct {
+			Href string
+		} `json:"html"`
+	} `json:"links"`
+	PullRequest struct {
+		Type  string
+		Id    int
+		Title string
+		Links struct {
+			Self struct {
+				Href string
+			}
+			Html struct {
+				Href string
+			}
+		}
+	}
+}
+
+func ExtractApiPullRequestsComments(taskCtx core.SubTaskContext) error {
+	rawDataSubTaskArgs, data := CreateRawDataSubTaskArgs(taskCtx, RAW_PULL_REQUEST_COMMENTS_TABLE)
+
+	extractor, err := helper.NewApiExtractor(helper.ApiExtractorArgs{
+		RawDataSubTaskArgs: *rawDataSubTaskArgs,
+		Extract: func(row *helper.RawData) ([]interface{}, error) {
+			prComment := &BitbucketPrCommentsResponse{}
+			err := json.Unmarshal(row.Data, prComment)
+			if err != nil {
+				return nil, err
+			}
+
+			toolprComment, err := convertPullRequestComment(prComment)
+			toolprComment.ConnectionId = data.Options.ConnectionId
+			if err != nil {
+				return nil, err
+			}
+			results := make([]interface{}, 0, 2)
+
+			if prComment.User != nil {
+				bitbucketUser, err := convertAccount(prComment.User, data.Options.ConnectionId)
+				if err != nil {
+					return nil, err
+				}
+				toolprComment.AuthorId = bitbucketUser.AccountId
+				toolprComment.AuthorName = bitbucketUser.UserName
+				results = append(results, bitbucketUser)
+			}
+			results = append(results, toolprComment)
+
+			return results, nil
+		},
+	})
+
+	if err != nil {
+		return err
+	}
+
+	return extractor.Execute()
+}
+
+func convertPullRequestComment(prComment *BitbucketPrCommentsResponse) (*models.BitbucketPrComment, error) {
+	bitbucketPrComment := &models.BitbucketPrComment{
+		BitbucketId:        prComment.BitbucketId,
+		AuthorId:           prComment.User.AccountId,
+		PullRequestId:      prComment.PullRequest.Id,
+		AuthorName:         prComment.User.DisplayName,
+		BitbucketCreatedAt: prComment.CreatedOn,
+		BitbucketUpdatedAt: prComment.UpdatedOn,
+		Type:               prComment.Type,
+		Body:               prComment.Content.Raw,
+	}
+	return bitbucketPrComment, nil
+}
diff --git a/plugins/bitbucket/tasks/pr_convertor.go b/plugins/bitbucket/tasks/pr_convertor.go
new file mode 100644
index 00000000..48107f85
--- /dev/null
+++ b/plugins/bitbucket/tasks/pr_convertor.go
@@ -0,0 +1,108 @@
+/*
+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 tasks
+
+import (
+	"reflect"
+
+	"github.com/apache/incubator-devlake/plugins/core/dal"
+
+	"github.com/apache/incubator-devlake/models/domainlayer"
+	"github.com/apache/incubator-devlake/models/domainlayer/code"
+	"github.com/apache/incubator-devlake/models/domainlayer/didgen"
+	"github.com/apache/incubator-devlake/plugins/bitbucket/models"
+	"github.com/apache/incubator-devlake/plugins/core"
+	"github.com/apache/incubator-devlake/plugins/helper"
+)
+
+var ConvertPullRequestsMeta = core.SubTaskMeta{
+	Name:             "convertPullRequests",
+	EntryPoint:       ConvertPullRequests,
+	EnabledByDefault: true,
+	Required:         true,
+	Description:      "ConvertPullRequests data from Bitbucket api",
+	DomainTypes:      []string{core.DOMAIN_TYPE_CODE},
+}
+
+func ConvertPullRequests(taskCtx core.SubTaskContext) error {
+	db := taskCtx.GetDal()
+	data := taskCtx.GetData().(*BitbucketTaskData)
+	repoId := data.Repo.BitbucketId
+
+	cursor, err := db.Cursor(
+		dal.From(&models.BitbucketPullRequest{}),
+		dal.Where("repo_id = ? and connection_id = ?", repoId, data.Options.ConnectionId),
+	)
+	if err != nil {
+		return err
+	}
+	defer cursor.Close()
+
+	prIdGen := didgen.NewDomainIdGenerator(&models.BitbucketPullRequest{})
+	repoIdGen := didgen.NewDomainIdGenerator(&models.BitbucketRepo{})
+	domainUserIdGen := didgen.NewDomainIdGenerator(&models.BitbucketAccount{})
+
+	converter, err := helper.NewDataConverter(helper.DataConverterArgs{
+		InputRowType: reflect.TypeOf(models.BitbucketPullRequest{}),
+		Input:        cursor,
+		RawDataSubTaskArgs: helper.RawDataSubTaskArgs{
+			Ctx: taskCtx,
+			Params: BitbucketApiParams{
+				ConnectionId: data.Options.ConnectionId,
+				Owner:        data.Options.Owner,
+				Repo:         data.Options.Repo,
+			},
+			Table: RAW_PULL_REQUEST_TABLE,
+		},
+		Convert: func(inputRow interface{}) ([]interface{}, error) {
+			pr := inputRow.(*models.BitbucketPullRequest)
+			domainPr := &code.PullRequest{
+				DomainEntity: domainlayer.DomainEntity{
+					Id: prIdGen.Generate(data.Options.ConnectionId, pr.BitbucketId),
+				},
+				BaseRepoId:     repoIdGen.Generate(data.Options.ConnectionId, pr.BaseRepoId),
+				HeadRepoId:     repoIdGen.Generate(data.Options.ConnectionId, pr.HeadRepoId),
+				Status:         pr.State,
+				Title:          pr.Title,
+				Url:            pr.Url,
+				AuthorId:       domainUserIdGen.Generate(data.Options.ConnectionId, pr.AuthorId),
+				AuthorName:     pr.AuthorName,
+				Description:    pr.Description,
+				CreatedDate:    pr.BitbucketCreatedAt,
+				MergedDate:     pr.MergedAt,
+				ClosedDate:     pr.ClosedAt,
+				PullRequestKey: pr.Number,
+				Type:           pr.Type,
+				Component:      pr.Component,
+				MergeCommitSha: pr.MergeCommitSha,
+				BaseRef:        pr.BaseRef,
+				BaseCommitSha:  pr.BaseCommitSha,
+				HeadRef:        pr.HeadRef,
+				HeadCommitSha:  pr.HeadCommitSha,
+			}
+			return []interface{}{
+				domainPr,
+			}, nil
+		},
+	})
+	if err != nil {
+		return err
+	}
+
+	return converter.Execute()
+}
diff --git a/plugins/bitbucket/tasks/pr_extractor.go b/plugins/bitbucket/tasks/pr_extractor.go
new file mode 100644
index 00000000..360739a1
--- /dev/null
+++ b/plugins/bitbucket/tasks/pr_extractor.go
@@ -0,0 +1,166 @@
+/*
+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 tasks
+
+import (
+	"encoding/json"
+	"github.com/apache/incubator-devlake/plugins/bitbucket/models"
+	"github.com/apache/incubator-devlake/plugins/core"
+	"github.com/apache/incubator-devlake/plugins/helper"
+	"time"
+)
+
+var ExtractApiPullRequestsMeta = core.SubTaskMeta{
+	Name:             "extractApiPullRequests",
+	EntryPoint:       ExtractApiPullRequests,
+	EnabledByDefault: true,
+	Required:         true,
+	Description:      "Extract raw PullRequests data into tool layer table bitbucket_pull_requests",
+	DomainTypes:      []string{core.DOMAIN_TYPE_CODE},
+}
+
+type BitbucketApiPullRequest struct {
+	BitbucketId  int    `json:"id"`
+	CommentCount int    `json:"comment_count"`
+	TaskCount    int    `json:"task_count"`
+	Type         string `json:"type"`
+	State        string `json:"state"`
+	Title        string `json:"title"`
+	Description  string `json:"description"`
+	MergeCommit  *struct {
+		Type  string
+		Hash  string `json:"hash"`
+		Links *struct {
+			Self struct{ Href string }
+			Html struct{ Href string }
+		}
+	} `json:"merge_commit"`
+	Links *struct {
+		Self struct{ Href string }
+		Html struct{ Href string }
+	}
+	ClosedBy           *BitbucketAccountResponse `json:"closed_by"`
+	Author             *BitbucketAccountResponse `json:"author"`
+	BitbucketCreatedAt time.Time                 `json:"created_on"`
+	BitbucketUpdatedAt time.Time                 `json:"updated_on"`
+	BaseRef            *struct {
+		Branch struct {
+			Name string
+		} `json:"branch"`
+		Commit struct {
+			Type string
+			Hash string
+		} `json:"commit"`
+		Repo *BitbucketApiRepo `json:"repository"`
+	} `json:"destination"`
+	HeadRef *struct {
+		Branch struct {
+			Name string
+		} `json:"branch"`
+		Commit struct {
+			Type string
+			Hash string
+		} `json:"commit"`
+		Repo *BitbucketApiRepo `json:"repository"`
+	} `json:"source"`
+	Reviewers    []BitbucketAccountResponse `json:"reviewers"`
+	Participants []BitbucketAccountResponse `json:"participants"`
+}
+
+func ExtractApiPullRequests(taskCtx core.SubTaskContext) error {
+	data := taskCtx.GetData().(*BitbucketTaskData)
+	var err error
+	extractor, err := helper.NewApiExtractor(helper.ApiExtractorArgs{
+		RawDataSubTaskArgs: helper.RawDataSubTaskArgs{
+			Ctx: taskCtx,
+			/*
+				This struct will be JSONEncoded and stored into database along with raw data itself, to identity minimal
+				set of data to be process, for example, we process JiraIssues by Board
+			*/
+			Params: BitbucketApiParams{
+				ConnectionId: data.Options.ConnectionId,
+				Owner:        data.Options.Owner,
+				Repo:         data.Options.Repo,
+			},
+			/*
+				Table store raw data
+			*/
+			Table: RAW_PULL_REQUEST_TABLE,
+		},
+		Extract: func(row *helper.RawData) ([]interface{}, error) {
+			rawL := &BitbucketApiPullRequest{}
+			err := json.Unmarshal(row.Data, rawL)
+			if err != nil {
+				return nil, err
+			}
+			// need to extract 2 kinds of entities here
+			results := make([]interface{}, 0, 1)
+			if rawL.BitbucketId == 0 {
+				return nil, nil
+			}
+
+			bitbucketPr, err := convertBitbucketPullRequest(rawL, data.Options.ConnectionId, data.Repo.BitbucketId)
+			if err != nil {
+				return nil, err
+			}
+			if rawL.Author != nil {
+				bitbucketUser, err := convertAccount(rawL.Author, data.Options.ConnectionId)
+				if err != nil {
+					return nil, err
+				}
+				results = append(results, bitbucketUser)
+				bitbucketPr.AuthorName = bitbucketUser.DisplayName
+				bitbucketPr.AuthorId = bitbucketUser.AccountId
+			}
+			if rawL.MergeCommit != nil {
+				bitbucketPr.MergeCommitSha = rawL.MergeCommit.Hash
+			}
+			results = append(results, bitbucketPr)
+
+			return results, nil
+		},
+	})
+
+	if err != nil {
+		return err
+	}
+
+	return extractor.Execute()
+}
+func convertBitbucketPullRequest(pull *BitbucketApiPullRequest, connId uint64, repoId string) (*models.BitbucketPullRequest, error) {
+	bitbucketPull := &models.BitbucketPullRequest{
+		ConnectionId:       connId,
+		BitbucketId:        pull.BitbucketId,
+		RepoId:             repoId,
+		BaseRepoId:         pull.BaseRef.Repo.FullName,
+		HeadRepoId:         pull.HeadRef.Repo.FullName,
+		State:              pull.State,
+		Title:              pull.Title,
+		Description:        pull.Description,
+		Url:                pull.Links.Html.Href,
+		Type:               pull.Type,
+		CommentCount:       pull.CommentCount,
+		BitbucketCreatedAt: pull.BitbucketCreatedAt,
+		BitbucketUpdatedAt: pull.BitbucketUpdatedAt,
+		BaseRef:            pull.BaseRef.Branch.Name,
+		BaseCommitSha:      pull.BaseRef.Commit.Hash,
+		HeadRef:            pull.HeadRef.Branch.Name,
+		HeadCommitSha:      pull.HeadRef.Commit.Hash,
+	}
+	return bitbucketPull, nil
+}
diff --git a/plugins/bitbucket/tasks/repo_collector.go b/plugins/bitbucket/tasks/repo_collector.go
new file mode 100644
index 00000000..efa7b8e7
--- /dev/null
+++ b/plugins/bitbucket/tasks/repo_collector.go
@@ -0,0 +1,63 @@
+/*
+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 tasks
+
+import (
+	"encoding/json"
+	"github.com/apache/incubator-devlake/plugins/helper"
+	"io/ioutil"
+	"net/http"
+
+	"github.com/apache/incubator-devlake/plugins/core"
+)
+
+const RAW_REPOSITORIES_TABLE = "bitbucket_api_repositories"
+
+var CollectApiRepoMeta = core.SubTaskMeta{
+	Name:        "collectApiRepo",
+	EntryPoint:  CollectApiRepositories,
+	Required:    true,
+	Description: "Collect repositories data from Bitbucket api",
+	DomainTypes: core.DOMAIN_TYPES,
+}
+
+func CollectApiRepositories(taskCtx core.SubTaskContext) error {
+	rawDataSubTaskArgs, data := CreateRawDataSubTaskArgs(taskCtx, RAW_REPOSITORIES_TABLE)
+
+	collector, err := helper.NewApiCollector(helper.ApiCollectorArgs{
+		RawDataSubTaskArgs: *rawDataSubTaskArgs,
+		ApiClient:          data.ApiClient,
+
+		UrlTemplate: "repositories/{{ .Params.Owner }}/{{ .Params.Repo }}",
+		Query:       GetQuery,
+		ResponseParser: func(res *http.Response) ([]json.RawMessage, error) {
+			body, err := ioutil.ReadAll(res.Body)
+			res.Body.Close()
+			if err != nil {
+				return nil, err
+			}
+			return []json.RawMessage{body}, nil
+		},
+	})
+
+	if err != nil {
+		return err
+	}
+
+	return collector.Execute()
+}
diff --git a/plugins/bitbucket/tasks/repo_convertor.go b/plugins/bitbucket/tasks/repo_convertor.go
new file mode 100644
index 00000000..1890e8d2
--- /dev/null
+++ b/plugins/bitbucket/tasks/repo_convertor.go
@@ -0,0 +1,106 @@
+/*
+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 tasks
+
+import (
+	"fmt"
+	"reflect"
+
+	"github.com/apache/incubator-devlake/plugins/core/dal"
+
+	"github.com/apache/incubator-devlake/models/domainlayer"
+	"github.com/apache/incubator-devlake/models/domainlayer/code"
+	"github.com/apache/incubator-devlake/models/domainlayer/didgen"
+	"github.com/apache/incubator-devlake/models/domainlayer/ticket"
+	"github.com/apache/incubator-devlake/plugins/bitbucket/models"
+	"github.com/apache/incubator-devlake/plugins/core"
+	"github.com/apache/incubator-devlake/plugins/helper"
+)
+
+var ConvertRepoMeta = core.SubTaskMeta{
+	Name:             "convertRepo",
+	EntryPoint:       ConvertRepo,
+	EnabledByDefault: true,
+	Description:      "Convert tool layer table bitbucket_repos into  domain layer table repos and boards",
+	DomainTypes:      core.DOMAIN_TYPES,
+}
+
+func ConvertRepo(taskCtx core.SubTaskContext) error {
+	db := taskCtx.GetDal()
+	data := taskCtx.GetData().(*BitbucketTaskData)
+	repoId := data.Repo.BitbucketId
+
+	cursor, err := db.Cursor(
+		dal.From(&models.BitbucketRepo{}),
+		dal.Where("bitbucket_id = ?", repoId),
+	)
+	if err != nil {
+		return err
+	}
+	defer cursor.Close()
+
+	repoIdGen := didgen.NewDomainIdGenerator(&models.BitbucketRepo{})
+
+	converter, err := helper.NewDataConverter(helper.DataConverterArgs{
+		InputRowType: reflect.TypeOf(models.BitbucketRepo{}),
+		Input:        cursor,
+		RawDataSubTaskArgs: helper.RawDataSubTaskArgs{
+			Ctx: taskCtx,
+			Params: BitbucketApiParams{
+				ConnectionId: data.Options.ConnectionId,
+				Owner:        data.Options.Owner,
+				Repo:         data.Options.Repo,
+			},
+			Table: RAW_REPOSITORIES_TABLE,
+		},
+		Convert: func(inputRow interface{}) ([]interface{}, error) {
+			repository := inputRow.(*models.BitbucketRepo)
+			domainRepository := &code.Repo{
+				DomainEntity: domainlayer.DomainEntity{
+					Id: repoIdGen.Generate(data.Options.ConnectionId, repository.BitbucketId),
+				},
+				Name:        repository.Name,
+				Url:         repository.HTMLUrl,
+				Description: repository.Description,
+				Language:    repository.Language,
+				CreatedDate: repository.CreatedDate,
+				UpdatedDate: repository.UpdatedDate,
+			}
+
+			domainBoard := &ticket.Board{
+				DomainEntity: domainlayer.DomainEntity{
+					Id: repoIdGen.Generate(data.Options.ConnectionId, repository.BitbucketId),
+				},
+				Name:        repository.Name,
+				Url:         fmt.Sprintf("%s/%s", repository.HTMLUrl, "issues"),
+				Description: repository.Description,
+				CreatedDate: &repository.CreatedDate,
+			}
+
+			return []interface{}{
+				domainRepository,
+				domainBoard,
+			}, nil
+		},
+	})
+	if err != nil {
+		return err
+	}
+
+	return converter.Execute()
+}
diff --git a/plugins/bitbucket/tasks/repo_extractor.go b/plugins/bitbucket/tasks/repo_extractor.go
new file mode 100644
index 00000000..40f94112
--- /dev/null
+++ b/plugins/bitbucket/tasks/repo_extractor.go
@@ -0,0 +1,126 @@
+/*
+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 tasks
+
+import (
+	"encoding/json"
+	"fmt"
+	"time"
+
+	"github.com/apache/incubator-devlake/plugins/bitbucket/models"
+	"github.com/apache/incubator-devlake/plugins/core"
+	"github.com/apache/incubator-devlake/plugins/helper"
+)
+
+var ExtractApiRepoMeta = core.SubTaskMeta{
+	Name:        "extractApiRepo",
+	EntryPoint:  ExtractApiRepositories,
+	Required:    true,
+	Description: "Extract raw Repositories data into tool layer table bitbucket_repos",
+	DomainTypes: core.DOMAIN_TYPES,
+}
+
+type ApiRepoResponse BitbucketApiRepo
+
+type BitbucketApiRepo struct {
+	BitbucketId string
+	Scm         string `json:"scm"`
+	HasWiki     bool   `json:"has_wiki"`
+	Links       struct {
+		Clone []struct {
+			Href string
+			Name string
+		} `json:"clone"`
+		Self struct {
+			Href string
+		} `json:"self"`
+
+		Html struct {
+			Href string
+		} `json:"html"`
+	} `json:"links"`
+	Uuid        string `json:"uuid"`
+	FullName    string `json:"full_name"`
+	Language    string `json:"language"`
+	Description string `json:"description"`
+	Type        string `json:"type"`
+	HasIssue    bool   `json:"has_issue"`
+	ForkPolicy  string `json:"fork_policy"`
+	Owner       models.BitbucketUser
+	CreatedAt   time.Time  `json:"created_on"`
+	UpdatedAt   *time.Time `json:"updated_on"`
+}
+
+func ExtractApiRepositories(taskCtx core.SubTaskContext) error {
+	data := taskCtx.GetData().(*BitbucketTaskData)
+	extractor, err := helper.NewApiExtractor(helper.ApiExtractorArgs{
+		RawDataSubTaskArgs: helper.RawDataSubTaskArgs{
+			Ctx: taskCtx,
+			/*
+				This struct will be JSONEncoded and stored into database along with raw data itself, to identity minimal
+				set of data to be process, for example, we process JiraIssues by Board
+			*/
+			Params: BitbucketApiParams{
+				ConnectionId: data.Options.ConnectionId,
+				Owner:        data.Options.Owner,
+				Repo:         data.Options.Repo,
+			},
+			/*
+				Table store raw data
+			*/
+			Table: RAW_REPOSITORIES_TABLE,
+		},
+		Extract: func(row *helper.RawData) ([]interface{}, error) {
+			body := &ApiRepoResponse{}
+			err := json.Unmarshal(row.Data, body)
+			if err != nil {
+				return nil, err
+			}
+			if body.FullName == "" {
+				return nil, fmt.Errorf("repo %s/%s not found", data.Options.Owner, data.Options.Repo)
+			}
+			results := make([]interface{}, 0, 1)
+			bitbucketRepository := &models.BitbucketRepo{
+				ConnectionId: data.Options.ConnectionId,
+				BitbucketId:  "repositories/" + body.FullName,
+				Name:         body.FullName,
+				HTMLUrl:      body.Links.Html.Href,
+				Description:  body.Description,
+				OwnerId:      body.Owner.AccountId,
+				Language:     body.Language,
+				CreatedDate:  body.CreatedAt,
+				UpdatedDate:  body.UpdatedAt,
+			}
+			data.Repo = bitbucketRepository
+
+			results = append(results, bitbucketRepository)
+
+			parentTaskContext := taskCtx.TaskContext()
+			if parentTaskContext != nil {
+				parentTaskContext.GetData().(*BitbucketTaskData).Repo = bitbucketRepository
+			}
+			return results, nil
+		},
+	})
+
+	if err != nil {
+		return err
+	}
+
+	return extractor.Execute()
+}
diff --git a/plugins/bitbucket/tasks/task_data.go b/plugins/bitbucket/tasks/task_data.go
new file mode 100644
index 00000000..e28968b6
--- /dev/null
+++ b/plugins/bitbucket/tasks/task_data.go
@@ -0,0 +1,90 @@
+/*
+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 tasks
+
+import (
+	"fmt"
+	"time"
+
+	"github.com/apache/incubator-devlake/plugins/bitbucket/models"
+	"github.com/apache/incubator-devlake/plugins/helper"
+	"github.com/mitchellh/mapstructure"
+)
+
+type BitbucketOptions struct {
+	ConnectionId               uint64   `json:"connectionId"`
+	Tasks                      []string `json:"tasks,omitempty"`
+	Since                      string
+	Owner                      string
+	Repo                       string
+	models.TransformationRules `mapstructure:"transformationRules" json:"transformationRules"`
+}
+
+type BitbucketTaskData struct {
+	Options   *BitbucketOptions
+	ApiClient *helper.ApiAsyncClient
+	Since     *time.Time
+	Repo      *models.BitbucketRepo
+}
+
+func DecodeAndValidateTaskOptions(options map[string]interface{}) (*BitbucketOptions, error) {
+	var op BitbucketOptions
+	err := mapstructure.Decode(options, &op)
+	if err != nil {
+		return nil, err
+	}
+	if op.Owner == "" {
+		return nil, fmt.Errorf("owner is required for Bitbucket execution")
+	}
+	if op.Repo == "" {
+		return nil, fmt.Errorf("repo is required for Bitbucket execution")
+	}
+	if op.PrType == "" {
+		op.PrType = "type/(.*)$"
+	}
+	if op.PrComponent == "" {
+		op.PrComponent = "component/(.*)$"
+	}
+	if op.PrBodyClosePattern == "" {
+		op.PrBodyClosePattern = "(?mi)(fix|close|resolve|fixes|closes|resolves|fixed|closed|resolved)[\\s]*.*(((and )?(#|https:\\/\\/api.bitbucket.org\\/2.0\\/%s\\/%s\\/issues\\/)\\d+[ ]*)+)"
+	}
+	if op.IssueSeverity == "" {
+		op.IssueSeverity = "severity/(.*)$"
+	}
+	if op.IssuePriority == "" {
+		op.IssuePriority = "^(highest|high|medium|low)$"
+	}
+	if op.IssueComponent == "" {
+		op.IssueComponent = "component/(.*)$"
+	}
+	if op.IssueTypeBug == "" {
+		op.IssueTypeBug = "^(bug|failure|error)$"
+	}
+	if op.IssueTypeIncident == "" {
+		op.IssueTypeIncident = ""
+	}
+	if op.IssueTypeRequirement == "" {
+		op.IssueTypeRequirement = "^(feat|feature|proposal|requirement)$"
+	}
+
+	// find the needed Bitbucket now
+	if op.ConnectionId == 0 {
+		return nil, fmt.Errorf("connectionId is invalid")
+	}
+	return &op, nil
+}
diff --git a/plugins/bitbucket/utils/utils.go b/plugins/bitbucket/utils/utils.go
new file mode 100644
index 00000000..14675b1c
--- /dev/null
+++ b/plugins/bitbucket/utils/utils.go
@@ -0,0 +1,152 @@
+/*
+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 utils
+
+import (
+	"errors"
+	"github.com/apache/incubator-devlake/plugins/helper"
+	"net/http"
+	"regexp"
+	"strconv"
+	"strings"
+	"time"
+)
+
+type PagingInfo struct {
+	Next  int
+	Last  int
+	First int
+	Prev  int
+}
+
+type RateLimitInfo struct {
+	Date      time.Time
+	ResetTime time.Time
+	Remaining int
+}
+
+func GetTotalPagesFromResponse(res *http.Response, args *helper.ApiCollectorArgs) (int, error) {
+	link := res.Header.Get("link")
+	pageInfo, err := GetPagingFromLinkHeader(link)
+	if err != nil {
+		return 0, nil
+	}
+	return pageInfo.Last, nil
+}
+
+func ConvertRateLimitInfo(date string, resetTime string, remaining string) (RateLimitInfo, error) {
+	var rateLimitInfo RateLimitInfo
+	var err error
+	if date != "" {
+		rateLimitInfo.Date, err = http.ParseTime(date)
+		if err != nil {
+			return rateLimitInfo, err
+		}
+	} else {
+		return rateLimitInfo, errors.New("rate limit date was an empty string")
+	}
+	if resetTime != "" {
+		resetInt, err := strconv.ParseInt(resetTime, 10, 64)
+		if err != nil {
+			return rateLimitInfo, err
+		}
+		rateLimitInfo.ResetTime = time.Unix(resetInt, 0)
+	} else {
+		return rateLimitInfo, errors.New("rate limit reset time was an empty string")
+	}
+	if remaining != "" {
+		rateLimitInfo.Remaining, err = strconv.Atoi(remaining)
+		if err != nil {
+			return rateLimitInfo, err
+		}
+	} else {
+		return rateLimitInfo, errors.New("rate remaining was an empty string")
+	}
+	return rateLimitInfo, nil
+}
+
+func GetRateLimitPerSecond(info RateLimitInfo) int {
+	unixResetTime := info.ResetTime.Unix()
+	unixNow := info.Date.Unix()
+	timeBetweenNowAndReset := unixResetTime - unixNow
+	// Adjust the remaining to be less then actual to avoid hitting the limit exactly.
+	multiplier := 0.98
+	adjustedRemaining := float64(info.Remaining) * multiplier
+	return int(adjustedRemaining / float64(timeBetweenNowAndReset)) //* multiplier
+}
+func ConvertStringToInt(input string) (int, error) {
+	return strconv.Atoi(input)
+}
+func GetPagingFromLinkHeader(link string) (PagingInfo, error) {
+	result := PagingInfo{
+		Next:  1,
+		Last:  1,
+		Prev:  1,
+		First: 1,
+	}
+	linksArray := strings.Split(link, ",")
+	pattern1 := regexp.MustCompile(`page=*[0-9]+`)
+	pattern2 := regexp.MustCompile(`rel="*[a-z]+`)
+	if len(linksArray) >= 2 {
+		for i := 0; i < len(linksArray); i++ {
+			content := []byte(linksArray[i])
+			loc1 := pattern1.FindIndex(content)
+			loc2 := pattern2.FindIndex(content)
+			if len(loc1) >= 2 && len(loc2) >= 2 {
+				pageNumberSubstring := string(content[loc1[0]:loc1[1]])
+				pageNumberString := strings.Replace(pageNumberSubstring, `page=`, ``, 1)
+				pageNameSubstring := string(content[loc2[0]:loc2[1]])
+				pageNameString := strings.Replace(pageNameSubstring, `rel="`, ``, 1)
+
+				pageNumberInt, convertErr := ConvertStringToInt(pageNumberString)
+				if convertErr != nil {
+					return result, convertErr
+				}
+				switch pageNameString {
+				case "next":
+					result.Next = pageNumberInt
+
+				case "first":
+					result.First = pageNumberInt
+
+				case "last":
+					result.Last = pageNumberInt
+
+				case "prev":
+					result.Prev = pageNumberInt
+				}
+
+			} else {
+				return result, errors.New("parsed string values aren't long enough")
+			}
+		}
+		return result, nil
+	} else {
+		return result, errors.New("the link string provided is invalid. There is likely no next page of data to fetch")
+	}
+}
+
+func GetIssueIdByIssueUrl(s string) (int, error) {
+	regex := regexp.MustCompile(`.*/issues/(\d+)`)
+	groups := regex.FindStringSubmatch(s)
+	if len(groups) > 0 {
+		return strconv.Atoi(groups[1])
+	} else {
+		return 0, errors.New("invalid issue url")
+	}
+}