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

likyh 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 2bd3193f3 feat: scope and transformationRule support for jenkins 
(#3815)
2bd3193f3 is described below

commit 2bd3193f3e4811a7867d1d45e22753fc71876c85
Author: mindlesscloud <[email protected]>
AuthorDate: Wed Nov 30 17:26:05 2022 +0800

    feat: scope and transformationRule support for jenkins (#3815)
    
    * feat: scope and transformationRule support for jenkins
    
    * fix: check core.PluginSource compliance for plugin jenkins
    
    * feat: support pagenation
    
    * refactor: remove utils file
---
 plugins/github/api/scope.go                        |   2 +-
 plugins/github/api/transformation_rule.go          |   2 +-
 plugins/jenkins/api/scope.go                       | 155 +++++++++++++++++++++
 .../{github => jenkins}/api/transformation_rule.go |  42 +++---
 plugins/jenkins/e2e/builds_test.go                 |   9 +-
 plugins/jenkins/e2e/jobs_test.go                   |   9 +-
 plugins/jenkins/e2e/stages_test.go                 |   9 +-
 plugins/jenkins/impl/impl.go                       |  38 +++++
 plugins/jenkins/models/connection.go               |   4 -
 plugins/jenkins/models/job.go                      |  21 +--
 ...go => 20221128_add_trasformation_rule_table.go} |  33 +++--
 .../archived/transformation_rules.go}              |  31 +----
 .../jenkins/models/migrationscripts/register.go    |   1 +
 .../register.go => transformation_rule.go}         |  23 ++-
 plugins/jenkins/tasks/build_cicd_convertor.go      |   4 +-
 plugins/jenkins/tasks/job_extractor.go             |   2 +-
 plugins/jenkins/tasks/stage_convertor.go           |   2 +-
 plugins/jenkins/tasks/task_data.go                 |  21 +--
 plugins/jira/api/scope.go                          |   5 +-
 plugins/jira/api/transformation_rule.go            |   5 +-
 20 files changed, 305 insertions(+), 113 deletions(-)

