feat: add support for creating deployments by project name#8611
feat: add support for creating deployments by project name#8611d4x1 merged 16 commits intoapache:mainfrom
Conversation
…ving connections by project and plugin name
|
There are no unit tests for this code and no documentation in this repository related to this. |
…ved clarity and maintainability
|
Testing this, we are able to push deployments and see these deployment data in the Because we now use one single webhook, which is then added to multiple projects, the query for the Looking into it, we can see that the Looking at this part of the query: with _deployment_commit_rank as(
SELECT
pm.project_name,
IF(cdc._raw_data_table != '', cdc._raw_data_table, cdc.cicd_scope_id) as _raw_data_table,
cdc.id,
cdc.display_title,
cdc.url,
cdc.cicd_deployment_id,
cdc.cicd_scope_id,
result,
environment,
finished_date,
row_number() over(partition by cdc.cicd_deployment_id order by finished_date desc) as _deployment_commit_rank
FROM cicd_deployment_commits cdc
left join project_mapping pm on cdc.cicd_scope_id = pm.row_id and pm.`table` = 'cicd_scopes'
WHERE
pm.project_name in ($project)
and result = 'SUCCESS'
and environment = 'PRODUCTION'
)I believe the issue to be around the line where the I'm not a db dev, nor a dba, so I'm out of my depth to try and solve this issue. Any suggestions here, would be welcomed. |
|
Okay, based on the discussion.
|
| postPipelineDeployTaskEndpoint: connection.postPipelineDeployTaskEndpoint, | ||
| postPullRequestsEndpoint: connection.postPullRequestsEndpoint, | ||
| apiKeyId: connection.apiKey.id, | ||
| apiKeyId: connection.apiKey?.id, |
There was a problem hiding this comment.
apiKey is optional for a webhook, so we won't always have an apiKey id.
| connection := &models.WebhookConnection{} | ||
| projectName := input.Params["projectName"] | ||
| webhookName := fmt.Sprintf("%s_deployments", projectName) | ||
| err := findByProjectName(connection, input.Params, pluginName) |
There was a problem hiding this comment.
It would be better to pass the webhookName to the findByProjectName function instead of redefining.
backend/server/api/router.go
Outdated
| } | ||
| // mount all api resources for all plugins | ||
| for pluginName, apiResources := range resources { | ||
| if pluginName == "webhook" { |
There was a problem hiding this comment.
This is not the way to handle route conflict.
What was the conflict exactly?
There was a problem hiding this comment.
Not exactly a conflict, but more a duplicate route not wanted. The way routing is done, this route, because how it is defined on the plugin, would have resulted in the route /plugins/webhook/projects/:projectName/deployments instead of only /projects/:projectName/deployments. With this we now only have the latter as we remove the registration of the route on the webhook plugin route. Best way I could think of achieving this, unless the code is moved elsewhere and not in the plugin itself.
There was a problem hiding this comment.
What is wrong with /plugins/webhook/projects/:projectName/deployments?
The API is offered by the webhook plugin, it should be prefixed by /plugins/webhook by convention.
|
@klesh I have made the requested changes. Please let me know if I need to make any further changes. |
| "connections/by-name/:connectionName/issue/:issueKey/close": { | ||
| "POST": api.CloseIssueByName, | ||
| }, | ||
| "projects/:projectName/deployments": { |
There was a problem hiding this comment.
I think projects/by-name/:projectName/deployments is better, just like onnections/by-name/***.
| if err != nil { | ||
| // if not found, we will attempt to create a new connection | ||
| // Use direct comparison against the package sentinel; only treat other errors as fatal. | ||
| if !errors.Is(err, gorm.ErrRecordNotFound) { |
There was a problem hiding this comment.
Maybe we can use https://github.com/apache/incubator-devlake/blob/920bc624f1c04bc01e944410d413fa113ed25554/backend/impls/dalgorm/dalgorm.go#L490 to keep a unified style.
There was a problem hiding this comment.
I hope my change is acceptable.
| // find or create the connection for this project | ||
| connection := &models.WebhookConnection{} | ||
| projectName := input.Params["projectName"] | ||
| webhookName := fmt.Sprintf("%s_deployments", projectName) |
There was a problem hiding this comment.
According to previous discussion, I think this means current project's default(or missing) webhook connection.
I prefer something that contains the default (or missing) meaning. We can add more items later under the default webhook.
This is just an advice.
There was a problem hiding this comment.
I used the _deployments suffix because I see can how I end up adding a similar webhook for incidents at one point. We are using an ITSM system which isn't supported, and to be honest, I won't even bother to look at supporting it. I would however consider adding a webhook like this so that system can call to open/close incidents to complete the DORA loop.
I could go with _deployments_default for the webhook name? Open to suggestions here.
There was a problem hiding this comment.
Thanks for your response. It makes sense.
| // @Failure 403 {string} errcode.Error "Forbidden" | ||
| // @Failure 500 {string} errcode.Error "Internal Error" | ||
| // @Router /projects/:projectName/deployments [POST] | ||
| func PostDeploymentsByProjectName(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors.Error) { |
There was a problem hiding this comment.
Try to make this handler looks simple and clear.
For example:
func PostDeploymentsByProjectName(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors.Error) {
GetOrCreateConnection
postDeployments
}
func GetOrCreateConnection(){
// part 1: check project's missing webhook connection, create or update.
// part 2: if the connection is created newly, updatte project's blueprint.
}There was a problem hiding this comment.
Let me know if the changes are satisfactory
…hook connection lookup
| // find or create the connection for this project | ||
| connection := &models.WebhookConnection{} | ||
| projectName := input.Params["projectName"] | ||
| webhookName := fmt.Sprintf("%s_deployments", projectName) |
There was a problem hiding this comment.
Thanks for your response. It makes sense.
pr-type/bug-fix,pr-type/feature-development, etc.Summary
Add a new endpoint for posting to a webhook using the project name. This will allow for a generic webhook to be created and added to multiple projects, and the webhook retrieved using the project name.
Does this close any open issues?
No
Screenshots
Include any relevant screenshots here.
Other Information
relates to discussion: #6348