diff --git a/src/backend/ci/core/common/common-pipeline-yaml/src/main/kotlin/com/tencent/devops/process/yaml/transfer/TriggerTransfer.kt b/src/backend/ci/core/common/common-pipeline-yaml/src/main/kotlin/com/tencent/devops/process/yaml/transfer/TriggerTransfer.kt index c50f543ae79..41a6a32348d 100644 --- a/src/backend/ci/core/common/common-pipeline-yaml/src/main/kotlin/com/tencent/devops/process/yaml/transfer/TriggerTransfer.kt +++ b/src/backend/ci/core/common/common-pipeline-yaml/src/main/kotlin/com/tencent/devops/process/yaml/transfer/TriggerTransfer.kt @@ -160,7 +160,8 @@ class TriggerTransfer @Autowired(required = false) constructor( repositoryName = triggerOn.repoName, enableThirdFilter = !mr.custom?.url.isNullOrBlank(), thirdUrl = mr.custom?.url, - thirdSecretToken = mr.custom?.credentials + thirdSecretToken = mr.custom?.credentials, + skipWip = mr.skipWip ).checkTriggerElementEnable(mr.enable).apply { version = "2.*" } @@ -296,7 +297,8 @@ class TriggerTransfer @Autowired(required = false) constructor( custom = if (git.enableThirdFilter == true) CustomFilter( url = git.thirdUrl, credentials = git.thirdSecretToken - ) else null + ) else null, + skipWip = git.skipWip ) CodeEventType.MERGE_REQUEST_ACCEPT -> throw PipelineTransferException( @@ -463,7 +465,8 @@ class TriggerTransfer @Autowired(required = false) constructor( ), eventType = CodeEventType.MERGE_REQUEST, repositoryType = repositoryType, - repositoryName = triggerOn.repoName + repositoryName = triggerOn.repoName, + skipWip = mr.skipWip ) ) ).checkTriggerElementEnable(mr.enable).apply { diff --git a/src/backend/ci/core/common/common-pipeline-yaml/src/main/kotlin/com/tencent/devops/process/yaml/transfer/pojo/WebHookTriggerElementChanger.kt b/src/backend/ci/core/common/common-pipeline-yaml/src/main/kotlin/com/tencent/devops/process/yaml/transfer/pojo/WebHookTriggerElementChanger.kt index b1ddc853ee4..85c174b1e5d 100644 --- a/src/backend/ci/core/common/common-pipeline-yaml/src/main/kotlin/com/tencent/devops/process/yaml/transfer/pojo/WebHookTriggerElementChanger.kt +++ b/src/backend/ci/core/common/common-pipeline-yaml/src/main/kotlin/com/tencent/devops/process/yaml/transfer/pojo/WebHookTriggerElementChanger.kt @@ -100,7 +100,9 @@ data class WebHookTriggerElementChanger( @get:Schema(title = "第三方应用鉴权token") val thirdSecretToken: String? = null, @get:Schema(title = "是否启用插件") - val enable: Boolean + val enable: Boolean, + @get:Schema(title = "跳过WIP") + val skipWip: Boolean? = false ) { constructor(data: CodeGitWebHookTriggerElement) : this( name = data.name, @@ -133,7 +135,8 @@ data class WebHookTriggerElementChanger( enableThirdFilter = data.enableThirdFilter, thirdUrl = data.thirdUrl, thirdSecretToken = data.thirdSecretToken, - enable = data.isElementEnable() + enable = data.isElementEnable(), + skipWip = data.skipWip ) constructor(data: CodeTGitWebHookTriggerElement) : this( @@ -165,7 +168,8 @@ data class WebHookTriggerElementChanger( includeMrAction = data.data.input.includeMrAction, includePushAction = data.data.input.includePushAction, enableThirdFilter = data.data.input.enableThirdFilter, - enable = data.isElementEnable() + enable = data.isElementEnable(), + skipWip = data.data.input.skipWip ) constructor(data: CodeGithubWebHookTriggerElement) : this( diff --git a/src/backend/ci/core/common/common-pipeline-yaml/src/main/kotlin/com/tencent/devops/process/yaml/v3/models/on/MrRule.kt b/src/backend/ci/core/common/common-pipeline-yaml/src/main/kotlin/com/tencent/devops/process/yaml/v3/models/on/MrRule.kt index 63acc584f17..13720b02a03 100644 --- a/src/backend/ci/core/common/common-pipeline-yaml/src/main/kotlin/com/tencent/devops/process/yaml/v3/models/on/MrRule.kt +++ b/src/backend/ci/core/common/common-pipeline-yaml/src/main/kotlin/com/tencent/devops/process/yaml/v3/models/on/MrRule.kt @@ -88,5 +88,9 @@ data class MrRule( @get:Schema(title = "custom-filter") @JsonProperty("custom-filter") - val custom: CustomFilter? = null + val custom: CustomFilter? = null, + + @JsonProperty("skip-wip") + @get:Schema(title = "skip-wip") + var skipWip: Boolean? = null ) diff --git a/src/backend/ci/core/common/common-pipeline-yaml/src/main/resources/schema/V3_0/ci.json b/src/backend/ci/core/common/common-pipeline-yaml/src/main/resources/schema/V3_0/ci.json index cac3c239d04..41a597c4e38 100644 --- a/src/backend/ci/core/common/common-pipeline-yaml/src/main/resources/schema/V3_0/ci.json +++ b/src/backend/ci/core/common/common-pipeline-yaml/src/main/resources/schema/V3_0/ci.json @@ -255,6 +255,9 @@ "type" : "string" } } + }, + "skip-wip" : { + "type" : "boolean" } } } ] @@ -943,6 +946,9 @@ "type" : "string" } } + }, + "skip-wip" : { + "type" : "boolean" } } } ] diff --git a/src/backend/ci/core/common/common-pipeline/src/main/kotlin/com/tencent/devops/common/pipeline/pojo/element/trigger/CodeGitWebHookTriggerElement.kt b/src/backend/ci/core/common/common-pipeline/src/main/kotlin/com/tencent/devops/common/pipeline/pojo/element/trigger/CodeGitWebHookTriggerElement.kt index d9eed37355b..2ded15777e0 100644 --- a/src/backend/ci/core/common/common-pipeline/src/main/kotlin/com/tencent/devops/common/pipeline/pojo/element/trigger/CodeGitWebHookTriggerElement.kt +++ b/src/backend/ci/core/common/common-pipeline/src/main/kotlin/com/tencent/devops/common/pipeline/pojo/element/trigger/CodeGitWebHookTriggerElement.kt @@ -102,7 +102,9 @@ data class CodeGitWebHookTriggerElement( @get:Schema(title = "第三方应用地址") val thirdUrl: String? = null, @get:Schema(title = "第三方应用鉴权token") - val thirdSecretToken: String? = null + val thirdSecretToken: String? = null, + @get:Schema(title = "跳过WIP") + val skipWip: Boolean? = false ) : WebHookTriggerElement(name, id, status) { companion object { const val classType = "codeGitWebHookTrigger" diff --git a/src/backend/ci/core/common/common-pipeline/src/main/kotlin/com/tencent/devops/common/pipeline/pojo/element/trigger/CodeTGitWebHookTriggerElement.kt b/src/backend/ci/core/common/common-pipeline/src/main/kotlin/com/tencent/devops/common/pipeline/pojo/element/trigger/CodeTGitWebHookTriggerElement.kt index 5a5c7c957ba..416bc6bb411 100644 --- a/src/backend/ci/core/common/common-pipeline/src/main/kotlin/com/tencent/devops/common/pipeline/pojo/element/trigger/CodeTGitWebHookTriggerElement.kt +++ b/src/backend/ci/core/common/common-pipeline/src/main/kotlin/com/tencent/devops/common/pipeline/pojo/element/trigger/CodeTGitWebHookTriggerElement.kt @@ -215,5 +215,7 @@ data class CodeTGitWebHookTriggerInput( @get:Schema(title = "push事件action") val includePushAction: List? = null, @get:Schema(title = "是否启用第三方过滤") - val enableThirdFilter: Boolean? = false + val enableThirdFilter: Boolean? = false, + @get:Schema(title = "跳过WIP") + val skipWip: Boolean? = false ) 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 index 4dcbdcdf679..eff82662b5e 100644 --- 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 @@ -144,6 +144,9 @@ object WebhookI18nConstants { // Github Push操作类型不匹配 const val PUSH_ACTION_NOT_MATCH = "bkRepoTriggerPushActionNotMatch" + // WIP阶段不触发 + const val MR_SKIP_WIP = "bkRepoTriggerSkipWipNotMatch" + // 事件回放 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/code/WebHookParams.kt b/src/backend/ci/core/common/common-webhook/api-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/pojo/code/WebHookParams.kt index 60d4b7896a0..838cba39355 100644 --- a/src/backend/ci/core/common/common-webhook/api-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/pojo/code/WebHookParams.kt +++ b/src/backend/ci/core/common/common-webhook/api-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/pojo/code/WebHookParams.kt @@ -73,5 +73,7 @@ data class WebHookParams( var thirdUrl: String? = null, var thirdSecretToken: String? = null, // 插件版本 - var version: String? = null + var version: String? = null, + // 跳过WIP + var skipWip: Boolean? = false ) diff --git a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/filter/SkipCiFilter.kt b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/filter/KeywordSkipFilter.kt similarity index 69% rename from src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/filter/SkipCiFilter.kt rename to src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/filter/KeywordSkipFilter.kt index dfbe1421ee3..5eb81b2b434 100644 --- a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/filter/SkipCiFilter.kt +++ b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/filter/KeywordSkipFilter.kt @@ -27,16 +27,32 @@ package com.tencent.devops.common.webhook.service.code.filter -class SkipCiFilter( +import org.slf4j.LoggerFactory + +class KeywordSkipFilter( private val pipelineId: String, - private val triggerOnMessage: String? + private val keyWord: List, + private val enable: Boolean? = true, + private val triggerOnMessage: String?, + private val failedReason: String = "" ) : WebhookFilter { companion object { - private const val SKIP_CI = "[skip ci]" + private val logger = LoggerFactory.getLogger(KeywordSkipFilter::class.java) + val KEYWORD_SKIP_CI = listOf("[skip ci]") + val KEYWORD_SKIP_WIP = listOf("[WIP]", "WIP") } override fun doFilter(response: WebhookFilterResponse): Boolean { - return triggerOnMessage?.contains(SKIP_CI) != true + logger.info("$pipelineId|triggerOnMessage:$triggerOnMessage|skipWord:$keyWord|enable:$enable") + return when { + enable == false -> true + keyWord.any { triggerOnMessage?.contains(it) == true } -> { + response.failedReason = failedReason + 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/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 18cae3e2895..ab1fbe9eccd 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 @@ -81,7 +81,9 @@ import com.tencent.devops.common.webhook.service.code.EventCacheService import com.tencent.devops.common.webhook.service.code.filter.BranchFilter 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.KeywordSkipFilter +import com.tencent.devops.common.webhook.service.code.filter.KeywordSkipFilter.Companion.KEYWORD_SKIP_CI +import com.tencent.devops.common.webhook.service.code.filter.KeywordSkipFilter.Companion.KEYWORD_SKIP_WIP 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 @@ -192,6 +194,13 @@ class TGitMrTriggerHandler( webHookParams: WebHookParams ): List { with(webHookParams) { + val wipFilter = KeywordSkipFilter( + pipelineId = pipelineId, + enable = skipWip, + keyWord = KEYWORD_SKIP_WIP, + triggerOnMessage = getMessage(event), + failedReason = I18Variable(WebhookI18nConstants.MR_SKIP_WIP).toJsonStr() + ) val userId = getUsername(event) val userFilter = UserFilter( pipelineId = pipelineId, @@ -237,8 +246,9 @@ class TGitMrTriggerHandler( params = listOf(sourceBranch) ).toJsonStr() ) - val skipCiFilter = SkipCiFilter( + val skipCiFilter = KeywordSkipFilter( pipelineId = pipelineId, + keyWord = KEYWORD_SKIP_CI, triggerOnMessage = event.object_attributes.last_commit.message ) val actionFilter = ContainsFilter( @@ -309,7 +319,7 @@ class TGitMrTriggerHandler( callbackCircuitBreakerRegistry = callbackCircuitBreakerRegistry ) return listOf( - userFilter, targetBranchFilter, + wipFilter, userFilter, targetBranchFilter, sourceBranchFilter, skipCiFilter, pathFilter, commitMessageFilter, actionFilter, 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/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 bd2d273da4a..f99f4d30d49 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 @@ -66,7 +66,8 @@ 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.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.KeywordSkipFilter +import com.tencent.devops.common.webhook.service.code.filter.KeywordSkipFilter.Companion.KEYWORD_SKIP_CI 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 @@ -216,8 +217,9 @@ class TGitPushTriggerHandler( params = listOf(triggerOnBranchName) ).toJsonStr() ) - val skipCiFilter = SkipCiFilter( + val skipCiFilter = KeywordSkipFilter( pipelineId = pipelineId, + keyWord = KEYWORD_SKIP_CI, triggerOnMessage = event.commits?.get(0)?.message ?: "" ) val commits = event.commits diff --git a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/param/GitWebhookElementParams.kt b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/param/GitWebhookElementParams.kt index d952bc679ae..7d4bed77fc2 100644 --- a/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/param/GitWebhookElementParams.kt +++ b/src/backend/ci/core/common/common-webhook/biz-common-webhook/src/main/kotlin/com/tencent/devops/common/webhook/service/code/param/GitWebhookElementParams.kt @@ -121,6 +121,7 @@ class GitWebhookElementParams : ScmWebhookElementParams2. To create a trigger, the credentials associated with the repository must have administrator privileges
3. Deleting the trigger plugin will not delete the server-side trigger, you need to delete it manually
"},"repositoryType":{"rule":{},"type":"enum-input","required":true,"label":"Repository","list":[{"value":"ID","label":"Select by repository ID"},{"value":"NAME","label":"Enter by repository alias"}],"default":"ID","desc":""},"repositoryHashId":{"rule":{},"label":"","hasAddItem":true,"type":"request-selector","searchable":true,"placeholder":"Please select a repository name","required":true,"default":"","url":"/repository/api/user/repositories/{projectId}/hasPermissionList?permission=USE&repositoryType=CODE_P4&page=1&pageSize=100","paramId":"repositoryHashId","paramName":"aliasName","tools":{"edit":true,"del":false},"rely":{"operation":"OR","expression":[{"key":"repositoryType","value":"ID"}]}},"repositoryName":{"rule":{},"type":"vuex-input","required":true,"label":"","placeholder":"请Enter a repository alias","default":"","rely":{"operation":"AND","expression":[{"key":"repositoryType","value":"NAME"}]}},"eventType":{"rule":{},"required":false,"type":"enum-input","label":"Event Type","list":[{"label":"change commit","value":"CHANGE_COMMIT"},{"label":"change content","value":"CHANGE_CONTENT"},{"label":"change submit","value":"CHANGE_SUBMIT"},{"label":"shelve commit","value":"SHELVE_COMMIT"},{"label":"shelve submit","value":"SHELVE_SUBMIT"}],"default":"CHANGE_COMMIT"},"noticePath":{"label":"","type":"tips","tipStr":"The Perforce path matching starts from the depot path. For example, if there is a demo depot, the configuration rules are as follows:
1. Listen to the aaa stream under //demo, //demo/aaa/**
2. Listen to //demo The java file under, //demo/*.java"},"includePaths":{"rule":{},"required":true,"type":"vuex-input","label":"Listen to the following paths","placeholder":"Separate multiple paths with commas","default":""},"excludePaths":{"rule":{},"required":false,"type":"vuex-input","label":"Exclude the following paths","placeholder":"Separate multiple paths with commas","default":""}}}','{}','BlueKing','2','system','system','2021-11-16 12:18:20','2021-11-16 12:18:20', 0); REPLACE INTO `T_ATOM` (`ID`, `NAME`, `ATOM_CODE`, `CLASS_TYPE`, `SERVICE_SCOPE`, `JOB_TYPE`, `OS`, `CLASSIFY_ID`, `DOCS_LINK`, `ATOM_TYPE`, `ATOM_STATUS`, `ATOM_STATUS_MSG`, `SUMMARY`, `DESCRIPTION`, `CATEGROY`, `VERSION`, `LOGO_URL`, `ICON`, `DEFAULT_FLAG`, `LATEST_FLAG`, `BUILD_LESS_RUN_FLAG`, `REPOSITORY_HASH_ID`, `CODE_SRC`, `PAY_FLAG`, `HTML_TEMPLATE_VERSION`, `PROPS`, `DATA`, `PUBLISHER`, `WEIGHT`, `CREATOR`, `MODIFIER`, `CREATE_TIME`, `UPDATE_TIME`, `VISIBILITY_LEVEL`) VALUES