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

klesh pushed a commit to branch kw-5519-jenkins
in repository https://gitbox.apache.org/repos/asf/incubator-devlake.git

commit 6c57b8a23ad9934e0983c14a67631fecbad00dea
Author: Klesh Wong <zhenmian.hu...@merico.dev>
AuthorDate: Mon Dec 4 13:24:06 2023 +0800

    refactor: jenkins adopts new dshelpers
---
 backend/plugins/jenkins/api/blueprint_v200.go      |  79 +++++----
 backend/plugins/jenkins/api/blueprint_v200_test.go | 111 -------------
 .../api/{connection.go => connection_api.go}       |  48 +-----
 backend/plugins/jenkins/api/init.go                |  48 ++----
 backend/plugins/jenkins/api/proxy.go               |  73 ---------
 backend/plugins/jenkins/api/remote.go              | 182 +++++++++------------
 .../plugins/jenkins/api/{scope.go => scope_api.go} |  14 +-
 .../api/{scope_config.go => scope_config_api.go}   |  10 +-
 backend/plugins/jenkins/impl/impl.go               |  10 +-
 backend/plugins/jenkins/models/response.go         |   4 +-
 10 files changed, 161 insertions(+), 418 deletions(-)

diff --git a/backend/plugins/jenkins/api/blueprint_v200.go 
b/backend/plugins/jenkins/api/blueprint_v200.go
index 10940fb62..9aaf59641 100644
--- a/backend/plugins/jenkins/api/blueprint_v200.go
+++ b/backend/plugins/jenkins/api/blueprint_v200.go
@@ -18,6 +18,8 @@ limitations under the License.
 package api
 
 import (
+       "context"
+
        "github.com/apache/incubator-devlake/core/errors"
        coreModels "github.com/apache/incubator-devlake/core/models"
        "github.com/apache/incubator-devlake/core/models/domainlayer"
@@ -26,7 +28,9 @@ import (
        "github.com/apache/incubator-devlake/core/plugin"
        "github.com/apache/incubator-devlake/core/utils"
        helper "github.com/apache/incubator-devlake/helpers/pluginhelper/api"
+       "github.com/apache/incubator-devlake/helpers/srvhelper"
        "github.com/apache/incubator-devlake/plugins/jenkins/models"
+       "github.com/apache/incubator-devlake/plugins/jenkins/tasks"
 )
 
 func MakeDataSourcePipelinePlanV200(
@@ -34,12 +38,28 @@ func MakeDataSourcePipelinePlanV200(
        connectionId uint64,
        bpScopes []*coreModels.BlueprintScope,
 ) (coreModels.PipelinePlan, []plugin.Scope, errors.Error) {
-       plan := make(coreModels.PipelinePlan, len(bpScopes))
-       plan, err := makeDataSourcePipelinePlanV200(subtaskMetas, plan, 
bpScopes, connectionId)
+       // load connection, scope and scopeConfig from the db
+       connection, err := dsHelper.ConnSrv.FindByPk(connectionId)
        if err != nil {
                return nil, nil, err
        }
-       scopes, err := makeScopesV200(bpScopes, connectionId)
+       scopeDetails, err := dsHelper.ScopeSrv.MapScopeDetails(connectionId, 
bpScopes)
+       if err != nil {
+               return nil, nil, err
+       }
+
+       // needed for the connection to populate its access tokens
+       // if AppKey authentication method is selected
+       _, err = helper.NewApiClientFromConnection(context.TODO(), basicRes, 
connection)
+       if err != nil {
+               return nil, nil, err
+       }
+
+       plan, err := makeDataSourcePipelinePlanV200(subtaskMetas, scopeDetails, 
connection)
+       if err != nil {
+               return nil, nil, err
+       }
+       scopes, err := makeScopesV200(scopeDetails, connection)
        if err != nil {
                return nil, nil, err
        }
@@ -49,59 +69,50 @@ func MakeDataSourcePipelinePlanV200(
 
 func makeDataSourcePipelinePlanV200(
        subtaskMetas []plugin.SubTaskMeta,
-       plan coreModels.PipelinePlan,
-       bpScopes []*coreModels.BlueprintScope,
-       connectionId uint64,
+       scopeDetails []*srvhelper.ScopeDetail[models.JenkinsJob, 
models.JenkinsScopeConfig],
+       connection *models.JenkinsConnection,
 ) (coreModels.PipelinePlan, errors.Error) {
-       for i, bpScope := range bpScopes {
+       plan := make(coreModels.PipelinePlan, len(scopeDetails))
+       for i, scopeDetail := range scopeDetails {
+               jenkinsJob, scopeConfig := scopeDetail.Scope, 
scopeDetail.ScopeConfig
                stage := plan[i]
                if stage == nil {
                        stage = coreModels.PipelineStage{}
                }
 
-               // construct task options for Jenkins
-               options := make(map[string]interface{})
-               options["scopeId"] = bpScope.ScopeId
-               options["connectionId"] = connectionId
-
-               // get scope config from db
-               _, scopeConfig, err := 
scopeHelper.DbHelper().GetScopeAndConfig(connectionId, bpScope.ScopeId)
+               // construct task options for github
+               task, err := helper.MakePipelinePlanTask(
+                       "jenkins",
+                       subtaskMetas,
+                       scopeConfig.Entities,
+                       tasks.JenkinsOptions{
+                               ConnectionId: jenkinsJob.ConnectionId,
+                               ScopeId:      jenkinsJob.ScopeId(),
+                       },
+               )
                if err != nil {
                        return nil, err
                }
 
-               subtasks, err := helper.MakePipelinePlanSubtasks(subtaskMetas, 
scopeConfig.Entities)
-               if err != nil {
-                       return nil, err
-               }
-               stage = append(stage, &coreModels.PipelineTask{
-                       Plugin:   "jenkins",
-                       Subtasks: subtasks,
-                       Options:  options,
-               })
+               stage = append(stage, task)
+
                plan[i] = stage
        }
-
        return plan, nil
 }
 
 func makeScopesV200(
-       bpScopes []*coreModels.BlueprintScope,
-       connectionId uint64,
+       scopeDetails []*srvhelper.ScopeDetail[models.JenkinsJob, 
models.JenkinsScopeConfig],
+       connection *models.JenkinsConnection,
 ) ([]plugin.Scope, errors.Error) {
        scopes := make([]plugin.Scope, 0)
-       for _, bpScope := range bpScopes {
-               // get job and scope config from db
-               jenkinsJob, scopeConfig, err := 
scopeHelper.DbHelper().GetScopeAndConfig(connectionId, bpScope.ScopeId)
-               if err != nil {
-                       return nil, err
-               }
-
+       for _, scopeDetail := range scopeDetails {
+               jenkinsJob, scopeConfig := scopeDetail.Scope, 
scopeDetail.ScopeConfig
                // add cicd_scope to scopes
                if utils.StringsContains(scopeConfig.Entities, 
plugin.DOMAIN_TYPE_CICD) {
                        scopeCICD := &devops.CicdScope{
                                DomainEntity: domainlayer.DomainEntity{
-                                       Id: 
didgen.NewDomainIdGenerator(&models.JenkinsJob{}).Generate(connectionId, 
jenkinsJob.FullName),
+                                       Id: 
didgen.NewDomainIdGenerator(&models.JenkinsJob{}).Generate(connection.ID, 
jenkinsJob.FullName),
                                },
                                Name: jenkinsJob.FullName,
                        }
diff --git a/backend/plugins/jenkins/api/blueprint_v200_test.go 
b/backend/plugins/jenkins/api/blueprint_v200_test.go
deleted file mode 100644
index e41a30ddf..000000000
--- a/backend/plugins/jenkins/api/blueprint_v200_test.go
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
-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 (
-       "testing"
-
-       coreModels "github.com/apache/incubator-devlake/core/models"
-       "github.com/apache/incubator-devlake/core/models/common"
-       "github.com/apache/incubator-devlake/core/models/domainlayer"
-       "github.com/apache/incubator-devlake/core/models/domainlayer/devops"
-       "github.com/apache/incubator-devlake/core/plugin"
-       "github.com/apache/incubator-devlake/helpers/unithelper"
-       mockdal "github.com/apache/incubator-devlake/mocks/core/dal"
-       mockplugin "github.com/apache/incubator-devlake/mocks/core/plugin"
-       "github.com/apache/incubator-devlake/plugins/jenkins/models"
-       "github.com/stretchr/testify/assert"
-       "github.com/stretchr/testify/mock"
-)
-
-func TestMakeDataSourcePipelinePlanV200(t *testing.T) {
-       mockMeta := mockplugin.NewPluginMeta(t)
-       
mockMeta.On("RootPkgPath").Return("github.com/apache/incubator-devlake/plugins/jenkins")
-       mockMeta.On("Name").Return("jenkins").Maybe()
-       err := plugin.RegisterPlugin("jenkins", mockMeta)
-       assert.Nil(t, err)
-       bs := &coreModels.BlueprintScope{
-               ScopeId: "a/b/ccc",
-       }
-       
-       bpScopes := make([]*coreModels.BlueprintScope, 0)
-       bpScopes = append(bpScopes, bs)
-
-       mockBasicRes(t)
-
-       plan := make(coreModels.PipelinePlan, len(bpScopes))
-       plan, err = makeDataSourcePipelinePlanV200(nil, plan, bpScopes, 1)
-       assert.Nil(t, err)
-       scopes, err := makeScopesV200(bpScopes, 1)
-       assert.Nil(t, err)
-
-       expectPlan := coreModels.PipelinePlan{
-               coreModels.PipelineStage{
-                       {
-                               Plugin:   "jenkins",
-                               Subtasks: []string{},
-                               Options: map[string]interface{}{
-                                       "connectionId": uint64(1),
-                                       "scopeId":      "a/b/ccc",
-                               },
-                       },
-               },
-       }
-       assert.Equal(t, expectPlan, plan)
-
-       expectScopes := make([]plugin.Scope, 0)
-       scopeCicd := &devops.CicdScope{
-               DomainEntity: domainlayer.DomainEntity{
-                       Id: "jenkins:JenkinsJob:1:a/b/ccc",
-               },
-               Name: "a/b/ccc",
-       }
-
-       expectScopes = append(expectScopes, scopeCicd)
-       assert.Equal(t, expectScopes, scopes)
-}
-
-func mockBasicRes(t *testing.T) {
-       jenkinsJob := &models.JenkinsJob{
-               Scope: common.Scope{
-                       ConnectionId: 1,
-               },
-               FullName: "a/b/ccc",
-       }
-
-       scopeConfig := &models.JenkinsScopeConfig{
-               ScopeConfig: common.ScopeConfig{
-                       Entities: []string{"CICD"},
-               },
-       }
-
-       // Refresh Global Variables and set the sql mock
-       mockRes := unithelper.DummyBasicRes(func(mockDal *mockdal.Dal) {
-               mockDal.On("First", 
mock.AnythingOfType("*models.JenkinsScopeConfig"), mock.Anything).Run(func(args 
mock.Arguments) {
-                       dst := args.Get(0).(*models.JenkinsScopeConfig)
-                       *dst = *scopeConfig
-               }).Return(nil)
-               mockDal.On("First", mock.AnythingOfType("*models.JenkinsJob"), 
mock.Anything).Run(func(args mock.Arguments) {
-                       dst := args.Get(0).(*models.JenkinsJob)
-                       *dst = *jenkinsJob
-               }).Return(nil)
-       })
-       p := mockplugin.NewPluginMeta(t)
-       p.On("Name").Return("dummy").Maybe()
-       Init(mockRes, p)
-}
diff --git a/backend/plugins/jenkins/api/connection.go 
b/backend/plugins/jenkins/api/connection_api.go
similarity index 83%
rename from backend/plugins/jenkins/api/connection.go
rename to backend/plugins/jenkins/api/connection_api.go
index 5ea1058da..ea6ee046a 100644
--- a/backend/plugins/jenkins/api/connection.go
+++ b/backend/plugins/jenkins/api/connection_api.go
@@ -106,8 +106,7 @@ func TestConnection(input *plugin.ApiResourceInput) 
(*plugin.ApiResourceOutput,
 // @Failure 500  {string} errcode.Error "Internal Error"
 // @Router /plugins/jenkins/{connectionId}/test [POST]
 func TestExistingConnection(input *plugin.ApiResourceInput) 
(*plugin.ApiResourceOutput, errors.Error) {
-       connection := &models.JenkinsConnection{}
-       err := connectionHelper.First(connection, input.Params)
+       connection, err := dsHelper.ConnApi.FindByPk(input)
        if err != nil {
                return nil, errors.BadInput.Wrap(err, "find connection from db")
        }
@@ -128,15 +127,7 @@ func TestExistingConnection(input 
*plugin.ApiResourceInput) (*plugin.ApiResource
 // @Failure 500  {string} errcode.Error "Internal Error"
 // @Router /plugins/jenkins/connections [POST]
 func PostConnections(input *plugin.ApiResourceInput) 
(*plugin.ApiResourceOutput, errors.Error) {
-       // create a new connection
-       connection := &models.JenkinsConnection{}
-
-       // update from request and save to database
-       err := connectionHelper.Create(connection, input)
-       if err != nil {
-               return nil, err
-       }
-       return &plugin.ApiResourceOutput{Body: connection.Sanitize(), Status: 
http.StatusOK}, nil
+       return dsHelper.ConnApi.Post(input)
 }
 
 // @Summary patch jenkins connection
@@ -148,13 +139,7 @@ func PostConnections(input *plugin.ApiResourceInput) 
(*plugin.ApiResourceOutput,
 // @Failure 500  {string} errcode.Error "Internal Error"
 // @Router /plugins/jenkins/connections/{connectionId} [PATCH]
 func PatchConnection(input *plugin.ApiResourceInput) 
(*plugin.ApiResourceOutput, errors.Error) {
-       connection := &models.JenkinsConnection{}
-       err := connectionHelper.Patch(connection, input)
-       if err != nil {
-               return nil, err
-       }
-
-       return &plugin.ApiResourceOutput{Body: connection.Sanitize()}, nil
+       return dsHelper.ConnApi.Patch(input)
 }
 
 // @Summary delete a jenkins connection
@@ -166,14 +151,7 @@ func PatchConnection(input *plugin.ApiResourceInput) 
(*plugin.ApiResourceOutput,
 // @Failure 500  {string} errcode.Error "Internal Error"
 // @Router /plugins/jenkins/connections/{connectionId} [DELETE]
 func DeleteConnection(input *plugin.ApiResourceInput) 
(*plugin.ApiResourceOutput, errors.Error) {
-       conn := &models.JenkinsConnection{}
-       output, err := connectionHelper.Delete(conn, input)
-       if err != nil {
-               return output, err
-       }
-       output.Body = conn.Sanitize()
-       return output, nil
-
+       return dsHelper.ConnApi.Delete(input)
 }
 
 // @Summary get all jenkins connections
@@ -184,16 +162,7 @@ func DeleteConnection(input *plugin.ApiResourceInput) 
(*plugin.ApiResourceOutput
 // @Failure 500  {string} errcode.Error "Internal Error"
 // @Router /plugins/jenkins/connections [GET]
 func ListConnections(input *plugin.ApiResourceInput) 
(*plugin.ApiResourceOutput, errors.Error) {
-       var connections []models.JenkinsConnection
-       err := connectionHelper.List(&connections)
-       if err != nil {
-               return nil, err
-       }
-
-       for idx, c := range connections {
-               connections[idx] = c.Sanitize()
-       }
-       return &plugin.ApiResourceOutput{Body: connections, Status: 
http.StatusOK}, nil
+       return dsHelper.ConnApi.GetAll(input)
 }
 
 // @Summary get jenkins connection detail
@@ -204,10 +173,5 @@ func ListConnections(input *plugin.ApiResourceInput) 
(*plugin.ApiResourceOutput,
 // @Failure 500  {string} errcode.Error "Internal Error"
 // @Router /plugins/jenkins/connections/{connectionId} [GET]
 func GetConnection(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, 
errors.Error) {
-       connection := &models.JenkinsConnection{}
-       err := connectionHelper.First(connection, input.Params)
-       if err != nil {
-               return nil, err
-       }
-       return &plugin.ApiResourceOutput{Body: connection.Sanitize()}, err
+       return dsHelper.ConnApi.GetDetail(input)
 }
diff --git a/backend/plugins/jenkins/api/init.go 
b/backend/plugins/jenkins/api/init.go
index 08f78716f..ebcb14c55 100644
--- a/backend/plugins/jenkins/api/init.go
+++ b/backend/plugins/jenkins/api/init.go
@@ -26,45 +26,29 @@ import (
 )
 
 var vld *validator.Validate
-var connectionHelper *api.ConnectionApiHelper
-var scopeHelper *api.ScopeApiHelper[models.JenkinsConnection, 
models.JenkinsJob, models.JenkinsScopeConfig]
-var remoteHelper *api.RemoteApiHelper[models.JenkinsConnection, 
models.JenkinsJob, models.Job, models.Job]
 
 var basicRes context.BasicRes
-var scHelper *api.ScopeConfigHelper[models.JenkinsScopeConfig, 
*models.JenkinsScopeConfig]
+var dsHelper *api.DsHelper[models.JenkinsConnection, models.JenkinsJob, 
models.JenkinsScopeConfig]
+var raProxy *api.DsRemoteApiProxyHelper[models.JenkinsConnection]
+var raScopeList *api.DsRemoteApiScopeListHelper[models.JenkinsConnection, 
models.JenkinsJob, JenkinsRemotePagination]
 
 func Init(br context.BasicRes, p plugin.PluginMeta) {
-
        basicRes = br
        vld = validator.New()
-       connectionHelper = api.NewConnectionHelper(
-               basicRes,
-               vld,
+       dsHelper = api.NewDataSourceHelper[
+               models.JenkinsConnection,
+               models.JenkinsJob,
+               models.JenkinsScopeConfig,
+       ](
+               br,
                p.Name(),
-       )
-       params := &api.ReflectionParameters{
-               ScopeIdFieldName:     "FullName",
-               ScopeIdColumnName:    "full_name",
-               RawScopeParamName:    "FullName",
-               SearchScopeParamName: "full_name",
-       }
-       scopeHelper = api.NewScopeHelper[models.JenkinsConnection, 
models.JenkinsJob, models.JenkinsScopeConfig](
-               basicRes,
-               vld,
-               connectionHelper,
-               api.NewScopeDatabaseHelperImpl[models.JenkinsConnection, 
models.JenkinsJob, models.JenkinsScopeConfig](
-                       basicRes, connectionHelper, params),
-               params,
+               []string{"full_name"},
+               func(c models.JenkinsConnection) models.JenkinsConnection {
+                       return c.Sanitize()
+               },
+               nil,
                nil,
        )
-       remoteHelper = api.NewRemoteHelper[models.JenkinsConnection, 
models.JenkinsJob, models.Job, models.Job](
-               basicRes,
-               vld,
-               connectionHelper,
-       )
-       scHelper = api.NewScopeConfigHelper[models.JenkinsScopeConfig, 
*models.JenkinsScopeConfig](
-               basicRes,
-               vld,
-               p.Name(),
-       )
+       raProxy = 
api.NewDsRemoteApiProxyHelper[models.JenkinsConnection](dsHelper.ConnApi.ModelApiHelper)
+       raScopeList = 
api.NewDsRemoteApiScopeListHelper[models.JenkinsConnection, models.JenkinsJob, 
JenkinsRemotePagination](raProxy, listJenkinsRemoteScopes)
 }
diff --git a/backend/plugins/jenkins/api/proxy.go 
b/backend/plugins/jenkins/api/proxy.go
deleted file mode 100644
index 0baac8d2f..000000000
--- a/backend/plugins/jenkins/api/proxy.go
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package api
-
-import (
-       "context"
-       "encoding/json"
-       "fmt"
-       "github.com/apache/incubator-devlake/core/errors"
-       "github.com/apache/incubator-devlake/core/plugin"
-       helper "github.com/apache/incubator-devlake/helpers/pluginhelper/api"
-       "github.com/apache/incubator-devlake/plugins/jenkins/models"
-       "io"
-       "time"
-)
-
-const (
-       TimeOut = 10 * time.Second
-)
-
-func Proxy(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, 
errors.Error) {
-       connection := &models.JenkinsConnection{}
-       err := connectionHelper.First(connection, input.Params)
-       if err != nil {
-               return nil, err
-       }
-       apiClient, err := helper.NewApiClient(
-               context.TODO(),
-               connection.Endpoint,
-               map[string]string{
-                       "Authorization": fmt.Sprintf("Basic %v", 
connection.GetEncodedToken()),
-               },
-               TimeOut,
-               connection.Proxy,
-               basicRes,
-       )
-       if err != nil {
-               return nil, err
-       }
-
-       resp, err := apiClient.Get(input.Params["path"], input.Query, nil)
-       if err != nil {
-               return nil, err
-       }
-       defer resp.Body.Close()
-
-       body, err := errors.Convert01(io.ReadAll(resp.Body))
-       if err != nil {
-               return nil, err
-       }
-       // verify response body is json
-       var tmp interface{}
-       err = errors.Convert(json.Unmarshal(body, &tmp))
-       if err != nil {
-               return nil, err
-       }
-       return &plugin.ApiResourceOutput{Status: resp.StatusCode, Body: 
json.RawMessage(body)}, nil
-}
diff --git a/backend/plugins/jenkins/api/remote.go 
b/backend/plugins/jenkins/api/remote.go
index cd932828a..171336dc8 100644
--- a/backend/plugins/jenkins/api/remote.go
+++ b/backend/plugins/jenkins/api/remote.go
@@ -18,128 +18,98 @@ limitations under the License.
 package api
 
 import (
-       gocontext "context"
-       "net/http"
-       "strings"
+       "fmt"
 
-       "github.com/apache/incubator-devlake/core/context"
        "github.com/apache/incubator-devlake/core/errors"
        "github.com/apache/incubator-devlake/core/plugin"
        "github.com/apache/incubator-devlake/helpers/pluginhelper/api"
+       dsmodels 
"github.com/apache/incubator-devlake/helpers/pluginhelper/api/models"
        "github.com/apache/incubator-devlake/plugins/jenkins/models"
 )
 
-// RemoteScopes list all available scope for users
-// @Summary list all available scope for users
-// @Description list all available scope for users
-// @Tags plugins/jenkins
-// @Accept application/json
-// @Param connectionId path int false "connection ID"
-// @Param groupId query string false "group ID"
-// @Param pageToken query string false "page Token"
-// @Success 200  {object} api.RemoteScopesOutput
-// @Failure 400  {object} shared.ApiBody "Bad Request"
-// @Failure 500  {object} shared.ApiBody "Internal Error"
-// @Router /plugins/jenkins/connections/{connectionId}/remote-scopes [GET]
-func RemoteScopes(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, 
errors.Error) {
-       getter := func(basicRes context.BasicRes, groupId string, queryData 
*api.RemoteQueryData, connection models.JenkinsConnection) 
(*api.RemoteScopesOutput, errors.Error) {
-               var resBody []api.RemoteScopesChild
-               apiClient, err := 
api.NewApiClientFromConnection(gocontext.TODO(), basicRes, &connection)
-               if err != nil {
-                       return nil, errors.BadInput.Wrap(err, "failed to get 
create apiClient")
-               }
-               getJobsPageCallBack := func(job *models.Job) errors.Error {
-                       if job.Jobs != nil {
-                               // this is a group
-                               job.Path = groupId
-                               groupChild := api.RemoteScopesChild{
-                                       Type: api.TypeGroup,
-                                       Id:   job.GroupId(),
-                                       Name: job.GroupName(),
-                                       // don't need to save group into data
-                                       Data: nil,
-                               }
-                               groupChild.ParentId = &groupId
-                               if *groupChild.ParentId == "" {
-                                       groupChild.ParentId = nil
-                               }
-                               resBody = append(resBody, groupChild)
-                       } else {
-                               // this is a scope
-                               scope := job.ConvertApiScope()
-                               scopeChild := api.RemoteScopesChild{
-                                       Type:     api.TypeScope,
-                                       Id:       scope.ScopeId(),
-                                       Name:     scope.ScopeName(),
-                                       FullName: scope.ScopeFullName(),
-                                       Data:     &scope,
-                               }
-                               scopeChild.ParentId = &groupId
-                               if *scopeChild.ParentId == "" {
-                                       scopeChild.ParentId = nil
-                               }
-                               resBody = append(resBody, scopeChild)
-                       }
-                       return nil
-               }
-               _, err = GetJobsPage(apiClient, groupId, queryData.Page-1, 
queryData.PerPage, getJobsPageCallBack)
-               if err != nil {
-                       return nil, errors.BadInput.Wrap(err, "failed to 
GetJobsPage")
+type JenkinsRemotePagination struct {
+       Page    int `json:"page"`
+       PerPage int `json:"per_page"`
+}
+
+func listJenkinsRemoteScopes(
+       connection *models.JenkinsConnection,
+       apiClient plugin.ApiClient,
+       groupId string,
+       page JenkinsRemotePagination,
+) (
+       children []dsmodels.DsRemoteApiScopeListEntry[models.JenkinsJob],
+       nextPage *JenkinsRemotePagination,
+       err errors.Error,
+) {
+       if page.Page == 0 {
+               page.Page = 1
+       }
+       if page.PerPage == 0 {
+               page.PerPage = 100
+       }
+       var parentId *string
+       if groupId != "" {
+               parentId = &groupId
+       }
+       getJobsPageCallBack := func(job *models.Job) errors.Error {
+               if job.Jobs != nil {
+                       // this is a group
+                       job.Path = groupId
+                       children = append(children, 
dsmodels.DsRemoteApiScopeListEntry[models.JenkinsJob]{
+                               Type:     api.RAS_ENTRY_TYPE_GROUP,
+                               Id:       fmt.Sprintf("%s/job/%s", job.Path, 
job.Name),
+                               Name:     job.Name,
+                               ParentId: parentId,
+                       })
+               } else {
+                       // this is a scope
+                       jenkinsJob := job.ToJenkinsJob()
+                       children = append(children, 
dsmodels.DsRemoteApiScopeListEntry[models.JenkinsJob]{
+                               Type:     api.RAS_ENTRY_TYPE_SCOPE,
+                               Id:       jenkinsJob.ScopeId(),
+                               Name:     jenkinsJob.ScopeName(),
+                               FullName: jenkinsJob.ScopeFullName(),
+                               Data:     jenkinsJob,
+                               ParentId: parentId,
+                       })
                }
-               return &api.RemoteScopesOutput{
-                       Children: resBody,
-               }, nil
+               return nil
        }
-       remoteScopesOutput, err := remoteHelper.GetRemoteScopesOutput(input, 
getter)
+       _, err = GetJobsPage(apiClient, groupId, page.Page-1, page.PerPage, 
getJobsPageCallBack)
        if err != nil {
-               return nil, err
+               return
        }
-       return &plugin.ApiResourceOutput{Body: remoteScopesOutput, Status: 
http.StatusOK}, nil
+       if len(children) == page.PerPage {
+               nextPage = &JenkinsRemotePagination{
+                       Page:    page.Page + 1,
+                       PerPage: page.PerPage,
+               }
+       }
+       return
 }
 
-// SearchRemoteScopes use the Search API and only return project
-// @Summary use the Search API and only return project
-// @Description use the Search API and only return project
-// @Tags plugins/jenkins
+// RemoteScopes list all available scopes on the remote server
+// @Summary list all available scopes on the remote server
+// @Description list all available scopes on the remote server
 // @Accept application/json
 // @Param connectionId path int false "connection ID"
-// @Param search query string false "search"
-// @Param page query int false "page number"
-// @Param pageSize query int false "page size per page"
-// @Success 200  {object} api.SearchRemoteScopesOutput
+// @Param groupId query string false "group ID"
+// @Param pageToken query string false "page Token"
 // @Failure 400  {object} shared.ApiBody "Bad Request"
 // @Failure 500  {object} shared.ApiBody "Internal Error"
-// @Router /plugins/jenkins/connections/{connectionId}/search-remote-scopes 
[GET]
-func SearchRemoteScopes(input *plugin.ApiResourceInput) 
(*plugin.ApiResourceOutput, errors.Error) {
-       return remoteHelper.SearchRemoteScopes(input,
-               func(basicRes context.BasicRes, queryData *api.RemoteQueryData, 
connection models.JenkinsConnection) ([]models.Job, errors.Error) {
-                       apiClient, err := 
api.NewApiClientFromConnection(gocontext.TODO(), basicRes, &connection)
-                       if err != nil {
-                               return nil, errors.BadInput.Wrap(err, "failed 
to get create apiClient")
-                       }
-
-                       var resBody []models.Job
-                       breakError := errors.Default.New("we need break from 
get all jobs for page full")
-                       count := 0
-                       pageoOffset := (queryData.Page - 1) * queryData.PerPage
-                       err = GetAllJobs(apiClient, "", "", queryData.PerPage, 
func(job *models.Job, isPath bool) errors.Error {
-                               if job.Jobs == nil {
-                                       if strings.Contains(job.FullName, 
queryData.Search[0]) {
-                                               if count >= pageoOffset {
-                                                       resBody = 
append(resBody, *job)
-                                               }
-                                               count++
-                                       }
-                                       if len(resBody) > queryData.PerPage {
-                                               return breakError
-                                       }
-                               }
-                               return nil
-                       })
-                       if err != nil && err != breakError {
-                               return nil, errors.BadInput.Wrap(err, "failed 
to get create apiClient")
-                       }
+// @Success 200  {object} dsmodels.DsRemoteApiScopeList[models.JenkinsJob]
+// @Tags plugins/jenkins
+// @Router /plugins/jenkins/connections/{connectionId}/remote-scopes [GET]
+func RemoteScopes(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, 
errors.Error) {
+       return raScopeList.Get(input)
+}
 
-                       return resBody, nil
-               })
+// @Summary Remote server API proxy
+// @Description Forward API requests to the specified remote server
+// @Param connectionId path int true "connection ID"
+// @Param path path string true "path to a API endpoint"
+// @Router /plugins/github/connections/{connectionId}/proxy/{path} [GET]
+func Proxy(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, 
errors.Error) {
+       return raProxy.Proxy(input)
 }
diff --git a/backend/plugins/jenkins/api/scope.go 
b/backend/plugins/jenkins/api/scope_api.go
similarity index 93%
rename from backend/plugins/jenkins/api/scope.go
rename to backend/plugins/jenkins/api/scope_api.go
index 21e07c8f3..e39d9cecc 100644
--- a/backend/plugins/jenkins/api/scope.go
+++ b/backend/plugins/jenkins/api/scope_api.go
@@ -45,10 +45,10 @@ type ScopeReq api.ScopeReq[models.JenkinsJob]
 // @Failure 500  {object} shared.ApiBody "Internal Error"
 // @Router /plugins/jenkins/connections/{connectionId}/scopes [PUT]
 func PutScope(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, 
errors.Error) {
-       return scopeHelper.Put(input)
+       return dsHelper.ScopeApi.PutMultiple(input)
 }
 
-// UpdateScope patch to jenkins job
+// PatchScope patch to jenkins job
 // @Summary patch to jenkins job
 // @Description patch to jenkins job
 // @Tags plugins/jenkins
@@ -60,9 +60,9 @@ func PutScope(input *plugin.ApiResourceInput) 
(*plugin.ApiResourceOutput, errors
 // @Failure 400  {object} shared.ApiBody "Bad Request"
 // @Failure 500  {object} shared.ApiBody "Internal Error"
 // @Router /plugins/jenkins/connections/{connectionId}/scopes/{scopeId} [PATCH]
-func UpdateScope(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, 
errors.Error) {
+func PatchScope(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, 
errors.Error) {
        input.Params["scopeId"] = strings.TrimLeft(input.Params["scopeId"], "/")
-       return scopeHelper.Update(input)
+       return dsHelper.ScopeApi.Patch(input)
 }
 
 // GetScopeList get Jenkins jobs
@@ -79,7 +79,7 @@ func UpdateScope(input *plugin.ApiResourceInput) 
(*plugin.ApiResourceOutput, err
 // @Failure 500  {object} shared.ApiBody "Internal Error"
 // @Router /plugins/jenkins/connections/{connectionId}/scopes [GET]
 func GetScopeList(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, 
errors.Error) {
-       return scopeHelper.GetScopeList(input)
+       return dsHelper.ScopeApi.GetPage(input)
 }
 
 // GetScope get one Jenkins job
@@ -94,7 +94,7 @@ func GetScopeList(input *plugin.ApiResourceInput) 
(*plugin.ApiResourceOutput, er
 // @Router /plugins/jenkins/connections/{connectionId}/scopes/{scopeId} [GET]
 func GetScope(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, 
errors.Error) {
        input.Params["scopeId"] = strings.TrimLeft(input.Params["scopeId"], "/")
-       return scopeHelper.GetScope(input)
+       return dsHelper.ScopeApi.GetScopeDetail(input)
 }
 
 // DeleteScope delete plugin data associated with the scope and optionally the 
scope itself
@@ -110,5 +110,5 @@ func GetScope(input *plugin.ApiResourceInput) 
(*plugin.ApiResourceOutput, errors
 // @Failure 500  {object} shared.ApiBody "Internal Error"
 // @Router /plugins/jenkins/connections/{connectionId}/scopes/{scopeId} 
[DELETE]
 func DeleteScope(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, 
errors.Error) {
-       return scopeHelper.Delete(input)
+       return dsHelper.ScopeApi.Delete(input)
 }
diff --git a/backend/plugins/jenkins/api/scope_config.go 
b/backend/plugins/jenkins/api/scope_config_api.go
similarity index 94%
rename from backend/plugins/jenkins/api/scope_config.go
rename to backend/plugins/jenkins/api/scope_config_api.go
index fee76e6bb..2a9c82df7 100644
--- a/backend/plugins/jenkins/api/scope_config.go
+++ b/backend/plugins/jenkins/api/scope_config_api.go
@@ -34,7 +34,7 @@ import (
 // @Failure 500  {object} shared.ApiBody "Internal Error"
 // @Router /plugins/jenkins/connections/{connectionId}/scope-configs [POST]
 func CreateScopeConfig(input *plugin.ApiResourceInput) 
(*plugin.ApiResourceOutput, errors.Error) {
-       return scHelper.Create(input)
+       return dsHelper.ScopeConfigApi.Post(input)
 }
 
 // UpdateScopeConfig update scope config for Jenkins
@@ -50,7 +50,7 @@ func CreateScopeConfig(input *plugin.ApiResourceInput) 
(*plugin.ApiResourceOutpu
 // @Failure 500  {object} shared.ApiBody "Internal Error"
 // @Router /plugins/jenkins/connections/{connectionId}/scope-configs/{id} 
[PATCH]
 func UpdateScopeConfig(input *plugin.ApiResourceInput) 
(*plugin.ApiResourceOutput, errors.Error) {
-       return scHelper.Update(input)
+       return dsHelper.ScopeConfigApi.Patch(input)
 }
 
 // GetScopeConfig return one scope config
@@ -64,7 +64,7 @@ func UpdateScopeConfig(input *plugin.ApiResourceInput) 
(*plugin.ApiResourceOutpu
 // @Failure 500  {object} shared.ApiBody "Internal Error"
 // @Router /plugins/jenkins/connections/{connectionId}/scope-configs/{id} [GET]
 func GetScopeConfig(input *plugin.ApiResourceInput) 
(*plugin.ApiResourceOutput, errors.Error) {
-       return scHelper.Update(input)
+       return dsHelper.ScopeConfigApi.GetDetail(input)
 }
 
 // GetScopeConfigList return all scope configs
@@ -79,7 +79,7 @@ func GetScopeConfig(input *plugin.ApiResourceInput) 
(*plugin.ApiResourceOutput,
 // @Failure 500  {object} shared.ApiBody "Internal Error"
 // @Router /plugins/jenkins/connections/{connectionId}/scope-configs [GET]
 func GetScopeConfigList(input *plugin.ApiResourceInput) 
(*plugin.ApiResourceOutput, errors.Error) {
-       return scHelper.List(input)
+       return dsHelper.ScopeConfigApi.GetAll(input)
 }
 
 // DeleteScopeConfig delete a scope config
@@ -93,5 +93,5 @@ func GetScopeConfigList(input *plugin.ApiResourceInput) 
(*plugin.ApiResourceOutp
 // @Failure 500  {object} shared.ApiBody "Internal Error"
 // @Router /plugins/jenkins/connections/{connectionId}/scope-configs/{id} 
[DELETE]
 func DeleteScopeConfig(input *plugin.ApiResourceInput) 
(*plugin.ApiResourceOutput, errors.Error) {
-       return scHelper.Delete(input)
+       return dsHelper.ScopeConfigApi.Delete(input)
 }
diff --git a/backend/plugins/jenkins/impl/impl.go 
b/backend/plugins/jenkins/impl/impl.go
index 8dee70297..db5bc2fe0 100644
--- a/backend/plugins/jenkins/impl/impl.go
+++ b/backend/plugins/jenkins/impl/impl.go
@@ -186,12 +186,12 @@ func (p Jenkins) ApiResources() 
map[string]map[string]plugin.ApiResourceHandler
                "connections/:connectionId/test": {
                        "POST": api.TestExistingConnection,
                },
-               "connections/:connectionId/search-remote-scopes": {
-                       "GET": api.SearchRemoteScopes,
-               },
+               // "connections/:connectionId/search-remote-scopes": {
+               //      "GET": api.SearchRemoteScopes,
+               // },
                "connections/:connectionId/scopes/*scopeId": {
                        "GET":    api.GetScope,
-                       "PATCH":  api.UpdateScope,
+                       "PATCH":  api.PatchScope,
                        "DELETE": api.DeleteScope,
                },
                "connections/:connectionId/scopes": {
@@ -250,7 +250,7 @@ func EnrichOptions(taskCtx plugin.TaskContext,
        err = api.GetJob(apiClient, op.JobPath, op.JobName, op.JobFullName, 
100, func(job *models.Job, isPath bool) errors.Error {
                log.Debug(fmt.Sprintf("Current job: %s", job.FullName))
                op.JobPath = job.Path
-               jenkinsJob := job.ConvertApiScope().(*models.JenkinsJob)
+               jenkinsJob := job.ToJenkinsJob()
 
                jenkinsJob.ConnectionId = op.ConnectionId
                jenkinsJob.ScopeConfigId = op.ScopeConfigId
diff --git a/backend/plugins/jenkins/models/response.go 
b/backend/plugins/jenkins/models/response.go
index 42fd079f8..643bec691 100644
--- a/backend/plugins/jenkins/models/response.go
+++ b/backend/plugins/jenkins/models/response.go
@@ -19,8 +19,6 @@ package models
 
 import (
        "strings"
-
-       "github.com/apache/incubator-devlake/core/plugin"
 )
 
 type Job struct {
@@ -45,7 +43,7 @@ func (j Job) GroupName() string {
        return j.Name
 }
 
-func (j Job) ConvertApiScope() plugin.ToolLayerScope {
+func (j Job) ToJenkinsJob() *JenkinsJob {
        if j.FullName == "" {
                if j.Name != "" || j.Path != "" {
                        beforeNames := strings.Split(j.Path, "/")

Reply via email to