diff --git a/plugins/github/api/scope.go b/plugins/github/api/scope.go
index 0bafb01a9..8b54f5fad 100644
--- a/plugins/github/api/scope.go
+++ b/plugins/github/api/scope.go
@@ -116,7 +116,7 @@ func GetScopeList(input *core.ApiResourceInput) 
(*core.ApiResourceOutput, errors
        if connectionId == 0 {
                return nil, errors.BadInput.New("invalid path params")
        }
-       limit, offset := getLimitOffset(input.Query)
+       limit, offset := helper.GetLimitOffset(input.Query, "pageSize", "page")
        err := basicRes.GetDal().All(&repos, dal.Where("connection_id = ?", 
connectionId), dal.Limit(limit), dal.Offset(offset))
        if err != nil {
                return nil, err
diff --git a/plugins/github/api/transformation_rule.go 
b/plugins/github/api/transformation_rule.go
index f027be902..e08255f3a 100644
--- a/plugins/github/api/transformation_rule.go
+++ b/plugins/github/api/transformation_rule.go
@@ -119,7 +119,7 @@ func GetTransformationRule(input *core.ApiResourceInput) 
(*core.ApiResourceOutpu
 // @Router /plugins/github/transformation_rules [GET]
 func GetTransformationRuleList(input *core.ApiResourceInput) 
(*core.ApiResourceOutput, errors.Error) {
        var rules []models.TransformationRules
-       limit, offset := getLimitOffset(input.Query)
+       limit, offset := helper.GetLimitOffset(input.Query, "pageSize", "page")
        err := basicRes.GetDal().All(&rules, dal.Limit(limit), 
dal.Offset(offset))
        if err != nil {
                return nil, errors.Default.Wrap(err, "error on get 
TransformationRule list")
diff --git a/plugins/jenkins/api/scope.go b/plugins/jenkins/api/scope.go
new file mode 100644
index 000000000..c9e6cdb67
--- /dev/null
+++ b/plugins/jenkins/api/scope.go
@@ -0,0 +1,155 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package api
+
+import (
+       "net/http"
+       "strconv"
+
+       "github.com/apache/incubator-devlake/errors"
+       "github.com/apache/incubator-devlake/plugins/core"
+       "github.com/apache/incubator-devlake/plugins/core/dal"
+       "github.com/apache/incubator-devlake/plugins/helper"
+       "github.com/apache/incubator-devlake/plugins/jenkins/models"
+       "github.com/mitchellh/mapstructure"
+)
+
+// PutScope create or update jenkins job
+// @Summary create or update jenkins job
+// @Description Create or update jenkins job
+// @Tags plugins/jenkins
+// @Accept application/json
+// @Param connectionId path int false "connection ID"
+// @Param fullName path string false "job's full name"
+// @Param scope body models.JenkinsJob true "json"
+// @Success 200  {object} models.JenkinsJob
+// @Failure 400  {object} shared.ApiBody "Bad Request"
+// @Failure 500  {object} shared.ApiBody "Internal Error"
+// @Router /plugins/jenkins/connections/{connectionId}/scopes/{fullName} [PUT]
+func PutScope(input *core.ApiResourceInput) (*core.ApiResourceOutput, 
errors.Error) {
+       connectionId, fullName, err := extractParam(input.Params)
+       if err != nil {
+               return nil, err
+       }
+       var job models.JenkinsJob
+       job.ConnectionId = connectionId
+       job.FullName = fullName
+       err = errors.Convert(mapstructure.Decode(input.Body, &job))
+       if err != nil {
+               return nil, errors.BadInput.Wrap(err, "decoding Jenkins job 
error")
+       }
+       err = BasicRes.GetDal().CreateOrUpdate(job)
+       if err != nil {
+               return nil, errors.Default.Wrap(err, "error on saving 
JenkinsJob")
+       }
+       return &core.ApiResourceOutput{Body: job, Status: http.StatusOK}, nil
+}
+
+// UpdateScope patch to jenkins job
+// @Summary patch to jenkins job
+// @Description patch to jenkins job
+// @Tags plugins/jenkins
+// @Accept application/json
+// @Param connectionId path int false "connection ID"
+// @Param fullName path string false "job's full name"
+// @Param scope body models.JenkinsJob true "json"
+// @Success 200  {object} models.JenkinsJob
+// @Failure 400  {object} shared.ApiBody "Bad Request"
+// @Failure 500  {object} shared.ApiBody "Internal Error"
+// @Router /plugins/jenkins/connections/{connectionId}/scopes/{fullName} 
[PATCH]
+func UpdateScope(input *core.ApiResourceInput) (*core.ApiResourceOutput, 
errors.Error) {
+       connectionId, fullName, err := extractParam(input.Params)
+       if err != nil {
+               return nil, err
+       }
+       var job models.JenkinsJob
+       job.ConnectionId = connectionId
+       job.FullName = fullName
+       err = BasicRes.GetDal().First(&job, dal.Where("connection_id = ? AND 
job_name = ?", connectionId, fullName))
+       if err != nil {
+               return nil, errors.Default.Wrap(err, "getting JenkinsJob error")
+       }
+       err = helper.DecodeMapStruct(input.Body, &job)
+       if err != nil {
+               return nil, errors.Default.Wrap(err, "patch jenkins job error")
+       }
+       err = BasicRes.GetDal().Update(job)
+       if err != nil {
+               return nil, errors.Default.Wrap(err, "error on saving 
JenkinsJob")
+       }
+       return &core.ApiResourceOutput{Body: job, Status: http.StatusOK}, nil
+}
+
+// GetScopeList get Jenkins jobs
+// @Summary get Jenkins jobs
+// @Description get Jenkins jobs
+// @Tags plugins/jenkins
+// @Param connectionId path int false "connection ID"
+// @Param pageSize query int false "page size, default 50"
+// @Param page query int false "page size, default 1"
+// @Success 200  {object} []models.JenkinsJob
+// @Failure 400  {object} shared.ApiBody "Bad Request"
+// @Failure 500  {object} shared.ApiBody "Internal Error"
+// @Router /plugins/jenkins/connections/{connectionId}/scopes/ [GET]
+func GetScopeList(input *core.ApiResourceInput) (*core.ApiResourceOutput, 
errors.Error) {
+       var jobs []models.JenkinsJob
+       connectionId, _ := strconv.ParseUint(input.Params["connectionId"], 10, 
64)
+       if connectionId == 0 {
+               return nil, errors.BadInput.New("invalid path params")
+       }
+       limit, offset := helper.GetLimitOffset(input.Query, "pageSize", "page")
+       err := BasicRes.GetDal().All(&jobs, dal.Where("connection_id = ?", 
connectionId), dal.Limit(limit), dal.Offset(offset))
+       if err != nil {
+               return nil, err
+       }
+       return &core.ApiResourceOutput{Body: jobs, Status: http.StatusOK}, nil
+}
+
+// GetScope get one Jenkins job
+// @Summary get one Jenkins job
+// @Description get one Jenkins job
+// @Tags plugins/jenkins
+// @Param connectionId path int false "connection ID"
+// @Param fullName path string false "job's full name"
+// @Success 200  {object} models.JenkinsJob
+// @Failure 400  {object} shared.ApiBody "Bad Request"
+// @Failure 500  {object} shared.ApiBody "Internal Error"
+// @Router /plugins/jenkins/connections/{connectionId}/scopes/{fullName} [GET]
+func GetScope(input *core.ApiResourceInput) (*core.ApiResourceOutput, 
errors.Error) {
+       var job models.JenkinsJob
+       connectionId, fullName, err := extractParam(input.Params)
+       if err != nil {
+               return nil, err
+       }
+       err = BasicRes.GetDal().First(&job, dal.Where("connection_id = ? AND 
full_name = ?", connectionId, fullName))
+       if err != nil {
+               return nil, err
+       }
+       return &core.ApiResourceOutput{Body: job, Status: http.StatusOK}, nil
+}
+
+func extractParam(params map[string]string) (uint64, string, errors.Error) {
+       connectionId, _ := strconv.ParseUint(params["connectionId"], 10, 64)
+       if connectionId == 0 {
+               return 0, "", errors.BadInput.New("invalid connectionId")
+       }
+       if params["fullName"] == "" {
+               return 0, "", errors.BadInput.New("invalid fullName")
+       }
+       return connectionId, params["fullName"], nil
+}
diff --git a/plugins/github/api/transformation_rule.go 
b/plugins/jenkins/api/transformation_rule.go
similarity index 80%
copy from plugins/github/api/transformation_rule.go
copy to plugins/jenkins/api/transformation_rule.go
index f027be902..f61ae59c4 100644
--- a/plugins/github/api/transformation_rule.go
+++ b/plugins/jenkins/api/transformation_rule.go
@@ -24,52 +24,52 @@ import (
        "github.com/apache/incubator-devlake/errors"
        "github.com/apache/incubator-devlake/plugins/core"
        "github.com/apache/incubator-devlake/plugins/core/dal"
-       "github.com/apache/incubator-devlake/plugins/github/models"
        "github.com/apache/incubator-devlake/plugins/helper"
+       "github.com/apache/incubator-devlake/plugins/jenkins/models"
        "github.com/mitchellh/mapstructure"
 )
 
-// CreateTransformationRule create transformation rule for Github
-// @Summary create transformation rule for Github
-// @Description create transformation rule for Github
-// @Tags plugins/github
+// CreateTransformationRule create transformation rule for Jenkins
+// @Summary create transformation rule for Jenkins
+// @Description create transformation rule for Jenkins
+// @Tags plugins/jenkins
 // @Accept application/json
 // @Param transformationRule body models.TransformationRules true 
"transformation rule"
 // @Success 200  {object} models.TransformationRules
 // @Failure 400  {object} shared.ApiBody "Bad Request"
 // @Failure 500  {object} shared.ApiBody "Internal Error"
-// @Router /plugins/github/transformation_rules [POST]
+// @Router /plugins/jenkins/transformation_rules [POST]
 func CreateTransformationRule(input *core.ApiResourceInput) 
(*core.ApiResourceOutput, errors.Error) {
        var rule models.TransformationRules
        err := mapstructure.Decode(input.Body, &rule)
        if err != nil {
                return nil, errors.Default.Wrap(err, "error in decoding 
transformation rule")
        }
-       err = basicRes.GetDal().Create(&rule)
+       err = BasicRes.GetDal().Create(&rule)
        if err != nil {
                return nil, errors.Default.Wrap(err, "error on saving 
TransformationRule")
        }
        return &core.ApiResourceOutput{Body: rule, Status: http.StatusOK}, nil
 }
 
-// UpdateTransformationRule update transformation rule for Github
-// @Summary update transformation rule for Github
-// @Description update transformation rule for Github
-// @Tags plugins/github
+// UpdateTransformationRule update transformation rule for Jenkins
+// @Summary update transformation rule for Jenkins
+// @Description update transformation rule for Jenkins
+// @Tags plugins/jenkins
 // @Accept application/json
 // @Param id path int true "id"
 // @Param transformationRule body models.TransformationRules true 
"transformation rule"
 // @Success 200  {object} models.TransformationRules
 // @Failure 400  {object} shared.ApiBody "Bad Request"
 // @Failure 500  {object} shared.ApiBody "Internal Error"
-// @Router /plugins/github/transformation_rules/{id} [PATCH]
+// @Router /plugins/jenkins/transformation_rules/{id} [PATCH]
 func UpdateTransformationRule(input *core.ApiResourceInput) 
(*core.ApiResourceOutput, errors.Error) {
        transformationRuleId, err := strconv.ParseUint(input.Params["id"], 10, 
64)
        if err != nil {
                return nil, errors.Default.Wrap(err, "the transformation rule 
ID should be an integer")
        }
        var old models.TransformationRules
-       err = basicRes.GetDal().First(&old, dal.Where("id = ?", 
transformationRuleId))
+       err = BasicRes.GetDal().First(&old, dal.Where("id = ?", 
transformationRuleId))
        if err != nil {
                return nil, errors.Default.Wrap(err, "error on saving 
TransformationRule")
        }
@@ -78,7 +78,7 @@ func UpdateTransformationRule(input *core.ApiResourceInput) 
(*core.ApiResourceOu
                return nil, errors.Default.Wrap(err, "error decoding map into 
transformationRule")
        }
        old.ID = transformationRuleId
-       err = basicRes.GetDal().Update(&old, dal.Where("id = ?", 
transformationRuleId))
+       err = BasicRes.GetDal().Update(&old, dal.Where("id = ?", 
transformationRuleId))
        if err != nil {
                return nil, errors.Default.Wrap(err, "error on saving 
TransformationRule")
        }
@@ -88,19 +88,19 @@ func UpdateTransformationRule(input *core.ApiResourceInput) 
(*core.ApiResourceOu
 // GetTransformationRule return one transformation rule
 // @Summary return one transformation rule
 // @Description return one transformation rule
-// @Tags plugins/github
+// @Tags plugins/jenkins
 // @Param id path int true "id"
 // @Success 200  {object} models.TransformationRules
 // @Failure 400  {object} shared.ApiBody "Bad Request"
 // @Failure 500  {object} shared.ApiBody "Internal Error"
-// @Router /plugins/github/transformation_rules/{id} [GET]
+// @Router /plugins/jenkins/transformation_rules/{id} [GET]
 func GetTransformationRule(input *core.ApiResourceInput) 
(*core.ApiResourceOutput, errors.Error) {
        transformationRuleId, err := strconv.ParseUint(input.Params["id"], 10, 
64)
        if err != nil {
                return nil, errors.Default.Wrap(err, "the transformation rule 
ID should be an integer")
        }
        var rule models.TransformationRules
-       err = basicRes.GetDal().First(&rule, dal.Where("id = ?", 
transformationRuleId))
+       err = BasicRes.GetDal().First(&rule, dal.Where("id = ?", 
transformationRuleId))
        if err != nil {
                return nil, errors.Default.Wrap(err, "error on get 
TransformationRule")
        }
@@ -110,17 +110,17 @@ func GetTransformationRule(input *core.ApiResourceInput) 
(*core.ApiResourceOutpu
 // GetTransformationRuleList return all transformation rules
 // @Summary return all transformation rules
 // @Description return all transformation rules
-// @Tags plugins/github
+// @Tags plugins/jenkins
 // @Param pageSize query int false "page size, default 50"
 // @Param page query int false "page size, default 1"
 // @Success 200  {object} []models.TransformationRules
 // @Failure 400  {object} shared.ApiBody "Bad Request"
 // @Failure 500  {object} shared.ApiBody "Internal Error"
-// @Router /plugins/github/transformation_rules [GET]
+// @Router /plugins/jenkins/transformation_rules [GET]
 func GetTransformationRuleList(input *core.ApiResourceInput) 
(*core.ApiResourceOutput, errors.Error) {
        var rules []models.TransformationRules
-       limit, offset := getLimitOffset(input.Query)
-       err := basicRes.GetDal().All(&rules, dal.Limit(limit), 
dal.Offset(offset))
+       limit, offset := helper.GetLimitOffset(input.Query, "pageSize", "page")
+       err := BasicRes.GetDal().All(&rules, dal.Limit(limit), 
dal.Offset(offset))
        if err != nil {
                return nil, errors.Default.Wrap(err, "error on get 
TransformationRule list")
        }
diff --git a/plugins/jenkins/e2e/builds_test.go 
b/plugins/jenkins/e2e/builds_test.go
index 4fee31bef..1de2289be 100644
--- a/plugins/jenkins/e2e/builds_test.go
+++ b/plugins/jenkins/e2e/builds_test.go
@@ -34,11 +34,12 @@ func TestJenkinsBuildsDataFlow(t *testing.T) {
 
        taskData := &tasks.JenkinsTaskData{
                Options: &tasks.JenkinsOptions{
-                       ConnectionId: 1,
-                       JobName:      `devlake`,
-                       JobPath:      
`job/Test-jenkins-dir/job/test-jenkins-sub-dir/job/test-sub-sub-dir/`,
+                       ConnectionId:        1,
+                       JobName:             `devlake`,
+                       JobFullName:         "Test-jenkins-dir » 
test-jenkins-sub-dir » test-sub-sub-dir » devlake",
+                       JobPath:             
`job/Test-jenkins-dir/job/test-jenkins-sub-dir/job/test-sub-sub-dir/`,
+                       TransformationRules: new(models.TransformationRules),
                },
-               Job: &models.JenkinsJob{FullName: "Test-jenkins-dir » 
test-jenkins-sub-dir » test-sub-sub-dir » devlake"},
        }
 
        dataflowTester.FlushTabler(&models.JenkinsBuild{})
diff --git a/plugins/jenkins/e2e/jobs_test.go b/plugins/jenkins/e2e/jobs_test.go
index 883ae7a15..d7ab5a25d 100644
--- a/plugins/jenkins/e2e/jobs_test.go
+++ b/plugins/jenkins/e2e/jobs_test.go
@@ -35,11 +35,12 @@ func TestJenkinsJobsDataFlow(t *testing.T) {
 
        taskData := &tasks.JenkinsTaskData{
                Options: &tasks.JenkinsOptions{
-                       ConnectionId: 1,
-                       JobName:      `devlake`,
-                       JobPath:      
`job/Test-jenkins-dir/job/test-jenkins-sub-dir/job/test-sub-sub-dir/`,
+                       ConnectionId:        1,
+                       JobName:             `devlake`,
+                       JobFullName:         "Test-jenkins-dir » 
test-jenkins-sub-dir » test-sub-sub-dir » devlake",
+                       JobPath:             
`job/Test-jenkins-dir/job/test-jenkins-sub-dir/job/test-sub-sub-dir/`,
+                       TransformationRules: new(models.TransformationRules),
                },
-               Job: &models.JenkinsJob{FullName: "Test-jenkins-dir » 
test-jenkins-sub-dir » test-sub-sub-dir » devlake"},
        }
 
        // import raw data table
diff --git a/plugins/jenkins/e2e/stages_test.go 
b/plugins/jenkins/e2e/stages_test.go
index 3976695c3..17aa70e77 100644
--- a/plugins/jenkins/e2e/stages_test.go
+++ b/plugins/jenkins/e2e/stages_test.go
@@ -33,11 +33,12 @@ func TestJenkinsStagesDataFlow(t *testing.T) {
 
        taskData := &tasks.JenkinsTaskData{
                Options: &tasks.JenkinsOptions{
-                       ConnectionId: 1,
-                       JobName:      `devlake`,
-                       JobPath:      
`job/Test-jenkins-dir/job/test-jenkins-sub-dir/job/test-sub-sub-dir/`,
+                       ConnectionId:        1,
+                       JobName:             `devlake`,
+                       JobFullName:         "Test-jenkins-dir » 
test-jenkins-sub-dir » test-sub-sub-dir » devlake",
+                       JobPath:             
`job/Test-jenkins-dir/job/test-jenkins-sub-dir/job/test-sub-sub-dir/`,
+                       TransformationRules: new(models.TransformationRules),
                },
-               Job: &models.JenkinsJob{FullName: "Test-jenkins-dir » 
test-jenkins-sub-dir » test-sub-sub-dir » devlake"},
        }
 
        // import raw data table
diff --git a/plugins/jenkins/impl/impl.go b/plugins/jenkins/impl/impl.go
index 6d1813d14..5a1dca84b 100644
--- a/plugins/jenkins/impl/impl.go
+++ b/plugins/jenkins/impl/impl.go
@@ -19,6 +19,7 @@ package impl
 
 import (
        "fmt"
+       "github.com/apache/incubator-devlake/plugins/core/dal"
        "strings"
 
        "github.com/apache/incubator-devlake/errors"
@@ -39,6 +40,7 @@ var _ core.PluginApi = (*Jenkins)(nil)
 var _ core.PluginModel = (*Jenkins)(nil)
 var _ core.PluginMigration = (*Jenkins)(nil)
 var _ core.CloseablePluginTask = (*Jenkins)(nil)
+var _ core.PluginSource = (*Jenkins)(nil)
 
 type Jenkins struct{}
 
@@ -47,6 +49,18 @@ func (plugin Jenkins) Init(config *viper.Viper, logger 
core.Logger, db *gorm.DB)
        return nil
 }
 
+func (plugin Jenkins) Connection() interface{} {
+       return &models.JenkinsConnection{}
+}
+
+func (plugin Jenkins) Scope() interface{} {
+       return &models.JenkinsJob{}
+}
+
+func (plugin Jenkins) TransformationRule() interface{} {
+       return &models.TransformationRules{}
+}
+
 func (plugin Jenkins) GetTablesInfo() []core.Tabler {
        return []core.Tabler{
                &models.JenkinsBuild{},
@@ -109,6 +123,14 @@ func (plugin Jenkins) PrepareTaskData(taskCtx 
core.TaskContext, options map[stri
        if !strings.HasSuffix(op.JobPath, "/") {
                op.JobPath = fmt.Sprintf("%s/", op.JobPath)
        }
+       if op.TransformationRules == nil && op.TransformationRuleId != 0 {
+               var transformationRule models.TransformationRules
+               err = taskCtx.GetDal().First(&transformationRule, dal.Where("id 
= ?", op.TransformationRuleId))
+               if err != nil {
+                       return nil, errors.BadInput.Wrap(err, "fail to get 
transformationRule")
+               }
+               op.TransformationRules = &transformationRule
+       }
        return &tasks.JenkinsTaskData{
                Options:    op,
                ApiClient:  apiClient,
@@ -142,6 +164,22 @@ func (plugin Jenkins) ApiResources() 
map[string]map[string]core.ApiResourceHandl
                        "DELETE": api.DeleteConnection,
                        "GET":    api.GetConnection,
                },
+               "connections/:connectionId/scopes/*fullName": {
+                       "GET":   api.GetScope,
+                       "PUT":   api.PutScope,
+                       "PATCH": api.UpdateScope,
+               },
+               "connections/:connectionId/scopes": {
+                       "GET": api.GetScopeList,
+               },
+               "transformation_rules": {
+                       "POST": api.CreateTransformationRule,
+                       "GET":  api.GetTransformationRuleList,
+               },
+               "transformation_rules/:id": {
+                       "PATCH": api.UpdateTransformationRule,
+                       "GET":   api.GetTransformationRule,
+               },
                "connections/:connectionId/proxy/rest/*path": {
                        "GET": api.Proxy,
                },
diff --git a/plugins/jenkins/models/connection.go 
b/plugins/jenkins/models/connection.go
index 7caab22b9..aa030327e 100644
--- a/plugins/jenkins/models/connection.go
+++ b/plugins/jenkins/models/connection.go
@@ -38,10 +38,6 @@ type TestConnectionRequest struct {
        Proxy    string `json:"proxy"`
 }
 
-type TransformationRules struct {
-       DeploymentPattern string `mapstructure:"deploymentPattern" 
json:"deploymentPattern"`
-}
-
 func (JenkinsConnection) TableName() string {
        return "_tool_jenkins_connections"
 }
diff --git a/plugins/jenkins/models/job.go b/plugins/jenkins/models/job.go
index 075bfa9ff..b548d62e9 100644
--- a/plugins/jenkins/models/job.go
+++ b/plugins/jenkins/models/job.go
@@ -23,16 +23,17 @@ import (
 
 // JenkinsJob db entity for jenkins job
 type JenkinsJob struct {
-       ConnectionId uint64 `gorm:"primaryKey"`
-       FullName     string `gorm:"primaryKey;type:varchar(255)"`
-       Name         string `gorm:"index;type:varchar(255)"`
-       Path         string `gorm:"index;type:varchar(511)"`
-       Class        string `gorm:"type:varchar(255)"`
-       Color        string `gorm:"type:varchar(255)"`
-       Base         string `gorm:"type:varchar(255)"`
-       Url          string
-       Description  string
-       PrimaryView  string `gorm:"type:varchar(255)"`
+       ConnectionId         uint64 `gorm:"primaryKey"`
+       FullName             string `gorm:"primaryKey;type:varchar(255)"`
+       TransformationRuleId uint64
+       Name                 string `gorm:"index;type:varchar(255)"`
+       Path                 string `gorm:"index;type:varchar(511)"`
+       Class                string `gorm:"type:varchar(255)"`
+       Color                string `gorm:"type:varchar(255)"`
+       Base                 string `gorm:"type:varchar(255)"`
+       Url                  string
+       Description          string
+       PrimaryView          string `gorm:"type:varchar(255)"`
        common.NoPKModel
 }
 
diff --git a/plugins/jenkins/models/migrationscripts/register.go 
b/plugins/jenkins/models/migrationscripts/20221128_add_trasformation_rule_table.go
similarity index 51%
copy from plugins/jenkins/models/migrationscripts/register.go
copy to 
plugins/jenkins/models/migrationscripts/20221128_add_trasformation_rule_table.go
index 8d607959f..c3c52e1c0 100644
--- a/plugins/jenkins/models/migrationscripts/register.go
+++ 
b/plugins/jenkins/models/migrationscripts/20221128_add_trasformation_rule_table.go
@@ -18,17 +18,30 @@ limitations under the License.
 package migrationscripts
 
 import (
+       "github.com/apache/incubator-devlake/errors"
+       "github.com/apache/incubator-devlake/helpers/migrationhelper"
        "github.com/apache/incubator-devlake/plugins/core"
+       
"github.com/apache/incubator-devlake/plugins/jenkins/models/migrationscripts/archived"
 )
 
-// All return all the migration scripts
-func All() []core.MigrationScript {
-       return []core.MigrationScript{
-               new(addInitTables),
-               new(modifyAllEntities),
-               new(modifyJenkinsBuild),
-               new(addJobFields),
-               new(addJobPathForBuilds),
-               new(changeIndexOfJobPath),
-       }
+type jenkinsJob20221128 struct {
+       TransformationRuleId uint64
+}
+
+func (jenkinsJob20221128) TableName() string {
+       return "_tool_jenkins_jobs"
+}
+
+type addTransformationRule20221128 struct{}
+
+func (*addTransformationRule20221128) Up(basicRes core.BasicRes) errors.Error {
+       return migrationhelper.AutoMigrateTables(basicRes, 
&jenkinsJob20221128{}, &archived.TransformationRules{})
+}
+
+func (*addTransformationRule20221128) Version() uint64 {
+       return 20221128113500
+}
+
+func (*addTransformationRule20221128) Name() string {
+       return "add table _tool_jenkins_transformation_rules, add 
transformation_rule_id to _tool_jenkins_jobs"
 }
diff --git a/plugins/github/api/utils.go 
b/plugins/jenkins/models/migrationscripts/archived/transformation_rules.go
similarity index 62%
rename from plugins/github/api/utils.go
rename to 
plugins/jenkins/models/migrationscripts/archived/transformation_rules.go
index 5a4682b8e..689723d53 100644
--- a/plugins/github/api/utils.go
+++ b/plugins/jenkins/models/migrationscripts/archived/transformation_rules.go
@@ -15,34 +15,17 @@ See the License for the specific language governing 
permissions and
 limitations under the License.
 */
 
-package api
+package archived
 
 import (
-       "net/url"
-       "strconv"
+       "github.com/apache/incubator-devlake/models/migrationscripts/archived"
 )
 
-const pageSize = 50
-
-func getPageParam(q url.Values) (int, int) {
-       var size, page int
-       if ps := q["pageSize"]; len(ps) > 0 {
-               size, _ = strconv.Atoi(ps[0])
-       }
-       if p := q["page"]; len(p) > 0 {
-               page, _ = strconv.Atoi(p[0])
-       }
-       if size < 1 {
-               size = pageSize
-       }
-       if page < 1 {
-               page = 1
-       }
-       return size, page
+type TransformationRules struct {
+       archived.Model
+       DeploymentPattern string `gorm:"type:varchar(255)" 
mapstructure:"deploymentPattern" json:"deploymentPattern"`
 }
 
-func getLimitOffset(q url.Values) (int, int) {
-       limit, page := getPageParam(q)
-       offset := (page - 1) * limit
-       return limit, offset
+func (t TransformationRules) TableName() string {
+       return "_tool_jenkins_transformation_rules"
 }
diff --git a/plugins/jenkins/models/migrationscripts/register.go 
b/plugins/jenkins/models/migrationscripts/register.go
index 8d607959f..cb180940f 100644
--- a/plugins/jenkins/models/migrationscripts/register.go
+++ b/plugins/jenkins/models/migrationscripts/register.go
@@ -30,5 +30,6 @@ func All() []core.MigrationScript {
                new(addJobFields),
                new(addJobPathForBuilds),
                new(changeIndexOfJobPath),
+               new(addTransformationRule20221128),
        }
 }
diff --git a/plugins/jenkins/models/migrationscripts/register.go 
b/plugins/jenkins/models/transformation_rule.go
similarity index 68%
copy from plugins/jenkins/models/migrationscripts/register.go
copy to plugins/jenkins/models/transformation_rule.go
index 8d607959f..aa99f458a 100644
--- a/plugins/jenkins/models/migrationscripts/register.go
+++ b/plugins/jenkins/models/transformation_rule.go
@@ -15,20 +15,15 @@ See the License for the specific language governing 
permissions and
 limitations under the License.
 */
 
-package migrationscripts
+package models
 
-import (
-       "github.com/apache/incubator-devlake/plugins/core"
-)
+import "github.com/apache/incubator-devlake/models/common"
 
-// All return all the migration scripts
-func All() []core.MigrationScript {
-       return []core.MigrationScript{
-               new(addInitTables),
-               new(modifyAllEntities),
-               new(modifyJenkinsBuild),
-               new(addJobFields),
-               new(addJobPathForBuilds),
-               new(changeIndexOfJobPath),
-       }
+type TransformationRules struct {
+       common.Model
+       DeploymentPattern string `gorm:"type:varchar(255)" 
mapstructure:"deploymentPattern" json:"deploymentPattern"`
+}
+
+func (t TransformationRules) TableName() string {
+       return "_tool_jenkins_transformation_rules"
 }
diff --git a/plugins/jenkins/tasks/build_cicd_convertor.go 
b/plugins/jenkins/tasks/build_cicd_convertor.go
index 9710d4336..8c4a980c4 100644
--- a/plugins/jenkins/tasks/build_cicd_convertor.go
+++ b/plugins/jenkins/tasks/build_cicd_convertor.go
@@ -114,7 +114,7 @@ func ConvertBuildsToCICD(taskCtx core.SubTaskContext) (err 
errors.Error) {
                                FinishedDate: jenkinsPipelineFinishedDate,
                                DurationSec:  uint64(durationSec),
                                CreatedDate:  jenkinsBuild.StartTime,
-                               CicdScopeId:  
jobIdGen.Generate(jenkinsBuild.ConnectionId, data.Job.FullName),
+                               CicdScopeId:  
jobIdGen.Generate(jenkinsBuild.ConnectionId, data.Options.JobFullName),
                        }
                        jenkinsPipeline.RawDataOrigin = 
jenkinsBuild.RawDataOrigin
                        results = append(results, jenkinsPipeline)
@@ -131,7 +131,7 @@ func ConvertBuildsToCICD(taskCtx core.SubTaskContext) (err 
errors.Error) {
                                        DurationSec:  uint64(durationSec),
                                        StartedDate:  jenkinsBuild.StartTime,
                                        FinishedDate: 
jenkinsPipelineFinishedDate,
-                                       CicdScopeId:  
jobIdGen.Generate(jenkinsBuild.ConnectionId, data.Job.FullName),
+                                       CicdScopeId:  
jobIdGen.Generate(jenkinsBuild.ConnectionId, data.Options.JobFullName),
                                }
                                if deployTagRegexp != nil {
                                        if deployFlag := 
deployTagRegexp.FindString(jenkinsBuild.JobName); deployFlag != "" {
diff --git a/plugins/jenkins/tasks/job_extractor.go 
b/plugins/jenkins/tasks/job_extractor.go
index 1ef90e6e6..47a227982 100644
--- a/plugins/jenkins/tasks/job_extractor.go
+++ b/plugins/jenkins/tasks/job_extractor.go
@@ -80,7 +80,7 @@ func ExtractApiJobs(taskCtx core.SubTaskContext) errors.Error 
{
                                }
                                results = append(results, &upDownJob)
                        }
-                       data.Job = job
+                       data.Options.JobFullName = body.FullName
                        results = append(results, job)
 
                        return results, nil
diff --git a/plugins/jenkins/tasks/stage_convertor.go 
b/plugins/jenkins/tasks/stage_convertor.go
index 027fb1148..267ba89ae 100644
--- a/plugins/jenkins/tasks/stage_convertor.go
+++ b/plugins/jenkins/tasks/stage_convertor.go
@@ -143,7 +143,7 @@ func ConvertStages(taskCtx core.SubTaskContext) (err 
errors.Error) {
                                DurationSec:  uint64(body.DurationMillis / 
1000),
                                StartedDate:  time.Unix(durationSec, 0),
                                FinishedDate: jenkinsTaskFinishedDate,
-                               CicdScopeId:  
jobIdGen.Generate(body.ConnectionId, data.Job.FullName),
+                               CicdScopeId:  
jobIdGen.Generate(body.ConnectionId, data.Options.JobFullName),
                        }
                        if deployTagRegexp != nil {
                                if deployFlag := 
deployTagRegexp.FindString(body.Name); deployFlag != "" {
diff --git a/plugins/jenkins/tasks/task_data.go 
b/plugins/jenkins/tasks/task_data.go
index c76325bf2..96639265a 100644
--- a/plugins/jenkins/tasks/task_data.go
+++ b/plugins/jenkins/tasks/task_data.go
@@ -32,12 +32,14 @@ type JenkinsApiParams struct {
 }
 
 type JenkinsOptions struct {
-       ConnectionId               uint64 `json:"connectionId"`
-       JobName                    string `json:"jobName"`
-       JobPath                    string `json:"jobPath"`
-       Since                      string
-       Tasks                      []string `json:"tasks,omitempty"`
-       models.TransformationRules `mapstructure:"transformationRules" 
json:"transformationRules"`
+       ConnectionId                uint64 `json:"connectionId"`
+       TransformationRuleId        uint64 `json:"transformationRuleId"`
+       JobFullName                 string `json:"JobFullName"`
+       JobName                     string `json:"jobName"`
+       JobPath                     string `json:"jobPath"`
+       Since                       string
+       Tasks                       []string `json:"tasks,omitempty"`
+       *models.TransformationRules `mapstructure:"transformationRules" 
json:"transformationRules"`
 }
 
 type JenkinsTaskData struct {
@@ -54,12 +56,11 @@ func DecodeAndValidateTaskOptions(options 
map[string]interface{}) (*JenkinsOptio
        if err != nil {
                return nil, errors.BadInput.Wrap(err, "could not decode request 
parameters")
        }
-       if op.DeploymentPattern == "" {
-               op.DeploymentPattern = "(?i)deploy"
-       }
-       // find the needed Jenkins now
        if op.ConnectionId == 0 {
                return nil, errors.BadInput.New("connectionId is invalid")
        }
+       if op.TransformationRules == nil && op.TransformationRuleId == 0 {
+               op.TransformationRules = new(models.TransformationRules)
+       }
        return &op, nil
 }
diff --git a/plugins/jira/api/scope.go b/plugins/jira/api/scope.go
index 2a241455c..e1b918ef3 100644
--- a/plugins/jira/api/scope.go
+++ b/plugins/jira/api/scope.go
@@ -104,6 +104,8 @@ func UpdateScope(input *core.ApiResourceInput) 
(*core.ApiResourceOutput, errors.
 // @Description get Jira boards
 // @Tags plugins/jira
 // @Param connectionId path int false "connection ID"
+// @Param pageSize query int false "page size, default 50"
+// @Param page query int false "page size, default 1"
 // @Success 200  {object} []models.JiraBoard
 // @Failure 400  {object} shared.ApiBody "Bad Request"
 // @Failure 500  {object} shared.ApiBody "Internal Error"
@@ -114,7 +116,8 @@ func GetScopeList(input *core.ApiResourceInput) 
(*core.ApiResourceOutput, errors
        if connectionId == 0 {
                return nil, errors.BadInput.New("invalid path params")
        }
-       err := basicRes.GetDal().All(&boards, dal.Where("connection_id = ?", 
connectionId))
+       limit, offset := helper.GetLimitOffset(input.Query, "pageSize", "page")
+       err := basicRes.GetDal().All(&boards, dal.Where("connection_id = ?", 
connectionId), dal.Limit(limit), dal.Offset(offset))
        if err != nil {
                return nil, err
        }
diff --git a/plugins/jira/api/transformation_rule.go 
b/plugins/jira/api/transformation_rule.go
index fd3391d65..013d5098e 100644
--- a/plugins/jira/api/transformation_rule.go
+++ b/plugins/jira/api/transformation_rule.go
@@ -133,13 +133,16 @@ func GetTransformationRule(input *core.ApiResourceInput) 
(*core.ApiResourceOutpu
 // @Summary return all transformation rules
 // @Description return all transformation rules
 // @Tags plugins/jira
+// @Param pageSize query int false "page size, default 50"
+// @Param page query int false "page size, default 1"
 // @Success 200  {object} []tasks.TransformationRules
 // @Failure 400  {object} shared.ApiBody "Bad Request"
 // @Failure 500  {object} shared.ApiBody "Internal Error"
 // @Router /plugins/jira/transformation_rules [GET]
 func GetTransformationRuleList(input *core.ApiResourceInput) 
(*core.ApiResourceOutput, errors.Error) {
        var rules []models.JiraTransformationRule
-       err := basicRes.GetDal().All(&rules)
+       limit, offset := helper.GetLimitOffset(input.Query, "pageSize", "page")
+       err := basicRes.GetDal().All(&rules, dal.Limit(limit), 
dal.Offset(offset))
        if err != nil {
                return nil, errors.Default.Wrap(err, "error on get 
TransformationRule list")
        }


Reply via email to