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

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


The following commit(s) were added to refs/heads/release-v0.16 by this push:
     new 6410c49ad cherry-pick(plugins): cp #4857 #4858 to release-v0.16 (#4904)
6410c49ad is described below

commit 6410c49add004e44c25d49b8268c9f8aec3a781f
Author: Warren Chen <[email protected]>
AuthorDate: Wed Apr 12 11:25:16 2023 +0800

    cherry-pick(plugins): cp #4857 #4858 to release-v0.16 (#4904)
    
    * fix(dora): ignore to calculate cycletime if pr has not been deployed 
(#4858)
    
    * fix(dora): ignore to calculate cycletime if pr has not been deployed
    
    * fix(dora): retaining the cumulative logic of the previous cycle time
    
    * fix(dora): fix for review
    
    * feat(jenkins): extract all commit info inside a build (#4857)
---
 .../e2e/snapshot_tables/project_pr_metrics.csv     |   4 +-
 .../dora/tasks/change_lead_time_calculator.go      | 161 +++++++++++++++------
 backend/plugins/jenkins/e2e/jobs_test.go           |   2 +-
 .../e2e/raw_tables/_raw_jenkins_api_builds.csv     |  36 +----
 .../_tool_jenkins_jobs.csv                         |   0
 .../_tool_jenkins_build_commits.csv                |   5 -
 .../e2e/snapshot_tables/_tool_jenkins_builds.csv   |  20 ---
 .../_tool_jenkins_builds_after_enrich.csv          |  38 ++---
 .../e2e/snapshot_tables/cicd_pipeline_commits.csv  |   5 -
 .../jenkins/e2e/snapshot_tables/cicd_pipelines.csv |  20 ---
 .../jenkins/e2e/snapshot_tables/cicd_tasks.csv     |  18 ---
 backend/plugins/jenkins/models/response.go         |  10 +-
 backend/plugins/jenkins/tasks/build_extractor.go   |  62 ++++----
 13 files changed, 167 insertions(+), 214 deletions(-)

diff --git a/backend/plugins/dora/e2e/snapshot_tables/project_pr_metrics.csv 
b/backend/plugins/dora/e2e/snapshot_tables/project_pr_metrics.csv
index eb02a5df1..2782878c7 100644
--- a/backend/plugins/dora/e2e/snapshot_tables/project_pr_metrics.csv
+++ b/backend/plugins/dora/e2e/snapshot_tables/project_pr_metrics.csv
@@ -3,5 +3,5 @@ 
github:GithubPullRequest:1:1043463302,project1,75ab753225b5b8acf3bc6e40e463b54b6
 
github:GithubPullRequest:1:1048233599,project1,4f8cdefc9a9d53af16dd482c61623312eb9e9b5e,,github:GithubPrComment:1:1239007576,194,4033,task12,76605,80833
 
github:GithubPullRequest:1:1049191985,project1,4b71faf666833c0c7b915a512811e2c5e746d3de,1,github:GithubPrComment:1:965369774,156,1712,task13,115026,116896
 github:GithubPullRequest:1:1051112182,project1,,,,,,task14,98341,98398
-github:GithubPullRequest:1:1051574863,project1,,,,,,,,108
-github:GithubPullRequest:1:1051637383,project1,9d53fb594958e65456793caa1bfa8d07a7614291,1,github:GithubPrReview:1:1102479199,45,13,,,60
+github:GithubPullRequest:1:1051574863,project1,,,,,,,,
+github:GithubPullRequest:1:1051637383,project1,9d53fb594958e65456793caa1bfa8d07a7614291,1,github:GithubPrReview:1:1102479199,45,13,,,
diff --git a/backend/plugins/dora/tasks/change_lead_time_calculator.go 
b/backend/plugins/dora/tasks/change_lead_time_calculator.go
index 09eaff9a0..c5743e670 100644
--- a/backend/plugins/dora/tasks/change_lead_time_calculator.go
+++ b/backend/plugins/dora/tasks/change_lead_time_calculator.go
@@ -29,40 +29,20 @@ import (
        "time"
 )
 
+// CalculateChangeLeadTime calculates change lead time for a project.
 func CalculateChangeLeadTime(taskCtx plugin.SubTaskContext) errors.Error {
+       // Get instances of the DAL and logger
        db := taskCtx.GetDal()
        logger := taskCtx.GetLogger()
        data := taskCtx.GetData().(*DoraTaskData)
-       // construct a list of tuple[task, oldPipelineCommitSha, 
newPipelineCommitSha, taskFinishedDate]
-       deploymentClause := []dal.Clause{
-               dal.Select(`ct.id as task_id, cpc.commit_sha as 
new_deploy_commit_sha,
-                       ct.finished_date as task_finished_date, cpc.repo_id as 
repo_id`),
-               dal.From(`cicd_tasks ct`),
-               dal.Join(`left join cicd_pipeline_commits cpc on ct.pipeline_id 
= cpc.pipeline_id`),
-               dal.Join(`left join project_mapping pm on pm.row_id = 
ct.cicd_scope_id`),
-               dal.Where(`ct.environment = ? and ct.type = ? and ct.result = ? 
and pm.project_name = ? and pm.table = ?`,
-                       devops.PRODUCTION, devops.DEPLOYMENT, devops.SUCCESS, 
data.Options.ProjectName, "cicd_scopes"),
-               dal.Orderby(`cpc.repo_id, ct.started_date `),
-       }
-       deploymentDiffPairs := make([]deploymentPair, 0)
-       err := db.All(&deploymentDiffPairs, deploymentClause...)
+
+       // Build deployment pairs
+       deploymentDiffPairs, err := buildDeploymentPairs(db, data)
        if err != nil {
                return err
        }
-       // deploymentDiffPairs[i-1].NewDeployCommitSha is 
deploymentDiffPairs[i].OldDeployCommitSha
-       oldDeployCommitSha := ""
-       lastRepoId := ""
-       for i := 0; i < len(deploymentDiffPairs); i++ {
-               // if two deployments belong to different repo, let's skip
-               if lastRepoId == deploymentDiffPairs[i].RepoId {
-                       deploymentDiffPairs[i].OldDeployCommitSha = 
oldDeployCommitSha
-               } else {
-                       lastRepoId = deploymentDiffPairs[i].RepoId
-               }
-               oldDeployCommitSha = deploymentDiffPairs[i].NewDeployCommitSha
-       }
 
-       // get prs by repo project_name
+       // Get pull requests by repo project_name
        clauses := []dal.Clause{
                dal.From(&code.PullRequest{}),
                dal.Join(`left join project_mapping pm on pm.row_id = 
pull_requests.base_repo_id`),
@@ -74,6 +54,7 @@ func CalculateChangeLeadTime(taskCtx plugin.SubTaskContext) 
errors.Error {
        }
        defer cursor.Close()
 
+       // Initialize a new data converter
        converter, err := api.NewDataConverter(api.DataConverterArgs{
                RawDataSubTaskArgs: api.RawDataSubTaskArgs{
                        Ctx: taskCtx,
@@ -86,17 +67,21 @@ func CalculateChangeLeadTime(taskCtx plugin.SubTaskContext) 
errors.Error {
                InputRowType: reflect.TypeOf(code.PullRequest{}),
                Input:        cursor,
                Convert: func(inputRow interface{}) ([]interface{}, 
errors.Error) {
+                       // Process each pull request
                        pr := inputRow.(*code.PullRequest)
+
+                       // Get the first commit for the PR
                        firstCommit, err := getFirstCommit(pr.Id, db)
                        if err != nil {
                                return nil, err
                        }
+
+                       // Initialize a new ProjectPrMetric
                        projectPrMetric := &crossdomain.ProjectPrMetric{}
                        projectPrMetric.Id = pr.Id
                        projectPrMetric.ProjectName = data.Options.ProjectName
-                       if err != nil {
-                               return nil, err
-                       }
+
+                       // Calculate PR coding time
                        if firstCommit != nil {
                                codingTime := 
int64(pr.CreatedDate.Sub(firstCommit.AuthoredDate).Seconds())
                                if codingTime/60 == 0 && codingTime%60 > 0 {
@@ -107,21 +92,28 @@ func CalculateChangeLeadTime(taskCtx 
plugin.SubTaskContext) errors.Error {
                                projectPrMetric.PrCodingTime = 
processNegativeValue(codingTime)
                                projectPrMetric.FirstCommitSha = firstCommit.Sha
                        }
+
+                       // Get the first review for the PR
                        firstReview, err := getFirstReview(pr.Id, pr.AuthorId, 
db)
                        if err != nil {
                                return nil, err
                        }
-                       // clauses filter by merged_date IS NOT NULL, so 
MergedDate must be not nil.
+
+                       // Calculate PR pickup time and PR review time
                        prDuring := 
processNegativeValue(int64(pr.MergedDate.Sub(pr.CreatedDate).Minutes()))
                        if firstReview != nil {
                                projectPrMetric.PrPickupTime = 
processNegativeValue(int64(firstReview.CreatedDate.Sub(pr.CreatedDate).Minutes()))
                                projectPrMetric.PrReviewTime = 
processNegativeValue(int64(pr.MergedDate.Sub(firstReview.CreatedDate).Minutes()))
                                projectPrMetric.FirstReviewId = firstReview.Id
                        }
+
+                       // Get the deployment for the PR
                        deployment, err := getDeployment(pr.MergeCommitSha, 
pr.BaseRepoId, deploymentDiffPairs, db)
                        if err != nil {
                                return nil, err
                        }
+
+                       // Calculate PR deploy time
                        if deployment != nil && deployment.TaskFinishedDate != 
nil {
                                timespan := 
deployment.TaskFinishedDate.Sub(*pr.MergedDate)
                                projectPrMetric.PrDeployTime = 
processNegativeValue(int64(timespan.Minutes()))
@@ -129,7 +121,12 @@ func CalculateChangeLeadTime(taskCtx 
plugin.SubTaskContext) errors.Error {
                        } else {
                                logger.Debug("deploy time of pr %v is nil\n", 
pr.PullRequestKey)
                        }
-                       projectPrMetric.PrCycleTime = nil
+
+                       // Calculate PR cycle time
+                       if deployment == nil || projectPrMetric.PrDeployTime == 
nil {
+                               // Return the projectPrMetric with nill cycle 
time
+                               return []interface{}{projectPrMetric}, nil
+                       }
                        var result int64
                        if projectPrMetric.PrCodingTime != nil {
                                result += *projectPrMetric.PrCodingTime
@@ -137,80 +134,148 @@ func CalculateChangeLeadTime(taskCtx 
plugin.SubTaskContext) errors.Error {
                        if prDuring != nil {
                                result += *prDuring
                        }
-                       if projectPrMetric.PrDeployTime != nil {
-                               result += *projectPrMetric.PrDeployTime
-                       }
+                       result += *projectPrMetric.PrDeployTime
                        if result > 0 {
                                projectPrMetric.PrCycleTime = &result
                        }
+
+                       // Return the projectPrMetric
                        return []interface{}{projectPrMetric}, nil
                },
        })
        if err != nil {
                return err
        }
-
+       // Execute the data converter
        return converter.Execute()
 }
 
+// buildDeploymentPairs populates the OldDeployCommitSha field of each 
deploymentPair in the given slice.
+func buildDeploymentPairs(db dal.Dal, data *DoraTaskData) ([]deploymentPair, 
errors.Error) {
+       // Construct a list of tuple[task, oldPipelineCommitSha, 
newPipelineCommitSha, taskFinishedDate]
+       deploymentClause := []dal.Clause{
+               dal.Select(`ct.id as task_id, cpc.commit_sha as 
new_deploy_commit_sha,
+                       ct.finished_date as task_finished_date, cpc.repo_id as 
repo_id`),
+               dal.From(`cicd_tasks ct`),
+               dal.Join(`left join cicd_pipeline_commits cpc on ct.pipeline_id 
= cpc.pipeline_id`),
+               dal.Join(`left join project_mapping pm on pm.row_id = 
ct.cicd_scope_id`),
+               dal.Where(`ct.environment = ? and ct.type = ? and ct.result = ? 
and pm.project_name = ? and pm.table = ?`,
+                       devops.PRODUCTION, devops.DEPLOYMENT, devops.SUCCESS, 
data.Options.ProjectName, "cicd_scopes"),
+               dal.Orderby(`cpc.repo_id, ct.started_date`),
+       }
+
+       // Initialize deploymentDiffPairs without oldPipelineCommitSha
+       deploymentDiffPairs := make([]deploymentPair, 0)
+       err := db.All(&deploymentDiffPairs, deploymentClause...)
+       if err != nil {
+               return nil, err
+       }
+
+       oldDeployCommitSha := ""
+       lastRepoId := ""
+       for i := 0; i < len(deploymentDiffPairs); i++ {
+               // If two deployments belong to different repos, skip
+               if lastRepoId == deploymentDiffPairs[i].RepoId {
+                       deploymentDiffPairs[i].OldDeployCommitSha = 
oldDeployCommitSha
+               } else {
+                       lastRepoId = deploymentDiffPairs[i].RepoId
+               }
+               oldDeployCommitSha = deploymentDiffPairs[i].NewDeployCommitSha
+       }
+       return deploymentDiffPairs, nil
+}
+
+// getFirstCommit takes a PR ID and a database connection as input, and 
returns the first commit of the PR.
 func getFirstCommit(prId string, db dal.Dal) (*code.Commit, errors.Error) {
+       // Initialize a commit object
        commit := &code.Commit{}
+       // Define the SQL clauses for the database query
        commitClauses := []dal.Clause{
-               dal.From(&code.Commit{}),
-               dal.Join("left join pull_request_commits on commits.sha = 
pull_request_commits.commit_sha"),
-               dal.Where("pull_request_commits.pull_request_id = ?", prId),
-               dal.Orderby("commits.authored_date ASC"),
+               dal.From(&code.Commit{}), // Select from the "commits" table
+               dal.Join("left join pull_request_commits on commits.sha = 
pull_request_commits.commit_sha"), // Join with the "pull_request_commits" table
+               dal.Where("pull_request_commits.pull_request_id = ?", prId),    
                             // Filter by the PR ID
+               dal.Orderby("commits.authored_date ASC"),                       
                             // Order by the authored date of the commits 
(ascending)
        }
+
+       // Execute the query and retrieve the first commit
        err := db.First(commit, commitClauses...)
+
+       // If the error indicates that no commit was found, return nil and no 
error
        if db.IsErrorNotFound(err) {
                return nil, nil
        }
+
+       // If any other error occurred, return nil and the error
        if err != nil {
                return nil, err
        }
+
+       // If there were no errors, return the first commit and no error
        return commit, nil
 }
 
+// getFirstReview takes a PR ID, PR creator ID, and a database connection as 
input, and returns the first review comment of the PR.
 func getFirstReview(prId string, prCreator string, db dal.Dal) 
(*code.PullRequestComment, errors.Error) {
+       // Initialize a review comment object
        review := &code.PullRequestComment{}
+       // Define the SQL clauses for the database query
        commentClauses := []dal.Clause{
-               dal.From(&code.PullRequestComment{}),
-               dal.Where("pull_request_id = ? and account_id != ?", prId, 
prCreator),
-               dal.Orderby("created_date ASC"),
+               dal.From(&code.PullRequestComment{}),                           
       // Select from the "pull_request_comments" table
+               dal.Where("pull_request_id = ? and account_id != ?", prId, 
prCreator), // Filter by the PR ID and exclude comments from the PR creator
+               dal.Orderby("created_date ASC"),                                
       // Order by the created date of the review comments (ascending)
        }
+
+       // Execute the query and retrieve the first review comment
        err := db.First(review, commentClauses...)
+
+       // If the error indicates that no review comment was found, return nil 
and no error
        if db.IsErrorNotFound(err) {
                return nil, nil
        }
+
+       // If any other error occurred, return nil and the error
        if err != nil {
                return nil, err
        }
+
+       // If there were no errors, return the first review comment and no error
        return review, nil
 }
 
+// getDeployment takes a merge commit SHA, a repository ID, a list of 
deployment pairs, and a database connection as input.
+// It returns the deployment pair related to the merge commit, or nil if not 
found.
 func getDeployment(mergeSha string, repoId string, deploymentPairList 
[]deploymentPair, db dal.Dal) (*deploymentPair, errors.Error) {
-       // ignore environment at this point because detecting it by name is 
obviously not engouh
-       // take 
https://github.com/apache/incubator-devlake/actions/workflows/build.yml for 
example
-       // one can not distingush testing/production by looking at the job name 
solely.
+       // Ignore environment detection based on job name since it's not enough 
to distinguish between testing/production environments.
        commitDiff := &code.CommitsDiff{}
-       // find if tuple[merge_sha, new_commit_sha, old_commit_sha] exist in 
commits_diffs, if yes, return pair.FinishedDate
+       // Iterate through the deploymentPairList to find if a tuple 
[merge_sha, new_commit_sha, old_commit_sha] exists in commits_diffs.
+       // If found, return the corresponding deployment pair.
        for _, pair := range deploymentPairList {
+               // Continue to the next iteration if the repoId does not match 
the current deployment pair's RepoId.
                if repoId != pair.RepoId {
                        continue
                }
+
+               // Query the database to find the commit diff with the given 
merge SHA, new commit SHA, and old commit SHA.
                err := db.First(commitDiff, dal.Where(`commit_sha = ? and 
new_commit_sha = ? and old_commit_sha = ?`,
                        mergeSha, pair.NewDeployCommitSha, 
pair.OldDeployCommitSha))
+
+               // If no error occurred, return the current deployment pair.
                if err == nil {
                        return &pair, nil
                }
+
+               // If the error indicates that no commit diff was found, 
continue to the next iteration.
                if db.IsErrorNotFound(err) {
                        continue
                }
+
+               // If any other error occurred, return nil and the error.
                if err != nil {
                        return nil, err
                }
-
        }
+
+       // If no matching deployment pair was found, return nil and no error.
        return nil, nil
 }
 
@@ -222,6 +287,7 @@ func processNegativeValue(v int64) *int64 {
        }
 }
 
+// CalculateChangeLeadTimeMeta contains metadata for the 
CalculateChangeLeadTime subtask.
 var CalculateChangeLeadTimeMeta = plugin.SubTaskMeta{
        Name:             "calculateChangeLeadTime",
        EntryPoint:       CalculateChangeLeadTime,
@@ -230,6 +296,7 @@ var CalculateChangeLeadTimeMeta = plugin.SubTaskMeta{
        DomainTypes:      []string{plugin.DOMAIN_TYPE_CICD, 
plugin.DOMAIN_TYPE_CODE},
 }
 
+// deploymentPair is a struct representing a deployment pair with fields for 
task ID, repo ID, new and old commit SHAs, and task finished date.
 type deploymentPair struct {
        TaskId             string
        RepoId             string
diff --git a/backend/plugins/jenkins/e2e/jobs_test.go 
b/backend/plugins/jenkins/e2e/jobs_test.go
index 3a5abda9f..d2cb60d6c 100644
--- a/backend/plugins/jenkins/e2e/jobs_test.go
+++ b/backend/plugins/jenkins/e2e/jobs_test.go
@@ -44,7 +44,7 @@ func TestJenkinsJobsDataFlow(t *testing.T) {
        }
 
        dataflowTester.FlushTabler(&devops.CicdScope{})
-       
dataflowTester.ImportCsvIntoTabler("./snapshot_tables/_tool_jenkins_jobs.csv", 
&models.JenkinsJob{})
+       
dataflowTester.ImportCsvIntoTabler("./raw_tables/_tool_jenkins_jobs.csv", 
&models.JenkinsJob{})
        dataflowTester.Subtask(tasks.ConvertJobsMeta, taskData)
        dataflowTester.VerifyTableWithOptions(&devops.CicdScope{}, 
e2ehelper.TableOptions{
                CSVRelPath:  "./snapshot_tables/cicd_scopes.csv",
diff --git a/backend/plugins/jenkins/e2e/raw_tables/_raw_jenkins_api_builds.csv 
b/backend/plugins/jenkins/e2e/raw_tables/_raw_jenkins_api_builds.csv
index 74276c3af..3ea3ce870 100644
--- a/backend/plugins/jenkins/e2e/raw_tables/_raw_jenkins_api_builds.csv
+++ b/backend/plugins/jenkins/e2e/raw_tables/_raw_jenkins_api_builds.csv
@@ -1,36 +1,8 @@
 "id","params","data","url","input","created_at"
-88,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.CauseAction"",""causes"":[{""_class"":""hudson.model.Cause$UserIdCause"",""shortDescription"":""Started
 by user 
思码逸"",""userId"":""merico"",""userName"":""思码逸""}]},{""_class"":""hudson.plugins.git.util.BuildData"",""lastBuiltRevision"":{""SHA1"":""0006e8105d70318aff5eeee38d405fa181a32aa0"",""branch""
 [...]
-89,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.CauseAction"",""causes"":[{""_class"":""hudson.model.Cause$UserIdCause"",""shortDescription"":""Started
 by user 
思码逸"",""userId"":""merico"",""userName"":""思码逸""}]},{""_class"":""hudson.plugins.git.util.BuildData"",""lastBuiltRevision"":{""SHA1"":""0006e8105d70318aff5eeee38d405fa181a32aa0"",""branch""
 [...]
-90,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.CauseAction"",""causes"":[{""_class"":""hudson.model.Cause$UserIdCause"",""shortDescription"":""Started
 by user 
思码逸"",""userId"":""merico"",""userName"":""思码逸""}]},{""_class"":""hudson.plugins.git.util.BuildData"",""lastBuiltRevision"":{""SHA1"":""20139afef3c6ec9f3ebffcb06e243b145cbef8c6"",""branch""
 [...]
-91,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.CauseAction"",""causes"":[{""_class"":""hudson.model.Cause$UserIdCause"",""shortDescription"":""Started
 by user 
思码逸"",""userId"":""merico"",""userName"":""思码逸""}]},{""_class"":""hudson.plugins.git.util.BuildData"",""lastBuiltRevision"":{""SHA1"":""20139afef3c6ec9f3ebffcb06e243b145cbef8c6"",""branch""
 [...]
-92,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.CauseAction"",""causes"":[{""_class"":""hudson.model.Cause$UserIdCause"",""shortDescription"":""Started
 by user 
思码逸"",""userId"":""merico"",""userName"":""思码逸""}]},{""_class"":""hudson.plugins.git.util.BuildData"",""lastBuiltRevision"":{""SHA1"":""20139afef3c6ec9f3ebffcb06e243b145cbef8c6"",""branch""
 [...]
-93,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.CauseAction"",""causes"":[{""_class"":""hudson.model.Cause$UserIdCause"",""shortDescription"":""Started
 by user 
思码逸"",""userId"":""merico"",""userName"":""思码逸""}]},{""_class"":""hudson.plugins.git.util.BuildData"",""lastBuiltRevision"":{""SHA1"":""0f886c74949c3ee7e489188911c7dc0c1d547418"",""branch""
 [...]
-94,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.CauseAction"",""causes"":[{""_class"":""hudson.model.Cause$UserIdCause"",""shortDescription"":""Started
 by user 
思码逸"",""userId"":""merico"",""userName"":""思码逸""}]},{""_class"":""hudson.plugins.git.util.BuildData"",""lastBuiltRevision"":{""SHA1"":""0f886c74949c3ee7e489188911c7dc0c1d547418"",""branch""
 [...]
-95,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.CauseAction"",""causes"":[{""_class"":""hudson.model.Cause$UserIdCause"",""shortDescription"":""Started
 by user 
思码逸"",""userId"":""merico"",""userName"":""思码逸""}]},{""_class"":""hudson.plugins.git.util.BuildData"",""lastBuiltRevision"":{""SHA1"":""ceeffdfdd06bce232f9adb3a656265bad13a8473"",""branch""
 [...]
-96,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}","{""_class"":""org.jenkinsci.plugins.workflow.job.WorkflowRun"",""actions"":[{""_class"":""hudson.model.CauseAction"",""causes"":[{""_class"":""hudson.model.Cause$UserIdCause"",""shortDescription"":""Started
 by user 
思码逸"",""userId"":""merico"",""userName"":""思码逸""}]},{""_class"":""org.jenkinsci.plugins.workflow.libs.LibrariesAction""},{},{},{""_class"":""org.jenkinsci.plugins.display
 [...]
-97,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}","{""_class"":""org.jenkinsci.plugins.workflow.job.WorkflowRun"",""actions"":[{""_class"":""hudson.model.CauseAction"",""causes"":[{""_class"":""hudson.model.Cause$UserIdCause"",""shortDescription"":""Started
 by user 
思码逸"",""userId"":""merico"",""userName"":""思码逸""}]},{""_class"":""org.jenkinsci.plugins.workflow.libs.LibrariesAction""},{},{},{""_class"":""org.jenkinsci.plugins.display
 [...]
-98,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}","{""_class"":""org.jenkinsci.plugins.workflow.job.WorkflowRun"",""actions"":[{""_class"":""hudson.model.CauseAction"",""causes"":[{""_class"":""hudson.model.Cause$UpstreamCause"",""shortDescription"":""Started
 by upstream project \""devlake\"" build number 
8"",""upstreamBuild"":8,""upstreamProject"":""devlake"",""upstreamUrl"":""job/devlake/""}]},{""_class"":""org.jenkinsci.plugins.w
 [...]
-99,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}","{""_class"":""org.jenkinsci.plugins.workflow.job.WorkflowRun"",""actions"":[{""_class"":""hudson.model.CauseAction"",""causes"":[{""_class"":""hudson.model.Cause$UpstreamCause"",""shortDescription"":""Started
 by upstream project \""devlake\"" build number 
7"",""upstreamBuild"":7,""upstreamProject"":""devlake"",""upstreamUrl"":""job/devlake/""}]},{""_class"":""org.jenkinsci.plugins.w
 [...]
-101,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.CauseAction"",""causes"":[{""_class"":""hudson.model.Cause$UserIdCause"",""shortDescription"":""Started
 by user 
思码逸"",""userId"":""merico"",""userName"":""思码逸""}]},{},{""_class"":""org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction""}],""duration"":11,""estimatedDuration"":8,""fullDisplayN
 [...]
-102,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.CauseAction"",""causes"":[{""_class"":""hudson.model.Cause$UserIdCause"",""shortDescription"":""Started
 by user 
思码逸"",""userId"":""merico"",""userName"":""思码逸""}]},{},{""_class"":""org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction""}],""duration"":4,""estimatedDuration"":8,""fullDisplayNa
 [...]
-103,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.CauseAction"",""causes"":[{""_class"":""hudson.model.Cause$UserIdCause"",""shortDescription"":""Started
 by user 
思码逸"",""userId"":""merico"",""userName"":""思码逸""}]},{},{""_class"":""org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction""}],""duration"":4,""estimatedDuration"":27,""fullDisplayN
 [...]
-104,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.CauseAction"",""causes"":[{""_class"":""hudson.model.Cause$UserIdCause"",""shortDescription"":""Started
 by user 
思码逸"",""userId"":""merico"",""userName"":""思码逸""}]},{},{""_class"":""org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction""}],""duration"":6,""estimatedDuration"":27,""fullDisplayN
 [...]
-105,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.CauseAction"",""causes"":[{""_class"":""hudson.model.Cause$UserIdCause"",""shortDescription"":""Started
 by user 
思码逸"",""userId"":""merico"",""userName"":""思码逸""}]},{},{""_class"":""org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction""}],""duration"":70,""estimatedDuration"":27,""fullDisplay
 [...]
-106,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}","{""_class"":""org.jenkinsci.plugins.workflow.job.WorkflowRun"",""actions"":[{""_class"":""hudson.model.CauseAction"",""causes"":[{""_class"":""hudson.model.Cause$UserIdCause"",""shortDescription"":""Started
 by user 
思码逸"",""userId"":""merico"",""userName"":""思码逸""}]},{""_class"":""org.jenkinsci.plugins.workflow.libs.LibrariesAction""},{},{},{""_class"":""org.jenkinsci.plugins.displa
 [...]
-107,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}","{""_class"":""org.jenkinsci.plugins.workflow.job.WorkflowRun"",""actions"":[{""_class"":""hudson.model.CauseAction"",""causes"":[{""_class"":""hudson.model.Cause$UserIdCause"",""shortDescription"":""Started
 by user 
思码逸"",""userId"":""merico"",""userName"":""思码逸""}]},{""_class"":""org.jenkinsci.plugins.workflow.libs.LibrariesAction""},{},{},{""_class"":""org.jenkinsci.plugins.displa
 [...]
-108,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}","{""_class"":""org.jenkinsci.plugins.workflow.job.WorkflowRun"",""actions"":[{""_class"":""hudson.model.CauseAction"",""causes"":[{""_class"":""hudson.model.Cause$UserIdCause"",""shortDescription"":""Started
 by user 
思码逸"",""userId"":""merico"",""userName"":""思码逸""}]},{""_class"":""org.jenkinsci.plugins.workflow.libs.LibrariesAction""},{},{},{""_class"":""org.jenkinsci.plugins.displa
 [...]
-109,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.CauseAction"",""causes"":[{""_class"":""hudson.model.Cause$UserIdCause"",""shortDescription"":""Started
 by user 
思码逸"",""userId"":""merico"",""userName"":""思码逸""}]},{},{""_class"":""org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction""}],""duration"":11,""estimatedDuration"":9,""fullDisplayN
 [...]
-110,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.CauseAction"",""causes"":[{""_class"":""hudson.model.Cause$UserIdCause"",""shortDescription"":""Started
 by user 
思码逸"",""userId"":""merico"",""userName"":""思码逸""}]},{},{""_class"":""org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction""}],""duration"":4,""estimatedDuration"":9,""fullDisplayNa
 [...]
-111,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.CauseAction"",""causes"":[{""_class"":""hudson.model.Cause$UserIdCause"",""shortDescription"":""Started
 by user 
思码逸"",""userId"":""merico"",""userName"":""思码逸""}]},{},{""_class"":""org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction""}],""duration"":11,""estimatedDuration"":9,""fullDisplayN
 [...]
-112,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.CauseAction"",""causes"":[{""_class"":""hudson.model.Cause$UserIdCause"",""shortDescription"":""Started
 by user 
思码逸"",""userId"":""merico"",""userName"":""思码逸""}]},{},{""_class"":""org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction""}],""duration"":4,""estimatedDuration"":9,""fullDisplayNa
 [...]
-113,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.CauseAction"",""causes"":[{""_class"":""hudson.model.Cause$UserIdCause"",""shortDescription"":""Started
 by user 
思码逸"",""userId"":""merico"",""userName"":""思码逸""}]},{},{""_class"":""org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction""}],""duration"":2,""estimatedDuration"":6,""fullDisplayNa
 [...]
-114,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.CauseAction"",""causes"":[{""_class"":""hudson.model.Cause$UserIdCause"",""shortDescription"":""Started
 by user 
思码逸"",""userId"":""merico"",""userName"":""思码逸""}]},{},{""_class"":""org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction""}],""duration"":4,""estimatedDuration"":6,""fullDisplayNa
 [...]
-115,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.CauseAction"",""causes"":[{""_class"":""hudson.model.Cause$UserIdCause"",""shortDescription"":""Started
 by user 
思码逸"",""userId"":""merico"",""userName"":""思码逸""}]},{},{""_class"":""org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction""}],""duration"":12,""estimatedDuration"":6,""fullDisplayN
 [...]
-116,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.CauseAction"",""causes"":[{""_class"":""hudson.model.Cause$UserIdCause"",""shortDescription"":""Started
 by user 
思码逸"",""userId"":""merico"",""userName"":""思码逸""}]},{},{""_class"":""org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction""}],""duration"":78,""estimatedDuration"":6,""fullDisplayN
 [...]
-117,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.CauseAction"",""causes"":[{""_class"":""hudson.model.Cause$UserIdCause"",""shortDescription"":""Started
 by user 
思码逸"",""userId"":""merico"",""userName"":""思码逸""}]},{},{""_class"":""org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction""}],""duration"":11,""estimatedDuration"":6,""fullDisplayN
 [...]
-118,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.CauseAction"",""causes"":[{""_class"":""hudson.model.Cause$UserIdCause"",""shortDescription"":""Started
 by user 
思码逸"",""userId"":""merico"",""userName"":""思码逸""}]},{},{""_class"":""org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction""}],""duration"":8,""estimatedDuration"":6,""fullDisplayNa
 [...]
-119,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.CauseAction"",""causes"":[{""_class"":""hudson.model.Cause$UserIdCause"",""shortDescription"":""Started
 by user 
思码逸"",""userId"":""merico"",""userName"":""思码逸""}]},{},{""_class"":""org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction""}],""duration"":10,""estimatedDuration"":6,""fullDisplayN
 [...]
-120,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.CauseAction"",""causes"":[{""_class"":""hudson.model.Cause$UserIdCause"",""shortDescription"":""Started
 by user 
思码逸"",""userId"":""merico"",""userName"":""思码逸""}]},{},{""_class"":""org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction""}],""duration"":6,""estimatedDuration"":6,""fullDisplayNa
 [...]
+93,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.CauseAction"",""causes"":[{""_class"":""hudson.model.Cause$UserIdCause"",""shortDescription"":""Started
 by user 
思码逸"",""userId"":""merico"",""userName"":""思码逸""}]},{""_class"":""hudson.plugins.git.util.BuildData"",""lastBuiltRevision"":{""SHA1"":""0f886c74949c3ee7e489188911c7dc0c1d547418"",""branch""
 [...]
+94,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.CauseAction"",""causes"":[{""_class"":""hudson.model.Cause$UserIdCause"",""shortDescription"":""Started
 by user 
思码逸"",""userId"":""merico"",""userName"":""思码逸""}]},{""_class"":""hudson.plugins.git.util.BuildData"",""lastBuiltRevision"":{""SHA1"":""0f886c74949c3ee7e489188911c7dc0c1d547418"",""branch""
 [...]
+95,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.CauseAction"",""causes"":[{""_class"":""hudson.model.Cause$UserIdCause"",""shortDescription"":""Started
 by user 
思码逸"",""userId"":""merico"",""userName"":""思码逸""}]},{""_class"":""hudson.plugins.git.util.BuildData"",""lastBuiltRevision"":{""SHA1"":""ceeffdfdd06bce232f9adb3a656265bad13a8473"",""branch""
 [...]
+96,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}","{""_class"":""org.jenkinsci.plugins.workflow.job.WorkflowRun"",""actions"":[{""_class"":""hudson.model.CauseAction"",""causes"":[{""_class"":""hudson.model.Cause$UserIdCause"",""shortDescription"":""Started
 by user 
思码逸"",""userId"":""merico"",""userName"":""思码逸""}]},{""_class"":""org.jenkinsci.plugins.workflow.libs.LibrariesAction""},{},{},{""_class"":""org.jenkinsci.plugins.display
 [...]
 
121,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.CauseAction"",""causes"":[{""_class"":""hudson.model.Cause$UserIdCause"",""shortDescription"":""Started
 by user 
思码逸"",""userId"":""merico"",""userName"":""思码逸""}]},{},{""_class"":""org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction""}],""duration"":6,""estimatedDuration"":6,""fullDisplayNa
 [...]
 
122,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.CauseAction"",""causes"":[{""_class"":""hudson.model.Cause$UserIdCause"",""shortDescription"":""Started
 by user 
思码逸"",""userId"":""merico"",""userName"":""思码逸""}]},{},{""_class"":""org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction""}],""duration"":3,""estimatedDuration"":6,""fullDisplayNa
 [...]
 
123,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.CauseAction"",""causes"":[{""_class"":""hudson.model.Cause$UserIdCause"",""shortDescription"":""Started
 by user 
思码逸"",""userId"":""merico"",""userName"":""思码逸""}]},{},{""_class"":""org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction""}],""building"":true,""duration"":4,""estimatedDuration""
 [...]
