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

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


The following commit(s) were added to refs/heads/main by this push:
     new e5b8f6660 refactor: webhook adopts cicd_deployment_commits (#4968)
e5b8f6660 is described below

commit e5b8f666037da4ff16aa3c03427016f6c51cbef5
Author: Klesh Wong <[email protected]>
AuthorDate: Thu Apr 20 14:17:22 2023 +0800

    refactor: webhook adopts cicd_deployment_commits (#4968)
    
    * refactor: webhook adopts cicd_deployment_commits
    
    * fix: end_time should default to now()
    
    * feat: add result as optional input
    
    * fix: end_time should be optional
---
 backend/plugins/webhook/api/cicd_pipeline.go       | 379 ---------------------
 backend/plugins/webhook/api/cicd_pipeline_test.go  |  67 ----
 backend/plugins/webhook/api/deployments.go         | 134 ++++++++
 .../plugins/webhook/api/{issue.go => incident.go}  |   0
 backend/plugins/webhook/impl/impl.go               |   6 -
 5 files changed, 134 insertions(+), 452 deletions(-)

diff --git a/backend/plugins/webhook/api/cicd_pipeline.go 
b/backend/plugins/webhook/api/cicd_pipeline.go
deleted file mode 100644
index cba9d6cd2..000000000
--- a/backend/plugins/webhook/api/cicd_pipeline.go
+++ /dev/null
@@ -1,379 +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 (
-       "crypto/md5"
-       "fmt"
-       "net/http"
-       "reflect"
-       "time"
-
-       "github.com/apache/incubator-devlake/core/dal"
-       "github.com/apache/incubator-devlake/core/errors"
-       "github.com/apache/incubator-devlake/core/models/domainlayer"
-       "github.com/apache/incubator-devlake/core/models/domainlayer/code"
-       "github.com/apache/incubator-devlake/core/models/domainlayer/devops"
-       "github.com/apache/incubator-devlake/core/models/domainlayer/ticket"
-       "github.com/apache/incubator-devlake/core/plugin"
-       "github.com/apache/incubator-devlake/helpers/pluginhelper/api"
-       "github.com/apache/incubator-devlake/plugins/webhook/models"
-
-       "github.com/go-playground/validator/v10"
-)
-
-type WebhookTaskRequest struct {
-       // PipelineName can be filled by any string unique in one pipeline
-       PipelineName string `mapstructure:"pipeline_name" validate:"required"`
-
-       Name         string     `validate:"required"` // Name should be unique 
in one pipeline
-       Result       string     `validate:"oneof=SUCCESS FAILURE ABORT 
IN_PROGRESS"`
-       Status       string     `validate:"oneof=IN_PROGRESS DONE"`
-       Type         string     `validate:"oneof=TEST LINT BUILD DEPLOYMENT"`
-       Environment  string     `validate:"oneof=PRODUCTION STAGING TESTING"`
-       StartedDate  time.Time  `mapstructure:"created_date" 
validate:"required"`
-       FinishedDate *time.Time `mapstructure:"finished_date"`
-
-       RepoId    string `mapstructure:"repo_id" validate:"required"` // RepoId 
should be unique string
-       Branch    string
-       CommitSha string `mapstructure:"commit_sha"`
-}
-
-// PostCicdTask
-// @Summary create pipeline by webhook
-// @Description Create pipeline by webhook.<br/>
-// @Description example1: 
{"pipeline_name":"A123","name":"unit-test","result":"IN_PROGRESS","status":"IN_PROGRESS","type":"TEST","environment":"PRODUCTION","created_date":"2020-01-01T12:00:00+00:00","finished_date":"2020-01-01T12:59:59+00:00","repo_id":"devlake","branch":"main","commit_sha":"015e3d3b480e417aede5a1293bd61de9b0fd051d"}<br/>
-// @Description example2: 
{"pipeline_name":"A123","name":"unit-test","result":"SUCCESS","status":"DONE","type":"DEPLOYMENT","environment":"PRODUCTION","created_date":"2020-01-01T12:00:00+00:00","finished_date":"2020-01-01T12:59:59+00:00","repo_id":"devlake","branch":"main","commit_sha":"015e3d3b480e417aede5a1293bd61de9b0fd051d"}<br/>
-// @Description When request webhook first time for each pipeline, it will be 
created.
-// @Description So we suggest request before task start and after pipeline 
finish.
-// @Description Remember fill all data to request after pipeline finish.
-// @Tags plugins/webhook
-// @Param body body WebhookTaskRequest 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/:connectionId/cicd_tasks [POST]
-func PostCicdTask(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, 
errors.Error) {
-       connection := &models.WebhookConnection{}
-       err := connectionHelper.First(connection, input.Params)
-       if err != nil {
-               return nil, err
-       }
-       // get request
-       request := &WebhookTaskRequest{}
-       err = api.DecodeMapStruct(input.Body, request, true)
-       if err != nil {
-               return &plugin.ApiResourceOutput{Body: err.Error(), Status: 
http.StatusBadRequest}, nil
-       }
-       // validate
-       vld = validator.New()
-       err = errors.Convert(vld.Struct(request))
-       if err != nil {
-               return nil, errors.BadInput.Wrap(vld.Struct(request), `input 
json error`)
-       }
-
-       db := basicRes.GetDal()
-       pipelineId := fmt.Sprintf("%s:%d:%s", "webhook", connection.ID, 
request.PipelineName)
-       domainCicdTask := &devops.CICDTask{
-               DomainEntity: domainlayer.DomainEntity{
-                       Id: fmt.Sprintf("%s:%d:%s:%s", "webhook", 
connection.ID, request.PipelineName, request.Name),
-               },
-               PipelineId:   pipelineId,
-               Name:         request.Name,
-               Result:       request.Result,
-               Status:       request.Status,
-               Type:         request.Type,
-               Environment:  request.Environment,
-               StartedDate:  request.StartedDate,
-               FinishedDate: request.FinishedDate,
-       }
-       if domainCicdTask.FinishedDate != nil {
-               domainCicdTask.DurationSec = 
uint64(domainCicdTask.FinishedDate.Sub(domainCicdTask.StartedDate).Seconds())
-       }
-
-       domainPipeline := &devops.CICDPipeline{}
-       err = db.First(domainPipeline, dal.Where("id = ?", pipelineId))
-       if err != nil {
-               domainPipeline = &devops.CICDPipeline{
-                       DomainEntity: domainlayer.DomainEntity{
-                               Id: pipelineId,
-                       },
-                       Name:         request.PipelineName,
-                       Result:       ``,
-                       Status:       `IN_PROGRESS`,
-                       Type:         ``,
-                       CreatedDate:  request.StartedDate,
-                       FinishedDate: nil,
-               }
-       } else if domainPipeline.Status == `DONE` {
-               return nil, errors.Forbidden.New(`can not receive this task 
because pipeline has already been done.`)
-       }
-
-       domainPipelineCommit := &devops.CiCDPipelineCommit{
-               PipelineId: pipelineId,
-               CommitSha:  request.CommitSha,
-               Branch:     request.Branch,
-               RepoId:     request.RepoId,
-       }
-
-       // save
-       err = db.CreateOrUpdate(domainCicdTask)
-       if err != nil {
-               return nil, err
-       }
-       err = db.CreateOrUpdate(domainPipeline)
-       if err != nil {
-               return nil, err
-       }
-       err = db.CreateOrUpdate(domainPipelineCommit)
-       if err != nil {
-               return nil, err
-       }
-
-       return &plugin.ApiResourceOutput{Body: nil, Status: http.StatusOK}, nil
-}
-
-// PostPipelineFinish
-// @Summary set pipeline's status to DONE
-// @Description set pipeline's status to DONE and cal duration
-// @Tags plugins/webhook
-// @Success 200
-// @Failure 400  {string} errcode.Error "Bad Request"
-// @Failure 500  {string} errcode.Error "Internal Error"
-// @Router /plugins/webhook/:connectionId/cicd_pipeline/:pipelineName/finish 
[POST]
-func PostPipelineFinish(input *plugin.ApiResourceInput) 
(*plugin.ApiResourceOutput, errors.Error) {
-       connection := &models.WebhookConnection{}
-       err := connectionHelper.First(connection, input.Params)
-       if err != nil {
-               return nil, err
-       }
-
-       db := basicRes.GetDal()
-       pipelineId := fmt.Sprintf("%s:%d:%s", "webhook", connection.ID, 
input.Params[`pipelineName`])
-
-       now := time.Now()
-
-       // finished all CICDTask
-       cursor, err := db.Cursor(
-               dal.From(&devops.CICDTask{}),
-               dal.Where("pipeline_id = ?", pipelineId),
-       )
-       if err != nil {
-               return nil, errors.Default.Wrap(err, "error on select CICDTask")
-       }
-       batch, err := api.NewBatchSave(basicRes, 
reflect.TypeOf(&devops.CICDTask{}), 500)
-       if err != nil {
-               return nil, errors.Default.Wrap(err, "error getting batch from 
CICDTask")
-       }
-       defer batch.Close()
-
-       domainTasks := []devops.CICDTask{}
-       for cursor.Next() {
-               task := &devops.CICDTask{}
-               err = db.Fetch(cursor, task)
-               if err != nil {
-                       return nil, errors.Default.Wrap(err, "error on Fetch 
CICDTask data")
-               }
-               // set the IN_PROGRESS task to be ABORT
-               if task.Result == `IN_PROGRESS` {
-                       task.Result = `ABORT`
-                       task.FinishedDate = &now
-               }
-               task.Status = ticket.DONE
-               domainTasks = append(domainTasks, *task)
-               err = batch.Add(task)
-               if err != nil {
-                       return nil, errors.Default.Wrap(err, fmt.Sprintf("error 
on CICDTask batch add %v", task))
-               }
-       }
-
-       // finished CICDPipeline
-       domainPipeline := &devops.CICDPipeline{}
-       err = db.First(domainPipeline, dal.Where("id = ?", pipelineId))
-       if err != nil {
-               return nil, errors.NotFound.Wrap(err, `pipeline not found`)
-       }
-
-       err = db.All(&domainTasks, dal.Where("pipeline_id = ?", pipelineId))
-       if err != nil {
-               return nil, errors.NotFound.Wrap(err, `tasks not found`)
-       }
-       pipelineType, result := getTypeAndResultFromTasks(domainTasks)
-       domainPipeline.Type = pipelineType
-       domainPipeline.Result = result
-       domainPipeline.Status = ticket.DONE
-       domainPipeline.FinishedDate = &now
-       domainPipeline.DurationSec = 
uint64(domainPipeline.FinishedDate.Sub(domainPipeline.CreatedDate).Seconds())
-
-       // save
-       err = db.Update(domainPipeline)
-       if err != nil {
-               return nil, err
-       }
-
-       return &plugin.ApiResourceOutput{Body: nil, Status: http.StatusOK}, nil
-}
-
-// getTypeAndResultFromTasks will extract pipeline type and result from tasks
-// type = tasks' type if all tasks have the same type, or empty string
-// result = ABORT if any tasks' type is ABORT,
-// or result = FAILURE if any tasks' type is ABORT and others are SUCCESS
-// or result = SUCCESS if all tasks' type is SUCCESS
-func getTypeAndResultFromTasks(domainTasks []devops.CICDTask) (pipelineType, 
result string) {
-       result = `SUCCESS`
-       if len(domainTasks) > 0 {
-               pipelineType = domainTasks[0].Type
-       }
-       for _, domainTask := range domainTasks {
-               if domainTask.Type != pipelineType {
-                       pipelineType = ``
-               }
-               if domainTask.Result == `ABORT` {
-                       result = `ABORT`
-               } else if domainTask.Result == `FAILURE` {
-                       if result == `SUCCESS` {
-                               result = `FAILURE`
-                       }
-               }
-       }
-       return
-}
-
-type WebhookDeployTaskRequest struct {
-       // RepoUrl should be unique string, fill url or other unique data
-       RepoUrl   string `mapstructure:"repo_url" validate:"required"`
-       CommitSha string `mapstructure:"commit_sha" validate:"required"`
-       // start_time and end_time is more readable for users,
-       // StartedDate and FinishedDate is same as columns in db.
-       // So they all keep.
-       StartedDate  *time.Time `mapstructure:"start_time" 
validate:"required_with=FinishedDate"`
-       FinishedDate *time.Time `mapstructure:"end_time"`
-       Environment  string     `validate:"omitempty,oneof=PRODUCTION STAGING 
TESTING DEVELOPMENT"`
-}
-
-// PostCicdTask
-// @Summary create deployment pipeline by webhook
-// @Description Create deployment pipeline by webhook.<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 WebhookDeployTaskRequest 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/:connectionId/deployments [POST]
-func PostDeploymentCicdTask(input *plugin.ApiResourceInput) 
(*plugin.ApiResourceOutput, errors.Error) {
-       connection := &models.WebhookConnection{}
-       err := connectionHelper.First(connection, input.Params)
-       if err != nil {
-               return nil, err
-       }
-       // get request
-       request := &WebhookDeployTaskRequest{}
-       err = api.DecodeMapStruct(input.Body, request, true)
-       if err != nil {
-               return &plugin.ApiResourceOutput{Body: err.Error(), Status: 
http.StatusBadRequest}, nil
-       }
-       // validate
-       vld = validator.New()
-       err = errors.Convert(vld.Struct(request))
-       if err != nil {
-               return nil, errors.BadInput.Wrap(vld.Struct(request), `input 
json error`)
-       }
-
-       db := basicRes.GetDal()
-       urlHash16 := fmt.Sprintf("%x", md5.Sum([]byte(request.RepoUrl)))[:16]
-       scopeId := fmt.Sprintf("%s:%d", "webhook", connection.ID)
-       pipelineId := fmt.Sprintf("%s:%d:%s:%s:%s", "webhook", connection.ID, 
`pipeline`, urlHash16, request.CommitSha)
-
-       taskId := fmt.Sprintf("%s:%d:%s:%s", "webhook", connection.ID, 
urlHash16, request.CommitSha)
-       domainCicdTask := &devops.CICDTask{
-               DomainEntity: domainlayer.DomainEntity{
-                       Id: taskId,
-               },
-               PipelineId:  pipelineId,
-               Name:        fmt.Sprintf(`deployment for %s`, 
request.CommitSha),
-               Result:      devops.SUCCESS,
-               Status:      devops.DONE,
-               Type:        devops.DEPLOYMENT,
-               Environment: request.Environment,
-               CicdScopeId: scopeId,
-       }
-       now := time.Now()
-       if request.StartedDate != nil {
-               domainCicdTask.StartedDate = *request.StartedDate
-               if request.FinishedDate != nil {
-                       domainCicdTask.FinishedDate = request.FinishedDate
-               } else {
-                       domainCicdTask.FinishedDate = &now
-               }
-               domainCicdTask.DurationSec = 
uint64(domainCicdTask.FinishedDate.Sub(domainCicdTask.StartedDate).Seconds())
-       } else {
-               domainCicdTask.StartedDate = now
-       }
-       if domainCicdTask.Environment == `` {
-               domainCicdTask.Environment = devops.PRODUCTION
-       }
-
-       domainPipeline := &devops.CICDPipeline{
-               DomainEntity: domainlayer.DomainEntity{
-                       Id: pipelineId,
-               },
-               Name:         fmt.Sprintf(`pipeline for %s`, request.CommitSha),
-               Result:       devops.SUCCESS,
-               Status:       devops.DONE,
-               Type:         devops.DEPLOYMENT,
-               CreatedDate:  domainCicdTask.StartedDate,
-               FinishedDate: domainCicdTask.FinishedDate,
-               DurationSec:  domainCicdTask.DurationSec,
-               Environment:  domainCicdTask.Environment,
-               CicdScopeId:  scopeId,
-       }
-
-       domainPipelineCommit := &devops.CiCDPipelineCommit{
-               PipelineId: pipelineId,
-               CommitSha:  request.CommitSha,
-               Branch:     ``,
-               RepoUrl:    request.RepoUrl,
-       }
-
-       mayRelatedRepo := code.Repo{}
-       relatedRepoErr := db.First(&mayRelatedRepo, dal.Where("url = ?", 
request.RepoUrl))
-       if relatedRepoErr == nil {
-               domainPipelineCommit.RepoId = mayRelatedRepo.Id
-       }
-
-       // save
-       err = db.CreateOrUpdate(domainCicdTask)
-       if err != nil {
-               return nil, err
-       }
-       err = db.CreateOrUpdate(domainPipeline)
-       if err != nil {
-               return nil, err
-       }
-       err = db.CreateOrUpdate(domainPipelineCommit)
-       if err != nil {
-               return nil, err
-       }
-
-       return &plugin.ApiResourceOutput{Body: nil, Status: http.StatusOK}, nil
-}
diff --git a/backend/plugins/webhook/api/cicd_pipeline_test.go 
b/backend/plugins/webhook/api/cicd_pipeline_test.go
deleted file mode 100644
index 24e5ff121..000000000
--- a/backend/plugins/webhook/api/cicd_pipeline_test.go
+++ /dev/null
@@ -1,67 +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 (
-       "github.com/apache/incubator-devlake/core/models/domainlayer/devops"
-       "github.com/stretchr/testify/assert"
-       "testing"
-)
-
-func TestGetTypeAndResultFromTasks(t *testing.T) {
-       testDomainTask := devops.CICDTask{Type: devops.TEST}
-       buildDomainTask := devops.CICDTask{Type: devops.BUILD}
-       deploymentDomainTask := devops.CICDTask{Type: devops.DEPLOYMENT}
-
-       abortDomainTask := devops.CICDTask{Result: `ABORT`}
-       failureDomainTask := devops.CICDTask{Result: `FAILURE`}
-       successDomainTask := devops.CICDTask{Result: `SUCCESS`}
-
-       pipelineType, _ := 
getTypeAndResultFromTasks([]devops.CICDTask{testDomainTask})
-       assert.Equal(t, devops.TEST, pipelineType)
-
-       pipelineType, _ = 
getTypeAndResultFromTasks([]devops.CICDTask{buildDomainTask})
-       assert.Equal(t, devops.BUILD, pipelineType)
-
-       pipelineType, _ = 
getTypeAndResultFromTasks([]devops.CICDTask{deploymentDomainTask, 
deploymentDomainTask, deploymentDomainTask})
-       assert.Equal(t, devops.DEPLOYMENT, pipelineType)
-
-       pipelineType, _ = 
getTypeAndResultFromTasks([]devops.CICDTask{buildDomainTask, 
deploymentDomainTask, buildDomainTask})
-       assert.Equal(t, ``, pipelineType)
-
-       _, result := 
getTypeAndResultFromTasks([]devops.CICDTask{abortDomainTask, failureDomainTask, 
successDomainTask})
-       assert.Equal(t, `ABORT`, result)
-
-       _, result = 
getTypeAndResultFromTasks([]devops.CICDTask{failureDomainTask, 
successDomainTask})
-       assert.Equal(t, `FAILURE`, result)
-
-       _, result = 
getTypeAndResultFromTasks([]devops.CICDTask{successDomainTask})
-       assert.Equal(t, `SUCCESS`, result)
-
-       _, result = 
getTypeAndResultFromTasks([]devops.CICDTask{successDomainTask, 
successDomainTask})
-       assert.Equal(t, `SUCCESS`, result)
-
-       _, result = 
getTypeAndResultFromTasks([]devops.CICDTask{successDomainTask, 
successDomainTask, failureDomainTask})
-       assert.Equal(t, `FAILURE`, result)
-
-       _, result = 
getTypeAndResultFromTasks([]devops.CICDTask{successDomainTask, 
successDomainTask, abortDomainTask})
-       assert.Equal(t, `ABORT`, result)
-
-       _, result = 
getTypeAndResultFromTasks([]devops.CICDTask{failureDomainTask, 
failureDomainTask, abortDomainTask})
-       assert.Equal(t, `ABORT`, result)
-}
diff --git a/backend/plugins/webhook/api/deployments.go 
b/backend/plugins/webhook/api/deployments.go
new file mode 100644
index 000000000..c9fbfd123
--- /dev/null
+++ b/backend/plugins/webhook/api/deployments.go
@@ -0,0 +1,134 @@
+/*
+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 (
+       "crypto/md5"
+       "fmt"
+       "net/http"
+       "time"
+
+       "github.com/apache/incubator-devlake/core/errors"
+       "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/pluginhelper/api"
+       "github.com/apache/incubator-devlake/plugins/webhook/models"
+
+       "github.com/go-playground/validator/v10"
+)
+
+type WebhookDeployTaskRequest struct {
+       PipelineId string `mapstructure:"pipeline_id"`
+       // RepoUrl should be unique string, fill url or other unique data
+       RepoId    string `mapstructure:"repo_id"`
+       RepoUrl   string `mapstructure:"repo_url" validate:"required"`
+       CommitSha string `mapstructure:"commit_sha" validate:"required"`
+       RefName   string `mapstructure:"ref_name"`
+       Result    string `mapstructure:"result"`
+       // start_time and end_time is more readable for users,
+       // StartedDate and FinishedDate is same as columns in db.
+       // So they all keep.
+       CreatedDate  *time.Time `mapstructure:"create_time"`
+       StartedDate  *time.Time `mapstructure:"start_time" validate:"required"`
+       FinishedDate *time.Time `mapstructure:"end_time"`
+       Environment  string     `validate:"omitempty,oneof=PRODUCTION STAGING 
TESTING DEVELOPMENT"`
+}
+
+// PostDeploymentCicdTask
+// @Summary create deployment by webhook
+// @Description Create deployment pipeline by webhook.<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 WebhookDeployTaskRequest 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/:connectionId/deployments [POST]
+func PostDeploymentCicdTask(input *plugin.ApiResourceInput) 
(*plugin.ApiResourceOutput, errors.Error) {
+       connection := &models.WebhookConnection{}
+       err := connectionHelper.First(connection, input.Params)
+       if err != nil {
+               return nil, err
+       }
+       // get request
+       request := &WebhookDeployTaskRequest{}
+       err = api.DecodeMapStruct(input.Body, request, true)
+       if err != nil {
+               return &plugin.ApiResourceOutput{Body: err.Error(), Status: 
http.StatusBadRequest}, nil
+       }
+       // validate
+       vld = validator.New()
+       err = errors.Convert(vld.Struct(request))
+       if err != nil {
+               return nil, errors.BadInput.Wrap(vld.Struct(request), `input 
json error`)
+       }
+       db := basicRes.GetDal()
+       urlHash16 := fmt.Sprintf("%x", md5.Sum([]byte(request.RepoUrl)))[:16]
+       scopeId := fmt.Sprintf("%s:%d", "webhook", connection.ID)
+       deploymentCommitId := fmt.Sprintf("%s:%d:%s:%s", "webhook", 
connection.ID, urlHash16, request.CommitSha)
+       pipelineId := request.PipelineId
+       if pipelineId == "" {
+               pipelineId = deploymentCommitId
+       }
+       if request.CreatedDate == nil {
+               request.CreatedDate = request.StartedDate
+       }
+       if request.Environment == "" {
+               request.Environment = devops.PRODUCTION
+       }
+       if request.FinishedDate == nil {
+               now := time.Now()
+               request.FinishedDate = &now
+       }
+       if request.Result == "" {
+               request.Result = devops.SUCCESS
+       }
+       duration := 
uint64(request.FinishedDate.Sub(*request.StartedDate).Seconds())
+
+       // create a deployment_commit record
+       deploymentCommit := &devops.CicdDeploymentCommit{
+               DomainEntity: domainlayer.DomainEntity{
+                       Id: deploymentCommitId,
+               },
+               CicdPipelineId: pipelineId,
+               CicdScopeId:    scopeId,
+               Name:           fmt.Sprintf(`deployment for %s`, 
request.CommitSha),
+               Result:         request.Result,
+               Status:         devops.DONE,
+               Environment:    request.Environment,
+               CreatedDate:    *request.CreatedDate,
+               StartedDate:    request.StartedDate,
+               DurationSec:    &duration,
+               CommitSha:      request.CommitSha,
+               RefName:        request.RefName,
+               RepoId:         request.RepoId,
+               RepoUrl:        request.RepoUrl,
+       }
+       err = db.CreateOrUpdate(deploymentCommit)
+       if err != nil {
+               return nil, err
+       }
+
+       // TODO: create a deployment record when the table is ready
+
+       return &plugin.ApiResourceOutput{Body: nil, Status: http.StatusOK}, nil
+}
diff --git a/backend/plugins/webhook/api/issue.go 
b/backend/plugins/webhook/api/incident.go
similarity index 100%
rename from backend/plugins/webhook/api/issue.go
rename to backend/plugins/webhook/api/incident.go
diff --git a/backend/plugins/webhook/impl/impl.go 
b/backend/plugins/webhook/impl/impl.go
index df9a8177d..3dcff3d43 100644
--- a/backend/plugins/webhook/impl/impl.go
+++ b/backend/plugins/webhook/impl/impl.go
@@ -72,12 +72,6 @@ func (p Webhook) ApiResources() 
map[string]map[string]plugin.ApiResourceHandler
                        "PATCH":  api.PatchConnection,
                        "DELETE": api.DeleteConnection,
                },
-               ":connectionId/cicd_tasks": {
-                       "POST": api.PostCicdTask,
-               },
-               ":connectionId/cicd_pipeline/:pipelineName/finish": {
-                       "POST": api.PostPipelineFinish,
-               },
                ":connectionId/deployments": {
                        "POST": api.PostDeploymentCicdTask,
                },

Reply via email to