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

klesh pushed a commit to branch release-v1.0
in repository https://gitbox.apache.org/repos/asf/incubator-devlake.git


The following commit(s) were added to refs/heads/release-v1.0 by this push:
     new 8573fbf65 feat(webhook): Support for Webhook Name in Webhook Endpoints 
(#8203) (#8213)
8573fbf65 is described below

commit 8573fbf6551e73b6eee124650e31ec89e92336be
Author: Rodrigo Silva <[email protected]>
AuthorDate: Tue Nov 26 07:43:51 2024 +0100

    feat(webhook): Support for Webhook Name in Webhook Endpoints (#8203) (#8213)
    
    * feat(webhooks): add by-name methods to connection helper
    
    * feat(webhooks): add connection endpoints by name
    
    * feat(webhooks): add post deployment endpoint by name
    
    * feat(webhooks): add issue endpoints by name
---
 .../helpers/pluginhelper/api/connection_helper.go  | 27 +++++++++-
 backend/plugins/webhook/api/connection.go          | 63 +++++++++++++++++++++-
 backend/plugins/webhook/api/deployments.go         | 25 +++++++++
 backend/plugins/webhook/api/issues.go              | 37 +++++++++++++
 backend/plugins/webhook/impl/impl.go               | 14 +++++
 5 files changed, 164 insertions(+), 2 deletions(-)

diff --git a/backend/helpers/pluginhelper/api/connection_helper.go 
b/backend/helpers/pluginhelper/api/connection_helper.go
index 5e306519c..d9630f81b 100644
--- a/backend/helpers/pluginhelper/api/connection_helper.go
+++ b/backend/helpers/pluginhelper/api/connection_helper.go
@@ -99,7 +99,20 @@ func (c *ConnectionApiHelper) Patch(connection interface{}, 
input *plugin.ApiRes
        return c.save(connection, c.db.CreateOrUpdate)
 }
 
-// First finds connection from db  by parsing request input and decrypt it
+// PatchByName (Modify) a connection record based on request body by 
connection name
+func (c *ConnectionApiHelper) PatchByName(connection interface{}, input 
*plugin.ApiResourceInput) errors.Error {
+       err := c.FirstByName(connection, input.Params)
+       if err != nil {
+               return err
+       }
+       err = c.merge(connection, input.Body)
+       if err != nil {
+               return err
+       }
+       return c.save(connection, c.db.CreateOrUpdate)
+}
+
+// First finds connection from db by id, parsing request input and decrypt it
 func (c *ConnectionApiHelper) First(connection interface{}, params 
map[string]string) errors.Error {
        connectionId := params["connectionId"]
        if connectionId == "" {
@@ -117,6 +130,18 @@ func (c *ConnectionApiHelper) FirstById(connection 
interface{}, id uint64) error
        return CallDB(c.db.First, connection, dal.Where("id = ?", id))
 }
 
+// FirstByName finds connection from db by name, parsing request input and 
decrypting it
+func (c *ConnectionApiHelper) FirstByName(connection interface{}, params 
map[string]string) errors.Error {
+       connectionName := params["connectionName"]
+       if connectionName == "" {
+               return errors.BadInput.New("missing connectionName")
+       }
+       if len(connectionName) > 100 {
+               return errors.BadInput.New("invalid connectionName")
+       }
+       return CallDB(c.db.First, connection, dal.Where("name = ?", 
connectionName))
+}
+
 // List returns all connections with password/token decrypted
 func (c *ConnectionApiHelper) List(connections interface{}) errors.Error {
        return CallDB(c.db.All, connections)
diff --git a/backend/plugins/webhook/api/connection.go 
b/backend/plugins/webhook/api/connection.go
index acb8a76a5..89ca8843f 100644
--- a/backend/plugins/webhook/api/connection.go
+++ b/backend/plugins/webhook/api/connection.go
@@ -97,6 +97,24 @@ func PatchConnection(input *plugin.ApiResourceInput) 
(*plugin.ApiResourceOutput,
        return &plugin.ApiResourceOutput{Body: connection}, nil
 }
 
+// PatchConnectionByName
+// @Summary patch webhook connection by name
+// @Description Patch webhook connection
+// @Tags plugins/webhook
+// @Param body body models.WebhookConnection true "json body"
+// @Success 200  {object} models.WebhookConnection
+// @Failure 400  {string} errcode.Error "Bad Request"
+// @Failure 500  {string} errcode.Error "Internal Error"
+// @Router /plugins/webhook/connections/by-name/{connectionName} [PATCH]
+func PatchConnectionByName(input *plugin.ApiResourceInput) 
(*plugin.ApiResourceOutput, errors.Error) {
+       connection := &models.WebhookConnection{}
+       err := connectionHelper.PatchByName(connection, input)
+       if err != nil {
+               return nil, err
+       }
+       return &plugin.ApiResourceOutput{Body: connection}, nil
+}
+
 // DeleteConnection
 // @Summary delete a webhook connection
 // @Description Delete a webhook connection
@@ -107,7 +125,32 @@ func PatchConnection(input *plugin.ApiResourceInput) 
(*plugin.ApiResourceOutput,
 // @Failure 500  {string} errcode.Error "Internal Error"
 // @Router /plugins/webhook/connections/{connectionId} [DELETE]
 func DeleteConnection(input *plugin.ApiResourceInput) 
(*plugin.ApiResourceOutput, errors.Error) {
-       connectionId, e := strconv.ParseInt(input.Params["connectionId"], 10, 
64)
+       connectionId, e := strconv.ParseUint(input.Params["connectionId"], 10, 
64)
+       return deleteConnection(e, connectionId)
+}
+
+// DeleteConnectionByName
+// @Summary delete a webhook connection by name
+// @Description Delete a webhook connection
+// @Tags plugins/webhook
+// @Success 200  {object} models.WebhookConnection
+// @Failure 400  {string} errcode.Error "Bad Request"
+// @Failure 409  {object} services.BlueprintProjectPairs "References exist to 
this connection"
+// @Failure 500  {string} errcode.Error "Internal Error"
+// @Router /plugins/webhook/connections/by-name/{connectionName} [DELETE]
+func DeleteConnectionByName(input *plugin.ApiResourceInput) 
(*plugin.ApiResourceOutput, errors.Error) {
+       connection := &models.WebhookConnection{}
+       err := connectionHelper.FirstByName(connection, input.Params)
+
+       if err != nil {
+               logger.Error(err, "query connection")
+               return nil, err
+       }
+
+       return deleteConnection(nil, connection.ConnectionId())
+}
+
+func deleteConnection(e error, connectionId uint64) 
(*plugin.ApiResourceOutput, errors.Error) {
        if e != nil {
                return nil, errors.BadInput.WrapRaw(e)
        }
@@ -183,6 +226,24 @@ func ListConnections(input *plugin.ApiResourceInput) 
(*plugin.ApiResourceOutput,
 func GetConnection(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, 
errors.Error) {
        connection := &models.WebhookConnection{}
        err := connectionHelper.First(connection, input.Params)
+       return getConnection(err, connection)
+}
+
+// GetConnectionByName
+// @Summary get webhook connection detail by name
+// @Description Get webhook connection detail
+// @Tags plugins/webhook
+// @Success 200  {object} WebhookConnectionResponse
+// @Failure 400  {string} errcode.Error "Bad Request"
+// @Failure 500  {string} errcode.Error "Internal Error"
+// @Router /plugins/webhook/connections/by-name/{connectionName} [GET]
+func GetConnectionByName(input *plugin.ApiResourceInput) 
(*plugin.ApiResourceOutput, errors.Error) {
+       connection := &models.WebhookConnection{}
+       err := connectionHelper.FirstByName(connection, input.Params)
+       return getConnection(err, connection)
+}
+
+func getConnection(err errors.Error, connection *models.WebhookConnection) 
(*plugin.ApiResourceOutput, errors.Error) {
        if err != nil {
                logger.Error(err, "query connection")
                return nil, err
diff --git a/backend/plugins/webhook/api/deployments.go 
b/backend/plugins/webhook/api/deployments.go
index 70c90f9e2..8df9d5003 100644
--- a/backend/plugins/webhook/api/deployments.go
+++ b/backend/plugins/webhook/api/deployments.go
@@ -84,6 +84,31 @@ type WebhookDeploymentCommitReq struct {
 func PostDeployments(input *plugin.ApiResourceInput) 
(*plugin.ApiResourceOutput, errors.Error) {
        connection := &models.WebhookConnection{}
        err := connectionHelper.First(connection, input.Params)
+
+       return postDeployments(input, connection, err)
+}
+
+// PostDeploymentsByName
+// @Summary create deployment by webhook name
+// @Description Create deployment pipeline by webhook name.<br/>
+// @Description example1: 
{"repo_url":"devlake","commit_sha":"015e3d3b480e417aede5a1293bd61de9b0fd051d","start_time":"2020-01-01T12:00:00+00:00","end_time":"2020-01-01T12:59:59+00:00","environment":"PRODUCTION"}<br/>
+// @Description So we suggest request before task after deployment pipeline 
finish.
+// @Description Both cicd_pipeline and cicd_task will be created
+// @Tags plugins/webhook
+// @Param body body WebhookDeploymentReq true "json body"
+// @Success 200
+// @Failure 400  {string} errcode.Error "Bad Request"
+// @Failure 403  {string} errcode.Error "Forbidden"
+// @Failure 500  {string} errcode.Error "Internal Error"
+// @Router /plugins/webhook/connections/by-name/:connectionName/deployments 
[POST]
+func PostDeploymentsByName(input *plugin.ApiResourceInput) 
(*plugin.ApiResourceOutput, errors.Error) {
+       connection := &models.WebhookConnection{}
+       err := connectionHelper.FirstByName(connection, input.Params)
+
+       return postDeployments(input, connection, err)
+}
+
+func postDeployments(input *plugin.ApiResourceInput, connection 
*models.WebhookConnection, err errors.Error) (*plugin.ApiResourceOutput, 
errors.Error) {
        if err != nil {
                return nil, err
        }
diff --git a/backend/plugins/webhook/api/issues.go 
b/backend/plugins/webhook/api/issues.go
index 88f7e859d..49ea72b51 100644
--- a/backend/plugins/webhook/api/issues.go
+++ b/backend/plugins/webhook/api/issues.go
@@ -94,6 +94,25 @@ func saveIncidentRelatedRecordsFromIssue(db dal.Transaction, 
logger log.Logger,
 func PostIssue(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, 
errors.Error) {
        connection := &models.WebhookConnection{}
        err := connectionHelper.First(connection, input.Params)
+       return postIssue(input, err, connection)
+}
+
+// PostIssueByName
+// @Summary receive a record as defined and save it
+// @Description receive a record as follow and save it, example: 
{"url":"","issue_key":"DLK-1234","title":"a feature from 
DLK","description":"","epic_key":"","type":"BUG","status":"TODO","original_status":"created","story_point":0,"resolution_date":null,"created_date":"2020-01-01T12:00:00+00:00","updated_date":null,"lead_time_minutes":0,"parent_issue_key":"DLK-1200","priority":"","original_estimate_minutes":0,"time_spent_minutes":0,"time_remaining_minutes":0,"creator_id":"user1131","crea
 [...]
+// @Tags plugins/webhook
+// @Param body body WebhookIssueRequest true "json body"
+// @Success 200  {string} noResponse ""
+// @Failure 400  {string} errcode.Error "Bad Request"
+// @Failure 500  {string} errcode.Error "Internal Error"
+// @Router /plugins/webhook/by-name/:connectionName/issues [POST]
+func PostIssueByName(input *plugin.ApiResourceInput) 
(*plugin.ApiResourceOutput, errors.Error) {
+       connection := &models.WebhookConnection{}
+       err := connectionHelper.FirstByName(connection, input.Params)
+       return postIssue(input, err, connection)
+}
+
+func postIssue(input *plugin.ApiResourceInput, err errors.Error, connection 
*models.WebhookConnection) (*plugin.ApiResourceOutput, errors.Error) {
        if err != nil {
                return nil, err
        }
@@ -212,6 +231,24 @@ func PostIssue(input *plugin.ApiResourceInput) 
(*plugin.ApiResourceOutput, error
 func CloseIssue(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, 
errors.Error) {
        connection := &models.WebhookConnection{}
        err := connectionHelper.First(connection, input.Params)
+       return closeIssue(input, err, connection)
+}
+
+// CloseIssueByName
+// @Summary set issue's status to DONE
+// @Description set issue's status to DONE
+// @Tags plugins/webhook
+// @Success 200  {string} noResponse ""
+// @Failure 400  {string} errcode.Error "Bad Request"
+// @Failure 500  {string} errcode.Error "Internal Error"
+// @Router /plugins/webhook/by-name/:connectionName/issue/:issueKey/close 
[POST]
+func CloseIssueByName(input *plugin.ApiResourceInput) 
(*plugin.ApiResourceOutput, errors.Error) {
+       connection := &models.WebhookConnection{}
+       err := connectionHelper.FirstByName(connection, input.Params)
+       return closeIssue(input, err, connection)
+}
+
+func closeIssue(input *plugin.ApiResourceInput, err errors.Error, connection 
*models.WebhookConnection) (*plugin.ApiResourceOutput, errors.Error) {
        if err != nil {
                return nil, err
        }
diff --git a/backend/plugins/webhook/impl/impl.go 
b/backend/plugins/webhook/impl/impl.go
index 6b1bac0af..78b1addf5 100644
--- a/backend/plugins/webhook/impl/impl.go
+++ b/backend/plugins/webhook/impl/impl.go
@@ -105,5 +105,19 @@ func (p Webhook) ApiResources() 
map[string]map[string]plugin.ApiResourceHandler
                ":connectionId/issue/:issueKey/close": {
                        "POST": api.CloseIssue,
                },
+               "connections/by-name/:connectionName": {
+                       "GET":    api.GetConnectionByName,
+                       "PATCH":  api.PatchConnectionByName,
+                       "DELETE": api.DeleteConnectionByName,
+               },
+               "connections/by-name/:connectionName/deployments": {
+                       "POST": api.PostDeploymentsByName,
+               },
+               "connections/by-name/:connectionName/issues": {
+                       "POST": api.PostIssueByName,
+               },
+               "connections/by-name/:connectionName/issue/:issueKey/close": {
+                       "POST": api.CloseIssueByName,
+               },
        }
 }

Reply via email to