diff --git a/backend/plugins/jenkins/e2e/snapshot_tables/_tool_jenkins_jobs.csv 
b/backend/plugins/jenkins/e2e/raw_tables/_tool_jenkins_jobs.csv
similarity index 100%
rename from backend/plugins/jenkins/e2e/snapshot_tables/_tool_jenkins_jobs.csv
rename to backend/plugins/jenkins/e2e/raw_tables/_tool_jenkins_jobs.csv
diff --git 
a/backend/plugins/jenkins/e2e/snapshot_tables/_tool_jenkins_build_commits.csv 
b/backend/plugins/jenkins/e2e/snapshot_tables/_tool_jenkins_build_commits.csv
index 82ce07b3a..f0a9915d6 100644
--- 
a/backend/plugins/jenkins/e2e/snapshot_tables/_tool_jenkins_build_commits.csv
+++ 
b/backend/plugins/jenkins/e2e/snapshot_tables/_tool_jenkins_build_commits.csv
@@ -2,8 +2,3 @@ 
connection_id,build_name,commit_sha,branch,repo_url,_raw_data_params,_raw_data_t
 
1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#11,ceeffdfdd06bce232f9adb3a656265bad13a8473,refs/remotes/origin/main,https://github.com/merico-dev/lake.git,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,95,
 
1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#21,0f886c74949c3ee7e489188911c7dc0c1d547418,refs/remotes/origin/main,https://github.com/merico-dev/lake.git,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,94,
 
1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#31,0f886c74949c3ee7e489188911c7dc0c1d547418,refs/remotes/origin/main,https://github.com/merico-dev/lake.git,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,93,
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#41,20139afef3c6ec9f3ebffcb06e243b145cbef8c6,refs/remotes/origin/main,https://github.com/merico-dev/lake.git,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,92,
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#51,20139afef3c6ec9f3ebffcb06e243b145cbef8c6,refs/remotes/origin/main,https://github.com/merico-dev/lake.git,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,91,
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#61,20139afef3c6ec9f3ebffcb06e243b145cbef8c6,refs/remotes/origin/main,https://github.com/merico-dev/lake.git,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,90,
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#71,0006e8105d70318aff5eeee38d405fa181a32aa0,refs/remotes/origin/main,https://github.com/merico-dev/lake.git,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,89,
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#81,0006e8105d70318aff5eeee38d405fa181a32aa0,refs/remotes/origin/main,https://github.com/merico-dev/lake.git,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,88,
diff --git 
a/backend/plugins/jenkins/e2e/snapshot_tables/_tool_jenkins_builds.csv 
b/backend/plugins/jenkins/e2e/snapshot_tables/_tool_jenkins_builds.csv
index 72ab64c3b..ecfcb9c32 100644
--- a/backend/plugins/jenkins/e2e/snapshot_tables/_tool_jenkins_builds.csv
+++ b/backend/plugins/jenkins/e2e/snapshot_tables/_tool_jenkins_builds.csv
@@ -1,29 +1,9 @@
 
