This is an automated email from the ASF dual-hosted git repository.
klesh pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-devlake.git
The following commit(s) were added to refs/heads/main by this push:
new 089e8367 fix: jenkins collect folder (#2480)
089e8367 is described below
commit 089e836752daf395b5419991295d3e9dc953a8c5
Author: mappjzc <[email protected]>
AuthorDate: Wed Jul 13 22:04:03 2022 +0800
fix: jenkins collect folder (#2480)
* fix: jenkins collect folder
Add queue.go
Add list.go
Add QueueIterator
Add some logic fix
Nddtfjiang <[email protected]>
* fix: fix for 2470
fix #2470
move apiClient.Release() to plugin close.
Nddtfjiang <[email protected]>
* fix: fix jenkins e2e test
update e2e test table csv.
add path too jobs_test
Nddtfjiang <[email protected]>
* refactor: changed list and queue to helper temporary
move list.go and queue.go to helper temporary
Nddtfjiang <[email protected]>
---
plugins/ae/impl/impl.go | 10 ++
plugins/feishu/impl/impl.go | 12 ++
plugins/gitee/impl/impl.go | 10 ++
plugins/github/impl/impl.go | 11 ++
plugins/gitlab/impl/impl.go | 10 ++
plugins/helper/api_collector.go | 11 +-
plugins/helper/api_collector_test.go | 2 +-
plugins/helper/iterator.go | 43 +++++++
plugins/{jenkins/jenkins.go => helper/list.go} | 42 ++++---
plugins/helper/queue.go | 127 +++++++++++++++++++++
plugins/icla/plugin_main.go | 12 ++
plugins/jenkins/e2e/jobs_test.go | 4 +-
.../e2e/raw_tables/_raw_jenkins_api_builds.csv | 30 ++---
.../e2e/raw_tables/_raw_jenkins_api_jobs.csv | 21 ++--
.../e2e/snapshot_tables/_tool_jenkins_builds.csv | 30 ++---
.../e2e/snapshot_tables/_tool_jenkins_jobs.csv | 21 ++--
plugins/jenkins/e2e/snapshot_tables/builds.csv | 28 ++---
plugins/jenkins/e2e/snapshot_tables/jobs.csv | 19 ++-
plugins/jenkins/impl/impl.go | 10 ++
plugins/jenkins/jenkins.go | 2 +-
plugins/jenkins/models/job.go | 18 ++-
.../models/migrationscripts/archived/job.go | 1 +
.../jenkins/models/migrationscripts/init_schema.go | 2 +-
plugins/jenkins/models/response.go | 1 +
plugins/jenkins/tasks/build_collector.go | 5 +-
plugins/jenkins/tasks/job_collector.go | 32 +++++-
plugins/jenkins/tasks/job_extractor.go | 8 ++
plugins/jira/impl/impl.go | 10 ++
plugins/tapd/impl/impl.go | 10 ++
29 files changed, 416 insertions(+), 126 deletions(-)
diff --git a/plugins/ae/impl/impl.go b/plugins/ae/impl/impl.go
index e8f9c217..cfc747a4 100644
--- a/plugins/ae/impl/impl.go
+++ b/plugins/ae/impl/impl.go
@@ -37,6 +37,7 @@ var _ core.PluginInit = (*AE)(nil)
var _ core.PluginTask = (*AE)(nil)
var _ core.PluginApi = (*AE)(nil)
var _ core.Migratable = (*AE)(nil)
+var _ core.CloseablePluginTask = (*AE)(nil)
type AE struct{}
@@ -118,3 +119,12 @@ func (plugin AE) ApiResources()
map[string]map[string]core.ApiResourceHandler {
},
}
}
+
+func (plugin AE) Close(taskCtx core.TaskContext) error {
+ data, ok := taskCtx.GetData().(*tasks.AeTaskData)
+ if !ok {
+ return fmt.Errorf("GetData failed when try to close %+v",
taskCtx)
+ }
+ data.ApiClient.Release()
+ return nil
+}
diff --git a/plugins/feishu/impl/impl.go b/plugins/feishu/impl/impl.go
index cc4a4e03..be72a418 100644
--- a/plugins/feishu/impl/impl.go
+++ b/plugins/feishu/impl/impl.go
@@ -18,6 +18,8 @@ limitations under the License.
package impl
import (
+ "fmt"
+
"github.com/mitchellh/mapstructure"
"github.com/spf13/viper"
"gorm.io/gorm"
@@ -36,6 +38,7 @@ var _ core.PluginInit = (*Feishu)(nil)
var _ core.PluginTask = (*Feishu)(nil)
var _ core.PluginApi = (*Feishu)(nil)
var _ core.Migratable = (*Feishu)(nil)
+var _ core.CloseablePluginTask = (*Feishu)(nil)
type Feishu struct{}
@@ -122,3 +125,12 @@ func (plugin Feishu) MigrationScripts() []migration.Script
{
func (plugin Feishu) ApiResources()
map[string]map[string]core.ApiResourceHandler {
return map[string]map[string]core.ApiResourceHandler{}
}
+
+func (plugin Feishu) Close(taskCtx core.TaskContext) error {
+ data, ok := taskCtx.GetData().(*tasks.FeishuTaskData)
+ if !ok {
+ return fmt.Errorf("GetData failed when try to close %+v",
taskCtx)
+ }
+ data.ApiClient.Release()
+ return nil
+}
diff --git a/plugins/gitee/impl/impl.go b/plugins/gitee/impl/impl.go
index 90a1eb53..44f8662a 100644
--- a/plugins/gitee/impl/impl.go
+++ b/plugins/gitee/impl/impl.go
@@ -37,6 +37,7 @@ var _ core.PluginInit = (*Gitee)(nil)
var _ core.PluginTask = (*Gitee)(nil)
var _ core.PluginApi = (*Gitee)(nil)
var _ core.Migratable = (*Gitee)(nil)
+var _ core.CloseablePluginTask = (*Gitee)(nil)
type Gitee string
@@ -186,3 +187,12 @@ func (plugin Gitee) ApiResources()
map[string]map[string]core.ApiResourceHandler
},
}
}
+
+func (plugin Gitee) Close(taskCtx core.TaskContext) error {
+ data, ok := taskCtx.GetData().(*tasks.GiteeTaskData)
+ if !ok {
+ return fmt.Errorf("GetData failed when try to close %+v",
taskCtx)
+ }
+ data.ApiClient.Release()
+ return nil
+}
diff --git a/plugins/github/impl/impl.go b/plugins/github/impl/impl.go
index 6bba76c1..6171a983 100644
--- a/plugins/github/impl/impl.go
+++ b/plugins/github/impl/impl.go
@@ -19,6 +19,7 @@ package impl
import (
"fmt"
+
"github.com/apache/incubator-devlake/migration"
"github.com/apache/incubator-devlake/plugins/core"
"github.com/apache/incubator-devlake/plugins/github/api"
@@ -36,6 +37,7 @@ var _ core.PluginTask = (*Github)(nil)
var _ core.PluginApi = (*Github)(nil)
var _ core.Migratable = (*Github)(nil)
var _ core.PluginBlueprintV100 = (*Github)(nil)
+var _ core.CloseablePluginTask = (*Github)(nil)
type Github struct{}
@@ -140,3 +142,12 @@ func (plugin Github) ApiResources()
map[string]map[string]core.ApiResourceHandle
func (plugin Github) MakePipelinePlan(connectionId uint64, scope
[]*core.BlueprintScopeV100) (core.PipelinePlan, error) {
return api.MakePipelinePlan(plugin.SubTaskMetas(), connectionId, scope)
}
+
+func (plugin Github) Close(taskCtx core.TaskContext) error {
+ data, ok := taskCtx.GetData().(*tasks.GithubTaskData)
+ if !ok {
+ return fmt.Errorf("GetData failed when try to close %+v",
taskCtx)
+ }
+ data.ApiClient.Release()
+ return nil
+}
diff --git a/plugins/gitlab/impl/impl.go b/plugins/gitlab/impl/impl.go
index 1550131d..b6bf0113 100644
--- a/plugins/gitlab/impl/impl.go
+++ b/plugins/gitlab/impl/impl.go
@@ -37,6 +37,7 @@ var _ core.PluginTask = (*Gitlab)(nil)
var _ core.PluginApi = (*Gitlab)(nil)
var _ core.Migratable = (*Gitlab)(nil)
var _ core.PluginBlueprintV100 = (*Gitlab)(nil)
+var _ core.CloseablePluginTask = (*Gitlab)(nil)
type Gitlab string
@@ -143,3 +144,12 @@ func (plugin Gitlab) ApiResources()
map[string]map[string]core.ApiResourceHandle
},
}
}
+
+func (plugin Gitlab) Close(taskCtx core.TaskContext) error {
+ data, ok := taskCtx.GetData().(*tasks.GitlabTaskData)
+ if !ok {
+ return fmt.Errorf("GetData failed when try to close %+v",
taskCtx)
+ }
+ data.ApiClient.Release()
+ return nil
+}
diff --git a/plugins/helper/api_collector.go b/plugins/helper/api_collector.go
index 3e08b859..a9b7390d 100644
--- a/plugins/helper/api_collector.go
+++ b/plugins/helper/api_collector.go
@@ -149,14 +149,21 @@ func (collector *ApiCollector) Execute() error {
collector.args.Ctx.SetProgress(0, -1)
if collector.args.Input != nil {
+
iterator := collector.args.Input
defer iterator.Close()
apiClient := collector.args.ApiClient
if apiClient == nil {
return fmt.Errorf("api_collector can not Execute with
nil apiClient")
}
- defer apiClient.Release()
- for iterator.HasNext() && !apiClient.HasError() {
+
+ for {
+ if !iterator.HasNext() || apiClient.HasError() {
+ collector.args.ApiClient.WaitAsync()
+ if !iterator.HasNext() || apiClient.HasError() {
+ break
+ }
+ }
input, err := iterator.Fetch()
if err != nil {
break
diff --git a/plugins/helper/api_collector_test.go
b/plugins/helper/api_collector_test.go
index be829d0a..ee9cb961 100644
--- a/plugins/helper/api_collector_test.go
+++ b/plugins/helper/api_collector_test.go
@@ -41,7 +41,7 @@ func TestFetchPageUndetermined(t *testing.T) {
mockInput := new(mocks.Iterator)
mockInput.On("HasNext").Return(true).Once()
- mockInput.On("HasNext").Return(false).Once()
+ mockInput.On("HasNext").Return(false).Twice()
mockInput.On("Fetch").Return(nil, nil).Once()
mockInput.On("Close").Return(nil)
diff --git a/plugins/helper/iterator.go b/plugins/helper/iterator.go
index 98c9be6a..7c8953b2 100644
--- a/plugins/helper/iterator.go
+++ b/plugins/helper/iterator.go
@@ -113,3 +113,46 @@ func NewDateIterator(days int) (*DateIterator, error) {
Current: 0,
}, nil
}
+
+type QueueIteratorNode struct {
+ data interface{}
+ next *QueueIteratorNode
+}
+
+func (q *QueueIteratorNode) Next() interface{} {
+ if q.next == nil {
+ return nil
+ }
+ return q.next
+}
+
+func (q *QueueIteratorNode) SetNext(next interface{}) {
+ q.next, _ = next.(*QueueIteratorNode)
+}
+
+type QueueIterator struct {
+ queue *Queue
+}
+
+func (q *QueueIterator) HasNext() bool {
+ return q.queue.GetCount() > 0
+}
+
+func (q *QueueIterator) Fetch() (interface{}, error) {
+ return q.queue.PullWithOutLock(), nil
+}
+
+func (q *QueueIterator) Push(data QueueNode) {
+ q.queue.PushWitouLock(data)
+}
+
+func (q *QueueIterator) Close() error {
+ q.queue.CleanWithOutLock()
+ return nil
+}
+
+func NewQueueIterator() *QueueIterator {
+ return &QueueIterator{
+ queue: NewQueue(),
+ }
+}
diff --git a/plugins/jenkins/jenkins.go b/plugins/helper/list.go
similarity index 59%
copy from plugins/jenkins/jenkins.go
copy to plugins/helper/list.go
index fcbd14b2..b3a1381b 100644
--- a/plugins/jenkins/jenkins.go
+++ b/plugins/helper/list.go
@@ -15,23 +15,29 @@ See the License for the specific language governing
permissions and
limitations under the License.
*/
-package main
-
-import (
- "github.com/apache/incubator-devlake/plugins/jenkins/impl"
- "github.com/apache/incubator-devlake/runner"
- "github.com/spf13/cobra"
-)
-
-var PluginEntry impl.Jenkins
-
-func main() {
- jenkinsCmd := &cobra.Command{Use: "jenkins"}
- connectionId := jenkinsCmd.Flags().Uint64P("connection", "c", 0,
"jenkins connection id")
- jenkinsCmd.Run = func(cmd *cobra.Command, args []string) {
- runner.DirectRun(cmd, args, PluginEntry, map[string]interface{}{
- "connectionId": *connectionId,
- })
+package helper
+
+type ListBaseNode struct {
+ next interface{}
+}
+
+func (l *ListBaseNode) Next() interface{} {
+ if l.next == nil {
+ return nil
}
- runner.RunCmd(jenkinsCmd)
+ return l.next
+}
+
+func (l *ListBaseNode) SetNext(next interface{}) {
+ l.next = next
}
+
+// NewListBaseNode create and init a new node
+func NewListBaseNode() *ListBaseNode {
+ return &ListBaseNode{
+ next: nil,
+ }
+}
+
+// check if is all right for interface QueueNode
+var _ QueueNode = (*ListBaseNode)(nil)
diff --git a/plugins/helper/queue.go b/plugins/helper/queue.go
new file mode 100644
index 00000000..b1e74783
--- /dev/null
+++ b/plugins/helper/queue.go
@@ -0,0 +1,127 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package helper
+
+import (
+ "sync"
+ "sync/atomic"
+)
+
+type QueueNode interface {
+ Next() interface{}
+ SetNext(next interface{})
+}
+
+type Queue struct {
+ count int64
+ head QueueNode
+ tail QueueNode
+ mux sync.Mutex
+}
+
+// Push add a node to queue
+func (q *Queue) Push(node QueueNode) {
+ q.mux.Lock()
+ defer q.mux.Unlock()
+ q.PushWitouLock(node)
+}
+
+// Pull get a node from queue
+func (q *Queue) Pull(add *int64) QueueNode {
+ q.mux.Lock()
+ defer q.mux.Unlock()
+
+ node := q.PullWithOutLock()
+
+ if node == nil {
+ return nil
+ }
+ if add != nil {
+ atomic.AddInt64(add, 1)
+ }
+ return node
+}
+
+// PushWitouLock is no lock mode of Push
+func (q *Queue) PushWitouLock(node QueueNode) {
+ if q.tail == nil {
+ q.head = node
+ q.tail = node
+ q.count = 1
+ } else {
+ q.tail.SetNext(node)
+ q.tail = node
+ q.count++
+ }
+}
+
+// PullWitouLock is no lock mode of Pull
+func (q *Queue) PullWithOutLock() QueueNode {
+ var node QueueNode = nil
+
+ if q.head != nil {
+ node = q.head
+ q.head, _ = node.Next().(QueueNode)
+
+ if q.head == nil {
+ q.tail = nil
+ }
+
+ node.SetNext(nil)
+ q.count--
+ } else {
+ q.count = 0
+ }
+ return node
+}
+
+// CleanWithOutLock is no lock mode of Clean
+func (q *Queue) CleanWithOutLock() {
+ q.count = 0
+ q.head = nil
+ q.tail = nil
+}
+
+// Clean remove all node on queue
+func (q *Queue) Clean() {
+ q.mux.Lock()
+ defer q.mux.Unlock()
+ q.CleanWithOutLock()
+}
+
+// GetCountWithOutLock is no lock mode of GetCount
+func (q *Queue) GetCountWithOutLock() int64 {
+ return q.count
+}
+
+// GetCount get the node count
+func (q *Queue) GetCount() int64 {
+ q.mux.Lock()
+ defer q.mux.Unlock()
+ return q.count
+}
+
+// NewQueue create and init a new Queue
+func NewQueue() *Queue {
+ return &Queue{
+ count: int64(0),
+ head: nil,
+ tail: nil,
+ mux: sync.Mutex{},
+ }
+}
diff --git a/plugins/icla/plugin_main.go b/plugins/icla/plugin_main.go
index e72f6bfb..57972adf 100644
--- a/plugins/icla/plugin_main.go
+++ b/plugins/icla/plugin_main.go
@@ -18,6 +18,8 @@ limitations under the License.
package main
import (
+ "fmt"
+
"github.com/apache/incubator-devlake/plugins/core"
"github.com/apache/incubator-devlake/plugins/icla/models"
"github.com/apache/incubator-devlake/plugins/icla/tasks"
@@ -33,6 +35,7 @@ var _ core.PluginMeta = (*Icla)(nil)
var _ core.PluginInit = (*Icla)(nil)
var _ core.PluginTask = (*Icla)(nil)
var _ core.PluginApi = (*Icla)(nil)
+var _ core.CloseablePluginTask = (*Icla)(nil)
// PluginEntry is a variable exported for Framework to search and load
var PluginEntry Icla //nolint
@@ -86,6 +89,15 @@ func (plugin Icla) ApiResources()
map[string]map[string]core.ApiResourceHandler
return nil
}
+func (plugin Icla) Close(taskCtx core.TaskContext) error {
+ data, ok := taskCtx.GetData().(*tasks.IclaTaskData)
+ if !ok {
+ return fmt.Errorf("GetData failed when try to close %+v",
taskCtx)
+ }
+ data.ApiClient.Release()
+ return nil
+}
+
// standalone mode for debugging
func main() {
cmd := &cobra.Command{Use: "icla"}
diff --git a/plugins/jenkins/e2e/jobs_test.go b/plugins/jenkins/e2e/jobs_test.go
index a8d1fe79..da0a9b8c 100644
--- a/plugins/jenkins/e2e/jobs_test.go
+++ b/plugins/jenkins/e2e/jobs_test.go
@@ -19,9 +19,10 @@ package e2e
import (
"fmt"
- "github.com/apache/incubator-devlake/models/domainlayer/devops"
"testing"
+ "github.com/apache/incubator-devlake/models/domainlayer/devops"
+
"github.com/apache/incubator-devlake/helpers/e2ehelper"
"github.com/apache/incubator-devlake/plugins/jenkins/impl"
"github.com/apache/incubator-devlake/plugins/jenkins/models"
@@ -51,6 +52,7 @@ func TestJenkinsJobsDataFlow(t *testing.T) {
[]string{
"connection_id",
"name",
+ "path",
"class",
"color",
"base",
diff --git a/plugins/jenkins/e2e/raw_tables/_raw_jenkins_api_builds.csv
b/plugins/jenkins/e2e/raw_tables/_raw_jenkins_api_builds.csv
index f5399bd1..250c8ce3 100644
--- a/plugins/jenkins/e2e/raw_tables/_raw_jenkins_api_builds.csv
+++ b/plugins/jenkins/e2e/raw_tables/_raw_jenkins_api_builds.csv
@@ -1,21 +1,9 @@
-"id","params","data","url","input","created_at"
-"1","{""ConnectionId"":1}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.ParametersAction""},{""_class"":""hudson.model.CauseAction""},{},{},{}],""displayName"":""#205"",""duration"":843,""estimatedDuration"":845,""number"":205,""result"":""SUCCESS"",""timestamp"":1647841830657,""changeSet"":{""_class"":""hudson.scm.EmptyChangeLogSet"",""kind"":null}}","https://jenkins.merico.cn/job/Create_License/api/json?tree=allBuilds%5Bnumber%2Ctimestamp%2Cdurat
[...]
-"2","{""ConnectionId"":1}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.ParametersAction""},{""_class"":""hudson.model.CauseAction""},{},{},{}],""displayName"":""#204"",""duration"":849,""estimatedDuration"":845,""number"":204,""result"":""SUCCESS"",""timestamp"":1645152359034,""changeSet"":{""_class"":""hudson.scm.EmptyChangeLogSet"",""kind"":null}}","https://jenkins.merico.cn/job/Create_License/api/json?tree=allBuilds%5Bnumber%2Ctimestamp%2Cdurat
[...]
-"3","{""ConnectionId"":1}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.ParametersAction""},{""_class"":""hudson.model.CauseAction""},{},{},{}],""displayName"":""#203"",""duration"":823,""estimatedDuration"":845,""number"":203,""result"":""SUCCESS"",""timestamp"":1642560020873,""changeSet"":{""_class"":""hudson.scm.EmptyChangeLogSet"",""kind"":null}}","https://jenkins.merico.cn/job/Create_License/api/json?tree=allBuilds%5Bnumber%2Ctimestamp%2Cdurat
[...]
-"4","{""ConnectionId"":1}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.ParametersAction""},{""_class"":""hudson.model.CauseAction""},{},{},{}],""displayName"":""#202"",""duration"":814,""estimatedDuration"":845,""number"":202,""result"":""SUCCESS"",""timestamp"":1641524412998,""changeSet"":{""_class"":""hudson.scm.EmptyChangeLogSet"",""kind"":null}}","https://jenkins.merico.cn/job/Create_License/api/json?tree=allBuilds%5Bnumber%2Ctimestamp%2Cdurat
[...]
-"5","{""ConnectionId"":1}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.ParametersAction""},{""_class"":""hudson.model.CauseAction""},{},{},{}],""displayName"":""#201"",""duration"":872,""estimatedDuration"":845,""number"":201,""result"":""SUCCESS"",""timestamp"":1641286809958,""changeSet"":{""_class"":""hudson.scm.EmptyChangeLogSet"",""kind"":null}}","https://jenkins.merico.cn/job/Create_License/api/json?tree=allBuilds%5Bnumber%2Ctimestamp%2Cdurat
[...]
-"6","{""ConnectionId"":1}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.ParametersAction""},{""_class"":""hudson.model.CauseAction""},{},{},{}],""displayName"":""#200"",""duration"":826,""estimatedDuration"":845,""number"":200,""result"":""SUCCESS"",""timestamp"":1638425697887,""changeSet"":{""_class"":""hudson.scm.EmptyChangeLogSet"",""kind"":null}}","https://jenkins.merico.cn/job/Create_License/api/json?tree=allBuilds%5Bnumber%2Ctimestamp%2Cdurat
[...]
-"7","{""ConnectionId"":1}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.ParametersAction""},{""_class"":""hudson.model.CauseAction""},{},{},{}],""displayName"":""#199"",""duration"":711,""estimatedDuration"":845,""number"":199,""result"":""FAILURE"",""timestamp"":1637636904142,""changeSet"":{""_class"":""hudson.scm.EmptyChangeLogSet"",""kind"":null}}","https://jenkins.merico.cn/job/Create_License/api/json?tree=allBuilds%5Bnumber%2Ctimestamp%2Cdurat
[...]
-"8","{""ConnectionId"":1}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.ParametersAction""},{""_class"":""hudson.model.CauseAction""},{},{},{}],""displayName"":""#198"",""duration"":855,""estimatedDuration"":845,""number"":198,""result"":""SUCCESS"",""timestamp"":1635842717468,""changeSet"":{""_class"":""hudson.scm.EmptyChangeLogSet"",""kind"":null}}","https://jenkins.merico.cn/job/Create_License/api/json?tree=allBuilds%5Bnumber%2Ctimestamp%2Cdurat
[...]
-"9","{""ConnectionId"":1}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.ParametersAction""},{""_class"":""hudson.model.CauseAction""},{},{},{}],""displayName"":""#197"",""duration"":806,""estimatedDuration"":845,""number"":197,""result"":""SUCCESS"",""timestamp"":1635143830616,""changeSet"":{""_class"":""hudson.scm.EmptyChangeLogSet"",""kind"":null}}","https://jenkins.merico.cn/job/Create_License/api/json?tree=allBuilds%5Bnumber%2Ctimestamp%2Cdurat
[...]
-"10","{""ConnectionId"":1}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.ParametersAction""},{""_class"":""hudson.model.CauseAction""},{},{},{}],""displayName"":""#196"",""duration"":840,""estimatedDuration"":845,""number"":196,""result"":""SUCCESS"",""timestamp"":1634713846944,""changeSet"":{""_class"":""hudson.scm.EmptyChangeLogSet"",""kind"":null}}","https://jenkins.merico.cn/job/Create_License/api/json?tree=allBuilds%5Bnumber%2Ctimestamp%2Cdura
[...]
-"11","{""ConnectionId"":1}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.ParametersAction""},{""_class"":""hudson.model.CauseAction""},{},{},{}],""displayName"":""#195"",""duration"":756,""estimatedDuration"":845,""number"":195,""result"":""SUCCESS"",""timestamp"":1634289009179,""changeSet"":{""_class"":""hudson.scm.EmptyChangeLogSet"",""kind"":null}}","https://jenkins.merico.cn/job/Create_License/api/json?tree=allBuilds%5Bnumber%2Ctimestamp%2Cdura
[...]
-"12","{""ConnectionId"":1}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.ParametersAction""},{""_class"":""hudson.model.CauseAction""},{},{},{}],""displayName"":""#194"",""duration"":735,""estimatedDuration"":845,""number"":194,""result"":""SUCCESS"",""timestamp"":1634111680194,""changeSet"":{""_class"":""hudson.scm.EmptyChangeLogSet"",""kind"":null}}","https://jenkins.merico.cn/job/Create_License/api/json?tree=allBuilds%5Bnumber%2Ctimestamp%2Cdura
[...]
-"13","{""ConnectionId"":1}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.ParametersAction""},{""_class"":""hudson.model.CauseAction""},{},{},{}],""displayName"":""#193"",""duration"":805,""estimatedDuration"":845,""number"":193,""result"":""SUCCESS"",""timestamp"":1634108932844,""changeSet"":{""_class"":""hudson.scm.EmptyChangeLogSet"",""kind"":null}}","https://jenkins.merico.cn/job/Create_License/api/json?tree=allBuilds%5Bnumber%2Ctimestamp%2Cdura
[...]
-"14","{""ConnectionId"":1}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.ParametersAction""},{""_class"":""hudson.model.CauseAction""},{},{},{}],""displayName"":""#192"",""duration"":776,""estimatedDuration"":845,""number"":192,""result"":""SUCCESS"",""timestamp"":1631935845537,""changeSet"":{""_class"":""hudson.scm.EmptyChangeLogSet"",""kind"":null}}","https://jenkins.merico.cn/job/Create_License/api/json?tree=allBuilds%5Bnumber%2Ctimestamp%2Cdura
[...]
-"15","{""ConnectionId"":1}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.ParametersAction""},{""_class"":""hudson.model.CauseAction""},{},{},{}],""displayName"":""#191"",""duration"":833,""estimatedDuration"":845,""number"":191,""result"":""SUCCESS"",""timestamp"":1631237966948,""changeSet"":{""_class"":""hudson.scm.EmptyChangeLogSet"",""kind"":null}}","https://jenkins.merico.cn/job/Create_License/api/json?tree=allBuilds%5Bnumber%2Ctimestamp%2Cdura
[...]
-"16","{""ConnectionId"":1}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.ParametersAction""},{""_class"":""hudson.model.CauseAction""},{},{},{}],""displayName"":""#190"",""duration"":819,""estimatedDuration"":845,""number"":190,""result"":""SUCCESS"",""timestamp"":1631000546032,""changeSet"":{""_class"":""hudson.scm.EmptyChangeLogSet"",""kind"":null}}","https://jenkins.merico.cn/job/Create_License/api/json?tree=allBuilds%5Bnumber%2Ctimestamp%2Cdura
[...]
-"17","{""ConnectionId"":1}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.ParametersAction""},{""_class"":""hudson.model.CauseAction""},{},{},{}],""displayName"":""#189"",""duration"":785,""estimatedDuration"":845,""number"":189,""result"":""SUCCESS"",""timestamp"":1630632234339,""changeSet"":{""_class"":""hudson.scm.EmptyChangeLogSet"",""kind"":null}}","https://jenkins.merico.cn/job/Create_License/api/json?tree=allBuilds%5Bnumber%2Ctimestamp%2Cdura
[...]
-"18","{""ConnectionId"":1}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.ParametersAction""},{""_class"":""hudson.model.CauseAction""},{},{},{}],""displayName"":""#188"",""duration"":752,""estimatedDuration"":845,""number"":188,""result"":""SUCCESS"",""timestamp"":1629169239734,""changeSet"":{""_class"":""hudson.scm.EmptyChangeLogSet"",""kind"":null}}","https://jenkins.merico.cn/job/Create_License/api/json?tree=allBuilds%5Bnumber%2Ctimestamp%2Cdura
[...]
-"19","{""ConnectionId"":1}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.ParametersAction""},{""_class"":""hudson.model.CauseAction""},{},{},{}],""displayName"":""#187"",""duration"":822,""estimatedDuration"":845,""number"":187,""result"":""SUCCESS"",""timestamp"":1628838712486,""changeSet"":{""_class"":""hudson.scm.EmptyChangeLogSet"",""kind"":null}}","https://jenkins.merico.cn/job/Create_License/api/json?tree=allBuilds%5Bnumber%2Ctimestamp%2Cdura
[...]
-"20","{""ConnectionId"":1}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.ParametersAction""},{""_class"":""hudson.model.CauseAction""},{},{},{}],""displayName"":""#186"",""duration"":725,""estimatedDuration"":845,""number"":186,""result"":""SUCCESS"",""timestamp"":1628674732761,""changeSet"":{""_class"":""hudson.scm.EmptyChangeLogSet"",""kind"":null}}","https://jenkins.merico.cn/job/Create_License/api/json?tree=allBuilds%5Bnumber%2Ctimestamp%2Cdura
[...]
\ No newline at end of file
+"id","params","data","url","input","created_at"
+75,"{""ConnectionId"":1}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.CauseAction""},{},{""_class"":""org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction""}],""displayName"":""#8"",""duration"":11,""estimatedDuration"":10,""number"":8,""result"":""SUCCESS"",""timestamp"":1650023894336,""changeSet"":{""_class"":""hudson.scm.EmptyChangeLogSet"",""kind"":null}}","https://test.nddtf.com/job/%E8%BF%99%E6%98%AF%E4%B8%80%E4%B8%AA%E6%94%B9%E4%BA%
[...]
+76,"{""ConnectionId"":1}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.CauseAction""},{},{""_class"":""org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction""}],""displayName"":""#7"",""duration"":8,""estimatedDuration"":10,""number"":7,""result"":""SUCCESS"",""timestamp"":1650023883294,""changeSet"":{""_class"":""hudson.scm.EmptyChangeLogSet"",""kind"":null}}","https://test.nddtf.com/job/%E8%BF%99%E6%98%AF%E4%B8%80%E4%B8%AA%E6%94%B9%E4%BA%8
[...]
+77,"{""ConnectionId"":1}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.CauseAction""},{},{""_class"":""org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction""}],""displayName"":""#6"",""duration"":10,""estimatedDuration"":10,""number"":6,""result"":""SUCCESS"",""timestamp"":1650022560954,""changeSet"":{""_class"":""hudson.scm.EmptyChangeLogSet"",""kind"":null}}","https://test.nddtf.com/job/%E8%BF%99%E6%98%AF%E4%B8%80%E4%B8%AA%E6%94%B9%E4%BA%
[...]
+78,"{""ConnectionId"":1}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.CauseAction""},{},{""_class"":""org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction""}],""displayName"":""#5"",""duration"":6,""estimatedDuration"":10,""number"":5,""result"":""SUCCESS"",""timestamp"":1650022558491,""changeSet"":{""_class"":""hudson.scm.EmptyChangeLogSet"",""kind"":null}}","https://test.nddtf.com/job/%E8%BF%99%E6%98%AF%E4%B8%80%E4%B8%AA%E6%94%B9%E4%BA%8
[...]
+79,"{""ConnectionId"":1}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.CauseAction""},{},{""_class"":""org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction""}],""displayName"":""#4"",""duration"":6,""estimatedDuration"":10,""number"":4,""result"":""SUCCESS"",""timestamp"":1650022556910,""changeSet"":{""_class"":""hudson.scm.EmptyChangeLogSet"",""kind"":null}}","https://test.nddtf.com/job/%E8%BF%99%E6%98%AF%E4%B8%80%E4%B8%AA%E6%94%B9%E4%BA%8
[...]
+80,"{""ConnectionId"":1}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.CauseAction""},{},{""_class"":""org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction""}],""displayName"":""#3"",""duration"":3,""estimatedDuration"":10,""number"":3,""result"":""SUCCESS"",""timestamp"":1650017186253,""changeSet"":{""_class"":""hudson.scm.EmptyChangeLogSet"",""kind"":null}}","https://test.nddtf.com/job/%E8%BF%99%E6%98%AF%E4%B8%80%E4%B8%AA%E6%94%B9%E4%BA%8
[...]
+81,"{""ConnectionId"":1}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.CauseAction""},{},{""_class"":""org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction""}],""displayName"":""#2"",""duration"":4,""estimatedDuration"":10,""number"":2,""result"":""SUCCESS"",""timestamp"":1650017177939,""changeSet"":{""_class"":""hudson.scm.EmptyChangeLogSet"",""kind"":null}}","https://test.nddtf.com/job/%E8%BF%99%E6%98%AF%E4%B8%80%E4%B8%AA%E6%94%B9%E4%BA%8
[...]
+82,"{""ConnectionId"":1}","{""_class"":""hudson.model.FreeStyleBuild"",""actions"":[{""_class"":""hudson.model.CauseAction""},{},{""_class"":""org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction""}],""displayName"":""#1"",""duration"":57,""estimatedDuration"":10,""number"":1,""result"":""SUCCESS"",""timestamp"":1650017153775,""changeSet"":{""_class"":""hudson.scm.EmptyChangeLogSet"",""kind"":null}}","https://test.nddtf.com/job/%E8%BF%99%E6%98%AF%E4%B8%80%E4%B8%AA%E6%94%B9%E4%BA%
[...]
diff --git a/plugins/jenkins/e2e/raw_tables/_raw_jenkins_api_jobs.csv
b/plugins/jenkins/e2e/raw_tables/_raw_jenkins_api_jobs.csv
index b4e45e6a..a8178b2b 100644
--- a/plugins/jenkins/e2e/raw_tables/_raw_jenkins_api_jobs.csv
+++ b/plugins/jenkins/e2e/raw_tables/_raw_jenkins_api_jobs.csv
@@ -1,12 +1,9 @@
-"id","params","data","url","input","created_at"
-"1","{""ConnectionId"":1}","{""_class"":""hudson.model.FreeStyleProject"",""name"":""auto_test"",""color"":""blue""}","https://jenkins.merico.cn/api/json?tree=jobs%5Bname%2Cclass%2Ccolor%2Cbase%5D%7B1%2C100%7D","null","2022-06-15
15:24:40.697"
-"2","{""ConnectionId"":1}","{""_class"":""hudson.model.FreeStyleProject"",""name"":""auto_test_framework"",""color"":""disabled""}","https://jenkins.merico.cn/api/json?tree=jobs%5Bname%2Cclass%2Ccolor%2Cbase%5D%7B1%2C100%7D","null","2022-06-15
15:24:40.697"
-"3","{""ConnectionId"":1}","{""_class"":""hudson.model.FreeStyleProject"",""name"":""build_devlake"",""color"":""blue""}","https://jenkins.merico.cn/api/json?tree=jobs%5Bname%2Cclass%2Ccolor%2Cbase%5D%7B1%2C100%7D","null","2022-06-15
15:24:40.697"
-"4","{""ConnectionId"":1}","{""_class"":""hudson.model.FreeStyleProject"",""name"":""Create_License"",""color"":""blue""}","https://jenkins.merico.cn/api/json?tree=jobs%5Bname%2Cclass%2Ccolor%2Cbase%5D%7B1%2C100%7D","null","2022-06-15
15:24:40.697"
-"5","{""ConnectionId"":1}","{""_class"":""hudson.model.FreeStyleProject"",""name"":""Create_License_new"",""color"":""blue""}","https://jenkins.merico.cn/api/json?tree=jobs%5Bname%2Cclass%2Ccolor%2Cbase%5D%7B1%2C100%7D","null","2022-06-15
15:24:40.697"
-"6","{""ConnectionId"":1}","{""_class"":""hudson.model.FreeStyleProject"",""name"":""Deploy
k8s
single_data"",""color"":""blue""}","https://jenkins.merico.cn/api/json?tree=jobs%5Bname%2Cclass%2Ccolor%2Cbase%5D%7B1%2C100%7D","null","2022-06-15
15:24:40.697"
-"7","{""ConnectionId"":1}","{""_class"":""hudson.model.FreeStyleProject"",""name"":""Deploy
k8s
single_new"",""color"":""blue""}","https://jenkins.merico.cn/api/json?tree=jobs%5Bname%2Cclass%2Ccolor%2Cbase%5D%7B1%2C100%7D","null","2022-06-15
15:24:40.697"
-"8","{""ConnectionId"":1}","{""_class"":""hudson.model.FreeStyleProject"",""name"":""Deploy
k8s
test"",""color"":""blue""}","https://jenkins.merico.cn/api/json?tree=jobs%5Bname%2Cclass%2Ccolor%2Cbase%5D%7B1%2C100%7D","null","2022-06-15
15:24:40.697"
-"9","{""ConnectionId"":1}","{""_class"":""hudson.model.FreeStyleProject"",""name"":""devlake_empty_build"",""color"":""blue""}","https://jenkins.merico.cn/api/json?tree=jobs%5Bname%2Cclass%2Ccolor%2Cbase%5D%7B1%2C100%7D","null","2022-06-15
15:24:40.697"
-"10","{""ConnectionId"":1}","{""_class"":""org.jenkinsci.plugins.workflow.job.WorkflowJob"",""name"":""test-platform-backend"",""color"":""blue""}","https://jenkins.merico.cn/api/json?tree=jobs%5Bname%2Cclass%2Ccolor%2Cbase%5D%7B1%2C100%7D","null","2022-06-15
15:24:40.697"
-"11","{""ConnectionId"":1}","{""_class"":""org.jenkinsci.plugins.workflow.job.WorkflowJob"",""name"":""test-platform-frontend"",""color"":""blue""}","https://jenkins.merico.cn/api/json?tree=jobs%5Bname%2Cclass%2Ccolor%2Cbase%5D%7B1%2C100%7D","null","2022-06-15
15:24:40.697"
+"id","params","data","url","input","created_at"
+12,"{""ConnectionId"":1}","{""_class"":""hudson.model.FreeStyleProject"",""name"":""devlake"",""url"":""https://test.nddtf.com/job/devlake/"",""color"":""blue""}","https://test.nddtf.com/api/json?tree=jobs%5Bname%2Cclass%2Curl%2Ccolor%2Cbase%2Cjobs%5D%7B0%2C100%7D","{""Path"":
""""}","2022-07-13 02:22:34.044"
+13,"{""ConnectionId"":1}","{""_class"":""com.cloudbees.hudson.plugins.folder.Folder"",""name"":""dir-test"",""url"":""https://test.nddtf.com/job/dir-test/"",""jobs"":[{""_class"":""com.cloudbees.hudson.plugins.folder.Folder""},{""_class"":""org.jenkinsci.plugins.workflow.job.WorkflowJob""},{""_class"":""hudson.model.FreeStyleProject""}]}","https://test.nddtf.com/api/json?tree=jobs%5Bname%2Cclass%2Curl%2Ccolor%2Cbase%2Cjobs%5D%7B0%2C100%7D","{""Path"":
""""}","2022-07-13 02:22:34.044"
+14,"{""ConnectionId"":1}","{""_class"":""org.jenkinsci.plugins.workflow.job.WorkflowJob"",""name"":""测试流水线"",""url"":""https://test.nddtf.com/job/%E6%B5%8B%E8%AF%95%E6%B5%81%E6%B0%B4%E7%BA%BF/"",""color"":""notbuilt""}","https://test.nddtf.com/api/json?tree=jobs%5Bname%2Cclass%2Curl%2Ccolor%2Cbase%2Cjobs%5D%7B0%2C100%7D","{""Path"":
""""}","2022-07-13 02:22:34.044"
+15,"{""ConnectionId"":1}","{""_class"":""hudson.model.FreeStyleProject"",""name"":""这是一个改了名字的测试任务"",""url"":""https://test.nddtf.com/job/%E8%BF%99%E6%98%AF%E4%B8%80%E4%B8%AA%E6%94%B9%E4%BA%86%E5%90%8D%E5%AD%97%E7%9A%84%E6%B5%8B%E8%AF%95%E4%BB%BB%E5%8A%A1/"",""color"":""blue""}","https://test.nddtf.com/api/json?tree=jobs%5Bname%2Cclass%2Curl%2Ccolor%2Cbase%2Cjobs%5D%7B0%2C100%7D","{""Path"":
""""}","2022-07-13 02:22:34.044"
+16,"{""ConnectionId"":1}","{""_class"":""com.cloudbees.hudson.plugins.folder.Folder"",""name"":""dir-test-2"",""url"":""https://test.nddtf.com/job/dir-test/job/dir-test-2/"",""jobs"":[{""_class"":""hudson.model.FreeStyleProject""}]}","https://test.nddtf.com/job/dir-test/api/json?tree=jobs%5Bname%2Cclass%2Curl%2Ccolor%2Cbase%2Cjobs%5D%7B0%2C100%7D","{""Path"":
""job/dir-test/""}","2022-07-13 02:22:34.178"
+17,"{""ConnectionId"":1}","{""_class"":""org.jenkinsci.plugins.workflow.job.WorkflowJob"",""name"":""pipeline-test"",""url"":""https://test.nddtf.com/job/dir-test/job/pipeline-test/"",""color"":""notbuilt""}","https://test.nddtf.com/job/dir-test/api/json?tree=jobs%5Bname%2Cclass%2Curl%2Ccolor%2Cbase%2Cjobs%5D%7B0%2C100%7D","{""Path"":
""job/dir-test/""}","2022-07-13 02:22:34.178"
+18,"{""ConnectionId"":1}","{""_class"":""hudson.model.FreeStyleProject"",""name"":""testfile"",""url"":""https://test.nddtf.com/job/dir-test/job/testfile/"",""color"":""notbuilt""}","https://test.nddtf.com/job/dir-test/api/json?tree=jobs%5Bname%2Cclass%2Curl%2Ccolor%2Cbase%2Cjobs%5D%7B0%2C100%7D","{""Path"":
""job/dir-test/""}","2022-07-13 02:22:34.178"
+19,"{""ConnectionId"":1}","{""_class"":""hudson.model.FreeStyleProject"",""name"":""free"",""url"":""https://test.nddtf.com/job/dir-test/job/dir-test-2/job/free/"",""color"":""notbuilt""}","https://test.nddtf.com/job/dir-test/job/dir-test-2/api/json?tree=jobs%5Bname%2Cclass%2Curl%2Ccolor%2Cbase%2Cjobs%5D%7B0%2C100%7D","{""Path"":
""job/dir-test/job/dir-test-2/""}","2022-07-13 02:22:34.500"
diff --git a/plugins/jenkins/e2e/snapshot_tables/_tool_jenkins_builds.csv
b/plugins/jenkins/e2e/snapshot_tables/_tool_jenkins_builds.csv
index 9a5c5a04..b61c1434 100644
--- a/plugins/jenkins/e2e/snapshot_tables/_tool_jenkins_builds.csv
+++ b/plugins/jenkins/e2e/snapshot_tables/_tool_jenkins_builds.csv
@@ -1,21 +1,9 @@
-connection_id,job_name,number,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark,connection_id,job_name,duration,display_name,estimated_duration,number,result,timestamp,start_time,commit_sha
-1,Create_License,186,"{""ConnectionId"":1}",_raw_jenkins_api_builds,20,,1,Create_License,725,#186,845,186,SUCCESS,1628674732761,2021-08-11T09:38:52.000+00:00,
-1,Create_License,187,"{""ConnectionId"":1}",_raw_jenkins_api_builds,19,,1,Create_License,822,#187,845,187,SUCCESS,1628838712486,2021-08-13T07:11:52.000+00:00,
-1,Create_License,188,"{""ConnectionId"":1}",_raw_jenkins_api_builds,18,,1,Create_License,752,#188,845,188,SUCCESS,1629169239734,2021-08-17T03:00:39.000+00:00,
-1,Create_License,189,"{""ConnectionId"":1}",_raw_jenkins_api_builds,17,,1,Create_License,785,#189,845,189,SUCCESS,1630632234339,2021-09-03T01:23:54.000+00:00,
-1,Create_License,190,"{""ConnectionId"":1}",_raw_jenkins_api_builds,16,,1,Create_License,819,#190,845,190,SUCCESS,1631000546032,2021-09-07T07:42:26.000+00:00,
-1,Create_License,191,"{""ConnectionId"":1}",_raw_jenkins_api_builds,15,,1,Create_License,833,#191,845,191,SUCCESS,1631237966948,2021-09-10T01:39:26.000+00:00,
-1,Create_License,192,"{""ConnectionId"":1}",_raw_jenkins_api_builds,14,,1,Create_License,776,#192,845,192,SUCCESS,1631935845537,2021-09-18T03:30:45.000+00:00,
-1,Create_License,193,"{""ConnectionId"":1}",_raw_jenkins_api_builds,13,,1,Create_License,805,#193,845,193,SUCCESS,1634108932844,2021-10-13T07:08:52.000+00:00,
-1,Create_License,194,"{""ConnectionId"":1}",_raw_jenkins_api_builds,12,,1,Create_License,735,#194,845,194,SUCCESS,1634111680194,2021-10-13T07:54:40.000+00:00,
-1,Create_License,195,"{""ConnectionId"":1}",_raw_jenkins_api_builds,11,,1,Create_License,756,#195,845,195,SUCCESS,1634289009179,2021-10-15T09:10:09.000+00:00,
-1,Create_License,196,"{""ConnectionId"":1}",_raw_jenkins_api_builds,10,,1,Create_License,840,#196,845,196,SUCCESS,1634713846944,2021-10-20T07:10:46.000+00:00,
-1,Create_License,197,"{""ConnectionId"":1}",_raw_jenkins_api_builds,9,,1,Create_License,806,#197,845,197,SUCCESS,1635143830616,2021-10-25T06:37:10.000+00:00,
-1,Create_License,198,"{""ConnectionId"":1}",_raw_jenkins_api_builds,8,,1,Create_License,855,#198,845,198,SUCCESS,1635842717468,2021-11-02T08:45:17.000+00:00,
-1,Create_License,199,"{""ConnectionId"":1}",_raw_jenkins_api_builds,7,,1,Create_License,711,#199,845,199,FAILURE,1637636904142,2021-11-23T03:08:24.000+00:00,
-1,Create_License,200,"{""ConnectionId"":1}",_raw_jenkins_api_builds,6,,1,Create_License,826,#200,845,200,SUCCESS,1638425697887,2021-12-02T06:14:57.000+00:00,
-1,Create_License,201,"{""ConnectionId"":1}",_raw_jenkins_api_builds,5,,1,Create_License,872,#201,845,201,SUCCESS,1641286809958,2022-01-04T09:00:09.000+00:00,
-1,Create_License,202,"{""ConnectionId"":1}",_raw_jenkins_api_builds,4,,1,Create_License,814,#202,845,202,SUCCESS,1641524412998,2022-01-07T03:00:12.000+00:00,
-1,Create_License,203,"{""ConnectionId"":1}",_raw_jenkins_api_builds,3,,1,Create_License,823,#203,845,203,SUCCESS,1642560020873,2022-01-19T02:40:20.000+00:00,
-1,Create_License,204,"{""ConnectionId"":1}",_raw_jenkins_api_builds,2,,1,Create_License,849,#204,845,204,SUCCESS,1645152359034,2022-02-18T02:45:59.000+00:00,
-1,Create_License,205,"{""ConnectionId"":1}",_raw_jenkins_api_builds,1,,1,Create_License,843,#205,845,205,SUCCESS,1647841830657,2022-03-21T05:50:30.000+00:00,
+connection_id,job_name,number,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark,duration,display_name,estimated_duration,result,timestamp,start_time,commit_sha
+1,这是一个改了名字的测试任务,1,"{""ConnectionId"":1}",_raw_jenkins_api_builds,82,,57,#1,10,SUCCESS,1650017153775,2022-04-15T10:05:53.000+00:00,
+1,这是一个改了名字的测试任务,2,"{""ConnectionId"":1}",_raw_jenkins_api_builds,81,,4,#2,10,SUCCESS,1650017177939,2022-04-15T10:06:17.000+00:00,
+1,这是一个改了名字的测试任务,3,"{""ConnectionId"":1}",_raw_jenkins_api_builds,80,,3,#3,10,SUCCESS,1650017186253,2022-04-15T10:06:26.000+00:00,
+1,这是一个改了名字的测试任务,4,"{""ConnectionId"":1}",_raw_jenkins_api_builds,79,,6,#4,10,SUCCESS,1650022556910,2022-04-15T11:35:56.000+00:00,
+1,这是一个改了名字的测试任务,5,"{""ConnectionId"":1}",_raw_jenkins_api_builds,78,,6,#5,10,SUCCESS,1650022558491,2022-04-15T11:35:58.000+00:00,
+1,这是一个改了名字的测试任务,6,"{""ConnectionId"":1}",_raw_jenkins_api_builds,77,,10,#6,10,SUCCESS,1650022560954,2022-04-15T11:36:00.000+00:00,
+1,这是一个改了名字的测试任务,7,"{""ConnectionId"":1}",_raw_jenkins_api_builds,76,,8,#7,10,SUCCESS,1650023883294,2022-04-15T11:58:03.000+00:00,
+1,这是一个改了名字的测试任务,8,"{""ConnectionId"":1}",_raw_jenkins_api_builds,75,,11,#8,10,SUCCESS,1650023894336,2022-04-15T11:58:14.000+00:00,
diff --git a/plugins/jenkins/e2e/snapshot_tables/_tool_jenkins_jobs.csv
b/plugins/jenkins/e2e/snapshot_tables/_tool_jenkins_jobs.csv
index 5cbe8dda..4b3db8a0 100644
--- a/plugins/jenkins/e2e/snapshot_tables/_tool_jenkins_jobs.csv
+++ b/plugins/jenkins/e2e/snapshot_tables/_tool_jenkins_jobs.csv
@@ -1,12 +1,9 @@
-connection_id,name,class,color,base,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark
-1,auto_test,hudson.model.FreeStyleProject,blue,,"{""ConnectionId"":1}",_raw_jenkins_api_jobs,1,
-1,auto_test_framework,hudson.model.FreeStyleProject,disabled,,"{""ConnectionId"":1}",_raw_jenkins_api_jobs,2,
-1,build_devlake,hudson.model.FreeStyleProject,blue,,"{""ConnectionId"":1}",_raw_jenkins_api_jobs,3,
-1,Create_License,hudson.model.FreeStyleProject,blue,,"{""ConnectionId"":1}",_raw_jenkins_api_jobs,4,
-1,Create_License_new,hudson.model.FreeStyleProject,blue,,"{""ConnectionId"":1}",_raw_jenkins_api_jobs,5,
-1,Deploy k8s
single_data,hudson.model.FreeStyleProject,blue,,"{""ConnectionId"":1}",_raw_jenkins_api_jobs,6,
-1,Deploy k8s
single_new,hudson.model.FreeStyleProject,blue,,"{""ConnectionId"":1}",_raw_jenkins_api_jobs,7,
-1,Deploy k8s
test,hudson.model.FreeStyleProject,blue,,"{""ConnectionId"":1}",_raw_jenkins_api_jobs,8,
-1,devlake_empty_build,hudson.model.FreeStyleProject,blue,,"{""ConnectionId"":1}",_raw_jenkins_api_jobs,9,
-1,test-platform-backend,org.jenkinsci.plugins.workflow.job.WorkflowJob,blue,,"{""ConnectionId"":1}",_raw_jenkins_api_jobs,10,
-1,test-platform-frontend,org.jenkinsci.plugins.workflow.job.WorkflowJob,blue,,"{""ConnectionId"":1}",_raw_jenkins_api_jobs,11,
+connection_id,name,path,class,color,base,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark
+1,devlake,,hudson.model.FreeStyleProject,blue,,"{""ConnectionId"":1}",_raw_jenkins_api_jobs,12,
+1,dir-test,,com.cloudbees.hudson.plugins.folder.Folder,,,"{""ConnectionId"":1}",_raw_jenkins_api_jobs,13,
+1,dir-test-2,job/dir-test/,com.cloudbees.hudson.plugins.folder.Folder,,,"{""ConnectionId"":1}",_raw_jenkins_api_jobs,16,
+1,free,job/dir-test/job/dir-test-2/,hudson.model.FreeStyleProject,notbuilt,,"{""ConnectionId"":1}",_raw_jenkins_api_jobs,19,
+1,pipeline-test,job/dir-test/,org.jenkinsci.plugins.workflow.job.WorkflowJob,notbuilt,,"{""ConnectionId"":1}",_raw_jenkins_api_jobs,17,
+1,testfile,job/dir-test/,hudson.model.FreeStyleProject,notbuilt,,"{""ConnectionId"":1}",_raw_jenkins_api_jobs,18,
+1,测试流水线,,org.jenkinsci.plugins.workflow.job.WorkflowJob,notbuilt,,"{""ConnectionId"":1}",_raw_jenkins_api_jobs,14,
+1,这是一个改了名字的测试任务,,hudson.model.FreeStyleProject,blue,,"{""ConnectionId"":1}",_raw_jenkins_api_jobs,15,
diff --git a/plugins/jenkins/e2e/snapshot_tables/builds.csv
b/plugins/jenkins/e2e/snapshot_tables/builds.csv
index f3dca0fa..38476b9b 100644
--- a/plugins/jenkins/e2e/snapshot_tables/builds.csv
+++ b/plugins/jenkins/e2e/snapshot_tables/builds.csv
@@ -1,21 +1,9 @@
id,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark,job_id,name,commit_sha,duration_sec,status,started_date
-jenkins:JenkinsBuild:1:Create_License:186,"{""ConnectionId"":1}",_raw_jenkins_api_builds,20,,jenkins:JenkinsJob:1:Create_License,#186,,0,SUCCESS,2021-08-11T09:38:52.000+00:00
-jenkins:JenkinsBuild:1:Create_License:187,"{""ConnectionId"":1}",_raw_jenkins_api_builds,19,,jenkins:JenkinsJob:1:Create_License,#187,,0,SUCCESS,2021-08-13T07:11:52.000+00:00
-jenkins:JenkinsBuild:1:Create_License:188,"{""ConnectionId"":1}",_raw_jenkins_api_builds,18,,jenkins:JenkinsJob:1:Create_License,#188,,0,SUCCESS,2021-08-17T03:00:39.000+00:00
-jenkins:JenkinsBuild:1:Create_License:189,"{""ConnectionId"":1}",_raw_jenkins_api_builds,17,,jenkins:JenkinsJob:1:Create_License,#189,,0,SUCCESS,2021-09-03T01:23:54.000+00:00
-jenkins:JenkinsBuild:1:Create_License:190,"{""ConnectionId"":1}",_raw_jenkins_api_builds,16,,jenkins:JenkinsJob:1:Create_License,#190,,0,SUCCESS,2021-09-07T07:42:26.000+00:00
-jenkins:JenkinsBuild:1:Create_License:191,"{""ConnectionId"":1}",_raw_jenkins_api_builds,15,,jenkins:JenkinsJob:1:Create_License,#191,,0,SUCCESS,2021-09-10T01:39:26.000+00:00
-jenkins:JenkinsBuild:1:Create_License:192,"{""ConnectionId"":1}",_raw_jenkins_api_builds,14,,jenkins:JenkinsJob:1:Create_License,#192,,0,SUCCESS,2021-09-18T03:30:45.000+00:00
-jenkins:JenkinsBuild:1:Create_License:193,"{""ConnectionId"":1}",_raw_jenkins_api_builds,13,,jenkins:JenkinsJob:1:Create_License,#193,,0,SUCCESS,2021-10-13T07:08:52.000+00:00
-jenkins:JenkinsBuild:1:Create_License:194,"{""ConnectionId"":1}",_raw_jenkins_api_builds,12,,jenkins:JenkinsJob:1:Create_License,#194,,0,SUCCESS,2021-10-13T07:54:40.000+00:00
-jenkins:JenkinsBuild:1:Create_License:195,"{""ConnectionId"":1}",_raw_jenkins_api_builds,11,,jenkins:JenkinsJob:1:Create_License,#195,,0,SUCCESS,2021-10-15T09:10:09.000+00:00
-jenkins:JenkinsBuild:1:Create_License:196,"{""ConnectionId"":1}",_raw_jenkins_api_builds,10,,jenkins:JenkinsJob:1:Create_License,#196,,0,SUCCESS,2021-10-20T07:10:46.000+00:00
-jenkins:JenkinsBuild:1:Create_License:197,"{""ConnectionId"":1}",_raw_jenkins_api_builds,9,,jenkins:JenkinsJob:1:Create_License,#197,,0,SUCCESS,2021-10-25T06:37:10.000+00:00
-jenkins:JenkinsBuild:1:Create_License:198,"{""ConnectionId"":1}",_raw_jenkins_api_builds,8,,jenkins:JenkinsJob:1:Create_License,#198,,0,SUCCESS,2021-11-02T08:45:17.000+00:00
-jenkins:JenkinsBuild:1:Create_License:199,"{""ConnectionId"":1}",_raw_jenkins_api_builds,7,,jenkins:JenkinsJob:1:Create_License,#199,,0,FAILURE,2021-11-23T03:08:24.000+00:00
-jenkins:JenkinsBuild:1:Create_License:200,"{""ConnectionId"":1}",_raw_jenkins_api_builds,6,,jenkins:JenkinsJob:1:Create_License,#200,,0,SUCCESS,2021-12-02T06:14:57.000+00:00
-jenkins:JenkinsBuild:1:Create_License:201,"{""ConnectionId"":1}",_raw_jenkins_api_builds,5,,jenkins:JenkinsJob:1:Create_License,#201,,0,SUCCESS,2022-01-04T09:00:09.000+00:00
-jenkins:JenkinsBuild:1:Create_License:202,"{""ConnectionId"":1}",_raw_jenkins_api_builds,4,,jenkins:JenkinsJob:1:Create_License,#202,,0,SUCCESS,2022-01-07T03:00:12.000+00:00
-jenkins:JenkinsBuild:1:Create_License:203,"{""ConnectionId"":1}",_raw_jenkins_api_builds,3,,jenkins:JenkinsJob:1:Create_License,#203,,0,SUCCESS,2022-01-19T02:40:20.000+00:00
-jenkins:JenkinsBuild:1:Create_License:204,"{""ConnectionId"":1}",_raw_jenkins_api_builds,2,,jenkins:JenkinsJob:1:Create_License,#204,,0,SUCCESS,2022-02-18T02:45:59.000+00:00
-jenkins:JenkinsBuild:1:Create_License:205,"{""ConnectionId"":1}",_raw_jenkins_api_builds,1,,jenkins:JenkinsJob:1:Create_License,#205,,0,SUCCESS,2022-03-21T05:50:30.000+00:00
+jenkins:JenkinsBuild:1:这是一个改了名字的测试任务:1,"{""ConnectionId"":1}",_raw_jenkins_api_builds,82,,jenkins:JenkinsJob:1:这是一个改了名字的测试任务,#1,,0,SUCCESS,2022-04-15T10:05:53.000+00:00
+jenkins:JenkinsBuild:1:这是一个改了名字的测试任务:2,"{""ConnectionId"":1}",_raw_jenkins_api_builds,81,,jenkins:JenkinsJob:1:这是一个改了名字的测试任务,#2,,0,SUCCESS,2022-04-15T10:06:17.000+00:00
+jenkins:JenkinsBuild:1:这是一个改了名字的测试任务:3,"{""ConnectionId"":1}",_raw_jenkins_api_builds,80,,jenkins:JenkinsJob:1:这是一个改了名字的测试任务,#3,,0,SUCCESS,2022-04-15T10:06:26.000+00:00
+jenkins:JenkinsBuild:1:这是一个改了名字的测试任务:4,"{""ConnectionId"":1}",_raw_jenkins_api_builds,79,,jenkins:JenkinsJob:1:这是一个改了名字的测试任务,#4,,0,SUCCESS,2022-04-15T11:35:56.000+00:00
+jenkins:JenkinsBuild:1:这是一个改了名字的测试任务:5,"{""ConnectionId"":1}",_raw_jenkins_api_builds,78,,jenkins:JenkinsJob:1:这是一个改了名字的测试任务,#5,,0,SUCCESS,2022-04-15T11:35:58.000+00:00
+jenkins:JenkinsBuild:1:这是一个改了名字的测试任务:6,"{""ConnectionId"":1}",_raw_jenkins_api_builds,77,,jenkins:JenkinsJob:1:这是一个改了名字的测试任务,#6,,0,SUCCESS,2022-04-15T11:36:00.000+00:00
+jenkins:JenkinsBuild:1:这是一个改了名字的测试任务:7,"{""ConnectionId"":1}",_raw_jenkins_api_builds,76,,jenkins:JenkinsJob:1:这是一个改了名字的测试任务,#7,,0,SUCCESS,2022-04-15T11:58:03.000+00:00
+jenkins:JenkinsBuild:1:这是一个改了名字的测试任务:8,"{""ConnectionId"":1}",_raw_jenkins_api_builds,75,,jenkins:JenkinsJob:1:这是一个改了名字的测试任务,#8,,0,SUCCESS,2022-04-15T11:58:14.000+00:00
diff --git a/plugins/jenkins/e2e/snapshot_tables/jobs.csv
b/plugins/jenkins/e2e/snapshot_tables/jobs.csv
index 372e8a97..13ac2c44 100644
--- a/plugins/jenkins/e2e/snapshot_tables/jobs.csv
+++ b/plugins/jenkins/e2e/snapshot_tables/jobs.csv
@@ -1,12 +1,9 @@
id,name,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark
-jenkins:JenkinsJob:1:auto_test,auto_test,"{""ConnectionId"":1}",_raw_jenkins_api_jobs,1,
-jenkins:JenkinsJob:1:auto_test_framework,auto_test_framework,"{""ConnectionId"":1}",_raw_jenkins_api_jobs,2,
-jenkins:JenkinsJob:1:build_devlake,build_devlake,"{""ConnectionId"":1}",_raw_jenkins_api_jobs,3,
-jenkins:JenkinsJob:1:Create_License,Create_License,"{""ConnectionId"":1}",_raw_jenkins_api_jobs,4,
-jenkins:JenkinsJob:1:Create_License_new,Create_License_new,"{""ConnectionId"":1}",_raw_jenkins_api_jobs,5,
-jenkins:JenkinsJob:1:Deploy k8s single_data,Deploy k8s
single_data,"{""ConnectionId"":1}",_raw_jenkins_api_jobs,6,
-jenkins:JenkinsJob:1:Deploy k8s single_new,Deploy k8s
single_new,"{""ConnectionId"":1}",_raw_jenkins_api_jobs,7,
-jenkins:JenkinsJob:1:Deploy k8s test,Deploy k8s
test,"{""ConnectionId"":1}",_raw_jenkins_api_jobs,8,
-jenkins:JenkinsJob:1:devlake_empty_build,devlake_empty_build,"{""ConnectionId"":1}",_raw_jenkins_api_jobs,9,
-jenkins:JenkinsJob:1:test-platform-backend,test-platform-backend,"{""ConnectionId"":1}",_raw_jenkins_api_jobs,10,
-jenkins:JenkinsJob:1:test-platform-frontend,test-platform-frontend,"{""ConnectionId"":1}",_raw_jenkins_api_jobs,11,
+jenkins:JenkinsJob:1:devlake,devlake,"{""ConnectionId"":1}",_raw_jenkins_api_jobs,12,
+jenkins:JenkinsJob:1:dir-test,dir-test,"{""ConnectionId"":1}",_raw_jenkins_api_jobs,13,
+jenkins:JenkinsJob:1:dir-test-2,dir-test-2,"{""ConnectionId"":1}",_raw_jenkins_api_jobs,16,
+jenkins:JenkinsJob:1:free,free,"{""ConnectionId"":1}",_raw_jenkins_api_jobs,19,
+jenkins:JenkinsJob:1:pipeline-test,pipeline-test,"{""ConnectionId"":1}",_raw_jenkins_api_jobs,17,
+jenkins:JenkinsJob:1:testfile,testfile,"{""ConnectionId"":1}",_raw_jenkins_api_jobs,18,
+jenkins:JenkinsJob:1:测试流水线,测试流水线,"{""ConnectionId"":1}",_raw_jenkins_api_jobs,14,
+jenkins:JenkinsJob:1:这是一个改了名字的测试任务,这是一个改了名字的测试任务,"{""ConnectionId"":1}",_raw_jenkins_api_jobs,15,
diff --git a/plugins/jenkins/impl/impl.go b/plugins/jenkins/impl/impl.go
index bebf0180..d9d6f92d 100644
--- a/plugins/jenkins/impl/impl.go
+++ b/plugins/jenkins/impl/impl.go
@@ -36,6 +36,7 @@ var _ core.PluginInit = (*Jenkins)(nil)
var _ core.PluginTask = (*Jenkins)(nil)
var _ core.PluginApi = (*Jenkins)(nil)
var _ core.Migratable = (*Jenkins)(nil)
+var _ core.CloseablePluginTask = (*Jenkins)(nil)
type Jenkins struct{}
@@ -119,3 +120,12 @@ func (plugin Jenkins) ApiResources()
map[string]map[string]core.ApiResourceHandl
},
}
}
+
+func (plugin Jenkins) Close(taskCtx core.TaskContext) error {
+ data, ok := taskCtx.GetData().(*tasks.JenkinsTaskData)
+ if !ok {
+ return fmt.Errorf("GetData failed when try to close %+v",
taskCtx)
+ }
+ data.ApiClient.Release()
+ return nil
+}
diff --git a/plugins/jenkins/jenkins.go b/plugins/jenkins/jenkins.go
index fcbd14b2..a693fa5c 100644
--- a/plugins/jenkins/jenkins.go
+++ b/plugins/jenkins/jenkins.go
@@ -27,7 +27,7 @@ var PluginEntry impl.Jenkins
func main() {
jenkinsCmd := &cobra.Command{Use: "jenkins"}
- connectionId := jenkinsCmd.Flags().Uint64P("connection", "c", 0,
"jenkins connection id")
+ connectionId := jenkinsCmd.Flags().Uint64P("connection", "c", 1,
"jenkins connection id")
jenkinsCmd.Run = func(cmd *cobra.Command, args []string) {
runner.DirectRun(cmd, args, PluginEntry, map[string]interface{}{
"connectionId": *connectionId,
diff --git a/plugins/jenkins/models/job.go b/plugins/jenkins/models/job.go
index dbac6366..13b0fd9d 100644
--- a/plugins/jenkins/models/job.go
+++ b/plugins/jenkins/models/job.go
@@ -17,13 +17,17 @@ limitations under the License.
package models
-import "github.com/apache/incubator-devlake/models/common"
+import (
+ "github.com/apache/incubator-devlake/models/common"
+ "github.com/apache/incubator-devlake/plugins/helper"
+)
// JenkinsJobProps current used jenkins job props
type JenkinsJobProps struct {
// collected fields
ConnectionId uint64 `gorm:"primaryKey"`
Name string `gorm:"primaryKey;type:varchar(255)"`
+ Path string `gorm:"primaryKey;type:varchar(511)"`
Class string `gorm:"type:varchar(255)"`
Color string `gorm:"type:varchar(255)"`
Base string `gorm:"type:varchar(255)"`
@@ -38,3 +42,15 @@ type JenkinsJob struct {
func (JenkinsJob) TableName() string {
return "_tool_jenkins_jobs"
}
+
+type FolderInput struct {
+ Path string
+ *helper.ListBaseNode
+}
+
+func NewFolderInput(path string) *FolderInput {
+ return &FolderInput{
+ Path: path,
+ ListBaseNode: helper.NewListBaseNode(),
+ }
+}
diff --git a/plugins/jenkins/models/migrationscripts/archived/job.go
b/plugins/jenkins/models/migrationscripts/archived/job.go
index 95310876..ace15009 100644
--- a/plugins/jenkins/models/migrationscripts/archived/job.go
+++ b/plugins/jenkins/models/migrationscripts/archived/job.go
@@ -26,6 +26,7 @@ type JenkinsJobProps struct {
// collected fields
ConnectionId uint64 `gorm:"primaryKey"`
Name string `gorm:"primaryKey;type:varchar(255)"`
+ Path string `gorm:"primaryKey;type:varchar(511)"`
Class string `gorm:"type:varchar(255)"`
Color string `gorm:"type:varchar(255)"`
Base string `gorm:"type:varchar(255)"`
diff --git a/plugins/jenkins/models/migrationscripts/init_schema.go
b/plugins/jenkins/models/migrationscripts/init_schema.go
index d5975fa1..406974c4 100644
--- a/plugins/jenkins/models/migrationscripts/init_schema.go
+++ b/plugins/jenkins/models/migrationscripts/init_schema.go
@@ -79,7 +79,7 @@ func (*InitSchemas) Up(ctx context.Context, db *gorm.DB)
error {
}
func (*InitSchemas) Version() uint64 {
- return 20220614201236
+ return 20220712201237
}
func (*InitSchemas) Name() string {
diff --git a/plugins/jenkins/models/response.go
b/plugins/jenkins/models/response.go
index cdeea46f..ace21939 100644
--- a/plugins/jenkins/models/response.go
+++ b/plugins/jenkins/models/response.go
@@ -41,6 +41,7 @@ type Job struct {
Name string `json:"name"`
Color string `json:"color"`
Class string `json:"_class"`
+ Jobs *[]Job `json:"jobs"`
}
type Views struct {
URL string `json:"url"`
diff --git a/plugins/jenkins/tasks/build_collector.go
b/plugins/jenkins/tasks/build_collector.go
index 4f6fff46..dc601421 100644
--- a/plugins/jenkins/tasks/build_collector.go
+++ b/plugins/jenkins/tasks/build_collector.go
@@ -41,13 +41,14 @@ var CollectApiBuildsMeta = core.SubTaskMeta{
type SimpleJob struct {
Name string
+ Path string
}
func CollectApiBuilds(taskCtx core.SubTaskContext) error {
db := taskCtx.GetDal()
data := taskCtx.GetData().(*JenkinsTaskData)
clauses := []dal.Clause{
- dal.Select("tjj.name"),
+ dal.Select("tjj.name,tjj.path"),
dal.From("_tool_jenkins_jobs tjj"),
dal.Where(`tjj.connection_id = ?`, data.Options.ConnectionId),
}
@@ -74,7 +75,7 @@ func CollectApiBuilds(taskCtx core.SubTaskContext) error {
ApiClient: data.ApiClient,
PageSize: 100,
Input: iterator,
- UrlTemplate: "job/{{ .Input.Name }}/api/json",
+ UrlTemplate: "{{ .Input.Path }}job/{{ .Input.Name }}/api/json",
/*
(Optional) Return query string for request, or you can
plug them into UrlTemplate directly
*/
diff --git a/plugins/jenkins/tasks/job_collector.go
b/plugins/jenkins/tasks/job_collector.go
index d010706c..59abde31 100644
--- a/plugins/jenkins/tasks/job_collector.go
+++ b/plugins/jenkins/tasks/job_collector.go
@@ -25,6 +25,7 @@ import (
"github.com/apache/incubator-devlake/plugins/core"
"github.com/apache/incubator-devlake/plugins/helper"
+ models "github.com/apache/incubator-devlake/plugins/jenkins/models"
)
const RAW_JOB_TABLE = "jenkins_api_jobs"
@@ -38,6 +39,8 @@ var CollectApiJobsMeta = core.SubTaskMeta{
}
func CollectApiJobs(taskCtx core.SubTaskContext) error {
+ it := helper.NewQueueIterator()
+ it.Push(models.NewFolderInput(""))
data := taskCtx.GetData().(*JenkinsTaskData)
incremental := false
collector, err := helper.NewApiCollector(helper.ApiCollectorArgs{
@@ -61,15 +64,28 @@ func CollectApiJobs(taskCtx core.SubTaskContext) error {
// jenkins api is special, 1. If the concurrency is larger than
1, then it will report 500.
Concurrency: 1,
- UrlTemplate: "api/json",
+ UrlTemplate: "{{ .Input.Path }}api/json",
+ Input: it,
Query: func(reqData *helper.RequestData) (url.Values, error) {
query := url.Values{}
treeValue := fmt.Sprintf(
- "jobs[name,class,color,base]{%d,%d}",
+ "jobs[name,class,url,color,base,jobs]{%d,%d}",
reqData.Pager.Skip,
reqData.Pager.Skip+reqData.Pager.Size)
query.Set("tree", treeValue)
return query, nil
},
+ Header: func(reqData *helper.RequestData) (http.Header, error) {
+ input, ok := reqData.Input.(*models.FolderInput)
+ if ok {
+ return http.Header{
+ "Path": {
+ input.Path,
+ },
+ }, nil
+ } else {
+ return nil, fmt.Errorf("empty FolderInput")
+ }
+ },
ResponseParser: func(res *http.Response) ([]json.RawMessage,
error) {
var data struct {
@@ -79,6 +95,18 @@ func CollectApiJobs(taskCtx core.SubTaskContext) error {
if err != nil {
return nil, err
}
+ BasePath := res.Request.Header.Get("Path")
+ for _, rawJobs := range data.Jobs {
+ job := &models.Job{}
+ err := json.Unmarshal(rawJobs, job)
+ if err != nil {
+ return nil, err
+ }
+
+ if job.Jobs != nil {
+ it.Push(models.NewFolderInput(BasePath
+ "job/" + job.Name + "/"))
+ }
+ }
return data.Jobs, nil
},
})
diff --git a/plugins/jenkins/tasks/job_extractor.go
b/plugins/jenkins/tasks/job_extractor.go
index 6f289008..1955c8fb 100644
--- a/plugins/jenkins/tasks/job_extractor.go
+++ b/plugins/jenkins/tasks/job_extractor.go
@@ -58,12 +58,20 @@ func ExtractApiJobs(taskCtx core.SubTaskContext) error {
if err != nil {
return nil, err
}
+
+ input := &models.FolderInput{}
+ err = json.Unmarshal(row.Input, input)
+ if err != nil {
+ return nil, err
+ }
+
results := make([]interface{}, 0, 1)
job := &models.JenkinsJob{
JenkinsJobProps: models.JenkinsJobProps{
ConnectionId: data.Options.ConnectionId,
Name: body.Name,
+ Path: input.Path,
Class: body.Class,
Color: body.Color,
},
diff --git a/plugins/jira/impl/impl.go b/plugins/jira/impl/impl.go
index a9131849..5e887584 100644
--- a/plugins/jira/impl/impl.go
+++ b/plugins/jira/impl/impl.go
@@ -40,6 +40,7 @@ var _ core.PluginTask = (*Jira)(nil)
var _ core.PluginApi = (*Jira)(nil)
var _ core.Migratable = (*Jira)(nil)
var _ core.PluginBlueprintV100 = (*Jira)(nil)
+var _ core.CloseablePluginTask = (*Jira)(nil)
type Jira struct{}
@@ -187,3 +188,12 @@ func (plugin Jira) ApiResources()
map[string]map[string]core.ApiResourceHandler
},
}
}
+
+func (plugin Jira) Close(taskCtx core.TaskContext) error {
+ data, ok := taskCtx.GetData().(*tasks.JiraTaskData)
+ if !ok {
+ return fmt.Errorf("GetData failed when try to close %+v",
taskCtx)
+ }
+ data.ApiClient.Release()
+ return nil
+}
diff --git a/plugins/tapd/impl/impl.go b/plugins/tapd/impl/impl.go
index 353b3456..d4709740 100644
--- a/plugins/tapd/impl/impl.go
+++ b/plugins/tapd/impl/impl.go
@@ -40,6 +40,7 @@ var _ core.PluginInit = (*Tapd)(nil)
var _ core.PluginTask = (*Tapd)(nil)
var _ core.PluginApi = (*Tapd)(nil)
var _ core.Migratable = (*Tapd)(nil)
+var _ core.CloseablePluginTask = (*Tapd)(nil)
type Tapd struct{}
@@ -187,3 +188,12 @@ func (plugin Tapd) ApiResources()
map[string]map[string]core.ApiResourceHandler
},
}
}
+
+func (plugin Tapd) Close(taskCtx core.TaskContext) error {
+ data, ok := taskCtx.GetData().(*tasks.TapdTaskData)
+ if !ok {
+ return fmt.Errorf("GetData failed when try to close %+v",
taskCtx)
+ }
+ data.ApiClient.Release()
+ return nil
+}