This is an automated email from the ASF dual-hosted git repository.
abeizn pushed a commit to branch feat#6162-webhook
in repository https://gitbox.apache.org/repos/asf/incubator-devlake.git
The following commit(s) were added to refs/heads/feat#6162-webhook by this push:
new 2c3b424ed feat: allow deployment webhook to push deployments to
multiple repos in one request
2c3b424ed is described below
commit 2c3b424ed13675738a064c637bb4aed850d0284a
Author: abeizn <[email protected]>
AuthorDate: Wed Nov 29 14:14:15 2023 +0800
feat: allow deployment webhook to push deployments to multiple repos in one
request
---
.../domainlayer/devops/cicd_deployment_commit.go | 3 +-
...27_add_commit_msg_to_cicd_deployment_commits.go | 52 ++++++
backend/core/models/migrationscripts/register.go | 1 +
backend/plugins/webhook/api/deployments.go | 178 +++++++++++++++------
4 files changed, 185 insertions(+), 49 deletions(-)
diff --git a/backend/core/models/domainlayer/devops/cicd_deployment_commit.go
b/backend/core/models/domainlayer/devops/cicd_deployment_commit.go
index 398dfe96a..cdc5c1783 100644
--- a/backend/core/models/domainlayer/devops/cicd_deployment_commit.go
+++ b/backend/core/models/domainlayer/devops/cicd_deployment_commit.go
@@ -38,6 +38,7 @@ type CicdDeploymentCommit struct {
FinishedDate *time.Time
DurationSec *float64
CommitSha string
`gorm:"primaryKey;type:varchar(255)"`
+ CommitMsg string
RefName string `gorm:"type:varchar(255)"` // to
delete?
RepoId string `gorm:"type:varchar(255)"`
RepoUrl string `gorm:"index;not null"`
@@ -64,6 +65,6 @@ func (cicdDeploymentCommit CicdDeploymentCommit)
ToDeployment() *CICDDeployment
CreatedDate: cicdDeploymentCommit.CreatedDate,
StartedDate: cicdDeploymentCommit.StartedDate,
FinishedDate: cicdDeploymentCommit.FinishedDate,
- DurationSec: cicdDeploymentCommit.DurationSec,
+ DurationSec: cicdDeploymentCommit.DurationSec,
}
}
diff --git
a/backend/core/models/migrationscripts/20231127_add_commit_msg_to_cicd_deployment_commits.go
b/backend/core/models/migrationscripts/20231127_add_commit_msg_to_cicd_deployment_commits.go
new file mode 100644
index 000000000..087ec8a9d
--- /dev/null
+++
b/backend/core/models/migrationscripts/20231127_add_commit_msg_to_cicd_deployment_commits.go
@@ -0,0 +1,52 @@
+/*
+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 migrationscripts
+
+import (
+ "github.com/apache/incubator-devlake/core/context"
+ "github.com/apache/incubator-devlake/core/errors"
+ "github.com/apache/incubator-devlake/core/plugin"
+)
+
+var _ plugin.MigrationScript = (*addCommitMsg)(nil)
+
+type cicdDeploymentCommit20231127 struct {
+ CommitMsg string
+}
+
+func (cicdDeploymentCommit20231127) TableName() string {
+ return "cicd_deployment_commits"
+}
+
+type addCommitMsg struct{}
+
+func (u *addCommitMsg) Up(basicRes context.BasicRes) errors.Error {
+ db := basicRes.GetDal()
+ if err := db.AutoMigrate(&cicdDeploymentCommit20231127{}); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (*addCommitMsg) Version() uint64 {
+ return 20231127142100
+}
+
+func (*addCommitMsg) Name() string {
+ return "add commit_msg to cicd_deployment_commit table"
+}
diff --git a/backend/core/models/migrationscripts/register.go
b/backend/core/models/migrationscripts/register.go
index 440125bb6..c329ec8c1 100644
--- a/backend/core/models/migrationscripts/register.go
+++ b/backend/core/models/migrationscripts/register.go
@@ -98,5 +98,6 @@ func All() []plugin.MigrationScript {
new(removePositionFromPullRequestComments),
new(changeDurationSecToFloat64),
new(addOriginalStatusAndResultToDevOpsTables),
+ new(addCommitMsg),
}
}
diff --git a/backend/plugins/webhook/api/deployments.go
b/backend/plugins/webhook/api/deployments.go
index dd2177296..f8966f4c3 100644
--- a/backend/plugins/webhook/api/deployments.go
+++ b/backend/plugins/webhook/api/deployments.go
@@ -20,11 +20,13 @@ package api
import (
"crypto/md5"
"fmt"
- "github.com/apache/incubator-devlake/helpers/dbhelper"
- "github.com/go-playground/validator/v10"
"net/http"
+ "strings"
"time"
+ "github.com/apache/incubator-devlake/helpers/dbhelper"
+ "github.com/go-playground/validator/v10"
+
"github.com/apache/incubator-devlake/core/errors"
"github.com/apache/incubator-devlake/core/models/domainlayer"
"github.com/apache/incubator-devlake/core/models/domainlayer/devops"
@@ -36,18 +38,31 @@ import (
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"`
+ RepoId string `mapstructure:"repo_id"`
+ 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"`
+ RepoUrl string `mapstructure:"repo_url"`
Environment string `validate:"omitempty,oneof=PRODUCTION STAGING
TESTING DEVELOPMENT"`
+ Name string `mapstructure:"name"`
+ RefName string `mapstructure:"ref_name"`
+ CommitSha string `mapstructure:"commit_sha"`
+ CommitMsg string `mapstructure:"commit_msg"`
+ // DeploymentCommits is used for multiple commits in one deployment
+ DeploymentCommits []DeploymentCommit `mapstructure:"deploymentCommits"
validate:"omitempty,dive"`
+}
+
+type DeploymentCommit struct {
+ RepoUrl string `mapstructure:"repo_url" validate:"required"`
+ Environment string `validate:"omitempty,oneof=PRODUCTION STAGING
TESTING DEVELOPMENT"`
+ Name string `mapstructure:"name"`
+ RefName string `mapstructure:"ref_name"`
+ CommitSha string `mapstructure:"commit_sha" validate:"required"`
+ CommitMsg string `mapstructure:"commit_msg"`
}
// PostDeploymentCicdTask
@@ -62,7 +77,7 @@ type WebhookDeployTaskRequest struct {
// @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]
+// @Router /plugins/webhook/connections/:connectionId/deployments [POST]
func PostDeploymentCicdTask(input *plugin.ApiResourceInput)
(*plugin.ApiResourceOutput, errors.Error) {
connection := &models.WebhookConnection{}
err := connectionHelper.First(connection, input.Params)
@@ -84,19 +99,12 @@ func PostDeploymentCicdTask(input *plugin.ApiResourceInput)
(*plugin.ApiResource
txHelper := dbhelper.NewTxHelper(basicRes, &err)
defer txHelper.End()
tx := txHelper.Begin()
- 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
- }
+ scopeId := fmt.Sprintf("%s:%d", "webhook", connection.ID)
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
@@ -105,39 +113,113 @@ func PostDeploymentCicdTask(input
*plugin.ApiResourceInput) (*plugin.ApiResource
request.Result = devops.RESULT_SUCCESS
}
duration := request.FinishedDate.Sub(*request.StartedDate).Seconds()
-
- // create a deployment_commit record
- deploymentCommit := &devops.CicdDeploymentCommit{
- DomainEntity: domainlayer.DomainEntity{
- Id: deploymentCommitId,
- },
- CicdDeploymentId: pipelineId,
- CicdScopeId: scopeId,
- Name: fmt.Sprintf(`deployment for %s`,
request.CommitSha),
- Result: request.Result,
- Status: devops.STATUS_DONE,
- OriginalResult: request.Result,
- OriginalStatus: devops.STATUS_DONE,
- Environment: request.Environment,
- CreatedDate: *request.CreatedDate,
- StartedDate: request.StartedDate,
- FinishedDate: request.FinishedDate,
- DurationSec: &duration,
- CommitSha: request.CommitSha,
- RefName: request.RefName,
- RepoId: request.RepoId,
- RepoUrl: request.RepoUrl,
- }
- err = tx.CreateOrUpdate(deploymentCommit)
- if err != nil {
- logger.Error(err, "create deployment commit")
- return nil, err
+ name := request.Name
+ if name == "" {
+ if request.DeploymentCommits == nil {
+ name = fmt.Sprintf(`deployment for %s`,
request.CommitSha)
+ } else {
+ commit_sha_list := []string{}
+ for _, commit := range request.DeploymentCommits {
+ commit_sha_list = append(commit_sha_list,
commit.CommitSha)
+ }
+ name = fmt.Sprintf(`deployment for %s`,
strings.Join(commit_sha_list, ","))
+ }
}
- // create a deployment record
- if err = tx.CreateOrUpdate(deploymentCommit.ToDeployment()); err != nil
{
- logger.Error(err, "create deployment")
- return nil, err
+ if request.DeploymentCommits == nil {
+ if request.CommitSha == "" || request.RepoUrl == "" {
+ return nil, errors.Convert(fmt.Errorf("commit_sha or
repo_url is required"))
+ }
+ urlHash16 := fmt.Sprintf("%x",
md5.Sum([]byte(request.RepoUrl)))[:16]
+ deploymentCommitId := fmt.Sprintf("%s:%d:%s:%s", "webhook",
connection.ID, urlHash16, request.CommitSha)
+ if pipelineId == "" {
+ pipelineId = deploymentCommitId
+ }
+ if request.Environment == "" {
+ request.Environment = devops.PRODUCTION
+ }
+
+ // create a deployment_commit record
+ deploymentCommit := &devops.CicdDeploymentCommit{
+ DomainEntity: domainlayer.DomainEntity{
+ Id: deploymentCommitId,
+ },
+ CicdDeploymentId: pipelineId,
+ CicdScopeId: scopeId,
+ Name: name,
+ Result: request.Result,
+ Status: devops.STATUS_DONE,
+ OriginalResult: request.Result,
+ OriginalStatus: devops.STATUS_DONE,
+ CreatedDate: *request.CreatedDate,
+ StartedDate: request.StartedDate,
+ FinishedDate: request.FinishedDate,
+ DurationSec: &duration,
+ RepoId: request.RepoId,
+ RepoUrl: request.RepoUrl,
+ Environment: request.Environment,
+ RefName: request.RefName,
+ CommitSha: request.CommitSha,
+ CommitMsg: request.CommitMsg,
+ }
+ err = tx.CreateOrUpdate(deploymentCommit)
+ if err != nil {
+ logger.Error(err, "create deployment commit")
+ return nil, err
+ }
+
+ // create a deployment record
+ if err = tx.CreateOrUpdate(deploymentCommit.ToDeployment());
err != nil {
+ logger.Error(err, "create deployment")
+ return nil, err
+ }
+ } else {
+ for _, commit := range request.DeploymentCommits {
+ urlHash16 := fmt.Sprintf("%x",
md5.Sum([]byte(commit.RepoUrl)))[:16]
+ deploymentCommitId := fmt.Sprintf("%s:%d:%s:%s",
"webhook", connection.ID, urlHash16, commit.CommitSha)
+ if pipelineId == "" {
+ pipelineId = deploymentCommitId
+ }
+ if commit.Environment == "" {
+ commit.Environment = devops.PRODUCTION
+ }
+ // create a deployment_commit record
+ deploymentCommit := &devops.CicdDeploymentCommit{
+ DomainEntity: domainlayer.DomainEntity{
+ Id: deploymentCommitId,
+ },
+ CicdDeploymentId: pipelineId,
+ CicdScopeId: scopeId,
+ Result: request.Result,
+ Status: devops.STATUS_DONE,
+ OriginalResult: request.Result,
+ OriginalStatus: devops.STATUS_DONE,
+ CreatedDate: *request.CreatedDate,
+ StartedDate: request.StartedDate,
+ FinishedDate: request.FinishedDate,
+ DurationSec: &duration,
+ RepoId: request.RepoId,
+ Name: fmt.Sprintf(`deployment for
%s`, commit.CommitSha),
+ RepoUrl: commit.RepoUrl,
+ Environment: commit.Environment,
+ RefName: commit.RefName,
+ CommitSha: commit.CommitSha,
+ CommitMsg: commit.CommitMsg,
+ }
+ err = tx.CreateOrUpdate(deploymentCommit)
+ if err != nil {
+ logger.Error(err, "create deployment commit")
+ return nil, err
+ }
+
+ // create a deployment record
+ deploymentCommit.Name = name
+ if err =
tx.CreateOrUpdate(deploymentCommit.ToDeployment()); err != nil {
+ logger.Error(err, "create deployment")
+ return nil, err
+ }
+ }
+
}
return &plugin.ApiResourceOutput{Body: nil, Status: http.StatusOK}, nil