connection_id,full_name,job_name,job_path,duration,estimated_duration,number,result,timestamp,start_time,has_stages,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark
 
1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#11,devlake,job/Test-jenkins-dir/job/test-jenkins-sub-dir/job/test-sub-sub-dir/,14820,1457,11,SUCCESS,1650017416514,2022-04-15T10:10:16.000+00:00,0,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,95,
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#13,devlake,job/Test-jenkins-dir/job/test-jenkins-sub-dir/job/test-sub-sub-dir/,1429,745,13,SUCCESS,1658385602419,2022-07-21T06:40:02.000+00:00,0,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,97,
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#15,devlake,job/Test-jenkins-dir/job/test-jenkins-sub-dir/job/test-sub-sub-dir/,70,27,15,SUCCESS,1658385566471,2022-07-21T06:39:26.000+00:00,0,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,105,
 
1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#17,devlake,job/Test-jenkins-dir/job/test-jenkins-sub-dir/job/test-sub-sub-dir/,57,6,17,SUCCESS,1650017153775,2022-04-15T10:05:53.000+00:00,0,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,124,
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#170,devlake,job/Test-jenkins-dir/job/test-jenkins-sub-dir/job/test-sub-sub-dir/,12,6,170,SUCCESS,1662647233074,2022-09-08T14:27:13.000+00:00,0,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,115,
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#171,devlake,job/Test-jenkins-dir/job/test-jenkins-sub-dir/job/test-sub-sub-dir/,4,6,171,SUCCESS,1662651656567,2022-09-08T15:40:56.000+00:00,0,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,114,
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#172,devlake,job/Test-jenkins-dir/job/test-jenkins-sub-dir/job/test-sub-sub-dir/,2,6,172,SUCCESS,1662651657893,2022-09-08T15:40:57.000+00:00,0,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,113,
 
