diff --git a/docs/overview/db/devops_ci_process.md b/docs/overview/db/devops_ci_process.md index dbba2a8cdf4..500da903438 100644 --- a/docs/overview/db/devops_ci_process.md +++ b/docs/overview/db/devops_ci_process.md @@ -50,8 +50,6 @@ | [T_PIPELINE_VIEW_USER_LAST_VIEW](#T_PIPELINE_VIEW_USER_LAST_VIEW) | | | [T_PIPELINE_VIEW_USER_SETTINGS](#T_PIPELINE_VIEW_USER_SETTINGS) | | | [T_PIPELINE_WEBHOOK](#T_PIPELINE_WEBHOOK) | | -| [T_PIPELINE_WEBHOOK_BUILD_LOG](#T_PIPELINE_WEBHOOK_BUILD_LOG) | | -| [T_PIPELINE_WEBHOOK_BUILD_LOG_DETAIL](#T_PIPELINE_WEBHOOK_BUILD_LOG_DETAIL) | | | [T_PIPELINE_WEBHOOK_QUEUE](#T_PIPELINE_WEBHOOK_QUEUE) | | | [T_PROJECT_PIPELINE_CALLBACK](#T_PROJECT_PIPELINE_CALLBACK) | | | [T_PROJECT_PIPELINE_CALLBACK_HISTORY](#T_PROJECT_PIPELINE_CALLBACK_HISTORY) | | @@ -60,6 +58,8 @@ | [T_TEMPLATE_INSTANCE_BASE](#T_TEMPLATE_INSTANCE_BASE) | 模板实列化基本信息表 | | [T_TEMPLATE_INSTANCE_ITEM](#T_TEMPLATE_INSTANCE_ITEM) | 模板实列化项信息表 | | [T_TEMPLATE_PIPELINE](#T_TEMPLATE_PIPELINE) | 流水线模板-实例映射表 | +| [T_PIPELINE_TRIGGER_EVENT](#T_PIPELINE_TRIGGER_EVENT) | 流水线触发事件表 | +| [T_PIPELINE_TRIGGER_DETAIL](#T_PIPELINE_TRIGGER_DETAIL) | 流水线触发事件明细表 | **表名:** T_AUDIT_RESOURCE @@ -848,44 +848,10 @@ | 8 | PROJECT_NAME | varchar | 128 | 0 | Y | N | | 项目名称 | | 9 | TASK_ID | varchar | 34 | 0 | Y | N | | 任务id | | 10 | DELETE | bit | 1 | 0 | Y | N | b'0' | 是否删除 | +| 11 | EXTERNAL_ID | varchar | 255 | 0 | Y | N | | webhook事件生产者ID,工蜂-工蜂ID,github-github id,svn-svn path,p4-p4port | +| 12 | EVENT_TYPE | varchar | 32 | 0 | Y | N | | 事件类型 | +| 13 | REPOSITORY_HASH_ID | varchar | 64 | 0 | Y | N | | 代码库hashId | -**表名:** T_PIPELINE_WEBHOOK_BUILD_LOG - -**说明:** - -**数据列:** - -| 序号 | 名称 | 数据类型 | 长度 | 小数位 | 允许空值 | 主键 | 默认值 | 说明 | -| :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | -| 1 | ID | bigint | 20 | 0 | N | Y | | 主键ID | -| 2 | CODE_TYPE | varchar | 32 | 0 | N | N | | 代码库类型 | -| 3 | REPO_NAME | varchar | 128 | 0 | N | N | | 代码库别名 | -| 4 | COMMIT_ID | varchar | 64 | 0 | N | N | | 代码提交ID | -| 5 | REQUEST_CONTENT | text | 65535 | 0 | Y | N | | 事件内容 | -| 6 | CREATED_TIME | datetime | 19 | 0 | N | Y | CURRENT_TIMESTAMP | 创建时间 | -| 7 | RECEIVED_TIME | datetime | 19 | 0 | N | N | | 接收时间 | -| 8 | FINISHED_TIME | datetime | 19 | 0 | N | N | | 完成时间 | - -**表名:** T_PIPELINE_WEBHOOK_BUILD_LOG_DETAIL - -**说明:** - -**数据列:** - -| 序号 | 名称 | 数据类型 | 长度 | 小数位 | 允许空值 | 主键 | 默认值 | 说明 | -| :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | -| 1 | ID | bigint | 20 | 0 | N | Y | | 主键ID | -| 2 | LOG_ID | bigint | 20 | 0 | N | N | | | -| 3 | CODE_TYPE | varchar | 32 | 0 | N | N | | 代码库类型 | -| 4 | REPO_NAME | varchar | 128 | 0 | N | N | | 代码库别名 | -| 5 | COMMIT_ID | varchar | 64 | 0 | N | N | | 代码提交ID | -| 6 | PROJECT_ID | varchar | 32 | 0 | N | N | | 项目ID | -| 7 | PIPELINE_ID | varchar | 34 | 0 | N | N | | 流水线ID | -| 8 | TASK_ID | varchar | 34 | 0 | N | N | | 任务id | -| 9 | TASK_NAME | varchar | 128 | 0 | Y | N | | 任务名称 | -| 10 | SUCCESS | bit | 1 | 0 | Y | N | b'0' | 是否成功 | -| 11 | TRIGGER_RESULT | text | 65535 | 0 | Y | N | | 触发结果 | -| 12 | CREATED_TIME | datetime | 19 | 0 | N | Y | CURRENT_TIMESTAMP | 创建时间 | **表名:** T_PIPELINE_WEBHOOK_QUEUE @@ -1055,3 +1021,44 @@ | 12 | BUILD_NO | text | 65535 | 0 | Y | N | | 构建号 | | 13 | PARAM | mediumtext | 16777215 | 0 | Y | N | | 参数 | | 14 | DELETED | bit | 1 | 0 | Y | N | b'0' | 流水线已被软删除 | + +**表名:** T_PIPELINE_TRIGGER_EVENT + +**说明:** 流水线触发事件表 + +**数据列:** + +| 序号 | 名称 | 数据类型 | 长度 | 小数位 | 允许空值 | 主键 | 默认值 | 说明 | +| :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | +| 1 | REQUEST_ID | varchar | 64 | 0 | N | N | | 请求ID | +| 2 | PROJECT_ID | varchar | 64 | 0 | N | Y | | 项目ID | +| 3 | EVENT_ID | bigint | 20 | 0 | N | Y | | 事件ID | +| 4 | TRIGGER_TYPE | varchar | 32 | 0 | N | N | | 触发类型 | +| 5 | EVENT_SOURCE | varchar | 20 | 0 | N | N | | 触发源,代码库hashId/触发人/远程ip | +| 6 | EVENT_TYPE | varchar | 64 | 0 | N | N | | 事件类型 | +| 7 | TRIGGER_USER | varchar | 100 | 0 | N | N | | 触发用户 | +| 8 | EVENT_DESC | text | | 0 | N | N | | 事件描述 | +| 9 | REPLAY_REQUEST_ID | varchar | 64 | 0 | Y | N | | 重放请求ID | +| 10 | REQUEST_PARAMS | text | | 0 | N | N | | 请求参数 | +| 11 | CREATE_TIME | timestamp | | 0 | N | Y | | 事件时间 | + +**表名:** T_PIPELINE_TRIGGER_DETAIL + +**说明:** 流水线触发事件明细表 + +**数据列:** + +| 序号 | 名称 | 数据类型 | 长度 | 小数位 | 允许空值 | 主键 | 默认值 | 说明 | +| :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | +| 1 | DETAIL_ID | varchar | 64 | 0 | N | Y | | 事件明细ID | +| 2 | PROJECT_ID | varchar | 64 | 0 | N | N | | 项目ID | +| 3 | EVENT_ID | bigint | 20 | 0 | N | N | | 事件ID | +| 4 | STATUS | varchar | 32 | 0 | Y | N | | 状态(success or failure) | +| 5 | PIPELINE_ID | varchar | 20 | 0 | Y | N | | 流水线ID | +| 6 | PIPELINE_NAME | varchar | 64 | 0 | Y | N | | 流水线名称 | +| 7 | VERSION | varchar | 100 | 0 | Y | N | | 流水线版本号 | +| 8 | BUILD_ID | text | | 0 | Y | N | | 构建ID | +| 9 | BUILD_NUM | varchar | 64 | 0 | Y | N | | 构建编号 | +| 10 | REASON | text | | 0 | Y | N | | 失败原因 | +| 11 | REASON_DETAIL | timestamp | | 0 | Y | N | | 原因详情 | +| 12 | CREATE_TIME | timestamp | | 0 | Y | Y | | 创建时间 | \ No newline at end of file diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/engine/service/PipelineWebhookBuildLogServiceImpl.kt b/src/backend/ci/core/common/common-api/src/main/kotlin/com/tencent/devops/common/api/pojo/I18Variable.kt similarity index 66% rename from src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/engine/service/PipelineWebhookBuildLogServiceImpl.kt rename to src/backend/ci/core/common/common-api/src/main/kotlin/com/tencent/devops/common/api/pojo/I18Variable.kt index 27ad3d005d8..687bb6ea39d 100644 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/engine/service/PipelineWebhookBuildLogServiceImpl.kt +++ b/src/backend/ci/core/common/common-api/src/main/kotlin/com/tencent/devops/common/api/pojo/I18Variable.kt @@ -23,28 +23,23 @@ * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * */ -package com.tencent.devops.process.engine.service - -import com.tencent.devops.common.api.model.SQLPage -import com.tencent.devops.process.pojo.webhook.PipelineWebhookBuildLog -import com.tencent.devops.process.pojo.webhook.PipelineWebhookBuildLogDetail -import org.springframework.stereotype.Service +package com.tencent.devops.common.api.pojo -@Service -class PipelineWebhookBuildLogServiceImpl : PipelineWebhookBuildLogService { - override fun saveWebhookBuildLog(webhookBuildLog: PipelineWebhookBuildLog) = Unit +import com.tencent.devops.common.api.util.JsonUtil +import io.swagger.annotations.ApiModel +import io.swagger.annotations.ApiModelProperty - override fun listWebhookBuildLogDetail( - userId: String, - projectId: String, - pipelineId: String, - repoName: String?, - commitId: String?, - page: Int?, - pageSize: Int? - ): SQLPage? { - return null - } +@ApiModel("国际化变量") +data class I18Variable( + @ApiModelProperty("国际化变量名") + val code: String, + @ApiModelProperty("国际化参数") + val params: List, + @ApiModelProperty("默认信息") + val defaultMessage: String? = null +) { + fun toJsonStr() = JsonUtil.toJson(this, false) } diff --git a/src/backend/ci/core/common/common-event/src/main/kotlin/com/tencent/devops/common/event/dispatcher/pipeline/mq/MQ.kt b/src/backend/ci/core/common/common-event/src/main/kotlin/com/tencent/devops/common/event/dispatcher/pipeline/mq/MQ.kt index f9444bee868..9739d0e40ff 100644 --- a/src/backend/ci/core/common/common-event/src/main/kotlin/com/tencent/devops/common/event/dispatcher/pipeline/mq/MQ.kt +++ b/src/backend/ci/core/common/common-event/src/main/kotlin/com/tencent/devops/common/event/dispatcher/pipeline/mq/MQ.kt @@ -206,6 +206,11 @@ object MQ { const val ROUTE_P4_BUILD_REQUEST_EVENT = "r.engine.pipeline.hook.p4.event" const val QUEUE_P4_BUILD_REQUEST_EVENT = "q.engine.pipeline.hook.p4.event" + // 代码库webhook重放请求 + const val EXCHANGE_REPLAY_BUILD_REQUEST_EVENT = "e.engine.pipeline.hook.replay.event" + const val ROUTE_REPLAY_BUILD_REQUEST_EVENT = "r.engine.pipeline.hook.replay.event" + const val QUEUE_REPLAY_BUILD_REQUEST_EVENT = "q.engine.pipeline.hook.replay.event" + // 广播清理文件 const val EXCHANGE_BKJOB_CLEAR_JOB_TMP_FANOUT = "e.bkjob.clear.file.fanout" const val ROUTE_BKJOB_CLEAR_JOB_TMP_EVENT = "r.bkjob.clear.file" diff --git a/src/backend/ci/core/common/common-pipeline/src/main/kotlin/com/tencent/devops/common/pipeline/pojo/element/Element.kt b/src/backend/ci/core/common/common-pipeline/src/main/kotlin/com/tencent/devops/common/pipeline/pojo/element/Element.kt index 0f38d87f1af..e4d19faa845 100644 --- a/src/backend/ci/core/common/common-pipeline/src/main/kotlin/com/tencent/devops/common/pipeline/pojo/element/Element.kt +++ b/src/backend/ci/core/common/common-pipeline/src/main/kotlin/com/tencent/devops/common/pipeline/pojo/element/Element.kt @@ -45,7 +45,6 @@ import com.tencent.devops.common.pipeline.pojo.element.market.MarketCheckImageEl import com.tencent.devops.common.pipeline.pojo.element.matrix.MatrixStatusElement import com.tencent.devops.common.pipeline.pojo.element.quality.QualityGateInElement import com.tencent.devops.common.pipeline.pojo.element.quality.QualityGateOutElement -import com.tencent.devops.common.pipeline.pojo.element.trigger.CodeGitGenericWebHookTriggerElement import com.tencent.devops.common.pipeline.pojo.element.trigger.CodeGitWebHookTriggerElement import com.tencent.devops.common.pipeline.pojo.element.trigger.CodeGithubWebHookTriggerElement import com.tencent.devops.common.pipeline.pojo.element.trigger.CodeGitlabWebHookTriggerElement @@ -89,10 +88,6 @@ import io.swagger.annotations.ApiModelProperty JsonSubTypes.Type(value = QualityGateInElement::class, name = QualityGateInElement.classType), JsonSubTypes.Type(value = QualityGateOutElement::class, name = QualityGateOutElement.classType), JsonSubTypes.Type(value = CodeTGitWebHookTriggerElement::class, name = CodeTGitWebHookTriggerElement.classType), - JsonSubTypes.Type( - value = CodeGitGenericWebHookTriggerElement::class, - name = CodeGitGenericWebHookTriggerElement.classType - ), JsonSubTypes.Type(value = CodeP4WebHookTriggerElement::class, name = CodeP4WebHookTriggerElement.classType) ) @Suppress("ALL") diff --git a/src/backend/ci/core/common/common-pipeline/src/main/kotlin/com/tencent/devops/common/pipeline/pojo/element/trigger/CodeGitGenericWebHookTrigger.kt b/src/backend/ci/core/common/common-pipeline/src/main/kotlin/com/tencent/devops/common/pipeline/pojo/element/trigger/CodeGitGenericWebHookTrigger.kt deleted file mode 100644 index 49abec0a545..00000000000 --- a/src/backend/ci/core/common/common-pipeline/src/main/kotlin/com/tencent/devops/common/pipeline/pojo/element/trigger/CodeGitGenericWebHookTrigger.kt +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. - * - * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. - * - * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. - * - * A copy of the MIT License is included in this file. - * - * - * Terms of the MIT License: - * --------------------------------------------------- - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated - * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or substantial portions of - * the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT - * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN - * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -package com.tencent.devops.common.pipeline.pojo.element.trigger - -import com.tencent.devops.common.api.enums.RepositoryTypeNew -import com.tencent.devops.common.pipeline.pojo.element.trigger.enums.CodeEventType -import io.swagger.annotations.ApiModel -import io.swagger.annotations.ApiModelProperty - -@ApiModel("Git通用事件触发", description = CodeGitGenericWebHookTriggerElement.classType) -data class CodeGitGenericWebHookTriggerElement( - @ApiModelProperty("任务名称", required = true) - override val name: String = "TGit变更触发", - @ApiModelProperty("id", required = false) - override var id: String? = null, - @ApiModelProperty("状态", required = false) - override var status: String? = null, - @ApiModelProperty("数据", required = true) - val data: CodeGitGenericWebHookTriggerData -) : WebHookTriggerElement(name, id, status) { - companion object { - const val classType = "codeGitGenericWebHookTrigger" - } - - override fun getClassType() = classType -} - -data class CodeGitGenericWebHookTriggerData( - @ApiModelProperty("Git通用事件触发数据", required = true) - val input: CodeGitGenericWebHookTriggerInput -) - -data class CodeGitGenericWebHookTriggerInput( - @ApiModelProperty("代码库类型", required = true) - val scmType: String, - @ApiModelProperty("代码库类型") - val repositoryType: RepositoryTypeNew? = null, - @ApiModelProperty("仓库ID", required = true) - val repositoryHashId: String?, - @ApiModelProperty("代码库名") - val repositoryName: String? = null, - @ApiModelProperty("代码库链接", required = true) - val repositoryUrl: String, - @ApiModelProperty("凭证ID", required = false) - val credentialId: String? = null, - @ApiModelProperty("凭证ID", required = false) - val token: String? = null, - @ApiModelProperty("触发事件", required = true) - val eventType: String = CodeEventType.PUSH.name, - @ApiModelProperty("hook地址,目前只对codecc开放", required = false) - var hookUrl: String? = null, - @ApiModelProperty("分支", required = false) - val branchName: String?, - @ApiModelProperty("用于排除的分支名", required = false) - val excludeBranchName: String?, - @ApiModelProperty("用于包含的路径", required = false) - val includePaths: String?, - @ApiModelProperty("相对路径", required = true) - val relativePath: String?, - @ApiModelProperty("用于排除的路径", required = false) - val excludePaths: String?, - @ApiModelProperty("用于排除的user id", required = false) - val excludeUsers: List?, - @ApiModelProperty("用户白名单", required = false) - val includeUsers: List?, - @ApiModelProperty("是否为block", required = false) - val block: Boolean?, - @ApiModelProperty("tag名称", required = false) - val tagName: String? = null, - @ApiModelProperty("用于排除的tag名称", required = false) - val excludeTagName: String? = null, - @ApiModelProperty("用于排除的源分支名称", required = false) - val excludeSourceBranchName: String? = null, - @ApiModelProperty("用于包含的源分支名称", required = false) - val includeSourceBranchName: String? = null -) diff --git a/src/backend/ci/core/common/common-pipeline/src/main/kotlin/com/tencent/devops/common/pipeline/pojo/element/trigger/enums/CodeEventType.kt b/src/backend/ci/core/common/common-pipeline/src/main/kotlin/com/tencent/devops/common/pipeline/pojo/element/trigger/enums/CodeEventType.kt index c6020b6b9d5..4122a547ee2 100644 --- a/src/backend/ci/core/common/common-pipeline/src/main/kotlin/com/tencent/devops/common/pipeline/pojo/element/trigger/enums/CodeEventType.kt +++ b/src/backend/ci/core/common/common-pipeline/src/main/kotlin/com/tencent/devops/common/pipeline/pojo/element/trigger/enums/CodeEventType.kt @@ -27,6 +27,8 @@ package com.tencent.devops.common.pipeline.pojo.element.trigger.enums +import com.tencent.devops.common.api.enums.ScmType + enum class CodeEventType { // git event PUSH, @@ -62,5 +64,71 @@ enum class CodeEventType { companion object { const val MESSAGE_CODE_PREFIX = "EVENT_TYPE" + + /** + * 工蜂事件类型 + */ + val CODE_GIT_EVENTS = listOf( + PUSH, + MERGE_REQUEST, + MERGE_REQUEST_ACCEPT, + TAG_PUSH, + NOTE, + REVIEW, + ISSUES + ) + + /** + * Github事件类型 + */ + val CODE_GITHUB_EVENTS = listOf( + PUSH, + MERGE_REQUEST, + MERGE_REQUEST_ACCEPT, + CREATE, + REVIEW, + ISSUES, + NOTE + ) + + val CODE_P4_EVENTS = listOf( + CHANGE_COMMIT, + CHANGE_SUBMIT, + CHANGE_CONTENT, + SHELVE_COMMIT, + SHELVE_SUBMIT + ) + + val CODE_GITLAB_EVENTS = listOf( + PUSH, + MERGE_REQUEST, + MERGE_REQUEST_ACCEPT, + TAG_PUSH + ) + + val CODE_TGIT_EVENTS = listOf( + PUSH, + MERGE_REQUEST, + MERGE_REQUEST_ACCEPT, + TAG_PUSH, + NOTE, + ISSUES + ) + + val CODE_SVN_EVENTS = listOf( + POST_COMMIT, + PRE_COMMIT, + LOCK_COMMIT + ) + + fun getEventsByScmType(scmType: ScmType?): List = when (scmType) { + ScmType.CODE_GIT -> CODE_GIT_EVENTS + ScmType.CODE_TGIT -> CODE_TGIT_EVENTS + ScmType.GITHUB -> CODE_GITHUB_EVENTS + ScmType.CODE_GITLAB -> CODE_GITLAB_EVENTS + ScmType.CODE_SVN -> CODE_SVN_EVENTS + ScmType.CODE_P4 -> CODE_P4_EVENTS + else -> values().toList() + } } } diff --git a/src/backend/ci/core/common/common-pipeline/src/main/kotlin/com/tencent/devops/common/pipeline/utils/RepositoryConfigUtils.kt b/src/backend/ci/core/common/common-pipeline/src/main/kotlin/com/tencent/devops/common/pipeline/utils/RepositoryConfigUtils.kt index 8b29e007b29..387b35f8521 100644 --- a/src/backend/ci/core/common/common-pipeline/src/main/kotlin/com/tencent/devops/common/pipeline/utils/RepositoryConfigUtils.kt +++ b/src/backend/ci/core/common/common-pipeline/src/main/kotlin/com/tencent/devops/common/pipeline/utils/RepositoryConfigUtils.kt @@ -29,7 +29,7 @@ package com.tencent.devops.common.pipeline.utils import com.tencent.devops.common.api.enums.RepositoryConfig import com.tencent.devops.common.api.enums.RepositoryType -import com.tencent.devops.common.api.enums.RepositoryTypeNew +import com.tencent.devops.common.api.enums.ScmType import com.tencent.devops.common.api.exception.InvalidParamException import com.tencent.devops.common.api.util.EnvUtils import com.tencent.devops.common.pipeline.pojo.element.Element @@ -37,13 +37,13 @@ import com.tencent.devops.common.pipeline.pojo.element.agent.CodeGitElement import com.tencent.devops.common.pipeline.pojo.element.agent.CodeGitlabElement import com.tencent.devops.common.pipeline.pojo.element.agent.CodeSvnElement import com.tencent.devops.common.pipeline.pojo.element.agent.GithubElement -import com.tencent.devops.common.pipeline.pojo.element.trigger.CodeGitGenericWebHookTriggerElement import com.tencent.devops.common.pipeline.pojo.element.trigger.CodeGitWebHookTriggerElement import com.tencent.devops.common.pipeline.pojo.element.trigger.CodeGithubWebHookTriggerElement import com.tencent.devops.common.pipeline.pojo.element.trigger.CodeGitlabWebHookTriggerElement import com.tencent.devops.common.pipeline.pojo.element.trigger.CodeP4WebHookTriggerElement import com.tencent.devops.common.pipeline.pojo.element.trigger.CodeSVNWebHookTriggerElement import com.tencent.devops.common.pipeline.pojo.element.trigger.CodeTGitWebHookTriggerElement +import com.tencent.devops.common.pipeline.pojo.element.trigger.enums.CodeEventType object RepositoryConfigUtils { @@ -95,32 +95,6 @@ object RepositoryConfigUtils { repositoryName = element.data.input.repositoryName, repositoryType = element.data.input.repositoryType ?: RepositoryType.ID ) - is CodeGitGenericWebHookTriggerElement -> { - with(element.data.input) { - when (repositoryType) { - RepositoryTypeNew.URL -> - RepositoryConfig( - repositoryHashId = null, - repositoryName = repositoryUrl, - repositoryType = RepositoryType.NAME - ) - RepositoryTypeNew.ID -> - RepositoryConfig( - repositoryHashId = repositoryHashId, - repositoryName = repositoryName, - repositoryType = RepositoryType.ID - ) - RepositoryTypeNew.NAME -> - RepositoryConfig( - repositoryHashId = repositoryHashId, - repositoryName = repositoryName, - repositoryType = RepositoryType.NAME - ) - else -> - throw InvalidParamException("Unknown repositoryType -> $element") - } - } - } is CodeP4WebHookTriggerElement -> RepositoryConfig( repositoryHashId = element.data.input.repositoryHashId, repositoryName = element.data.input.repositoryName, @@ -160,4 +134,102 @@ object RepositoryConfigUtils { repositoryType = RepositoryType.NAME ) } + + fun buildWebhookConfig( + element: Element, + variables: Map + ): Triple { + return when (element) { + is CodeGitWebHookTriggerElement -> { + val repositoryConfig = RepositoryConfig( + repositoryHashId = element.repositoryHashId, + repositoryName = EnvUtils.parseEnv(element.repositoryName, variables), + repositoryType = element.repositoryType ?: RepositoryType.ID + ) + Triple(ScmType.CODE_GIT, element.eventType, repositoryConfig) + } + + is CodeSVNWebHookTriggerElement -> { + val repositoryConfig = RepositoryConfig( + repositoryHashId = element.repositoryHashId, + repositoryName = EnvUtils.parseEnv(element.repositoryName, variables), + repositoryType = element.repositoryType ?: RepositoryType.ID + ) + Triple(ScmType.CODE_SVN, CodeEventType.PUSH_COMMIT, repositoryConfig) + } + + is CodeGitlabWebHookTriggerElement -> { + val repositoryConfig = RepositoryConfig( + repositoryHashId = element.repositoryHashId, + repositoryName = EnvUtils.parseEnv(element.repositoryName, variables), + repositoryType = element.repositoryType ?: RepositoryType.ID + ) + Triple(ScmType.CODE_GITLAB, element.eventType, repositoryConfig) + } + + is CodeGithubWebHookTriggerElement -> { + val repositoryConfig = RepositoryConfig( + repositoryHashId = element.repositoryHashId, + repositoryName = EnvUtils.parseEnv(element.repositoryName, variables), + repositoryType = element.repositoryType ?: RepositoryType.ID + ) + Triple(ScmType.GITHUB, element.eventType, repositoryConfig) + } + + is CodeTGitWebHookTriggerElement -> { + val repositoryConfig = RepositoryConfig( + repositoryHashId = element.data.input.repositoryHashId, + repositoryName = EnvUtils.parseEnv(element.data.input.repositoryName, variables), + repositoryType = element.data.input.repositoryType ?: RepositoryType.ID + ) + Triple(ScmType.CODE_TGIT, element.data.input.eventType, repositoryConfig) + } + + is CodeP4WebHookTriggerElement -> { + val repositoryConfig = RepositoryConfig( + repositoryHashId = element.data.input.repositoryHashId, + repositoryName = EnvUtils.parseEnv(element.data.input.repositoryName, variables), + repositoryType = element.data.input.repositoryType ?: RepositoryType.ID + ) + Triple(ScmType.CODE_P4, element.data.input.eventType, repositoryConfig) + } + + else -> + throw InvalidParamException("Unknown code element -> $element") + } + } + + fun getRepositoryConfig( + repoHashId: String?, + repoName: String?, + repoType: RepositoryType?, + variables: Map? = null + ): RepositoryConfig { + return when (repoType) { + RepositoryType.ID -> RepositoryConfig(repoHashId, null, RepositoryType.ID) + RepositoryType.NAME -> { + val repositoryName = if (variables.isNullOrEmpty()) { + repoName!! + } else { + EnvUtils.parseEnv(repoName!!, variables) + } + RepositoryConfig(null, repositoryName, RepositoryType.NAME) + } + else -> { + if (!repoHashId.isNullOrBlank()) { + RepositoryConfig(repoHashId, null, RepositoryType.ID) + } else if (!repoName.isNullOrBlank()) { + val repositoryName = if (variables.isNullOrEmpty()) { + repoName + } else { + EnvUtils.parseEnv(repoName, variables) + } + RepositoryConfig(null, repositoryName, RepositoryType.NAME) + } else { + // 两者不能同时为空 + throw IllegalArgumentException("repoName and Id cannot both be empty") + } + } + } + } } diff --git a/src/backend/ci/core/common/common-pipeline/src/test/kotlin/com/tencent/devops/common/pipeline/enums/EnvControlTaskTypeTest.kt b/src/backend/ci/core/common/common-pipeline/src/test/kotlin/com/tencent/devops/common/pipeline/enums/EnvControlTaskTypeTest.kt index 4b2538a3478..cadb56ee2bc 100644 --- a/src/backend/ci/core/common/common-pipeline/src/test/kotlin/com/tencent/devops/common/pipeline/enums/EnvControlTaskTypeTest.kt +++ b/src/backend/ci/core/common/common-pipeline/src/test/kotlin/com/tencent/devops/common/pipeline/enums/EnvControlTaskTypeTest.kt @@ -41,7 +41,6 @@ import com.tencent.devops.common.pipeline.pojo.element.market.MarketCheckImageEl import com.tencent.devops.common.pipeline.pojo.element.matrix.MatrixStatusElement import com.tencent.devops.common.pipeline.pojo.element.quality.QualityGateInElement import com.tencent.devops.common.pipeline.pojo.element.quality.QualityGateOutElement -import com.tencent.devops.common.pipeline.pojo.element.trigger.CodeGitGenericWebHookTriggerElement import com.tencent.devops.common.pipeline.pojo.element.trigger.CodeGitWebHookTriggerElement import com.tencent.devops.common.pipeline.pojo.element.trigger.CodeGithubWebHookTriggerElement import com.tencent.devops.common.pipeline.pojo.element.trigger.CodeGitlabWebHookTriggerElement @@ -68,7 +67,6 @@ class EnvControlTaskTypeTest { assertEquals(EnvControlTaskType.parse(""), actualNull) assertEquals(EnvControlTaskType.parse("nullActual"), actualNull) assertEquals(EnvControlTaskType.parse("Other"), actualNull) - assertEquals(EnvControlTaskType.parse(CodeGitGenericWebHookTriggerElement.classType), actualNull) assertEquals(EnvControlTaskType.parse(CodeP4WebHookTriggerElement.classType), actualNull) assertEquals(EnvControlTaskType.parse(MatrixStatusElement.classType), actualNull) assertEquals(EnvControlTaskType.parse(CodeGitWebHookTriggerElement.classType), actualNull) diff --git a/src/backend/ci/core/common/common-web/src/main/kotlin/com/tencent/devops/common/web/utils/I18nUtil.kt b/src/backend/ci/core/common/common-web/src/main/kotlin/com/tencent/devops/common/web/utils/I18nUtil.kt index dede2937967..c4d63f914e8 100644 --- a/src/backend/ci/core/common/common-web/src/main/kotlin/com/tencent/devops/common/web/utils/I18nUtil.kt +++ b/src/backend/ci/core/common/common-web/src/main/kotlin/com/tencent/devops/common/web/utils/I18nUtil.kt @@ -33,12 +33,14 @@ import com.tencent.devops.common.api.constant.DEFAULT_LOCALE_LANGUAGE import com.tencent.devops.common.api.constant.REQUEST_CHANNEL import com.tencent.devops.common.api.enums.RequestChannelTypeEnum import com.tencent.devops.common.api.enums.SystemModuleEnum +import com.tencent.devops.common.api.pojo.I18Variable import com.tencent.devops.common.api.pojo.Result import com.tencent.devops.common.api.util.LocaleUtil import com.tencent.devops.common.api.util.MessageUtil import com.tencent.devops.common.client.Client import com.tencent.devops.common.redis.RedisOperation import com.tencent.devops.common.service.config.CommonConfig +import com.tencent.devops.common.service.utils.CommonUtils import com.tencent.devops.common.service.utils.CookieUtil import com.tencent.devops.common.service.utils.SpringContextUtil import com.tencent.devops.common.web.service.ServiceLocaleResource @@ -221,6 +223,14 @@ object I18nUtil { } } + fun I18Variable.getCodeLanMessage(language: String? = CommonUtils.ZH_CN): String { + return getCodeLanMessage( + language = language, + messageCode = code, + params = params.toTypedArray() + ) + } + /** * 生成请求响应对象 * @param messageCode 状态码 diff --git a/src/backend/ci/core/common/common-webhook/api-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/enums/WebhookI18nConstants.kt b/src/backend/ci/core/common/common-webhook/api-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/enums/WebhookI18nConstants.kt new file mode 100644 index 00000000000..eecfed46836 --- /dev/null +++ b/src/backend/ci/core/common/common-webhook/api-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/enums/WebhookI18nConstants.kt @@ -0,0 +1,132 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package com.tencent.devops.common.webhook.enums + +object WebhookI18nConstants { + // 工蜂事件描述 + const val TGIT_PUSH_EVENT_DESC = "bkTgitPushEventDesc" + const val TGIT_ISSUE_CREATED_EVENT_DESC = "bkTgitIssueCreatedEventDesc" + const val TGIT_ISSUE_UPDATED_EVENT_DESC = "bkTgitIssueUpdatedEventDesc" + const val TGIT_ISSUE_CLOSED_EVENT_DESC = "bkTgitIssueClosedEventDesc" + const val TGIT_ISSUE_REOPENED_EVENT_DESC = "bkTgitIssueReopenedEventDesc" + const val TGIT_MR_CREATED_EVENT_DESC = "bkTgitMrCreatedEventDesc" + const val TGIT_MR_UPDATED_EVENT_DESC = "bkTgitMrUpdatedEventDesc" + const val TGIT_MR_CLOSED_EVENT_DESC = "bkTgitMrClosedEventDesc" + const val TGIT_MR_REOPENED_EVENT_DESC = "bkTgitMrReopenedEventDesc" + const val TGIT_MR_PUSH_UPDATED_EVENT_DESC = "bkTgitMrPushUpdatedEventDesc" + const val TGIT_MR_MERGED_EVENT_DESC = "bkTgitMrMergedEventDesc" + const val TGIT_NOTE_EVENT_DESC = "bkTgitNoteEventDesc" + const val TGIT_REVIEW_APPROVED_EVENT_DESC = "bkTgitReviewApprovedEventDesc" + const val TGIT_REVIEW_APPROVING_EVENT_DESC = "bkTgitReviewApprovingEventDesc" + const val TGIT_REVIEW_CHANGE_DENIED_EVENT_DESC = "bkTgitReviewChangeDeniedEventDesc" + const val TGIT_REVIEW_CHANGE_REQUIRED_EVENT_DESC = "bkTgitReviewChangeRequiredEventDesc" + const val TGIT_REVIEW_CREATED_EVENT_DESC = "bkTgitReviewCreatedEventDesc" + const val TGIT_TAG_PUSH_EVENT_DESC = "bkTgitTagPushEventDesc" + + // Github事件描述 + const val GITHUB_PUSH_EVENT_DESC = "bkGithubPushEventDesc" + const val GITHUB_CREATE_TAG_EVENT_DESC = "bkGithubCreateTagEventDesc" + const val GITHUB_CREATE_BRANCH_EVENT_DESC = "bkGithubCreateBranchEventDesc" + const val GITHUB_PR_EVENT_DESC = "bkGithubPrEventDesc" + + // P4事件描述 + const val P4_EVENT_DESC = "bkP4EventDesc" + + // SVN事件描述 + const val SVN_COMMIT_EVENT_DESC = "bkSvnCommitEventDesc" + + // 手动触发 + const val MANUAL_START_EVENT_DESC = "bkManualStartEventDesc" + + // 远程触发 + const val REMOTE_START_EVENT_DESC = "bkRemoteStartEventDesc" + + // openApi触发 + const val OPENAPI_START_EVENT_DESC = "bkServiceStartEventDesc" + + // 流水线触发 + const val PIPELINE_START_EVENT_DESC = "bkPipelineStartEventDesc" + + // 定时触发 + const val TIMING_START_EVENT_DESC = "bkTimingStartEventDesc" + + // 事件类型匹配 + const val EVENT_TYPE_MATCHED = "bkRepoTriggerEventTypeMatched" + + // 事件类型不匹配 + const val EVENT_TYPE_NOT_MATCH = "bkRepoTriggerEventTypeNotMatch" + + // 目标分支不匹配 + const val TARGET_BRANCH_NOT_MATCH = "bkRepoTriggerTargetBranchNotMatch" + + // 目标分支被排除 + const val TARGET_BRANCH_IGNORED = "bkRepoTriggerTargetBranchIgnored" + + // 源分支不匹配 + const val SOURCE_BRANCH_NOT_MATCH = "bkRepoTriggerSourceBranchNotMatch" + + // 源分支被排除 + const val SOURCE_BRANCH_IGNORED = "bkRepoTriggerSourceBranchIgnored" + + // 用户不匹配 + const val USER_NOT_MATCH = "bkRepoTriggerUserNotMatch" + + // 用户被排除 + const val USER_IGNORED = "bkRepoTriggerUserIgnored" + + // 路径不匹配 + const val PATH_NOT_MATCH = "bkRepoTriggerPathNotMatch" + + // 路径被排除 + const val PATH_IGNORED = "bkRepoTriggerPathIgnored" + + // Tag名称不匹配 + const val TAG_NAME_NOT_MATCH = "bkRepoTriggerTagNameNotMatch" + + // Tag名称被排除 + const val TAG_NAME_IGNORED = "bkRepoTriggerTagNameIgnored" + + // Tag来源分支不匹配 + const val TAG_SOURCE_BRANCH_NOT_MATCH = "bkRepoTriggerTagSourceBranchNotMatch" + + // 评论内容不匹配 + const val NOTE_CONTENT_NOT_MATCH = "bkRepoTriggerNoteContentNotMatch" + + // 评论类型不匹配 + const val NOTE_ACTION_NOT_MATCH = "bkRepoTriggerNoteActionNotMatch" + + // 评审操作类型不匹配 + const val REVIEW_ACTION_NOT_MATCH = "bkRepoTriggerReviewActionNotMatch" + + // issues操作类型不匹配 + const val ISSUES_ACTION_NOT_MATCH = "bkRepoTriggerIssueActionNotMatch" + + // 事件回放 + const val EVENT_REPLAY_DESC = "bkEventReplayDesc" +} diff --git a/src/backend/ci/core/common/common-webhook/api-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/pojo/WebhookRequest.kt b/src/backend/ci/core/common/common-webhook/api-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/pojo/WebhookRequest.kt new file mode 100644 index 00000000000..281289b675c --- /dev/null +++ b/src/backend/ci/core/common/common-webhook/api-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/pojo/WebhookRequest.kt @@ -0,0 +1,35 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package com.tencent.devops.common.webhook.pojo + +data class WebhookRequest( + val headers: Map? = null, + val queryParams: Map? = null, + val body: String +) diff --git a/src/backend/ci/core/common/common-webhook/api-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/pojo/code/PathFilterConfig.kt b/src/backend/ci/core/common/common-webhook/api-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/pojo/code/PathFilterConfig.kt index 2f1425ad408..a9afda34326 100644 --- a/src/backend/ci/core/common/common-webhook/api-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/pojo/code/PathFilterConfig.kt +++ b/src/backend/ci/core/common/common-webhook/api-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/pojo/code/PathFilterConfig.kt @@ -35,5 +35,9 @@ data class PathFilterConfig( val triggerOnPath: List, val includedPaths: List, val excludedPaths: List, + // 包含过滤失败原因 + val includedFailedReason: String, + // 排除过滤失败原因 + val excludedFailedReason: String, val caseSensitive: Boolean = true ) diff --git a/src/backend/ci/core/common/common-webhook/api-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/pojo/code/git/GitIssueEvent.kt b/src/backend/ci/core/common/common-webhook/api-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/pojo/code/git/GitIssueEvent.kt index a3f6702a61a..fd8fece88f8 100644 --- a/src/backend/ci/core/common/common-webhook/api-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/pojo/code/git/GitIssueEvent.kt +++ b/src/backend/ci/core/common/common-webhook/api-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/pojo/code/git/GitIssueEvent.kt @@ -39,6 +39,10 @@ data class GitIssueEvent( ) : GitEvent() { companion object { const val classType = "issue" + const val ACTION_CREATED = "open" + const val ACTION_UPDATED = "update" + const val ACTION_CLOSED = "close" + const val ACTION_REOPENED = "reopen" } } diff --git a/src/backend/ci/core/common/common-webhook/api-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/pojo/code/git/GitMergeRequestEvent.kt b/src/backend/ci/core/common/common-webhook/api-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/pojo/code/git/GitMergeRequestEvent.kt index 53438d4d7cf..8ec0a48540d 100644 --- a/src/backend/ci/core/common/common-webhook/api-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/pojo/code/git/GitMergeRequestEvent.kt +++ b/src/backend/ci/core/common/common-webhook/api-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/pojo/code/git/GitMergeRequestEvent.kt @@ -39,6 +39,11 @@ data class GitMergeRequestEvent( ) : GitEvent() { companion object { const val classType = "merge_request" + const val ACTION_CREATED = "open" + const val ACTION_UPDATED = "update" + const val ACTION_CLOSED = "close" + const val ACTION_REOPENED = "reopen" + const val ACTION_MERGED = "merge" } } diff --git a/src/backend/ci/core/common/common-webhook/api-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/pojo/code/git/GitPushEvent.kt b/src/backend/ci/core/common/common-webhook/api-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/pojo/code/git/GitPushEvent.kt index 2e98b768deb..fb008141f2b 100644 --- a/src/backend/ci/core/common/common-webhook/api-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/pojo/code/git/GitPushEvent.kt +++ b/src/backend/ci/core/common/common-webhook/api-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/pojo/code/git/GitPushEvent.kt @@ -47,12 +47,15 @@ data class GitPushEvent( val operation_kind: String?, val action_kind: String?, val push_options: Map?, + @JsonProperty("push_timestamp") + val pushTimestamp: String?, val create_and_update: Boolean?, @JsonProperty("diff_files") val diffFiles: List? ) : GitEvent() { companion object { const val classType = "push" + const val SHORT_COMMIT_ID_LENGTH = 8 } } diff --git a/src/backend/ci/core/common/common-webhook/api-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/pojo/code/git/GitReviewEvent.kt b/src/backend/ci/core/common/common-webhook/api-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/pojo/code/git/GitReviewEvent.kt index 8ff3a76a677..99d61480f9d 100644 --- a/src/backend/ci/core/common/common-webhook/api-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/pojo/code/git/GitReviewEvent.kt +++ b/src/backend/ci/core/common/common-webhook/api-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/pojo/code/git/GitReviewEvent.kt @@ -55,10 +55,19 @@ data class GitReviewEvent( val commitId: String? = null, val state: String, @JsonProperty("restrict_type") - val restrictType: String? = null + val restrictType: String? = null, + @JsonProperty("created_at") + val createdAt: String, + @JsonProperty("updated_at") + val updatedAt: String ) : GitEvent() { companion object { const val classType = "review" + const val ACTION_APPROVED = "approved" + const val ACTION_APPROVING = "approving" + const val ACTION_CHANGE_DENIED = "change_denied" + const val ACTION_CHANGE_REQUIRED = "change_required" + const val ACTION_EMPTY = "empty" } } diff --git a/src/backend/ci/core/common/common-webhook/api-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/pojo/code/git/GitTagPushEvent.kt b/src/backend/ci/core/common/common-webhook/api-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/pojo/code/git/GitTagPushEvent.kt index ab9bb938179..ab861620d5c 100644 --- a/src/backend/ci/core/common/common-webhook/api-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/pojo/code/git/GitTagPushEvent.kt +++ b/src/backend/ci/core/common/common-webhook/api-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/pojo/code/git/GitTagPushEvent.kt @@ -28,6 +28,7 @@ package com.tencent.devops.common.webhook.pojo.code.git import com.fasterxml.jackson.annotation.JsonIgnoreProperties +import com.fasterxml.jackson.annotation.JsonProperty import com.tencent.devops.common.webhook.enums.code.tgit.TGitTagPushActionKind import com.tencent.devops.common.webhook.enums.code.tgit.TGitTagPushOperationKind @@ -46,6 +47,8 @@ data class GitTagPushEvent( val total_commits_count: Int, val operation_kind: String?, val create_from: String? = null, + @JsonProperty("push_timestamp") + val pushTimestamp: String?, val message: String? ) : GitEvent() { companion object { diff --git a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/filter/BasePathFilter.kt b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/filter/BasePathFilter.kt index 0211c3b4169..89aac73b23b 100644 --- a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/filter/BasePathFilter.kt +++ b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/filter/BasePathFilter.kt @@ -35,6 +35,10 @@ abstract class BasePathFilter( private val triggerOnPath: List, private val includedPaths: List, private val excludedPaths: List, + // 包含过滤失败原因 + private val includedFailedReason: String, + // 排除过滤失败原因 + private val excludedFailedReason: String, private val caseSensitive: Boolean = true ) : WebhookFilter { @@ -90,8 +94,16 @@ abstract class BasePathFilter( // 1. 包含不为空,过滤为空,判断matchIncludePaths是否为空 // 2. 包含为空,过滤不为空,matchIncludePaths与triggerOnPath相同,判断matchIncludePaths与matchExcludedPaths大小 return when { - excludedPaths.isEmpty() && includedPaths.isNotEmpty() && matchIncludePaths.isEmpty() -> false - matchIncludePaths.size == matchExcludedPaths.size -> false + excludedPaths.isEmpty() && includedPaths.isNotEmpty() && matchIncludePaths.isEmpty() -> { + response.failedReason = includedFailedReason + false + } + + matchIncludePaths.size == matchExcludedPaths.size -> { + response.failedReason = excludedFailedReason + false + } + else -> true } } diff --git a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/filter/BranchFilter.kt b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/filter/BranchFilter.kt index 7bea9f12b3e..aa7f4d4fa78 100644 --- a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/filter/BranchFilter.kt +++ b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/filter/BranchFilter.kt @@ -35,7 +35,11 @@ class BranchFilter( private val pipelineId: String, private val triggerOnBranchName: String, private val includedBranches: List, - private val excludedBranches: List + private val excludedBranches: List, + // 包含过滤失败原因 + private val includedFailedReason: String = "", + // 排除过滤失败原因 + private val excludedFailedReason: String = "" ) : WebhookFilter { companion object { @@ -48,19 +52,20 @@ class BranchFilter( "$pipelineId|triggerOnBranchName:$triggerOnBranchName|includedBranches:$includedBranches" + "|excludedBranches:$excludedBranches|branch filter" ) - return hasNoBranchSpecs() || (isBranchNotExcluded() && isBranchIncluded(response)) + return hasNoBranchSpecs() || (isBranchNotExcluded(response) && isBranchIncluded(response)) } private fun hasNoBranchSpecs(): Boolean { return includedBranches.isEmpty() && excludedBranches.isEmpty() } - private fun isBranchNotExcluded(): Boolean { + private fun isBranchNotExcluded(response: WebhookFilterResponse): Boolean { excludedBranches.forEach { excludePattern -> if (matcher.match(excludePattern, triggerOnBranchName)) { logger.warn( "$pipelineId|the excluded branch match the git event branch $excludePattern" ) + response.failedReason = excludedFailedReason return false } } @@ -77,6 +82,10 @@ class BranchFilter( return true } } - return includedBranches.isEmpty() + val branchIncluded = includedBranches.isEmpty() + if (!branchIncluded) { + response.failedReason = includedFailedReason + } + return branchIncluded } } diff --git a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/filter/ContainsFilter.kt b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/filter/ContainsFilter.kt index 75c7822d73d..1db5720e0da 100644 --- a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/filter/ContainsFilter.kt +++ b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/filter/ContainsFilter.kt @@ -37,7 +37,8 @@ class ContainsFilter( // 过滤器名字 private val filterName: String, private val triggerOn: String, - private val included: List + private val included: List, + private val failedReason: String = "" ) : WebhookFilter { companion object { @@ -46,6 +47,10 @@ class ContainsFilter( override fun doFilter(response: WebhookFilterResponse): Boolean { logger.info("$pipelineId|triggerOn:$triggerOn|included:$included|$filterName filter") - return included.isEmpty() || included.contains(triggerOn) + val filterResult = included.isEmpty() || included.contains(triggerOn) + if (!filterResult && failedReason.isNotBlank()) { + response.failedReason = failedReason + } + return filterResult } } diff --git a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/filter/PathFilterFactory.kt b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/filter/PathFilterFactory.kt index 9873485c278..e6250aacefc 100644 --- a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/filter/PathFilterFactory.kt +++ b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/filter/PathFilterFactory.kt @@ -41,6 +41,8 @@ object PathFilterFactory { triggerOnPath = triggerOnPath, includedPaths = includedPaths, excludedPaths = excludedPaths, + includedFailedReason = includedFailedReason, + excludedFailedReason = excludedFailedReason, caseSensitive = caseSensitive ) else -> @@ -48,7 +50,9 @@ object PathFilterFactory { pipelineId = pipelineId, triggerOnPath = triggerOnPath, includedPaths = includedPaths, - excludedPaths = excludedPaths + excludedPaths = excludedPaths, + includedFailedReason = includedFailedReason, + excludedFailedReason = excludedFailedReason ) } } diff --git a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/filter/PathPrefixFilter.kt b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/filter/PathPrefixFilter.kt index 37cbc1fb314..2cc1c6e0e0e 100644 --- a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/filter/PathPrefixFilter.kt +++ b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/filter/PathPrefixFilter.kt @@ -31,12 +31,18 @@ class PathPrefixFilter( private val pipelineId: String, private val triggerOnPath: List, private val includedPaths: List, - private val excludedPaths: List + private val excludedPaths: List, + // 包含过滤失败原因 + private val includedFailedReason: String = "", + // 排除过滤失败原因 + private val excludedFailedReason: String = "" ) : BasePathFilter( pipelineId = pipelineId, triggerOnPath = triggerOnPath, includedPaths = includedPaths, - excludedPaths = excludedPaths + excludedPaths = excludedPaths, + includedFailedReason = includedFailedReason, + excludedFailedReason = excludedFailedReason ) { override fun isPathMatch(eventPath: String, userPath: String): Boolean { diff --git a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/filter/PathRegexFilter.kt b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/filter/PathRegexFilter.kt index 885fbc6f8e1..b3bc9754b5d 100644 --- a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/filter/PathRegexFilter.kt +++ b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/filter/PathRegexFilter.kt @@ -34,12 +34,18 @@ class PathRegexFilter( private val triggerOnPath: List, private val includedPaths: List, private val excludedPaths: List, + // 包含过滤失败原因 + private val includedFailedReason: String = "", + // 排除过滤失败原因 + private val excludedFailedReason: String = "", private val caseSensitive: Boolean ) : BasePathFilter( pipelineId = pipelineId, triggerOnPath = triggerOnPath, includedPaths = includedPaths, excludedPaths = excludedPaths, + includedFailedReason = includedFailedReason, + excludedFailedReason = excludedFailedReason, caseSensitive = caseSensitive ) { private val matcher = AntPathMatcher() diff --git a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/filter/PathStreamFilter.kt b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/filter/PathStreamFilter.kt index f35c32c49fc..3d6c101ba40 100644 --- a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/filter/PathStreamFilter.kt +++ b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/filter/PathStreamFilter.kt @@ -12,12 +12,18 @@ class PathStreamFilter( private val pipelineId: String, private val triggerOnPath: List, private val includedPaths: List, - private val excludedPaths: List + private val excludedPaths: List, + // 包含过滤失败原因 + private val includedFailedReason: String = "", + // 排除过滤失败原因 + private val excludedFailedReason: String = "" ) : BasePathFilter( pipelineId = pipelineId, triggerOnPath = triggerOnPath, includedPaths = includedPaths, - excludedPaths = excludedPaths + excludedPaths = excludedPaths, + includedFailedReason = includedFailedReason, + excludedFailedReason = excludedFailedReason ) { companion object { diff --git a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/filter/RegexContainFilter.kt b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/filter/RegexContainFilter.kt index da00ab5e892..55025621f9e 100644 --- a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/filter/RegexContainFilter.kt +++ b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/filter/RegexContainFilter.kt @@ -39,7 +39,8 @@ class RegexContainFilter( // 过滤器名字 private val filterName: String, private val triggerOn: String, - private val included: List + private val included: List, + private val failedReason: String = "" ) : WebhookFilter { companion object { @@ -48,6 +49,15 @@ class RegexContainFilter( override fun doFilter(response: WebhookFilterResponse): Boolean { logger.info("$pipelineId|triggerOn:$triggerOn|included:$included|$filterName filter") + val filterResult = filterAction() + if (!filterResult && failedReason.isNotBlank()) { + response.failedReason = failedReason + } + return filterResult + } + + @SuppressWarnings("ReturnCount") + private fun filterAction(): Boolean { if (included.isEmpty()) { return true } diff --git a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/filter/UserFilter.kt b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/filter/UserFilter.kt index 30577e7ad7e..411fde2799b 100644 --- a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/filter/UserFilter.kt +++ b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/filter/UserFilter.kt @@ -33,7 +33,11 @@ class UserFilter( private val pipelineId: String, private val triggerOnUser: String, private val includedUsers: List, - private val excludedUsers: List + private val excludedUsers: List, + // 包含过滤失败原因 + private val includedFailedReason: String = "", + // 排除过滤失败原因 + private val excludedFailedReason: String = "" ) : WebhookFilter { companion object { @@ -45,30 +49,35 @@ class UserFilter( "$pipelineId|triggerOnUser:$triggerOnUser|includedUsers:$includedUsers" + "|excludedUsers:$excludedUsers|user filter" ) - return hasNoUserSpecs() || (isUserNotExcluded() && isUserIncluded()) + return hasNoUserSpecs() || (isUserNotExcluded(response) && isUserIncluded(response)) } private fun hasNoUserSpecs(): Boolean { return includedUsers.isEmpty() && excludedUsers.isEmpty() } - private fun isUserNotExcluded(): Boolean { + private fun isUserNotExcluded(response: WebhookFilterResponse): Boolean { excludedUsers.forEach { excludeUser -> if (excludeUser == triggerOnUser) { logger.warn("$pipelineId|$excludeUser|the exclude user match the git event user") + response.failedReason = excludedFailedReason return false } } return true } - private fun isUserIncluded(): Boolean { + private fun isUserIncluded(response: WebhookFilterResponse): Boolean { includedUsers.forEach { includedUser -> if (includedUser == triggerOnUser) { logger.warn("$pipelineId|includedUser|the included user match the git event user") return true } } - return includedUsers.isEmpty() + val userIncluded = includedUsers.isEmpty() + if (!userIncluded) { + response.failedReason = includedFailedReason + } + return userIncluded } } diff --git a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/filter/WebhookFilterResponse.kt b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/filter/WebhookFilterResponse.kt index 038b2227bce..5811a18a32b 100644 --- a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/filter/WebhookFilterResponse.kt +++ b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/filter/WebhookFilterResponse.kt @@ -30,14 +30,12 @@ package com.tencent.devops.common.webhook.service.code.filter /** * webhook过滤器返回结果 */ -class WebhookFilterResponse { - private val params = mutableMapOf() - +data class WebhookFilterResponse( + val params: MutableMap = mutableMapOf(), + // 过滤失败原因 + var failedReason: String? = null +) { fun addParam(key: String, value: String) { params[key] = value } - - fun getParam(): Map { - return params - } } diff --git a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/CodeWebhookTriggerHandler.kt b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/CodeWebhookTriggerHandler.kt index f547ef5b4d1..e84118bc7a4 100644 --- a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/CodeWebhookTriggerHandler.kt +++ b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/CodeWebhookTriggerHandler.kt @@ -33,7 +33,7 @@ import com.tencent.devops.common.webhook.pojo.code.WebHookParams import com.tencent.devops.common.webhook.service.code.filter.WebhookFilter import com.tencent.devops.common.webhook.service.code.filter.WebhookFilterChain import com.tencent.devops.common.webhook.service.code.filter.WebhookFilterResponse -import com.tencent.devops.common.webhook.service.code.matcher.ScmWebhookMatcher +import com.tencent.devops.common.webhook.service.code.pojo.WebhookMatchResult import com.tencent.devops.repository.pojo.Repository import com.tencent.devops.scm.pojo.WebhookCommit @@ -67,9 +67,22 @@ interface CodeWebhookTriggerHandler { fun getMergeRequestId(event: T): Long? = null + /** + * 事件产生时的消息 + */ fun getMessage(event: T): String? - fun preMatch(event: T): ScmWebhookMatcher.MatchResult = ScmWebhookMatcher.MatchResult(isMatch = true) + /** + * 获取事件说明,根据不同的事件组织事件说明 + */ + fun getEventDesc(event: T): String = "" + + /** + * 获取webhook事件生产者ID,工蜂-工蜂ID,github-github id,svn-svn path,p4-p4port + */ + fun getExternalId(event: T): String = "" + + fun preMatch(event: T): WebhookMatchResult = WebhookMatchResult(isMatch = true) fun getWebhookCommitList( event: T, @@ -90,7 +103,7 @@ interface CodeWebhookTriggerHandler { pipelineId: String, repository: Repository, webHookParams: WebHookParams - ): ScmWebhookMatcher.MatchResult { + ): WebhookMatchResult { val filters = getWebhookFilters( event = event, projectId = projectId, @@ -100,12 +113,13 @@ interface CodeWebhookTriggerHandler { ) val response = WebhookFilterResponse() return if (filters.isNotEmpty()) { - ScmWebhookMatcher.MatchResult( + WebhookMatchResult( isMatch = WebhookFilterChain(filters = filters).doFilter(response), - extra = response.getParam() + extra = response.params, + reason = response.failedReason ) } else { - ScmWebhookMatcher.MatchResult(isMatch = true) + WebhookMatchResult(isMatch = true) } } diff --git a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/GitHookTriggerHandler.kt b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/GitHookTriggerHandler.kt index df8faa42548..8b81ca145a4 100644 --- a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/GitHookTriggerHandler.kt +++ b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/GitHookTriggerHandler.kt @@ -29,12 +29,9 @@ package com.tencent.devops.common.webhook.service.code.handler import com.tencent.devops.common.webhook.pojo.code.CodeWebhookEvent import com.tencent.devops.common.webhook.pojo.code.WebHookParams -import com.tencent.devops.common.webhook.service.code.filter.BranchFilter import com.tencent.devops.common.webhook.service.code.filter.EventTypeFilter import com.tencent.devops.common.webhook.service.code.filter.GitUrlFilter -import com.tencent.devops.common.webhook.service.code.filter.UserFilter import com.tencent.devops.common.webhook.service.code.filter.WebhookFilter -import com.tencent.devops.common.webhook.util.WebhookUtils import com.tencent.devops.repository.pojo.Repository interface GitHookTriggerHandler : CodeWebhookTriggerHandler { @@ -96,19 +93,7 @@ interface GitHookTriggerHandler : CodeWebhookTriggerHandle eventType = eventType, action = getAction(event) ) - val userFilter = UserFilter( - pipelineId = pipelineId, - triggerOnUser = getUsername(event), - includedUsers = WebhookUtils.convert(includeUsers), - excludedUsers = WebhookUtils.convert(excludeUsers) - ) - val branchFilter = BranchFilter( - pipelineId = pipelineId, - triggerOnBranchName = getBranchName(event), - includedBranches = WebhookUtils.convert(branchName), - excludedBranches = WebhookUtils.convert(excludeBranchName) - ) - return listOf(urlFilter, eventTypeFilter, userFilter, branchFilter) + return listOf(urlFilter, eventTypeFilter) } } } diff --git a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/github/GithubCreateTriggerHandler.kt b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/github/GithubCreateTriggerHandler.kt index 50258e5ac15..7886358ef25 100644 --- a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/github/GithubCreateTriggerHandler.kt +++ b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/github/GithubCreateTriggerHandler.kt @@ -27,12 +27,15 @@ package com.tencent.devops.common.webhook.service.code.handler.github +import com.tencent.devops.common.api.pojo.I18Variable import com.tencent.devops.common.pipeline.pojo.element.trigger.enums.CodeEventType import com.tencent.devops.common.webhook.annotation.CodeWebhookHandler +import com.tencent.devops.common.webhook.enums.WebhookI18nConstants import com.tencent.devops.common.webhook.pojo.code.BK_REPO_GITHUB_WEBHOOK_CREATE_REF_NAME import com.tencent.devops.common.webhook.pojo.code.BK_REPO_GITHUB_WEBHOOK_CREATE_REF_TYPE import com.tencent.devops.common.webhook.pojo.code.BK_REPO_GITHUB_WEBHOOK_CREATE_USERNAME import com.tencent.devops.common.webhook.pojo.code.WebHookParams +import com.tencent.devops.common.webhook.pojo.code.github.GithubBaseInfo import com.tencent.devops.common.webhook.pojo.code.github.GithubCreateEvent import com.tencent.devops.common.webhook.service.code.filter.WebhookFilter import com.tencent.devops.common.webhook.service.code.handler.GitHookTriggerHandler @@ -73,6 +76,29 @@ class GithubCreateTriggerHandler : GitHookTriggerHandler { return event.ref } + override fun getEventDesc(event: GithubCreateEvent): String { + val (i18Code, linkUrl) = if (event.ref_type == "tag") { + WebhookI18nConstants.GITHUB_CREATE_TAG_EVENT_DESC to + "${GithubBaseInfo.GITHUB_HOME_PAGE_URL}/${event.repository.fullName}/releases/tag/${event.ref}" + } else { + WebhookI18nConstants.GITHUB_CREATE_BRANCH_EVENT_DESC to + "${GithubBaseInfo.GITHUB_HOME_PAGE_URL}/${event.repository.fullName}/tree/${event.ref}" + } + // 事件重放 + return I18Variable( + code = i18Code, + params = listOf( + linkUrl, + getBranchName(event), + getUsername(event) + ) + ).toJsonStr() + } + + override fun getExternalId(event: GithubCreateEvent): String { + return event.repository.id.toString() + } + override fun retrieveParams( event: GithubCreateEvent, projectId: String?, diff --git a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/github/GithubIssueTriggerHandler.kt b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/github/GithubIssueTriggerHandler.kt index 4348b9717a3..4ca7f4c772a 100644 --- a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/github/GithubIssueTriggerHandler.kt +++ b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/github/GithubIssueTriggerHandler.kt @@ -27,9 +27,11 @@ package com.tencent.devops.common.webhook.service.code.handler.github +import com.tencent.devops.common.api.pojo.I18Variable import com.tencent.devops.common.pipeline.pojo.element.trigger.enums.CodeEventType import com.tencent.devops.common.pipeline.utils.PIPELINE_GIT_EVENT_URL import com.tencent.devops.common.webhook.annotation.CodeWebhookHandler +import com.tencent.devops.common.webhook.enums.WebhookI18nConstants import com.tencent.devops.common.webhook.pojo.code.BK_REPO_GIT_WEBHOOK_ISSUE_ACTION import com.tencent.devops.common.webhook.pojo.code.BK_REPO_GIT_WEBHOOK_ISSUE_DESCRIPTION import com.tencent.devops.common.webhook.pojo.code.BK_REPO_GIT_WEBHOOK_ISSUE_ID @@ -40,13 +42,14 @@ import com.tencent.devops.common.webhook.pojo.code.BK_REPO_GIT_WEBHOOK_ISSUE_TIT import com.tencent.devops.common.webhook.pojo.code.BK_REPO_GIT_WEBHOOK_ISSUE_URL import com.tencent.devops.common.webhook.pojo.code.WebHookParams import com.tencent.devops.common.webhook.pojo.code.github.GithubBaseInfo +import com.tencent.devops.common.webhook.pojo.code.github.GithubIssuesAction import com.tencent.devops.common.webhook.pojo.code.github.GithubIssuesEvent import com.tencent.devops.common.webhook.service.code.filter.ContainsFilter import com.tencent.devops.common.webhook.service.code.filter.EventTypeFilter import com.tencent.devops.common.webhook.service.code.filter.GitUrlFilter import com.tencent.devops.common.webhook.service.code.filter.WebhookFilter import com.tencent.devops.common.webhook.service.code.handler.CodeWebhookTriggerHandler -import com.tencent.devops.common.webhook.service.code.matcher.ScmWebhookMatcher +import com.tencent.devops.common.webhook.service.code.pojo.WebhookMatchResult import com.tencent.devops.common.webhook.util.WebhookUtils import com.tencent.devops.repository.pojo.Repository @@ -87,8 +90,23 @@ class GithubIssueTriggerHandler : CodeWebhookTriggerHandler { return event.issue.title } - override fun preMatch(event: GithubIssuesEvent): ScmWebhookMatcher.MatchResult { - return ScmWebhookMatcher.MatchResult(true) + override fun getExternalId(event: GithubIssuesEvent): String { + return event.repository.id.toString() + } + + override fun getEventDesc(event: GithubIssuesEvent): String { + return I18Variable( + code = getI18Code(event), + params = listOf( + buildIssuesUrl(event), + event.issue.number.toString(), + getUsername(event) + ) + ).toJsonStr() + } + + override fun preMatch(event: GithubIssuesEvent): WebhookMatchResult { + return WebhookMatchResult(true) } override fun getWebhookFilters( @@ -114,7 +132,11 @@ class GithubIssueTriggerHandler : CodeWebhookTriggerHandler { pipelineId = pipelineId, filterName = "issueAction", triggerOn = event.convertAction(), - included = WebhookUtils.convert(includeIssueAction) + included = WebhookUtils.convert(includeIssueAction), + failedReason = I18Variable( + code = WebhookI18nConstants.ISSUES_ACTION_NOT_MATCH, + params = listOf() + ).toJsonStr() ) return listOf(urlFilter, eventTypeFilter, actionFilter) } @@ -139,4 +161,16 @@ class GithubIssueTriggerHandler : CodeWebhookTriggerHandler { } return startParams } + + private fun getI18Code(event: GithubIssuesEvent) = when (event.action) { + GithubIssuesAction.OPENED.value -> WebhookI18nConstants.TGIT_ISSUE_CREATED_EVENT_DESC + GithubIssuesAction.EDITED.value -> WebhookI18nConstants.TGIT_ISSUE_UPDATED_EVENT_DESC + GithubIssuesAction.CLOSED.value -> WebhookI18nConstants.TGIT_ISSUE_CLOSED_EVENT_DESC + GithubIssuesAction.REOPENED.value -> WebhookI18nConstants.TGIT_ISSUE_REOPENED_EVENT_DESC + else -> "" + } + + private fun buildIssuesUrl(event: GithubIssuesEvent) = with(event) { + issue.htmlUrl ?: "${GithubBaseInfo.GITHUB_HOME_PAGE_URL}/${repository.fullName}/issues/${issue.number}" + } } diff --git a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/github/GithubPrTriggerHandler.kt b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/github/GithubPrTriggerHandler.kt index 6cb172e2cd8..abd224e6ea7 100644 --- a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/github/GithubPrTriggerHandler.kt +++ b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/github/GithubPrTriggerHandler.kt @@ -27,6 +27,7 @@ package com.tencent.devops.common.webhook.service.code.handler.github +import com.tencent.devops.common.api.pojo.I18Variable import com.tencent.devops.common.pipeline.pojo.element.trigger.enums.CodeEventType import com.tencent.devops.common.pipeline.utils.PIPELINE_GIT_ACTION import com.tencent.devops.common.pipeline.utils.PIPELINE_GIT_BASE_REF @@ -45,6 +46,7 @@ import com.tencent.devops.common.pipeline.utils.PIPELINE_GIT_MR_TITLE import com.tencent.devops.common.pipeline.utils.PIPELINE_GIT_MR_URL import com.tencent.devops.common.pipeline.utils.PIPELINE_GIT_REPO_URL import com.tencent.devops.common.webhook.annotation.CodeWebhookHandler +import com.tencent.devops.common.webhook.enums.WebhookI18nConstants import com.tencent.devops.common.webhook.pojo.code.BK_REPO_GIT_WEBHOOK_MR_ASSIGNEE import com.tencent.devops.common.webhook.pojo.code.BK_REPO_GIT_WEBHOOK_MR_AUTHOR import com.tencent.devops.common.webhook.pojo.code.BK_REPO_GIT_WEBHOOK_MR_CREATE_TIME @@ -78,9 +80,11 @@ import com.tencent.devops.common.webhook.pojo.code.PIPELINE_WEBHOOK_TARGET_REPO_ import com.tencent.devops.common.webhook.pojo.code.PIPELINE_WEBHOOK_TARGET_URL import com.tencent.devops.common.webhook.pojo.code.WebHookParams import com.tencent.devops.common.webhook.pojo.code.github.GithubPullRequestEvent +import com.tencent.devops.common.webhook.service.code.filter.BranchFilter +import com.tencent.devops.common.webhook.service.code.filter.UserFilter import com.tencent.devops.common.webhook.service.code.filter.WebhookFilter import com.tencent.devops.common.webhook.service.code.handler.GitHookTriggerHandler -import com.tencent.devops.common.webhook.service.code.matcher.ScmWebhookMatcher +import com.tencent.devops.common.webhook.service.code.pojo.WebhookMatchResult import com.tencent.devops.common.webhook.util.WebhookUtils import com.tencent.devops.repository.pojo.Repository import com.tencent.devops.scm.utils.code.git.GitUtils @@ -126,6 +130,22 @@ class GithubPrTriggerHandler : GitHookTriggerHandler { return event.pullRequest.title } + override fun getEventDesc(event: GithubPullRequestEvent): String { + return I18Variable( + code = WebhookI18nConstants.GITHUB_PR_EVENT_DESC, + params = listOf( + event.pullRequest.htmlUrl, + event.pullRequest.number.toString(), + getUsername(event), + event.action + ) + ).toJsonStr() + } + + override fun getExternalId(event: GithubPullRequestEvent): String { + return event.repository.id.toString() + } + override fun getEnv(event: GithubPullRequestEvent): Map { return mapOf(GITHUB_PR_NUMBER to event.number) } @@ -138,12 +158,12 @@ class GithubPrTriggerHandler : GitHookTriggerHandler { return event.pullRequest.base.repo.cloneUrl } - override fun preMatch(event: GithubPullRequestEvent): ScmWebhookMatcher.MatchResult { + override fun preMatch(event: GithubPullRequestEvent): WebhookMatchResult { if (!(event.action == "opened" || event.action == "reopened" || event.action == "synchronize")) { logger.info("Github pull request no open or update") - return ScmWebhookMatcher.MatchResult(false) + return WebhookMatchResult(false) } - return ScmWebhookMatcher.MatchResult(true) + return WebhookMatchResult(true) } override fun getEventFilters( @@ -153,7 +173,39 @@ class GithubPrTriggerHandler : GitHookTriggerHandler { repository: Repository, webHookParams: WebHookParams ): List { - return emptyList() + with(webHookParams) { + val userId = getUsername(event) + val userFilter = UserFilter( + pipelineId = pipelineId, + triggerOnUser = userId, + includedUsers = WebhookUtils.convert(includeUsers), + excludedUsers = WebhookUtils.convert(excludeUsers), + includedFailedReason = I18Variable( + code = WebhookI18nConstants.USER_NOT_MATCH, + params = listOf(getUsername(event)) + ).toJsonStr(), + excludedFailedReason = I18Variable( + code = WebhookI18nConstants.USER_IGNORED, + params = listOf(getUsername(event)) + ).toJsonStr() + ) + val targetBranch = getBranchName(event) + val targetBranchFilter = BranchFilter( + pipelineId = pipelineId, + triggerOnBranchName = targetBranch, + includedBranches = WebhookUtils.convert(branchName), + excludedBranches = WebhookUtils.convert(excludeBranchName), + includedFailedReason = I18Variable( + code = WebhookI18nConstants.TARGET_BRANCH_NOT_MATCH, + params = listOf(targetBranch) + ).toJsonStr(), + excludedFailedReason = I18Variable( + code = WebhookI18nConstants.TARGET_BRANCH_IGNORED, + params = listOf(targetBranch) + ).toJsonStr() + ) + return listOf(userFilter, targetBranchFilter) + } } override fun retrieveParams( diff --git a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/github/GithubPushTriggerHandler.kt b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/github/GithubPushTriggerHandler.kt index 78a2fbce7d6..c9b0bd43930 100644 --- a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/github/GithubPushTriggerHandler.kt +++ b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/github/GithubPushTriggerHandler.kt @@ -27,6 +27,7 @@ package com.tencent.devops.common.webhook.service.code.handler.github +import com.tencent.devops.common.api.pojo.I18Variable import com.tencent.devops.common.pipeline.pojo.element.trigger.enums.CodeEventType import com.tencent.devops.common.pipeline.utils.PIPELINE_GIT_ACTION import com.tencent.devops.common.pipeline.utils.PIPELINE_GIT_BEFORE_SHA @@ -37,6 +38,7 @@ import com.tencent.devops.common.pipeline.utils.PIPELINE_GIT_EVENT_URL import com.tencent.devops.common.pipeline.utils.PIPELINE_GIT_REF import com.tencent.devops.common.pipeline.utils.PIPELINE_GIT_REPO_URL import com.tencent.devops.common.webhook.annotation.CodeWebhookHandler +import com.tencent.devops.common.webhook.enums.WebhookI18nConstants import com.tencent.devops.common.webhook.enums.code.github.GithubPushOperationKind import com.tencent.devops.common.webhook.enums.code.tgit.TGitPushActionType import com.tencent.devops.common.webhook.pojo.code.BK_REPO_GIT_WEBHOOK_BRANCH @@ -52,10 +54,13 @@ import com.tencent.devops.common.webhook.pojo.code.WebHookParams import com.tencent.devops.common.webhook.pojo.code.git.GitCommit import com.tencent.devops.common.webhook.pojo.code.git.GitCommitAuthor import com.tencent.devops.common.webhook.pojo.code.git.GitPushEvent +import com.tencent.devops.common.webhook.pojo.code.github.GithubBaseInfo import com.tencent.devops.common.webhook.pojo.code.github.GithubPushEvent +import com.tencent.devops.common.webhook.service.code.filter.BranchFilter +import com.tencent.devops.common.webhook.service.code.filter.UserFilter import com.tencent.devops.common.webhook.service.code.filter.WebhookFilter import com.tencent.devops.common.webhook.service.code.handler.GitHookTriggerHandler -import com.tencent.devops.common.webhook.service.code.matcher.ScmWebhookMatcher +import com.tencent.devops.common.webhook.service.code.pojo.WebhookMatchResult import com.tencent.devops.common.webhook.util.WebhookUtils import com.tencent.devops.repository.pojo.Repository import com.tencent.devops.scm.utils.code.git.GitUtils @@ -101,12 +106,39 @@ class GithubPushTriggerHandler : GitHookTriggerHandler { return event.headCommit?.message ?: "" } - override fun preMatch(event: GithubPushEvent): ScmWebhookMatcher.MatchResult { + override fun getEventDesc(event: GithubPushEvent): String { + val linkUrl = if (event.headCommit != null) { + "${GithubBaseInfo.GITHUB_HOME_PAGE_URL}/${event.repository.fullName}/commit/${event.headCommit?.id}" + } else { + "${GithubBaseInfo.GITHUB_HOME_PAGE_URL}/${event.repository.fullName}/commit/${getBranchName(event)}" + } + val revision = getRevision(event) + val commitId = if (revision.isNotBlank()) { + revision.substring(0, GitPushEvent.SHORT_COMMIT_ID_LENGTH) + } else { + revision + } + return I18Variable( + code = WebhookI18nConstants.GITHUB_PUSH_EVENT_DESC, + params = listOf( + getBranchName(event), + linkUrl, + commitId, + getUsername(event) + ) + ).toJsonStr() + } + + override fun getExternalId(event: GithubPushEvent): String { + return event.repository.id.toString() + } + + override fun preMatch(event: GithubPushEvent): WebhookMatchResult { if (event.commits.isEmpty()) { logger.info("Github web hook no commit") - return ScmWebhookMatcher.MatchResult(false) + return WebhookMatchResult(false) } - return ScmWebhookMatcher.MatchResult(true) + return WebhookMatchResult(true) } override fun getEventFilters( @@ -116,7 +148,39 @@ class GithubPushTriggerHandler : GitHookTriggerHandler { repository: Repository, webHookParams: WebHookParams ): List { - return emptyList() + with(webHookParams) { + val userId = getUsername(event) + val userFilter = UserFilter( + pipelineId = pipelineId, + triggerOnUser = userId, + includedUsers = WebhookUtils.convert(includeUsers), + excludedUsers = WebhookUtils.convert(excludeUsers), + includedFailedReason = I18Variable( + code = WebhookI18nConstants.USER_NOT_MATCH, + params = listOf(userId) + ).toJsonStr(), + excludedFailedReason = I18Variable( + code = WebhookI18nConstants.USER_IGNORED, + params = listOf(userId) + ).toJsonStr() + ) + val triggerOnBranchName = getBranchName(event) + val branchFilter = BranchFilter( + pipelineId = pipelineId, + triggerOnBranchName = triggerOnBranchName, + includedBranches = WebhookUtils.convert(branchName), + excludedBranches = WebhookUtils.convert(excludeBranchName), + includedFailedReason = I18Variable( + code = WebhookI18nConstants.TARGET_BRANCH_NOT_MATCH, + params = listOf(triggerOnBranchName) + ).toJsonStr(), + excludedFailedReason = I18Variable( + code = WebhookI18nConstants.TARGET_BRANCH_IGNORED, + params = listOf(triggerOnBranchName) + ).toJsonStr() + ) + return listOf(userFilter, branchFilter) + } } override fun retrieveParams( diff --git a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/github/GithubReviewTriggerHandler.kt b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/github/GithubReviewTriggerHandler.kt index bbfc9dece7c..293b2f95f0f 100644 --- a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/github/GithubReviewTriggerHandler.kt +++ b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/github/GithubReviewTriggerHandler.kt @@ -27,8 +27,10 @@ package com.tencent.devops.common.webhook.service.code.handler.github +import com.tencent.devops.common.api.pojo.I18Variable import com.tencent.devops.common.pipeline.pojo.element.trigger.enums.CodeEventType import com.tencent.devops.common.webhook.annotation.CodeWebhookHandler +import com.tencent.devops.common.webhook.enums.WebhookI18nConstants import com.tencent.devops.common.webhook.pojo.code.BK_REPO_GIT_WEBHOOK_REVIEW_APPROVING_REVIEWERS import com.tencent.devops.common.webhook.pojo.code.BK_REPO_GIT_WEBHOOK_REVIEW_ID import com.tencent.devops.common.webhook.pojo.code.BK_REPO_GIT_WEBHOOK_REVIEW_IID @@ -48,7 +50,7 @@ import com.tencent.devops.common.webhook.service.code.filter.EventTypeFilter import com.tencent.devops.common.webhook.service.code.filter.GitUrlFilter import com.tencent.devops.common.webhook.service.code.filter.WebhookFilter import com.tencent.devops.common.webhook.service.code.handler.CodeWebhookTriggerHandler -import com.tencent.devops.common.webhook.service.code.matcher.ScmWebhookMatcher +import com.tencent.devops.common.webhook.service.code.pojo.WebhookMatchResult import com.tencent.devops.common.webhook.util.WebhookUtils import com.tencent.devops.repository.pojo.Repository import org.slf4j.LoggerFactory @@ -93,11 +95,26 @@ class GithubReviewTriggerHandler @Autowired constructor( return event.pullRequest.title } - override fun preMatch(event: GithubReviewEvent): ScmWebhookMatcher.MatchResult { + override fun getExternalId(event: GithubReviewEvent): String { + return event.repository.id.toString() + } + + override fun getEventDesc(event: GithubReviewEvent): String { + return I18Variable( + code = getI18Code(event), + params = listOf( + buildReviewUrl(event), + event.pullRequest.number.toString(), + getUsername(event) + ) + ).toJsonStr() + } + + override fun preMatch(event: GithubReviewEvent): WebhookMatchResult { // Review事件仅提交操作才触发,评审通过、拒绝、要求修改 val result = (event.action == "submitted" || event.action == "dismissed") && event.review.state != GithubReviewState.COMMENTED.value - return ScmWebhookMatcher.MatchResult(result) + return WebhookMatchResult(result) } override fun getWebhookFilters( @@ -133,7 +150,11 @@ class GithubReviewTriggerHandler @Autowired constructor( pipelineId = pipelineId, filterName = "crState", triggerOn = event.convertState(), - included = WebhookUtils.convert(includeCrState) + included = WebhookUtils.convert(includeCrState), + failedReason = I18Variable( + code = WebhookI18nConstants.REVIEW_ACTION_NOT_MATCH, + params = listOf() + ).toJsonStr() ) return listOf(urlFilter, eventTypeFilter, crStateFilter) } @@ -169,6 +190,17 @@ class GithubReviewTriggerHandler @Autowired constructor( return startParams } + private fun getI18Code(event: GithubReviewEvent) = when (event.review.state) { + GithubReviewState.APPROVED.value -> WebhookI18nConstants.TGIT_REVIEW_APPROVED_EVENT_DESC + GithubReviewState.CHANGES_REQUESTED.value -> WebhookI18nConstants.TGIT_REVIEW_CHANGE_REQUIRED_EVENT_DESC + GithubReviewState.DISMISSED.value -> WebhookI18nConstants.TGIT_REVIEW_CHANGE_DENIED_EVENT_DESC + else -> "" + } + + private fun buildReviewUrl(event: GithubReviewEvent) = with(event) { + review.htmlUrl ?: "${GithubBaseInfo.GITHUB_HOME_PAGE_URL}/${repository.fullName}/pull/${pullRequest.number}" + } + companion object { private val logger = LoggerFactory.getLogger(GithubReviewTriggerHandler::class.java) } diff --git a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/github/comment/GithubCommentTriggerHandler.kt b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/github/comment/GithubCommentTriggerHandler.kt index 400a6d1afce..b591c6cdff2 100644 --- a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/github/comment/GithubCommentTriggerHandler.kt +++ b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/github/comment/GithubCommentTriggerHandler.kt @@ -27,7 +27,9 @@ package com.tencent.devops.common.webhook.service.code.handler.github.comment +import com.tencent.devops.common.api.pojo.I18Variable import com.tencent.devops.common.pipeline.pojo.element.trigger.enums.CodeEventType +import com.tencent.devops.common.webhook.enums.WebhookI18nConstants import com.tencent.devops.common.webhook.pojo.code.BK_REPO_GIT_WEBHOOK_NOTE_AUTHOR_ID import com.tencent.devops.common.webhook.pojo.code.BK_REPO_GIT_WEBHOOK_NOTE_COMMENT import com.tencent.devops.common.webhook.pojo.code.BK_REPO_GIT_WEBHOOK_NOTE_CREATED_AT @@ -47,7 +49,7 @@ import com.tencent.devops.common.webhook.service.code.filter.GitUrlFilter import com.tencent.devops.common.webhook.service.code.filter.RegexContainFilter import com.tencent.devops.common.webhook.service.code.filter.WebhookFilter import com.tencent.devops.common.webhook.service.code.handler.CodeWebhookTriggerHandler -import com.tencent.devops.common.webhook.service.code.matcher.ScmWebhookMatcher +import com.tencent.devops.common.webhook.service.code.pojo.WebhookMatchResult import com.tencent.devops.common.webhook.util.WebhookUtils import com.tencent.devops.repository.pojo.Repository @@ -86,8 +88,23 @@ interface GithubCommentTriggerHandler : CodeWebhookTrigg return event.comment.body } - override fun preMatch(event: T): ScmWebhookMatcher.MatchResult { - return ScmWebhookMatcher.MatchResult(true) + override fun getExternalId(event: T): String { + return event.repository.id.toString() + } + + override fun getEventDesc(event: T): String { + return I18Variable( + code = WebhookI18nConstants.TGIT_NOTE_EVENT_DESC, + params = listOf( + buildCommentUrl(event), + event.comment.id.toString(), + getUsername(event) + ) + ).toJsonStr() + } + + override fun preMatch(event: T): WebhookMatchResult { + return WebhookMatchResult(true) } override fun getWebhookFilters( @@ -113,13 +130,21 @@ interface GithubCommentTriggerHandler : CodeWebhookTrigg pipelineId = pipelineId, filterName = "noteTypeAction", triggerOn = event.getCommentType(), - included = WebhookUtils.convert(includeNoteTypes) + included = WebhookUtils.convert(includeNoteTypes), + failedReason = I18Variable( + code = WebhookI18nConstants.NOTE_ACTION_NOT_MATCH, + params = listOf() + ).toJsonStr() ) val commentActionFilter = RegexContainFilter( pipelineId = pipelineId, filterName = "noteCommentAction", triggerOn = event.comment.body, - included = WebhookUtils.convert(includeNoteComment) + included = WebhookUtils.convert(includeNoteComment), + failedReason = I18Variable( + code = WebhookI18nConstants.NOTE_CONTENT_NOT_MATCH, + params = listOf() + ).toJsonStr() ) return listOf(urlFilter, eventTypeFilter, typeActionFilter, commentActionFilter) } @@ -153,4 +178,6 @@ interface GithubCommentTriggerHandler : CodeWebhookTrigg * Github 评论事件关联参数,根据具体事件类型进行填充 */ fun getCommentParam(event: T): Map + + fun buildCommentUrl(event: T): String } diff --git a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/github/comment/GithubCommitCommentTriggerHandler.kt b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/github/comment/GithubCommitCommentTriggerHandler.kt index 607358634a5..eef2f1b345c 100644 --- a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/github/comment/GithubCommitCommentTriggerHandler.kt +++ b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/github/comment/GithubCommitCommentTriggerHandler.kt @@ -31,6 +31,7 @@ import com.tencent.devops.common.pipeline.utils.PIPELINE_GIT_COMMIT_AUTHOR import com.tencent.devops.common.pipeline.utils.PIPELINE_GIT_SHA import com.tencent.devops.common.pipeline.utils.PIPELINE_GIT_SHA_SHORT import com.tencent.devops.common.webhook.annotation.CodeWebhookHandler +import com.tencent.devops.common.webhook.pojo.code.github.GithubBaseInfo import com.tencent.devops.common.webhook.pojo.code.github.GithubCommitCommentEvent @CodeWebhookHandler @@ -53,4 +54,16 @@ class GithubCommitCommentTriggerHandler : GithubCommentTriggerHandler P4ChangeEvent.CHANGE_COMMIT + CodeEventType.CHANGE_SUBMIT.name -> P4ChangeEvent.CHANGE_SUBMIT + CodeEventType.CHANGE_CONTENT.name -> P4ChangeEvent.CHANGE_CONTENT + else -> event.eventType + } } diff --git a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/p4/P4ShelveTriggerHandler.kt b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/p4/P4ShelveTriggerHandler.kt index 569fe5f88b4..d98c126bc07 100644 --- a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/p4/P4ShelveTriggerHandler.kt +++ b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/p4/P4ShelveTriggerHandler.kt @@ -27,10 +27,12 @@ package com.tencent.devops.common.webhook.service.code.handler.p4 +import com.tencent.devops.common.api.pojo.I18Variable import com.tencent.devops.common.client.Client import com.tencent.devops.common.pipeline.pojo.element.trigger.enums.CodeEventType import com.tencent.devops.common.pipeline.pojo.element.trigger.enums.PathFilterType import com.tencent.devops.common.webhook.annotation.CodeWebhookHandler +import com.tencent.devops.common.webhook.enums.WebhookI18nConstants import com.tencent.devops.common.webhook.pojo.code.BK_REPO_P4_WEBHOOK_CHANGE import com.tencent.devops.common.webhook.pojo.code.PathFilterConfig import com.tencent.devops.common.webhook.pojo.code.WebHookParams @@ -83,6 +85,21 @@ class P4ShelveTriggerHandler( override fun getMessage(event: P4ShelveEvent) = event.description + override fun getEventDesc(event: P4ShelveEvent): String { + return I18Variable( + code = WebhookI18nConstants.P4_EVENT_DESC, + params = listOf( + getRevision(event), + getUsername(event), + getFormatEventType(event) + ) + ).toJsonStr() + } + + override fun getExternalId(event: P4ShelveEvent): String { + return event.p4Port + } + override fun getWebhookFilters( event: P4ShelveEvent, projectId: String, @@ -145,7 +162,15 @@ class P4ShelveTriggerHandler( triggerOnPath = changeFiles, includedPaths = WebhookUtils.convert(includePaths), excludedPaths = WebhookUtils.convert(excludePaths), - caseSensitive = caseSensitive + caseSensitive = caseSensitive, + includedFailedReason = I18Variable( + code = WebhookI18nConstants.PATH_NOT_MATCH, + params = listOf() + ).toJsonStr(), + excludedFailedReason = I18Variable( + code = WebhookI18nConstants.PATH_IGNORED, + params = listOf() + ).toJsonStr() ) ).doFilter(response) } @@ -164,4 +189,11 @@ class P4ShelveTriggerHandler( startParams[PIPELINE_BUILD_MSG] = event.description ?: P4ShelveEvent.DEFAULT_SHELVE_DESCRIPTION return startParams } + + private fun getFormatEventType(event: P4ShelveEvent) = when (event.eventType) { + CodeEventType.SHELVE_COMMIT.name -> P4ShelveEvent.SHELVE_COMMIT + CodeEventType.SHELVE_SUBMIT.name -> P4ShelveEvent.SHELVE_SUBMIT + CodeEventType.SHELVE_DELETE.name -> P4ShelveEvent.SHELVE_DELETE + else -> event.eventType + } } diff --git a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/svn/SvnCommitTriggerHandler.kt b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/svn/SvnCommitTriggerHandler.kt index 7834389cb22..c13f1b29601 100644 --- a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/svn/SvnCommitTriggerHandler.kt +++ b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/svn/SvnCommitTriggerHandler.kt @@ -27,9 +27,11 @@ package com.tencent.devops.common.webhook.service.code.handler.svn +import com.tencent.devops.common.api.pojo.I18Variable import com.tencent.devops.common.pipeline.pojo.element.trigger.enums.CodeEventType import com.tencent.devops.common.pipeline.pojo.element.trigger.enums.PathFilterType import com.tencent.devops.common.webhook.annotation.CodeWebhookHandler +import com.tencent.devops.common.webhook.enums.WebhookI18nConstants import com.tencent.devops.common.webhook.pojo.code.BK_REPO_SVN_WEBHOOK_COMMIT_TIME import com.tencent.devops.common.webhook.pojo.code.BK_REPO_SVN_WEBHOOK_REVERSION import com.tencent.devops.common.webhook.pojo.code.BK_REPO_SVN_WEBHOOK_USERNAME @@ -79,6 +81,20 @@ class SvnCommitTriggerHandler : CodeWebhookTriggerHandler { return event.log } + override fun getEventDesc(event: SvnCommitEvent): String { + return I18Variable( + code = WebhookI18nConstants.SVN_COMMIT_EVENT_DESC, + params = listOf( + getRevision(event), + getUsername(event) + ) + ).toJsonStr() + } + + override fun getExternalId(event: SvnCommitEvent): String { + return event.rep_name + } + override fun getWebhookFilters( event: SvnCommitEvent, projectId: String, @@ -92,11 +108,20 @@ class SvnCommitTriggerHandler : CodeWebhookTriggerHandler { projectName = repository.projectName, triggerOnProjectName = event.rep_name ) + val userId = getUsername(event) val userFilter = UserFilter( pipelineId = pipelineId, - triggerOnUser = getUsername(event), + triggerOnUser = userId, includedUsers = WebhookUtils.convert(includeUsers), - excludedUsers = WebhookUtils.convert(excludeUsers) + excludedUsers = WebhookUtils.convert(excludeUsers), + includedFailedReason = I18Variable( + code = WebhookI18nConstants.USER_NOT_MATCH, + params = listOf(userId) + ).toJsonStr(), + excludedFailedReason = I18Variable( + code = WebhookI18nConstants.USER_IGNORED, + params = listOf(userId) + ).toJsonStr() ) val projectRelativePath = WebhookUtils.getRelativePath(repository.url) val pathFilter = PathFilterFactory.newPathFilter( @@ -110,7 +135,15 @@ class SvnCommitTriggerHandler : CodeWebhookTriggerHandler { relativeSubPath = path ) }, - includedPaths = getIncludePaths(projectRelativePath) + includedPaths = getIncludePaths(projectRelativePath), + includedFailedReason = I18Variable( + code = WebhookI18nConstants.PATH_NOT_MATCH, + params = listOf() + ).toJsonStr(), + excludedFailedReason = I18Variable( + code = WebhookI18nConstants.PATH_IGNORED, + params = listOf() + ).toJsonStr() ) ) return listOf(projectNameFilter, userFilter, pathFilter) diff --git a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/tgit/TGitIssueTriggerHandler.kt b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/tgit/TGitIssueTriggerHandler.kt index 3107925555c..47a23365f96 100644 --- a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/tgit/TGitIssueTriggerHandler.kt +++ b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/tgit/TGitIssueTriggerHandler.kt @@ -27,6 +27,7 @@ package com.tencent.devops.common.webhook.service.code.handler.tgit +import com.tencent.devops.common.api.pojo.I18Variable import com.tencent.devops.common.pipeline.pojo.element.trigger.enums.CodeEventType import com.tencent.devops.common.pipeline.utils.PIPELINE_GIT_COMMIT_AUTHOR import com.tencent.devops.common.pipeline.utils.PIPELINE_GIT_EVENT @@ -36,6 +37,7 @@ import com.tencent.devops.common.pipeline.utils.PIPELINE_GIT_REPO_URL import com.tencent.devops.common.pipeline.utils.PIPELINE_GIT_SHA import com.tencent.devops.common.pipeline.utils.PIPELINE_GIT_SHA_SHORT import com.tencent.devops.common.webhook.annotation.CodeWebhookHandler +import com.tencent.devops.common.webhook.enums.WebhookI18nConstants import com.tencent.devops.common.webhook.pojo.code.BK_REPO_GIT_WEBHOOK_ISSUE_ACTION import com.tencent.devops.common.webhook.pojo.code.BK_REPO_GIT_WEBHOOK_ISSUE_DESCRIPTION import com.tencent.devops.common.webhook.pojo.code.BK_REPO_GIT_WEBHOOK_ISSUE_ID @@ -53,7 +55,7 @@ import com.tencent.devops.common.webhook.service.code.filter.ContainsFilter import com.tencent.devops.common.webhook.service.code.filter.EventTypeFilter import com.tencent.devops.common.webhook.service.code.filter.GitUrlFilter import com.tencent.devops.common.webhook.service.code.filter.WebhookFilter -import com.tencent.devops.common.webhook.service.code.handler.CodeWebhookTriggerHandler +import com.tencent.devops.common.webhook.service.code.handler.GitHookTriggerHandler import com.tencent.devops.common.webhook.util.WebhookUtils import com.tencent.devops.repository.pojo.Repository import com.tencent.devops.scm.utils.code.git.GitUtils @@ -61,7 +63,7 @@ import com.tencent.devops.scm.utils.code.git.GitUtils @CodeWebhookHandler class TGitIssueTriggerHandler( private val eventCacheService: EventCacheService -) : CodeWebhookTriggerHandler { +) : GitHookTriggerHandler { override fun eventClass(): Class { return GitIssueEvent::class.java @@ -114,7 +116,11 @@ class TGitIssueTriggerHandler( pipelineId = pipelineId, filterName = "issueAction", triggerOn = event.objectAttributes.action ?: "", - included = WebhookUtils.convert(includeIssueAction) + included = WebhookUtils.convert(includeIssueAction), + failedReason = I18Variable( + code = WebhookI18nConstants.ISSUES_ACTION_NOT_MATCH, + params = listOf() + ).toJsonStr() ) return listOf(urlFilter, eventTypeFilter, actionFilter) } @@ -124,6 +130,49 @@ class TGitIssueTriggerHandler( return event.objectAttributes.title } + override fun getEventDesc(event: GitIssueEvent): String { + return I18Variable( + code = getI18Code(event), + params = listOf( + "${event.objectAttributes.url}", + event.objectAttributes.iid, + getUsername(event) + ) + ).toJsonStr() + } + + override fun getExternalId(event: GitIssueEvent): String { + return event.objectAttributes.projectId.toString() + } + + override fun getAction(event: GitIssueEvent): String? { + return event.objectAttributes.action + } + + override fun getEventFilters( + event: GitIssueEvent, + projectId: String, + pipelineId: String, + repository: Repository, + webHookParams: WebHookParams + ): List { + val actionFilter = ContainsFilter( + pipelineId = pipelineId, + filterName = "issueAction", + triggerOn = event.objectAttributes.action ?: "", + included = WebhookUtils.convert(webHookParams.includeIssueAction), + failedReason = I18Variable( + code = WebhookI18nConstants.ISSUES_ACTION_NOT_MATCH, + params = listOf( + "${event.objectAttributes.url}", + event.objectAttributes.iid, + getUsername(event) + ) + ).toJsonStr() + ) + return listOf(actionFilter) + } + override fun retrieveParams(event: GitIssueEvent, projectId: String?, repository: Repository?): Map { val startParams = mutableMapOf() with(event.objectAttributes) { @@ -154,4 +203,12 @@ class TGitIssueTriggerHandler( startParams[PIPELINE_GIT_EVENT_URL] = event.objectAttributes.url ?: "" return startParams } + + private fun getI18Code(event: GitIssueEvent) = when (getAction(event)) { + GitIssueEvent.ACTION_CREATED -> WebhookI18nConstants.TGIT_ISSUE_CREATED_EVENT_DESC + GitIssueEvent.ACTION_UPDATED -> WebhookI18nConstants.TGIT_ISSUE_UPDATED_EVENT_DESC + GitIssueEvent.ACTION_CLOSED -> WebhookI18nConstants.TGIT_ISSUE_CLOSED_EVENT_DESC + GitIssueEvent.ACTION_REOPENED -> WebhookI18nConstants.TGIT_ISSUE_REOPENED_EVENT_DESC + else -> "" + } } diff --git a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/tgit/TGitMrTriggerHandler.kt b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/tgit/TGitMrTriggerHandler.kt index 27bd066a950..81fb646970e 100644 --- a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/tgit/TGitMrTriggerHandler.kt +++ b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/tgit/TGitMrTriggerHandler.kt @@ -28,6 +28,7 @@ package com.tencent.devops.common.webhook.service.code.handler.tgit import com.tencent.devops.common.api.enums.ScmType +import com.tencent.devops.common.api.pojo.I18Variable import com.tencent.devops.common.api.util.DateTimeUtil import com.tencent.devops.common.pipeline.pojo.element.trigger.enums.CodeEventType import com.tencent.devops.common.pipeline.utils.PIPELINE_GIT_ACTION @@ -47,6 +48,7 @@ import com.tencent.devops.common.pipeline.utils.PIPELINE_GIT_MR_TITLE import com.tencent.devops.common.pipeline.utils.PIPELINE_GIT_MR_URL import com.tencent.devops.common.pipeline.utils.PIPELINE_GIT_REPO_URL import com.tencent.devops.common.webhook.annotation.CodeWebhookHandler +import com.tencent.devops.common.webhook.enums.WebhookI18nConstants import com.tencent.devops.common.webhook.enums.code.tgit.TGitMrEventAction import com.tencent.devops.common.webhook.pojo.code.BK_REPO_GIT_MANUAL_UNLOCK import com.tencent.devops.common.webhook.pojo.code.BK_REPO_GIT_WEBHOOK_MR_LAST_COMMIT @@ -78,10 +80,11 @@ import com.tencent.devops.common.webhook.service.code.filter.ContainsFilter import com.tencent.devops.common.webhook.service.code.filter.PathFilterFactory import com.tencent.devops.common.webhook.service.code.filter.SkipCiFilter import com.tencent.devops.common.webhook.service.code.filter.ThirdFilter +import com.tencent.devops.common.webhook.service.code.filter.UserFilter import com.tencent.devops.common.webhook.service.code.filter.WebhookFilter import com.tencent.devops.common.webhook.service.code.filter.WebhookFilterResponse import com.tencent.devops.common.webhook.service.code.handler.GitHookTriggerHandler -import com.tencent.devops.common.webhook.service.code.matcher.ScmWebhookMatcher +import com.tencent.devops.common.webhook.service.code.pojo.WebhookMatchResult import com.tencent.devops.common.webhook.util.WebhookUtils import com.tencent.devops.common.webhook.util.WebhookUtils.convert import com.tencent.devops.common.webhook.util.WebhookUtils.getBranch @@ -157,6 +160,21 @@ class TGitMrTriggerHandler( return event.object_attributes.id } + override fun getEventDesc(event: GitMergeRequestEvent): String { + return I18Variable( + code = getI18Code(event), + params = listOf( + "${event.object_attributes.url}", + event.object_attributes.iid.toString(), + getUsername(event) + ) + ).toJsonStr() + } + + override fun getExternalId(event: GitMergeRequestEvent): String { + return event.object_attributes.target_project_id.toString() + } + override fun getEnv(event: GitMergeRequestEvent): Map { return mapOf( GIT_MR_NUMBER to event.object_attributes.iid, @@ -164,7 +182,7 @@ class TGitMrTriggerHandler( ) } - override fun preMatch(event: GitMergeRequestEvent): ScmWebhookMatcher.MatchResult { + override fun preMatch(event: GitMergeRequestEvent): WebhookMatchResult { if (event.object_attributes.action == "close" || ( event.object_attributes.action == "update" && @@ -172,9 +190,9 @@ class TGitMrTriggerHandler( ) ) { logger.info("Git web hook is ${event.object_attributes.action} merge request") - return ScmWebhookMatcher.MatchResult(false) + return WebhookMatchResult(false) } - return ScmWebhookMatcher.MatchResult(true) + return WebhookMatchResult(true) } override fun getEventFilters( @@ -185,11 +203,50 @@ class TGitMrTriggerHandler( webHookParams: WebHookParams ): List { with(webHookParams) { + val userId = getUsername(event) + val userFilter = UserFilter( + pipelineId = pipelineId, + triggerOnUser = getUsername(event), + includedUsers = convert(includeUsers), + excludedUsers = convert(excludeUsers), + includedFailedReason = I18Variable( + code = WebhookI18nConstants.USER_NOT_MATCH, + params = listOf(userId) + ).toJsonStr(), + excludedFailedReason = I18Variable( + code = WebhookI18nConstants.USER_IGNORED, + params = listOf(userId) + ).toJsonStr() + ) + val targetBranch = getBranchName(event) + val targetBranchFilter = BranchFilter( + pipelineId = pipelineId, + triggerOnBranchName = targetBranch, + includedBranches = convert(branchName), + excludedBranches = convert(excludeBranchName), + includedFailedReason = I18Variable( + code = WebhookI18nConstants.TARGET_BRANCH_NOT_MATCH, + params = listOf(targetBranch) + ).toJsonStr(), + excludedFailedReason = I18Variable( + code = WebhookI18nConstants.TARGET_BRANCH_IGNORED, + params = listOf(targetBranch) + ).toJsonStr() + ) + val sourceBranch = getBranch(event.object_attributes.source_branch) val sourceBranchFilter = BranchFilter( pipelineId = pipelineId, - triggerOnBranchName = getBranch(event.object_attributes.source_branch), + triggerOnBranchName = sourceBranch, includedBranches = convert(includeSourceBranchName), - excludedBranches = convert(excludeSourceBranchName) + excludedBranches = convert(excludeSourceBranchName), + includedFailedReason = I18Variable( + code = WebhookI18nConstants.SOURCE_BRANCH_NOT_MATCH, + params = listOf(sourceBranch) + ).toJsonStr(), + excludedFailedReason = I18Variable( + code = WebhookI18nConstants.SOURCE_BRANCH_IGNORED, + params = listOf(sourceBranch) + ).toJsonStr() ) val skipCiFilter = SkipCiFilter( pipelineId = pipelineId, @@ -224,7 +281,15 @@ class TGitMrTriggerHandler( pipelineId = pipelineId, triggerOnPath = changeFiles, includedPaths = convert(includePaths), - excludedPaths = convert(excludePaths) + excludedPaths = convert(excludePaths), + includedFailedReason = I18Variable( + code = WebhookI18nConstants.PATH_NOT_MATCH, + params = listOf() + ).toJsonStr(), + excludedFailedReason = I18Variable( + code = WebhookI18nConstants.PATH_IGNORED, + params = listOf() + ).toJsonStr() ) ).doFilter(response) } @@ -246,7 +311,11 @@ class TGitMrTriggerHandler( gitScmService = gitScmService, callbackCircuitBreakerRegistry = callbackCircuitBreakerRegistry ) - return listOf(sourceBranchFilter, skipCiFilter, pathFilter, commitMessageFilter, actionFilter, thirdFilter) + return listOf( + userFilter, targetBranchFilter, + sourceBranchFilter, skipCiFilter, pathFilter, + commitMessageFilter, actionFilter, thirdFilter + ) } } @@ -383,4 +452,37 @@ class TGitMrTriggerHandler( mrRequestId = mrRequestId ) } + + private fun getI18Code(event: GitMergeRequestEvent) = with(getAction(event)) { + when { + this == GitMergeRequestEvent.ACTION_CLOSED -> { + WebhookI18nConstants.TGIT_MR_CLOSED_EVENT_DESC + } + + this == GitMergeRequestEvent.ACTION_CREATED -> { + WebhookI18nConstants.TGIT_MR_CREATED_EVENT_DESC + } + // MR源分支提交更新 + (this == GitMergeRequestEvent.ACTION_UPDATED && + event.object_attributes.extension_action == "push-update") -> { + WebhookI18nConstants.TGIT_MR_PUSH_UPDATED_EVENT_DESC + } + // MR更新 + this == GitMergeRequestEvent.ACTION_UPDATED -> { + WebhookI18nConstants.TGIT_MR_UPDATED_EVENT_DESC + } + + this == GitMergeRequestEvent.ACTION_REOPENED -> { + WebhookI18nConstants.TGIT_MR_REOPENED_EVENT_DESC + } + + this == GitMergeRequestEvent.ACTION_MERGED -> { + WebhookI18nConstants.TGIT_MR_MERGED_EVENT_DESC + } + + else -> { + "" + } + } + } } diff --git a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/tgit/TGitNoteTriggerHandler.kt b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/tgit/TGitNoteTriggerHandler.kt index 681576d6844..5c48ffe3430 100644 --- a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/tgit/TGitNoteTriggerHandler.kt +++ b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/tgit/TGitNoteTriggerHandler.kt @@ -27,6 +27,7 @@ package com.tencent.devops.common.webhook.service.code.handler.tgit +import com.tencent.devops.common.api.pojo.I18Variable import com.tencent.devops.common.pipeline.pojo.element.trigger.enums.CodeEventType import com.tencent.devops.common.pipeline.utils.PIPELINE_GIT_BEFORE_SHA import com.tencent.devops.common.pipeline.utils.PIPELINE_GIT_BEFORE_SHA_SHORT @@ -40,6 +41,7 @@ import com.tencent.devops.common.pipeline.utils.PIPELINE_GIT_REPO_URL import com.tencent.devops.common.pipeline.utils.PIPELINE_GIT_SHA import com.tencent.devops.common.pipeline.utils.PIPELINE_GIT_SHA_SHORT import com.tencent.devops.common.webhook.annotation.CodeWebhookHandler +import com.tencent.devops.common.webhook.enums.WebhookI18nConstants import com.tencent.devops.common.webhook.pojo.code.BK_REPO_GIT_WEBHOOK_ISSUE_DESCRIPTION import com.tencent.devops.common.webhook.pojo.code.BK_REPO_GIT_WEBHOOK_ISSUE_ID import com.tencent.devops.common.webhook.pojo.code.BK_REPO_GIT_WEBHOOK_ISSUE_IID @@ -138,13 +140,21 @@ class TGitNoteTriggerHandler( pipelineId = pipelineId, filterName = "noteTypeAction", triggerOn = event.objectAttributes.noteableType, - included = WebhookUtils.convert(includeNoteTypes) + included = WebhookUtils.convert(includeNoteTypes), + failedReason = I18Variable( + code = WebhookI18nConstants.NOTE_ACTION_NOT_MATCH, + params = listOf() + ).toJsonStr() ) val commentActionFilter = RegexContainFilter( pipelineId = pipelineId, filterName = "noteCommentAction", triggerOn = event.objectAttributes.note, - included = WebhookUtils.convert(includeNoteComment) + included = WebhookUtils.convert(includeNoteComment), + failedReason = I18Variable( + code = WebhookI18nConstants.NOTE_CONTENT_NOT_MATCH, + params = listOf() + ).toJsonStr() ) return listOf(urlFilter, eventTypeFilter, typeActionFilter, commentActionFilter) } @@ -154,6 +164,21 @@ class TGitNoteTriggerHandler( return event.objectAttributes.note } + override fun getEventDesc(event: GitNoteEvent): String { + return I18Variable( + code = WebhookI18nConstants.TGIT_NOTE_EVENT_DESC, + params = listOf( + event.objectAttributes.url, + event.objectAttributes.id.toString(), + getUsername(event) + ) + ).toJsonStr() + } + + override fun getExternalId(event: GitNoteEvent): String { + return event.objectAttributes.projectId.toString() + } + @SuppressWarnings("ComplexMethod", "LongMethod") override fun retrieveParams(event: GitNoteEvent, projectId: String?, repository: Repository?): Map { val startParams = mutableMapOf() diff --git a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/tgit/TGitPushTriggerHandler.kt b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/tgit/TGitPushTriggerHandler.kt index fa3c0111dae..bb5999fb04b 100644 --- a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/tgit/TGitPushTriggerHandler.kt +++ b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/tgit/TGitPushTriggerHandler.kt @@ -28,6 +28,7 @@ package com.tencent.devops.common.webhook.service.code.handler.tgit import com.tencent.devops.common.api.enums.ScmType +import com.tencent.devops.common.api.pojo.I18Variable import com.tencent.devops.common.api.util.DateTimeUtil import com.tencent.devops.common.pipeline.pojo.element.trigger.enums.CodeEventType import com.tencent.devops.common.pipeline.utils.PIPELINE_GIT_ACTION @@ -39,6 +40,8 @@ import com.tencent.devops.common.pipeline.utils.PIPELINE_GIT_EVENT_URL import com.tencent.devops.common.pipeline.utils.PIPELINE_GIT_REF import com.tencent.devops.common.pipeline.utils.PIPELINE_GIT_REPO_URL import com.tencent.devops.common.webhook.annotation.CodeWebhookHandler +import com.tencent.devops.common.webhook.enums.WebhookI18nConstants +import com.tencent.devops.common.webhook.enums.WebhookI18nConstants.TGIT_PUSH_EVENT_DESC import com.tencent.devops.common.webhook.enums.code.tgit.TGitPushActionType import com.tencent.devops.common.webhook.enums.code.tgit.TGitPushOperationKind import com.tencent.devops.common.webhook.pojo.code.BK_REPO_GIT_WEBHOOK_BRANCH @@ -56,14 +59,16 @@ import com.tencent.devops.common.webhook.pojo.code.git.GitPushEvent import com.tencent.devops.common.webhook.pojo.code.git.isDeleteBranch import com.tencent.devops.common.webhook.service.code.EventCacheService import com.tencent.devops.common.webhook.service.code.GitScmService +import com.tencent.devops.common.webhook.service.code.filter.BranchFilter import com.tencent.devops.common.webhook.service.code.filter.PathFilterFactory import com.tencent.devops.common.webhook.service.code.filter.PushKindFilter import com.tencent.devops.common.webhook.service.code.filter.SkipCiFilter import com.tencent.devops.common.webhook.service.code.filter.ThirdFilter +import com.tencent.devops.common.webhook.service.code.filter.UserFilter import com.tencent.devops.common.webhook.service.code.filter.WebhookFilter import com.tencent.devops.common.webhook.service.code.filter.WebhookFilterResponse import com.tencent.devops.common.webhook.service.code.handler.GitHookTriggerHandler -import com.tencent.devops.common.webhook.service.code.matcher.ScmWebhookMatcher +import com.tencent.devops.common.webhook.service.code.pojo.WebhookMatchResult import com.tencent.devops.common.webhook.util.WebhookUtils import com.tencent.devops.common.webhook.util.WebhookUtils.convert import com.tencent.devops.process.engine.service.code.filter.CommitMessageFilter @@ -125,7 +130,23 @@ class TGitPushTriggerHandler( } } - override fun preMatch(event: GitPushEvent): ScmWebhookMatcher.MatchResult { + override fun getEventDesc(event: GitPushEvent): String { + return I18Variable( + code = TGIT_PUSH_EVENT_DESC, + params = listOf( + getBranchName(event), + "${event.repository.homepage}/commit/${event.checkout_sha}", + "${event.checkout_sha}".substring(0, GitPushEvent.SHORT_COMMIT_ID_LENGTH), + getUsername(event) + ) + ).toJsonStr() + } + + override fun getExternalId(event: GitPushEvent): String { + return event.project_id.toString() + } + + override fun preMatch(event: GitPushEvent): WebhookMatchResult { val isMatch = when { event.total_commits_count <= 0 -> { logger.info("Git web hook no commit(${event.total_commits_count})") @@ -138,7 +159,7 @@ class TGitPushTriggerHandler( else -> true } - return ScmWebhookMatcher.MatchResult(isMatch) + return WebhookMatchResult(isMatch) } override fun getEventFilters( @@ -149,6 +170,36 @@ class TGitPushTriggerHandler( webHookParams: WebHookParams ): List { with(webHookParams) { + val userId = getUsername(event) + val userFilter = UserFilter( + pipelineId = pipelineId, + triggerOnUser = userId, + includedUsers = convert(includeUsers), + excludedUsers = convert(excludeUsers), + includedFailedReason = I18Variable( + code = WebhookI18nConstants.USER_NOT_MATCH, + params = listOf(userId) + ).toJsonStr(), + excludedFailedReason = I18Variable( + code = WebhookI18nConstants.USER_IGNORED, + params = listOf(userId) + ).toJsonStr() + ) + val triggerOnBranchName = getBranchName(event) + val branchFilter = BranchFilter( + pipelineId = pipelineId, + triggerOnBranchName = triggerOnBranchName, + includedBranches = convert(branchName), + excludedBranches = convert(excludeBranchName), + includedFailedReason = I18Variable( + code = WebhookI18nConstants.SOURCE_BRANCH_NOT_MATCH, + params = listOf(triggerOnBranchName) + ).toJsonStr(), + excludedFailedReason = I18Variable( + code = WebhookI18nConstants.SOURCE_BRANCH_IGNORED, + params = listOf(triggerOnBranchName) + ).toJsonStr() + ) val skipCiFilter = SkipCiFilter( pipelineId = pipelineId, triggerOnMessage = event.commits?.get(0)?.message ?: "" @@ -183,7 +234,15 @@ class TGitPushTriggerHandler( pipelineId = pipelineId, triggerOnPath = eventPaths.toList(), includedPaths = convert(includePaths), - excludedPaths = convert(excludePaths) + excludedPaths = convert(excludePaths), + includedFailedReason = I18Variable( + code = WebhookI18nConstants.PATH_NOT_MATCH, + params = listOf() + ).toJsonStr(), + excludedFailedReason = I18Variable( + code = WebhookI18nConstants.PATH_IGNORED, + params = listOf() + ).toJsonStr() ) ).doFilter(response) } @@ -204,7 +263,10 @@ class TGitPushTriggerHandler( gitScmService = gitScmService, callbackCircuitBreakerRegistry = callbackCircuitBreakerRegistry ) - return listOf(skipCiFilter, pathFilter, commitMessageFilter, pushKindFilter, thirdFilter) + return listOf( + userFilter, branchFilter, skipCiFilter, + pathFilter, commitMessageFilter, pushKindFilter, thirdFilter + ) } } diff --git a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/tgit/TGitReviewTriggerHandler.kt b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/tgit/TGitReviewTriggerHandler.kt index 0983a4845f3..6ae82d59615 100644 --- a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/tgit/TGitReviewTriggerHandler.kt +++ b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/tgit/TGitReviewTriggerHandler.kt @@ -27,6 +27,7 @@ package com.tencent.devops.common.webhook.service.code.handler.tgit +import com.tencent.devops.common.api.pojo.I18Variable import com.tencent.devops.common.pipeline.pojo.element.trigger.enums.CodeEventType import com.tencent.devops.common.pipeline.utils.PIPELINE_GIT_COMMIT_AUTHOR import com.tencent.devops.common.pipeline.utils.PIPELINE_GIT_EVENT @@ -36,6 +37,7 @@ import com.tencent.devops.common.pipeline.utils.PIPELINE_GIT_REPO_URL import com.tencent.devops.common.pipeline.utils.PIPELINE_GIT_SHA import com.tencent.devops.common.pipeline.utils.PIPELINE_GIT_SHA_SHORT import com.tencent.devops.common.webhook.annotation.CodeWebhookHandler +import com.tencent.devops.common.webhook.enums.WebhookI18nConstants import com.tencent.devops.common.webhook.pojo.code.BK_REPO_GIT_WEBHOOK_REVIEW_APPROVED_REVIEWERS import com.tencent.devops.common.webhook.pojo.code.BK_REPO_GIT_WEBHOOK_REVIEW_APPROVING_REVIEWERS import com.tencent.devops.common.webhook.pojo.code.BK_REPO_GIT_WEBHOOK_REVIEW_ID @@ -96,6 +98,27 @@ class TGitReviewTriggerHandler( return "" } + override fun getEventDesc(event: GitReviewEvent): String { + // 评审状态 to 事件人 + val (state, eventUser) = if (event.reviewer != null) { + event.reviewer!!.state to event.reviewer!!.reviewer.name + } else { + event.state to getUsername(event) + } + return I18Variable( + code = getI18Code(state), + params = listOf( + "${event.repository.homepage}/reviews/${event.iid}", + event.iid, + eventUser + ) + ).toJsonStr() + } + + override fun getExternalId(event: GitReviewEvent): String { + return event.projectId.toString() + } + @SuppressWarnings("ComplexMethod", "ComplexCondition") override fun retrieveParams(event: GitReviewEvent, projectId: String?, repository: Repository?): Map { val startParams = mutableMapOf() @@ -206,7 +229,11 @@ class TGitReviewTriggerHandler( pipelineId = pipelineId, filterName = "crState", triggerOn = event.state, - included = WebhookUtils.convert(includeCrState) + included = WebhookUtils.convert(includeCrState), + failedReason = I18Variable( + code = WebhookI18nConstants.REVIEW_ACTION_NOT_MATCH, + params = listOf() + ).toJsonStr() ) val crTypeFilter = ContainsFilter( pipelineId = pipelineId, @@ -217,4 +244,13 @@ class TGitReviewTriggerHandler( return listOf(urlFilter, eventTypeFilter, crStateFilter, crTypeFilter) } } + + private fun getI18Code(state: String) = when (state) { + GitReviewEvent.ACTION_APPROVED -> WebhookI18nConstants.TGIT_REVIEW_APPROVED_EVENT_DESC + GitReviewEvent.ACTION_APPROVING -> WebhookI18nConstants.TGIT_REVIEW_APPROVING_EVENT_DESC + GitReviewEvent.ACTION_CHANGE_DENIED -> WebhookI18nConstants.TGIT_REVIEW_CHANGE_DENIED_EVENT_DESC + GitReviewEvent.ACTION_CHANGE_REQUIRED -> WebhookI18nConstants.TGIT_REVIEW_CHANGE_REQUIRED_EVENT_DESC + GitReviewEvent.ACTION_EMPTY -> WebhookI18nConstants.TGIT_REVIEW_CREATED_EVENT_DESC + else -> "" + } } diff --git a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/tgit/TGitTagPushTriggerHandler.kt b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/tgit/TGitTagPushTriggerHandler.kt index 81202067f08..2a4cc2d5096 100644 --- a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/tgit/TGitTagPushTriggerHandler.kt +++ b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/handler/tgit/TGitTagPushTriggerHandler.kt @@ -27,6 +27,7 @@ package com.tencent.devops.common.webhook.service.code.handler.tgit +import com.tencent.devops.common.api.pojo.I18Variable import com.tencent.devops.common.pipeline.pojo.element.trigger.enums.CodeEventType import com.tencent.devops.common.pipeline.utils.PIPELINE_GIT_BEFORE_SHA import com.tencent.devops.common.pipeline.utils.PIPELINE_GIT_BEFORE_SHA_SHORT @@ -38,6 +39,7 @@ import com.tencent.devops.common.pipeline.utils.PIPELINE_GIT_REPO_URL import com.tencent.devops.common.pipeline.utils.PIPELINE_GIT_TAG_FROM import com.tencent.devops.common.pipeline.utils.PIPELINE_GIT_TAG_MESSAGE import com.tencent.devops.common.webhook.annotation.CodeWebhookHandler +import com.tencent.devops.common.webhook.enums.WebhookI18nConstants import com.tencent.devops.common.webhook.pojo.code.BK_REPO_GIT_WEBHOOK_PUSH_TOTAL_COMMIT import com.tencent.devops.common.webhook.pojo.code.BK_REPO_GIT_WEBHOOK_TAG_CREATE_FROM import com.tencent.devops.common.webhook.pojo.code.BK_REPO_GIT_WEBHOOK_TAG_NAME @@ -97,6 +99,31 @@ class TGitTagPushTriggerHandler : CodeWebhookTriggerHandler { return event.ref.replace("refs/tags/", "") } + override fun getEventDesc(event: GitTagPushEvent): String { + val createFrom = when { + event.create_from.isNullOrBlank() || event.checkout_sha == event.create_from -> { + GitUtils.getShortSha(event.checkout_sha) + } + + else -> { + event.create_from + } + } + return I18Variable( + code = WebhookI18nConstants.TGIT_TAG_PUSH_EVENT_DESC, + params = listOf( + "$createFrom", + "${event.repository.homepage}/-/tags/${getBranchName(event)}", + getBranchName(event), + getUsername(event) + ) + ).toJsonStr() + } + + override fun getExternalId(event: GitTagPushEvent): String { + return event.project_id.toString() + } + override fun retrieveParams( event: GitTagPushEvent, projectId: String?, @@ -150,23 +177,47 @@ class TGitTagPushTriggerHandler : CodeWebhookTriggerHandler { triggerOnEventType = getEventType(), eventType = eventType ) + val eventTag = getBranchName(event) val branchFilter = BranchFilter( pipelineId = pipelineId, - triggerOnBranchName = getBranchName(event), + triggerOnBranchName = eventTag, includedBranches = WebhookUtils.convert(tagName), - excludedBranches = WebhookUtils.convert(excludeTagName) + excludedBranches = WebhookUtils.convert(excludeTagName), + includedFailedReason = I18Variable( + code = WebhookI18nConstants.TAG_NAME_NOT_MATCH, + params = listOf(eventTag) + ).toJsonStr(), + excludedFailedReason = I18Variable( + code = WebhookI18nConstants.TAG_NAME_IGNORED, + params = listOf(eventTag) + ).toJsonStr() ) + val userId = getUsername(event) val userFilter = UserFilter( pipelineId = pipelineId, triggerOnUser = getUsername(event), includedUsers = WebhookUtils.convert(includeUsers), - excludedUsers = WebhookUtils.convert(excludeUsers) + excludedUsers = WebhookUtils.convert(excludeUsers), + includedFailedReason = I18Variable( + code = WebhookI18nConstants.USER_NOT_MATCH, + params = listOf(userId) + ).toJsonStr(), + excludedFailedReason = I18Variable( + code = WebhookI18nConstants.USER_IGNORED, + params = listOf(userId) + ).toJsonStr() ) + val fromBranch = event.create_from ?: "" val fromBranchFilter = BranchFilter( pipelineId = pipelineId, - triggerOnBranchName = event.create_from ?: "", + triggerOnBranchName = fromBranch, includedBranches = WebhookUtils.convert(fromBranches), - excludedBranches = emptyList() + excludedBranches = emptyList(), + includedFailedReason = I18Variable( + code = WebhookI18nConstants.TAG_SOURCE_BRANCH_NOT_MATCH, + params = listOf(fromBranch) + ).toJsonStr(), + excludedFailedReason = "" ) return listOf(urlFilter, eventTypeFilter, branchFilter, userFilter, fromBranchFilter) } diff --git a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/matcher/AbstractScmWebhookMatcher.kt b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/matcher/AbstractScmWebhookMatcher.kt index 5044e86eb8d..813f906aa9a 100644 --- a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/matcher/AbstractScmWebhookMatcher.kt +++ b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/matcher/AbstractScmWebhookMatcher.kt @@ -30,6 +30,7 @@ package com.tencent.devops.common.webhook.service.code.matcher import com.tencent.devops.common.pipeline.pojo.element.trigger.enums.CodeEventType import com.tencent.devops.common.webhook.pojo.code.CodeWebhookEvent import com.tencent.devops.common.webhook.service.code.loader.CodeWebhookHandlerRegistrar +import com.tencent.devops.common.webhook.service.code.pojo.WebhookMatchResult import com.tencent.devops.repository.pojo.Repository @Suppress("TooManyFunctions") @@ -38,7 +39,7 @@ abstract class AbstractScmWebhookMatcher( ) : ScmWebhookMatcher { protected val eventHandler by lazy { CodeWebhookHandlerRegistrar.getHandler(webhookEvent = event) } - override fun preMatch(): ScmWebhookMatcher.MatchResult { + override fun preMatch(): WebhookMatchResult { return eventHandler.preMatch(event) } @@ -82,6 +83,14 @@ abstract class AbstractScmWebhookMatcher( return eventHandler.getMessage(event) } + override fun getEventDesc(): String { + return eventHandler.getEventDesc(event) + } + + override fun getExternalId(): String { + return eventHandler.getExternalId(event) + } + override fun retrieveParams(projectId: String?, repository: Repository?): Map { return eventHandler.retrieveParams( event = event, diff --git a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/matcher/GitWebHookMatcher.kt b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/matcher/GitWebHookMatcher.kt index d8e95a7b119..47a30f556ff 100644 --- a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/matcher/GitWebHookMatcher.kt +++ b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/matcher/GitWebHookMatcher.kt @@ -30,6 +30,7 @@ package com.tencent.devops.common.webhook.service.code.matcher import com.tencent.devops.common.pipeline.pojo.element.trigger.enums.CodeType import com.tencent.devops.common.webhook.pojo.code.WebHookParams import com.tencent.devops.common.webhook.pojo.code.git.GitEvent +import com.tencent.devops.common.webhook.service.code.pojo.WebhookMatchResult import com.tencent.devops.repository.pojo.CodeGitRepository import com.tencent.devops.repository.pojo.CodeTGitRepository import com.tencent.devops.repository.pojo.Repository @@ -49,12 +50,12 @@ open class GitWebHookMatcher( pipelineId: String, repository: Repository, webHookParams: WebHookParams - ): ScmWebhookMatcher.MatchResult { + ): WebhookMatchResult { if (repository !is CodeGitRepository && repository !is CodeTGitRepository ) { logger.warn("$pipelineId|Is not code repo for git web hook for repo and pipeline: $repository") - return ScmWebhookMatcher.MatchResult(isMatch = false) + return WebhookMatchResult(isMatch = false) } return eventHandler.isMatch( event = event, diff --git a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/matcher/GithubWebHookMatcher.kt b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/matcher/GithubWebHookMatcher.kt index 32b168b37ab..49b9b723722 100644 --- a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/matcher/GithubWebHookMatcher.kt +++ b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/matcher/GithubWebHookMatcher.kt @@ -30,6 +30,7 @@ package com.tencent.devops.common.webhook.service.code.matcher import com.tencent.devops.common.pipeline.pojo.element.trigger.enums.CodeType import com.tencent.devops.common.webhook.pojo.code.WebHookParams import com.tencent.devops.common.webhook.pojo.code.github.GithubEvent +import com.tencent.devops.common.webhook.service.code.pojo.WebhookMatchResult import com.tencent.devops.repository.pojo.GithubRepository import com.tencent.devops.repository.pojo.Repository import org.slf4j.LoggerFactory @@ -48,10 +49,10 @@ class GithubWebHookMatcher( pipelineId: String, repository: Repository, webHookParams: WebHookParams - ): ScmWebhookMatcher.MatchResult { + ): WebhookMatchResult { if (repository !is GithubRepository) { logger.warn("$pipelineId|The repo($repository) is not code git repo for github web hook") - return ScmWebhookMatcher.MatchResult(isMatch = false) + return WebhookMatchResult(isMatch = false) } return eventHandler.isMatch( event = event, diff --git a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/matcher/GitlabWebHookMatcher.kt b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/matcher/GitlabWebHookMatcher.kt index 3469dee5056..f5d01b1bbd4 100644 --- a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/matcher/GitlabWebHookMatcher.kt +++ b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/matcher/GitlabWebHookMatcher.kt @@ -30,6 +30,7 @@ package com.tencent.devops.common.webhook.service.code.matcher import com.tencent.devops.common.pipeline.pojo.element.trigger.enums.CodeType import com.tencent.devops.common.webhook.pojo.code.WebHookParams import com.tencent.devops.common.webhook.pojo.code.git.GitEvent +import com.tencent.devops.common.webhook.service.code.pojo.WebhookMatchResult import com.tencent.devops.repository.pojo.CodeGitlabRepository import com.tencent.devops.repository.pojo.Repository import org.slf4j.LoggerFactory @@ -47,10 +48,10 @@ class GitlabWebHookMatcher( pipelineId: String, repository: Repository, webHookParams: WebHookParams - ): ScmWebhookMatcher.MatchResult { + ): WebhookMatchResult { if (repository !is CodeGitlabRepository) { logger.warn("$$pipelineId|the repo($repository) is not code git repo for git web hook") - return ScmWebhookMatcher.MatchResult(isMatch = false) + return WebhookMatchResult(isMatch = false) } return eventHandler.isMatch( event = event, diff --git a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/matcher/P4WebHookMatcher.kt b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/matcher/P4WebHookMatcher.kt index 011df0a3565..9b095b1780c 100644 --- a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/matcher/P4WebHookMatcher.kt +++ b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/matcher/P4WebHookMatcher.kt @@ -30,6 +30,7 @@ package com.tencent.devops.common.webhook.service.code.matcher import com.tencent.devops.common.pipeline.pojo.element.trigger.enums.CodeType import com.tencent.devops.common.webhook.pojo.code.WebHookParams import com.tencent.devops.common.webhook.pojo.code.p4.P4Event +import com.tencent.devops.common.webhook.service.code.pojo.WebhookMatchResult import com.tencent.devops.repository.pojo.CodeP4Repository import com.tencent.devops.repository.pojo.Repository import org.slf4j.LoggerFactory @@ -47,10 +48,10 @@ class P4WebHookMatcher( pipelineId: String, repository: Repository, webHookParams: WebHookParams - ): ScmWebhookMatcher.MatchResult { + ): WebhookMatchResult { if (repository !is CodeP4Repository) { logger.warn("$pipelineId|The repo($repository) is not code p4 repo for p4 web hook") - return ScmWebhookMatcher.MatchResult(isMatch = false) + return WebhookMatchResult(isMatch = false) } return eventHandler.isMatch( event = event, diff --git a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/matcher/ScmWebhookMatcher.kt b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/matcher/ScmWebhookMatcher.kt index a6c7d047ce7..718fbae741e 100644 --- a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/matcher/ScmWebhookMatcher.kt +++ b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/matcher/ScmWebhookMatcher.kt @@ -30,6 +30,7 @@ package com.tencent.devops.common.webhook.service.code.matcher import com.tencent.devops.common.pipeline.pojo.element.trigger.enums.CodeEventType import com.tencent.devops.common.pipeline.pojo.element.trigger.enums.CodeType import com.tencent.devops.common.webhook.pojo.code.WebHookParams +import com.tencent.devops.common.webhook.service.code.pojo.WebhookMatchResult import com.tencent.devops.repository.pojo.Repository import com.tencent.devops.scm.pojo.WebhookCommit import org.slf4j.LoggerFactory @@ -40,14 +41,14 @@ interface ScmWebhookMatcher { /** * 预匹配,在还没有解析流水线列表时判断 */ - fun preMatch(): MatchResult + fun preMatch(): WebhookMatchResult fun isMatch( projectId: String, pipelineId: String, repository: Repository, webHookParams: WebHookParams - ): MatchResult + ): WebhookMatchResult fun getUsername(): String @@ -71,6 +72,16 @@ interface ScmWebhookMatcher { fun getMessage(): String? + /** + * 获取事件描述,根据不同的事件组织事件说明 + */ + fun getEventDesc(): String = "" + + /** + * 获取webhook事件生产者ID,工蜂-工蜂ID,github-github id,svn-svn path,p4-p4port + */ + fun getExternalId(): String = "" + fun getWebHookParamsMap(): Map = emptyMap() fun retrieveParams( diff --git a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/matcher/SvnWebHookMatcher.kt b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/matcher/SvnWebHookMatcher.kt index b35513abd10..1c5c0d6958d 100644 --- a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/matcher/SvnWebHookMatcher.kt +++ b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/matcher/SvnWebHookMatcher.kt @@ -30,6 +30,7 @@ package com.tencent.devops.common.webhook.service.code.matcher import com.tencent.devops.common.pipeline.pojo.element.trigger.enums.CodeType import com.tencent.devops.common.webhook.pojo.code.WebHookParams import com.tencent.devops.common.webhook.pojo.code.svn.SvnCommitEvent +import com.tencent.devops.common.webhook.service.code.pojo.WebhookMatchResult import com.tencent.devops.repository.pojo.CodeSvnRepository import com.tencent.devops.repository.pojo.Repository import org.slf4j.LoggerFactory @@ -48,10 +49,10 @@ class SvnWebHookMatcher( pipelineId: String, repository: Repository, webHookParams: WebHookParams - ): ScmWebhookMatcher.MatchResult { + ): WebhookMatchResult { if (repository !is CodeSvnRepository) { logger.warn("$pipelineId|The repo($repository) is not code svn repo for svn web hook") - return ScmWebhookMatcher.MatchResult(isMatch = false) + return WebhookMatchResult(isMatch = false) } return eventHandler.isMatch( event = event, diff --git a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/param/GitWebHookStartParam.kt b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/param/GitWebHookStartParam.kt index b9f7d476507..3631406142d 100644 --- a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/param/GitWebHookStartParam.kt +++ b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/param/GitWebHookStartParam.kt @@ -46,6 +46,7 @@ import com.tencent.devops.common.webhook.pojo.code.MATCH_PATHS import com.tencent.devops.common.webhook.pojo.code.WebHookParams import com.tencent.devops.common.webhook.service.code.EventCacheService import com.tencent.devops.common.webhook.service.code.matcher.ScmWebhookMatcher +import com.tencent.devops.common.webhook.service.code.pojo.WebhookMatchResult import com.tencent.devops.repository.pojo.CodeGitRepository import com.tencent.devops.repository.pojo.Repository import com.tencent.devops.repository.pojo.enums.RepoAuthType @@ -68,7 +69,7 @@ class GitWebHookStartParam @Autowired constructor( matcher: ScmWebhookMatcher, variables: Map, params: WebHookParams, - matchResult: ScmWebhookMatcher.MatchResult + matchResult: WebhookMatchResult ): Map { val startParams = mutableMapOf() startParams[BK_REPO_GIT_WEBHOOK_COMMIT_ID] = matcher.getRevision() diff --git a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/param/GithubWebHookStartParam.kt b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/param/GithubWebHookStartParam.kt index f51dfa3a3d2..5a55b1e13aa 100644 --- a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/param/GithubWebHookStartParam.kt +++ b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/param/GithubWebHookStartParam.kt @@ -36,6 +36,7 @@ import com.tencent.devops.common.webhook.pojo.code.BK_REPO_GIT_WEBHOOK_EXCLUDE_U import com.tencent.devops.common.webhook.pojo.code.BK_REPO_GIT_WEBHOOK_INCLUDE_BRANCHS import com.tencent.devops.common.webhook.pojo.code.WebHookParams import com.tencent.devops.common.webhook.service.code.matcher.ScmWebhookMatcher +import com.tencent.devops.common.webhook.service.code.pojo.WebhookMatchResult import com.tencent.devops.repository.pojo.Repository import org.springframework.stereotype.Service @@ -53,7 +54,7 @@ class GithubWebHookStartParam : ScmWebhookStartParams, params: WebHookParams, - matchResult: ScmWebhookMatcher.MatchResult + matchResult: WebhookMatchResult ): Map { val startParams = mutableMapOf() startParams[BK_REPO_GIT_WEBHOOK_COMMIT_ID] = matcher.getRevision() diff --git a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/param/GitlabWebHookStartParam.kt b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/param/GitlabWebHookStartParam.kt index edf44d05355..14442ac5822 100644 --- a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/param/GitlabWebHookStartParam.kt +++ b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/param/GitlabWebHookStartParam.kt @@ -41,6 +41,7 @@ import com.tencent.devops.common.webhook.pojo.code.MATCH_BRANCH import com.tencent.devops.common.webhook.pojo.code.MATCH_PATHS import com.tencent.devops.common.webhook.pojo.code.WebHookParams import com.tencent.devops.common.webhook.service.code.matcher.ScmWebhookMatcher +import com.tencent.devops.common.webhook.service.code.pojo.WebhookMatchResult import com.tencent.devops.repository.pojo.Repository import org.springframework.stereotype.Service @@ -58,7 +59,7 @@ class GitlabWebHookStartParam : ScmWebhookStartParams, params: WebHookParams, - matchResult: ScmWebhookMatcher.MatchResult + matchResult: WebhookMatchResult ): Map { val startParams = mutableMapOf() startParams[BK_REPO_GIT_WEBHOOK_COMMIT_ID] = matcher.getRevision() diff --git a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/param/P4WebHookStartParam.kt b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/param/P4WebHookStartParam.kt index 3969e41f0b6..3d69b07fb22 100644 --- a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/param/P4WebHookStartParam.kt +++ b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/param/P4WebHookStartParam.kt @@ -33,6 +33,7 @@ import com.tencent.devops.common.webhook.pojo.code.BK_REPO_P4_WEBHOOK_INCLUDE_PA import com.tencent.devops.common.webhook.pojo.code.BK_REPO_P4_WEBHOOK_P4PORT import com.tencent.devops.common.webhook.pojo.code.WebHookParams import com.tencent.devops.common.webhook.service.code.matcher.ScmWebhookMatcher +import com.tencent.devops.common.webhook.service.code.pojo.WebhookMatchResult import com.tencent.devops.repository.pojo.Repository import org.springframework.stereotype.Service @@ -50,7 +51,7 @@ class P4WebHookStartParam : ScmWebhookStartParams { matcher: ScmWebhookMatcher, variables: Map, params: WebHookParams, - matchResult: ScmWebhookMatcher.MatchResult + matchResult: WebhookMatchResult ): Map { val startParams = mutableMapOf() with(element.data.input) { diff --git a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/param/ScmWebhookStartParams.kt b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/param/ScmWebhookStartParams.kt index 1badbd260b5..7168d5b32fa 100644 --- a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/param/ScmWebhookStartParams.kt +++ b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/param/ScmWebhookStartParams.kt @@ -53,6 +53,7 @@ import com.tencent.devops.common.webhook.pojo.code.PIPELINE_WEBHOOK_TARGET_URL import com.tencent.devops.common.webhook.pojo.code.PIPELINE_WEBHOOK_TYPE import com.tencent.devops.common.webhook.pojo.code.WebHookParams import com.tencent.devops.common.webhook.service.code.matcher.ScmWebhookMatcher +import com.tencent.devops.common.webhook.service.code.pojo.WebhookMatchResult import com.tencent.devops.process.utils.PIPELINE_BUILD_MSG import com.tencent.devops.process.utils.PIPELINE_START_TASK_ID import com.tencent.devops.repository.pojo.Repository @@ -70,7 +71,7 @@ interface ScmWebhookStartParams { matcher: ScmWebhookMatcher, variables: Map, params: WebHookParams, - matchResult: ScmWebhookMatcher.MatchResult + matchResult: WebhookMatchResult ): Map { val startParams = mutableMapOf() startParams.putAll( @@ -160,6 +161,6 @@ interface ScmWebhookStartParams { matcher: ScmWebhookMatcher, variables: Map, params: WebHookParams, - matchResult: ScmWebhookMatcher.MatchResult + matchResult: WebhookMatchResult ): Map } diff --git a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/param/SvnWebHookStartParam.kt b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/param/SvnWebHookStartParam.kt index af3f0c82b22..cd2076278f9 100644 --- a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/param/SvnWebHookStartParam.kt +++ b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/param/SvnWebHookStartParam.kt @@ -36,6 +36,7 @@ import com.tencent.devops.common.webhook.pojo.code.BK_REPO_SVN_WEBHOOK_RELATIVE_ import com.tencent.devops.common.webhook.pojo.code.MATCH_PATHS import com.tencent.devops.common.webhook.pojo.code.WebHookParams import com.tencent.devops.common.webhook.service.code.matcher.ScmWebhookMatcher +import com.tencent.devops.common.webhook.service.code.pojo.WebhookMatchResult import com.tencent.devops.repository.pojo.Repository import org.springframework.stereotype.Service @@ -53,7 +54,7 @@ class SvnWebHookStartParam : ScmWebhookStartParams matcher: ScmWebhookMatcher, variables: Map, params: WebHookParams, - matchResult: ScmWebhookMatcher.MatchResult + matchResult: WebhookMatchResult ): Map { val startParams = mutableMapOf() startParams[BK_REPO_SVN_WEBHOOK_RELATIVE_PATH] = element.relativePath ?: "" diff --git a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/param/TGitWebHookStartParam.kt b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/param/TGitWebHookStartParam.kt index 0dd6e44ff5c..84fcaf781ba 100644 --- a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/param/TGitWebHookStartParam.kt +++ b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/param/TGitWebHookStartParam.kt @@ -44,6 +44,7 @@ import com.tencent.devops.common.webhook.pojo.code.MATCH_PATHS import com.tencent.devops.common.webhook.pojo.code.WebHookParams import com.tencent.devops.common.webhook.service.code.GitScmService import com.tencent.devops.common.webhook.service.code.matcher.ScmWebhookMatcher +import com.tencent.devops.common.webhook.service.code.pojo.WebhookMatchResult import com.tencent.devops.repository.pojo.CodeTGitRepository import com.tencent.devops.repository.pojo.Repository import com.tencent.devops.repository.pojo.enums.RepoAuthType @@ -66,7 +67,7 @@ class TGitWebHookStartParam @Autowired constructor( matcher: ScmWebhookMatcher, variables: Map, params: WebHookParams, - matchResult: ScmWebhookMatcher.MatchResult + matchResult: WebhookMatchResult ): Map { val startParams = mutableMapOf() with(element.data.input) { diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/engine/pojo/WebhookElementParams.kt b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/pojo/WebhookMatchResult.kt similarity index 77% rename from src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/engine/pojo/WebhookElementParams.kt rename to src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/pojo/WebhookMatchResult.kt index 9a72b6c28e3..aa8a6be062d 100644 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/engine/pojo/WebhookElementParams.kt +++ b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/pojo/WebhookMatchResult.kt @@ -23,19 +23,20 @@ * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * */ -package com.tencent.devops.process.engine.pojo +package com.tencent.devops.common.webhook.service.code.pojo -import com.tencent.devops.common.api.enums.RepositoryConfig -import com.tencent.devops.common.api.enums.ScmType -import com.tencent.devops.common.pipeline.pojo.element.trigger.enums.CodeEventType +import io.swagger.annotations.ApiModel +import io.swagger.annotations.ApiModelProperty -/** - * webhook事件触发插件参数配置 - */ -data class WebhookElementParams( - val repositoryConfig: RepositoryConfig, - val scmType: ScmType, - val eventType: CodeEventType? +@ApiModel +data class WebhookMatchResult( + @ApiModelProperty("是否匹配") + val isMatch: Boolean, + @ApiModelProperty("匹配时输出的变量") + val extra: Map = mapOf(), + @ApiModelProperty("匹配失败原因") + val reason: String? = null ) diff --git a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/test/kotlin/com/tencent/devops/common/webhook/service/code/filter/PathRegexFilterTest.kt b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/test/kotlin/com/tencent/devops/common/webhook/service/code/filter/PathRegexFilterTest.kt index 272f49abbf6..024db5177d6 100644 --- a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/test/kotlin/com/tencent/devops/common/webhook/service/code/filter/PathRegexFilterTest.kt +++ b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/test/kotlin/com/tencent/devops/common/webhook/service/code/filter/PathRegexFilterTest.kt @@ -313,7 +313,7 @@ class PathRegexFilterTest { caseSensitive = true ) Assertions.assertTrue(pathRegexFilter.doFilter(response)) - response.getParam()[MATCH_PATHS]?.let { + response.params[MATCH_PATHS]?.let { Assertions.assertTrue( it.split(",").toSet().containsAll( setOf( @@ -332,7 +332,7 @@ class PathRegexFilterTest { caseSensitive = true ) Assertions.assertTrue(pathRegexFilter.doFilter(response)) - response.getParam()[MATCH_PATHS]?.let { + response.params[MATCH_PATHS]?.let { Assertions.assertTrue( it.split(",").toSet().containsAll( setOf( @@ -350,7 +350,7 @@ class PathRegexFilterTest { caseSensitive = true ) Assertions.assertTrue(pathRegexFilter.doFilter(response)) - response.getParam()[MATCH_PATHS]?.let { + response.params[MATCH_PATHS]?.let { Assertions.assertTrue( it.split(",").toSet().containsAll( setOf( @@ -368,7 +368,7 @@ class PathRegexFilterTest { caseSensitive = true ) Assertions.assertTrue(pathRegexFilter.doFilter(response)) - response.getParam()[MATCH_PATHS]?.let { + response.params[MATCH_PATHS]?.let { Assertions.assertTrue( it.split(",").toSet().containsAll( setOf( @@ -386,7 +386,7 @@ class PathRegexFilterTest { caseSensitive = true ) Assertions.assertTrue(pathRegexFilter.doFilter(response)) - response.getParam()[MATCH_PATHS]?.let { + response.params[MATCH_PATHS]?.let { Assertions.assertTrue( it.split(",").toSet().containsAll( setOf( @@ -404,7 +404,7 @@ class PathRegexFilterTest { caseSensitive = true ) Assertions.assertTrue(pathRegexFilter.doFilter(response)) - response.getParam()[MATCH_PATHS]?.let { + response.params[MATCH_PATHS]?.let { Assertions.assertTrue( it.split(",").toSet().containsAll( setOf( @@ -422,7 +422,7 @@ class PathRegexFilterTest { caseSensitive = true ) Assertions.assertTrue(pathRegexFilter.doFilter(response)) - response.getParam()[MATCH_PATHS]?.let { + response.params[MATCH_PATHS]?.let { Assertions.assertTrue( it.split(",").toSet().containsAll( setOf( @@ -448,7 +448,7 @@ class PathRegexFilterTest { caseSensitive = true ) Assertions.assertTrue(pathRegexFilter.doFilter(response)) - response.getParam()[MATCH_PATHS]?.let { + response.params[MATCH_PATHS]?.let { Assertions.assertTrue( it.split(",").toSet().containsAll( setOf( @@ -476,7 +476,7 @@ class PathRegexFilterTest { caseSensitive = true ) Assertions.assertTrue(pathRegexFilter.doFilter(response)) - response.getParam()[MATCH_PATHS]?.let { + response.params[MATCH_PATHS]?.let { Assertions.assertTrue( it.split(",").toSet().containsAll( setOf( @@ -498,7 +498,7 @@ class PathRegexFilterTest { caseSensitive = true ) Assertions.assertTrue(pathRegexFilter.doFilter(response)) - response.getParam()[MATCH_PATHS]?.let { + response.params[MATCH_PATHS]?.let { Assertions.assertTrue( it.split(",").toSet().containsAll( setOf( @@ -519,7 +519,7 @@ class PathRegexFilterTest { caseSensitive = true ) Assertions.assertTrue(pathRegexFilter.doFilter(response)) - response.getParam()[MATCH_PATHS]?.let { + response.params[MATCH_PATHS]?.let { Assertions.assertTrue( it.split(",").toSet().containsAll( setOf( @@ -540,7 +540,7 @@ class PathRegexFilterTest { caseSensitive = true ) Assertions.assertTrue(pathRegexFilter.doFilter(response)) - response.getParam()[MATCH_PATHS]?.let { + response.params[MATCH_PATHS]?.let { Assertions.assertTrue( it.split(",").toSet().containsAll( setOf( diff --git a/src/backend/ci/core/misc/biz-misc/src/main/kotlin/com/tencent/devops/misc/dao/process/ProcessDataDeleteDao.kt b/src/backend/ci/core/misc/biz-misc/src/main/kotlin/com/tencent/devops/misc/dao/process/ProcessDataDeleteDao.kt index 5c5ef7a0b62..fe2ad9291ed 100644 --- a/src/backend/ci/core/misc/biz-misc/src/main/kotlin/com/tencent/devops/misc/dao/process/ProcessDataDeleteDao.kt +++ b/src/backend/ci/core/misc/biz-misc/src/main/kotlin/com/tencent/devops/misc/dao/process/ProcessDataDeleteDao.kt @@ -58,7 +58,6 @@ import com.tencent.devops.model.process.tables.TPipelineViewGroup import com.tencent.devops.model.process.tables.TPipelineViewTop import com.tencent.devops.model.process.tables.TPipelineViewUserLastView import com.tencent.devops.model.process.tables.TPipelineViewUserSettings -import com.tencent.devops.model.process.tables.TPipelineWebhookBuildLogDetail import com.tencent.devops.model.process.tables.TPipelineWebhookBuildParameter import com.tencent.devops.model.process.tables.TPipelineWebhookQueue import com.tencent.devops.model.process.tables.TProjectPipelineCallback @@ -257,14 +256,6 @@ class ProcessDataDeleteDao { } } - fun deletePipelineWebhookBuildLogDetail(dslContext: DSLContext, projectId: String, pipelineId: String) { - with(TPipelineWebhookBuildLogDetail.T_PIPELINE_WEBHOOK_BUILD_LOG_DETAIL) { - dslContext.deleteFrom(this) - .where(PROJECT_ID.eq(projectId).and(PIPELINE_ID.eq(pipelineId))) - .execute() - } - } - fun deletePipelineWebhookQueue(dslContext: DSLContext, projectId: String, buildIds: List) { with(TPipelineWebhookQueue.T_PIPELINE_WEBHOOK_QUEUE) { dslContext.deleteFrom(this) diff --git a/src/backend/ci/core/misc/biz-misc/src/main/kotlin/com/tencent/devops/misc/dao/process/ProcessDataMigrateDao.kt b/src/backend/ci/core/misc/biz-misc/src/main/kotlin/com/tencent/devops/misc/dao/process/ProcessDataMigrateDao.kt index f94d8038f1a..71e603f388f 100644 --- a/src/backend/ci/core/misc/biz-misc/src/main/kotlin/com/tencent/devops/misc/dao/process/ProcessDataMigrateDao.kt +++ b/src/backend/ci/core/misc/biz-misc/src/main/kotlin/com/tencent/devops/misc/dao/process/ProcessDataMigrateDao.kt @@ -58,7 +58,6 @@ import com.tencent.devops.model.process.tables.TPipelineViewGroup import com.tencent.devops.model.process.tables.TPipelineViewTop import com.tencent.devops.model.process.tables.TPipelineViewUserLastView import com.tencent.devops.model.process.tables.TPipelineViewUserSettings -import com.tencent.devops.model.process.tables.TPipelineWebhookBuildLogDetail import com.tencent.devops.model.process.tables.TPipelineWebhookBuildParameter import com.tencent.devops.model.process.tables.TPipelineWebhookQueue import com.tencent.devops.model.process.tables.TProjectPipelineCallback @@ -97,7 +96,6 @@ import com.tencent.devops.model.process.tables.records.TPipelineViewRecord import com.tencent.devops.model.process.tables.records.TPipelineViewTopRecord import com.tencent.devops.model.process.tables.records.TPipelineViewUserLastViewRecord import com.tencent.devops.model.process.tables.records.TPipelineViewUserSettingsRecord -import com.tencent.devops.model.process.tables.records.TPipelineWebhookBuildLogDetailRecord import com.tencent.devops.model.process.tables.records.TPipelineWebhookBuildParameterRecord import com.tencent.devops.model.process.tables.records.TPipelineWebhookQueueRecord import com.tencent.devops.model.process.tables.records.TProjectPipelineCallbackHistoryRecord @@ -653,31 +651,6 @@ class ProcessDataMigrateDao { } } - fun getPipelineWebhookBuildLogDetailRecords( - dslContext: DSLContext, - projectId: String, - pipelineId: String, - limit: Int, - offset: Int - ): List { - with(TPipelineWebhookBuildLogDetail.T_PIPELINE_WEBHOOK_BUILD_LOG_DETAIL) { - return dslContext.selectFrom(this) - .where(PROJECT_ID.eq(projectId).and(PIPELINE_ID.eq(pipelineId))) - .orderBy(ID.asc()) - .limit(limit).offset(offset).fetchInto(TPipelineWebhookBuildLogDetailRecord::class.java) - } - } - - fun migratePipelineWebhookBuildLogDetailData( - migratingShardingDslContext: DSLContext, - webhookBuildLogDetailRecords: List - ) { - with(TPipelineWebhookBuildLogDetail.T_PIPELINE_WEBHOOK_BUILD_LOG_DETAIL) { - val insertRecords = webhookBuildLogDetailRecords.map { migratingShardingDslContext.newRecord(this, it) } - migratingShardingDslContext.batchInsert(insertRecords).execute() - } - } - fun getPipelineWebhookQueueRecords( dslContext: DSLContext, projectId: String, diff --git a/src/backend/ci/core/misc/biz-misc/src/main/kotlin/com/tencent/devops/misc/service/process/ProcessMigrationDataDeleteService.kt b/src/backend/ci/core/misc/biz-misc/src/main/kotlin/com/tencent/devops/misc/service/process/ProcessMigrationDataDeleteService.kt index d134281dd0e..811fcc85ccf 100644 --- a/src/backend/ci/core/misc/biz-misc/src/main/kotlin/com/tencent/devops/misc/service/process/ProcessMigrationDataDeleteService.kt +++ b/src/backend/ci/core/misc/biz-misc/src/main/kotlin/com/tencent/devops/misc/service/process/ProcessMigrationDataDeleteService.kt @@ -177,7 +177,6 @@ class ProcessMigrationDataDeleteService @Autowired constructor( processDataDeleteDao.deletePipelineBuildContainer(dslContext, projectId, pipelineId) processDataDeleteDao.deletePipelineBuildStage(dslContext, projectId, pipelineId) processDataDeleteDao.deletePipelineFavor(dslContext, projectId, pipelineId) - processDataDeleteDao.deletePipelineWebhookBuildLogDetail(dslContext, projectId, pipelineId) offset += DEFAULT_PAGE_SIZE } while (historyInfoRecords?.size == DEFAULT_PAGE_SIZE) } diff --git a/src/backend/ci/core/misc/biz-misc/src/main/kotlin/com/tencent/devops/misc/task/MigratePipelineDataTask.kt b/src/backend/ci/core/misc/biz-misc/src/main/kotlin/com/tencent/devops/misc/task/MigratePipelineDataTask.kt index b2075ea7642..87aa5c3afb7 100644 --- a/src/backend/ci/core/misc/biz-misc/src/main/kotlin/com/tencent/devops/misc/task/MigratePipelineDataTask.kt +++ b/src/backend/ci/core/misc/biz-misc/src/main/kotlin/com/tencent/devops/misc/task/MigratePipelineDataTask.kt @@ -166,14 +166,6 @@ class MigratePipelineDataTask constructor( migratingShardingDslContext = migratingShardingDslContext, processDataMigrateDao = processDbMigrateDao ) - // 3.14、迁移T_PIPELINE_WEBHOOK_BUILD_LOG_DETAIL表数据 - migratePipelineWebhookBuildLogDetailData( - projectId = projectId, - pipelineId = pipelineId, - dslContext = dslContext, - migratingShardingDslContext = migratingShardingDslContext, - processDataMigrateDao = processDbMigrateDao - ) // 3.15、迁移T_PIPELINE_WEBHOOK_QUEUE表数据 migratePipelineWebhookQueueData( projectId = projectId, @@ -597,32 +589,6 @@ class MigratePipelineDataTask constructor( } while (pipelineSettingVersionRecords.size == SHORT_PAGE_SIZE) } - private fun migratePipelineWebhookBuildLogDetailData( - projectId: String, - pipelineId: String, - dslContext: DSLContext, - migratingShardingDslContext: DSLContext, - processDataMigrateDao: ProcessDataMigrateDao - ) { - var offset = 0 - do { - val webhookBuildLogDetailRecords = processDataMigrateDao.getPipelineWebhookBuildLogDetailRecords( - dslContext = dslContext, - projectId = projectId, - pipelineId = pipelineId, - limit = SHORT_PAGE_SIZE, - offset = offset - ) - if (webhookBuildLogDetailRecords.isNotEmpty()) { - processDataMigrateDao.migratePipelineWebhookBuildLogDetailData( - migratingShardingDslContext = migratingShardingDslContext, - webhookBuildLogDetailRecords = webhookBuildLogDetailRecords - ) - } - offset += SHORT_PAGE_SIZE - } while (webhookBuildLogDetailRecords.size == SHORT_PAGE_SIZE) - } - private fun migratePipelineWebhookQueueData( projectId: String, pipelineId: String, diff --git a/src/backend/ci/core/openapi/api-openapi/src/main/kotlin/com/tencent/devops/openapi/api/apigw/v3/ApigwPipelineWebhookResourceV3.kt b/src/backend/ci/core/openapi/api-openapi/src/main/kotlin/com/tencent/devops/openapi/api/apigw/v3/ApigwPipelineWebhookResourceV3.kt index 33cd7be80a0..8fea657eb82 100644 --- a/src/backend/ci/core/openapi/api-openapi/src/main/kotlin/com/tencent/devops/openapi/api/apigw/v3/ApigwPipelineWebhookResourceV3.kt +++ b/src/backend/ci/core/openapi/api-openapi/src/main/kotlin/com/tencent/devops/openapi/api/apigw/v3/ApigwPipelineWebhookResourceV3.kt @@ -30,10 +30,8 @@ package com.tencent.devops.openapi.api.apigw.v3 import com.tencent.devops.common.api.auth.AUTH_HEADER_DEVOPS_APP_CODE import com.tencent.devops.common.api.auth.AUTH_HEADER_DEVOPS_APP_CODE_DEFAULT_VALUE import com.tencent.devops.common.api.auth.AUTH_HEADER_DEVOPS_USER_ID -import com.tencent.devops.common.api.model.SQLPage import com.tencent.devops.common.api.pojo.Result import com.tencent.devops.process.pojo.webhook.PipelineWebhook -import com.tencent.devops.process.pojo.webhook.PipelineWebhookBuildLogDetail import io.swagger.annotations.Api import io.swagger.annotations.ApiOperation import io.swagger.annotations.ApiParam @@ -76,38 +74,4 @@ interface ApigwPipelineWebhookResourceV3 { @QueryParam("pageSize") pageSize: Int? ): Result> - - @ApiOperation( - "获取流水线的webhook构建日志列表", - tags = ["v3_user_pipeline_webhook_build_log", "v3_app_pipeline_webhook_build_log"] - ) - @GET - @Path("/buildLog") - fun listPipelineWebhookBuildLog( - @ApiParam(value = "appCode", required = true, defaultValue = AUTH_HEADER_DEVOPS_APP_CODE_DEFAULT_VALUE) - @HeaderParam(AUTH_HEADER_DEVOPS_APP_CODE) - appCode: String?, - @ApiParam(value = "apigw Type", required = true) - @PathParam("apigwType") - apigwType: String?, - @ApiParam("userId", required = true) - @HeaderParam(AUTH_HEADER_DEVOPS_USER_ID) - userId: String, - @PathParam("projectId") - projectId: String, - @PathParam("pipelineId") - pipelineId: String, - @ApiParam("仓库名", required = false) - @QueryParam("repoName") - repoName: String?, - @ApiParam("commitId", required = false) - @QueryParam("commitId") - commitId: String?, - @ApiParam("页码", required = false) - @QueryParam("page") - page: Int?, - @ApiParam("每页大小", required = false) - @QueryParam("pageSize") - pageSize: Int? - ): Result?> } diff --git a/src/backend/ci/core/openapi/api-openapi/src/main/kotlin/com/tencent/devops/openapi/api/apigw/v4/ApigwPipelineWebhookResourceV4.kt b/src/backend/ci/core/openapi/api-openapi/src/main/kotlin/com/tencent/devops/openapi/api/apigw/v4/ApigwPipelineWebhookResourceV4.kt index d3672728efa..ae41614eae3 100644 --- a/src/backend/ci/core/openapi/api-openapi/src/main/kotlin/com/tencent/devops/openapi/api/apigw/v4/ApigwPipelineWebhookResourceV4.kt +++ b/src/backend/ci/core/openapi/api-openapi/src/main/kotlin/com/tencent/devops/openapi/api/apigw/v4/ApigwPipelineWebhookResourceV4.kt @@ -30,10 +30,8 @@ package com.tencent.devops.openapi.api.apigw.v4 import com.tencent.devops.common.api.auth.AUTH_HEADER_DEVOPS_APP_CODE import com.tencent.devops.common.api.auth.AUTH_HEADER_DEVOPS_APP_CODE_DEFAULT_VALUE import com.tencent.devops.common.api.auth.AUTH_HEADER_DEVOPS_USER_ID -import com.tencent.devops.common.api.model.SQLPage import com.tencent.devops.common.api.pojo.Result import com.tencent.devops.process.pojo.webhook.PipelineWebhook -import com.tencent.devops.process.pojo.webhook.PipelineWebhookBuildLogDetail import io.swagger.annotations.Api import io.swagger.annotations.ApiOperation import io.swagger.annotations.ApiParam @@ -77,38 +75,4 @@ interface ApigwPipelineWebhookResourceV4 { @QueryParam("pageSize") pageSize: Int? ): Result> - - @ApiOperation( - "获取流水线的webhook构建日志列表", - tags = ["v4_user_pipeline_webhook_build_log", "v4_app_pipeline_webhook_build_log"] - ) - @GET - @Path("/pipeline_webhook_build_log_detail") - fun listPipelineWebhookBuildLog( - @ApiParam(value = "appCode", required = true, defaultValue = AUTH_HEADER_DEVOPS_APP_CODE_DEFAULT_VALUE) - @HeaderParam(AUTH_HEADER_DEVOPS_APP_CODE) - appCode: String?, - @ApiParam(value = "apigw Type", required = true) - @PathParam("apigwType") - apigwType: String?, - @ApiParam("userId", required = true) - @HeaderParam(AUTH_HEADER_DEVOPS_USER_ID) - userId: String, - @PathParam("projectId") - projectId: String, - @QueryParam("pipelineId") - pipelineId: String, - @ApiParam("仓库名", required = false) - @QueryParam("repoName") - repoName: String?, - @ApiParam("commitId", required = false) - @QueryParam("commitId") - commitId: String?, - @ApiParam("页码", required = false) - @QueryParam("page") - page: Int?, - @ApiParam("每页大小", required = false) - @QueryParam("pageSize") - pageSize: Int? - ): Result?> } diff --git a/src/backend/ci/core/openapi/biz-openapi/src/main/kotlin/com/tencent/devops/openapi/resources/apigw/v3/ApigwPipelineWebhookResourceV3Impl.kt b/src/backend/ci/core/openapi/biz-openapi/src/main/kotlin/com/tencent/devops/openapi/resources/apigw/v3/ApigwPipelineWebhookResourceV3Impl.kt index 41f125d4539..ea816c84d8b 100644 --- a/src/backend/ci/core/openapi/biz-openapi/src/main/kotlin/com/tencent/devops/openapi/resources/apigw/v3/ApigwPipelineWebhookResourceV3Impl.kt +++ b/src/backend/ci/core/openapi/biz-openapi/src/main/kotlin/com/tencent/devops/openapi/resources/apigw/v3/ApigwPipelineWebhookResourceV3Impl.kt @@ -27,14 +27,12 @@ package com.tencent.devops.openapi.resources.apigw.v3 -import com.tencent.devops.common.api.model.SQLPage import com.tencent.devops.common.api.pojo.Result import com.tencent.devops.common.client.Client import com.tencent.devops.common.web.RestResource import com.tencent.devops.openapi.api.apigw.v3.ApigwPipelineWebhookResourceV3 import com.tencent.devops.process.api.service.ServiceScmWebhookResource import com.tencent.devops.process.pojo.webhook.PipelineWebhook -import com.tencent.devops.process.pojo.webhook.PipelineWebhookBuildLogDetail import org.slf4j.LoggerFactory import org.springframework.beans.factory.annotation.Autowired @@ -63,33 +61,6 @@ class ApigwPipelineWebhookResourceV3Impl @Autowired constructor( ) } - override fun listPipelineWebhookBuildLog( - appCode: String?, - apigwType: String?, - userId: String, - projectId: String, - pipelineId: String, - repoName: String?, - commitId: String?, - page: Int?, - pageSize: Int? - ): Result?> { - logger.info( - "OPENAPI_PIPELINE_WEBHOOK_V3|$userId|list pipeline webhook build log|$projectId|$pipelineId" + - "|$repoName|$commitId|$page|$pageSize" - ) - return client.get(ServiceScmWebhookResource::class) - .listPipelineWebhookBuildLog( - userId = userId, - projectId = projectId, - pipelineId = pipelineId, - repoName = repoName, - commitId = commitId, - page = page, - pageSize = pageSize - ) - } - companion object { private val logger = LoggerFactory.getLogger(ApigwPipelineWebhookResourceV3Impl::class.java) } diff --git a/src/backend/ci/core/openapi/biz-openapi/src/main/kotlin/com/tencent/devops/openapi/resources/apigw/v4/ApigwPipelineWebhookResourceV4Impl.kt b/src/backend/ci/core/openapi/biz-openapi/src/main/kotlin/com/tencent/devops/openapi/resources/apigw/v4/ApigwPipelineWebhookResourceV4Impl.kt index dfd9811f751..252df956732 100644 --- a/src/backend/ci/core/openapi/biz-openapi/src/main/kotlin/com/tencent/devops/openapi/resources/apigw/v4/ApigwPipelineWebhookResourceV4Impl.kt +++ b/src/backend/ci/core/openapi/biz-openapi/src/main/kotlin/com/tencent/devops/openapi/resources/apigw/v4/ApigwPipelineWebhookResourceV4Impl.kt @@ -27,14 +27,12 @@ package com.tencent.devops.openapi.resources.apigw.v4 -import com.tencent.devops.common.api.model.SQLPage import com.tencent.devops.common.api.pojo.Result import com.tencent.devops.common.client.Client import com.tencent.devops.common.web.RestResource import com.tencent.devops.openapi.api.apigw.v4.ApigwPipelineWebhookResourceV4 import com.tencent.devops.process.api.service.ServiceScmWebhookResource import com.tencent.devops.process.pojo.webhook.PipelineWebhook -import com.tencent.devops.process.pojo.webhook.PipelineWebhookBuildLogDetail import org.slf4j.LoggerFactory import org.springframework.beans.factory.annotation.Autowired @@ -63,33 +61,6 @@ class ApigwPipelineWebhookResourceV4Impl @Autowired constructor( ) } - override fun listPipelineWebhookBuildLog( - appCode: String?, - apigwType: String?, - userId: String, - projectId: String, - pipelineId: String, - repoName: String?, - commitId: String?, - page: Int?, - pageSize: Int? - ): Result?> { - logger.info( - "OPENAPI_PIPELINE_WEBHOOK_V4|$userId|list pipeline webhook build log|$projectId|$pipelineId" + - "|$repoName|$commitId|$page|$pageSize" - ) - return client.get(ServiceScmWebhookResource::class) - .listPipelineWebhookBuildLog( - userId = userId, - projectId = projectId, - pipelineId = pipelineId, - repoName = repoName, - commitId = commitId, - page = page, - pageSize = pageSize - ) - } - companion object { private val logger = LoggerFactory.getLogger(ApigwPipelineWebhookResourceV4Impl::class.java) } diff --git a/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/api/op/OpScmWebhookResource.kt b/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/api/op/OpScmWebhookResource.kt index e6e283e296d..4757a1a38af 100644 --- a/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/api/op/OpScmWebhookResource.kt +++ b/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/api/op/OpScmWebhookResource.kt @@ -17,6 +17,11 @@ import javax.ws.rs.core.MediaType @Consumes(MediaType.APPLICATION_JSON) interface OpScmWebhookResource { + @ApiOperation("更新所有的webhook项目名") + @PUT + @Path("/updateProjectNameAndTaskId") + fun updateProjectNameAndTaskId(): Result + @ApiOperation("更新webhook secret") @PUT @Path("/updateWebhookSecret") @@ -25,4 +30,9 @@ interface OpScmWebhookResource { @QueryParam("scmType") scmType: String ): Result + + @ApiOperation("更新webhook 事件信息") + @PUT + @Path("/updateWebhookEventInfo") + fun updateWebhookEventInfo(): Result } diff --git a/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/api/service/ServiceScmWebhookResource.kt b/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/api/service/ServiceScmWebhookResource.kt index 1cb6201711e..0f56119adf9 100644 --- a/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/api/service/ServiceScmWebhookResource.kt +++ b/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/api/service/ServiceScmWebhookResource.kt @@ -29,12 +29,10 @@ package com.tencent.devops.process.api.service import com.tencent.devops.common.api.auth.AUTH_HEADER_DEVOPS_PROJECT_ID import com.tencent.devops.common.api.auth.AUTH_HEADER_USER_ID -import com.tencent.devops.common.api.model.SQLPage import com.tencent.devops.common.api.pojo.Result import com.tencent.devops.common.webhook.pojo.code.github.GithubWebhook import com.tencent.devops.process.pojo.code.WebhookCommit import com.tencent.devops.process.pojo.webhook.PipelineWebhook -import com.tencent.devops.process.pojo.webhook.PipelineWebhookBuildLogDetail import io.swagger.annotations.Api import io.swagger.annotations.ApiOperation import io.swagger.annotations.ApiParam @@ -88,29 +86,4 @@ interface ServiceScmWebhookResource { @QueryParam("pageSize") pageSize: Int? ): Result> - - @ApiOperation("获取流水线的webhook构建日志列表") - @GET - @Path("/{projectId}/{pipelineId}/buildLog") - @Suppress("ALL") - fun listPipelineWebhookBuildLog( - @HeaderParam(AUTH_HEADER_USER_ID) - userId: String, - @PathParam("projectId") - projectId: String, - @PathParam("pipelineId") - pipelineId: String, - @ApiParam("仓库名", required = false) - @QueryParam("repoName") - repoName: String?, - @ApiParam("commitId", required = false) - @QueryParam("commitId") - commitId: String?, - @ApiParam("页码", required = false) - @QueryParam("page") - page: Int?, - @ApiParam("每页大小", required = false) - @QueryParam("pageSize") - pageSize: Int? - ): Result?> } diff --git a/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/api/user/UserPipelineTriggerEventResource.kt b/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/api/user/UserPipelineTriggerEventResource.kt new file mode 100644 index 00000000000..4231fd04dbc --- /dev/null +++ b/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/api/user/UserPipelineTriggerEventResource.kt @@ -0,0 +1,219 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package com.tencent.devops.process.api.user + +import com.tencent.devops.common.api.auth.AUTH_HEADER_USER_ID +import com.tencent.devops.common.api.auth.AUTH_HEADER_USER_ID_DEFAULT_VALUE +import com.tencent.devops.common.api.enums.ScmType +import com.tencent.devops.common.api.model.SQLPage +import com.tencent.devops.common.api.pojo.IdValue +import com.tencent.devops.common.api.pojo.Result +import com.tencent.devops.process.pojo.trigger.PipelineTriggerEventVo +import com.tencent.devops.process.pojo.trigger.RepoTriggerEventVo +import io.swagger.annotations.Api +import io.swagger.annotations.ApiOperation +import io.swagger.annotations.ApiParam +import javax.ws.rs.Consumes +import javax.ws.rs.GET +import javax.ws.rs.HeaderParam +import javax.ws.rs.POST +import javax.ws.rs.Path +import javax.ws.rs.PathParam +import javax.ws.rs.Produces +import javax.ws.rs.QueryParam +import javax.ws.rs.core.MediaType + +@Api(tags = ["USER_PIPELINE_TRIGGER_EVENT"], description = "用户-流水线触发事件") +@Path("/user/trigger/event") +@Produces(MediaType.APPLICATION_JSON) +@Consumes(MediaType.APPLICATION_JSON) +interface UserPipelineTriggerEventResource { + + @ApiOperation("获取触发类型") + @GET + @Path("listTriggerType") + fun listTriggerType( + @ApiParam(value = "用户ID", required = true, defaultValue = AUTH_HEADER_USER_ID_DEFAULT_VALUE) + @HeaderParam(AUTH_HEADER_USER_ID) + userId: String, + @ApiParam("代码库类型,为空则返回所有事件类型", required = false) + @QueryParam("scmType") + scmType: ScmType? + ): Result> + + @ApiOperation("获取事件类型") + @GET + @Path("listEventType") + fun listEventType( + @ApiParam(value = "用户ID", required = true, defaultValue = AUTH_HEADER_USER_ID_DEFAULT_VALUE) + @HeaderParam(AUTH_HEADER_USER_ID) + userId: String, + @ApiParam("代码库类型,为空则返回所有事件类型", required = false) + @QueryParam("scmType") + scmType: ScmType? + ): Result> + + @ApiOperation("获取流水线触发事件列表") + @GET + @Path("/{projectId}/{pipelineId}/listPipelineTriggerEvent") + fun listPipelineTriggerEvent( + @ApiParam(value = "用户ID", required = true, defaultValue = AUTH_HEADER_USER_ID_DEFAULT_VALUE) + @HeaderParam(AUTH_HEADER_USER_ID) + userId: String, + @ApiParam("项目ID", required = true) + @PathParam("projectId") + projectId: String, + @ApiParam("流水线ID", required = true) + @PathParam("pipelineId") + pipelineId: String, + @ApiParam("事件类型", required = false) + @QueryParam("eventType") + eventType: String?, + @ApiParam("触发类型", required = false) + @QueryParam("triggerType") + triggerType: String?, + @ApiParam("触发用户", required = false) + @QueryParam("triggerUser") + triggerUser: String?, + @ApiParam("开始时间", required = false) + @QueryParam("startTime") + startTime: Long?, + @ApiParam("结束", required = false) + @QueryParam("endTime") + endTime: Long?, + @ApiParam("第几页", required = false, defaultValue = "1") + @QueryParam("page") + page: Int?, + @ApiParam("每页多少条", required = false, defaultValue = "20") + @QueryParam("pageSize") + pageSize: Int? + ): Result> + + @ApiOperation("获取代码库webhook事件列表") + @GET + @Path("/{projectId}/{repoHashId}/listRepoTriggerEvent") + fun listRepoTriggerEvent( + @ApiParam(value = "用户ID", required = true, defaultValue = AUTH_HEADER_USER_ID_DEFAULT_VALUE) + @HeaderParam(AUTH_HEADER_USER_ID) + userId: String, + @ApiParam("项目ID", required = true) + @PathParam("projectId") + projectId: String, + @ApiParam("代码库hashId", required = true) + @PathParam("repoHashId") + repoHashId: String, + @ApiParam("事件类型", required = false) + @QueryParam("eventType") + eventType: String?, + @ApiParam("触发类型", required = false) + @QueryParam("triggerType") + triggerType: String?, + @ApiParam("触发用户", required = false) + @QueryParam("triggerUser") + triggerUser: String?, + @ApiParam("流水线ID", required = false) + @QueryParam("pipelineId") + pipelineId: String?, + @ApiParam("事件ID", required = false) + @QueryParam("eventId") + eventId: Long?, + @ApiParam("流水线名称", required = false) + @QueryParam("pipelineName") + pipelineName: String?, + @ApiParam("开始时间", required = false) + @QueryParam("startTime") + startTime: Long?, + @ApiParam("结束", required = false) + @QueryParam("endTime") + endTime: Long?, + @ApiParam("第几页", required = false, defaultValue = "1") + @QueryParam("page") + page: Int?, + @ApiParam("每页多少条", required = false, defaultValue = "20") + @QueryParam("pageSize") + pageSize: Int? + ): Result> + + @ApiOperation("获取触发事件详情") + @GET + @Path("/{projectId}/{eventId}/listEventDetail") + fun listEventDetail( + @ApiParam(value = "用户ID", required = true, defaultValue = AUTH_HEADER_USER_ID_DEFAULT_VALUE) + @HeaderParam(AUTH_HEADER_USER_ID) + userId: String, + @ApiParam("项目ID", required = true) + @PathParam("projectId") + projectId: String, + @ApiParam("事件ID", required = true) + @PathParam("eventId") + eventId: Long, + @ApiParam("流水线ID", required = false) + @QueryParam("pipelineId") + pipelineId: String?, + @ApiParam("流水线名", required = false) + @QueryParam("pipelineName") + pipelineName: String?, + @ApiParam("第几页", required = false, defaultValue = "1") + @QueryParam("page") + page: Int?, + @ApiParam("每页多少条", required = false, defaultValue = "20") + @QueryParam("pageSize") + pageSize: Int? + ): Result> + + @ApiOperation("重新触发") + @POST + @Path("/{projectId}/{detailId}/replay") + fun replay( + @ApiParam(value = "用户ID", required = true, defaultValue = AUTH_HEADER_USER_ID_DEFAULT_VALUE) + @HeaderParam(AUTH_HEADER_USER_ID) + userId: String, + @ApiParam("项目ID", required = true) + @PathParam("projectId") + projectId: String, + @ApiParam("触发详情ID", required = true) + @PathParam("detailId") + detailId: Long + ): Result + + @ApiOperation("一键重新触发") + @POST + @Path("/{projectId}/{eventId}/replayAll") + fun replayAll( + @ApiParam(value = "用户ID", required = true, defaultValue = AUTH_HEADER_USER_ID_DEFAULT_VALUE) + @HeaderParam(AUTH_HEADER_USER_ID) + userId: String, + @ApiParam("项目ID", required = true) + @PathParam("projectId") + projectId: String, + @ApiParam("事件ID", required = true) + @PathParam("eventId") + eventId: Long + ): Result +} diff --git a/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/api/user/UserScmWebhookResource.kt b/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/api/user/UserScmWebhookResource.kt index 7d055f011b4..f1a3eb3f3cc 100644 --- a/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/api/user/UserScmWebhookResource.kt +++ b/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/api/user/UserScmWebhookResource.kt @@ -28,10 +28,8 @@ package com.tencent.devops.process.api.user import com.tencent.devops.common.api.auth.AUTH_HEADER_USER_ID -import com.tencent.devops.common.api.model.SQLPage import com.tencent.devops.common.api.pojo.Result import com.tencent.devops.process.pojo.webhook.PipelineWebhook -import com.tencent.devops.process.pojo.webhook.PipelineWebhookBuildLogDetail import com.tencent.devops.process.pojo.webhook.WebhookEventType import io.swagger.annotations.Api import io.swagger.annotations.ApiOperation @@ -39,7 +37,6 @@ import io.swagger.annotations.ApiParam import javax.ws.rs.Consumes import javax.ws.rs.GET import javax.ws.rs.HeaderParam -import javax.ws.rs.PUT import javax.ws.rs.Path import javax.ws.rs.PathParam import javax.ws.rs.Produces @@ -51,12 +48,6 @@ import javax.ws.rs.core.MediaType @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) interface UserScmWebhookResource { - - @ApiOperation("更新所有的webhook项目名") - @PUT - @Path("/updateProjectNameAndTaskId") - fun updateProjectNameAndTaskId(): Result - @ApiOperation("根据代码库类型获取事件") @GET @Path("/eventType") @@ -83,29 +74,4 @@ interface UserScmWebhookResource { @QueryParam("pageSize") pageSize: Int? ): Result> - - @ApiOperation("获取流水线的webhook构建日志列表") - @GET - @Path("/{projectId}/{pipelineId}/buildLog") - @Suppress("ALL") - fun listPipelineWebhookBuildLog( - @HeaderParam(AUTH_HEADER_USER_ID) - userId: String, - @PathParam("projectId") - projectId: String, - @PathParam("pipelineId") - pipelineId: String, - @ApiParam("仓库名", required = false) - @QueryParam("repoName") - repoName: String?, - @ApiParam("commitId", required = false) - @QueryParam("commitId") - commitId: String?, - @ApiParam("页码", required = false) - @QueryParam("page") - page: Int?, - @ApiParam("每页大小", required = false) - @QueryParam("pageSize") - pageSize: Int? - ): Result?> } diff --git a/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/constant/ProcessMessageCode.kt b/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/constant/ProcessMessageCode.kt index 32b52981641..c30f2eae3b8 100644 --- a/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/constant/ProcessMessageCode.kt +++ b/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/constant/ProcessMessageCode.kt @@ -282,6 +282,12 @@ object ProcessMessageCode { const val GROUP_IS_EXIST = "2101181" // 分组({0})已存在/group ({0}) is already exist const val GROUP_LABEL_IS_EXIST = "2101182" // 分组标签({0})已存在/group label ({0}) is already exist + const val ERROR_TRIGGER_DETAIL_NOT_FOUND = "2101181" // 触发详情{0}不存在 + const val ERROR_TRIGGER_EVENT_NOT_FOUND = "2101182" // 触发事件{0}不存在 + const val ERROR_TRIGGER_TYPE_REPLAY_NOT_SUPPORT = "2101183" // 触发类型{0}不支持重放 + const val ERROR_TRIGGER_REPLAY_PIPELINE_NOT_EMPTY = "2101184" // 重放流水线ID不能为空 + const val ERROR_WEBHOOK_REQUEST_NOT_FOUND = "2101185" // webhook {0} 不存在 + const val BK_SUCCESSFULLY_DISTRIBUTED = "bkSuccessfullyDistributed" // 跨项目构件分发成功,共分发了{0}个文件 const val BK_SUCCESSFULLY_FAILED = "bkSuccessfullyFailed" // 跨项目构件分发失败, const val BK_NO_MATCH_FILE_DISTRIBUTE = "bkNoMatchFileDistribute" // 匹配不到待分发的文件: {0} diff --git a/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/pojo/BuildId.kt b/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/pojo/BuildId.kt index 6dcc0eb0313..f0fa23644af 100644 --- a/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/pojo/BuildId.kt +++ b/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/pojo/BuildId.kt @@ -39,5 +39,7 @@ data class BuildId( @ApiModelProperty("项目ID") val projectId: String? = null, @ApiModelProperty("流水线ID") - val pipelineId: String? = null + val pipelineId: String? = null, + @ApiModelProperty("构建编号") + val num: Int? = null ) diff --git a/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/pojo/trigger/PipelineTriggerDetail.kt b/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/pojo/trigger/PipelineTriggerDetail.kt new file mode 100644 index 00000000000..9329a4c2ad9 --- /dev/null +++ b/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/pojo/trigger/PipelineTriggerDetail.kt @@ -0,0 +1,57 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package com.tencent.devops.process.pojo.trigger + +import io.swagger.annotations.ApiModel +import io.swagger.annotations.ApiModelProperty + +@ApiModel("流水线触发详情") +data class PipelineTriggerDetail( + var detailId: Long? = null, + @ApiModelProperty("蓝盾项目ID") + val projectId: String, + @ApiModelProperty("事件ID") + val eventId: Long, + @ApiModelProperty("触发状态") + var status: String, + @ApiModelProperty("流水线Id") + var pipelineId: String? = null, + @ApiModelProperty("流水线名称") + var pipelineName: String? = null, + @ApiModelProperty("构建Id") + var buildId: String? = null, + @ApiModelProperty("构建编号") + var buildNum: String? = null, + @ApiModelProperty("原因") + var reason: String? = null, + @ApiModelProperty("原因详情", required = false) + var reasonDetailList: List? = null, + @ApiModelProperty("创建时间", required = false) + val createTime: Long? = null +) diff --git a/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/pojo/trigger/PipelineTriggerDetailBuilder.kt b/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/pojo/trigger/PipelineTriggerDetailBuilder.kt new file mode 100644 index 00000000000..3ec63a19676 --- /dev/null +++ b/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/pojo/trigger/PipelineTriggerDetailBuilder.kt @@ -0,0 +1,102 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package com.tencent.devops.process.pojo.trigger + +class PipelineTriggerDetailBuilder { + private lateinit var projectId: String + private var eventId: Long? = null + private var eventSource: String? = null + private var status: String = "" + private var pipelineId: String? = null + private var pipelineName: String? = null + private var buildId: String? = null + private var buildNum: String? = null + private var reason: String? = null + private var reasonDetailList: MutableList? = null + + fun projectId(projectId: String) = apply { + this.projectId = projectId + } + + fun eventId(eventId: Long) = apply { + this.eventId = eventId + } + + fun pipelineId(pipelineId: String) = apply { + this.pipelineId = pipelineId + } + + fun pipelineName(pipelineName: String) = apply { + this.pipelineName = pipelineName + } + + fun eventSource(eventSource: String) = apply { + this.eventSource = eventSource + } + + fun getEventSource() = eventSource + + fun status(status: String) = apply { + this.status = status + } + + fun buildId(buildId: String) = apply { + this.buildId = buildId + } + + fun reason(reason: String) = apply { + this.reason = reason + } + + fun reasonDetail(reasonDetail: String) = apply { + if (reasonDetailList == null) { + reasonDetailList = mutableListOf(reasonDetail) + } else { + reasonDetailList!!.add(reasonDetail) + } + } + + fun buildNum(buildNum: String) = apply { + this.buildNum = buildNum + } + + fun build(): PipelineTriggerDetail { + return PipelineTriggerDetail( + projectId = projectId, + eventId = eventId!!, + status = status, + pipelineId = pipelineId, + pipelineName = pipelineName, + buildId = buildId, + buildNum = buildNum, + reason = reason, + reasonDetailList = reasonDetailList + ) + } +} diff --git a/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/pojo/trigger/PipelineTriggerEvent.kt b/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/pojo/trigger/PipelineTriggerEvent.kt new file mode 100644 index 00000000000..66097b779e3 --- /dev/null +++ b/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/pojo/trigger/PipelineTriggerEvent.kt @@ -0,0 +1,59 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package com.tencent.devops.process.pojo.trigger + +import io.swagger.annotations.ApiModel +import io.swagger.annotations.ApiModelProperty +import java.time.LocalDateTime + +@ApiModel("流水线触发事件") +data class PipelineTriggerEvent( + @ApiModelProperty("请求ID") + val requestId: String, + @ApiModelProperty("项目ID") + var projectId: String? = null, + @ApiModelProperty("事件ID") + var eventId: Long? = null, + @ApiModelProperty("触发类型") + val triggerType: String, + @ApiModelProperty("事件源", required = false) + var eventSource: String? = null, + @ApiModelProperty("事件类型") + val eventType: String, + @ApiModelProperty("触发人") + val triggerUser: String, + @ApiModelProperty("事件描述") + val eventDesc: String, + @ApiModelProperty("重放事件ID") + val replayRequestId: String? = null, + @ApiModelProperty("事件请求参数, 记录手动/openapi/定时/远程触发启动参数") + val requestParams: Map? = null, + @ApiModelProperty("触发时间") + val createTime: LocalDateTime +) diff --git a/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/pojo/trigger/PipelineTriggerEventBuilder.kt b/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/pojo/trigger/PipelineTriggerEventBuilder.kt new file mode 100644 index 00000000000..42f9081661c --- /dev/null +++ b/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/pojo/trigger/PipelineTriggerEventBuilder.kt @@ -0,0 +1,99 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package com.tencent.devops.process.pojo.trigger + +import java.time.LocalDateTime + +class PipelineTriggerEventBuilder { + private var requestId: String? = null + private var projectId: String? = null + private var eventId: Long? = null + private var triggerType: String? = null + private var eventSource: String? = null + private var eventType: String? = null + private var triggerUser: String? = null + private var eventDesc: String? = null + private var requestParams: Map? = null + private var createTime: LocalDateTime? = null + + fun requestId(requestId: String) = apply { + this.requestId = requestId + } + + fun projectId(projectId: String) = apply { + this.projectId = projectId + } + + fun eventId(eventId: Long) = apply { + this.eventId = eventId + } + + fun triggerType(triggerType: String) = apply { + this.triggerType = triggerType + } + + fun eventSource(eventSource: String) = apply { + this.eventSource = eventSource + } + + fun eventType(eventType: String) = apply { + this.eventType = eventType + } + + fun triggerUser(triggerUser: String) = apply { + this.triggerUser = triggerUser + } + + fun eventDesc(eventDesc: String) = apply { + this.eventDesc = eventDesc + } + + fun requestParams(requestParams: Map) = apply { + this.requestParams = requestParams + } + + fun createTime(createTime: LocalDateTime) = apply { + this.createTime = createTime + } + + fun build(): PipelineTriggerEvent { + return PipelineTriggerEvent( + requestId = requestId!!, + projectId = projectId, + eventId = eventId, + triggerType = triggerType!!, + eventSource = eventSource!!, + eventType = eventType!!, + triggerUser = triggerUser!!, + eventDesc = eventDesc!!, + requestParams = requestParams, + createTime = createTime!! + ) + } +} diff --git a/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/pojo/trigger/PipelineTriggerEventVo.kt b/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/pojo/trigger/PipelineTriggerEventVo.kt new file mode 100644 index 00000000000..edefbcdb43c --- /dev/null +++ b/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/pojo/trigger/PipelineTriggerEventVo.kt @@ -0,0 +1,68 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package com.tencent.devops.process.pojo.trigger + +import io.swagger.annotations.ApiModelProperty + +data class PipelineTriggerEventVo( + @ApiModelProperty("事件明细ID") + var detailId: Long, + @ApiModelProperty("蓝盾项目ID") + val projectId: String, + @ApiModelProperty("事件ID") + val eventId: Long, + @ApiModelProperty("触发类型") + val triggerType: String, + @ApiModelProperty("事件触发源,代码库触发-代码库ID", required = false) + val eventSource: String? = "", + @ApiModelProperty("事件类型") + val eventType: String, + @ApiModelProperty("触发人") + val triggerUser: String, + @ApiModelProperty("事件描述") + var eventDesc: String, + @ApiModelProperty("事件时间") + val eventTime: Long, + @ApiModelProperty("触发状态") + var status: String, + @ApiModelProperty("流水线Id") + var pipelineId: String? = null, + @ApiModelProperty("流水线名称") + var pipelineName: String? = null, + @ApiModelProperty("构建Id") + var buildId: String? = null, + @ApiModelProperty("构建编号") + var buildNum: String? = null, + @ApiModelProperty("原因") + var reason: String? = null, + @ApiModelProperty("失败原因详情", required = false) + var reasonDetailList: List? = null, + @ApiModelProperty("失败原因", required = false) + var failReason: String = "" +) diff --git a/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/pojo/trigger/PipelineTriggerReason.kt b/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/pojo/trigger/PipelineTriggerReason.kt new file mode 100644 index 00000000000..765328ecc43 --- /dev/null +++ b/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/pojo/trigger/PipelineTriggerReason.kt @@ -0,0 +1,35 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package com.tencent.devops.process.pojo.trigger + +enum class PipelineTriggerReason(val detail: String) { + TRIGGER_SUCCESS("Trigger success"), + TRIGGER_FAILED("Trigger failed"), + TRIGGER_NOT_MATCH("Does not meet the trigger condition :%s") +} diff --git a/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/pojo/trigger/PipelineTriggerReasonDetail.kt b/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/pojo/trigger/PipelineTriggerReasonDetail.kt new file mode 100644 index 00000000000..08916fcbb0f --- /dev/null +++ b/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/pojo/trigger/PipelineTriggerReasonDetail.kt @@ -0,0 +1,44 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package com.tencent.devops.process.pojo.trigger + +import io.swagger.annotations.ApiModel +import io.swagger.annotations.ApiModelProperty + +@ApiModel("流水线触发原因详情") +data class PipelineTriggerReasonDetail( + @ApiModelProperty("触发插件ID") + val elementId: String?, + @ApiModelProperty("触发插件Code") + val elementAtomCode: String, + @ApiModelProperty("触发插件名称") + val elementName: String, + @ApiModelProperty("触发原因,JSON字符串,便于国际化") + val reasonMsg: String +) diff --git a/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/pojo/trigger/PipelineTriggerStatus.kt b/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/pojo/trigger/PipelineTriggerStatus.kt new file mode 100644 index 00000000000..aaa77a02dc1 --- /dev/null +++ b/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/pojo/trigger/PipelineTriggerStatus.kt @@ -0,0 +1,34 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package com.tencent.devops.process.pojo.trigger + +enum class PipelineTriggerStatus { + SUCCEED, + FAILED +} diff --git a/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/pojo/trigger/PipelineTriggerType.kt b/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/pojo/trigger/PipelineTriggerType.kt new file mode 100644 index 00000000000..6f91d5ed6f9 --- /dev/null +++ b/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/pojo/trigger/PipelineTriggerType.kt @@ -0,0 +1,113 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.devops.process.pojo.trigger + +import com.tencent.devops.common.api.enums.ScmType +import com.tencent.devops.common.api.pojo.IdValue +import com.tencent.devops.common.web.utils.I18nUtil +import io.swagger.annotations.ApiModel +import io.swagger.annotations.ApiModelProperty + +@Suppress("IMPLICIT_CAST_TO_ANY") +@ApiModel("流水线触发类型") +enum class PipelineTriggerType { + // WEB_HOOK 触发 + @ApiModelProperty("SVN 代码库") + CODE_SVN, + + @ApiModelProperty("GIT 代码库") + CODE_GIT, + + @ApiModelProperty("Gitlab 代码库") + CODE_GITLAB, + + @ApiModelProperty("Github 代码库") + GITHUB, + + @ApiModelProperty("TGIT 代码库") + CODE_TGIT, + + @ApiModelProperty("P4 代码库") + CODE_P4, + + // 手动触发 + @ApiModelProperty("手动触发") + MANUAL, + + // 定时触发 + @ApiModelProperty("定时触发") + TIME_TRIGGER, + + // 服务触发 + @ApiModelProperty("服务触发") + OPENAPI, + + // 流水线触发 + @ApiModelProperty("流水线触发") + PIPELINE, + + // 远程触发 + @ApiModelProperty("远程触发") + REMOTE; + + companion object { + // 通用触发类型 + private val commonTriggerTypes = listOf(MANUAL, TIME_TRIGGER, REMOTE) + + fun toMap( + scmType: ScmType?, + userId: String + ): List { + val triggerTypes = if (scmType == null) { + PipelineTriggerType.values().toList() + } else { + PipelineTriggerType.values().filter { + scmType.name == it.name + }.plus(commonTriggerTypes) + } + return triggerTypes.map { + IdValue( + id = it.name, + value = I18nUtil.getCodeLanMessage( + messageCode = "TRIGGER_TYPE_${it.name}", + defaultMessage = it.name, + language = I18nUtil.getLanguage(userId) + ) + ) + } + } + + fun toScmType(triggerType: String): ScmType? { + return if (ScmType.values().map { it.name }.contains(triggerType)) { + ScmType.valueOf(triggerType) + } else { + null + } + } + } +} diff --git a/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/pojo/trigger/RepoTriggerEventDetail.kt b/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/pojo/trigger/RepoTriggerEventDetail.kt new file mode 100644 index 00000000000..ef62458a716 --- /dev/null +++ b/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/pojo/trigger/RepoTriggerEventDetail.kt @@ -0,0 +1,44 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package com.tencent.devops.process.pojo.trigger + +import io.swagger.annotations.ApiModel +import io.swagger.annotations.ApiModelProperty + +@ApiModel("代码库webhook事件记录") +data class RepoTriggerEventDetail( + @ApiModelProperty("项目ID") + val projectId: String, + @ApiModelProperty("事件ID") + val eventId: Long, + @ApiModelProperty("总流水线数") + val total: Int, + @ApiModelProperty("成功的流水线数") + val success: Int +) diff --git a/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/pojo/trigger/RepoTriggerEventVo.kt b/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/pojo/trigger/RepoTriggerEventVo.kt new file mode 100644 index 00000000000..26665410833 --- /dev/null +++ b/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/pojo/trigger/RepoTriggerEventVo.kt @@ -0,0 +1,50 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package com.tencent.devops.process.pojo.trigger + +import io.swagger.annotations.ApiModel +import io.swagger.annotations.ApiModelProperty + +@ApiModel("代码库webhook事件记录") +data class RepoTriggerEventVo( + @ApiModelProperty("项目ID") + val projectId: String, + @ApiModelProperty("事件ID") + val eventId: Long, + @ApiModelProperty("代码库ID", required = false) + val repoHashId: String, + @ApiModelProperty("事件描述") + var eventDesc: String, + @ApiModelProperty("触发时间") + val eventTime: Long, + @ApiModelProperty("总流水线数") + val total: Int, + @ApiModelProperty("成功的流水线数") + val success: Int +) diff --git a/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/pojo/webhook/PipelineWebhook.kt b/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/pojo/webhook/PipelineWebhook.kt index 5b4968f00d2..609b2d58ec9 100644 --- a/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/pojo/webhook/PipelineWebhook.kt +++ b/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/pojo/webhook/PipelineWebhook.kt @@ -42,8 +42,8 @@ data class PipelineWebhook( val repositoryType: ScmType, @ApiModelProperty("代码库标识类型, ID 代码库HashId / NAME 别名", required = false) val repoType: RepositoryType?, - @ApiModelProperty("代码库HashId,repoHashId 与 repoName 不能同时为空,如果两个都不为空就用repoName", required = false) - val repoHashId: String?, // repoHashId 与 repoName 不能同时为空,如果两个都不为空就用repoName + @ApiModelProperty("插件配置的代码库HashId,repoHashId与repoName 不能同时为空,如果两个都不为空就用repoName", required = false) + var repoHashId: String?, // repoHashId 与 repoName 不能同时为空,如果两个都不为空就用repoName @ApiModelProperty("代码库别名", required = false) val repoName: String?, @ApiModelProperty("代码库自增ID,唯一", required = false) @@ -51,5 +51,11 @@ data class PipelineWebhook( @ApiModelProperty("项目名称", required = false) var projectName: String? = null, @ApiModelProperty("拉取当前代码库所在的插件ID", required = false) - val taskId: String? = null + val taskId: String? = null, + @ApiModelProperty("事件类型", required = false) + var eventType: String? = null, + @ApiModelProperty("代码库hashId,插件配置解析后的代码库ID", required = false) + var repositoryHashId: String? = null, + @ApiModelProperty("事件源外联Id", required = false) + var externalId: String? = null ) diff --git a/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/pojo/webhook/PipelineWebhookBuildLog.kt b/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/pojo/webhook/PipelineWebhookBuildLog.kt deleted file mode 100644 index f2cc63365f0..00000000000 --- a/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/pojo/webhook/PipelineWebhookBuildLog.kt +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. - * - * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. - * - * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. - * - * A copy of the MIT License is included in this file. - * - * - * Terms of the MIT License: - * --------------------------------------------------- - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated - * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or substantial portions of - * the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT - * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN - * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -package com.tencent.devops.process.pojo.webhook - -import io.swagger.annotations.ApiModel -import io.swagger.annotations.ApiModelProperty - -@ApiModel("流水线webhook-触发日志") -data class PipelineWebhookBuildLog( - val id: Long? = null, - @ApiModelProperty("代码库类型", required = true) - val codeType: String, - @ApiModelProperty("仓库名", required = true) - val repoName: String? = null, - @ApiModelProperty("commitId", required = true) - val commitId: String? = null, - @ApiModelProperty("事件内容", required = true) - val requestContent: String, - @ApiModelProperty("接受请求时间", required = true) - val receivedTime: Long, - @ApiModelProperty("完成时间", required = true) - var finishedTime: Long? = null, - val createdTime: Long, - @ApiModelProperty("触发构建日志详情", required = true) - val detail: MutableList = mutableListOf() -) - -@ApiModel("流水线webhook-触发日志明细") -data class PipelineWebhookBuildLogDetail( - val id: Long? = null, - val logId: Long? = null, - @ApiModelProperty("代码库类型", required = true) - val codeType: String, - @ApiModelProperty("仓库名", required = true) - val repoName: String, - @ApiModelProperty("commitId", required = true) - val commitId: String, - @ApiModelProperty("项目ID", required = true) - val projectId: String, - @ApiModelProperty("流水线ID", required = true) - val pipelineId: String, - @ApiModelProperty("插件ID", required = true) - val taskId: String, - @ApiModelProperty("插件名", required = true) - val taskName: String, - @ApiModelProperty("是否成功触发", required = true) - val success: Boolean, - @ApiModelProperty("触发结果,如果触发成功就是buildId,触发不成功就是不成功原因", required = true) - val triggerResult: String?, - val createdTime: Long -) diff --git a/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/pojo/webhook/WebhookTriggerPipeline.kt b/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/pojo/webhook/WebhookTriggerPipeline.kt new file mode 100644 index 00000000000..4c5a6530126 --- /dev/null +++ b/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/pojo/webhook/WebhookTriggerPipeline.kt @@ -0,0 +1,35 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package com.tencent.devops.process.pojo.webhook + +data class WebhookTriggerPipeline( + val projectId: String, + val pipelineId: String, + val version: Int? = null +) diff --git a/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/utils/Constants.kt b/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/utils/Constants.kt index 2de3db01658..fc066eae3c6 100644 --- a/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/utils/Constants.kt +++ b/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/utils/Constants.kt @@ -30,6 +30,7 @@ package com.tencent.devops.process.utils const val PIPELINE_VERSION = "BK_CI_PIPELINE_VERSION" // "pipeline.version" const val PIPELINE_START_PARENT_PROJECT_ID = "BK_CI_PARENT_PROJECT_ID" const val PIPELINE_START_PARENT_PIPELINE_ID = "BK_CI_PARENT_PIPELINE_ID" // "pipeline.start.parent.pipeline.id" +const val PIPELINE_START_PARENT_PIPELINE_NAME = "BK_CI_PARENT_PIPELINE_NAME" const val PIPELINE_START_PARENT_BUILD_ID = "BK_CI_PARENT_BUILD_ID" // "pipeline.start.parent.build.id" const val PIPELINE_START_PARENT_BUILD_TASK_ID = "BK_CI_PARENT_BUILD_TASK_ID" // "pipeline.start.parent.build.task.id" const val PIPELINE_START_USER_ID = "BK_CI_START_USER_ID" // "pipeline.start.user.id" @@ -40,6 +41,7 @@ const val PIPELINE_START_SERVICE_USER_ID = "BK_CI_START_SERVICE_USER_ID" // "pip const val PIPELINE_START_MANUAL_USER_ID = "BK_CI_START_MANUAL_USER_ID" // "pipeline.start.manual.user.id" const val PIPELINE_START_TIME_TRIGGER_USER_ID = "BK_CI_START_TIME_TRIGGER_USER_ID" const val PIPELINE_START_REMOTE_USER_ID = "BK_CI_START_REMOTE_USER_ID" +const val PIPELINE_START_REMOTE_CLIENT_IP = "BK_CI_START_REMOTE_CLIENT_IP" const val PIPELINE_START_TYPE = "BK_CI_START_TYPE" // "pipeline.start.type" const val PIPELINE_START_CHANNEL = "BK_CI_START_CHANNEL" // "pipeline.start.channel" const val PIPELINE_BUILD_NUM = "BK_CI_BUILD_NUM" // "pipeline.build.num"// 当前构建的唯一标示ID,从1开始自增 diff --git a/src/backend/ci/core/process/biz-base/src/main/kotlin/com/tencent/devops/process/engine/dao/PipelineWebhookDao.kt b/src/backend/ci/core/process/biz-base/src/main/kotlin/com/tencent/devops/process/engine/dao/PipelineWebhookDao.kt index 52f9ccc5f76..0b30adf76e1 100644 --- a/src/backend/ci/core/process/biz-base/src/main/kotlin/com/tencent/devops/process/engine/dao/PipelineWebhookDao.kt +++ b/src/backend/ci/core/process/biz-base/src/main/kotlin/com/tencent/devops/process/engine/dao/PipelineWebhookDao.kt @@ -32,8 +32,8 @@ import com.tencent.devops.common.api.enums.ScmType import com.tencent.devops.model.process.Tables.T_PIPELINE_WEBHOOK import com.tencent.devops.model.process.tables.records.TPipelineWebhookRecord import com.tencent.devops.process.pojo.webhook.PipelineWebhook +import com.tencent.devops.process.pojo.webhook.WebhookTriggerPipeline import org.jooq.DSLContext -import org.jooq.Record2 import org.jooq.Result import org.slf4j.LoggerFactory import org.springframework.stereotype.Repository @@ -55,7 +55,10 @@ class PipelineWebhookDao { REPO_HASH_ID, REPO_NAME, PROJECT_NAME, - TASK_ID + TASK_ID, + EVENT_TYPE, + REPOSITORY_HASH_ID, + EXTERNAL_ID ) .values( projectId, @@ -65,13 +68,19 @@ class PipelineWebhookDao { repoHashId, repoName, projectName, - taskId + taskId, + eventType, + repositoryHashId, + externalId ) .onDuplicateKeyUpdate() .set(REPO_TYPE, repoType?.name) .set(REPO_HASH_ID, repoHashId) .set(REPO_NAME, repoName) .set(PROJECT_NAME, projectName) + .set(EVENT_TYPE, eventType) + .set(REPOSITORY_HASH_ID, repositoryHashId) + .set(EXTERNAL_ID, externalId) .execute() } } @@ -151,14 +160,57 @@ class PipelineWebhookDao { dslContext: DSLContext, projectName: String, repositoryType: String - ): Result>? { + ): List? { with(T_PIPELINE_WEBHOOK) { return dslContext.select(PROJECT_ID, PIPELINE_ID).from(this) .where(PROJECT_NAME.eq(projectName)) .and(REPOSITORY_TYPE.eq(repositoryType)) .and(DELETE.eq(false)) .groupBy(PROJECT_ID, PIPELINE_ID) - .fetch() + .fetch().map { + WebhookTriggerPipeline( + projectId = it.value1(), + pipelineId = it.value2() + ) + } + } + } + + fun listTriggerPipeline( + dslContext: DSLContext, + projectId: String, + repositoryHashId: String, + eventType: String + ): List? { + with(T_PIPELINE_WEBHOOK) { + return dslContext.select(PROJECT_ID, PIPELINE_ID).from(this) + .where(PROJECT_ID.eq(projectId)) + .and(REPOSITORY_HASH_ID.eq(repositoryHashId)) + .and(EVENT_TYPE.eq(eventType)) + .and(DELETE.eq(false)) + .groupBy(PROJECT_ID, PIPELINE_ID) + .fetch().map { + WebhookTriggerPipeline( + projectId = it.value1(), + pipelineId = it.value2() + ) + } + } + } + + fun listWebhookPipeline( + dslContext: DSLContext, + projectName: String, + repositoryType: String, + eventType: String + ): List? { + with(T_PIPELINE_WEBHOOK) { + return dslContext.selectFrom(this) + .where(PROJECT_NAME.eq(projectName)) + .and(REPOSITORY_TYPE.eq(repositoryType)) + .and(EVENT_TYPE.eq(eventType)) + .and(DELETE.eq(false)) + .fetch().map { convert(it) } } } @@ -220,6 +272,45 @@ class PipelineWebhookDao { }?.map { convert(it) } } + fun listPipelines( + dslContext: DSLContext, + offset: Int, + limit: Int + ): List { + return with(T_PIPELINE_WEBHOOK) { + dslContext.select(PROJECT_ID, PIPELINE_ID).from(this) + .where(DELETE.eq(false)) + .limit(offset, limit) + .fetch().map { + WebhookTriggerPipeline( + projectId = it.value1(), + pipelineId = it.value2() + ) + } + } + } + + fun updateWebhookEventInfo( + dslContext: DSLContext, + repositoryHashId: String?, + eventType: String, + externalId: String?, + pipelineId: String, + projectId: String, + taskId: String + ) { + return with(T_PIPELINE_WEBHOOK) { + dslContext.update(this) + .set(REPOSITORY_HASH_ID, repositoryHashId) + .set(EVENT_TYPE, eventType) + .set(EXTERNAL_ID, externalId) + .where(PROJECT_ID.eq(projectId)) + .and(PIPELINE_ID.eq(pipelineId)) + .and(TASK_ID.eq(taskId)) + .execute() + } + } + companion object { private val logger = LoggerFactory.getLogger(PipelineWebhookDao::class.java) } diff --git a/src/backend/ci/core/process/biz-base/src/main/kotlin/com/tencent/devops/process/engine/service/PipelineRuntimeService.kt b/src/backend/ci/core/process/biz-base/src/main/kotlin/com/tencent/devops/process/engine/service/PipelineRuntimeService.kt index cfb9a5904d2..a796be96b3c 100644 --- a/src/backend/ci/core/process/biz-base/src/main/kotlin/com/tencent/devops/process/engine/service/PipelineRuntimeService.kt +++ b/src/backend/ci/core/process/biz-base/src/main/kotlin/com/tencent/devops/process/engine/service/PipelineRuntimeService.kt @@ -1014,7 +1014,8 @@ class PipelineRuntimeService @Autowired constructor( id = context.buildId, executeCount = context.executeCount, projectId = context.projectId, - pipelineId = context.pipelineId + pipelineId = context.pipelineId, + num = context.buildNum ) } diff --git a/src/backend/ci/core/process/biz-base/src/main/kotlin/com/tencent/devops/process/service/scm/ScmProxyService.kt b/src/backend/ci/core/process/biz-base/src/main/kotlin/com/tencent/devops/process/service/scm/ScmProxyService.kt index 3dd05a7884d..db5dad0b542 100644 --- a/src/backend/ci/core/process/biz-base/src/main/kotlin/com/tencent/devops/process/service/scm/ScmProxyService.kt +++ b/src/backend/ci/core/process/biz-base/src/main/kotlin/com/tencent/devops/process/service/scm/ScmProxyService.kt @@ -406,7 +406,11 @@ class ScmProxyService @Autowired constructor(private val client: Client) { } } - fun addGitWebhook(projectId: String, repositoryConfig: RepositoryConfig, codeEventType: CodeEventType?): String { + fun addGitWebhook( + projectId: String, + repositoryConfig: RepositoryConfig, + codeEventType: CodeEventType? + ): CodeGitRepository { checkRepoID(repositoryConfig) val repo = getRepo(projectId, repositoryConfig) as? CodeGitRepository ?: throw ErrorCodeException(errorCode = ProcessMessageCode.GIT_INVALID) @@ -445,10 +449,14 @@ class ScmProxyService @Autowired constructor(private val client: Client) { ) } - return repo.projectName + return repo } - fun addGitlabWebhook(projectId: String, repositoryConfig: RepositoryConfig, codeEventType: CodeEventType?): String { + fun addGitlabWebhook( + projectId: String, + repositoryConfig: RepositoryConfig, + codeEventType: CodeEventType? + ): Repository { checkRepoID(repositoryConfig) val repo = getRepo(projectId, repositoryConfig) as? CodeGitlabRepository ?: throw ErrorCodeException(errorCode = GITLAB_INVALID) @@ -464,10 +472,10 @@ class ScmProxyService @Autowired constructor(private val client: Client) { userName = repo.userName, event = convertEvent(codeEventType) ) - return repo.projectName + return repo } - fun addSvnWebhook(projectId: String, repositoryConfig: RepositoryConfig): String { + fun addSvnWebhook(projectId: String, repositoryConfig: RepositoryConfig): Repository { checkRepoID(repositoryConfig) val repo = getRepo(projectId, repositoryConfig) as? CodeSvnRepository ?: throw ErrorCodeException(errorCode = ProcessMessageCode.SVN_INVALID) @@ -483,10 +491,14 @@ class ScmProxyService @Autowired constructor(private val client: Client) { userName = credential.username, event = null ) - return repo.projectName + return repo } - fun addTGitWebhook(projectId: String, repositoryConfig: RepositoryConfig, codeEventType: CodeEventType?): String { + fun addTGitWebhook( + projectId: String, + repositoryConfig: RepositoryConfig, + codeEventType: CodeEventType? + ): Repository { checkRepoID(repositoryConfig) val repo = getRepo(projectId, repositoryConfig) as? CodeTGitRepository ?: throw ErrorCodeException(defaultMessage = "TGit", errorCode = ProcessMessageCode.TGIT_INVALID) @@ -517,7 +529,7 @@ class ScmProxyService @Autowired constructor(private val client: Client) { event = convertEvent(codeEventType) ) } - return repo.projectName + return repo } private fun convertEvent(codeEventType: CodeEventType?): String? { @@ -538,7 +550,7 @@ class ScmProxyService @Autowired constructor(private val client: Client) { projectId: String, repositoryConfig: RepositoryConfig, codeEventType: CodeEventType? - ): String { + ): Repository { checkRepoID(repositoryConfig) val repo = getRepo(projectId, repositoryConfig) as? CodeP4Repository ?: throw ErrorCodeException(errorCode = ProcessMessageCode.P4_INVALID) @@ -554,7 +566,7 @@ class ScmProxyService @Autowired constructor(private val client: Client) { userName = credential.username, event = codeEventType?.name ) - return repo.projectName + return repo } fun addGithubCheckRuns( diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/api/ServiceBuildResourceImpl.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/api/ServiceBuildResourceImpl.kt index 5db79ecf450..c3c3f19e6a9 100644 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/api/ServiceBuildResourceImpl.kt +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/api/ServiceBuildResourceImpl.kt @@ -43,7 +43,6 @@ import com.tencent.devops.common.pipeline.pojo.StageReviewRequest import com.tencent.devops.common.web.RestResource import com.tencent.devops.process.api.service.ServiceBuildResource import com.tencent.devops.process.engine.service.PipelineBuildDetailService -import com.tencent.devops.process.engine.service.PipelineContainerService import com.tencent.devops.process.engine.service.PipelineRuntimeService import com.tencent.devops.process.engine.service.vmbuild.EngineVMBuildService import com.tencent.devops.process.pojo.BuildBasicInfo @@ -73,8 +72,7 @@ class ServiceBuildResourceImpl @Autowired constructor( private val engineVMBuildService: EngineVMBuildService, private val pipelineBuildDetailService: PipelineBuildDetailService, private val pipelinePauseBuildFacadeService: PipelinePauseBuildFacadeService, - private val pipelineRuntimeService: PipelineRuntimeService, - private val pipelineContainerService: PipelineContainerService + private val pipelineRuntimeService: PipelineRuntimeService ) : ServiceBuildResource { override fun getPipelineIdFromBuildId(projectId: String, buildId: String): Result { if (buildId.isBlank()) { @@ -737,17 +735,17 @@ class ServiceBuildResourceImpl @Autowired constructor( checkUserId(userId) checkParam(projectId, pipelineId) return Result( - pipelineBuildFacadeService.buildManualStartup( - userId = userId, - startType = startType, - projectId = projectId, - pipelineId = pipelineId, - values = values, - channelCode = channelCode, - buildNo = buildNo, - checkPermission = ChannelCode.isNeedAuth(channelCode), - frequencyLimit = true - ) + pipelineBuildFacadeService.buildManualStartup( + userId = userId, + startType = startType, + projectId = projectId, + pipelineId = pipelineId, + values = values, + channelCode = channelCode, + buildNo = buildNo, + checkPermission = ChannelCode.isNeedAuth(channelCode), + frequencyLimit = true + ) ) } diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/api/ServiceScmWebhookResourceImpl.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/api/ServiceScmWebhookResourceImpl.kt index 5e126a76aea..45075f00109 100644 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/api/ServiceScmWebhookResourceImpl.kt +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/api/ServiceScmWebhookResourceImpl.kt @@ -27,16 +27,13 @@ package com.tencent.devops.process.api -import com.tencent.devops.common.api.model.SQLPage import com.tencent.devops.common.api.pojo.Result import com.tencent.devops.common.web.RestResource import com.tencent.devops.common.webhook.pojo.code.github.GithubWebhook import com.tencent.devops.process.api.service.ServiceScmWebhookResource -import com.tencent.devops.process.engine.service.PipelineWebhookBuildLogService import com.tencent.devops.process.engine.service.PipelineWebhookService import com.tencent.devops.process.pojo.code.WebhookCommit import com.tencent.devops.process.pojo.webhook.PipelineWebhook -import com.tencent.devops.process.pojo.webhook.PipelineWebhookBuildLogDetail import com.tencent.devops.process.service.webhook.PipelineBuildWebhookService import com.tencent.devops.process.webhook.CodeWebhookEventDispatcher import com.tencent.devops.process.webhook.pojo.event.commit.GithubWebhookEvent @@ -47,8 +44,7 @@ import org.springframework.beans.factory.annotation.Autowired class ServiceScmWebhookResourceImpl @Autowired constructor( private val pipelineBuildWebhookService: PipelineBuildWebhookService, private val rabbitTemplate: RabbitTemplate, - private val pipelineWebhookService: PipelineWebhookService, - private val pipelineWebhookBuildLogService: PipelineWebhookBuildLogService + private val pipelineWebhookService: PipelineWebhookService ) : ServiceScmWebhookResource { override fun webHookCodeGithubCommit(webhook: GithubWebhook): Result { return Result(CodeWebhookEventDispatcher.dispatchGithubEvent( @@ -78,27 +74,4 @@ class ServiceScmWebhookResourceImpl @Autowired constructor( ) ) } - - override fun listPipelineWebhookBuildLog( - userId: String, - projectId: String, - pipelineId: String, - repoName: String?, - commitId: String?, - page: Int?, - pageSize: Int? - ): Result?> { - return Result( - pipelineWebhookBuildLogService.listWebhookBuildLogDetail( - userId = userId, - projectId = projectId, - pipelineId = pipelineId, - repoName = repoName, - commitId = commitId, - page = page, - pageSize = pageSize - - ) - ) - } } diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/api/UserPipelineTriggerEventResourceImpl.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/api/UserPipelineTriggerEventResourceImpl.kt new file mode 100644 index 00000000000..821c977d656 --- /dev/null +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/api/UserPipelineTriggerEventResourceImpl.kt @@ -0,0 +1,189 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package com.tencent.devops.process.api + +import com.tencent.devops.common.api.enums.ScmType +import com.tencent.devops.common.api.model.SQLPage +import com.tencent.devops.common.api.pojo.IdValue +import com.tencent.devops.common.api.pojo.Result +import com.tencent.devops.common.pipeline.pojo.element.trigger.enums.CodeEventType +import com.tencent.devops.common.web.RestResource +import com.tencent.devops.common.web.utils.I18nUtil +import com.tencent.devops.process.api.user.UserPipelineTriggerEventResource +import com.tencent.devops.process.pojo.trigger.PipelineTriggerEventVo +import com.tencent.devops.process.pojo.trigger.PipelineTriggerType +import com.tencent.devops.process.pojo.trigger.RepoTriggerEventVo +import com.tencent.devops.process.trigger.PipelineTriggerEventService + +@RestResource +class UserPipelineTriggerEventResourceImpl( + private val pipelineTriggerEventService: PipelineTriggerEventService +) : UserPipelineTriggerEventResource { + + override fun listTriggerType( + userId: String, + scmType: ScmType? + ): Result> { + return Result( + PipelineTriggerType.toMap( + userId = userId, + scmType = scmType + ) + ) + } + + override fun listEventType( + userId: String, + scmType: ScmType? + ): Result> { + val eventTypes = CodeEventType.getEventsByScmType(scmType).map { + IdValue( + id = it.name, + value = I18nUtil.getCodeLanMessage( + messageCode = "${CodeEventType.MESSAGE_CODE_PREFIX}_${it.name}", + defaultMessage = it.name, + language = I18nUtil.getLanguage(userId) + ) + ) + } + return Result(eventTypes) + } + + override fun listPipelineTriggerEvent( + userId: String, + projectId: String, + pipelineId: String, + eventType: String?, + triggerType: String?, + triggerUser: String?, + startTime: Long?, + endTime: Long?, + page: Int?, + pageSize: Int? + ): Result> { + return Result( + pipelineTriggerEventService.listPipelineTriggerEvent( + userId = userId, + projectId = projectId, + pipelineId = pipelineId, + eventType = eventType, + triggerType = triggerType, + triggerUser = triggerUser, + startTime = startTime, + endTime = endTime, + page = page, + pageSize = pageSize + ) + ) + } + + override fun listRepoTriggerEvent( + userId: String, + projectId: String, + repoHashId: String, + eventType: String?, + triggerType: String?, + triggerUser: String?, + pipelineId: String?, + eventId: Long?, + pipelineName: String?, + startTime: Long?, + endTime: Long?, + page: Int?, + pageSize: Int? + ): Result> { + return Result( + pipelineTriggerEventService.listRepoTriggerEvent( + projectId = projectId, + repoHashId = repoHashId, + triggerType = triggerType, + eventType = eventType, + triggerUser = triggerUser, + pipelineId = pipelineId, + eventId = eventId, + pipelineName = pipelineName, + startTime = startTime, + endTime = endTime, + page = page, + pageSize = pageSize, + userId = userId + ) + ) + } + + override fun listEventDetail( + userId: String, + projectId: String, + eventId: Long, + pipelineId: String?, + pipelineName: String?, + page: Int?, + pageSize: Int? + ): Result> { + return Result( + pipelineTriggerEventService.listRepoTriggerEventDetail( + projectId = projectId, + eventId = eventId, + pipelineId = pipelineId, + pipelineName = pipelineName, + page = page, + pageSize = pageSize, + userId = userId + ) + ) + } + + override fun replay( + userId: String, + projectId: String, + detailId: Long + ): Result { + return Result( + pipelineTriggerEventService.replay( + userId = userId, + projectId = projectId, + detailId = detailId + ) + ) + } + + override fun replayAll( + userId: String, + projectId: String, + eventId: Long + ): Result { + return Result( + pipelineTriggerEventService.replayAll( + userId = userId, + projectId = projectId, + eventId = eventId + ) + ) + } +} diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/api/UserScmWebhookResourceImpl.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/api/UserScmWebhookResourceImpl.kt index c9a36036f35..c6ce6b19792 100644 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/api/UserScmWebhookResourceImpl.kt +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/api/UserScmWebhookResourceImpl.kt @@ -28,29 +28,19 @@ package com.tencent.devops.process.api import com.tencent.devops.common.api.enums.ScmType -import com.tencent.devops.common.api.model.SQLPage import com.tencent.devops.common.api.pojo.Result import com.tencent.devops.common.pipeline.pojo.element.trigger.enums.CodeEventType import com.tencent.devops.common.web.RestResource import com.tencent.devops.process.api.user.UserScmWebhookResource -import com.tencent.devops.process.engine.service.PipelineWebhookBuildLogService import com.tencent.devops.process.engine.service.PipelineWebhookService import com.tencent.devops.process.pojo.webhook.PipelineWebhook -import com.tencent.devops.process.pojo.webhook.PipelineWebhookBuildLogDetail import com.tencent.devops.process.pojo.webhook.WebhookEventType import org.springframework.beans.factory.annotation.Autowired @RestResource class UserScmWebhookResourceImpl @Autowired constructor( - private val pipelineWebhookService: PipelineWebhookService, - private val pipelineWebhookBuildLogService: PipelineWebhookBuildLogService + private val pipelineWebhookService: PipelineWebhookService ) : UserScmWebhookResource { - - override fun updateProjectNameAndTaskId(): Result { - pipelineWebhookService.updateProjectNameAndTaskId() - return Result(true) - } - override fun getEventType(scmType: String): Result> { val eventTypeList = when (scmType) { ScmType.CODE_GIT.name, ScmType.CODE_TGIT.name -> @@ -97,27 +87,4 @@ class UserScmWebhookResourceImpl @Autowired constructor( ) ) } - - override fun listPipelineWebhookBuildLog( - userId: String, - projectId: String, - pipelineId: String, - repoName: String?, - commitId: String?, - page: Int?, - pageSize: Int? - ): Result?> { - return Result( - pipelineWebhookBuildLogService.listWebhookBuildLogDetail( - userId = userId, - projectId = projectId, - pipelineId = pipelineId, - repoName = repoName, - commitId = commitId, - page = page, - pageSize = pageSize - - ) - ) - } } diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/api/external/ExternalScmResourceImpl.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/api/external/ExternalScmResourceImpl.kt index 164adc938c2..3f47a797617 100644 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/api/external/ExternalScmResourceImpl.kt +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/api/external/ExternalScmResourceImpl.kt @@ -60,17 +60,16 @@ class ExternalScmResourceImpl @Autowired constructor( secret: String?, traceId: String, body: String - ) = - Result( - CodeWebhookEventDispatcher.dispatchEvent( - rabbitTemplate = rabbitTemplate, - event = GitWebhookEvent( - requestContent = body, - event = event, - secret = secret - ) + ): Result = Result( + CodeWebhookEventDispatcher.dispatchEvent( + rabbitTemplate = rabbitTemplate, + event = GitWebhookEvent( + requestContent = body, + event = event, + secret = secret ) ) + ) override fun webHookGitlabCommit(event: String) = Result(CodeWebhookEventDispatcher.dispatchEvent(rabbitTemplate, GitlabWebhookEvent(requestContent = event))) diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/api/op/OpScmWebhookResourceImpl.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/api/op/OpScmWebhookResourceImpl.kt index a56f3c78539..41d954f348f 100644 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/api/op/OpScmWebhookResourceImpl.kt +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/api/op/OpScmWebhookResourceImpl.kt @@ -3,15 +3,25 @@ package com.tencent.devops.process.api.op import com.tencent.devops.common.api.enums.ScmType import com.tencent.devops.common.api.pojo.Result import com.tencent.devops.common.web.RestResource -import com.tencent.devops.process.engine.service.PipelineWebhookService +import com.tencent.devops.process.engine.service.PipelineWebhookUpgradeService @RestResource class OpScmWebhookResourceImpl( - private val pipelineWebhookService: PipelineWebhookService + private val pipelineWebhookUpgradeService: PipelineWebhookUpgradeService ) : OpScmWebhookResource { + override fun updateProjectNameAndTaskId(): Result { + pipelineWebhookUpgradeService.updateProjectNameAndTaskId() + return Result(true) + } + override fun updateWebhookSecret(scmType: String): Result { - pipelineWebhookService.updateWebhookSecret(ScmType.valueOf(scmType)) + pipelineWebhookUpgradeService.updateWebhookSecret(ScmType.valueOf(scmType)) + return Result(true) + } + + override fun updateWebhookEventInfo(): Result { + pipelineWebhookUpgradeService.updateWebhookEventInfo() return Result(true) } } diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/dao/PipelineTriggerEventDao.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/dao/PipelineTriggerEventDao.kt new file mode 100644 index 00000000000..934d49657e6 --- /dev/null +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/dao/PipelineTriggerEventDao.kt @@ -0,0 +1,635 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.devops.process.dao + +import com.fasterxml.jackson.core.type.TypeReference +import com.tencent.devops.common.api.pojo.I18Variable +import com.tencent.devops.common.api.util.JsonUtil +import com.tencent.devops.common.api.util.timestamp +import com.tencent.devops.common.api.util.timestampmilli +import com.tencent.devops.common.web.utils.I18nUtil.getCodeLanMessage +import com.tencent.devops.model.process.tables.TPipelineTriggerDetail +import com.tencent.devops.model.process.tables.TPipelineTriggerDetail.T_PIPELINE_TRIGGER_DETAIL +import com.tencent.devops.model.process.tables.TPipelineTriggerEvent +import com.tencent.devops.model.process.tables.TPipelineTriggerEvent.T_PIPELINE_TRIGGER_EVENT +import com.tencent.devops.model.process.tables.records.TPipelineTriggerDetailRecord +import com.tencent.devops.model.process.tables.records.TPipelineTriggerEventRecord +import com.tencent.devops.process.pojo.trigger.PipelineTriggerDetail +import com.tencent.devops.process.pojo.trigger.PipelineTriggerEvent +import com.tencent.devops.process.pojo.trigger.PipelineTriggerEventVo +import com.tencent.devops.process.pojo.trigger.PipelineTriggerStatus +import com.tencent.devops.process.pojo.trigger.RepoTriggerEventDetail +import org.jooq.Condition +import org.jooq.DSLContext +import org.jooq.Result +import org.jooq.impl.DSL.count +import org.jooq.impl.DSL.countDistinct +import org.jooq.impl.DSL.`when` +import org.springframework.stereotype.Repository +import java.sql.Timestamp +import java.time.LocalDateTime + +@Suppress("ALL") +@Repository +class PipelineTriggerEventDao { + + fun save( + dslContext: DSLContext, + triggerEvent: PipelineTriggerEvent + ) { + with(T_PIPELINE_TRIGGER_EVENT) { + dslContext.insertInto( + this, + REQUEST_ID, + PROJECT_ID, + EVENT_ID, + TRIGGER_TYPE, + EVENT_SOURCE, + EVENT_TYPE, + TRIGGER_USER, + EVENT_DESC, + REPLAY_REQUEST_ID, + REQUEST_PARAMS, + CREATE_TIME + ).values( + triggerEvent.requestId, + triggerEvent.projectId, + triggerEvent.eventId, + triggerEvent.triggerType, + triggerEvent.eventSource, + triggerEvent.eventType, + triggerEvent.triggerUser, + JsonUtil.toJson(triggerEvent.eventDesc), + triggerEvent.replayRequestId, + triggerEvent.requestParams?.let { JsonUtil.toJson(it) }, + triggerEvent.createTime + ).onDuplicateKeyIgnore().execute() + } + } + + fun saveDetail( + dslContext: DSLContext, + triggerDetail: PipelineTriggerDetail + ) { + with(T_PIPELINE_TRIGGER_DETAIL) { + dslContext.insertInto( + this, + DETAIL_ID, + PROJECT_ID, + EVENT_ID, + STATUS, + PIPELINE_ID, + PIPELINE_NAME, + BUILD_ID, + BUILD_NUM, + REASON, + REASON_DETAIL, + CREATE_TIME + ).values( + triggerDetail.detailId!!, + triggerDetail.projectId, + triggerDetail.eventId, + triggerDetail.status, + triggerDetail.pipelineId, + triggerDetail.pipelineName, + triggerDetail.buildId, + triggerDetail.buildNum, + triggerDetail.reason, + triggerDetail.reasonDetailList?.let { + JsonUtil.toJson(it) + }, + LocalDateTime.now() + ).execute() + } + } + + fun listTriggerDetail( + dslContext: DSLContext, + projectId: String, + eventId: Long? = null, + eventType: String? = null, + triggerType: String? = null, + triggerUser: String? = null, + pipelineId: String? = null, + pipelineName: String? = null, + startTime: Long? = null, + endTime: Long? = null, + limit: Int, + offset: Int + ): List { + val t1 = T_PIPELINE_TRIGGER_EVENT.`as`("t1") + val t2 = T_PIPELINE_TRIGGER_DETAIL.`as`("t2") + val conditions = buildConditions( + t1 = t1, + t2 = t2, + projectId = projectId, + eventId = eventId, + eventType = eventType, + triggerUser = triggerUser, + triggerType = triggerType, + pipelineId = pipelineId, + pipelineName = pipelineName, + startTime = startTime, + endTime = endTime + ) + return dslContext.select( + t2.DETAIL_ID, + t1.PROJECT_ID, + t1.EVENT_ID, + t1.TRIGGER_TYPE, + t1.EVENT_SOURCE, + t1.EVENT_TYPE, + t1.TRIGGER_USER, + t1.EVENT_DESC, + t1.CREATE_TIME, + t2.STATUS, + t2.PIPELINE_ID, + t2.PIPELINE_NAME, + t2.BUILD_ID, + t2.BUILD_NUM, + t2.REASON, + t2.REASON_DETAIL + ).from(t2).leftJoin(t1) + .on(t1.EVENT_ID.eq(t2.EVENT_ID)).and(t1.PROJECT_ID.eq(t2.PROJECT_ID)) + .where(conditions) + .orderBy(t1.CREATE_TIME.desc()).limit(limit) + .offset(offset) + .fetch().map { + PipelineTriggerEventVo( + detailId = it.value1(), + projectId = it.value2(), + eventId = it.value3(), + triggerType = it.value4(), + eventSource = it.value5(), + eventType = it.value6(), + triggerUser = it.value7(), + eventDesc = it.value8(), + eventTime = it.value9().timestampmilli(), + status = it.value10(), + pipelineId = it.value11(), + pipelineName = it.value12(), + buildId = it.value13(), + buildNum = it.value14(), + reason = it.value15(), + reasonDetailList = it.value16() + ?.let { r -> JsonUtil.to(r, object : TypeReference>() {}) } + ) + } + } + + fun countTriggerDetail( + dslContext: DSLContext, + projectId: String, + eventId: Long? = null, + eventType: String? = null, + triggerType: String? = null, + triggerUser: String? = null, + pipelineId: String? = null, + pipelineName: String? = null, + startTime: Long? = null, + endTime: Long? = null + ): Long { + val t1 = T_PIPELINE_TRIGGER_EVENT.`as`("t1") + val t2 = T_PIPELINE_TRIGGER_DETAIL.`as`("t2") + val conditions = buildConditions( + t1 = t1, + t2 = t2, + projectId = projectId, + eventId = eventId, + eventType = eventType, + triggerUser = triggerUser, + triggerType = triggerType, + pipelineId = pipelineId, + pipelineName = pipelineName, + startTime = startTime, + endTime = endTime + ) + return dslContext.selectCount().from(t2).leftJoin(t1) + .on(t1.EVENT_ID.eq(t2.EVENT_ID)).and(t1.PROJECT_ID.eq(t2.PROJECT_ID)) + .where(conditions) + .fetchOne(0, Long::class.java)!! + } + + fun listByEventIds( + dslContext: DSLContext, + eventIds: List + ): Result { + return with(T_PIPELINE_TRIGGER_EVENT) { + dslContext.selectFrom(this) + .where(EVENT_ID.`in`(eventIds)) + .fetch() + } + } + + fun getEventIdsByEvent( + dslContext: DSLContext, + eventId: Long? = null, + eventSource: String? = null, + projectId: String, + eventType: String? = null, + triggerType: String? = null, + triggerUser: String? = null, + startTime: Long? = null, + endTime: Long? = null, + limit: Int? = null, + offset: Int? = null + ): Set { + return with(T_PIPELINE_TRIGGER_EVENT) { + val step = dslContext + .selectFrom(this) + .where( + buildEventCondition( + this, + projectId = projectId, + eventSource = eventSource, + eventId = eventId, + eventType = eventType, + triggerUser = triggerUser, + triggerType = triggerType, + startTime = startTime, + endTime = endTime + ) + ) + .orderBy(CREATE_TIME.desc()) + if (limit != null) { + step.limit(limit) + } + if (offset != null) { + step.offset(offset) + } + step.fetch(EVENT_ID).toSet() + } + } + + fun getCountByEvent( + dslContext: DSLContext, + eventId: Long? = null, + eventSource: String? = null, + projectId: String, + eventType: String? = null, + triggerType: String? = null, + triggerUser: String? = null, + startTime: Long? = null, + endTime: Long? = null + ): Long { + return with(T_PIPELINE_TRIGGER_EVENT) { + dslContext.selectCount() + .from(this) + .where( + buildEventCondition( + this, + projectId = projectId, + eventSource = eventSource, + eventId = eventId, + eventType = eventType, + triggerUser = triggerUser, + triggerType = triggerType, + startTime = startTime, + endTime = endTime + ) + ).fetchOne(0, Long::class.java)!! + } + } + + fun getCountByDetail( + dslContext: DSLContext, + pipelineName: String?, + pipelineId: String?, + eventId: Long? = null, + eventSource: String? = null, + projectId: String, + eventType: String? = null, + triggerType: String? = null, + triggerUser: String? = null, + startTime: Long? = null, + endTime: Long? = null + ): Long { + val t1 = T_PIPELINE_TRIGGER_EVENT.`as`("t1") + val t2 = T_PIPELINE_TRIGGER_DETAIL.`as`("t2") + val conditions = buildConditions( + t1 = t1, + t2 = t2, + projectId = projectId, + eventSource = eventSource, + eventId = eventId, + eventType = eventType, + triggerUser = triggerUser, + triggerType = triggerType, + pipelineId = pipelineId, + pipelineName = pipelineName, + startTime = startTime, + endTime = endTime + ) + return dslContext.select(countDistinct(t2.EVENT_ID)) + .from(t2).leftJoin(t1) + .on(t1.EVENT_ID.eq(t2.EVENT_ID)).and(t1.PROJECT_ID.eq(t2.PROJECT_ID)) + .where(conditions) + .fetchOne(0, Long::class.java)!! + } + + fun getDetailEventIds( + dslContext: DSLContext, + pipelineName: String?, + pipelineId: String?, + eventId: Long? = null, + eventSource: String? = null, + projectId: String, + eventType: String? = null, + triggerType: String? = null, + triggerUser: String? = null, + startTime: Long? = null, + endTime: Long? = null, + limit: Int, + offset: Int + ): Set { + val t1 = T_PIPELINE_TRIGGER_EVENT.`as`("t1") + val t2 = T_PIPELINE_TRIGGER_DETAIL.`as`("t2") + val conditions = buildConditions( + t1 = t1, + t2 = t2, + projectId = projectId, + eventSource = eventSource, + eventId = eventId, + eventType = eventType, + triggerUser = triggerUser, + triggerType = triggerType, + pipelineId = pipelineId, + pipelineName = pipelineName, + startTime = startTime, + endTime = endTime + ) + return dslContext.select(t2.EVENT_ID) + .from(t2).leftJoin(t1) + .on(t1.EVENT_ID.eq(t2.EVENT_ID)).and(t1.PROJECT_ID.eq(t2.PROJECT_ID)) + .where(conditions) + .orderBy(t2.CREATE_TIME.desc()) + .limit(limit) + .offset(offset) + .fetch().distinct().map { it.value1() }.toSet() + } + + fun listRepoTriggerEvent( + dslContext: DSLContext, + eventIds: Set + ): List { + return with(T_PIPELINE_TRIGGER_EVENT) { + dslContext.selectFrom(this) + .where(EVENT_ID.`in`(eventIds)) + .orderBy(CREATE_TIME.desc()) + .fetch() + } + } + + fun listRepoTriggerDetail( + dslContext: DSLContext, + projectId: String, + eventIds: Set, + pipelineName: String?, + pipelineId: String? + ): List { + return with(T_PIPELINE_TRIGGER_DETAIL) { + val conditions = mutableListOf( + EVENT_ID.`in`(eventIds), + PROJECT_ID.eq(PROJECT_ID) + ) + if (!pipelineName.isNullOrBlank()) { + conditions.add(PIPELINE_NAME.like("%$pipelineName%")) + } + if (!pipelineId.isNullOrBlank()) { + conditions.add(PIPELINE_ID.eq(pipelineId)) + } + dslContext.select( + PROJECT_ID, + EVENT_ID, + count().`as`("total"), + count(`when`(STATUS.eq(PipelineTriggerStatus.SUCCEED.name), 1)) + ) + .from(this) + .where(conditions) + .groupBy(PROJECT_ID, EVENT_ID) + .fetch().map { + RepoTriggerEventDetail( + projectId = it.value1(), + eventId = it.value2(), + total = it.value3(), + success = it.value4() + ) + } + } + } + + fun getTriggerEvent( + dslContext: DSLContext, + projectId: String, + eventId: Long + ): PipelineTriggerEvent? { + val record = with(T_PIPELINE_TRIGGER_EVENT) { + dslContext.selectFrom(this) + .where(EVENT_ID.eq(eventId)) + .and(PROJECT_ID.eq(projectId)) + .fetchOne() + } + return record?.let { convertEvent(it) } + } + + fun getEventByRequestId( + dslContext: DSLContext, + projectId: String, + requestId: String, + eventSource: String + ): PipelineTriggerEvent? { + val record = with(T_PIPELINE_TRIGGER_EVENT) { + dslContext.selectFrom(this) + .where(PROJECT_ID.eq(projectId)) + .and(REQUEST_ID.eq(requestId)) + .and(EVENT_SOURCE.eq(eventSource)) + .fetchOne() + } + return record?.let { convertEvent(it) } + } + + fun getTriggerDetail( + dslContext: DSLContext, + projectId: String, + detailId: Long + ): PipelineTriggerDetail? { + val record = with(T_PIPELINE_TRIGGER_DETAIL) { + dslContext.selectFrom(this) + .where(DETAIL_ID.eq(detailId)) + .and(PROJECT_ID.eq(projectId)) + .fetchOne() + } + return record?.let { convertDetail(it) } + } + + private fun buildDetailCondition( + t2: TPipelineTriggerDetail, + eventId: Long? = null, + pipelineName: String? = null, + projectId: String, + pipelineId: String? = null + ): List { + val conditions = mutableListOf() + with(t2) { + if (eventId != null) { + conditions.add(EVENT_ID.eq(eventId)) + } + if (!pipelineName.isNullOrBlank()) { + conditions.add(PIPELINE_NAME.like("%$pipelineName%")) + } + if (projectId.isNotBlank()) { + conditions.add(PROJECT_ID.eq(projectId)) + } + if (!pipelineId.isNullOrBlank()) { + conditions.add(PIPELINE_ID.eq(pipelineId)) + } + } + return conditions + } + + private fun buildEventCondition( + t1: TPipelineTriggerEvent, + eventId: Long? = null, + eventSource: String? = null, + projectId: String, + eventType: String?, + triggerUser: String? = null, + triggerType: String? = null, + startTime: Long? = null, + endTime: Long? = null + ): List { + val conditions = mutableListOf() + with(t1) { + if (eventId != null) { + conditions.add(EVENT_ID.eq(eventId)) + } + if (!eventSource.isNullOrBlank()) { + conditions.add(EVENT_SOURCE.eq(eventSource)) + } + if (projectId.isNotBlank()) { + conditions.add(PROJECT_ID.eq(projectId)) + } + if (!eventType.isNullOrBlank()) { + conditions.add(EVENT_TYPE.eq(eventType)) + } + if (!triggerUser.isNullOrBlank()) { + conditions.add(TRIGGER_USER.eq(triggerUser)) + } + if (!triggerType.isNullOrBlank()) { + conditions.add(TRIGGER_TYPE.eq(triggerType)) + } + if (startTime != null) { + conditions.add(CREATE_TIME.ge(Timestamp(startTime).toLocalDateTime())) + } + if (endTime != null) { + conditions.add(CREATE_TIME.le(Timestamp(endTime).toLocalDateTime())) + } + } + return conditions + } + + private fun buildConditions( + t1: TPipelineTriggerEvent, + t2: TPipelineTriggerDetail, + projectId: String, + pipelineName: String? = null, + eventSource: String? = null, + eventId: Long? = null, + eventType: String? = null, + triggerUser: String? = null, + triggerType: String? = null, + pipelineId: String? = null, + startTime: Long? = null, + endTime: Long? = null + ): List { + val conditions = mutableListOf() + conditions.addAll( + buildEventCondition( + t1, + eventId = eventId, + eventSource = eventSource, + projectId = projectId, + eventType = eventType, + triggerType = triggerType, + triggerUser = triggerUser, + startTime = startTime, + endTime = endTime + ) + ) + conditions.addAll( + buildDetailCondition( + t2, + eventId = eventId, + projectId = projectId, + pipelineName = pipelineName, + pipelineId = pipelineId + ) + ) + return conditions + } + + fun convertEvent(record: TPipelineTriggerEventRecord): PipelineTriggerEvent { + return with(record) { + PipelineTriggerEvent( + requestId = requestId, + projectId = projectId, + eventId = eventId, + eventSource = eventSource, + triggerType = triggerType, + triggerUser = triggerUser, + eventType = eventType, + eventDesc = JsonUtil.to(eventDesc, I18Variable::class.java).getCodeLanMessage(), + replayRequestId = replayRequestId, + requestParams = requestParams?.let { + JsonUtil.to( + it, + object : TypeReference>() {}) + }, + createTime = createTime + ) + } + } + + fun convertDetail(record: TPipelineTriggerDetailRecord): PipelineTriggerDetail { + return with(record) { + PipelineTriggerDetail( + detailId = detailId, + projectId = projectId, + eventId = eventId, + status = status, + pipelineId = pipelineId, + pipelineName = pipelineName, + buildId = buildId, + buildNum = buildNum, + reason = reason, + reasonDetailList = reasonDetail?.let { JsonUtil.to(it, object : TypeReference>() {}) }, + createTime = createTime.timestamp() + ) + } + } +} diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/engine/dao/PipelineWebhookBuildLogDetailDao.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/engine/dao/PipelineWebhookBuildLogDetailDao.kt deleted file mode 100644 index f1610de3a67..00000000000 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/engine/dao/PipelineWebhookBuildLogDetailDao.kt +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. - * - * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. - * - * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. - * - * A copy of the MIT License is included in this file. - * - * - * Terms of the MIT License: - * --------------------------------------------------- - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated - * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or substantial portions of - * the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT - * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN - * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -package com.tencent.devops.process.engine.dao - -import com.tencent.devops.common.api.util.timestampmilli -import com.tencent.devops.model.process.Tables.T_PIPELINE_WEBHOOK_BUILD_LOG_DETAIL -import com.tencent.devops.model.process.tables.records.TPipelineWebhookBuildLogDetailRecord -import com.tencent.devops.process.pojo.webhook.PipelineWebhookBuildLogDetail -import org.jooq.DSLContext -import org.springframework.stereotype.Repository -import java.sql.Timestamp - -@Repository -@Suppress("ALL") -class PipelineWebhookBuildLogDetailDao { - - fun save( - dslContext: DSLContext, - logId: Long, - webhookBuildLogDetails: List - ) { - if (webhookBuildLogDetails.isEmpty()) { - return - } - webhookBuildLogDetails.map { - with(T_PIPELINE_WEBHOOK_BUILD_LOG_DETAIL) { - dslContext.insertInto( - this, - LOG_ID, - CODE_TYPE, - REPO_NAME, - COMMIT_ID, - PROJECT_ID, - PIPELINE_ID, - TASK_ID, - TASK_NAME, - SUCCESS, - TRIGGER_RESULT, - CREATED_TIME, - ID - ).values( - logId, - it.codeType, - it.repoName, - it.commitId, - it.projectId, - it.pipelineId, - it.taskId, - it.taskName, - it.success, - it.triggerResult, - Timestamp(it.createdTime).toLocalDateTime(), - it.id - ).execute() - } - } - } - - fun listByPage( - dslContext: DSLContext, - projectId: String, - pipelineId: String, - repoName: String?, - commitId: String?, - offset: Int, - limit: Int - ): List { - return with(T_PIPELINE_WEBHOOK_BUILD_LOG_DETAIL) { - val where = dslContext.selectFrom(this) - .where(PIPELINE_ID.eq(pipelineId)) - .and(PROJECT_ID.eq(projectId)) - if (commitId != null) { - where.and(COMMIT_ID.eq(commitId)) - } - if (repoName != null) { - where.and(REPO_NAME.eq(repoName)) - } - where.orderBy(CREATED_TIME.desc()) - .limit(offset, limit).fetch() - }.map { convert(it) } - } - - fun countByPage( - dslContext: DSLContext, - projectId: String, - pipelineId: String, - repoName: String?, - commitId: String? - ): Long { - return with(T_PIPELINE_WEBHOOK_BUILD_LOG_DETAIL) { - val where = dslContext.selectCount() - .from(this) - .where(PIPELINE_ID.eq(pipelineId)) - .and(PROJECT_ID.eq(projectId)) - if (commitId != null) { - where.and(COMMIT_ID.eq(commitId)) - } - if (repoName != null) { - where.and(REPO_NAME.eq(repoName)) - } - where.fetchOne(0, Long::class.java)!! - } - } - - fun convert(record: TPipelineWebhookBuildLogDetailRecord): PipelineWebhookBuildLogDetail { - return with(record) { - PipelineWebhookBuildLogDetail( - id = id, - logId = logId, - codeType = codeType, - repoName = repoName, - commitId = commitId, - projectId = projectId, - pipelineId = pipelineId, - taskId = taskId, - taskName = taskName, - success = success, - triggerResult = triggerResult, - createdTime = createdTime.timestampmilli() - ) - } - } -} diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/engine/service/PipelineWebhookBuildLogContext.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/engine/service/PipelineWebhookBuildLogContext.kt deleted file mode 100644 index 06ea5f04a0c..00000000000 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/engine/service/PipelineWebhookBuildLogContext.kt +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. - * - * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. - * - * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. - * - * A copy of the MIT License is included in this file. - * - * - * Terms of the MIT License: - * --------------------------------------------------- - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated - * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or substantial portions of - * the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT - * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN - * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -package com.tencent.devops.process.engine.service - -import com.tencent.devops.common.api.util.timestampmilli -import com.tencent.devops.process.pojo.webhook.PipelineWebhookBuildLog -import com.tencent.devops.process.pojo.webhook.PipelineWebhookBuildLogDetail -import java.time.LocalDateTime - -object PipelineWebhookBuildLogContext { - private val currentTriggerLog = ThreadLocal() - - fun initTriggerLog( - codeType: String, - requestContent: String - ) { - currentTriggerLog.set( - PipelineWebhookBuildLog( - codeType = codeType, - requestContent = requestContent, - receivedTime = LocalDateTime.now().timestampmilli(), - createdTime = LocalDateTime.now().timestampmilli() - ) - ) - } - - fun addRepoInfo( - repoName: String, - commitId: String - ) { - val triggerLog = with(currentTriggerLog.get()) { - PipelineWebhookBuildLog( - id = id, - codeType = codeType, - requestContent = requestContent, - receivedTime = receivedTime, - createdTime = createdTime, - repoName = repoName, - commitId = commitId - ) - } - currentTriggerLog.set(triggerLog) - } - - @Suppress("ALL") - fun addLogBuildInfo( - projectId: String, - pipelineId: String, - taskId: String, - taskName: String, - success: Boolean, - triggerResult: String?, - id: Long? = null - ) { - val webhookLog = currentTriggerLog.get() - webhookLog.detail.add( - PipelineWebhookBuildLogDetail( - codeType = webhookLog.codeType, - repoName = webhookLog.repoName!!, - commitId = webhookLog.commitId!!, - projectId = projectId, - pipelineId = pipelineId, - taskId = taskId, - taskName = taskName, - success = success, - triggerResult = triggerResult, - createdTime = LocalDateTime.now().timestampmilli(), - id = id - ) - ) - } - - fun get(): PipelineWebhookBuildLog { - return currentTriggerLog.get() - } - - fun remove() { - currentTriggerLog.remove() - } -} diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/engine/service/PipelineWebhookService.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/engine/service/PipelineWebhookService.kt index f4eaced2395..7b0fbea62a9 100644 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/engine/service/PipelineWebhookService.kt +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/engine/service/PipelineWebhookService.kt @@ -29,12 +29,9 @@ package com.tencent.devops.process.engine.service import com.fasterxml.jackson.databind.ObjectMapper import com.tencent.devops.common.api.enums.RepositoryConfig -import com.tencent.devops.common.api.enums.RepositoryType import com.tencent.devops.common.api.enums.ScmType import com.tencent.devops.common.api.exception.ErrorCodeException -import com.tencent.devops.common.api.exception.InvalidParamException import com.tencent.devops.common.api.pojo.Result -import com.tencent.devops.common.api.util.EnvUtils import com.tencent.devops.common.api.util.PageUtil import com.tencent.devops.common.auth.api.AuthPermission import com.tencent.devops.common.client.Client @@ -42,12 +39,6 @@ import com.tencent.devops.common.notify.enums.NotifyType import com.tencent.devops.common.pipeline.Model import com.tencent.devops.common.pipeline.container.TriggerContainer import com.tencent.devops.common.pipeline.pojo.element.Element -import com.tencent.devops.common.pipeline.pojo.element.trigger.CodeGitWebHookTriggerElement -import com.tencent.devops.common.pipeline.pojo.element.trigger.CodeGithubWebHookTriggerElement -import com.tencent.devops.common.pipeline.pojo.element.trigger.CodeGitlabWebHookTriggerElement -import com.tencent.devops.common.pipeline.pojo.element.trigger.CodeP4WebHookTriggerElement -import com.tencent.devops.common.pipeline.pojo.element.trigger.CodeSVNWebHookTriggerElement -import com.tencent.devops.common.pipeline.pojo.element.trigger.CodeTGitWebHookTriggerElement import com.tencent.devops.common.pipeline.pojo.element.trigger.WebHookTriggerElement import com.tencent.devops.common.pipeline.pojo.element.trigger.enums.CodeEventType import com.tencent.devops.common.pipeline.utils.RepositoryConfigUtils @@ -60,12 +51,13 @@ import com.tencent.devops.notify.pojo.SendNotifyMessageTemplateRequest import com.tencent.devops.process.constant.ProcessMessageCode import com.tencent.devops.process.engine.dao.PipelineResDao import com.tencent.devops.process.engine.dao.PipelineWebhookDao -import com.tencent.devops.process.engine.pojo.WebhookElementParams import com.tencent.devops.process.permission.PipelinePermissionService import com.tencent.devops.process.pojo.PipelineNotifyTemplateEnum import com.tencent.devops.process.pojo.webhook.PipelineWebhook +import com.tencent.devops.process.pojo.webhook.WebhookTriggerPipeline import com.tencent.devops.process.service.scm.ScmProxyService import com.tencent.devops.repository.api.ServiceRepositoryResource +import com.tencent.devops.repository.pojo.Repository import org.jooq.DSLContext import org.slf4j.LoggerFactory import org.springframework.beans.factory.annotation.Autowired @@ -87,8 +79,9 @@ class PipelineWebhookService @Autowired constructor( private val pipelinePermissionService: PipelinePermissionService, private val redisOperation: RedisOperation ) { - - private val logger = LoggerFactory.getLogger(javaClass)!! + companion object { + private val logger = LoggerFactory.getLogger(PipelineWebhookService::class.java) + } fun addWebhook( projectId: String, @@ -102,101 +95,75 @@ class PipelineWebhookService @Autowired constructor( return } val triggerContainer = model.stages[0].containers[0] as TriggerContainer - val params = triggerContainer.params.associate { param -> + val variables = triggerContainer.params.associate { param -> param.id to param.defaultValue.toString() } val elements = triggerContainer.elements.filterIsInstance() val failedElementNames = mutableListOf() elements.forEach { element -> - val webhookElementParams = getElementRepositoryConfig(element, variable = params) - ?: return@forEach - with(webhookElementParams) { - try { - logger.info("$pipelineId| Trying to add the $scmType web hook for repo($repositoryConfig)") - saveWebhook( - pipelineWebhook = PipelineWebhook( - projectId = projectId, - pipelineId = pipelineId, - repositoryType = scmType, - repoType = repositoryConfig.repositoryType, - repoHashId = repositoryConfig.repositoryHashId, - repoName = repositoryConfig.repositoryName, - taskId = element.id - ), - codeEventType = eventType, - repositoryConfig = repositoryConfig, - createPipelineFlag = true, - version = element.version - ) - } catch (ignore: Exception) { - failedElementNames.add("- ${element.name}: ${ignore.message}") - logger.warn("$projectId|$pipelineId|add webhook failed", ignore) - } - } - } - if (failedElementNames.isNotEmpty()) { - client.get(ServiceNotifyMessageTemplateResource::class).sendNotifyMessageByTemplate( - SendNotifyMessageTemplateRequest( - templateCode = - PipelineNotifyTemplateEnum.PIPELINE_WEBHOOK_REGISTER_FAILURE_NOTIFY_TEMPLATE.templateCode, - receivers = mutableSetOf(userId), - notifyType = mutableSetOf(NotifyType.RTX.name), - titleParams = mapOf("pipelineName" to model.name), - bodyParams = mapOf( - "pipelineName" to model.name, - "elementNames" to failedElementNames.joinToString(""), - "pipelineEditUrl" to pipelineEditUrl(projectId, pipelineId) - ), - cc = null, - bcc = null + try { + saveWebhook( + projectId = projectId, + pipelineId = pipelineId, + element = element, + variables = variables ) - ) + } catch (ignore: Exception) { + failedElementNames.add("- ${element.name}: ${ignore.message}") + logger.warn("$projectId|$pipelineId|add webhook failed", ignore) + } } + sendNotify( + userId = userId, + projectId = projectId, + pipelineId = pipelineId, + pipelineName = model.name, + failedElementNames = failedElementNames + ) } - fun saveWebhook( - pipelineWebhook: PipelineWebhook, - codeEventType: CodeEventType? = null, - repositoryConfig: RepositoryConfig, - createPipelineFlag: Boolean? = false, - version: String + private fun saveWebhook( + projectId: String, + pipelineId: String, + element: Element, + variables: Map ) { - logger.info("save Webhook[$pipelineWebhook]") - var continueFlag = true - if (createPipelineFlag != null && createPipelineFlag) { - // 新增流水线时,模版里配置的代码库是变量或者当前项目下不存在,不需创建webhook - try { - scmProxyService.getRepo(pipelineWebhook.projectId, repositoryConfig) - } catch (e: Exception) { - logger.info("skip save Webhook[$pipelineWebhook]: ${e.message}") - continueFlag = false - } - } - - if (continueFlag) { - val projectName = registerWebhook( - pipelineWebhook = pipelineWebhook, - repositoryConfig = repositoryConfig, - codeEventType = codeEventType, - version = version - ) - logger.info("add $projectName webhook to [$pipelineWebhook]") - if (!projectName.isNullOrBlank()) { - pipelineWebhook.projectName = getProjectName(projectName) - pipelineWebhookDao.save( - dslContext = dslContext, - pipelineWebhook = pipelineWebhook - ) - } - } + val (repositoryType, eventType, repositoryConfig) = + RepositoryConfigUtils.buildWebhookConfig(element, variables) + logger.info("$pipelineId| Trying to add the $repositoryType web hook for repo($repositoryConfig)") + val repository = registerWebhook( + projectId = projectId, + repositoryType = repositoryType, + repositoryConfig = repositoryConfig, + codeEventType = eventType, + elementVersion = element.version + ) ?: return + val pipelineWebhook = PipelineWebhook( + projectId = projectId, + pipelineId = pipelineId, + repositoryType = repositoryType, + repoType = repositoryConfig.repositoryType, + repoHashId = repositoryConfig.repositoryHashId, + repoName = repositoryConfig.repositoryName, + taskId = element.id, + projectName = getProjectName(repository.projectName), + repositoryHashId = repository.repoHashId, + eventType = eventType?.name ?: "", + externalId = repository.getExternalId() + ) + pipelineWebhookDao.save( + dslContext = dslContext, + pipelineWebhook = pipelineWebhook + ) } private fun registerWebhook( - pipelineWebhook: PipelineWebhook, + projectId: String, + repositoryType: ScmType, repositoryConfig: RepositoryConfig, codeEventType: CodeEventType?, - version: String - ): String? { + elementVersion: String + ): Repository? { // 防止同一个仓库注册多个相同事件的webhook val redisLock = RedisLock( redisOperation = redisOperation, @@ -205,39 +172,56 @@ class PipelineWebhookService @Autowired constructor( ) try { redisLock.lock() - return when (pipelineWebhook.repositoryType) { + return when (repositoryType) { ScmType.CODE_GIT -> - scmProxyService.addGitWebhook(pipelineWebhook.projectId, repositoryConfig, codeEventType) + scmProxyService.addGitWebhook( + projectId = projectId, + repositoryConfig = repositoryConfig, + codeEventType = codeEventType + ) + ScmType.CODE_SVN -> - scmProxyService.addSvnWebhook(pipelineWebhook.projectId, repositoryConfig) + scmProxyService.addSvnWebhook(projectId = projectId, repositoryConfig = repositoryConfig) + ScmType.CODE_GITLAB -> - scmProxyService.addGitlabWebhook(pipelineWebhook.projectId, repositoryConfig, codeEventType) + scmProxyService.addGitlabWebhook( + projectId = projectId, + repositoryConfig = repositoryConfig, + codeEventType = codeEventType + ) + ScmType.GITHUB -> { - val repo = client.get(ServiceRepositoryResource::class).get( - pipelineWebhook.projectId, - repositoryConfig.getURLEncodeRepositoryId(), - repositoryConfig.repositoryType + client.get(ServiceRepositoryResource::class).get( + projectId = projectId, + repositoryId = repositoryConfig.getURLEncodeRepositoryId(), + repositoryType = repositoryConfig.repositoryType ).data!! - repo.projectName } + ScmType.CODE_TGIT -> { - scmProxyService.addTGitWebhook(pipelineWebhook.projectId, repositoryConfig, codeEventType) + scmProxyService.addTGitWebhook( + projectId = projectId, + repositoryConfig = repositoryConfig, + codeEventType = codeEventType + ) } + ScmType.CODE_P4 -> - if (WebhookUtils.isCustomP4TriggerVersion(version)) { + if (WebhookUtils.isCustomP4TriggerVersion(elementVersion)) { val repo = client.get(ServiceRepositoryResource::class).get( - pipelineWebhook.projectId, - repositoryConfig.getURLEncodeRepositoryId(), - repositoryConfig.repositoryType + projectId = projectId, + repositoryId = repositoryConfig.getURLEncodeRepositoryId(), + repositoryType = repositoryConfig.repositoryType ).data!! - repo.projectName + repo } else { scmProxyService.addP4Webhook( - projectId = pipelineWebhook.projectId, + projectId = projectId, repositoryConfig = repositoryConfig, codeEventType = codeEventType ) } + else -> { null } @@ -247,6 +231,33 @@ class PipelineWebhookService @Autowired constructor( } } + private fun sendNotify( + userId: String, + projectId: String, + pipelineId: String, + pipelineName: String, + failedElementNames: List + ) { + if (failedElementNames.isNotEmpty()) { + client.get(ServiceNotifyMessageTemplateResource::class).sendNotifyMessageByTemplate( + SendNotifyMessageTemplateRequest( + templateCode = + PipelineNotifyTemplateEnum.PIPELINE_WEBHOOK_REGISTER_FAILURE_NOTIFY_TEMPLATE.templateCode, + receivers = mutableSetOf(userId), + notifyType = mutableSetOf(NotifyType.RTX.name), + titleParams = mapOf("pipelineName" to pipelineName), + bodyParams = mapOf( + "pipelineName" to pipelineName, + "elementNames" to failedElementNames.joinToString(""), + "pipelineEditUrl" to pipelineEditUrl(projectId, pipelineId) + ), + cc = null, + bcc = null + ) + ) + } + } + private fun pipelineEditUrl(projectId: String, pipelineId: String) = "${HomeHostUtil.innerServerHost()}/console/pipeline/$projectId/$pipelineId/edit" @@ -278,43 +289,26 @@ class PipelineWebhookService @Autowired constructor( } } - fun getWebhookPipelines(name: String, type: String): Set> { - val records = pipelineWebhookDao.getByProjectNameAndType( + fun getTriggerPipelines(name: String, repositoryType: String): List { + return pipelineWebhookDao.getByProjectNameAndType( dslContext = dslContext, projectName = getProjectName(name), - repositoryType = getWebhookScmType(type).name - ) - val pipelineWebhookSet = mutableSetOf>() - records?.forEach { - pipelineWebhookSet.add(Pair(it.value1(), it.value2())) - } - return pipelineWebhookSet + repositoryType = repositoryType + ) ?: emptyList() } - fun getWebhookScmType(type: String) = - when (type) { - CodeGitWebHookTriggerElement.classType -> { - ScmType.CODE_GIT - } - CodeSVNWebHookTriggerElement.classType -> { - ScmType.CODE_SVN - } - CodeGitlabWebHookTriggerElement.classType -> { - ScmType.CODE_GITLAB - } - CodeGithubWebHookTriggerElement.classType -> { - ScmType.GITHUB - } - CodeTGitWebHookTriggerElement.classType -> { - ScmType.CODE_TGIT - } - CodeP4WebHookTriggerElement.classType -> { - ScmType.CODE_P4 - } - else -> { - throw IllegalArgumentException("Unknown web hook type($type)") - } - } + fun listTriggerPipeline( + projectId: String, + repositoryHashId: String, + eventType: String + ): List { + return pipelineWebhookDao.listTriggerPipeline( + dslContext = dslContext, + projectId = projectId, + repositoryHashId = repositoryHashId, + eventType = eventType + ) ?: emptyList() + } fun getProjectName(projectName: String): String { // 如果项目名是三层的,比如a/b/c,那对应的rep_name是b @@ -325,254 +319,6 @@ class PipelineWebhookService @Autowired constructor( return repoSplit[1].trim() } - private fun getRepositoryConfig( - pipelineWebhook: PipelineWebhook, - variable: Map? = null - ): RepositoryConfig { - return getRepositoryConfig( - repoHashId = pipelineWebhook.repoHashId, - repoName = pipelineWebhook.repoName, - repoType = pipelineWebhook.repoType, - variable = variable - ) - } - - private fun getRepositoryConfig( - repoHashId: String?, - repoName: String?, - repoType: RepositoryType?, - variable: Map? = null - ): RepositoryConfig { - return when (repoType) { - RepositoryType.ID -> RepositoryConfig(repoHashId, null, RepositoryType.ID) - RepositoryType.NAME -> { - val repositoryName = if (variable == null || variable.isEmpty()) { - repoName!! - } else { - EnvUtils.parseEnv(repoName!!, variable) - } - RepositoryConfig(null, repositoryName, RepositoryType.NAME) - } - else -> { - if (!repoHashId.isNullOrBlank()) { - RepositoryConfig(repoHashId, null, RepositoryType.ID) - } else if (!repoName.isNullOrBlank()) { - val repositoryName = if (variable == null || variable.isEmpty()) { - repoName - } else { - EnvUtils.parseEnv(repoName, variable) - } - RepositoryConfig(null, repositoryName, RepositoryType.NAME) - } else { - // 两者不能同时为空 - throw ErrorCodeException( - errorCode = ProcessMessageCode.ERROR_PARAM_WEBHOOK_ID_NAME_ALL_NULL - ) - } - } - } - } - - fun listRepositoryTypeWebhooks( - repositoryType: ScmType, - start: Int, - limit: Int - ): Result> { - if (start < 0) { - return Result(emptyList()) - } - val list = pipelineWebhookDao.getPipelineWebHooksByRepositoryType(dslContext, repositoryType.name, start, limit) - val pipelineWebhookList = mutableListOf() - list.forEach { - pipelineWebhookList.add(pipelineWebhookDao.convert(it)) - } - return Result(pipelineWebhookList) - } - - fun updateProjectNameAndTaskId() { - ScmType.values().forEach { - doUpdateProjectNameAndTaskId(it) - } - } - - /** - * 批量更新TASK_ID和PROJECT_NAME - */ - private fun doUpdateProjectNameAndTaskId(type: ScmType) { - val pipelines = mutableMapOf/*trigger element*/>() - val pipelineVariables = HashMap>() - val usedTask = mutableListOf() - var start = 0 - loop@ while (true) { - val typeWebhooksResp = listRepositoryTypeWebhooks(type, start, 100) - if (typeWebhooksResp.isNotOk() || typeWebhooksResp.data == null || typeWebhooksResp.data!!.isEmpty()) { - break@loop - } - typeWebhooksResp.data!!.forEach webhook@{ - with(it) { - try { - val (elements, params) = getElementsAndParams( - projectId = projectId, - pipelineId = pipelineId, - pipelines = pipelines, - pipelineVariables = pipelineVariables - ) - - val result = matchElement(elements = elements, params = params, usedTask = usedTask) - if (!result) { - logger.warn("$id|$pipelineId|$taskId|not match element, delete webhook $it") - pipelineWebhookDao.deleteById(dslContext = dslContext, projectId = projectId, id = id!!) - } - } catch (t: Throwable) { - logger.warn("update projectName and taskId $it exception ignore", t) - } - } - } - start += 100 - } - } - - private fun getElementsAndParams( - projectId: String, - pipelineId: String, - pipelines: MutableMap/*trigger element*/>, - pipelineVariables: MutableMap> - ): Pair, Map> { - return if (pipelines[pipelineId] == null) { - val model = getModel(projectId, pipelineId) - // 如果model为空,缓存空值 - val (elements, params) = if (model == null) { - Pair(emptyList(), emptyMap()) - } else { - val triggerContainer = model.stages[0].containers[0] as TriggerContainer - val params = triggerContainer.params.associate { param -> - param.id to param.defaultValue.toString() - } - Pair(triggerContainer.elements.filterIsInstance(), params) - } - pipelines[pipelineId] = elements - pipelineVariables[pipelineId] = params - Pair(elements, params) - } else { - Pair(pipelines[pipelineId]!!, pipelineVariables[pipelineId]!!) - } - } - - private fun PipelineWebhook.matchElement( - elements: List, - params: Map, - usedTask: MutableList - ): Boolean { - val webhookRepositoryConfig = getRepositoryConfig(this, params) - if (elements.isEmpty()) { - logger.warn("$id|$pipelineId|$taskId|pipeline does not exist") - return false - } - val repo = try { - client.get(ServiceRepositoryResource::class).get( - projectId = projectId, - repositoryId = webhookRepositoryConfig.getURLEncodeRepositoryId(), - repositoryType = webhookRepositoryConfig.repositoryType - ).data - } catch (e: Exception) { - null - } - if (repo == null) { - logger.warn("$id|$pipelineId|$taskId|repo[$webhookRepositoryConfig] does not exist") - return false - } - var findResult = false - for (element in elements) { - val (elementRepositoryConfig, elementScmType) = getElementRepositoryConfig(element, params) ?: continue - val usedKey = "${pipelineId}_${element.id!!}" - if (webhookRepositoryConfig.getRepositoryId() == elementRepositoryConfig.getRepositoryId() && - elementScmType == repositoryType && - !usedTask.contains(usedKey) - ) { - /* - * 配置相同并且没有使用过才进行更新和标记 - * 1. 如果taskId为空,则表示没有更新过,直接更新 - * 2. 如果taskId不为空,taskId和插件ID相同,则标记已使用 - * */ - if (taskId == null) { - pipelineWebhookDao.updateProjectNameAndTaskId( - dslContext = dslContext, - projectId = projectId, - projectName = getProjectName(repo.projectName), - taskId = element.id!!, - id = id!! - ) - usedTask.add(usedKey) - findResult = true - break - } else if (taskId == element.id) { - usedTask.add(usedKey) - findResult = true - break - } - } - } - return findResult - } - - private fun getElementRepositoryConfig( - element: Element, - variable: Map - ): WebhookElementParams? { - if (element !is WebHookTriggerElement) { - return null - } - val elementRepositoryConfig = RepositoryConfigUtils.buildConfig(element) - val realRepositoryConfig = with(elementRepositoryConfig) { - getRepositoryConfig( - repoHashId = repositoryHashId, - repoName = repositoryName, - repoType = repositoryType, - variable = variable - ) - } - return when (element) { - is CodeGitWebHookTriggerElement -> - WebhookElementParams( - repositoryConfig = realRepositoryConfig, - scmType = ScmType.CODE_GIT, - eventType = element.eventType - ) - is CodeGithubWebHookTriggerElement -> - WebhookElementParams( - repositoryConfig = realRepositoryConfig, - scmType = ScmType.GITHUB, - eventType = null - ) - is CodeGitlabWebHookTriggerElement -> - WebhookElementParams( - repositoryConfig = realRepositoryConfig, - scmType = ScmType.CODE_GITLAB, - eventType = element.eventType - ) - is CodeSVNWebHookTriggerElement -> - WebhookElementParams( - repositoryConfig = realRepositoryConfig, - scmType = ScmType.CODE_SVN, - eventType = null - ) - is CodeTGitWebHookTriggerElement -> - WebhookElementParams( - repositoryConfig = realRepositoryConfig, - scmType = ScmType.CODE_TGIT, - eventType = element.data.input.eventType - ) - is CodeP4WebHookTriggerElement -> - WebhookElementParams( - repositoryConfig = realRepositoryConfig, - scmType = ScmType.CODE_P4, - eventType = element.data.input.eventType - ) - else -> - throw InvalidParamException("Unknown code element -> $element") - } - } - fun listWebhook( userId: String, projectId: String, @@ -603,64 +349,4 @@ class PipelineWebhookService @Autowired constructor( limit = limit.limit ) ?: emptyList() } - - fun updateWebhookSecret(type: ScmType) { - val pipelines = mutableMapOf/*trigger element*/>() - val pipelineVariables = HashMap>() - var start = 0 - loop@ while (true) { - logger.info("update webhook secret|start=$start") - val typeWebhooksResp = listRepositoryTypeWebhooks(type, start, 100) - if (typeWebhooksResp.isNotOk() || typeWebhooksResp.data == null || typeWebhooksResp.data!!.isEmpty()) { - break@loop - } - typeWebhooksResp.data!!.forEach webhook@{ - it.doUpdateWebhookSecret(pipelines, pipelineVariables) - } - start += 100 - } - } - - private fun PipelineWebhook.doUpdateWebhookSecret( - pipelines: MutableMap>, - pipelineVariables: HashMap> - ) { - try { - val (elements, params) = getElementsAndParams( - projectId = projectId, - pipelineId = pipelineId, - pipelines = pipelines, - pipelineVariables = pipelineVariables - ) - - val repositoryConfig = getRepositoryConfig(this, params) - for (element in elements) { - if (element.id == taskId) { - when (element) { - is CodeGitWebHookTriggerElement -> - scmProxyService.addGitWebhook( - projectId, - repositoryConfig = repositoryConfig, - codeEventType = element.eventType - ) - is CodeTGitWebHookTriggerElement -> - scmProxyService.addTGitWebhook( - projectId, - repositoryConfig = repositoryConfig, - codeEventType = element.data.input.eventType - ) - is CodeGitlabWebHookTriggerElement -> - scmProxyService.addGitlabWebhook( - projectId, - repositoryConfig = repositoryConfig, - codeEventType = element.eventType - ) - } - break - } - } - } catch (t: Throwable) { - logger.warn("$id|$pipelineId|update webhook secret exception ignore", t) - } - } } diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/engine/service/PipelineWebhookUpgradeService.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/engine/service/PipelineWebhookUpgradeService.kt new file mode 100644 index 00000000000..5787b33d9e9 --- /dev/null +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/engine/service/PipelineWebhookUpgradeService.kt @@ -0,0 +1,429 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package com.tencent.devops.process.engine.service + +import com.tencent.devops.common.api.enums.RepositoryConfig +import com.tencent.devops.common.api.enums.RepositoryType +import com.tencent.devops.common.api.enums.ScmType +import com.tencent.devops.common.api.pojo.Result +import com.tencent.devops.common.client.Client +import com.tencent.devops.common.pipeline.container.TriggerContainer +import com.tencent.devops.common.pipeline.pojo.element.Element +import com.tencent.devops.common.pipeline.pojo.element.trigger.CodeGitWebHookTriggerElement +import com.tencent.devops.common.pipeline.pojo.element.trigger.CodeGitlabWebHookTriggerElement +import com.tencent.devops.common.pipeline.pojo.element.trigger.CodeTGitWebHookTriggerElement +import com.tencent.devops.common.pipeline.pojo.element.trigger.WebHookTriggerElement +import com.tencent.devops.common.pipeline.utils.RepositoryConfigUtils +import com.tencent.devops.process.engine.dao.PipelineWebhookDao +import com.tencent.devops.process.pojo.webhook.PipelineWebhook +import com.tencent.devops.process.service.scm.ScmProxyService +import com.tencent.devops.repository.api.ServiceRepositoryResource +import com.tencent.devops.repository.pojo.Repository +import org.jooq.DSLContext +import org.slf4j.LoggerFactory +import org.springframework.stereotype.Service +import java.util.Optional +import java.util.concurrent.Executors + +@Service +class PipelineWebhookUpgradeService( + private val scmProxyService: ScmProxyService, + private val dslContext: DSLContext, + private val pipelineWebhookDao: PipelineWebhookDao, + private val client: Client, + private val pipelineWebhookService: PipelineWebhookService +) { + + companion object { + private val logger = LoggerFactory.getLogger(PipelineWebhookUpgradeService::class.java) + } + + fun updateProjectNameAndTaskId() { + ScmType.values().forEach { + doUpdateProjectNameAndTaskId(it) + } + } + + /** + * 批量更新TASK_ID和PROJECT_NAME + */ + @Suppress("NestedBlockDepth") + private fun doUpdateProjectNameAndTaskId(type: ScmType) { + val pipelines = mutableMapOf/*trigger element*/>() + val pipelineVariables = HashMap>() + val usedTask = mutableListOf() + var start = 0 + loop@ while (true) { + val typeWebhooksResp = listRepositoryTypeWebhooks(type, start, 100) + if (typeWebhooksResp.isNotOk() || typeWebhooksResp.data == null || typeWebhooksResp.data!!.isEmpty()) { + break@loop + } + typeWebhooksResp.data!!.forEach webhook@{ + with(it) { + try { + val (elements, params) = getElementsAndParams( + projectId = projectId, + pipelineId = pipelineId, + pipelines = pipelines, + pipelineVariables = pipelineVariables + ) + + val result = matchElement(elements = elements, params = params, usedTask = usedTask) + if (!result) { + logger.warn("$id|$pipelineId|$taskId|not match element, delete webhook $it") + pipelineWebhookDao.deleteById(dslContext = dslContext, projectId = projectId, id = id!!) + } + } catch (t: Throwable) { + logger.warn("update projectName and taskId $it exception ignore", t) + } + } + } + start += 100 + } + } + + fun listRepositoryTypeWebhooks( + repositoryType: ScmType, + start: Int, + limit: Int + ): Result> { + if (start < 0) { + return Result(emptyList()) + } + val list = pipelineWebhookDao.getPipelineWebHooksByRepositoryType(dslContext, repositoryType.name, start, limit) + val pipelineWebhookList = mutableListOf() + list.forEach { + pipelineWebhookList.add(pipelineWebhookDao.convert(it)) + } + return Result(pipelineWebhookList) + } + + private fun getElementsAndParams( + projectId: String, + pipelineId: String, + pipelines: MutableMap/*trigger element*/>, + pipelineVariables: MutableMap> + ): Pair, Map> { + return if (pipelines[pipelineId] == null) { + val model = pipelineWebhookService.getModel(projectId, pipelineId) + // 如果model为空,缓存空值 + val (elements, params) = if (model == null) { + Pair(emptyList(), emptyMap()) + } else { + val triggerContainer = model.stages[0].containers[0] as TriggerContainer + val params = triggerContainer.params.associate { param -> + param.id to param.defaultValue.toString() + } + Pair(triggerContainer.elements.filterIsInstance(), params) + } + pipelines[pipelineId] = elements + pipelineVariables[pipelineId] = params + Pair(elements, params) + } else { + Pair(pipelines[pipelineId]!!, pipelineVariables[pipelineId]!!) + } + } + + @Suppress("LoopWithTooManyJumpStatements", "ComplexMethod") + private fun PipelineWebhook.matchElement( + elements: List, + params: Map, + usedTask: MutableList + ): Boolean { + val webhookRepositoryConfig = RepositoryConfigUtils.getRepositoryConfig( + repoHashId = repoHashId, + repoName = repoName, + repoType = repoType, + variables = params + ) + if (elements.isEmpty()) { + logger.warn("$id|$pipelineId|$taskId|pipeline does not exist") + return false + } + val repo = try { + client.get(ServiceRepositoryResource::class).get( + projectId = projectId, + repositoryId = webhookRepositoryConfig.getURLEncodeRepositoryId(), + repositoryType = webhookRepositoryConfig.repositoryType + ).data + } catch (e: Exception) { + null + } + if (repo == null) { + logger.warn("$id|$pipelineId|$taskId|repo[$webhookRepositoryConfig] does not exist") + return false + } + var findResult = false + for (element in elements) { + val (elementScmType, elementEventType, elementRepositoryConfig) = + RepositoryConfigUtils.buildWebhookConfig(element, params) + val usedKey = "${pipelineId}_${element.id!!}" + if (webhookRepositoryConfig.getRepositoryId() == elementRepositoryConfig.getRepositoryId() && + elementScmType == repositoryType && + !usedTask.contains(usedKey) + ) { + /* + * 配置相同并且没有使用过才进行更新和标记 + * 1. 如果taskId为空,则表示没有更新过,直接更新 + * 2. 如果taskId不为空,taskId和插件ID相同,则标记已使用 + * */ + if (taskId == null) { + pipelineWebhookDao.updateProjectNameAndTaskId( + dslContext = dslContext, + projectId = projectId, + projectName = pipelineWebhookService.getProjectName(repo.projectName), + taskId = element.id!!, + id = id!! + ) + usedTask.add(usedKey) + findResult = true + break + } else if (taskId == element.id) { + usedTask.add(usedKey) + findResult = true + break + } + } + } + return findResult + } + + fun updateWebhookSecret(type: ScmType) { + val pipelines = mutableMapOf/*trigger element*/>() + val pipelineVariables = HashMap>() + var start = 0 + loop@ while (true) { + logger.info("update webhook secret|start=$start") + val typeWebhooksResp = listRepositoryTypeWebhooks(type, start, 100) + if (typeWebhooksResp.isNotOk() || typeWebhooksResp.data == null || typeWebhooksResp.data!!.isEmpty()) { + break@loop + } + typeWebhooksResp.data!!.forEach webhook@{ + it.doUpdateWebhookSecret(pipelines, pipelineVariables) + } + start += 100 + } + } + + @Suppress("NestedBlockDepth") + private fun PipelineWebhook.doUpdateWebhookSecret( + pipelines: MutableMap>, + pipelineVariables: HashMap> + ) { + try { + val (elements, params) = getElementsAndParams( + projectId = projectId, + pipelineId = pipelineId, + pipelines = pipelines, + pipelineVariables = pipelineVariables + ) + + val repositoryConfig = RepositoryConfigUtils.getRepositoryConfig( + repoHashId = repoHashId, + repoName = repoName, + repoType = repoType, + variables = params + ) + elements.forEach { element -> + if (element.id == taskId) { + when (element) { + is CodeGitWebHookTriggerElement -> + scmProxyService.addGitWebhook( + projectId, + repositoryConfig = repositoryConfig, + codeEventType = element.eventType + ) + + is CodeTGitWebHookTriggerElement -> + scmProxyService.addTGitWebhook( + projectId, + repositoryConfig = repositoryConfig, + codeEventType = element.data.input.eventType + ) + + is CodeGitlabWebHookTriggerElement -> + scmProxyService.addGitlabWebhook( + projectId, + repositoryConfig = repositoryConfig, + codeEventType = element.eventType + ) + } + return + } + } + } catch (t: Throwable) { + logger.warn("$id|$pipelineId|update webhook secret exception ignore", t) + } + } + + fun updateWebhookEventInfo() { + val startTime = System.currentTimeMillis() + val threadPoolExecutor = Executors.newSingleThreadExecutor() + threadPoolExecutor.submit { + logger.info("PipelineWebhookService:begin updateWebhookEventInfo threadPoolExecutor") + try { + updateWebhookEventInfoTask() + } catch (ignored: Exception) { + logger.warn("PipelineWebhookService:updateWebhookEventInfo failed", ignored) + } finally { + threadPoolExecutor.shutdown() + logger.info("updateWebhookEventInfo finish cost: ${System.currentTimeMillis() - startTime}") + } + } + } + + private fun updateWebhookEventInfoTask() { + var offset = 0 + val limit = 1000 + val repoCache = mutableMapOf>() + // 上一个更新的项目ID + var preProjectId: String? = null + do { + val pipelines = pipelineWebhookDao.listPipelines( + dslContext = dslContext, + limit = limit, + offset = offset + ) + pipelines.forEach { (projectId, pipelineId) -> + // 更改项目,清空代码库缓存 + if (preProjectId != null && preProjectId != projectId) { + repoCache.clear() + } + preProjectId = projectId + updatePipelineEventInfo(projectId = projectId, pipelineId = pipelineId, repoCache = repoCache) + } + offset += limit + } while (pipelines.size == 1000) + } + + private fun updatePipelineEventInfo( + projectId: String, + pipelineId: String, + repoCache: MutableMap> + ) { + val model = pipelineWebhookService.getModel(projectId, pipelineId) + if (model == null) { + logger.info("$projectId|$pipelineId|model is null") + return + } + val triggerContainer = model.stages[0].containers[0] as TriggerContainer + val params = triggerContainer.params.associate { param -> + param.id to param.defaultValue.toString() + } + val elementMap = + triggerContainer.elements.filterIsInstance().associateBy { it.id } + val pipelineWebhooks = pipelineWebhookDao.listWebhook( + dslContext = dslContext, + projectId = projectId, + pipelineId = pipelineId, + limit = 1000, + offset = 0 + ) + pipelineWebhooks?.forEach webhook@{ webhook -> + try { + if (webhook.taskId.isNullOrBlank()) return@webhook + val element = elementMap[webhook.taskId] ?: return@webhook + val (elementScmType, elementEventType, elementRepositoryConfig) = + RepositoryConfigUtils.buildWebhookConfig(element, params) + val webhookRepositoryConfig = RepositoryConfigUtils.getRepositoryConfig( + repoHashId = webhook.repoHashId, + repoName = webhook.repoName, + repoType = webhook.repoType, + variables = params + ) + // 插件的配置与表中数据不一致,如保存流水线时,注册webhook失败,就会导致数据不一致,打印日志统计 + if (elementRepositoryConfig.getRepositoryId() != webhookRepositoryConfig.getRepositoryId()) { + logger.info( + "webhook repository config different from element repository config|" + + "webhook:$webhookRepositoryConfig|element:$elementRepositoryConfig" + ) + } + val repository = getAndCacheRepo(projectId, webhookRepositoryConfig, repoCache) + + // 历史原因,git的projectName有三个,如aaa/bbb/ccc,只读取了bbb,统计数据量 + if (repository != null && webhook.projectName != repository.projectName) { + logger.info( + "webhook projectName different from repo projectName|" + + "webhook:${webhook.projectName}|repo:${repository.projectName}" + ) + } + val repositoryHashId = when { + repository != null -> repository.repoHashId + webhookRepositoryConfig.repositoryType == RepositoryType.ID -> + webhookRepositoryConfig.repositoryHashId + + else -> null + } + pipelineWebhookDao.updateWebhookEventInfo( + dslContext = dslContext, + eventType = elementEventType?.name ?: "", + externalId = repository?.getExternalId(), + projectId = projectId, + pipelineId = pipelineId, + taskId = webhook.taskId!!, + repositoryHashId = repositoryHashId + ) + } catch (ignored: Exception) { + logger.info("update webhook event info error|$webhook", ignored) + } + } + } + + private fun getAndCacheRepo( + projectId: String, + webhookRepositoryConfig: RepositoryConfig, + repoCache: MutableMap> + ): Repository? { + // 缓存代码库信息,避免频繁调用代码库信息接口 + val repoCacheKey = "${projectId}_${webhookRepositoryConfig.getRepositoryId()}" + val repositoryOptional = repoCache[repoCacheKey] ?: run { + val repo = try { + scmProxyService.getRepo( + projectId = projectId, + repositoryConfig = webhookRepositoryConfig + ) + } catch (ignored: Exception) { + logger.warn( + "$projectId|${webhookRepositoryConfig.getRepositoryId()}|" + + "fail to get repository info", ignored + ) + null + } + val optional = Optional.ofNullable(repo) + repoCache[repoCacheKey] = optional + optional + } + val repository = if (repositoryOptional.isPresent) { + repositoryOptional.get() + } else { + null + } + return repository + } +} diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/service/PipelineRemoteAuthService.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/service/PipelineRemoteAuthService.kt index 92bffbbf527..841fdc0e883 100644 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/service/PipelineRemoteAuthService.kt +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/service/PipelineRemoteAuthService.kt @@ -48,7 +48,7 @@ import com.tencent.devops.process.engine.control.lock.PipelineRemoteAuthLock import com.tencent.devops.process.engine.service.PipelineRepositoryService import com.tencent.devops.process.pojo.BuildId import com.tencent.devops.process.pojo.PipelineRemoteToken -import com.tencent.devops.process.service.builds.PipelineBuildFacadeService +import com.tencent.devops.process.utils.PIPELINE_START_REMOTE_CLIENT_IP import com.tencent.devops.process.utils.PIPELINE_START_REMOTE_USER_ID import com.tencent.devops.process.utils.PIPELINE_START_TASK_ID import org.jooq.DSLContext @@ -61,7 +61,6 @@ import org.springframework.stereotype.Service class PipelineRemoteAuthService @Autowired constructor( private val dslContext: DSLContext, private val pipelineRemoteAuthDao: PipelineRemoteAuthDao, - private val pipelineBuildFacadeService: PipelineBuildFacadeService, private val pipelineReportService: PipelineRepositoryService, private val redisOperation: RedisOperation, private val client: Client, @@ -119,14 +118,17 @@ class PipelineRemoteAuthService @Autowired constructor( if (!startUser.isNullOrBlank()) { vals[PIPELINE_START_REMOTE_USER_ID] = startUser } - + if (!sourceIp.isNullOrBlank()) { + vals[PIPELINE_START_REMOTE_CLIENT_IP] = sourceIp + } logger.info("Start the pipeline remotely of $userId ${pipeline.pipelineId} of project ${pipeline.projectId}") // #5779 为兼容多集群的场景。流水线的启动需要路由到项目对应的集群。此处携带X-DEVOPS-PROJECT-ID头重新请求网关,由网关路由到项目对应的集群 /* #7095 因Bktag设置了router_tag 默认为本集群,导致网关不会根据X-DEVOPS-PROJECT-ID路由。故直接根据项目获取router 不使用client.get直接调用,因client内不支持同服务间的feign调用。故只能通过网关代理下 */ val projectConsulTag = redisOperation.hget(ConsulConstants.PROJECT_TAG_REDIS_KEY, pipeline.projectId) return bkTag.invokeByTag(projectConsulTag) { - logger.info("start call service api ${pipeline.projectId} ${pipeline.pipelineId}, $projectConsulTag ${bkTag.getFinalTag()}") + logger.info("start call service api ${pipeline.projectId} ${pipeline.pipelineId}, " + + "$projectConsulTag ${bkTag.getFinalTag()}") val buildId = client.getGateway(ServiceBuildResource::class).manualStartupNew( userId = userId!!, projectId = pipeline.projectId, @@ -159,7 +161,8 @@ class PipelineRemoteAuthService @Autowired constructor( id = buildId.id, executeCount = 1, pipelineId = pipeline.pipelineId, - projectId = pipeline.projectId + projectId = pipeline.projectId, + num = buildId.num ) } } diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/service/SubPipelineStartUpService.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/service/SubPipelineStartUpService.kt index a9f371c0adf..cd3dba6ed97 100644 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/service/SubPipelineStartUpService.kt +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/service/SubPipelineStartUpService.kt @@ -60,6 +60,7 @@ import com.tencent.devops.process.utils.PIPELINE_START_CHANNEL import com.tencent.devops.process.utils.PIPELINE_START_PARENT_BUILD_ID import com.tencent.devops.process.utils.PIPELINE_START_PARENT_BUILD_TASK_ID import com.tencent.devops.process.utils.PIPELINE_START_PARENT_PIPELINE_ID +import com.tencent.devops.process.utils.PIPELINE_START_PARENT_PIPELINE_NAME import com.tencent.devops.process.utils.PIPELINE_START_PARENT_PROJECT_ID import com.tencent.devops.process.utils.PIPELINE_START_PIPELINE_USER_ID import com.tencent.devops.process.utils.PIPELINE_START_USER_ID @@ -231,6 +232,8 @@ class SubPipelineStartUpService @Autowired constructor( BuildParameters(key = PIPELINE_START_PARENT_PROJECT_ID, value = parentProjectId) params[PIPELINE_START_PARENT_PIPELINE_ID] = BuildParameters(key = PIPELINE_START_PARENT_PIPELINE_ID, value = parentPipelineId) + params[PIPELINE_START_PARENT_PIPELINE_NAME] = + BuildParameters(key = PIPELINE_START_PARENT_PIPELINE_NAME, value = parentPipelineInfo.pipelineName) params[PIPELINE_START_PARENT_BUILD_ID] = BuildParameters(key = PIPELINE_START_PARENT_BUILD_ID, value = parentBuildId) params[PIPELINE_START_PARENT_BUILD_TASK_ID] = @@ -243,7 +246,6 @@ class SubPipelineStartUpService @Autowired constructor( } // 校验父流水线最后修改人是否有子流水线执行权限 checkPermission(userId = parentPipelineInfo.lastModifyUser, projectId = projectId, pipelineId = pipelineId) - // 子流水线的调用不受频率限制 val subBuildId = pipelineBuildService.startPipeline( userId = readyToBuildPipelineInfo.lastModifyUser, diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/service/builds/PipelineBuildFacadeService.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/service/builds/PipelineBuildFacadeService.kt index eef2411b48d..0f96076ecbf 100644 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/service/builds/PipelineBuildFacadeService.kt +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/service/builds/PipelineBuildFacadeService.kt @@ -693,7 +693,6 @@ class PipelineBuildFacadeService( val triggerContainer = model.stages[0].containers[0] as TriggerContainer val paramPamp = buildParamCompatibilityTransformer.parseTriggerParam(triggerContainer.params, parameters) - return pipelineBuildService.startPipeline( userId = userId, pipeline = pipeline, diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/service/webhook/PipelineBuildWebhookService.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/service/webhook/PipelineBuildWebhookService.kt index 33dc4b0f019..8fc0ce5b8c7 100644 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/service/webhook/PipelineBuildWebhookService.kt +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/service/webhook/PipelineBuildWebhookService.kt @@ -28,11 +28,7 @@ package com.tencent.devops.process.service.webhook import com.fasterxml.jackson.databind.ObjectMapper -import com.fasterxml.jackson.module.kotlin.readValue -import com.tencent.devops.common.api.enums.RepositoryTypeNew -import com.tencent.devops.common.api.enums.ScmType import com.tencent.devops.common.api.util.JsonUtil -import com.tencent.devops.common.api.util.Watcher import com.tencent.devops.common.client.Client import com.tencent.devops.common.log.pojo.message.LogMessage import com.tencent.devops.common.log.utils.BuildLogPrinter @@ -40,28 +36,7 @@ import com.tencent.devops.common.pipeline.container.TriggerContainer import com.tencent.devops.common.pipeline.enums.ChannelCode import com.tencent.devops.common.pipeline.enums.StartType import com.tencent.devops.common.pipeline.pojo.BuildParameters -import com.tencent.devops.common.pipeline.pojo.element.trigger.CodeGitGenericWebHookTriggerElement -import com.tencent.devops.common.pipeline.pojo.element.trigger.CodeGitWebHookTriggerElement -import com.tencent.devops.common.pipeline.pojo.element.trigger.CodeGithubWebHookTriggerElement -import com.tencent.devops.common.pipeline.pojo.element.trigger.CodeGitlabWebHookTriggerElement -import com.tencent.devops.common.pipeline.pojo.element.trigger.CodeP4WebHookTriggerElement -import com.tencent.devops.common.pipeline.pojo.element.trigger.CodeSVNWebHookTriggerElement -import com.tencent.devops.common.pipeline.pojo.element.trigger.CodeTGitWebHookTriggerElement import com.tencent.devops.common.pipeline.pojo.element.trigger.WebHookTriggerElement -import com.tencent.devops.common.webhook.pojo.code.git.GitEvent -import com.tencent.devops.common.webhook.pojo.code.git.GitReviewEvent -import com.tencent.devops.common.webhook.pojo.code.github.GithubCheckRunEvent -import com.tencent.devops.common.webhook.pojo.code.github.GithubCommitCommentEvent -import com.tencent.devops.common.webhook.pojo.code.github.GithubCreateEvent -import com.tencent.devops.common.webhook.pojo.code.github.GithubEvent -import com.tencent.devops.common.webhook.pojo.code.github.GithubIssueCommentEvent -import com.tencent.devops.common.webhook.pojo.code.github.GithubIssuesEvent -import com.tencent.devops.common.webhook.pojo.code.github.GithubPullRequestEvent -import com.tencent.devops.common.webhook.pojo.code.github.GithubPushEvent -import com.tencent.devops.common.webhook.pojo.code.github.GithubReviewCommentEvent -import com.tencent.devops.common.webhook.pojo.code.github.GithubReviewEvent -import com.tencent.devops.common.webhook.pojo.code.p4.P4Event -import com.tencent.devops.common.webhook.pojo.code.svn.SvnCommitEvent import com.tencent.devops.common.webhook.service.code.loader.WebhookElementParamsRegistrar import com.tencent.devops.common.webhook.service.code.loader.WebhookStartParamsRegistrar import com.tencent.devops.common.webhook.service.code.matcher.ScmWebhookMatcher @@ -70,19 +45,23 @@ import com.tencent.devops.process.api.service.ServiceBuildResource import com.tencent.devops.process.api.service.ServiceScmWebhookResource import com.tencent.devops.process.engine.service.PipelineRepositoryService import com.tencent.devops.process.engine.service.PipelineWebHookQueueService -import com.tencent.devops.process.engine.service.PipelineWebhookBuildLogContext import com.tencent.devops.process.engine.service.PipelineWebhookService import com.tencent.devops.process.engine.service.WebhookBuildParameterService import com.tencent.devops.process.engine.service.code.GitWebhookUnlockDispatcher import com.tencent.devops.process.engine.service.code.ScmWebhookMatcherBuilder import com.tencent.devops.process.pojo.code.WebhookCommit +import com.tencent.devops.process.pojo.trigger.PipelineTriggerEvent +import com.tencent.devops.process.pojo.trigger.PipelineTriggerDetailBuilder +import com.tencent.devops.process.pojo.trigger.PipelineTriggerReason +import com.tencent.devops.process.pojo.trigger.PipelineTriggerReasonDetail +import com.tencent.devops.process.pojo.trigger.PipelineTriggerStatus +import com.tencent.devops.process.pojo.webhook.WebhookTriggerPipeline import com.tencent.devops.process.service.builds.PipelineBuildCommitService import com.tencent.devops.process.service.pipeline.PipelineBuildService +import com.tencent.devops.process.trigger.PipelineTriggerEventService import com.tencent.devops.process.utils.PIPELINE_START_TASK_ID import com.tencent.devops.process.utils.PipelineVarUtil -import com.tencent.devops.project.api.service.ServiceAllocIdResource import com.tencent.devops.repository.api.ServiceRepositoryResource -import com.tencent.devops.repository.utils.RepositoryUtils import org.slf4j.LoggerFactory import org.springframework.context.ApplicationContext import org.springframework.context.ApplicationContextAware @@ -103,6 +82,7 @@ abstract class PipelineBuildWebhookService : ApplicationContextAware { pipelinebuildWebhookService = applicationContext.getBean(PipelineBuildWebhookService::class.java) pipelineBuildCommitService = applicationContext.getBean(PipelineBuildCommitService::class.java) webhookBuildParameterService = applicationContext.getBean(WebhookBuildParameterService::class.java) + pipelineTriggerEventService = applicationContext.getBean(PipelineTriggerEventService::class.java) } companion object { @@ -118,170 +98,47 @@ abstract class PipelineBuildWebhookService : ApplicationContextAware { lateinit var pipelinebuildWebhookService: PipelineBuildWebhookService // 给AOP调用 lateinit var pipelineBuildCommitService: PipelineBuildCommitService lateinit var webhookBuildParameterService: WebhookBuildParameterService + lateinit var pipelineTriggerEventService: PipelineTriggerEventService private val logger = LoggerFactory.getLogger(PipelineBuildWebhookService::class.java) } - fun externalCodeSvnBuild(e: String): Boolean { - logger.info("Trigger code svn build - $e") - - val event = try { - objectMapper.readValue(e, SvnCommitEvent::class.java) - } catch (e: Exception) { - logger.warn("Fail to parse the svn web hook commit event", e) - return false - } - - val svnWebHookMatcher = scmWebhookMatcherBuilder.createSvnWebHookMatcher(event) - - return startProcessByWebhook(CodeSVNWebHookTriggerElement.classType, svnWebHookMatcher) - } - - fun externalCodeGitBuild(codeRepositoryType: String, event: String?, body: String): Boolean { - logger.info("Trigger code git build($body|$event)") - - val gitEvent = try { - if (event == "Review Hook") { - objectMapper.readValue(body) - } else { - objectMapper.readValue(body) - } - } catch (e: Exception) { - logger.warn("Fail to parse the git web hook commit event", e) - return false - } - - val gitWebHookMatcher = scmWebhookMatcherBuilder.createGitWebHookMatcher(gitEvent) - if (!gitWebHookMatcher.preMatch().isMatch) { - return true - } - - return startProcessByWebhook(codeRepositoryType, gitWebHookMatcher) - } - - fun externalGitlabBuild(e: String): Boolean { - logger.info("Trigger gitlab build($e)") - - val event = try { - objectMapper.readValue(e, GitEvent::class.java) - } catch (e: Exception) { - logger.warn("Fail to parse the gitlab web hook commit event", e) - return false - } - - val gitlabWebHookMatcher = scmWebhookMatcherBuilder.createGitlabWebHookMatcher(event) - - return startProcessByWebhook(CodeGitlabWebHookTriggerElement.classType, gitlabWebHookMatcher) - } - - fun externalCodeGithubBuild(eventType: String, guid: String, signature: String, body: String): Boolean { - logger.info("Trigger code github build (event=$eventType, guid=$guid, signature=$signature, body=$body)") - - val event: GithubEvent = when (eventType) { - GithubPushEvent.classType -> objectMapper.readValue(body) - GithubCreateEvent.classType -> objectMapper.readValue(body) - GithubPullRequestEvent.classType -> objectMapper.readValue(body) - GithubCheckRunEvent.classType -> objectMapper.readValue(body) - GithubCommitCommentEvent.classType -> objectMapper.readValue(body) - GithubIssueCommentEvent.classType -> objectMapper.readValue(body) - GithubReviewCommentEvent.classType -> objectMapper.readValue(body) - GithubIssuesEvent.classType -> objectMapper.readValue(body) - GithubReviewEvent.classType -> objectMapper.readValue(body) - else -> { - logger.info("Github event($eventType) is ignored") - return true - } - } - val githubWebHookMatcher = scmWebhookMatcherBuilder.createGithubWebHookMatcher(event) - if (!githubWebHookMatcher.preMatch().isMatch) { - return true - } - if (event is GithubCheckRunEvent) { - if (event.action != "rerequested") { - logger.info("Unsupported check run action:${event.action}") - return true - } - if (event.checkRun.externalId == null) { - logger.info("github check run externalId is empty") - return true - } - val buildInfo = event.checkRun.externalId!!.split("_") - if (buildInfo.size < 4) { - logger.info("the buildInfo of github check run is error") - return true - } - client.get(ServiceBuildResource::class).retry( - userId = buildInfo[0], - projectId = buildInfo[1], - pipelineId = buildInfo[2], - buildId = buildInfo[3], - channelCode = ChannelCode.BS - ) - return true - } - return startProcessByWebhook(CodeGithubWebHookTriggerElement.classType, githubWebHookMatcher) - } - - fun externalP4Build(body: String): Boolean { - logger.info("Trigger p4 build($body)") - - val event = try { - objectMapper.readValue(body, P4Event::class.java) - } catch (e: Exception) { - logger.warn("Fail to parse the p4 web hook event", e) - return false - } - - val p4WebHookMatcher = scmWebhookMatcherBuilder.createP4WebHookMatcher(event) - - return startProcessByWebhook(CodeP4WebHookTriggerElement.classType, p4WebHookMatcher) - } - - private fun startProcessByWebhook(codeRepositoryType: String, matcher: ScmWebhookMatcher): Boolean { - val watcher = Watcher("${matcher.getRepoName()}|${matcher.getRevision()}|webhook trigger") - PipelineWebhookBuildLogContext.addRepoInfo(repoName = matcher.getRepoName(), commitId = matcher.getRevision()) + fun dispatchTriggerPipelines( + matcher: ScmWebhookMatcher, + triggerEvent: PipelineTriggerEvent, + triggerPipelines: List + ): Boolean { try { - watcher.start("getWebhookPipelines") - logger.info("startProcessByWebhook|repo(${matcher.getRepoName()})|type($codeRepositoryType)") - val pipelines = pipelineWebhookService.getWebhookPipelines( - name = matcher.getRepoName(), - type = codeRepositoryType - ) + logger.info("dispatch pipeline webhook subscriber|repo(${matcher.getRepoName()})") - if (pipelines.isEmpty()) { + if (triggerPipelines.isEmpty()) { gitWebhookUnlockDispatcher.dispatchUnlockHookLockEvent(matcher) return false } - watcher.start("webhookTriggerPipelineBuild") EventCacheUtil.initEventCache() - pipelines.forEach outside@{ pipeline -> - val projectId = pipeline.first - val pipelineId = pipeline.second + // 代码库触发的事件ID,一个代码库会触发多条流水线,但应该只有一条触发事件 + val repoEventIdMap = mutableMapOf() + triggerPipelines.forEach outside@{ subscriber -> + val projectId = subscriber.projectId + val pipelineId = subscriber.pipelineId try { logger.info("pipelineId is $pipelineId") - val model = pipelineRepositoryService.getModel(projectId, pipelineId) ?: run { - logger.info("$pipelineId|pipeline does not exists, ignore") - return@outside - } + val builder = PipelineTriggerDetailBuilder() + .projectId(projectId) + .pipelineId(pipelineId) - /** - * 验证流水线参数构建启动参数 - */ - val triggerContainer = model.stages[0].containers[0] as TriggerContainer - val canWebhookStartup = canWebhookStartup(triggerContainer, codeRepositoryType) - - if (!canWebhookStartup) { - logger.info("$pipelineId|can not start by $codeRepositoryType, ignore") - return@outside - } - - if (pipelinebuildWebhookService.webhookTriggerPipelineBuild( - projectId = projectId, - pipelineId = pipelineId, - codeRepositoryType = codeRepositoryType, - matcher = matcher - ) - ) return@outside + webhookTriggerPipelineBuild( + projectId = projectId, + pipelineId = pipelineId, + matcher = matcher, + builder = builder + ) + saveTriggerEvent( + projectId = projectId, + builder = builder, + triggerEvent = triggerEvent, + repoEventIdMap = repoEventIdMap + ) } catch (e: Throwable) { logger.warn("[$pipelineId]|webhookTriggerPipelineBuild fail: $e", e) } @@ -302,65 +159,39 @@ abstract class PipelineBuildWebhookService : ApplicationContextAware { ) } EventCacheUtil.remove() - logger.info("$watcher") } } - private fun canWebhookStartup( - triggerContainer: TriggerContainer, - codeRepositoryType: String - ): Boolean { - var canWebhookStartup = false - run lit@{ - triggerContainer.elements.forEach { - when (codeRepositoryType) { - CodeSVNWebHookTriggerElement.classType -> { - if ((it is CodeSVNWebHookTriggerElement && it.isElementEnable())) { - canWebhookStartup = true - return@lit - } - } - CodeGitWebHookTriggerElement.classType -> { - if ((it is CodeGitWebHookTriggerElement && it.isElementEnable())) { - canWebhookStartup = true - return@lit - } - } - CodeGithubWebHookTriggerElement.classType -> { - if ((it is CodeGithubWebHookTriggerElement && it.isElementEnable())) { - canWebhookStartup = true - return@lit - } - } - CodeGitlabWebHookTriggerElement.classType -> { - if ((it is CodeGitlabWebHookTriggerElement && it.isElementEnable())) { - canWebhookStartup = true - return@lit - } - } - CodeTGitWebHookTriggerElement.classType -> { - if ((it is CodeTGitWebHookTriggerElement && it.isElementEnable())) { - canWebhookStartup = true - return@lit - } - } - CodeP4WebHookTriggerElement.classType -> { - if (it is CodeP4WebHookTriggerElement && it.isElementEnable()) { - canWebhookStartup = true - return@lit - } - } - } + private fun saveTriggerEvent( + projectId: String, + builder: PipelineTriggerDetailBuilder, + triggerEvent: PipelineTriggerEvent, + repoEventIdMap: MutableMap + ) { + if (!builder.getEventSource().isNullOrBlank()) { + triggerEvent.eventSource = builder.getEventSource() + triggerEvent.projectId = projectId + val eventId = repoEventIdMap[builder.getEventSource()] ?: run { + val eventId = pipelineTriggerEventService.getEventId( + projectId = projectId, requestId = triggerEvent.requestId, eventSource = triggerEvent.eventSource!! + ) + repoEventIdMap[builder.getEventSource()!!] = eventId + eventId } + triggerEvent.eventId = eventId + builder.eventId(eventId) + pipelineTriggerEventService.saveEvent( + triggerEvent = triggerEvent, + triggerDetail = builder.build() + ) } - return canWebhookStartup } open fun webhookTriggerPipelineBuild( projectId: String, pipelineId: String, - codeRepositoryType: String, - matcher: ScmWebhookMatcher + matcher: ScmWebhookMatcher, + builder: PipelineTriggerDetailBuilder ): Boolean { val pipelineInfo = pipelineRepositoryService.getPipelineInfo(projectId, pipelineId) ?: return false @@ -370,7 +201,8 @@ abstract class PipelineBuildWebhookService : ApplicationContextAware { logger.warn("[$pipelineId]| Fail to get the model") return false } - + // 触发事件保存流水线名称 + builder.pipelineName(pipelineInfo.pipelineName) val userId = pipelineInfo.lastModifyUser val variables = mutableMapOf() val container = model.stages[0].containers[0] as TriggerContainer @@ -396,24 +228,11 @@ abstract class PipelineBuildWebhookService : ApplicationContextAware { logger.info("$pipelineId|${element.name}|Get the code trigger pipeline") // #2958 如果仓库找不到,会抛出404异常,就不会继续往下遍历 val repo = try { - if (element is CodeGitGenericWebHookTriggerElement && - element.data.input.repositoryType == RepositoryTypeNew.URL - ) { - RepositoryUtils.buildRepository( - projectId = pipelineInfo.projectId, - userName = pipelineInfo.lastModifyUser, - scmType = ScmType.valueOf(element.data.input.scmType), - repositoryUrl = repositoryConfig.repositoryName!!, - credentialId = element.data.input.credentialId - ) - } else { - client.get(ServiceRepositoryResource::class) - .get( - projectId, - repositoryConfig.getURLEncodeRepositoryId(), - repositoryConfig.repositoryType - ).data - } + client.get(ServiceRepositoryResource::class).get( + projectId, + repositoryConfig.getURLEncodeRepositoryId(), + repositoryConfig.repositoryType + ).data } catch (e: Exception) { null } @@ -446,16 +265,6 @@ abstract class PipelineBuildWebhookService : ApplicationContextAware { ) val buildId = client.getGateway(ServiceScmWebhookResource::class).webhookCommit(projectId, webhookCommit).data - PipelineWebhookBuildLogContext.addLogBuildInfo( - projectId = projectId, - pipelineId = pipelineId, - taskId = element.id!!, - taskName = element.name, - success = true, - triggerResult = buildId, - id = client.get(ServiceAllocIdResource::class) - .generateSegmentId("PIPELINE_WEBHOOK_BUILD_LOG_DETAIL").data - ) logger.info("$pipelineId|$buildId|webhook trigger|(${element.name}|repo(${matcher.getRepoName()})") if (!buildId.isNullOrEmpty()) { pipelineBuildCommitService.create( @@ -465,6 +274,18 @@ abstract class PipelineBuildWebhookService : ApplicationContextAware { matcher = matcher, repo = repo ) + val buildDetail = client.getGateway(ServiceBuildResource::class).getBuildDetail( + userId = userId, + buildId = buildId, + pipelineId = pipelineId, + projectId = projectId, + channelCode = ChannelCode.BS + ).data + builder.buildId(buildId) + .status(PipelineTriggerStatus.SUCCEED.name) + .eventSource(eventSource = repo.repoHashId!!) + .reason(PipelineTriggerReason.TRIGGER_SUCCESS.name) + .buildNum(buildDetail?.buildNum.toString()) } } catch (ignore: Exception) { logger.warn("$pipelineId|webhook trigger|(${element.name})|repo(${matcher.getRepoName()})", ignore) @@ -474,8 +295,24 @@ abstract class PipelineBuildWebhookService : ApplicationContextAware { logger.info( "$pipelineId|webhook trigger match unsuccess|(${element.name})|repo(${matcher.getRepoName()})" ) + if (!matchResult.reason.isNullOrBlank()) { + builder.eventSource(eventSource = repo.repoHashId!!) + .reasonDetail(JsonUtil.toJson( + PipelineTriggerReasonDetail( + elementId = element.id, + elementName = element.name, + elementAtomCode = element.getAtomCode(), + reasonMsg = matchResult.reason!! + ) + )) + } } } + + // 历史原因,webhook表没有记录eventType,所以查找出来的订阅者可能因为事件类型不匹配,事件不需要记录 + if (!builder.getEventSource().isNullOrBlank()) { + builder.status(PipelineTriggerStatus.FAILED.name).reason(PipelineTriggerReason.TRIGGER_NOT_MATCH.name) + } return false } diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/trigger/PipelineTriggerEventAspect.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/trigger/PipelineTriggerEventAspect.kt new file mode 100644 index 00000000000..e4a8c80dac7 --- /dev/null +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/trigger/PipelineTriggerEventAspect.kt @@ -0,0 +1,303 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package com.tencent.devops.process.trigger + +import com.tencent.devops.common.api.pojo.I18Variable +import com.tencent.devops.common.pipeline.enums.ChannelCode +import com.tencent.devops.common.pipeline.enums.StartType +import com.tencent.devops.common.pipeline.pojo.BuildParameters +import com.tencent.devops.common.service.trace.TraceTag +import com.tencent.devops.common.webhook.enums.WebhookI18nConstants.MANUAL_START_EVENT_DESC +import com.tencent.devops.common.webhook.enums.WebhookI18nConstants.OPENAPI_START_EVENT_DESC +import com.tencent.devops.common.webhook.enums.WebhookI18nConstants.PIPELINE_START_EVENT_DESC +import com.tencent.devops.common.webhook.enums.WebhookI18nConstants.REMOTE_START_EVENT_DESC +import com.tencent.devops.common.webhook.enums.WebhookI18nConstants.TIMING_START_EVENT_DESC +import com.tencent.devops.process.engine.pojo.PipelineInfo +import com.tencent.devops.process.pojo.BuildId +import com.tencent.devops.process.pojo.trigger.PipelineTriggerDetail +import com.tencent.devops.process.pojo.trigger.PipelineTriggerDetailBuilder +import com.tencent.devops.process.pojo.trigger.PipelineTriggerEvent +import com.tencent.devops.process.pojo.trigger.PipelineTriggerEventBuilder +import com.tencent.devops.process.pojo.trigger.PipelineTriggerReason +import com.tencent.devops.process.pojo.trigger.PipelineTriggerStatus +import com.tencent.devops.process.pojo.trigger.PipelineTriggerType +import com.tencent.devops.process.utils.PIPELINE_RETRY_BUILD_ID +import com.tencent.devops.process.utils.PIPELINE_START_PARENT_BUILD_ID +import com.tencent.devops.process.utils.PIPELINE_START_PARENT_PIPELINE_ID +import com.tencent.devops.process.utils.PIPELINE_START_PARENT_PIPELINE_NAME +import com.tencent.devops.process.utils.PIPELINE_START_PARENT_PROJECT_ID +import com.tencent.devops.process.utils.PIPELINE_START_REMOTE_CLIENT_IP +import org.aspectj.lang.ProceedingJoinPoint +import org.aspectj.lang.annotation.Around +import org.aspectj.lang.annotation.Aspect +import org.aspectj.lang.reflect.MethodSignature +import org.slf4j.LoggerFactory +import org.slf4j.MDC +import org.springframework.stereotype.Service +import java.time.LocalDateTime + +@Service +@Aspect +class PipelineTriggerEventAspect( + private val triggerEventService: PipelineTriggerEventService +) { + + companion object { + private val logger = LoggerFactory.getLogger(PipelineTriggerEventAspect::class.java) + } + + @Around("execution(* com.tencent.devops.process.service.pipeline.PipelineBuildService.startPipeline(..))") + fun aroundStartPipeline(pjp: ProceedingJoinPoint): Any? { + var result: Any? = null + var exception: Throwable? = null + try { + result = pjp.proceed() + return result + } catch (e: Throwable) { + exception = e + throw e + } finally { + saveTriggerEvent(pjp = pjp, result = result, exception = exception) + } + } + + private fun saveTriggerEvent(pjp: ProceedingJoinPoint, result: Any?, exception: Throwable?) { + try { + // 参数value + val parameterValue = pjp.args + // 参数key + val parameterNames = (pjp.signature as MethodSignature).parameterNames + var pipeline: PipelineInfo? = null + var userId: String? = null + var channelCode: ChannelCode? = null + var startValues: Map? = null + var pipelineParamMap: MutableMap? = null + var startType: StartType? = null + + for (index in parameterValue.indices) { + when (parameterNames[index]) { + "pipeline" -> pipeline = parameterValue[index] as PipelineInfo + "userId" -> userId = parameterValue[index]?.toString() + "channelCode" -> channelCode = parameterValue[index] as ChannelCode + "startValues" -> startValues = parameterValue[index] as Map? + "startType" -> startType = parameterValue[index] as StartType + "pipelineParamMap" -> + pipelineParamMap = parameterValue[index] as MutableMap? + else -> Unit + } + } + // 判断是否应该跳过保存触发事件 + val isSkip = skipSaveTriggerEvent( + pipeline = pipeline, + userId = userId, + channelCode = channelCode, + startType = startType, + pipelineParamMap = pipelineParamMap, + result = result, + exception = exception + ) + if (isSkip) { + return + } + val triggerEvent = + buildTriggerEvent( + userId = userId!!, + projectId = pipeline!!.projectId, + startValues = startValues, + pipelineParamMap = pipelineParamMap, + startType = startType!! + ) ?: return + + val triggerDetail = buildTriggerDetail( + pipeline = pipeline, + eventId = triggerEvent.eventId!!, + result = result, + exception = exception + ) + triggerEventService.saveEvent( + triggerEvent = triggerEvent, + triggerDetail = triggerDetail + ) + } catch (ignored: Throwable) { + // 为了不影响业务,保存事件异常不抛出 + logger.warn("Failed to save trigger event", ignored) + } + } + + @Suppress("ComplexCondition") + private fun skipSaveTriggerEvent( + pipeline: PipelineInfo?, + userId: String?, + channelCode: ChannelCode?, + startType: StartType?, + pipelineParamMap: MutableMap?, + result: Any?, + exception: Throwable? + ): Boolean { + if (result == null && exception == null) { + return true + } + if (pipeline == null || userId == null || channelCode == null || startType == null) { + return true + } + // 不是BS渠道的不需要记录,webhook的在webhook触发时已记录,在这不需要记录 + if (channelCode != ChannelCode.BS || startType == StartType.WEB_HOOK) { + return true + } + // 重试不需要记录 + return pipelineParamMap != null && pipelineParamMap[PIPELINE_RETRY_BUILD_ID] != null + } + + @Suppress("ComplexCondition") + private fun buildTriggerEvent( + userId: String, + projectId: String, + startValues: Map?, + pipelineParamMap: MutableMap?, + startType: StartType + ): PipelineTriggerEvent? { + val requestId = MDC.get(TraceTag.BIZID) + val eventId = triggerEventService.getEventId() + val triggerEventBuilder = PipelineTriggerEventBuilder() + triggerEventBuilder.requestId(requestId) + triggerEventBuilder.projectId(projectId) + triggerEventBuilder.eventId(eventId) + triggerEventBuilder.triggerUser(userId) + triggerEventBuilder.createTime(LocalDateTime.now()) + startValues?.let { triggerEventBuilder.requestParams(it) } + + when (startType) { + StartType.MANUAL -> { + triggerEventBuilder.triggerType(PipelineTriggerType.MANUAL.name) + triggerEventBuilder.eventSource(userId) + triggerEventBuilder.eventType(PipelineTriggerType.MANUAL.name) + triggerEventBuilder.eventDesc( + I18Variable( + code = MANUAL_START_EVENT_DESC, + params = listOf(userId) + ).toJsonStr() + ) + } + + StartType.REMOTE -> { + val eventSource = startValues?.get(PIPELINE_START_REMOTE_CLIENT_IP) ?: userId + triggerEventBuilder.triggerType(PipelineTriggerType.REMOTE.name) + triggerEventBuilder.eventSource(eventSource) + triggerEventBuilder.eventType(PipelineTriggerType.REMOTE.name) + triggerEventBuilder.eventDesc( + I18Variable( + code = REMOTE_START_EVENT_DESC, + params = listOf(eventSource, userId) + ).toJsonStr() + ) + } + + StartType.TIME_TRIGGER -> { + triggerEventBuilder.triggerType(PipelineTriggerType.TIME_TRIGGER.name) + triggerEventBuilder.eventSource(userId) + triggerEventBuilder.eventType(PipelineTriggerType.TIME_TRIGGER.name) + triggerEventBuilder.eventDesc( + I18Variable( + code = TIMING_START_EVENT_DESC, + params = listOf(userId) + ).toJsonStr() + ) + } + + StartType.PIPELINE -> { + val parentProjectId = pipelineParamMap?.get(PIPELINE_START_PARENT_PROJECT_ID)?.value?.toString() + val parentPipelineId = pipelineParamMap?.get(PIPELINE_START_PARENT_PIPELINE_ID)?.value?.toString() + val parentPipelineName = pipelineParamMap?.get(PIPELINE_START_PARENT_PIPELINE_NAME)?.value?.toString() + val parentBuildId = pipelineParamMap?.get(PIPELINE_START_PARENT_BUILD_ID)?.value?.toString() + if (parentProjectId == null || parentPipelineId == null || + parentBuildId == null || parentPipelineName == null + ) { + return null + } + triggerEventBuilder.triggerType(PipelineTriggerType.PIPELINE.name) + triggerEventBuilder.eventSource(parentPipelineId) + triggerEventBuilder.eventType(PipelineTriggerType.PIPELINE.name) + triggerEventBuilder.eventDesc( + I18Variable( + code = PIPELINE_START_EVENT_DESC, + params = listOf( + userId, + "/console/pipeline/$parentProjectId/$parentPipelineId/detail/$parentBuildId", + parentPipelineName + ) + ).toJsonStr() + ) + } + // 目前channel为BS的,只有openapi的startType为service + StartType.SERVICE -> { + triggerEventBuilder.triggerType(PipelineTriggerType.OPENAPI.name) + triggerEventBuilder.eventSource(userId) + triggerEventBuilder.eventType(PipelineTriggerType.OPENAPI.name) + triggerEventBuilder.eventDesc( + I18Variable( + code = OPENAPI_START_EVENT_DESC, + params = listOf(userId) + ).toJsonStr() + ) + } + + else -> return null + } + return triggerEventBuilder.build() + } + + private fun buildTriggerDetail( + pipeline: PipelineInfo, + eventId: Long, + result: Any?, + exception: Throwable? + ): PipelineTriggerDetail { + val triggerDetailBuilder = PipelineTriggerDetailBuilder() + triggerDetailBuilder.eventId(eventId) + triggerDetailBuilder.projectId(pipeline.projectId) + triggerDetailBuilder.pipelineId(pipelineId = pipeline.pipelineId) + triggerDetailBuilder.pipelineName(pipeline.pipelineName) + + when { + result != null -> { + val buildId = result as BuildId + triggerDetailBuilder.status(PipelineTriggerStatus.SUCCEED.name) + triggerDetailBuilder.buildId(buildId.id) + triggerDetailBuilder.buildNum(buildId.num?.toString() ?: "") + } + + exception != null -> { + triggerDetailBuilder.status(PipelineTriggerStatus.FAILED.name) + triggerDetailBuilder.reason(PipelineTriggerReason.TRIGGER_FAILED.name) + triggerDetailBuilder.reasonDetail(exception.message ?: "unknown error") + } + } + return triggerDetailBuilder.build() + } +} diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/trigger/PipelineTriggerEventService.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/trigger/PipelineTriggerEventService.kt new file mode 100644 index 00000000000..ff54a300504 --- /dev/null +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/trigger/PipelineTriggerEventService.kt @@ -0,0 +1,478 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package com.tencent.devops.process.trigger + +import com.fasterxml.jackson.core.type.TypeReference +import com.tencent.devops.common.api.exception.ErrorCodeException +import com.tencent.devops.common.api.exception.ParamBlankException +import com.tencent.devops.common.api.model.SQLPage +import com.tencent.devops.common.api.pojo.I18Variable +import com.tencent.devops.common.api.util.JsonUtil +import com.tencent.devops.common.api.util.PageUtil +import com.tencent.devops.common.api.util.timestampmilli +import com.tencent.devops.common.client.Client +import com.tencent.devops.common.service.trace.TraceTag +import com.tencent.devops.common.service.utils.HomeHostUtil +import com.tencent.devops.common.web.utils.I18nUtil +import com.tencent.devops.common.web.utils.I18nUtil.getCodeLanMessage +import com.tencent.devops.common.webhook.enums.WebhookI18nConstants.EVENT_REPLAY_DESC +import com.tencent.devops.process.constant.ProcessMessageCode +import com.tencent.devops.process.constant.ProcessMessageCode.ERROR_TRIGGER_DETAIL_NOT_FOUND +import com.tencent.devops.process.constant.ProcessMessageCode.ERROR_TRIGGER_REPLAY_PIPELINE_NOT_EMPTY +import com.tencent.devops.process.dao.PipelineTriggerEventDao +import com.tencent.devops.process.pojo.trigger.PipelineTriggerDetail +import com.tencent.devops.process.pojo.trigger.PipelineTriggerEvent +import com.tencent.devops.process.pojo.trigger.PipelineTriggerEventVo +import com.tencent.devops.process.pojo.trigger.PipelineTriggerReason +import com.tencent.devops.process.pojo.trigger.PipelineTriggerReasonDetail +import com.tencent.devops.process.pojo.trigger.PipelineTriggerStatus +import com.tencent.devops.process.pojo.trigger.PipelineTriggerType +import com.tencent.devops.process.pojo.trigger.RepoTriggerEventVo +import com.tencent.devops.process.webhook.CodeWebhookEventDispatcher +import com.tencent.devops.process.webhook.pojo.event.commit.ReplayWebhookEvent +import com.tencent.devops.project.api.service.ServiceAllocIdResource +import org.jooq.DSLContext +import org.jooq.impl.DSL +import org.slf4j.LoggerFactory +import org.slf4j.MDC +import org.springframework.amqp.rabbit.core.RabbitTemplate +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.stereotype.Service +import java.text.MessageFormat +import java.time.LocalDateTime + +@Suppress("ALL") +@Service +class PipelineTriggerEventService @Autowired constructor( + private val dslContext: DSLContext, + private val client: Client, + private val pipelineTriggerEventDao: PipelineTriggerEventDao, + private val rabbitTemplate: RabbitTemplate +) { + + companion object { + private val logger = LoggerFactory.getLogger(PipelineTriggerEventService::class.java) + private const val PIPELINE_TRIGGER_EVENT_BIZ_ID = "PIPELINE_TRIGGER_EVENT" + private const val PIPELINE_TRIGGER_DETAIL_BIZ_ID = "PIPELINE_TRIGGER_DETAIL" + // 构建链接 + const val PIPELINE_BUILD_URL_PATTERN = "#{1}" + } + + fun getDetailId(): Long { + return client.get(ServiceAllocIdResource::class).generateSegmentId(PIPELINE_TRIGGER_DETAIL_BIZ_ID).data ?: 0 + } + + fun getEventId(): Long { + return client.get(ServiceAllocIdResource::class).generateSegmentId(PIPELINE_TRIGGER_EVENT_BIZ_ID).data ?: 0 + } + + fun getEventId(projectId: String, requestId: String, eventSource: String): Long { + return pipelineTriggerEventDao.getEventByRequestId( + dslContext = dslContext, + projectId = projectId, + requestId = requestId, + eventSource = eventSource + )?.eventId ?: getEventId() + } + + fun saveEvent( + triggerEvent: PipelineTriggerEvent, + triggerDetail: PipelineTriggerDetail + ) { + triggerDetail.detailId = getDetailId() + dslContext.transaction { configuration -> + val transactionContext = DSL.using(configuration) + pipelineTriggerEventDao.save( + dslContext = transactionContext, + triggerEvent = triggerEvent + ) + pipelineTriggerEventDao.saveDetail( + dslContext = transactionContext, + triggerDetail = triggerDetail + ) + } + } + + fun listPipelineTriggerEvent( + userId: String, + projectId: String, + pipelineId: String, + eventType: String?, + triggerType: String?, + triggerUser: String?, + startTime: Long?, + endTime: Long?, + page: Int?, + pageSize: Int? + ): SQLPage { + val pageNotNull = page ?: 0 + val pageSizeNotNull = pageSize ?: PageUtil.MAX_PAGE_SIZE + val sqlLimit = PageUtil.convertPageSizeToSQLMAXLimit(pageNotNull, pageSizeNotNull) + val language = I18nUtil.getLanguage(userId) + val count = pipelineTriggerEventDao.countTriggerDetail( + dslContext = dslContext, + projectId = projectId, + eventType = eventType, + triggerType = triggerType, + triggerUser = triggerUser, + pipelineId = pipelineId, + startTime = startTime, + endTime = endTime + ) + val records = pipelineTriggerEventDao.listTriggerDetail( + dslContext = dslContext, + projectId = projectId, + eventType = eventType, + triggerUser = triggerUser, + triggerType = triggerType, + pipelineId = pipelineId, + startTime = startTime, + endTime = endTime, + limit = sqlLimit.limit, + offset = sqlLimit.offset + ).map { + it.eventDesc = it.getI18nEventDesc(language) + it.reason = getI18nReason(it.reason, language) + it + } + return SQLPage(count = count, records = records) + } + + fun listRepoTriggerEvent( + projectId: String, + repoHashId: String, + triggerType: String?, + eventType: String?, + triggerUser: String?, + pipelineId: String?, + eventId: Long?, + pipelineName: String?, + startTime: Long?, + endTime: Long?, + page: Int?, + pageSize: Int?, + userId: String + ): SQLPage { + val pageNotNull = page ?: 0 + val pageSizeNotNull = pageSize ?: PageUtil.MAX_PAGE_SIZE + val sqlLimit = PageUtil.convertPageSizeToSQLMAXLimit(pageNotNull, pageSizeNotNull) + val language = I18nUtil.getLanguage(userId) + // 事件ID to 总数 + val (eventIds, count) = if (pipelineName.isNullOrBlank() && pipelineId.isNullOrBlank()) { + val eventIds = pipelineTriggerEventDao.getEventIdsByEvent( + dslContext = dslContext, + projectId = projectId, + eventSource = repoHashId, + eventId = eventId, + eventType = eventType, + triggerUser = triggerUser, + triggerType = triggerType, + startTime = startTime, + endTime = endTime, + limit = sqlLimit.limit, + offset = sqlLimit.offset + ) + val count = pipelineTriggerEventDao.getCountByEvent( + dslContext = dslContext, + eventId = eventId, + projectId = projectId, + eventSource = repoHashId, + eventType = eventType, + triggerType = triggerType, + triggerUser = triggerUser, + startTime = startTime, + endTime = endTime + ) + eventIds to count + } else { + val eventIds = pipelineTriggerEventDao.getDetailEventIds( + dslContext = dslContext, + projectId = projectId, + eventSource = repoHashId, + eventId = eventId, + eventType = eventType, + triggerUser = triggerUser, + triggerType = triggerType, + startTime = startTime, + endTime = endTime, + pipelineName = pipelineName, + pipelineId = pipelineId, + limit = sqlLimit.limit, + offset = sqlLimit.offset + ) + val count = pipelineTriggerEventDao.getCountByDetail( + dslContext = dslContext, + projectId = projectId, + eventSource = repoHashId, + eventId = eventId, + eventType = eventType, + triggerUser = triggerUser, + triggerType = triggerType, + startTime = startTime, + endTime = endTime, + pipelineName = pipelineName, + pipelineId = pipelineId + ) + eventIds to count + } + // 事件信息 + val triggerEvent = pipelineTriggerEventDao.listRepoTriggerEvent( + dslContext = dslContext, + eventIds = eventIds + ) + // 触发详情记录(总数,成功数) + val eventDetailsMap = pipelineTriggerEventDao.listRepoTriggerDetail( + dslContext = dslContext, + projectId = projectId, + eventIds = eventIds, + pipelineName = pipelineName, + pipelineId = pipelineId + ).associateBy { it.eventId } + val records = triggerEvent.map { + RepoTriggerEventVo( + projectId = it.projectId, + eventId = it.eventId, + repoHashId = it.eventSource, + eventDesc = try { + JsonUtil.to(it.eventDesc, I18Variable::class.java).getCodeLanMessage(language) + } catch (ignored: Exception) { + logger.warn("Failed to resolve repo trigger event|sourceDesc[${it.eventDesc}]", ignored) + it.eventDesc + }, + eventTime = it.createTime.timestampmilli(), + total = eventDetailsMap[it.eventId]?.total ?: 0, + success = eventDetailsMap[it.eventId]?.success ?: 0 + ) + } + return SQLPage(count = count, records = records) + } + + fun listRepoTriggerEventDetail( + projectId: String, + eventId: Long, + pipelineId: String?, + pipelineName: String?, + page: Int?, + pageSize: Int?, + userId: String + ): SQLPage { + if (projectId.isBlank()) { + throw ParamBlankException("Invalid projectId") + } + val pageNotNull = page ?: 0 + val pageSizeNotNull = pageSize ?: PageUtil.MAX_PAGE_SIZE + val sqlLimit = PageUtil.convertPageSizeToSQLMAXLimit(pageNotNull, pageSizeNotNull) + val language = I18nUtil.getLanguage(userId) + val records = pipelineTriggerEventDao.listTriggerDetail( + dslContext = dslContext, + projectId = projectId, + eventId = eventId, + pipelineId = pipelineId, + pipelineName = pipelineName, + limit = sqlLimit.limit, + offset = sqlLimit.offset + ).map { + fillEventDetailParam(it, language) + } + val count = pipelineTriggerEventDao.countTriggerDetail( + dslContext = dslContext, + projectId = projectId, + eventId = eventId, + pipelineId = pipelineId, + pipelineName = pipelineName + ) + return SQLPage(count = count, records = records) + } + + fun replay( + userId: String, + projectId: String, + detailId: Long + ): Boolean { + logger.info("replay pipeline trigger event|$userId|$projectId|$detailId") + val triggerDetail = pipelineTriggerEventDao.getTriggerDetail( + dslContext = dslContext, + projectId = projectId, + detailId = detailId + ) ?: throw ErrorCodeException( + errorCode = ERROR_TRIGGER_DETAIL_NOT_FOUND, + params = arrayOf(detailId.toString()) + ) + val pipelineId = triggerDetail.pipelineId ?: throw ErrorCodeException( + errorCode = ERROR_TRIGGER_REPLAY_PIPELINE_NOT_EMPTY, + params = arrayOf(detailId.toString()) + ) + replayAll( + userId = userId, + projectId = projectId, + eventId = triggerDetail.eventId, + pipelineId = pipelineId + ) + return true + } + + fun replayAll( + userId: String, + projectId: String, + eventId: Long, + pipelineId: String? = null + ): Boolean { + logger.info("replay all pipeline trigger event|$userId|$projectId|$eventId") + val triggerEvent = pipelineTriggerEventDao.getTriggerEvent( + dslContext = dslContext, + projectId = projectId, + eventId = eventId + ) ?: throw ErrorCodeException( + errorCode = ProcessMessageCode.ERROR_TRIGGER_EVENT_NOT_FOUND, + params = arrayOf(eventId.toString()) + ) + val scmType = PipelineTriggerType.toScmType(triggerEvent.triggerType) ?: throw ErrorCodeException( + errorCode = ProcessMessageCode.ERROR_TRIGGER_TYPE_REPLAY_NOT_SUPPORT, + params = arrayOf(triggerEvent.triggerType) + ) + // 保存重放事件 + val requestId = MDC.get(TraceTag.BIZID) + val replayEventId = getEventId() + // 如果重试的事件也由重试产生,则应该记录最开始的请求ID + val replayRequestId = triggerEvent.replayRequestId ?: triggerEvent.requestId + val replayTriggerEvent = with(triggerEvent) { + PipelineTriggerEvent( + requestId = requestId, + projectId = projectId, + eventId = replayEventId, + triggerType = triggerType, + eventSource = eventSource, + eventType = eventType, + triggerUser = userId, + eventDesc = I18Variable( + code = EVENT_REPLAY_DESC, + params = listOf(eventId.toString(), userId) + ).toJsonStr(), + replayRequestId = replayRequestId, + requestParams = requestParams, + createTime = LocalDateTime.now() + ) + } + pipelineTriggerEventDao.save( + dslContext = dslContext, + triggerEvent = replayTriggerEvent + ) + CodeWebhookEventDispatcher.dispatchReplayEvent( + rabbitTemplate = rabbitTemplate, + event = ReplayWebhookEvent( + userId = userId, + projectId = projectId, + eventId = replayEventId, + replayRequestId = replayRequestId, + scmType = scmType, + pipelineId = pipelineId + ) + ) + return true + } + + /** + * 获取国际化构建事件描述 + */ + private fun PipelineTriggerEventVo.getI18nEventDesc(language: String) = try { + JsonUtil.to(eventDesc, I18Variable::class.java).getCodeLanMessage(language) + } catch (ignored: Exception) { + logger.warn("Failed to resolve repo trigger event|sourceDesc[$eventDesc]", ignored) + eventDesc + } + + /** + * 获取国际化构建事件详情描述 + */ + private fun PipelineTriggerEventVo.getI18nReasonDetailDesc(language: String): List = try { + logger.info("get pipeline trigger event detail desc,source[$eventDesc]") + if (reasonDetailList.isNullOrEmpty()) { + listOf() + } else { + reasonDetailList!!.map { + val reasonDetail = JsonUtil.to(it, PipelineTriggerReasonDetail::class.java) + // 国际化触发失败原因 + val i18nReason = JsonUtil.to( + json = reasonDetail.reasonMsg, + typeReference = object : TypeReference() {} + ).getCodeLanMessage(language) + // 详情格式: {{触发器名称}}|{{国际化后的触发失败原因}} + "${reasonDetail.elementName} | $i18nReason" + } + } + } catch (ignored: Exception) { + logger.warn("Failed to resolve repo trigger event detail|source[$eventDesc]", ignored) + listOf() + } + + private fun getI18nReason(reason: String?, language: String): String = getCodeLanMessage( + messageCode = if (reason.isNullOrBlank()) { + PipelineTriggerReason.TRIGGER_SUCCESS.name + } else { + reason + }, + language = language, + defaultMessage = reason + ) + + /** + * 获取构建链接 + */ + private fun PipelineTriggerEventVo.getBuildNumUrl(): String? { + return if (status == PipelineTriggerStatus.SUCCEED.name) { + val linkUrl = "${HomeHostUtil.innerServerHost()}/console" + + "/pipeline/$projectId/$pipelineId/detail/$buildId/executeDetail" + MessageFormat.format(PIPELINE_BUILD_URL_PATTERN, linkUrl, buildNum) + } else { + null + } + } + + /** + * 填充事件相关参数 + * 事件描述国际化,构建链接,失败详情国际化,触发状态国际化,失败状态国际化 + */ + private fun fillEventDetailParam( + eventParam: PipelineTriggerEventVo, + language: String + ): PipelineTriggerEventVo { + return with(eventParam) { + eventDesc = getI18nEventDesc(language) + buildNum = getBuildNumUrl() + reasonDetailList = getI18nReasonDetailDesc(language) + reason = getI18nReason(eventParam.reason, language) + failReason = if (!reasonDetailList.isNullOrEmpty()) { + getI18nReason(PipelineTriggerReason.TRIGGER_NOT_MATCH.name, language) + } else { + "" + } + this + } + } +} diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/trigger/WebhookTriggerService.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/trigger/WebhookTriggerService.kt new file mode 100644 index 00000000000..7b10a80a809 --- /dev/null +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/trigger/WebhookTriggerService.kt @@ -0,0 +1,114 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package com.tencent.devops.process.trigger + +import com.tencent.devops.common.api.enums.ScmType +import com.tencent.devops.common.webhook.service.code.matcher.ScmWebhookMatcher +import com.tencent.devops.process.engine.service.PipelineWebhookService +import com.tencent.devops.process.pojo.trigger.PipelineTriggerEvent +import com.tencent.devops.process.pojo.webhook.WebhookTriggerPipeline +import com.tencent.devops.process.service.webhook.PipelineBuildWebhookService +import com.tencent.devops.process.webhook.pojo.event.commit.ReplayWebhookEvent +import org.slf4j.LoggerFactory +import org.springframework.stereotype.Service +import java.time.LocalDateTime + +@Service +class WebhookTriggerService( + private val pipelineWebhookService: PipelineWebhookService, + private val pipelineBuildWebhookService: PipelineBuildWebhookService +) { + companion object { + private val logger = LoggerFactory.getLogger(WebhookTriggerService::class.java) + } + + fun trigger( + scmType: ScmType, + matcher: ScmWebhookMatcher, + requestId: String, + eventTime: LocalDateTime + ) { + val preMatch = matcher.preMatch() + if (!preMatch.isMatch) { + logger.info("webhook trigger pre match|${preMatch.reason}") + return + } + val triggerEvent = PipelineTriggerEvent( + requestId = requestId, + triggerType = scmType.name, + eventType = matcher.getEventType().name, + triggerUser = matcher.getUsername(), + eventDesc = matcher.getEventDesc(), + createTime = eventTime + ) + val triggerPipelines = pipelineWebhookService.getTriggerPipelines( + name = matcher.getRepoName(), + repositoryType = scmType.name + ) + pipelineBuildWebhookService.dispatchTriggerPipelines( + matcher = matcher, + triggerEvent = triggerEvent, + triggerPipelines = triggerPipelines + ) + } + + fun replay( + replayEvent: ReplayWebhookEvent, + triggerEvent: PipelineTriggerEvent, + matcher: ScmWebhookMatcher + ) { + val preMatch = matcher.preMatch() + if (!preMatch.isMatch) { + logger.info("webhook replay trigger pre match|${preMatch.reason}") + return + } + + val triggerPipelines = with(replayEvent) { + pipelineId?.let { + listOf( + WebhookTriggerPipeline( + projectId = projectId, + pipelineId = pipelineId + ) + ) + } ?: run { + pipelineWebhookService.listTriggerPipeline( + projectId = projectId, + repositoryHashId = triggerEvent.eventSource!!, + eventType = triggerEvent.eventType + ) + } + } + pipelineBuildWebhookService.dispatchTriggerPipelines( + matcher = matcher, + triggerEvent = triggerEvent, + triggerPipelines = triggerPipelines + ) + } +} diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/webhook/CodeWebhookEventDispatcher.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/webhook/CodeWebhookEventDispatcher.kt index 8aaae61e898..b53d3c3a0f1 100644 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/webhook/CodeWebhookEventDispatcher.kt +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/webhook/CodeWebhookEventDispatcher.kt @@ -30,6 +30,7 @@ package com.tencent.devops.process.webhook import com.tencent.devops.common.event.annotation.Event import com.tencent.devops.process.webhook.pojo.event.commit.GithubWebhookEvent import com.tencent.devops.process.webhook.pojo.event.commit.ICodeWebhookEvent +import com.tencent.devops.process.webhook.pojo.event.commit.ReplayWebhookEvent import org.slf4j.LoggerFactory import org.springframework.amqp.rabbit.core.RabbitTemplate @@ -83,5 +84,27 @@ object CodeWebhookEventDispatcher { return result } + fun dispatchReplayEvent(rabbitTemplate: RabbitTemplate, event: ReplayWebhookEvent): Boolean { + logger.debug("Webhook comming [replay|$event]") + var result = false + try { + logger.info("Dispatch the replay webhook event by MQ") + val eventType = event::class.java.annotations.find { s -> s is Event } as Event + rabbitTemplate.convertAndSend(eventType.exchange, eventType.routeKey, event) { message -> + // 事件中的变量指定 + if (event.delayMills > 0) { + message.messageProperties.setHeader("x-delay", event.delayMills) + } else if (eventType.delayMills > 0) { // 事件类型固化默认值 + message.messageProperties.setHeader("x-delay", eventType.delayMills) + } + message + } + result = true + } catch (e: Throwable) { + logger.error("Fail to dispatch the event($event) by MQ", e) + } + return result + } + private val logger = LoggerFactory.getLogger(CodeWebhookEventDispatcher::class.java) } diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/webhook/WebHookTriggerElementBizPlugin.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/webhook/WebHookTriggerElementBizPlugin.kt index fba577862ff..35a57e003ef 100644 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/webhook/WebHookTriggerElementBizPlugin.kt +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/webhook/WebHookTriggerElementBizPlugin.kt @@ -27,13 +27,9 @@ package com.tencent.devops.process.webhook -import com.tencent.devops.common.api.constant.CommonMessageCode -import com.tencent.devops.common.api.enums.RepositoryTypeNew -import com.tencent.devops.common.api.exception.ErrorCodeException import com.tencent.devops.common.pipeline.container.Container import com.tencent.devops.common.pipeline.enums.ChannelCode import com.tencent.devops.common.pipeline.pojo.element.atom.BeforeDeleteParam -import com.tencent.devops.common.pipeline.pojo.element.trigger.CodeGitGenericWebHookTriggerElement import com.tencent.devops.common.pipeline.pojo.element.trigger.CodeGitWebHookTriggerElement import com.tencent.devops.common.pipeline.pojo.element.trigger.CodeGithubWebHookTriggerElement import com.tencent.devops.common.pipeline.pojo.element.trigger.CodeGitlabWebHookTriggerElement @@ -120,45 +116,6 @@ class CodeTGitWebHookTriggerElementBizPlugin constructor( } } -@ElementBiz -class CodeGitGenericWebHookTriggerElementBizPlugin constructor( - pipelineWebhookService: PipelineWebhookService -) : WebHookTriggerElementBizPlugin(pipelineWebhookService) { - override fun elementClass(): Class { - return CodeGitGenericWebHookTriggerElement::class.java - } - - override fun check(element: CodeGitGenericWebHookTriggerElement, appearedCnt: Int) { - with(element.data.input) { - if (repositoryType == RepositoryTypeNew.URL && - credentialId.isNullOrBlank() && - token.isNullOrBlank() - ) { - throw ErrorCodeException( - errorCode = CommonMessageCode.PARAMETER_IS_NULL, - params = arrayOf("credentialId") - ) - } - } - } - - override fun afterCreate( - element: CodeGitGenericWebHookTriggerElement, - projectId: String, - pipelineId: String, - pipelineName: String, - userId: String, - channelCode: ChannelCode, - create: Boolean, - container: Container - ) { - // 只支持codecc才能自定义hookUrl - if (channelCode != ChannelCode.CODECC && !element.data.input.hookUrl.isNullOrBlank()) { - element.data.input.hookUrl = null - } - } -} - @ElementBiz class CodeP4WebHookTriggerElementBizPlugin constructor( pipelineWebhookService: PipelineWebhookService diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/webhook/WebhookEventFactory.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/webhook/WebhookEventFactory.kt new file mode 100644 index 00000000000..7b3bdc71ee4 --- /dev/null +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/webhook/WebhookEventFactory.kt @@ -0,0 +1,100 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package com.tencent.devops.process.webhook + +import com.fasterxml.jackson.databind.ObjectMapper +import com.tencent.devops.common.api.enums.ScmType +import com.tencent.devops.common.api.exception.InvalidParamException +import com.tencent.devops.common.webhook.pojo.WebhookRequest +import com.tencent.devops.common.webhook.pojo.code.CodeWebhookEvent +import com.tencent.devops.common.webhook.pojo.code.git.GitEvent +import com.tencent.devops.common.webhook.pojo.code.github.GithubEvent +import com.tencent.devops.common.webhook.pojo.code.p4.P4Event +import com.tencent.devops.common.webhook.pojo.code.svn.SvnCommitEvent +import com.tencent.devops.common.webhook.service.code.matcher.ScmWebhookMatcher +import com.tencent.devops.process.engine.service.code.ScmWebhookMatcherBuilder +import com.tencent.devops.process.webhook.parser.GithubWebhookEventParser +import com.tencent.devops.process.webhook.parser.GitlabWebhookEventParser +import com.tencent.devops.process.webhook.parser.P4WebhookEventParser +import com.tencent.devops.process.webhook.parser.SvnWebhookEventParser +import com.tencent.devops.process.webhook.parser.TGitWebhookEventParser +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.stereotype.Service + +@Service +class WebhookEventFactory @Autowired constructor( + private val objectMapper: ObjectMapper, + private val scmWebhookMatcherBuilder: ScmWebhookMatcherBuilder +) { + + fun parseEvent(scmType: ScmType, request: WebhookRequest): CodeWebhookEvent? { + val webhookEventParser = when (scmType) { + ScmType.CODE_GIT, ScmType.CODE_TGIT -> + TGitWebhookEventParser(objectMapper = objectMapper) + + ScmType.CODE_SVN -> + SvnWebhookEventParser(objectMapper = objectMapper) + + ScmType.CODE_P4 -> + P4WebhookEventParser(objectMapper = objectMapper) + + ScmType.CODE_GITLAB -> + GitlabWebhookEventParser(objectMapper = objectMapper) + + ScmType.GITHUB -> + GithubWebhookEventParser(objectMapper = objectMapper) + + else -> + throw InvalidParamException("Unknown scm type($scmType)") + } + return webhookEventParser.parseEvent(request = request) + } + + fun createScmWebHookMatcher(scmType: ScmType, event: CodeWebhookEvent): ScmWebhookMatcher { + return when (scmType) { + ScmType.CODE_GIT, ScmType.CODE_TGIT -> + scmWebhookMatcherBuilder.createGitWebHookMatcher(event = event as GitEvent) + + ScmType.CODE_SVN -> + scmWebhookMatcherBuilder.createSvnWebHookMatcher(event = event as SvnCommitEvent) + + ScmType.CODE_P4 -> + scmWebhookMatcherBuilder.createP4WebHookMatcher(event = event as P4Event) + + ScmType.CODE_GITLAB -> + scmWebhookMatcherBuilder.createGitlabWebHookMatcher(event = event as GitEvent) + + ScmType.GITHUB -> + scmWebhookMatcherBuilder.createGithubWebHookMatcher(event = event as GithubEvent) + + else -> + throw InvalidParamException("Unknown scm type($scmType)") + } + } +} diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/webhook/WebhookMQConfiguration.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/webhook/WebhookMQConfiguration.kt index 12ec72b0c91..5e5bbc4e275 100644 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/webhook/WebhookMQConfiguration.kt +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/webhook/WebhookMQConfiguration.kt @@ -337,6 +337,50 @@ class WebhookMQConfiguration @Autowired constructor() { ) } + // replay 消息队列配置 + @Bean + fun replayEventExchange(): DirectExchange { + val directExchange = DirectExchange(MQ.EXCHANGE_REPLAY_BUILD_REQUEST_EVENT, true, false) + directExchange.isDelayed = true + return directExchange + } + + @Bean + fun replayEventQueue(): Queue { + return Queue(MQ.QUEUE_REPLAY_BUILD_REQUEST_EVENT, true) + } + + @Bean + fun replayEventBind( + @Autowired replayEventQueue: Queue, + @Autowired replayEventExchange: DirectExchange + ): Binding { + return BindingBuilder.bind(replayEventQueue).to(replayEventExchange).with(MQ.ROUTE_REPLAY_BUILD_REQUEST_EVENT) + } + + @Bean + fun replayEventListener( + @Autowired connectionFactory: ConnectionFactory, + @Autowired replayEventQueue: Queue, + @Autowired rabbitAdmin: RabbitAdmin, + @Autowired webhookEventListener: WebhookEventListener, + @Autowired messageConverter: Jackson2JsonMessageConverter + ): SimpleMessageListenerContainer { + logger.info("Start webhook replay event listener") + val adapter = MessageListenerAdapter(webhookEventListener, WebhookEventListener::handleReplayEvent.name) + adapter.setMessageConverter(messageConverter) + return Tools.createSimpleMessageListenerContainerByAdapter( + connectionFactory = connectionFactory, + queue = replayEventQueue, + rabbitAdmin = rabbitAdmin, + adapter = adapter, + startConsumerMinInterval = 1, + consecutiveActiveTrigger = 1, + concurrency = 10, + maxConcurrency = 20 + ) + } + companion object { private val logger = LoggerFactory.getLogger(WebhookMQConfiguration::class.java) } diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/webhook/WebhookRequestService.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/webhook/WebhookRequestService.kt new file mode 100644 index 00000000000..8e1191b16a7 --- /dev/null +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/webhook/WebhookRequestService.kt @@ -0,0 +1,159 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package com.tencent.devops.process.webhook + +import com.tencent.devops.common.api.enums.ScmType +import com.tencent.devops.common.client.Client +import com.tencent.devops.common.pipeline.enums.ChannelCode +import com.tencent.devops.common.service.trace.TraceTag +import com.tencent.devops.common.webhook.pojo.WebhookRequest +import com.tencent.devops.common.webhook.pojo.code.github.GithubCheckRunEvent +import com.tencent.devops.process.api.service.ServiceBuildResource +import com.tencent.devops.process.dao.PipelineTriggerEventDao +import com.tencent.devops.process.trigger.WebhookTriggerService +import com.tencent.devops.process.webhook.pojo.event.commit.ReplayWebhookEvent +import com.tencent.devops.repository.api.ServiceRepositoryWebhookResource +import com.tencent.devops.repository.pojo.RepositoryWebhookRequest +import org.jooq.DSLContext +import org.slf4j.LoggerFactory +import org.slf4j.MDC +import org.springframework.stereotype.Service +import java.time.LocalDateTime + +@Service +class WebhookRequestService( + private val client: Client, + private val webhookEventFactory: WebhookEventFactory, + private val webhookTriggerService: WebhookTriggerService, + private val dslContext: DSLContext, + private val pipelineTriggerEventDao: PipelineTriggerEventDao +) { + + companion object { + private val logger = LoggerFactory.getLogger(WebhookRequestService::class.java) + } + + fun handleRequest(scmType: ScmType, request: WebhookRequest) { + val event = webhookEventFactory.parseEvent(scmType = scmType, request = request) ?: run { + logger.warn("Failed to parse webhook event") + return + } + if (event is GithubCheckRunEvent) { + githubRetry(event) + return + } + val matcher = webhookEventFactory.createScmWebHookMatcher(scmType = scmType, event = event) + + val eventTime = LocalDateTime.now() + val requestId = MDC.get(TraceTag.BIZID) + val repositoryWebhookRequest = RepositoryWebhookRequest( + requestId = requestId, + externalId = matcher.getExternalId(), + eventType = matcher.getEventType().name, + triggerUser = matcher.getUsername(), + eventMessage = matcher.getMessage() ?: "", + repositoryType = scmType.name, + requestHeader = request.headers, + requestParam = request.queryParams, + requestBody = request.body, + createTime = eventTime + ) + try { + client.get(ServiceRepositoryWebhookResource::class).saveWebhookRequest( + repositoryWebhookRequest = repositoryWebhookRequest + ).data!! + } catch (ignored: Throwable) { + // 日志保存异常,不影响正常触发 + logger.warn("Failed to save webhook request", ignored) + } + webhookTriggerService.trigger( + scmType = scmType, + matcher = matcher, + requestId = requestId, + eventTime = eventTime + ) + } + + fun handleReplay(replayEvent: ReplayWebhookEvent) { + with(replayEvent) { + val triggerEvent = pipelineTriggerEventDao.getTriggerEvent( + dslContext = dslContext, + projectId = projectId, + eventId = eventId + ) ?: run { + logger.info("replay trigger event not found|$eventId") + return + } + val repoWebhookRequest = client.get(ServiceRepositoryWebhookResource::class).getWebhookRequest( + requestId = replayRequestId + ).data ?: run { + logger.info("replay webhook request not found|$replayRequestId") + return + } + val webhookRequest = WebhookRequest( + headers = repoWebhookRequest.requestHeader, + body = repoWebhookRequest.requestBody + ) + val event = webhookEventFactory.parseEvent(scmType = scmType, request = webhookRequest) ?: run { + logger.warn("Failed to parse webhook event") + return + } + val matcher = webhookEventFactory.createScmWebHookMatcher(scmType = scmType, event = event) + + webhookTriggerService.replay( + replayEvent = replayEvent, + triggerEvent = triggerEvent, + matcher = matcher + ) + } + } + + private fun githubRetry(event: GithubCheckRunEvent) { + if (event.action != "rerequested") { + logger.info("Unsupported check run action:${event.action}") + return + } + if (event.checkRun.externalId == null) { + logger.info("github check run externalId is empty") + return + } + val buildInfo = event.checkRun.externalId!!.split("_") + if (buildInfo.size < 4) { + logger.info("the buildInfo of github check run is error") + return + } + client.get(ServiceBuildResource::class).retry( + userId = buildInfo[0], + projectId = buildInfo[1], + pipelineId = buildInfo[2], + buildId = buildInfo[3], + channelCode = ChannelCode.BS + ) + } +} diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/webhook/listener/WebhookEventListener.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/webhook/listener/WebhookEventListener.kt index 4be58dd3420..269eed9608c 100644 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/webhook/listener/WebhookEventListener.kt +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/webhook/listener/WebhookEventListener.kt @@ -27,19 +27,17 @@ package com.tencent.devops.process.webhook.listener -import com.tencent.devops.common.pipeline.pojo.element.trigger.CodeGitWebHookTriggerElement -import com.tencent.devops.common.pipeline.pojo.element.trigger.CodeTGitWebHookTriggerElement -import com.tencent.devops.common.pipeline.pojo.element.trigger.enums.CodeType +import com.tencent.devops.common.api.enums.ScmType import com.tencent.devops.common.service.trace.TraceTag -import com.tencent.devops.process.engine.service.PipelineWebhookBuildLogContext -import com.tencent.devops.process.engine.service.PipelineWebhookBuildLogService -import com.tencent.devops.process.service.webhook.PipelineBuildWebhookService +import com.tencent.devops.common.webhook.pojo.WebhookRequest import com.tencent.devops.process.webhook.CodeWebhookEventDispatcher +import com.tencent.devops.process.webhook.WebhookRequestService import com.tencent.devops.process.webhook.pojo.event.commit.GitWebhookEvent import com.tencent.devops.process.webhook.pojo.event.commit.GithubWebhookEvent import com.tencent.devops.process.webhook.pojo.event.commit.GitlabWebhookEvent import com.tencent.devops.process.webhook.pojo.event.commit.ICodeWebhookEvent import com.tencent.devops.process.webhook.pojo.event.commit.P4WebhookEvent +import com.tencent.devops.process.webhook.pojo.event.commit.ReplayWebhookEvent import com.tencent.devops.process.webhook.pojo.event.commit.SvnWebhookEvent import com.tencent.devops.process.webhook.pojo.event.commit.TGitWebhookEvent import com.tencent.devops.process.webhook.pojo.event.commit.enum.CommitEventType @@ -50,11 +48,11 @@ import org.springframework.stereotype.Component @Component class WebhookEventListener constructor( - private val pipelineBuildWebhookService: PipelineBuildWebhookService, private val rabbitTemplate: RabbitTemplate, - private val triggerBuildLogService: PipelineWebhookBuildLogService + private val webhookRequestService: WebhookRequestService ) { + @SuppressWarnings("ComplexMethod", "LongMethod") fun handleCommitEvent(event: ICodeWebhookEvent) { val traceId = MDC.get(TraceTag.BIZID) if (traceId.isNullOrEmpty()) { @@ -67,30 +65,58 @@ class WebhookEventListener constructor( logger.info("Receive WebhookEvent from MQ [${event.commitEventType}|${event.requestContent}]|[${event.event}]") var result = false try { - PipelineWebhookBuildLogContext.initTriggerLog( - codeType = event.commitEventType.name, - requestContent = event.requestContent - ) when (event.commitEventType) { - CommitEventType.SVN -> pipelineBuildWebhookService.externalCodeSvnBuild(event.requestContent) + CommitEventType.SVN -> { + val request = WebhookRequest( + body = event.requestContent + ) + webhookRequestService.handleRequest( + scmType = ScmType.CODE_SVN, + request = request + ) + } CommitEventType.GIT -> { - pipelineBuildWebhookService.externalCodeGitBuild( - codeRepositoryType = CodeGitWebHookTriggerElement.classType, - event = event.event, + val request = WebhookRequest( + headers = mapOf( + "X-Event" to event.event!! + ), body = event.requestContent ) + webhookRequestService.handleRequest( + scmType = ScmType.CODE_GIT, + request = request + ) + } + CommitEventType.GITLAB -> { + val request = WebhookRequest( + body = event.requestContent + ) + webhookRequestService.handleRequest( + scmType = ScmType.CODE_GITLAB, + request = request + ) } - CommitEventType.GITLAB -> pipelineBuildWebhookService.externalGitlabBuild( - e = event.requestContent - ) CommitEventType.TGIT -> { - pipelineBuildWebhookService.externalCodeGitBuild( - codeRepositoryType = CodeTGitWebHookTriggerElement.classType, - event = event.event, + val request = WebhookRequest( + headers = mapOf( + "X-Event" to event.event!! + ), body = event.requestContent ) + webhookRequestService.handleRequest( + scmType = ScmType.CODE_TGIT, + request = request + ) + } + CommitEventType.P4 -> { + val request = WebhookRequest( + body = event.requestContent + ) + webhookRequestService.handleRequest( + scmType = ScmType.CODE_P4, + request = request + ) } - CommitEventType.P4 -> pipelineBuildWebhookService.externalP4Build(event.requestContent) } result = true } catch (ignore: Throwable) { @@ -99,8 +125,6 @@ class WebhookEventListener constructor( if (!result) { retryCommitEvent(event) } - saveWebhookTriggerLog(event.commitEventType.name) - PipelineWebhookBuildLogContext.remove() MDC.remove(TraceTag.BIZID) } } @@ -169,24 +193,30 @@ class WebhookEventListener constructor( logger.info("Receive Github from MQ [GITHUB|${event.githubWebhook.event}]") val thisGithubWebhook = event.githubWebhook var result = false - PipelineWebhookBuildLogContext.initTriggerLog( - codeType = CodeType.GITHUB.name, - requestContent = thisGithubWebhook.body - ) try { - pipelineBuildWebhookService.externalCodeGithubBuild( - eventType = thisGithubWebhook.event, - guid = thisGithubWebhook.guid, - signature = thisGithubWebhook.signature, - body = thisGithubWebhook.body + val request = with(thisGithubWebhook) { + WebhookRequest( + headers = mapOf( + "X-GitHub-Event" to thisGithubWebhook.event, + "X-Github-Delivery" to guid, + "X-Hub-Signature" to signature + ), + body = thisGithubWebhook.body + ) + } + webhookRequestService.handleRequest( + scmType = ScmType.GITHUB, + request = request ) + result = true } catch (ignore: Throwable) { logger.warn("Fail to handle the Github event [${event.retryTime}]", ignore) } finally { if (!result && event.retryTime >= 0) { logger.warn("Retry to handle the Github event [${event.retryTime}]") - CodeWebhookEventDispatcher.dispatchGithubEvent(rabbitTemplate, + CodeWebhookEventDispatcher.dispatchGithubEvent( + rabbitTemplate, GithubWebhookEvent( thisGithubWebhook, retryTime = event.retryTime - 1, @@ -194,17 +224,46 @@ class WebhookEventListener constructor( ) ) } - saveWebhookTriggerLog(CodeType.GITHUB.name) - PipelineWebhookBuildLogContext.remove() MDC.remove(TraceTag.BIZID) } } - private fun saveWebhookTriggerLog(codeType: String) { + fun handleReplayEvent(replayEvent: ReplayWebhookEvent) { + val traceId = MDC.get(TraceTag.BIZID) + if (traceId.isNullOrEmpty()) { + if (!replayEvent.traceId.isNullOrEmpty()) { + MDC.put(TraceTag.BIZID, replayEvent.traceId) + } else { + MDC.put(TraceTag.BIZID, TraceTag.buildBiz()) + } + } + logger.info("Receive ReplayWebhookEvent from MQ [replay|$replayEvent]") + var result = false try { - triggerBuildLogService.saveWebhookBuildLog(PipelineWebhookBuildLogContext.get()) + webhookRequestService.handleReplay(replayEvent = replayEvent) + result = true } catch (ignore: Throwable) { - logger.error("save webhook trigger log failed|codeType=$codeType", ignore) + logger.warn("Fail to handle the Github event [${replayEvent.retryTime}]", ignore) + } finally { + if (!result && replayEvent.retryTime >= 0) { + logger.warn("Retry to handle the Github event [${replayEvent.retryTime}]") + with(replayEvent) { + CodeWebhookEventDispatcher.dispatchReplayEvent( + rabbitTemplate = rabbitTemplate, + event = ReplayWebhookEvent( + userId = userId, + projectId = projectId, + eventId = eventId, + replayRequestId = replayRequestId, + scmType = scmType, + pipelineId = pipelineId, + retryTime = retryTime - 1, + delayMills = DELAY_MILLS + ) + ) + } + } + MDC.remove(TraceTag.BIZID) } } diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/webhook/parser/GithubWebhookEventParser.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/webhook/parser/GithubWebhookEventParser.kt new file mode 100644 index 00000000000..aa7ead80d43 --- /dev/null +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/webhook/parser/GithubWebhookEventParser.kt @@ -0,0 +1,80 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package com.tencent.devops.process.webhook.parser + +import com.fasterxml.jackson.databind.ObjectMapper +import com.fasterxml.jackson.module.kotlin.readValue +import com.tencent.devops.common.webhook.pojo.WebhookRequest +import com.tencent.devops.common.webhook.pojo.code.CodeWebhookEvent +import com.tencent.devops.common.webhook.pojo.code.github.GithubCheckRunEvent +import com.tencent.devops.common.webhook.pojo.code.github.GithubCommitCommentEvent +import com.tencent.devops.common.webhook.pojo.code.github.GithubCreateEvent +import com.tencent.devops.common.webhook.pojo.code.github.GithubIssueCommentEvent +import com.tencent.devops.common.webhook.pojo.code.github.GithubIssuesEvent +import com.tencent.devops.common.webhook.pojo.code.github.GithubPullRequestEvent +import com.tencent.devops.common.webhook.pojo.code.github.GithubPushEvent +import com.tencent.devops.common.webhook.pojo.code.github.GithubReviewCommentEvent +import com.tencent.devops.common.webhook.pojo.code.github.GithubReviewEvent +import org.slf4j.LoggerFactory + +/** + * github webhook事件解析 + */ +class GithubWebhookEventParser( + private val objectMapper: ObjectMapper +) : IWebhookEventParser { + + companion object { + private val logger = LoggerFactory.getLogger(GithubWebhookEventParser::class.java) + } + + override fun parseEvent(request: WebhookRequest): CodeWebhookEvent? { + val eventType = request.headers?.get("X-GitHub-Event") + val guid = request.headers?.get("X-Github-Delivery") + val signature = request.headers?.get("X-Hub-Signature") + val body = request.body + logger.info("Trigger code github build (event=$eventType, guid=$guid, signature=$signature, body=$body)") + + return when (eventType) { + GithubPushEvent.classType -> objectMapper.readValue(body) + GithubCreateEvent.classType -> objectMapper.readValue(body) + GithubPullRequestEvent.classType -> objectMapper.readValue(body) + GithubCheckRunEvent.classType -> objectMapper.readValue(body) + GithubCommitCommentEvent.classType -> objectMapper.readValue(body) + GithubIssueCommentEvent.classType -> objectMapper.readValue(body) + GithubReviewCommentEvent.classType -> objectMapper.readValue(body) + GithubIssuesEvent.classType -> objectMapper.readValue(body) + GithubReviewEvent.classType -> objectMapper.readValue(body) + else -> { + logger.info("Github event($eventType) is ignored") + return null + } + } + } +} diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/webhook/parser/GitlabWebhookEventParser.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/webhook/parser/GitlabWebhookEventParser.kt new file mode 100644 index 00000000000..0db1917c33a --- /dev/null +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/webhook/parser/GitlabWebhookEventParser.kt @@ -0,0 +1,57 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package com.tencent.devops.process.webhook.parser + +import com.fasterxml.jackson.databind.ObjectMapper +import com.tencent.devops.common.webhook.pojo.WebhookRequest +import com.tencent.devops.common.webhook.pojo.code.CodeWebhookEvent +import com.tencent.devops.common.webhook.pojo.code.git.GitEvent +import org.slf4j.LoggerFactory + +/** + * gitlab webhook事件解析 + */ +class GitlabWebhookEventParser( + private val objectMapper: ObjectMapper +) : IWebhookEventParser { + + companion object { + private val logger = LoggerFactory.getLogger(GitlabWebhookEventParser::class.java) + } + + override fun parseEvent(request: WebhookRequest): CodeWebhookEvent? { + logger.info("Trigger gitlab build(${request.body})") + return try { + objectMapper.readValue(request.body, GitEvent::class.java) + } catch (e: Exception) { + logger.warn("Fail to parse the gitlab web hook commit event", e) + return null + } + } +} diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/engine/service/PipelineWebhookBuildLogService.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/webhook/parser/IWebhookEventParser.kt similarity index 67% rename from src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/engine/service/PipelineWebhookBuildLogService.kt rename to src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/webhook/parser/IWebhookEventParser.kt index a98b63f8869..74dccc37b5c 100644 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/engine/service/PipelineWebhookBuildLogService.kt +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/webhook/parser/IWebhookEventParser.kt @@ -23,32 +23,18 @@ * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * */ -package com.tencent.devops.process.engine.service - -import com.tencent.devops.common.api.model.SQLPage -import com.tencent.devops.process.pojo.webhook.PipelineWebhookBuildLog -import com.tencent.devops.process.pojo.webhook.PipelineWebhookBuildLogDetail +package com.tencent.devops.process.webhook.parser -interface PipelineWebhookBuildLogService { +import com.tencent.devops.common.webhook.pojo.WebhookRequest +import com.tencent.devops.common.webhook.pojo.code.CodeWebhookEvent - /** - * 保存webhook构建日志 - */ - fun saveWebhookBuildLog(webhookBuildLog: PipelineWebhookBuildLog) +interface IWebhookEventParser { /** - * 查询webhook构建日志明细 + * webhook 事件解析 */ - @Suppress("ALL") - fun listWebhookBuildLogDetail( - userId: String, - projectId: String, - pipelineId: String, - repoName: String?, - commitId: String?, - page: Int?, - pageSize: Int? - ): SQLPage? + fun parseEvent(request: WebhookRequest): CodeWebhookEvent? } diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/webhook/parser/P4WebhookEventParser.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/webhook/parser/P4WebhookEventParser.kt new file mode 100644 index 00000000000..937f826fba9 --- /dev/null +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/webhook/parser/P4WebhookEventParser.kt @@ -0,0 +1,57 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package com.tencent.devops.process.webhook.parser + +import com.fasterxml.jackson.databind.ObjectMapper +import com.tencent.devops.common.webhook.pojo.WebhookRequest +import com.tencent.devops.common.webhook.pojo.code.CodeWebhookEvent +import com.tencent.devops.common.webhook.pojo.code.p4.P4Event +import org.slf4j.LoggerFactory + +/** + * p4 webhook事件解析 + */ +class P4WebhookEventParser( + private val objectMapper: ObjectMapper +) : IWebhookEventParser { + + companion object { + private val logger = LoggerFactory.getLogger(P4WebhookEventParser::class.java) + } + + override fun parseEvent(request: WebhookRequest): CodeWebhookEvent? { + logger.info("Trigger p4 build(${request.body})") + return try { + objectMapper.readValue(request.body, P4Event::class.java) + } catch (e: Exception) { + logger.warn("Fail to parse the p4 web hook event", e) + return null + } + } +} diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/webhook/parser/SvnWebhookEventParser.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/webhook/parser/SvnWebhookEventParser.kt new file mode 100644 index 00000000000..8d11dffb08d --- /dev/null +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/webhook/parser/SvnWebhookEventParser.kt @@ -0,0 +1,57 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package com.tencent.devops.process.webhook.parser + +import com.fasterxml.jackson.databind.ObjectMapper +import com.tencent.devops.common.webhook.pojo.WebhookRequest +import com.tencent.devops.common.webhook.pojo.code.CodeWebhookEvent +import com.tencent.devops.common.webhook.pojo.code.svn.SvnCommitEvent +import org.slf4j.LoggerFactory + +/** + * svn webhook事件解析 + */ +class SvnWebhookEventParser( + private val objectMapper: ObjectMapper +) : IWebhookEventParser { + + companion object { + private val logger = LoggerFactory.getLogger(SvnWebhookEventParser::class.java) + } + + override fun parseEvent(request: WebhookRequest): CodeWebhookEvent? { + logger.info("Trigger code svn build - ${request.body}") + return try { + objectMapper.readValue(request.body, SvnCommitEvent::class.java) + } catch (e: Exception) { + logger.warn("Fail to parse the svn web hook commit event", e) + return null + } + } +} diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/webhook/parser/TGitWebhookEventParser.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/webhook/parser/TGitWebhookEventParser.kt new file mode 100644 index 00000000000..3f70e117aaf --- /dev/null +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/webhook/parser/TGitWebhookEventParser.kt @@ -0,0 +1,65 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package com.tencent.devops.process.webhook.parser + +import com.fasterxml.jackson.databind.ObjectMapper +import com.fasterxml.jackson.module.kotlin.readValue +import com.tencent.devops.common.webhook.pojo.WebhookRequest +import com.tencent.devops.common.webhook.pojo.code.CodeWebhookEvent +import com.tencent.devops.common.webhook.pojo.code.git.GitEvent +import com.tencent.devops.common.webhook.pojo.code.git.GitReviewEvent +import org.slf4j.LoggerFactory + +/** + * 工蜂webhoook 事件解析 + */ +class TGitWebhookEventParser( + private val objectMapper: ObjectMapper +) : IWebhookEventParser { + + companion object { + private val logger = LoggerFactory.getLogger(TGitWebhookEventParser::class.java) + } + + override fun parseEvent(request: WebhookRequest): CodeWebhookEvent? { + val eventType = request.headers?.get("X-Event") + val body = request.body + logger.info("Trigger code git build($body|$eventType)") + return try { + if (eventType == "Review Hook") { + objectMapper.readValue(body) + } else { + objectMapper.readValue(body) + } + } catch (e: Exception) { + logger.warn("Fail to parse the git web hook commit event", e) + return null + } + } +} diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/webhook/pojo/event/commit/ReplayWebhookEvent.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/webhook/pojo/event/commit/ReplayWebhookEvent.kt new file mode 100644 index 00000000000..53490a87a44 --- /dev/null +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/webhook/pojo/event/commit/ReplayWebhookEvent.kt @@ -0,0 +1,50 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package com.tencent.devops.process.webhook.pojo.event.commit + +import com.tencent.devops.common.api.enums.ScmType +import com.tencent.devops.common.event.annotation.Event +import com.tencent.devops.common.event.dispatcher.pipeline.mq.MQ +import com.tencent.devops.common.service.trace.TraceTag +import org.slf4j.MDC + +@Event(exchange = MQ.EXCHANGE_REPLAY_BUILD_REQUEST_EVENT, routeKey = MQ.ROUTE_REPLAY_BUILD_REQUEST_EVENT) +data class ReplayWebhookEvent( + val userId: String, + val projectId: String, + // 事件重放生成的事件ID + val eventId: Long, + // 重放的请求ID + val replayRequestId: String, + val scmType: ScmType, + val pipelineId: String? = null, + var retryTime: Int = 3, + var delayMills: Int = 0, + var traceId: String? = MDC.get(TraceTag.BIZID) +) diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/webhook/service/SamplePipelineBuildWebhookService.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/webhook/service/SamplePipelineBuildWebhookService.kt index 6d854932e19..92182b7f9d3 100644 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/webhook/service/SamplePipelineBuildWebhookService.kt +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/webhook/service/SamplePipelineBuildWebhookService.kt @@ -34,6 +34,7 @@ import com.tencent.devops.common.webhook.service.code.matcher.ScmWebhookMatcher import com.tencent.devops.process.constant.ProcessMessageCode import com.tencent.devops.process.permission.PipelinePermissionService import com.tencent.devops.process.service.webhook.PipelineBuildWebhookService +import com.tencent.devops.process.pojo.trigger.PipelineTriggerDetailBuilder import org.springframework.beans.factory.annotation.Autowired import org.springframework.stereotype.Service @@ -60,9 +61,14 @@ class SamplePipelineBuildWebhookService : PipelineBuildWebhookService() { override fun webhookTriggerPipelineBuild( projectId: String, pipelineId: String, - codeRepositoryType: String, - matcher: ScmWebhookMatcher + matcher: ScmWebhookMatcher, + builder: PipelineTriggerDetailBuilder ): Boolean { - return super.webhookTriggerPipelineBuild(projectId, pipelineId, codeRepositoryType, matcher) + return super.webhookTriggerPipelineBuild( + projectId = projectId, + pipelineId = pipelineId, + matcher = matcher, + builder = builder + ) } } diff --git a/src/backend/ci/core/repository/api-repository/src/main/kotlin/com/tencent/devops/repository/api/ServiceRepositoryWebhookResource.kt b/src/backend/ci/core/repository/api-repository/src/main/kotlin/com/tencent/devops/repository/api/ServiceRepositoryWebhookResource.kt new file mode 100644 index 00000000000..9b77de0be79 --- /dev/null +++ b/src/backend/ci/core/repository/api-repository/src/main/kotlin/com/tencent/devops/repository/api/ServiceRepositoryWebhookResource.kt @@ -0,0 +1,65 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.devops.repository.api + +import com.tencent.devops.common.api.pojo.Result +import com.tencent.devops.repository.pojo.RepositoryWebhookRequest +import io.swagger.annotations.Api +import io.swagger.annotations.ApiOperation +import io.swagger.annotations.ApiParam +import javax.ws.rs.Consumes +import javax.ws.rs.GET +import javax.ws.rs.POST +import javax.ws.rs.Path +import javax.ws.rs.PathParam +import javax.ws.rs.Produces +import javax.ws.rs.core.MediaType + +@Api(tags = ["SERVICE_REPOSITORY_WEBHOOK"], description = "服务-代码库webhook") +@Path("/service/repository/webhook") +@Produces(MediaType.APPLICATION_JSON) +@Consumes(MediaType.APPLICATION_JSON) +interface ServiceRepositoryWebhookResource { + + @ApiOperation("保存代码库触发事件") + @POST + @Path("/save") + fun saveWebhookRequest( + @ApiParam(value = "代码库触发事件", required = true) + repositoryWebhookRequest: RepositoryWebhookRequest + ): Result + + @ApiOperation("获取代码库事件请求") + @GET + @Path("/{requestId}") + fun getWebhookRequest( + @ApiParam(value = "事件ID", required = true) + @PathParam("requestId") + requestId: String + ): Result +} diff --git a/src/backend/ci/core/repository/api-repository/src/main/kotlin/com/tencent/devops/repository/pojo/CodeGitRepository.kt b/src/backend/ci/core/repository/api-repository/src/main/kotlin/com/tencent/devops/repository/pojo/CodeGitRepository.kt index afa69192cc3..3a833bb1701 100644 --- a/src/backend/ci/core/repository/api-repository/src/main/kotlin/com/tencent/devops/repository/pojo/CodeGitRepository.kt +++ b/src/backend/ci/core/repository/api-repository/src/main/kotlin/com/tencent/devops/repository/pojo/CodeGitRepository.kt @@ -78,4 +78,6 @@ data class CodeGitRepository( } override fun getScmType() = ScmType.CODE_GIT + + override fun getExternalId(): String = gitProjectId?.toString() ?: "" } diff --git a/src/backend/ci/core/repository/api-repository/src/main/kotlin/com/tencent/devops/repository/pojo/CodeGitlabRepository.kt b/src/backend/ci/core/repository/api-repository/src/main/kotlin/com/tencent/devops/repository/pojo/CodeGitlabRepository.kt index bb8d992a7ec..1cc59a3ba49 100644 --- a/src/backend/ci/core/repository/api-repository/src/main/kotlin/com/tencent/devops/repository/pojo/CodeGitlabRepository.kt +++ b/src/backend/ci/core/repository/api-repository/src/main/kotlin/com/tencent/devops/repository/pojo/CodeGitlabRepository.kt @@ -77,4 +77,6 @@ data class CodeGitlabRepository( } override fun getScmType() = ScmType.CODE_GITLAB + + override fun getExternalId(): String = gitProjectId?.toString() ?: "" } diff --git a/src/backend/ci/core/repository/api-repository/src/main/kotlin/com/tencent/devops/repository/pojo/CodeP4Repository.kt b/src/backend/ci/core/repository/api-repository/src/main/kotlin/com/tencent/devops/repository/pojo/CodeP4Repository.kt index 65e6ca3f415..2094892afe3 100644 --- a/src/backend/ci/core/repository/api-repository/src/main/kotlin/com/tencent/devops/repository/pojo/CodeP4Repository.kt +++ b/src/backend/ci/core/repository/api-repository/src/main/kotlin/com/tencent/devops/repository/pojo/CodeP4Repository.kt @@ -62,4 +62,6 @@ data class CodeP4Repository( } override fun getScmType() = ScmType.CODE_P4 + + override fun getExternalId(): String = projectName } diff --git a/src/backend/ci/core/repository/api-repository/src/main/kotlin/com/tencent/devops/repository/pojo/CodeSvnRepository.kt b/src/backend/ci/core/repository/api-repository/src/main/kotlin/com/tencent/devops/repository/pojo/CodeSvnRepository.kt index d5db961b91b..8cc506b1d71 100644 --- a/src/backend/ci/core/repository/api-repository/src/main/kotlin/com/tencent/devops/repository/pojo/CodeSvnRepository.kt +++ b/src/backend/ci/core/repository/api-repository/src/main/kotlin/com/tencent/devops/repository/pojo/CodeSvnRepository.kt @@ -88,4 +88,6 @@ data class CodeSvnRepository( override fun getStartPrefix() = "svn+ssh://" override fun getScmType() = ScmType.CODE_SVN + + override fun getExternalId(): String = projectName } diff --git a/src/backend/ci/core/repository/api-repository/src/main/kotlin/com/tencent/devops/repository/pojo/CodeTGitRepository.kt b/src/backend/ci/core/repository/api-repository/src/main/kotlin/com/tencent/devops/repository/pojo/CodeTGitRepository.kt index e11a3d68bdc..497ccda06be 100644 --- a/src/backend/ci/core/repository/api-repository/src/main/kotlin/com/tencent/devops/repository/pojo/CodeTGitRepository.kt +++ b/src/backend/ci/core/repository/api-repository/src/main/kotlin/com/tencent/devops/repository/pojo/CodeTGitRepository.kt @@ -78,4 +78,6 @@ data class CodeTGitRepository( } override fun getScmType() = ScmType.CODE_TGIT + + override fun getExternalId(): String = gitProjectId?.toString() ?: "" } diff --git a/src/backend/ci/core/repository/api-repository/src/main/kotlin/com/tencent/devops/repository/pojo/GithubRepository.kt b/src/backend/ci/core/repository/api-repository/src/main/kotlin/com/tencent/devops/repository/pojo/GithubRepository.kt index 5232ca255ff..b0f0b10cba7 100644 --- a/src/backend/ci/core/repository/api-repository/src/main/kotlin/com/tencent/devops/repository/pojo/GithubRepository.kt +++ b/src/backend/ci/core/repository/api-repository/src/main/kotlin/com/tencent/devops/repository/pojo/GithubRepository.kt @@ -58,4 +58,6 @@ data class GithubRepository( override fun getStartPrefix() = "https://github.com/" override fun getScmType() = ScmType.GITHUB + + override fun getExternalId(): String = gitProjectId?.toString() ?: "" } diff --git a/src/backend/ci/core/repository/api-repository/src/main/kotlin/com/tencent/devops/repository/pojo/Repository.kt b/src/backend/ci/core/repository/api-repository/src/main/kotlin/com/tencent/devops/repository/pojo/Repository.kt index 7daafe70bf3..5424f71a04a 100644 --- a/src/backend/ci/core/repository/api-repository/src/main/kotlin/com/tencent/devops/repository/pojo/Repository.kt +++ b/src/backend/ci/core/repository/api-repository/src/main/kotlin/com/tencent/devops/repository/pojo/Repository.kt @@ -58,4 +58,6 @@ interface Repository { fun getFormatURL() = url fun getScmType(): ScmType + + fun getExternalId(): String = projectName } diff --git a/src/backend/ci/core/repository/api-repository/src/main/kotlin/com/tencent/devops/repository/pojo/RepositoryWebhookRequest.kt b/src/backend/ci/core/repository/api-repository/src/main/kotlin/com/tencent/devops/repository/pojo/RepositoryWebhookRequest.kt new file mode 100644 index 00000000000..c9e0e15d196 --- /dev/null +++ b/src/backend/ci/core/repository/api-repository/src/main/kotlin/com/tencent/devops/repository/pojo/RepositoryWebhookRequest.kt @@ -0,0 +1,29 @@ +package com.tencent.devops.repository.pojo + +import io.swagger.annotations.ApiModel +import io.swagger.annotations.ApiModelProperty +import java.time.LocalDateTime + +@ApiModel("代码库webhook请求") +data class RepositoryWebhookRequest( + @ApiModelProperty("请求ID") + var requestId: String, + @ApiModelProperty("事件源,工蜂-工蜂ID,github-github id,svn-svn path,p4-p4port") + val externalId: String, + @ApiModelProperty("事件类型") + val eventType: String, + @ApiModelProperty("代码库类型") + val repositoryType: String, + @ApiModelProperty("触发人") + val triggerUser: String, + @ApiModelProperty("事件信息") + val eventMessage: String, + @ApiModelProperty("请求头") + val requestHeader: Map? = null, + @ApiModelProperty("请求参数") + val requestParam: Map? = null, + @ApiModelProperty("请求体") + val requestBody: String, + @ApiModelProperty("事件时间") + val createTime: LocalDateTime +) diff --git a/src/backend/ci/core/repository/biz-repository/src/main/kotlin/com/tencent/devops/repository/dao/RepositoryDao.kt b/src/backend/ci/core/repository/biz-repository/src/main/kotlin/com/tencent/devops/repository/dao/RepositoryDao.kt index c1485baacaa..8447bfd3d43 100644 --- a/src/backend/ci/core/repository/biz-repository/src/main/kotlin/com/tencent/devops/repository/dao/RepositoryDao.kt +++ b/src/backend/ci/core/repository/biz-repository/src/main/kotlin/com/tencent/devops/repository/dao/RepositoryDao.kt @@ -304,7 +304,7 @@ class RepositoryDao { query.and(PROJECT_ID.eq(projectId)) } return query.and(IS_DELETED.eq(false)).fetchOne() ?: throw NotFoundException( - I18nUtil.getCodeLanMessage(messageCode = GIT_NOT_FOUND) + I18nUtil.getCodeLanMessage(messageCode = GIT_NOT_FOUND, params = arrayOf(repositoryId.toString())) ) } } diff --git a/src/backend/ci/core/repository/biz-repository/src/main/kotlin/com/tencent/devops/repository/dao/RepositoryWebhookRequestDao.kt b/src/backend/ci/core/repository/biz-repository/src/main/kotlin/com/tencent/devops/repository/dao/RepositoryWebhookRequestDao.kt new file mode 100644 index 00000000000..36eb84644ca --- /dev/null +++ b/src/backend/ci/core/repository/biz-repository/src/main/kotlin/com/tencent/devops/repository/dao/RepositoryWebhookRequestDao.kt @@ -0,0 +1,106 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.devops.repository.dao + +import com.fasterxml.jackson.core.type.TypeReference +import com.tencent.devops.common.api.util.JsonUtil +import com.tencent.devops.model.repository.tables.TRepositoryWebhookRequest +import com.tencent.devops.model.repository.tables.records.TRepositoryWebhookRequestRecord +import com.tencent.devops.repository.pojo.RepositoryWebhookRequest +import org.jooq.DSLContext +import org.springframework.stereotype.Repository + +@Suppress("ALL") +@Repository +class RepositoryWebhookRequestDao { + fun saveWebhookRequest(dslContext: DSLContext, webhookRequest: RepositoryWebhookRequest) { + return with(TRepositoryWebhookRequest.T_REPOSITORY_WEBHOOK_REQUEST) { + dslContext.insertInto( + this, + REQUEST_ID, + EXTERNAL_ID, + REPOSITORY_TYPE, + EVENT_TYPE, + TRIGGER_USER, + EVENT_MESSAGE, + REQUEST_HEADER, + REQUEST_PARAM, + REQUEST_BODY, + CREATE_TIME + ).values( + webhookRequest.requestId, + webhookRequest.externalId, + webhookRequest.repositoryType, + webhookRequest.eventType, + webhookRequest.triggerUser, + webhookRequest.eventMessage, + webhookRequest.requestHeader?.let { JsonUtil.toJson(it) }, + webhookRequest.requestParam?.let { JsonUtil.toJson(it) }, + webhookRequest.requestBody, + webhookRequest.createTime + ).execute() + } + } + + fun get( + dslContext: DSLContext, + requestId: String + ): RepositoryWebhookRequest? { + val record = with(TRepositoryWebhookRequest.T_REPOSITORY_WEBHOOK_REQUEST) { + dslContext.selectFrom(this) + .where(REQUEST_ID.eq(requestId)) + .fetchOne() + } + return record?.let { convert(it) } + } + + fun convert(record: TRepositoryWebhookRequestRecord): RepositoryWebhookRequest { + return with(record) { + RepositoryWebhookRequest( + requestId = requestId, + externalId = externalId, + eventType = eventType, + repositoryType = repositoryType, + triggerUser = triggerUser, + eventMessage = eventMessage, + requestHeader = requestHeader?.let { + JsonUtil.to( + it, + object : TypeReference>() {}) + }, + requestParam = requestParam?.let { + JsonUtil.to( + it, + object : TypeReference>() {}) + }, + requestBody = requestBody, + createTime = createTime + ) + } + } +} diff --git a/src/backend/ci/core/repository/biz-repository/src/main/kotlin/com/tencent/devops/repository/resources/ServiceRepositoryWebhookResourceImpl.kt b/src/backend/ci/core/repository/biz-repository/src/main/kotlin/com/tencent/devops/repository/resources/ServiceRepositoryWebhookResourceImpl.kt new file mode 100644 index 00000000000..35b2930f43e --- /dev/null +++ b/src/backend/ci/core/repository/biz-repository/src/main/kotlin/com/tencent/devops/repository/resources/ServiceRepositoryWebhookResourceImpl.kt @@ -0,0 +1,51 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.devops.repository.resources + +import com.tencent.devops.common.api.pojo.Result +import com.tencent.devops.common.web.RestResource +import com.tencent.devops.repository.api.ServiceRepositoryWebhookResource +import com.tencent.devops.repository.pojo.RepositoryWebhookRequest +import com.tencent.devops.repository.service.RepositoryWebhookService +import org.springframework.beans.factory.annotation.Autowired + +@Suppress("ALL") +@RestResource +class ServiceRepositoryWebhookResourceImpl @Autowired constructor( + val repositoryWebhookService: RepositoryWebhookService +) : ServiceRepositoryWebhookResource { + + override fun saveWebhookRequest(repositoryWebhookRequest: RepositoryWebhookRequest): Result { + repositoryWebhookService.saveWebhookRequest(repositoryWebhookRequest) + return Result(true) + } + + override fun getWebhookRequest(requestId: String): Result { + return Result(repositoryWebhookService.getWebhookRequest(requestId = requestId)) + } +} diff --git a/src/backend/ci/core/repository/biz-repository/src/main/kotlin/com/tencent/devops/repository/service/RepositoryWebhookService.kt b/src/backend/ci/core/repository/biz-repository/src/main/kotlin/com/tencent/devops/repository/service/RepositoryWebhookService.kt new file mode 100644 index 00000000000..7da2fc78609 --- /dev/null +++ b/src/backend/ci/core/repository/biz-repository/src/main/kotlin/com/tencent/devops/repository/service/RepositoryWebhookService.kt @@ -0,0 +1,40 @@ +package com.tencent.devops.repository.service + +import com.tencent.devops.common.api.exception.ParamBlankException +import com.tencent.devops.repository.dao.RepositoryWebhookRequestDao +import com.tencent.devops.repository.pojo.RepositoryWebhookRequest +import org.jooq.DSLContext +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.stereotype.Service + +@Service +@SuppressWarnings("ALL") +class RepositoryWebhookService @Autowired constructor( + val repositoryWebhookRequestDao: RepositoryWebhookRequestDao, + val dslContext: DSLContext +) { + fun saveWebhookRequest(repositoryWebhookRequest: RepositoryWebhookRequest) { + with(repositoryWebhookRequest) { + if (externalId.isBlank()) { + throw ParamBlankException("Invalid eventSource") + } + if (repositoryType.isBlank()) { + throw ParamBlankException("Invalid triggerType") + } + if (eventType.isBlank()) { + throw ParamBlankException("Invalid eventType") + } + repositoryWebhookRequestDao.saveWebhookRequest( + dslContext = dslContext, + webhookRequest = repositoryWebhookRequest + ) + } + } + + fun getWebhookRequest(requestId: String): RepositoryWebhookRequest? { + return repositoryWebhookRequestDao.get( + dslContext = dslContext, + requestId = requestId + ) + } +} diff --git a/src/backend/ci/core/stream/biz-stream/src/main/kotlin/com/tencent/devops/stream/trigger/actions/GitActionCommon.kt b/src/backend/ci/core/stream/biz-stream/src/main/kotlin/com/tencent/devops/stream/trigger/actions/GitActionCommon.kt index 29ab48d4d1d..1543a447e42 100644 --- a/src/backend/ci/core/stream/biz-stream/src/main/kotlin/com/tencent/devops/stream/trigger/actions/GitActionCommon.kt +++ b/src/backend/ci/core/stream/biz-stream/src/main/kotlin/com/tencent/devops/stream/trigger/actions/GitActionCommon.kt @@ -3,8 +3,8 @@ package com.tencent.devops.stream.trigger.actions import com.tencent.devops.common.api.util.JsonUtil import com.tencent.devops.common.webhook.service.code.loader.WebhookElementParamsRegistrar import com.tencent.devops.common.webhook.service.code.loader.WebhookStartParamsRegistrar -import com.tencent.devops.common.webhook.service.code.matcher.ScmWebhookMatcher import com.tencent.devops.common.webhook.service.code.pojo.EventRepositoryCache +import com.tencent.devops.common.webhook.service.code.pojo.WebhookMatchResult import com.tencent.devops.common.webhook.util.EventCacheUtil import com.tencent.devops.process.yaml.v2.models.on.TriggerOn import com.tencent.devops.stream.common.Constansts @@ -97,7 +97,7 @@ object GitActionCommon { matcher = matcher, variables = mapOf(), params = webHookParams, - matchResult = ScmWebhookMatcher.MatchResult(isMatch = isMatch) + matchResult = WebhookMatchResult(isMatch = isMatch) ).map { entry -> entry.key to entry.value.toString() }.toMap() } else { emptyMap() diff --git a/src/backend/ci/core/stream/biz-stream/src/main/kotlin/com/tencent/devops/stream/trigger/parsers/triggerMatch/matchUtils/PathMatchUtils.kt b/src/backend/ci/core/stream/biz-stream/src/main/kotlin/com/tencent/devops/stream/trigger/parsers/triggerMatch/matchUtils/PathMatchUtils.kt index 65876a6ef88..81a09390bce 100644 --- a/src/backend/ci/core/stream/biz-stream/src/main/kotlin/com/tencent/devops/stream/trigger/parsers/triggerMatch/matchUtils/PathMatchUtils.kt +++ b/src/backend/ci/core/stream/biz-stream/src/main/kotlin/com/tencent/devops/stream/trigger/parsers/triggerMatch/matchUtils/PathMatchUtils.kt @@ -27,7 +27,7 @@ object PathMatchUtils { // 包含匹配失败 val includePathsMatch = pathIgnoreList.isEmpty() && pathList.isNotEmpty() && - response.getParam()[MATCH_PATHS] == null + response.params[MATCH_PATHS] == null return if (includePathsMatch) { TriggerBody().triggerFail("on.push.paths", "change path($pathList) not match") } else { diff --git a/support-files/i18n/message_en_US.properties b/support-files/i18n/message_en_US.properties index ffa7e6b9a6f..b2a4e95c302 100644 --- a/support-files/i18n/message_en_US.properties +++ b/support-files/i18n/message_en_US.properties @@ -425,3 +425,34 @@ BUILD_ENV_TYPE_WINDOWS=Build-Windows BUILD_ENV_TYPE_MACOS=Build-MacOS BUILD_ENV_TYPE_BUILDLESS=Buildles BUILD_ENV_TYPE_BUILD_TRIGGER=BuildTrigger +EVENT_TYPE_PUSH=Push +EVENT_TYPE_TAG_PUSH=Tag Push +EVENT_TYPE_MERGE_REQUEST=Merge Request +EVENT_TYPE_MERGE_REQUEST_ACCEPT=Merge Request Accept +EVENT_TYPE_ISSUES=Issue +EVENT_TYPE_NOTE=Note +EVENT_TYPE_REVIEW=Review +EVENT_TYPE_CREATE=Create Tag or Branch +EVENT_TYPE_PULL_REQUEST=Pull Request +EVENT_TYPE_POST_COMMIT=Post Commit +EVENT_TYPE_LOCK_COMMIT=Lock +EVENT_TYPE_PRE_COMMIT=Pre Commit +EVENT_TYPE_CHANGE_COMMIT=Change-Commit +EVENT_TYPE_CHANGE_CONTENT=Change-Content +EVENT_TYPE_CHANGE_SUBMIT=Change-Submit +EVENT_TYPE_SHELVE_COMMIT=Shelve-Commit +EVENT_TYPE_SHELVE_SUBMIT=Shelve-Submit +TRIGGER_TYPE_CODE_SVN=SVN +TRIGGER_TYPE_CODE_GIT=GIT +TRIGGER_TYPE_CODE_GITLAB=Gitlab +TRIGGER_TYPE_GITHUB=Github +TRIGGER_TYPE_CODE_TGIT=TGIT +TRIGGER_TYPE_CODE_P4=P4 +TRIGGER_TYPE_MANUAL=Manual Trigger +TRIGGER_TYPE_TIME_TRIGGER=Time Trigger +TRIGGER_TYPE_SERVICE=Service Trigger +TRIGGER_TYPE_PIPELINE=Pipeline Trigger +TRIGGER_TYPE_REMOTE=Remote Trigger +TRIGGER_SUCCESS=Trigger success +TRIGGER_FAILED=Trigger failed +TRIGGER_NOT_MATCH=Trigger not match diff --git a/support-files/i18n/message_zh_CN.properties b/support-files/i18n/message_zh_CN.properties index dd5fba1847f..27139a4849e 100644 --- a/support-files/i18n/message_zh_CN.properties +++ b/support-files/i18n/message_zh_CN.properties @@ -425,3 +425,34 @@ BUILD_ENV_TYPE_WINDOWS=构建环境-Windows BUILD_ENV_TYPE_MACOS=构建环境-MacOS BUILD_ENV_TYPE_BUILDLESS=无编译环境 BUILD_ENV_TYPE_BUILD_TRIGGER=构建触发 +EVENT_TYPE_PUSH=推送事件 +EVENT_TYPE_TAG_PUSH=Tag 推送事件 +EVENT_TYPE_MERGE_REQUEST=合并请求事件 +EVENT_TYPE_MERGE_REQUEST_ACCEPT=合并请求已合并事件 +EVENT_TYPE_ISSUES=议题事件 +EVENT_TYPE_NOTE=评论事件 +EVENT_TYPE_REVIEW=评审事件 +EVENT_TYPE_CREATE=创建 Tag/Branch 事件 +EVENT_TYPE_PULL_REQUEST=拉取请求事件 +EVENT_TYPE_POST_COMMIT=提交后置事件 +EVENT_TYPE_LOCK_COMMIT=锁定事件 +EVENT_TYPE_PRE_COMMIT=提交前置事件 +EVENT_TYPE_CHANGE_COMMIT=Change-Commit +EVENT_TYPE_CHANGE_CONTENT=Change-Content +EVENT_TYPE_CHANGE_SUBMIT=Change-Submit +EVENT_TYPE_SHELVE_COMMIT=Shelve-Commit +EVENT_TYPE_SHELVE_SUBMIT=Shelve-Submit +TRIGGER_TYPE_CODE_SVN=SVN 代码库 +TRIGGER_TYPE_CODE_GIT=GIT 代码库 +TRIGGER_TYPE_CODE_GITLAB=Gitlab 代码库 +TRIGGER_TYPE_GITHUB=Github 代码库 +TRIGGER_TYPE_CODE_TGIT=TGIT 代码库 +TRIGGER_TYPE_CODE_P4=P4 代码库 +TRIGGER_TYPE_MANUAL=手动触发 +TRIGGER_TYPE_TIME_TRIGGER=定时触发 +TRIGGER_TYPE_SERVICE=服务触发 +TRIGGER_TYPE_PIPELINE=流水线触发 +TRIGGER_TYPE_REMOTE=远程触发 +TRIGGER_SUCCESS=触发成功 +TRIGGER_FAILED=触发失败 +TRIGGER_NOT_MATCH=触发器不匹配 diff --git a/support-files/i18n/process/message_en_US.properties b/support-files/i18n/process/message_en_US.properties index 2ac4b2549c5..30f2e7ed438 100644 --- a/support-files/i18n/process/message_en_US.properties +++ b/support-files/i18n/process/message_en_US.properties @@ -359,3 +359,49 @@ commonShutdownSuccessContent=【${%s}】- 【${%s}】#${%s} Execution succeed, commonShutdownFailureContent=【${%s}】- 【${%s}】#${%s} Execution failed,consume time${%s}, trigger user: ${%s}。 bkBeforePosition=Check-in- Control points can only be executed if the conditions are met. bkAfterPosition=Check-out - Subsequent plugins can only be executed if the conditions are met. +bkTgitPushEventDesc=[{0}] Commit [{2}] pushed by {3} +bkTgitIssueOpenedEventDesc=Issue [!{1}] opened by {2} +bkTgitIssueUpdatedEventDesc=Issue [!{1}] updated by {2} +bkTgitIssueClosedEventDesc=Issue [!{1}] closed by {2} +bkTgitIssueReopenedEventDesc=Issue [!{1}] reopened by {2} +bkTgitMrCreatedEventDesc=Merge requests [!{1}] opened by {2} +bkTgitMrUpdatedEventDesc=Merge requests [!{1}] updated by {2} +bkTgitMrClosedEventDesc=Merge requests [!{1}] closed by {2} +bkTgitMrReopenedEventDesc=Merge requests [!{1}] reopened by {2} +bkTgitMrPushUpdatedEventDesc=Merge requests [!{1}] push updated by {2} +bkTgitMrMergedEventDesc=Merge requests [!{1}] merged by {2} +bkTgitTagPushEventDesc=[{0}]Tag [{2}] pushed by {3} +bkTgitNoteEventDesc=Note [{1}] submitted by {2} +bkTgitReviewCreatedEventDesc=Code review [{1}] created by {2} +bkTgitReviewApprovedEventDesc=Code review [{1}] approved by {2} +bkTgitReviewApprovingEventDesc=Code review [{1}] approving +bkTgitReviewChangeDeniedEventDesc=Code review [{1}] change denied by {2} +bkTgitReviewChangeRequiredEventDesc=Code review [{1}] change required by {2} +bkGithubPushEventDesc=[{0}] Commit [{2}] pushed by {3} +bkGithubCreateBranchEventDesc=Branch [{1}] created by {2} +bkGithubCreateTagEventDesc=Tag [{1}] pushed by {2} +bkGithubPrEventDesc=Pull request [!{1}] by {2} {3} +bkP4EventDesc=Change [{0}] by {1} {2} +bkSvnCommitEventDesc=Commit [{0}] pushed by {1} +bkManualStartEventDesc=Manually triggered by {0} +bkRemoteStartEventDesc=Remote api triggered by {0} [{1}] +bkServiceStartEventDesc=Pipeline invocation triggered by {0} invoke +bkPipelineStartEventDesc=Sub-Pipeline triggered by [{2}] {0} +bkTimingStartEventDesc=Timer triggered by {0} +bkEventReplayDesc=Event [{0}] replayed by {1} +bkRepoTriggerEventTypeNotMatch=Event type mismatch +bkRepoTriggerTargetBranchNotMatch=Target branch [{0}] of merge request does not match +bkRepoTriggerTargetBranchIgnored=Target branch [{0}] of merge request has been excluded +bkRepoTriggerSourceBranchNotMatch=Source branch [{0}] of merge request does not match +bkRepoTriggerSourceBranchIgnored=Source branch [{0}] of merge request has been excluded +bkRepoTriggerUserNotMatch=Trigger user [{0}] does not match +bkRepoTriggerUserIgnored=Trigger user [{0}] has been excluded +bkRepoTriggerPathNotMatch=Path does not match +bkRepoTriggerPathIgnored=Path has been excluded +bkRepoTriggerTagNameNotMatch=Tag [{0}] does not match +bkRepoTriggerTagNameIgnored=Tag [{0}] has been excluded +bkRepoTriggerTagSourceBranchNotMatch=Tag source branch does not match +bkRepoTriggerNoteContentNotMatch=Note does not match +bkRepoTriggerNoteActionNotMatch=Note type does not match +bkRepoTriggerReviewActionNotMatch=Code review type does not match +bkRepoTriggerIssueActionNotMatch=Issue action does not match diff --git a/support-files/i18n/process/message_zh_CN.properties b/support-files/i18n/process/message_zh_CN.properties index a9674a67306..2760a28a4a8 100644 --- a/support-files/i18n/process/message_zh_CN.properties +++ b/support-files/i18n/process/message_zh_CN.properties @@ -359,3 +359,49 @@ commonShutdownSuccessContent=【${%s}】- 【${%s}】#${%s} 执行成功,耗 commonShutdownFailureContent=【${%s}】- 【${%s}】#${%s} 执行失败,耗时${%s}, 触发人: ${%s}。 bkBeforePosition=准入-满足条件才能执行控制点 bkAfterPosition=准出-满足条件才能执行后续插件 +bkTgitPushEventDesc=[{0}] 提交 [{2}] 由 {3} 推送 +bkTgitIssueCreatedEventDesc=议题 [!{1}] 由 {2} 创建 +bkTgitIssueUpdatedEventDesc=议题 [!{1}] 由 {2} 更新 +bkTgitIssueClosedEventDesc=议题 [!{1}] 由 {2} 关闭 +bkTgitIssueReopenedEventDesc=议题 [!{1}] 由 {2} 重新打开 +bkTgitMrCreatedEventDesc=合并请求 [!{1}] 由 {2} 创建 +bkTgitMrUpdatedEventDesc=合并请求 [!{1}] 由 {2} 更新 +bkTgitMrClosedEventDesc=合并请求 [!{1}] 由 {2} 关闭 +bkTgitMrReopenedEventDesc=合并请求 [!{1}] 由 {2} 重新打开 +bkTgitMrPushUpdatedEventDesc=合并请求 [!{1}] 由 {2} 在源分支提交代码触发 +bkTgitMrMergedEventDesc=合并请求 [!{1}] 由 {2} 合并 +bkTgitTagPushEventDesc=[{0}] 创建Tag [{2}] 由 {3} 推送 +bkTgitNoteEventDesc=评论 [{1}] 由 {2} 发表 +bkTgitReviewCreatedEventDesc=代码审查 [{1}] 由 {2} 创建 +bkTgitReviewApprovedEventDesc=代码审查 [{1}] 由 {2} 评审通过 +bkTgitReviewApprovingEventDesc=代码审查 [{1}] 评审中 +bkTgitReviewChangeDeniedEventDesc=代码审查 [{1}] 被 {2} 拒绝 +bkTgitReviewChangeRequiredEventDesc=代码审查 [{1}] 由 {2} 要求修改 +bkGithubPushEventDesc=[{0}] 提交 [{2}] 由 {3} 推送 +bkGithubCreateBranchEventDesc=分支 [{1}] 由 {2} 创建 +bkGithubCreateTagEventDesc=Tag [{1}] 由 {2} 推送 +bkGithubPrEventDesc=拉取请求 [{1}] 由 {2} {3} +bkP4EventDesc=Change {0} 由 {1} {2} +bkSvnCommitEventDesc=提交 [{0}] 由 {1} 推送 +bkManualStartEventDesc={0} 手动触发 +bkRemoteStartEventDesc={0} [{1}] 远程触发 +bkServiceStartEventDesc={0} 触发的流水线调用 +bkPipelineStartEventDesc=[{2}] {0} 子流水线调用 +bkTimingStartEventDesc={0} 定时触发 +bkEventReplayDesc=事件 [{0}] 由 {1} 重放 +bkRepoTriggerEventTypeNotMatch=事件类型不满足触发条件 +bkRepoTriggerTargetBranchNotMatch=MR目标分支[{0}]不满足触发条件 +bkRepoTriggerTargetBranchIgnored=MR目标分支[{0}]被排除 +bkRepoTriggerSourceBranchNotMatch=MR源分支[{0}]不满足触发条件 +bkRepoTriggerSourceBranchIgnored=MR源分支[{0}]被排除 +bkRepoTriggerUserNotMatch=触发人[{0}]不匹配 +bkRepoTriggerUserIgnored=触发人[{0}]被排除 +bkRepoTriggerPathNotMatch=路径不满足触发条件 +bkRepoTriggerPathIgnored=路径被排除 +bkRepoTriggerTagNameNotMatch=Tag 名称[{0}]不满足触发条件 +bkRepoTriggerTagNameIgnored=Tag 名称[{0}]被排除 +bkRepoTriggerTagSourceBranchNotMatch=Tag 来源分支不满足触发条件 +bkRepoTriggerNoteContentNotMatch=评论内容不满足触发条件 +bkRepoTriggerNoteActionNotMatch=评论类型不满足触发条件 +bkRepoTriggerReviewActionNotMatch=评审类型不满足触发条件 +bkRepoTriggerIssueActionNotMatch=Issue 动作不满足触发条件 diff --git a/support-files/sql/1001_ci_process_ddl_mysql.sql b/support-files/sql/1001_ci_process_ddl_mysql.sql index 9124b4450ec..1737a0f3c7f 100644 --- a/support-files/sql/1001_ci_process_ddl_mysql.sql +++ b/support-files/sql/1001_ci_process_ddl_mysql.sql @@ -640,6 +640,9 @@ CREATE TABLE IF NOT EXISTS `T_PIPELINE_WEBHOOK` ( `PROJECT_NAME` VARCHAR(128) DEFAULT NULL COMMENT '项目名称', `TASK_ID` VARCHAR(34) DEFAULT NULL COMMENT '任务id', `DELETE` BIT(1) DEFAULT 0 COMMENT '是否删除', + `EVENT_TYPE` varchar(64) DEFAULT NULL COMMENT '事件类型', + `EXTERNAL_ID` varchar(255) DEFAULT NULL COMMENT '代码库平台ID', + `REPOSITORY_HASH_ID` varchar(64) null comment '代码库hashId', PRIMARY KEY (`ID`), UNIQUE KEY `UNI_INX_TPW_PROJECT_PIPELINE_TASK` (`PROJECT_ID`, `PIPELINE_ID`,`TASK_ID`), KEY `IDX_PROJECT_NAME_REPOSITORY_TYPE` (`PROJECT_NAME`, `REPOSITORY_TYPE`) @@ -906,36 +909,6 @@ CREATE TABLE IF NOT EXISTS `T_PIPELINE_ATOM_REPLACE_HISTORY` ( KEY `INX_TPARH_ITEM_ID` (`ITEM_ID`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='流水线插件替换历史信息表'; -CREATE TABLE IF NOT EXISTS `T_PIPELINE_WEBHOOK_BUILD_LOG` ( - `ID` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID', - `CODE_TYPE` VARCHAR(32) NOT NULL COMMENT '代码库类型', - `REPO_NAME` VARCHAR(128) NOT NULL COMMENT '代码库别名', - `COMMIT_ID` VARCHAR(64) NOT NULL COMMENT '代码提交ID', - `REQUEST_CONTENT` TEXT COMMENT '事件内容', - `CREATED_TIME` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `RECEIVED_TIME` DATETIME NOT NULL COMMENT '接收时间', - `FINISHED_TIME` DATETIME NOT NULL COMMENT '完成时间', - PRIMARY KEY (`ID`,`CREATED_TIME`), - KEY `IDX_REPO_NAME_COMMIT_ID`(`REPO_NAME`, `COMMIT_ID`) -)ENGINE=INNODB DEFAULT CHARSET=utf8mb4 COMMENT=''; - -CREATE TABLE IF NOT EXISTS `T_PIPELINE_WEBHOOK_BUILD_LOG_DETAIL` ( - `ID` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID', - `LOG_ID` BIGINT(20) NOT NULL COMMENT '', - `CODE_TYPE` VARCHAR(32) NOT NULL COMMENT '代码库类型', - `REPO_NAME` VARCHAR(128) NOT NULL COMMENT '代码库别名', - `COMMIT_ID` VARCHAR(64) NOT NULL COMMENT '代码提交ID', - `PROJECT_ID` varchar(32) NOT NULL COMMENT '项目ID', - `PIPELINE_ID` varchar(34) NOT NULL COMMENT '流水线ID', - `TASK_ID` VARCHAR(34) NOT NULL COMMENT '任务id', - `TASK_NAME` VARCHAR(128) COMMENT '任务名称', - `SUCCESS` BIT(1) DEFAULT b'0' COMMENT '是否成功', - `TRIGGER_RESULT` TEXT COMMENT '触发结果', - `CREATED_TIME` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - PRIMARY KEY (`ID`,`CREATED_TIME`), - KEY `IDX_PIPELINE_ID_COMMIT_ID`(`PIPELINE_ID`,`COMMIT_ID`) -)ENGINE=INNODB DEFAULT CHARSET=utf8mb4 COMMENT=''; - CREATE TABLE IF NOT EXISTS `T_PIPELINE_RESOURCE_VERSION` ( `PROJECT_ID` varchar(64) COLLATE utf8mb4_bin NOT NULL DEFAULT '' COMMENT '项目ID', `PIPELINE_ID` varchar(34) NOT NULL COMMENT '流水线ID', @@ -1172,4 +1145,49 @@ CREATE TABLE IF NOT EXISTS `T_PIPELINE_BUILD_RECORD_TASK` ( PRIMARY KEY (`BUILD_ID`,`TASK_ID`,`EXECUTE_COUNT`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='流水线构建任务表'; + +-- ---------------------------- +-- Table structure for T_PIPELINE_TRIGGER_EVENT +-- ---------------------------- + +CREATE TABLE IF NOT EXISTS `T_PIPELINE_TRIGGER_EVENT` +( + `REQUEST_ID` varchar(64) NOT NULL COMMENT '请求ID', + `PROJECT_ID` varchar(64) NOT NULL COMMENT '项目ID', + `EVENT_ID` bigint(20) NOT NULL COMMENT '事件ID', + `TRIGGER_TYPE` varchar(64) NOT NULL COMMENT '触发类型', + `EVENT_SOURCE` varchar(255) NOT NULL COMMENT '触发源,代码库hashId/触发人/远程ip', + `EVENT_TYPE` varchar(64) NOT NULL COMMENT '事件类型', + `TRIGGER_USER` varchar(100) NOT NULL COMMENT '触发用户', + `EVENT_DESC` text NOT NULL COMMENT '事件描述', + `REPLAY_REQUEST_ID` varchar(64) NULL COMMENT '重放请求ID', + `REQUEST_PARAMS` text DEFAULT NULL COMMENT '请求参数', + `CREATE_TIME` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '事件时间', + PRIMARY KEY (`EVENT_ID`, `CREATE_TIME`), + unique UNIQ_REQUEST(`REQUEST_ID`, `EVENT_SOURCE`), + INDEX IDX_EVENT (`PROJECT_ID`, `EVENT_SOURCE`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COMMENT ='流水线触发事件表'; + +-- ---------------------------- +-- Table structure for T_PIPELINE_TRIGGER_DETAIL +-- ---------------------------- + +CREATE TABLE IF NOT EXISTS `T_PIPELINE_TRIGGER_DETAIL` +( + `DETAIL_ID` bigint(20) NOT NULL COMMENT '事件明细ID', + `PROJECT_ID` varchar(64) NOT NULL COMMENT '项目ID', + `EVENT_ID` bigint(20) NOT NULL COMMENT '事件ID', + `STATUS` varchar(100) DEFAULT NULL COMMENT '状态(success or failure)', + `PIPELINE_ID` varchar(100) DEFAULT NULL COMMENT '流水线ID', + `PIPELINE_NAME` varchar(255) DEFAULT NULL COMMENT '流水线名称', + `VERSION` int DEFAULT NULL COMMENT '流水线版本号', + `BUILD_ID` varchar(100) DEFAULT NULL COMMENT '构建ID', + `BUILD_NUM` varchar(100) DEFAULT NULL COMMENT '构建编号', + `REASON` varchar(100) DEFAULT NULL COMMENT '失败原因', + `REASON_DETAIL` text DEFAULT NULL COMMENT '原因详情', + `CREATE_TIME` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + PRIMARY KEY (`DETAIL_ID`, `CREATE_TIME`), + INDEX IDX_PROJECT_ID_EVENT_ID (`PROJECT_ID`, `EVENT_ID`, `PIPELINE_NAME`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COMMENT ='流水线触发事件明细表'; + SET FOREIGN_KEY_CHECKS = 1; diff --git a/support-files/sql/1001_ci_repository_ddl_mysql.sql b/support-files/sql/1001_ci_repository_ddl_mysql.sql index e08a870c280..34f7e7c4b2c 100644 --- a/support-files/sql/1001_ci_repository_ddl_mysql.sql +++ b/support-files/sql/1001_ci_repository_ddl_mysql.sql @@ -219,4 +219,23 @@ CREATE TABLE IF NOT EXISTS `T_REPOSITORY_PIPELINE_REF` ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COMMENT = '流水线引用代码库表'; +-- ---------------------------- +-- Table structure for T_REPOSITORY_WEBHOOK_REQUEST +-- ---------------------------- + +CREATE TABLE IF NOT EXISTS `T_REPOSITORY_WEBHOOK_REQUEST` +( + `REQUEST_ID` varchar(64) NOT NULL COMMENT '请求ID', + `EXTERNAL_ID` varchar(255) DEFAULT NULL COMMENT '代码库平台ID', + `REPOSITORY_TYPE` varchar(32) DEFAULT NULL COMMENT '触发类型', + `EVENT_TYPE` varchar(255) DEFAULT NULL COMMENT '事件类型', + `TRIGGER_USER` varchar(100) NOT NULL COMMENT '触发用户', + `EVENT_MESSAGE` text NOT NULL COMMENT '事件信息', + `REQUEST_HEADER` text COMMENT '事件请求头', + `REQUEST_PARAM` text COMMENT '事件请求参数', + `REQUEST_BODY` text COMMENT '事件请求体', + `CREATE_TIME` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + PRIMARY KEY (`REQUEST_ID`, `CREATE_TIME`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COMMENT ='代码库WEBHOOK请求表'; + SET FOREIGN_KEY_CHECKS = 1; diff --git a/support-files/sql/2003_v2.x/2020_ci_process-update_v2.0_mysql.sql b/support-files/sql/2003_v2.x/2020_ci_process-update_v2.0_mysql.sql index 7119a8d49e8..9e8b2a08b5e 100644 --- a/support-files/sql/2003_v2.x/2020_ci_process-update_v2.0_mysql.sql +++ b/support-files/sql/2003_v2.x/2020_ci_process-update_v2.0_mysql.sql @@ -85,6 +85,34 @@ BEGIN ADD INDEX `IDX_TPVUS_PROJECT_ID`(`PROJECT_ID`); END IF; + IF NOT EXISTS(SELECT 1 + FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = db + AND TABLE_NAME = 'T_PIPELINE_WEBHOOK' + AND COLUMN_NAME = 'EVENT_TYPE') THEN + ALTER TABLE `T_PIPELINE_WEBHOOK` + ADD COLUMN `EVENT_TYPE` varchar(64) DEFAULT null COMMENT '事件类型'; + END IF; + + IF NOT EXISTS(SELECT 1 + FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = db + AND TABLE_NAME = 'T_PIPELINE_WEBHOOK' + AND COLUMN_NAME = 'EXTERNAL_ID') THEN + ALTER TABLE `T_PIPELINE_WEBHOOK` + ADD COLUMN `EXTERNAL_ID` varchar(255) DEFAULT null COMMENT '代码库平台ID'; + END IF; + + IF NOT EXISTS(SELECT 1 + FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = db + AND TABLE_NAME = 'T_PIPELINE_WEBHOOK' + AND COLUMN_NAME = 'REPOSITORY_HASH_ID') THEN + ALTER TABLE `T_PIPELINE_WEBHOOK` + ADD COLUMN `REPOSITORY_HASH_ID` varchar(64) null comment '代码库hashId'; + END IF; + + COMMIT; END DELIMITER ; diff --git a/support-files/sql/5001_init_dml/5001_ci_project-init_dml_mysql.sql b/support-files/sql/5001_init_dml/5001_ci_project-init_dml_mysql.sql index abda94e3f08..ed69ba28dec 100755 --- a/support-files/sql/5001_init_dml/5001_ci_project-init_dml_mysql.sql +++ b/support-files/sql/5001_init_dml/5001_ci_project-init_dml_mysql.sql @@ -49,6 +49,8 @@ REPLACE INTO `T_LEAF_ALLOC`(`BIZ_TAG`, `MAX_ID`, `STEP`, `DESCRIPTION`) VALUES ( REPLACE INTO `T_LEAF_ALLOC`(`BIZ_TAG`, `MAX_ID`, `STEP`, `DESCRIPTION`) VALUES ('AUTH_RESOURCE', 1, 100, '权限资源'); REPLACE INTO `T_LEAF_ALLOC`(`BIZ_TAG`, `MAX_ID`, `STEP`, `DESCRIPTION`) VALUES ('ATOM_MONITOR_DATA_DAILY', 1, 100, '插件每日监控数据ID管理'); REPLACE INTO `T_LEAF_ALLOC`(`BIZ_TAG`, `MAX_ID`, `STEP`, `DESCRIPTION`) VALUES ('METRICS_PROJECT_ATOM_RELEVANCY_INFO', 1, 50, 'metris项目插件关联表ID管理'); +REPLACE INTO `T_LEAF_ALLOC`(`BIZ_TAG`, `MAX_ID`, `STEP`, `DESCRIPTION`) VALUES ('PIPELINE_TRIGGER_EVENT', 1, 2000, '流水线触发事件'); +REPLACE INTO `T_LEAF_ALLOC`(`BIZ_TAG`, `MAX_ID`, `STEP`, `DESCRIPTION`) VALUES ('PIPELINE_TRIGGER_DETAIL', 1, 2000, '流水线触发详情'); REPLACE INTO `T_I18N_MESSAGE` (`ID`, `MODULE_CODE`, `LANGUAGE`, `KEY`, `VALUE`, `CREATOR`, `MODIFIER`, `UPDATE_TIME`, `CREATE_TIME`) VALUES('12cfe76hgu9cn4047bfd4e6ddd0aaada', 'STORE', 'zh_CN', 'reason.e20897c838564d61b5af1a8c9c1d26d2.content', '只是试用下', 'system', 'system', '2023-06-26 10:59:20.561', '2023-06-26 10:59:47'); REPLACE INTO `T_I18N_MESSAGE` (`ID`, `MODULE_CODE`, `LANGUAGE`, `KEY`, `VALUE`, `CREATOR`, `MODIFIER`, `UPDATE_TIME`, `CREATE_TIME`) VALUES('13312a05cxt1468088bdb71637sc14ds', 'STORE', 'en_US', 'reason.e20897c838564d61b5af1a8c9c1d26d2.content', 'Just trying it out.', 'system', 'system', '2023-06-26 10:59:20.561', '2023-06-26 10:59:47'); diff --git a/support-files/templates/#etc#ci#common.yml b/support-files/templates/#etc#ci#common.yml index 0db6d84cb5e..9f4f0cd95a5 100644 --- a/support-files/templates/#etc#ci#common.yml +++ b/support-files/templates/#etc#ci#common.yml @@ -132,9 +132,6 @@ spring: - index: 23 name: T_PIPELINE_VIEW_USER_SETTINGS databaseShardingStrategy: SHARDING - - index: 24 - name: T_PIPELINE_WEBHOOK_BUILD_LOG_DETAIL - databaseShardingStrategy: SHARDING - index: 25 name: T_PIPELINE_WEBHOOK_QUEUE databaseShardingStrategy: SHARDING @@ -219,7 +216,13 @@ spring: - index: 52 name: T_PIPELINE_BUILD_RECORD_TASK databaseShardingStrategy: SHARDING - + - index: 53 + name: T_PIPELINE_TRIGGER_EVENT + databaseShardingStrategy: SHARDING + - index: 54 + name: T_PIPELINE_TRIGGER_DETAIL + databaseShardingStrategy: SHARDING + endpoints: metrics: