This is an automated email from the ASF dual-hosted git repository.
warren 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 dca268280 Bamboo scopes and remote api (#4461)
dca268280 is described below
commit dca268280fae478f5433a2589e34489458961c0c
Author: mappjzc <[email protected]>
AuthorDate: Tue Feb 21 20:43:42 2023 +0800
Bamboo scopes and remote api (#4461)
* feat: bamboo blueprint
Add bamboo blueprint.
Nddtfjiang <[email protected]>
* fix: fix for merge
fix for merge
Nddtfjiang <[email protected]>
* feat: add scopes and remote
Add scopes and remote api for bamboo
Nddtfjiang <[email protected]>
* feat: scope and remote api for bamboo
Add scope and remote api for bamboo
Nddtfjiang <[email protected]>
---
backend/plugins/bamboo/api/blueprint_V200_test.go | 11 +-
backend/plugins/bamboo/api/blueprint_v200.go | 8 +-
backend/plugins/bamboo/api/remote.go | 302 +++++++++++++++++++++
backend/plugins/{sonarqube => bamboo}/api/scope.go | 153 +++++++----
backend/plugins/bamboo/impl/impl.go | 15 +
backend/plugins/bamboo/models/job.go | 21 +-
.../migrationscripts/20230216_add_init_tables.go | 2 +-
.../models/migrationscripts/archived/project.go | 16 +-
backend/plugins/bamboo/models/plan.go | 39 ++-
backend/plugins/bamboo/models/project.go | 19 ++
backend/plugins/bamboo/tasks/job_extractor.go | 4 +-
backend/plugins/bamboo/tasks/plan_extractor.go | 4 +-
backend/plugins/sonarqube/api/scope.go | 4 +-
13 files changed, 496 insertions(+), 102 deletions(-)
diff --git a/backend/plugins/bamboo/api/blueprint_V200_test.go
b/backend/plugins/bamboo/api/blueprint_V200_test.go
index 3622b93c2..e9f1f4b43 100644
--- a/backend/plugins/bamboo/api/blueprint_V200_test.go
+++ b/backend/plugins/bamboo/api/blueprint_V200_test.go
@@ -30,6 +30,7 @@ import (
helper "github.com/apache/incubator-devlake/helpers/pluginhelper/api"
"github.com/apache/incubator-devlake/helpers/unithelper"
"github.com/apache/incubator-devlake/plugins/bamboo/models"
+ "github.com/apache/incubator-devlake/plugins/bamboo/tasks"
"github.com/go-playground/validator/v10"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
@@ -94,13 +95,17 @@ func TestMakeDataSourcePipelinePlanV200(t *testing.T) {
var expectRepoId = "bamboo:BambooProject:1:TEST"
- var testSubTaskMeta = []plugin.SubTaskMeta{}
+ var testSubTaskMeta = []plugin.SubTaskMeta{
+ tasks.ConvertProjectsMeta,
+ }
var expectPlans = plugin.PipelinePlan{
{
{
- Plugin: "bamboo",
- Subtasks: []string{},
+ Plugin: "bamboo",
+ Subtasks: []string{
+ tasks.ConvertProjectsMeta.Name,
+ },
Options: map[string]interface{}{
"connectionId": uint64(1),
"projectKey": testKey,
diff --git a/backend/plugins/bamboo/api/blueprint_v200.go
b/backend/plugins/bamboo/api/blueprint_v200.go
index d627b0973..d7fd92815 100644
--- a/backend/plugins/bamboo/api/blueprint_v200.go
+++ b/backend/plugins/bamboo/api/blueprint_v200.go
@@ -67,7 +67,7 @@ func makeScopeV200(connectionId uint64, scopes
[]*plugin.BlueprintScopeV200) ([]
id :=
didgen.NewDomainIdGenerator(&models.BambooProject{}).Generate(connectionId,
scope.Id)
// get project from db
- BambooProject, err :=
GetprojectByConnectionIdAndscopeId(connectionId, scope.Id)
+ BambooProject, err :=
GetProjectByConnectionIdAndscopeId(connectionId, scope.Id)
if err != nil {
return nil, err
}
@@ -93,7 +93,7 @@ func makePipelinePlanV200(
var stage plugin.PipelineStage
var err errors.Error
// get project
- project, err :=
GetprojectByConnectionIdAndscopeId(connection.ID, scope.Id)
+ project, err :=
GetProjectByConnectionIdAndscopeId(connection.ID, scope.Id)
if err != nil {
return nil, err
}
@@ -127,8 +127,8 @@ func makePipelinePlanV200(
return plans, nil
}
-// GetprojectByConnectionIdAndscopeId get tbe project by the connectionId and
the scopeId
-func GetprojectByConnectionIdAndscopeId(connectionId uint64, scopeId string)
(*models.BambooProject, errors.Error) {
+// GetProjectByConnectionIdAndscopeId get tbe project by the connectionId and
the scopeId
+func GetProjectByConnectionIdAndscopeId(connectionId uint64, scopeId string)
(*models.BambooProject, errors.Error) {
key := scopeId
project := &models.BambooProject{}
db := basicRes.GetDal()
diff --git a/backend/plugins/bamboo/api/remote.go
b/backend/plugins/bamboo/api/remote.go
new file mode 100644
index 000000000..250571390
--- /dev/null
+++ b/backend/plugins/bamboo/api/remote.go
@@ -0,0 +1,302 @@
+/*
+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/base64"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "net/url"
+ "strconv"
+
+ "github.com/apache/incubator-devlake/core/errors"
+ "github.com/apache/incubator-devlake/core/plugin"
+ "github.com/apache/incubator-devlake/helpers/pluginhelper/api"
+ "github.com/apache/incubator-devlake/plugins/bamboo/models"
+)
+
+type RemoteScopesChild struct {
+ Type string `json:"type"`
+ ParentId *string `json:"parentId"`
+ Id string `json:"id"`
+ Name string `json:"name"`
+ Data interface{} `json:"data"`
+}
+
+type RemoteScopesOutput struct {
+ Children []RemoteScopesChild `json:"children"`
+ NextPageToken string `json:"nextPageToken"`
+}
+
+type SearchRemoteScopesOutput struct {
+ Children []RemoteScopesChild `json:"children"`
+ Page int `json:"page"`
+ PageSize int `json:"pageSize"`
+}
+
+type PageData struct {
+ Page int `json:"page"`
+ PageSize int `json:"per_page"`
+}
+
+const BambooRemoteScopesPerPage int = 100
+const TypeProject string = "scope"
+const TypeGroup string = "group"
+
+// RemoteScopes list all available scope for users
+// @Summary list all available scope for users
+// @Description list all available scope for users
+// @Tags plugins/bamboo
+// @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} RemoteScopesOutput
+// @Failure 400 {object} shared.ApiBody "Bad Request"
+// @Failure 500 {object} shared.ApiBody "Internal Error"
+// @Router /plugins/bamboo/connections/{connectionId}/remote-scopes [GET]
+func RemoteScopes(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput,
errors.Error) {
+ connectionId, _ := extractParam(input.Params)
+ if connectionId == 0 {
+ return nil, errors.BadInput.New("invalid connectionId")
+ }
+
+ connection := &models.BambooConnection{}
+ err := connectionHelper.First(connection, input.Params)
+ if err != nil {
+ return nil, err
+ }
+
+ pageToken, ok := input.Query["pageToken"]
+ if !ok || len(pageToken) == 0 {
+ pageToken = []string{""}
+ }
+
+ // get pageData
+ pageData, err := GetPageDataFromPageToken(pageToken[0])
+ if err != nil {
+ return nil, errors.BadInput.New("failed to get paget token")
+ }
+
+ // create api client
+ apiClient, err := api.NewApiClientFromConnection(context.TODO(),
basicRes, connection)
+ if err != nil {
+ return nil, err
+ }
+
+ var res *http.Response
+ outputBody := &RemoteScopesOutput{}
+
+ query := GetQueryFromPageData(pageData)
+
+ res, err = apiClient.Get("/project.json", query, nil)
+
+ if err != nil {
+ return nil, err
+ }
+
+ resBody := models.ApiBambooProjectResponse{}
+ err = api.UnmarshalResponse(res, &resBody)
+ if err != nil {
+ return nil, err
+ }
+
+ // append project to output
+ for _, apiProject := range resBody.Projects.Projects {
+ project := &models.BambooProject{}
+ project.Convert(&apiProject)
+ child := RemoteScopesChild{
+ Type: TypeProject,
+ ParentId: nil,
+ Id: project.ProjectKey,
+ Name: project.Name,
+ Data: project,
+ }
+
+ outputBody.Children = append(outputBody.Children, child)
+ }
+
+ // check project count
+ if len(resBody.Projects.Projects) < pageData.PageSize {
+ pageData = nil
+ }
+
+ // get the next page token
+ outputBody.NextPageToken = ""
+ if pageData != nil {
+ pageData.Page += 1
+ pageData.PageSize = BambooRemoteScopesPerPage
+
+ outputBody.NextPageToken, err =
GetPageTokenFromPageData(pageData)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ return &plugin.ApiResourceOutput{Body: outputBody, Status:
http.StatusOK}, nil
+}
+
+// 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/bamboo
+// @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} SearchRemoteScopesOutput
+// @Failure 400 {object} shared.ApiBody "Bad Request"
+// @Failure 500 {object} shared.ApiBody "Internal Error"
+// @Router /plugins/bamboo/connections/{connectionId}/search-remote-scopes
[GET]
+func SearchRemoteScopes(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput, errors.Error) {
+ connectionId, _ := extractParam(input.Params)
+ if connectionId == 0 {
+ return nil, errors.BadInput.New("invalid connectionId")
+ }
+
+ connection := &models.BambooConnection{}
+ err := connectionHelper.First(connection, input.Params)
+ if err != nil {
+ return nil, err
+ }
+
+ search, ok := input.Query["search"]
+ if !ok || len(search) == 0 {
+ search = []string{""}
+ }
+
+ var p int
+ var err1 error
+ page, ok := input.Query["page"]
+ if !ok || len(page) == 0 {
+ p = 1
+ } else {
+ p, err1 = strconv.Atoi(page[0])
+ if err != nil {
+ return nil, errors.BadInput.Wrap(err1,
fmt.Sprintf("failed to Atoi page:%s", page[0]))
+ }
+ }
+ var ps int
+ pageSize, ok := input.Query["pageSize"]
+ if !ok || len(pageSize) == 0 {
+ ps = BambooRemoteScopesPerPage
+ } else {
+ ps, err1 = strconv.Atoi(pageSize[0])
+ if err1 != nil {
+ return nil, errors.BadInput.Wrap(err1,
fmt.Sprintf("failed to Atoi pageSize:%s", pageSize[0]))
+ }
+ }
+ // create api client
+ apiClient, err := api.NewApiClientFromConnection(context.TODO(),
basicRes, connection)
+ if err != nil {
+ return nil, err
+ }
+
+ // set query
+ query := GetQueryForSearchProject(search[0], p, ps)
+
+ // request search
+ res, err := apiClient.Get("search/projects.json", query, nil)
+ if err != nil {
+ return nil, err
+ }
+ resBody := models.ApiBambooSearchProjectResponse{}
+ err = api.UnmarshalResponse(res, &resBody)
+ if err != nil {
+ return nil, err
+ }
+
+ outputBody := &SearchRemoteScopesOutput{}
+
+ // append project to output
+ for _, apiResult := range resBody.SearchResults {
+ var project models.BambooProject
+ apiProject, err := GetApiProject(apiResult.SearchEntity.Key,
apiClient)
+ if err != nil {
+ return nil, err
+ }
+
+ project.Convert(apiProject)
+ child := RemoteScopesChild{
+ Type: TypeProject,
+ Id: project.ProjectKey,
+ ParentId: nil,
+ Name: project.Name,
+ Data: project,
+ }
+
+ outputBody.Children = append(outputBody.Children, child)
+ }
+
+ outputBody.Page = p
+ outputBody.PageSize = ps
+
+ return &plugin.ApiResourceOutput{Body: outputBody, Status:
http.StatusOK}, nil
+}
+
+func GetPageTokenFromPageData(pageData *PageData) (string, errors.Error) {
+ // Marshal json
+ pageTokenDecode, err := json.Marshal(pageData)
+ if err != nil {
+ return "", errors.Default.Wrap(err, fmt.Sprintf("Marshal
pageToken failed %+v", pageData))
+ }
+
+ // Encode pageToken Base64
+ return base64.StdEncoding.EncodeToString(pageTokenDecode), nil
+}
+
+func GetPageDataFromPageToken(pageToken string) (*PageData, errors.Error) {
+ if pageToken == "" {
+ return &PageData{
+ Page: 1,
+ PageSize: BambooRemoteScopesPerPage,
+ }, nil
+ }
+
+ // Decode pageToken Base64
+ pageTokenDecode, err := base64.StdEncoding.DecodeString(pageToken)
+ if err != nil {
+ return nil, errors.Default.Wrap(err, fmt.Sprintf("decode
pageToken failed %s", pageToken))
+ }
+ // Unmarshal json
+ pt := &PageData{}
+ err = json.Unmarshal(pageTokenDecode, pt)
+ if err != nil {
+ return nil, errors.Default.Wrap(err, fmt.Sprintf("json
Unmarshal pageTokenDecode failed %s", pageTokenDecode))
+ }
+
+ return pt, nil
+}
+
+func GetQueryFromPageData(pageData *PageData) url.Values {
+ query := url.Values{}
+ query.Set("showEmpty", fmt.Sprintf("%v", true))
+ query.Set("max-result", fmt.Sprintf("%v", pageData.PageSize))
+ query.Set("start-index", fmt.Sprintf("%v",
(pageData.Page-1)*pageData.PageSize))
+ return query
+}
+
+func GetQueryForSearchProject(search string, page int, perPage int) url.Values
{
+ query := GetQueryFromPageData(&PageData{Page: page, PageSize: perPage})
+ query.Set("searchTerm", search)
+
+ return query
+}
diff --git a/backend/plugins/sonarqube/api/scope.go
b/backend/plugins/bamboo/api/scope.go
similarity index 54%
copy from backend/plugins/sonarqube/api/scope.go
copy to backend/plugins/bamboo/api/scope.go
index 063020133..703f20a39 100644
--- a/backend/plugins/sonarqube/api/scope.go
+++ b/backend/plugins/bamboo/api/scope.go
@@ -18,6 +18,7 @@ limitations under the License.
package api
import (
+ "context"
"net/http"
"strconv"
@@ -25,34 +26,40 @@ import (
"github.com/apache/incubator-devlake/core/errors"
"github.com/apache/incubator-devlake/core/plugin"
"github.com/apache/incubator-devlake/helpers/pluginhelper/api"
- "github.com/apache/incubator-devlake/plugins/sonarqube/models"
+ "github.com/apache/incubator-devlake/plugins/bamboo/models"
+ "github.com/mitchellh/mapstructure"
)
+type apiProject struct {
+ models.BambooProject
+ TransformationRuleName string `json:"transformationRuleName,omitempty"`
+}
+
type req struct {
- Data []*models.SonarqubeProject `json:"data"`
+ Data []*models.BambooProject `json:"data"`
}
-// PutScope create or update sonarqube project
-// @Summary create or update sonarqube project
-// @Description Create or update sonarqube project
-// @Tags plugins/sonarqube
+// PutScope create or update bamboo project
+// @Summary create or update bamboo project
+// @Description Create or update bamboo project
+// @Tags plugins/bamboo
// @Accept application/json
// @Param connectionId path int false "connection ID"
// @Param scope body req true "json"
-// @Success 200 {object} []models.SonarqubeProject
+// @Success 200 {object} []models.BambooProject
// @Failure 400 {object} shared.ApiBody "Bad Request"
// @Failure 500 {object} shared.ApiBody "Internal Error"
-// @Router /plugins/sonarqube/connections/{connectionId}/scopes [PUT]
+// @Router /plugins/bamboo/connections/{connectionId}/scopes [PUT]
func PutScope(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput,
errors.Error) {
connectionId, _ := extractParam(input.Params)
+
if connectionId == 0 {
return nil, errors.BadInput.New("invalid connectionId")
}
var projects req
- // As we need to process *api.Iso8601Time, we need to use
DecodeMapStruct instead of mapstructure.Decode
- err := errors.Convert(api.DecodeMapStruct(input.Body, &projects))
+ err := errors.Convert(mapstructure.Decode(input.Body, &projects))
if err != nil {
- return nil, errors.BadInput.Wrap(err, "decoding Sonarqube
project error")
+ return nil, errors.BadInput.Wrap(err, "decoding Bamboo project
error")
}
keeper := make(map[string]struct{})
for _, project := range projects.Data {
@@ -69,36 +76,36 @@ func PutScope(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput, errors
}
err = basicRes.GetDal().CreateOrUpdate(projects.Data)
if err != nil {
- return nil, errors.Default.Wrap(err, "error on saving
SonarqubeProject")
+ return nil, errors.Default.Wrap(err, "error on saving
BambooProject")
}
return &plugin.ApiResourceOutput{Body: projects.Data, Status:
http.StatusOK}, nil
}
-// UpdateScope patch to sonarqube project
-// @Summary patch to sonarqube project
-// @Description patch to sonarqube project
-// @Tags plugins/sonarqube
+// UpdateScope patch to bamboo project
+// @Summary patch to bamboo project
+// @Description patch to bamboo project
+// @Tags plugins/bamboo
// @Accept application/json
// @Param connectionId path int false "connection ID"
-// @Param projectKey path string false "project Key"
-// @Param scope body models.SonarqubeProject true "json"
-// @Success 200 {object} models.SonarqubeProject
+// @Param projectKey path int false "project ID"
+// @Param scope body models.BambooProject true "json"
+// @Success 200 {object} models.BambooProject
// @Failure 400 {object} shared.ApiBody "Bad Request"
// @Failure 500 {object} shared.ApiBody "Internal Error"
-// @Router /plugins/sonarqube/connections/{connectionId}/scopes/{projectKey}
[PATCH]
+// @Router /plugins/bamboo/connections/{connectionId}/scopes/{projectKey}
[PATCH]
func UpdateScope(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput,
errors.Error) {
connectionId, projectKey := extractParam(input.Params)
- if connectionId*uint64(len(projectKey)) == 0 {
- return nil, errors.BadInput.New("invalid connectionId or
projectKey")
+ if connectionId == 0 || projectKey == "" {
+ return nil, errors.BadInput.New("invalid path params")
}
- var project models.SonarqubeProject
+ var project models.BambooProject
err := basicRes.GetDal().First(&project, dal.Where("connection_id = ?
AND project_key = ?", connectionId, projectKey))
if err != nil {
- return nil, errors.Default.Wrap(err, "getting SonarqubeProject
error")
+ return nil, errors.Default.Wrap(err, "getting BambooProject
error")
}
err = api.DecodeMapStruct(input.Body, &project)
if err != nil {
- return nil, errors.Default.Wrap(err, "patch sonarqube project
error")
+ return nil, errors.Default.Wrap(err, "patch bamboo project
error")
}
err = verifyProject(&project)
if err != nil {
@@ -106,22 +113,22 @@ func UpdateScope(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput, err
}
err = basicRes.GetDal().Update(project)
if err != nil {
- return nil, errors.Default.Wrap(err, "error on saving
SonarqubeProject")
+ return nil, errors.Default.Wrap(err, "error on saving
BambooProject")
}
return &plugin.ApiResourceOutput{Body: project, Status: http.StatusOK},
nil
}
-// GetScopeList get Sonarqube projects
-// @Summary get Sonarqube projects
-// @Description get Sonarqube projects
-// @Tags plugins/sonarqube
+// GetScopeList get Bamboo projects
+// @Summary get Bamboo projects
+// @Description get Bamboo projects
+// @Tags plugins/bamboo
// @Param connectionId path int false "connection ID"
// @Success 200 {object} []apiProject
// @Failure 400 {object} shared.ApiBody "Bad Request"
// @Failure 500 {object} shared.ApiBody "Internal Error"
-// @Router /plugins/sonarqube/connections/{connectionId}/scopes/ [GET]
+// @Router /plugins/bamboo/connections/{connectionId}/scopes/ [GET]
func GetScopeList(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput,
errors.Error) {
- var projects []models.SonarqubeProject
+ var projects []models.BambooProject
connectionId, _ := extractParam(input.Params)
if connectionId == 0 {
return nil, errors.BadInput.New("invalid path params")
@@ -131,38 +138,86 @@ func GetScopeList(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput, er
if err != nil {
return nil, err
}
-
- return &plugin.ApiResourceOutput{Body: projects, Status:
http.StatusOK}, nil
+ var ruleIds []uint64
+ for _, proj := range projects {
+ if proj.TransformationRuleId > 0 {
+ ruleIds = append(ruleIds, proj.TransformationRuleId)
+ }
+ }
+ var rules []models.BambooTransformationRule
+ if len(ruleIds) > 0 {
+ err = basicRes.GetDal().All(&rules, dal.Where("id IN (?)",
ruleIds))
+ if err != nil {
+ return nil, err
+ }
+ }
+ names := make(map[uint64]string)
+ for _, rule := range rules {
+ names[rule.ID] = rule.Name
+ }
+ var apiProjects []apiProject
+ for _, proj := range projects {
+ apiProjects = append(apiProjects, apiProject{proj,
names[proj.TransformationRuleId]})
+ }
+ return &plugin.ApiResourceOutput{Body: apiProjects, Status:
http.StatusOK}, nil
}
-// GetScope get one Sonarqube project
-// @Summary get one Sonarqube project
-// @Description get one Sonarqube project
-// @Tags plugins/sonarqube
+// GetScope get one Bamboo project
+// @Summary get one Bamboo project
+// @Description get one Bamboo project
+// @Tags plugins/bamboo
// @Param connectionId path int false "connection ID"
-// @Param projectKey path string false "project key"
+// @Param projectKey path int false "project ID"
// @Param pageSize query int false "page size, default 50"
// @Param page query int false "page size, default 1"
// @Success 200 {object} apiProject
// @Failure 400 {object} shared.ApiBody "Bad Request"
// @Failure 500 {object} shared.ApiBody "Internal Error"
-// @Router /plugins/sonarqube/connections/{connectionId}/scopes/{projectKey}
[GET]
+// @Router /plugins/bamboo/connections/{connectionId}/scopes/{projectKey} [GET]
func GetScope(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput,
errors.Error) {
- var project models.SonarqubeProject
+ var project models.BambooProject
connectionId, projectKey := extractParam(input.Params)
- if connectionId*uint64(len(projectKey)) == 0 {
+ if connectionId == 0 || projectKey == "" {
return nil, errors.BadInput.New("invalid path params")
}
db := basicRes.GetDal()
err := db.First(&project, dal.Where("connection_id = ? AND project_key
= ?", connectionId, projectKey))
- if db.IsErrorNotFound(err) {
+ if err != nil && db.IsErrorNotFound(err) {
+ var scope models.BambooProject
+ connection := &models.BambooConnection{}
+ err = connectionHelper.First(connection, input.Params)
+ if err != nil {
+ return nil, err
+ }
+ apiClient, err :=
api.NewApiClientFromConnection(context.TODO(), basicRes, connection)
+ if err != nil {
+ return nil, err
+ }
+
+ apiProject, err := GetApiProject(projectKey, apiClient)
+ if err != nil {
+ return nil, err
+ }
+
+ scope.Convert(apiProject)
+ scope.ConnectionId = connectionId
+ err = db.CreateIfNotExist(&scope)
+ if err != nil {
+ return nil, err
+ }
return nil, errors.NotFound.New("record not found")
- }
- if err != nil {
+ } else if err != nil {
return nil, err
}
- return &plugin.ApiResourceOutput{Body: project, Status: http.StatusOK},
nil
+ var rule models.BambooTransformationRule
+ if project.TransformationRuleId > 0 {
+ err = basicRes.GetDal().First(&rule, dal.Where("id = ?",
project.TransformationRuleId))
+ if err != nil {
+ return nil, err
+ }
+ }
+ return &plugin.ApiResourceOutput{Body: apiProject{project, rule.Name},
Status: http.StatusOK}, nil
}
func extractParam(params map[string]string) (uint64, string) {
@@ -171,12 +226,12 @@ func extractParam(params map[string]string) (uint64,
string) {
return connectionId, projectKey
}
-func verifyProject(project *models.SonarqubeProject) errors.Error {
+func verifyProject(project *models.BambooProject) errors.Error {
if project.ConnectionId == 0 {
return errors.BadInput.New("invalid connectionId")
}
- if len(project.ProjectKey) == 0 {
- return errors.BadInput.New("invalid project key")
+ if project.ProjectKey == "" {
+ return errors.BadInput.New("invalid projectKey")
}
return nil
}
diff --git a/backend/plugins/bamboo/impl/impl.go
b/backend/plugins/bamboo/impl/impl.go
index d8fe3b244..70cb8ede7 100644
--- a/backend/plugins/bamboo/impl/impl.go
+++ b/backend/plugins/bamboo/impl/impl.go
@@ -19,6 +19,7 @@ package impl
import (
"fmt"
+
"github.com/apache/incubator-devlake/core/context"
"github.com/apache/incubator-devlake/core/dal"
"github.com/apache/incubator-devlake/core/errors"
@@ -186,6 +187,20 @@ func (p Bamboo) ApiResources()
map[string]map[string]plugin.ApiResourceHandler {
"PATCH": api.PatchConnection,
"DELETE": api.DeleteConnection,
},
+ "connections/:connectionId/scopes": {
+ "GET": api.GetScopeList,
+ "PUT": api.PutScope,
+ },
+ "connections/:connectionId/remote-scopes": {
+ "GET": api.RemoteScopes,
+ },
+ "connections/:connectionId/search-remote-scopes": {
+ "GET": api.SearchRemoteScopes,
+ },
+ "connections/:connectionId/scopes/:projectKey": {
+ "GET": api.GetScope,
+ "PATCH": api.UpdateScope,
+ },
}
}
diff --git a/backend/plugins/bamboo/models/job.go
b/backend/plugins/bamboo/models/job.go
index 6ee00dc08..a47a7950a 100644
--- a/backend/plugins/bamboo/models/job.go
+++ b/backend/plugins/bamboo/models/job.go
@@ -37,18 +37,15 @@ type BambooJob struct {
common.NoPKModel
}
-func (BambooJob) Convert(apiRes *ApiBambooJob) *BambooJob {
- b := &BambooJob{
- JobKey: apiRes.SearchEntity.Key,
- Id: apiRes.Id,
- Name: apiRes.SearchEntity.JobName,
- PlanName: apiRes.SearchEntity.PlanName,
- ProjectName: apiRes.SearchEntity.ProjectName,
- Description: apiRes.SearchEntity.Description,
- BranchName: apiRes.SearchEntity.BranchName,
- Type: apiRes.SearchEntity.Type,
- }
- return b
+func (b *BambooJob) Convert(apiRes *ApiBambooJob) {
+ b.JobKey = apiRes.SearchEntity.Key
+ b.Id = apiRes.Id
+ b.Name = apiRes.SearchEntity.JobName
+ b.PlanName = apiRes.SearchEntity.PlanName
+ b.ProjectName = apiRes.SearchEntity.ProjectName
+ b.Description = apiRes.SearchEntity.Description
+ b.BranchName = apiRes.SearchEntity.BranchName
+ b.Type = apiRes.SearchEntity.Type
}
func (BambooJob) TableName() string {
diff --git
a/backend/plugins/bamboo/models/migrationscripts/20230216_add_init_tables.go
b/backend/plugins/bamboo/models/migrationscripts/20230216_add_init_tables.go
index c78946a2e..bfb399c34 100644
--- a/backend/plugins/bamboo/models/migrationscripts/20230216_add_init_tables.go
+++ b/backend/plugins/bamboo/models/migrationscripts/20230216_add_init_tables.go
@@ -48,7 +48,7 @@ func (u *addInitTables) Up(baseRes context.BasicRes)
errors.Error {
}
func (*addInitTables) Version() uint64 {
- return 20230216205037
+ return 20230221205032
}
func (*addInitTables) Name() string {
diff --git a/backend/plugins/bamboo/models/migrationscripts/archived/project.go
b/backend/plugins/bamboo/models/migrationscripts/archived/project.go
index 0ac9d3b8d..ccabf8ef1 100644
--- a/backend/plugins/bamboo/models/migrationscripts/archived/project.go
+++ b/backend/plugins/bamboo/models/migrationscripts/archived/project.go
@@ -22,14 +22,14 @@ import (
)
type BambooProject struct {
- ConnectionId uint64 `gorm:"primaryKey"`
- ProjectKey string `gorm:"primaryKey;type:varchar(100)"`
- Expand string `json:"expand"`
- Name string `gorm:"index;type:varchar(100)"`
- Description string `json:"description"`
- Href string `json:"link"`
- Rel string `gorm:"type:varchar(100)"`
- archived.NoPKModel
+ ConnectionId uint64 `json:"connectionId"
mapstructure:"connectionId" gorm:"primaryKey"`
+ ProjectKey string `json:"projectKey"
gorm:"primaryKey;type:varchar(256)"`
+ TransformationRuleId uint64 `json:"transformationRuleId,omitempty"
mapstructure:"transformationRuleId"`
+ Name string `json:"name" gorm:"index;type:varchar(256)"`
+ Description string `json:"description"`
+ Href string `json:"link"`
+ Rel string `json:"rel" gorm:"type:varchar(100)"`
+ archived.NoPKModel `json:"-" mapstructure:"-"`
}
func (BambooProject) TableName() string {
diff --git a/backend/plugins/bamboo/models/plan.go
b/backend/plugins/bamboo/models/plan.go
index 4720f8842..8b35ae4f5 100644
--- a/backend/plugins/bamboo/models/plan.go
+++ b/backend/plugins/bamboo/models/plan.go
@@ -43,27 +43,24 @@ type BambooPlan struct {
common.NoPKModel
}
-func (BambooPlan) Convert(apiProject *ApiBambooPlan) *BambooPlan {
- b := &BambooPlan{
- PlanKey: apiProject.Key,
- Name: apiProject.Name,
- Expand: apiProject.Expand,
- ProjectKey: apiProject.ProjectKey,
- ProjectName: apiProject.ProjectName,
- Description: apiProject.Description,
- ShortName: apiProject.ShortName,
- BuildName: apiProject.BuildName,
- ShortKey: apiProject.ShortKey,
- Type: apiProject.Type,
- Enabled: apiProject.Enabled,
- Href: apiProject.Href,
- Rel: apiProject.Rel,
- IsFavourite: apiProject.IsFavourite,
- IsActive: apiProject.IsActive,
- IsBuilding: apiProject.IsBuilding,
- AverageBuildTimeInSeconds: apiProject.AverageBuildTimeInSeconds,
- }
- return b
+func (b *BambooPlan) Convert(apiProject *ApiBambooPlan) {
+ b.PlanKey = apiProject.Key
+ b.Name = apiProject.Name
+ b.Expand = apiProject.Expand
+ b.ProjectKey = apiProject.ProjectKey
+ b.ProjectName = apiProject.ProjectName
+ b.Description = apiProject.Description
+ b.ShortName = apiProject.ShortName
+ b.BuildName = apiProject.BuildName
+ b.ShortKey = apiProject.ShortKey
+ b.Type = apiProject.Type
+ b.Enabled = apiProject.Enabled
+ b.Href = apiProject.Href
+ b.Rel = apiProject.Rel
+ b.IsFavourite = apiProject.IsFavourite
+ b.IsActive = apiProject.IsActive
+ b.IsBuilding = apiProject.IsBuilding
+ b.AverageBuildTimeInSeconds = apiProject.AverageBuildTimeInSeconds
}
func (BambooPlan) TableName() string {
diff --git a/backend/plugins/bamboo/models/project.go
b/backend/plugins/bamboo/models/project.go
index d8b903351..89e7caa4b 100644
--- a/backend/plugins/bamboo/models/project.go
+++ b/backend/plugins/bamboo/models/project.go
@@ -19,6 +19,7 @@ package models
import (
"encoding/json"
+
"github.com/apache/incubator-devlake/core/models/common"
)
@@ -70,3 +71,21 @@ type ApiBambooProjectResponse struct {
Link ApiBambooLink `json:"link"`
Projects ApiBambooProjects `json:"projects"`
}
+
+type ApiSearchEntityProject struct {
+ Id string `json:"id"`
+ Key string `json:"key"`
+ ProjectName string `json:"projectName"`
+ Description string `json:"description"`
+}
+
+type ApiSearchResultProjects struct {
+ Id string `json:"id"`
+ Type string `json:"type"`
+ SearchEntity ApiSearchEntityProject `json:"searchResults"`
+}
+
+type ApiBambooSearchProjectResponse struct {
+ ApiBambooSizeData `json:"squash"`
+ SearchResults []ApiSearchResultProjects `json:"searchResults"`
+}
diff --git a/backend/plugins/bamboo/tasks/job_extractor.go
b/backend/plugins/bamboo/tasks/job_extractor.go
index 74515fcbf..5668eabeb 100644
--- a/backend/plugins/bamboo/tasks/job_extractor.go
+++ b/backend/plugins/bamboo/tasks/job_extractor.go
@@ -19,6 +19,7 @@ package tasks
import (
"encoding/json"
+
"github.com/apache/incubator-devlake/core/errors"
"github.com/apache/incubator-devlake/core/plugin"
helper "github.com/apache/incubator-devlake/helpers/pluginhelper/api"
@@ -44,7 +45,8 @@ func ExtractJob(taskCtx plugin.SubTaskContext) errors.Error {
if err != nil {
return nil, err
}
- body := models.BambooJob{}.Convert(res)
+ body := &models.BambooJob{}
+ body.Convert(res)
body.ConnectionId = data.Options.ConnectionId
body.ProjectKey = data.Options.ProjectKey
body.PlanKey = plan.PlanKey
diff --git a/backend/plugins/bamboo/tasks/plan_extractor.go
b/backend/plugins/bamboo/tasks/plan_extractor.go
index 5174b7b5e..43d92e0f1 100644
--- a/backend/plugins/bamboo/tasks/plan_extractor.go
+++ b/backend/plugins/bamboo/tasks/plan_extractor.go
@@ -19,6 +19,7 @@ package tasks
import (
"encoding/json"
+
"github.com/apache/incubator-devlake/core/errors"
"github.com/apache/incubator-devlake/core/plugin"
helper "github.com/apache/incubator-devlake/helpers/pluginhelper/api"
@@ -39,7 +40,8 @@ func ExtractPlan(taskCtx plugin.SubTaskContext) errors.Error {
if err != nil {
return nil, err
}
- body := models.BambooPlan{}.Convert(res)
+ body := &models.BambooPlan{}
+ body.Convert(res)
body.ConnectionId = data.Options.ConnectionId
return []interface{}{body}, nil
},
diff --git a/backend/plugins/sonarqube/api/scope.go
b/backend/plugins/sonarqube/api/scope.go
index 063020133..3ec71af35 100644
--- a/backend/plugins/sonarqube/api/scope.go
+++ b/backend/plugins/sonarqube/api/scope.go
@@ -116,7 +116,7 @@ func UpdateScope(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput, err
// @Description get Sonarqube projects
// @Tags plugins/sonarqube
// @Param connectionId path int false "connection ID"
-// @Success 200 {object} []apiProject
+// @Success 200 {object} []models.SonarqubeProject
// @Failure 400 {object} shared.ApiBody "Bad Request"
// @Failure 500 {object} shared.ApiBody "Internal Error"
// @Router /plugins/sonarqube/connections/{connectionId}/scopes/ [GET]
@@ -143,7 +143,7 @@ func GetScopeList(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput, er
// @Param projectKey path string false "project key"
// @Param pageSize query int false "page size, default 50"
// @Param page query int false "page size, default 1"
-// @Success 200 {object} apiProject
+// @Success 200 {object} models.SonarqubeProject
// @Failure 400 {object} shared.ApiBody "Bad Request"
// @Failure 500 {object} shared.ApiBody "Internal Error"
// @Router /plugins/sonarqube/connections/{connectionId}/scopes/{projectKey}
[GET]