1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#21,devlake,job/Test-jenkins-dir/job/test-jenkins-sub-dir/job/test-sub-sub-dir/,2121,1457,21,SUCCESS,1650022548450,2022-04-15T11:35:48.000+00:00,0,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,94,
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#215,devlake,job/Test-jenkins-dir/job/test-jenkins-sub-dir/job/test-sub-sub-dir/,11,8,215,SUCCESS,1662647212436,2022-09-08T14:26:52.000+00:00,0,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,101,
 
1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#23,devlake,job/Test-jenkins-dir/job/test-jenkins-sub-dir/job/test-sub-sub-dir/,61,745,23,SUCCESS,1662647211512,2022-09-08T14:26:51.000+00:00,0,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,96,
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#24,devlake,job/Test-jenkins-dir/job/test-jenkins-sub-dir/job/test-sub-sub-dir/,551,1972,24,SUCCESS,1662651633991,2022-09-08T15:40:33.000+00:00,0,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,99,
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#25,devlake,job/Test-jenkins-dir/job/test-jenkins-sub-dir/job/test-sub-sub-dir/,6,27,25,SUCCESS,1658385576367,2022-07-21T06:39:36.000+00:00,0,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,104,
 
1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#27,devlake,job/Test-jenkins-dir/job/test-jenkins-sub-dir/job/test-sub-sub-dir/,4,6,27,SUCCESS,1650017177939,2022-04-15T10:06:17.000+00:00,0,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,123,
 
1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#31,devlake,job/Test-jenkins-dir/job/test-jenkins-sub-dir/job/test-sub-sub-dir/,1587,1457,31,SUCCESS,1650024049161,2022-04-15T12:00:49.000+00:00,0,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,93,
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#34,devlake,job/Test-jenkins-dir/job/test-jenkins-sub-dir/job/test-sub-sub-dir/,802,1972,34,SUCCESS,1662651648992,2022-09-08T15:40:48.000+00:00,0,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,98,
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#35,devlake,job/Test-jenkins-dir/job/test-jenkins-sub-dir/job/test-sub-sub-dir/,4,27,35,SUCCESS,1662647217041,2022-09-08T14:26:57.000+00:00,0,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,103,
 
1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#37,devlake,job/Test-jenkins-dir/job/test-jenkins-sub-dir/job/test-sub-sub-dir/,3,6,37,SUCCESS,1650017186253,2022-04-15T10:06:26.000+00:00,0,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,122,
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#41,devlake,job/Test-jenkins-dir/job/test-jenkins-sub-dir/job/test-sub-sub-dir/,13952,1457,41,SUCCESS,1662647203905,2022-09-08T14:26:43.000+00:00,0,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,92,
 
1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#47,devlake,job/Test-jenkins-dir/job/test-jenkins-sub-dir/job/test-sub-sub-dir/,6,6,47,SUCCESS,1650022556910,2022-04-15T11:35:56.000+00:00,0,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,121,
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#51,devlake,job/Test-jenkins-dir/job/test-jenkins-sub-dir/job/test-sub-sub-dir/,1274,1457,51,SUCCESS,1662647231332,2022-09-08T14:27:11.000+00:00,0,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,91,
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#57,devlake,job/Test-jenkins-dir/job/test-jenkins-sub-dir/job/test-sub-sub-dir/,6,6,57,SUCCESS,1650022558491,2022-04-15T11:35:58.000+00:00,0,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,120,
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#61,devlake,job/Test-jenkins-dir/job/test-jenkins-sub-dir/job/test-sub-sub-dir/,1202,1457,61,SUCCESS,1662647242809,2022-09-08T14:27:22.000+00:00,0,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,90,
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#67,devlake,job/Test-jenkins-dir/job/test-jenkins-sub-dir/job/test-sub-sub-dir/,10,6,67,SUCCESS,1650022560954,2022-04-15T11:36:00.000+00:00,0,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,119,
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#71,devlake,job/Test-jenkins-dir/job/test-jenkins-sub-dir/job/test-sub-sub-dir/,1988,1457,71,SUCCESS,1662651625889,2022-09-08T15:40:25.000+00:00,0,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,89,
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#77,devlake,job/Test-jenkins-dir/job/test-jenkins-sub-dir/job/test-sub-sub-dir/,8,6,77,SUCCESS,1650023883294,2022-04-15T11:58:03.000+00:00,0,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,118,
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#81,devlake,job/Test-jenkins-dir/job/test-jenkins-sub-dir/job/test-sub-sub-dir/,1180,1457,81,SUCCESS,1662651640536,2022-09-08T15:40:40.000+00:00,0,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,88,
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#87,devlake,job/Test-jenkins-dir/job/test-jenkins-sub-dir/job/test-sub-sub-dir/,11,6,87,SUCCESS,1650023894336,2022-04-15T11:58:14.000+00:00,0,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,117,
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#97,devlake,job/Test-jenkins-dir/job/test-jenkins-sub-dir/job/test-sub-sub-dir/,78,6,97,SUCCESS,1662647207972,2022-09-08T14:26:47.000+00:00,0,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,116,
diff --git 
a/backend/plugins/jenkins/e2e/snapshot_tables/_tool_jenkins_builds_after_enrich.csv
 
b/backend/plugins/jenkins/e2e/snapshot_tables/_tool_jenkins_builds_after_enrich.csv
index 9cc84a18d..8b46d25c6 100644
--- 
a/backend/plugins/jenkins/e2e/snapshot_tables/_tool_jenkins_builds_after_enrich.csv
+++ 
b/backend/plugins/jenkins/e2e/snapshot_tables/_tool_jenkins_builds_after_enrich.csv
@@ -1,29 +1,9 @@
-connection_id,full_name,full_display_name,job_name,duration,has_stages
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#11,Test-jenkins-dir
 » test-jenkins-sub-dir » test-sub-sub-dir » devlake #11,devlake,14820,1
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#13,Test-jenkins-dir
 » test-jenkins-sub-dir » test-sub-sub-dir » devlake #13,devlake,1429,1
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#15,Test-jenkins-dir
 » test-jenkins-sub-dir » test-sub-sub-dir » devlake #15,devlake,70,1
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#17,Test-jenkins-dir
 » test-jenkins-sub-dir » test-sub-sub-dir » devlake #17,devlake,57,0
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#170,Test-jenkins-dir
 » test-jenkins-sub-dir » test-sub-sub-dir » devlake #170,devlake,12,0
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#171,Test-jenkins-dir
 » test-jenkins-sub-dir » test-sub-sub-dir » devlake #171,devlake,4,0
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#172,Test-jenkins-dir
 » test-jenkins-sub-dir » test-sub-sub-dir » devlake #172,devlake,2,0
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#21,Test-jenkins-dir
 » test-jenkins-sub-dir » test-sub-sub-dir » devlake #21,devlake,2121,0
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#215,Test-jenkins-dir
 » test-jenkins-sub-dir » test-sub-sub-dir » devlake #215,devlake,11,0
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#23,Test-jenkins-dir
 » test-jenkins-sub-dir » test-sub-sub-dir » devlake #23,devlake,61,0
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#24,Test-jenkins-dir
 » test-jenkins-sub-dir » test-sub-sub-dir » devlake #24,devlake,551,0
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#25,Test-jenkins-dir
 » test-jenkins-sub-dir » test-sub-sub-dir » devlake #25,devlake,6,0
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#27,Test-jenkins-dir
 » test-jenkins-sub-dir » test-sub-sub-dir » devlake #27,devlake,4,0
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#31,Test-jenkins-dir
 » test-jenkins-sub-dir » test-sub-sub-dir » devlake #31,devlake,1587,0
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#34,Test-jenkins-dir
 » test-jenkins-sub-dir » test-sub-sub-dir » devlake #34,devlake,802,0
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#35,Test-jenkins-dir
 » test-jenkins-sub-dir » test-sub-sub-dir » devlake #35,devlake,4,0
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#37,Test-jenkins-dir
 » test-jenkins-sub-dir » test-sub-sub-dir » devlake #37,devlake,3,0
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#41,Test-jenkins-dir
 » test-jenkins-sub-dir » test-sub-sub-dir » devlake #41,devlake,13952,0
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#47,Test-jenkins-dir
 » test-jenkins-sub-dir » test-sub-sub-dir » devlake #47,devlake,6,0
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#51,Test-jenkins-dir
 » test-jenkins-sub-dir » test-sub-sub-dir » devlake #51,devlake,1274,0
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#57,Test-jenkins-dir
 » test-jenkins-sub-dir » test-sub-sub-dir » devlake #57,devlake,6,0
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#61,Test-jenkins-dir
 » test-jenkins-sub-dir » test-sub-sub-dir » devlake #61,devlake,1202,0
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#67,Test-jenkins-dir
 » test-jenkins-sub-dir » test-sub-sub-dir » devlake #67,devlake,10,0
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#71,Test-jenkins-dir
 » test-jenkins-sub-dir » test-sub-sub-dir » devlake #71,devlake,1988,0
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#77,Test-jenkins-dir
 » test-jenkins-sub-dir » test-sub-sub-dir » devlake #77,devlake,8,0
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#81,Test-jenkins-dir
 » test-jenkins-sub-dir » test-sub-sub-dir » devlake #81,devlake,1180,0
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#87,Test-jenkins-dir
 » test-jenkins-sub-dir » test-sub-sub-dir » devlake #87,devlake,11,0
-1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#97,Test-jenkins-dir
 » test-jenkins-sub-dir » test-sub-sub-dir » devlake #97,devlake,78,0
+connection_id,full_name,job_name,duration,has_stages
+1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#11,devlake,14820,1
+1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#17,devlake,57,0
+1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#21,devlake,2121,0
+1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#23,devlake,61,0
+1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#27,devlake,4,0
+1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#31,devlake,1587,0
+1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#37,devlake,3,0
+1,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#47,devlake,6,0
diff --git 
a/backend/plugins/jenkins/e2e/snapshot_tables/cicd_pipeline_commits.csv 
b/backend/plugins/jenkins/e2e/snapshot_tables/cicd_pipeline_commits.csv
index dec0c0ceb..16b754634 100644
--- a/backend/plugins/jenkins/e2e/snapshot_tables/cicd_pipeline_commits.csv
+++ b/backend/plugins/jenkins/e2e/snapshot_tables/cicd_pipeline_commits.csv
@@ -2,8 +2,3 @@ 
pipeline_id,commit_sha,repo_id,repo,branch,_raw_data_params,_raw_data_table,_raw
 
jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#11,ceeffdfdd06bce232f9adb3a656265bad13a8473,,https://github.com/merico-dev/lake.git,refs/remotes/origin/main,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,95,
 
jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#21,0f886c74949c3ee7e489188911c7dc0c1d547418,,https://github.com/merico-dev/lake.git,refs/remotes/origin/main,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,94,
 
jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#31,0f886c74949c3ee7e489188911c7dc0c1d547418,,https://github.com/merico-dev/lake.git,refs/remotes/origin/main,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,93,
-jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#41,20139afef3c6ec9f3ebffcb06e243b145cbef8c6,,https://github.com/merico-dev/lake.git,refs/remotes/origin/main,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,92,
-jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#51,20139afef3c6ec9f3ebffcb06e243b145cbef8c6,,https://github.com/merico-dev/lake.git,refs/remotes/origin/main,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,91,
-jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#61,20139afef3c6ec9f3ebffcb06e243b145cbef8c6,,https://github.com/merico-dev/lake.git,refs/remotes/origin/main,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,90,
-jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#71,0006e8105d70318aff5eeee38d405fa181a32aa0,,https://github.com/merico-dev/lake.git,refs/remotes/origin/main,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,89,
-jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#81,0006e8105d70318aff5eeee38d405fa181a32aa0,,https://github.com/merico-dev/lake.git,refs/remotes/origin/main,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,88,
diff --git a/backend/plugins/jenkins/e2e/snapshot_tables/cicd_pipelines.csv 
b/backend/plugins/jenkins/e2e/snapshot_tables/cicd_pipelines.csv
index ec6fd4ddd..401c93939 100644
--- a/backend/plugins/jenkins/e2e/snapshot_tables/cicd_pipelines.csv
+++ b/backend/plugins/jenkins/e2e/snapshot_tables/cicd_pipelines.csv
@@ -1,29 +1,9 @@
 
id,name,result,status,type,duration_sec,environment,created_date,finished_date,cicd_scope_id,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark
 
jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#11,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#11,SUCCESS,DONE,,14,,2022-04-15T10:10:16.000+00:00,2022-04-15T10:10:30.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,95,
-jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#13,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#13,SUCCESS,DONE,,1,,2022-07-21T06:40:02.000+00:00,2022-07-21T06:40:03.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,97,
-jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#15,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#15,SUCCESS,DONE,,0,,2022-07-21T06:39:26.000+00:00,2022-07-21T06:39:26.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,105,
 
jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#17,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#17,SUCCESS,DONE,,0,,2022-04-15T10:05:53.000+00:00,2022-04-15T10:05:53.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,124,
-jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#170,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#170,SUCCESS,DONE,,0,,2022-09-08T14:27:13.000+00:00,2022-09-08T14:27:13.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,115,
-jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#171,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#171,SUCCESS,DONE,,0,,2022-09-08T15:40:56.000+00:00,2022-09-08T15:40:56.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,114,
-jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#172,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#172,SUCCESS,DONE,,0,,2022-09-08T15:40:57.000+00:00,2022-09-08T15:40:57.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,113,
 
jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#21,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#21,SUCCESS,DONE,,2,,2022-04-15T11:35:48.000+00:00,2022-04-15T11:35:50.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,94,
-jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#215,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#215,SUCCESS,DONE,,0,,2022-09-08T14:26:52.000+00:00,2022-09-08T14:26:52.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,101,
 
jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#23,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#23,SUCCESS,DONE,,0,,2022-09-08T14:26:51.000+00:00,2022-09-08T14:26:51.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,96,
-jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#24,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#24,SUCCESS,DONE,,0,,2022-09-08T15:40:33.000+00:00,2022-09-08T15:40:33.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,99,
-jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#25,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#25,SUCCESS,DONE,,0,,2022-07-21T06:39:36.000+00:00,2022-07-21T06:39:36.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,104,
 
jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#27,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#27,,IN_PROGRESS,,0,,2022-04-15T10:06:17.000+00:00,,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,123,
 
jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#31,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#31,SUCCESS,DONE,,1,,2022-04-15T12:00:49.000+00:00,2022-04-15T12:00:50.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,93,
-jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#34,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#34,SUCCESS,DONE,,0,,2022-09-08T15:40:48.000+00:00,2022-09-08T15:40:48.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,98,
-jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#35,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#35,SUCCESS,DONE,,0,,2022-09-08T14:26:57.000+00:00,2022-09-08T14:26:57.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,103,
 
jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#37,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#37,SUCCESS,DONE,,0,,2022-04-15T10:06:26.000+00:00,2022-04-15T10:06:26.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,122,
-jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#41,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#41,SUCCESS,DONE,,13,,2022-09-08T14:26:43.000+00:00,2022-09-08T14:26:56.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,92,
 
jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#47,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#47,SUCCESS,DONE,,0,,2022-04-15T11:35:56.000+00:00,2022-04-15T11:35:56.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,121,
-jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#51,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#51,SUCCESS,DONE,,1,,2022-09-08T14:27:11.000+00:00,2022-09-08T14:27:12.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,91,
-jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#57,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#57,SUCCESS,DONE,,0,,2022-04-15T11:35:58.000+00:00,2022-04-15T11:35:58.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,120,
-jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#61,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#61,SUCCESS,DONE,,1,,2022-09-08T14:27:22.000+00:00,2022-09-08T14:27:23.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,90,
-jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#67,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#67,SUCCESS,DONE,,0,,2022-04-15T11:36:00.000+00:00,2022-04-15T11:36:00.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,119,
-jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#71,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#71,SUCCESS,DONE,,1,,2022-09-08T15:40:25.000+00:00,2022-09-08T15:40:26.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,89,
-jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#77,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#77,SUCCESS,DONE,,0,,2022-04-15T11:58:03.000+00:00,2022-04-15T11:58:03.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,118,
-jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#81,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#81,SUCCESS,DONE,,1,,2022-09-08T15:40:40.000+00:00,2022-09-08T15:40:41.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,88,
-jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#87,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#87,SUCCESS,DONE,,0,,2022-04-15T11:58:14.000+00:00,2022-04-15T11:58:14.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,117,
-jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#97,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#97,SUCCESS,DONE,,0,,2022-09-08T14:26:47.000+00:00,2022-09-08T14:26:47.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,116,
diff --git a/backend/plugins/jenkins/e2e/snapshot_tables/cicd_tasks.csv 
b/backend/plugins/jenkins/e2e/snapshot_tables/cicd_tasks.csv
index 4d20786d7..ace6607bf 100644
--- a/backend/plugins/jenkins/e2e/snapshot_tables/cicd_tasks.csv
+++ b/backend/plugins/jenkins/e2e/snapshot_tables/cicd_tasks.csv
@@ -1,26 +1,8 @@
 
id,name,pipeline_id,result,status,type,environment,duration_sec,started_date,finished_date,cicd_scope_id,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark
 
jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#17,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#17,SUCCESS,DONE,DEPLOYMENT,PRODUCTION,0,2022-04-15T10:05:53.000+00:00,2022-04-15T10:05:53.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-
 [...]
-jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#170,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#170,SUCCESS,DONE,DEPLOYMENT,PRODUCTION,0,2022-09-08T14:27:13.000+00:00,2022-09-08T14:27:13.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-su
 [...]
-jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#171,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#171,SUCCESS,DONE,DEPLOYMENT,PRODUCTION,0,2022-09-08T15:40:56.000+00:00,2022-09-08T15:40:56.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-su
 [...]
-jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#172,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#172,SUCCESS,DONE,DEPLOYMENT,PRODUCTION,0,2022-09-08T15:40:57.000+00:00,2022-09-08T15:40:57.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-su
 [...]
 
jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#21,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#21,SUCCESS,DONE,DEPLOYMENT,PRODUCTION,2,2022-04-15T11:35:48.000+00:00,2022-04-15T11:35:50.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-
 [...]
-jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#215,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#215,SUCCESS,DONE,DEPLOYMENT,PRODUCTION,0,2022-09-08T14:26:52.000+00:00,2022-09-08T14:26:52.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-su
 [...]
 
jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#23,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#23,SUCCESS,DONE,DEPLOYMENT,PRODUCTION,0,2022-09-08T14:26:51.000+00:00,2022-09-08T14:26:51.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-
 [...]
-jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#24,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#24,SUCCESS,DONE,DEPLOYMENT,PRODUCTION,0,2022-09-08T15:40:33.000+00:00,2022-09-08T15:40:33.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-
 [...]
-jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#25,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#25,SUCCESS,DONE,DEPLOYMENT,PRODUCTION,0,2022-07-21T06:39:36.000+00:00,2022-07-21T06:39:36.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-
 [...]
 
jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#27,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#27,,IN_PROGRESS,DEPLOYMENT,PRODUCTION,0,2022-04-15T10:06:17.000+00:00,,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake"
 [...]
 
jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#31,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#31,SUCCESS,DONE,DEPLOYMENT,PRODUCTION,1,2022-04-15T12:00:49.000+00:00,2022-04-15T12:00:50.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-
 [...]
-jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#34,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#34,SUCCESS,DONE,DEPLOYMENT,PRODUCTION,0,2022-09-08T15:40:48.000+00:00,2022-09-08T15:40:48.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-
 [...]
-jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#35,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#35,SUCCESS,DONE,DEPLOYMENT,PRODUCTION,0,2022-09-08T14:26:57.000+00:00,2022-09-08T14:26:57.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-
 [...]
 
jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#37,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#37,SUCCESS,DONE,DEPLOYMENT,PRODUCTION,0,2022-04-15T10:06:26.000+00:00,2022-04-15T10:06:26.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-
 [...]
-jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#41,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#41,SUCCESS,DONE,DEPLOYMENT,PRODUCTION,13,2022-09-08T14:26:43.000+00:00,2022-09-08T14:26:56.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub
 [...]
 
jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#47,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#47,SUCCESS,DONE,DEPLOYMENT,PRODUCTION,0,2022-04-15T11:35:56.000+00:00,2022-04-15T11:35:56.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-
 [...]
-jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#51,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#51,SUCCESS,DONE,DEPLOYMENT,PRODUCTION,1,2022-09-08T14:27:11.000+00:00,2022-09-08T14:27:12.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-
 [...]
-jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#57,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#57,SUCCESS,DONE,DEPLOYMENT,PRODUCTION,0,2022-04-15T11:35:58.000+00:00,2022-04-15T11:35:58.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-
 [...]
-jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#61,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#61,SUCCESS,DONE,DEPLOYMENT,PRODUCTION,1,2022-09-08T14:27:22.000+00:00,2022-09-08T14:27:23.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-
 [...]
-jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#67,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#67,SUCCESS,DONE,DEPLOYMENT,PRODUCTION,0,2022-04-15T11:36:00.000+00:00,2022-04-15T11:36:00.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-
 [...]
-jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#71,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#71,SUCCESS,DONE,DEPLOYMENT,PRODUCTION,1,2022-09-08T15:40:25.000+00:00,2022-09-08T15:40:26.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-
 [...]
-jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#77,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#77,SUCCESS,DONE,DEPLOYMENT,PRODUCTION,0,2022-04-15T11:58:03.000+00:00,2022-04-15T11:58:03.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-
 [...]
-jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#81,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#81,SUCCESS,DONE,DEPLOYMENT,PRODUCTION,1,2022-09-08T15:40:40.000+00:00,2022-09-08T15:40:41.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-
 [...]
-jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#87,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#87,SUCCESS,DONE,DEPLOYMENT,PRODUCTION,0,2022-04-15T11:58:14.000+00:00,2022-04-15T11:58:14.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-
 [...]
-jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#97,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#97,SUCCESS,DONE,DEPLOYMENT,PRODUCTION,0,2022-09-08T14:26:47.000+00:00,2022-09-08T14:26:47.000+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-
 [...]
diff --git a/backend/plugins/jenkins/models/response.go 
b/backend/plugins/jenkins/models/response.go
index 179898d7c..31db53db0 100644
--- a/backend/plugins/jenkins/models/response.go
+++ b/backend/plugins/jenkins/models/response.go
@@ -73,11 +73,11 @@ type LastBuiltRevision struct {
 }
 
 type Action struct {
-       Class                   string            `json:"_class,omitempty"`
-       LastBuiltRevision       LastBuiltRevision 
`json:"lastBuiltRevision,omitempty"`
-       MercurialRevisionNumber string            
`json:"mercurialRevisionNumber"`
-       RemoteUrls              []string          `json:"remoteUrls"`
-       Causes                  []Cause           `json:"causes"`
+       Class                   string             `json:"_class,omitempty"`
+       LastBuiltRevision       *LastBuiltRevision 
`json:"lastBuiltRevision,omitempty"`
+       MercurialRevisionNumber string             
`json:"mercurialRevisionNumber"`
+       RemoteUrls              []string           `json:"remoteUrls"`
+       Causes                  []Cause            `json:"causes"`
 }
 type ChangeSet struct {
        Class     string     `json:"_class"`
diff --git a/backend/plugins/jenkins/tasks/build_extractor.go 
b/backend/plugins/jenkins/tasks/build_extractor.go
index d7d7567f7..287d2b788 100644
--- a/backend/plugins/jenkins/tasks/build_extractor.go
+++ b/backend/plugins/jenkins/tasks/build_extractor.go
@@ -73,39 +73,41 @@ func ExtractApiBuilds(taskCtx plugin.SubTaskContext) 
errors.Error {
                                Building:          body.Building,
                                StartTime:         
time.Unix(body.Timestamp/1000, 0),
                        }
-                       vcs := body.ChangeSet.Kind
-                       if vcs == "git" || vcs == "hg" {
-                               for _, a := range body.Actions {
-                                       sha := ""
-                                       branch := ""
-                                       if a.LastBuiltRevision.SHA1 != "" {
-                                               sha = a.LastBuiltRevision.SHA1
-                                       }
-                                       if a.MercurialRevisionNumber != "" {
-                                               sha = a.MercurialRevisionNumber
-                                       }
+                       // we also need to collect the commit info from the 
build which does not have changeSet
+                       // changeSet describes the changes that were made in 
the build
+                       for _, a := range body.Actions {
+                               if a.LastBuiltRevision == nil {
+                                       continue
+                               }
+                               sha := ""
+                               branch := ""
+                               if a.LastBuiltRevision.SHA1 != "" {
+                                       sha = a.LastBuiltRevision.SHA1
+                               }
+                               if a.MercurialRevisionNumber != "" {
+                                       sha = a.MercurialRevisionNumber
+                               }
 
-                                       if len(a.LastBuiltRevision.Branches) > 
0 {
-                                               branch = 
a.LastBuiltRevision.Branches[0].Name
-                                       }
-                                       for _, url := range a.RemoteUrls {
-                                               if url != "" {
-                                                       buildCommitRemoteUrl := 
models.JenkinsBuildCommit{
-                                                               ConnectionId: 
data.Options.ConnectionId,
-                                                               BuildName:    
build.FullName,
-                                                               CommitSha:    
sha,
-                                                               RepoUrl:      
url,
-                                                               Branch:       
branch,
-                                                       }
-                                                       results = 
append(results, &buildCommitRemoteUrl)
+                               if len(a.LastBuiltRevision.Branches) > 0 {
+                                       branch = 
a.LastBuiltRevision.Branches[0].Name
+                               }
+                               for _, url := range a.RemoteUrls {
+                                       if url != "" {
+                                               buildCommitRemoteUrl := 
models.JenkinsBuildCommit{
+                                                       ConnectionId: 
data.Options.ConnectionId,
+                                                       BuildName:    
build.FullName,
+                                                       CommitSha:    sha,
+                                                       RepoUrl:      url,
+                                                       Branch:       branch,
                                                }
+                                               results = append(results, 
&buildCommitRemoteUrl)
                                        }
-                                       if len(a.Causes) > 0 {
-                                               for _, cause := range a.Causes {
-                                                       if 
cause.UpstreamProject != "" {
-                                                               
triggeredByBuild := fmt.Sprintf("%s #%d", cause.UpstreamProject, 
cause.UpstreamBuild)
-                                                               
build.TriggeredBy = triggeredByBuild
-                                                       }
+                               }
+                               if len(a.Causes) > 0 {
+                                       for _, cause := range a.Causes {
+                                               if cause.UpstreamProject != "" {
+                                                       triggeredByBuild := 
fmt.Sprintf("%s #%d", cause.UpstreamProject, cause.UpstreamBuild)
+                                                       build.TriggeredBy = 
triggeredByBuild
                                                }
                                        }
                                }


Reply via email to