From ca3702da56048027f429d531211f1aa099ff8e60 Mon Sep 17 00:00:00 2001 From: hejieehe <904696180@qq.com> Date: Thu, 21 Nov 2024 17:25:59 +0800 Subject: [PATCH 01/15] =?UTF-8?q?feat=EF=BC=9A=E5=AE=9A=E6=97=B6=E8=A7=A6?= =?UTF-8?q?=E5=8F=91=E5=99=A8=E6=94=AF=E6=8C=81=E8=AE=BE=E7=BD=AE=E5=90=AF?= =?UTF-8?q?=E5=8A=A8=E5=8F=98=E9=87=8F=20#10617?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../element/trigger/TimerTriggerElement.kt | 4 +- .../process/api/op/OpPipelineTimerResource.kt | 64 +++++++ .../process/engine/pojo/PipelineTimer.kt | 4 +- .../service/PipelineRepositoryService.kt | 11 ++ .../api/op/OpPipelineTimerResourceImpl.kt | 77 ++++++++ .../plugin/trigger/dao/PipelineTimerDao.kt | 81 ++++++++- .../element/TimerTriggerElementBizPlugin.kt | 113 ++---------- .../pojo/event/PipelineTimerBuildEvent.kt | 2 + .../pojo/event/PipelineTimerChangeEvent.kt | 1 + .../trigger/service/PipelineTimerService.kt | 59 +++++- .../PipelineTimerTriggerTaskService.kt | 171 ++++++++++++++++++ .../service/PipelineTimerUpgradeService.kt | 163 +++++++++++++++++ .../listener/PipelineTimerBuildListener.kt | 8 +- .../listener/PipelineTimerChangerListener.kt | 10 +- .../timer/quartz/PipelineQuartzService.kt | 19 +- 15 files changed, 668 insertions(+), 119 deletions(-) create mode 100644 src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/api/op/OpPipelineTimerResource.kt create mode 100644 src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/api/op/OpPipelineTimerResourceImpl.kt create mode 100644 src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/service/PipelineTimerTriggerTaskService.kt create mode 100644 src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/service/PipelineTimerUpgradeService.kt diff --git a/src/backend/ci/core/common/common-pipeline/src/main/kotlin/com/tencent/devops/common/pipeline/pojo/element/trigger/TimerTriggerElement.kt b/src/backend/ci/core/common/common-pipeline/src/main/kotlin/com/tencent/devops/common/pipeline/pojo/element/trigger/TimerTriggerElement.kt index 5fdfaff30e73..3905b24c715c 100644 --- a/src/backend/ci/core/common/common-pipeline/src/main/kotlin/com/tencent/devops/common/pipeline/pojo/element/trigger/TimerTriggerElement.kt +++ b/src/backend/ci/core/common/common-pipeline/src/main/kotlin/com/tencent/devops/common/pipeline/pojo/element/trigger/TimerTriggerElement.kt @@ -62,7 +62,9 @@ data class TimerTriggerElement( @get:Schema(title = "代码库HashId", required = false) val repoHashId: String? = null, @get:Schema(title = "指定代码库别名", required = false) - val repoName: String? = null + val repoName: String? = null, + @get:Schema(title = "定时启动参数", required = false) + val startParam: Map? = null ) : Element(name, id, status) { companion object { const val classType = "timerTrigger" diff --git a/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/api/op/OpPipelineTimerResource.kt b/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/api/op/OpPipelineTimerResource.kt new file mode 100644 index 000000000000..da2fb5525787 --- /dev/null +++ b/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/api/op/OpPipelineTimerResource.kt @@ -0,0 +1,64 @@ +/* + * 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.op + +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.pojo.Result +import io.swagger.v3.oas.annotations.tags.Tag +import io.swagger.v3.oas.annotations.Operation +import io.swagger.v3.oas.annotations.Parameter +import javax.ws.rs.Consumes +import javax.ws.rs.HeaderParam +import javax.ws.rs.POST +import javax.ws.rs.Path +import javax.ws.rs.Produces +import javax.ws.rs.QueryParam +import javax.ws.rs.core.MediaType + +@Tag(name = "OP_PIPELINE_AGENT_REF", description = "OP-流水线-更新流水线定时触发信息") +@Path("/op/pipeline/timer") +@Produces(MediaType.APPLICATION_JSON) +@Consumes(MediaType.APPLICATION_JSON) +interface OpPipelineTimerResource { + + @Operation(summary = "更新定时触发器信息") + @POST + @Path("/update") + fun updatePipelineTimerInfo( + @Parameter(description = "用户ID", required = true, example = AUTH_HEADER_USER_ID_DEFAULT_VALUE) + @HeaderParam(AUTH_HEADER_USER_ID) + userId: String, + @Parameter(description = "项目ID", required = false) + @QueryParam("projectId") + projectId: String?, + @Parameter(description = "流水线id", required = false) + @QueryParam("pipelineId") + pipelineId: String? + ): Result +} diff --git a/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/engine/pojo/PipelineTimer.kt b/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/engine/pojo/PipelineTimer.kt index 6bc77f0b1418..85c1b11b8f88 100644 --- a/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/engine/pojo/PipelineTimer.kt +++ b/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/engine/pojo/PipelineTimer.kt @@ -37,5 +37,7 @@ data class PipelineTimer( val channelCode: ChannelCode, val repoHashId: String?, val branchs: List?, - val noScm: Boolean? + val noScm: Boolean?, + val taskId: String, + val startParam: Map? ) diff --git a/src/backend/ci/core/process/biz-base/src/main/kotlin/com/tencent/devops/process/engine/service/PipelineRepositoryService.kt b/src/backend/ci/core/process/biz-base/src/main/kotlin/com/tencent/devops/process/engine/service/PipelineRepositoryService.kt index 6309eff2f9b1..1e4865382b85 100644 --- a/src/backend/ci/core/process/biz-base/src/main/kotlin/com/tencent/devops/process/engine/service/PipelineRepositoryService.kt +++ b/src/backend/ci/core/process/biz-base/src/main/kotlin/com/tencent/devops/process/engine/service/PipelineRepositoryService.kt @@ -1306,6 +1306,17 @@ class PipelineRepositoryService constructor( ).map { it.key to str2model(it.value, it.key) }.toMap() } + /** + * 批量获取model + */ + fun getModel(projectId: String, pipelineId: String): Model? { + return pipelineResourceDao.getLatestVersionModelString( + dslContext = dslContext, + projectId = projectId, + pipelineId = pipelineId + )?.let { str2model(it, pipelineId) } + } + /** * 获取编排版本的通用方法 * 1 如果指定了[version]则一定按照version号查询版本 diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/api/op/OpPipelineTimerResourceImpl.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/api/op/OpPipelineTimerResourceImpl.kt new file mode 100644 index 000000000000..ee86acf88bd4 --- /dev/null +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/api/op/OpPipelineTimerResourceImpl.kt @@ -0,0 +1,77 @@ +/* + * 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.op + +import com.tencent.devops.common.api.pojo.Result +import com.tencent.devops.common.web.RestResource +import com.tencent.devops.process.plugin.trigger.service.PipelineTimerUpgradeService +import org.slf4j.LoggerFactory +import org.springframework.beans.factory.annotation.Autowired +import java.util.concurrent.Executors +import java.util.concurrent.LinkedBlockingQueue +import java.util.concurrent.ThreadPoolExecutor +import java.util.concurrent.TimeUnit + +@RestResource +class OpPipelineTimerResourceImpl @Autowired constructor( + val timerUpgradeService: PipelineTimerUpgradeService +) : OpPipelineTimerResource { + override fun updatePipelineTimerInfo(userId: String, projectId: String?, pipelineId: String?): Result { + val startTime = System.currentTimeMillis() + val threadPoolExecutor = ThreadPoolExecutor( + 1, + 1, + 0, + TimeUnit.SECONDS, + LinkedBlockingQueue(1), + Executors.defaultThreadFactory(), + ThreadPoolExecutor.AbortPolicy() + ) + threadPoolExecutor.submit { + logger.info("Start to update pipeline timer|projectId=$projectId|pipelineId=$pipelineId") + try { + timerUpgradeService.upgrade( + userId = userId, + targetPipelineId = projectId, + targetProjectId = pipelineId + ) + } catch (ignored: Exception) { + logger.warn("Failed to update pipeline timer", ignored) + } finally { + logger.info("Finish to update pipeline timer|${System.currentTimeMillis() - startTime}") + threadPoolExecutor.shutdown() + } + } + return Result(true) + } + + + companion object { + private val logger = LoggerFactory.getLogger(OpPipelineTimerResourceImpl::class.java) + } +} diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/dao/PipelineTimerDao.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/dao/PipelineTimerDao.kt index e6b6b97ba3ff..cefeddd5124c 100644 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/dao/PipelineTimerDao.kt +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/dao/PipelineTimerDao.kt @@ -31,6 +31,7 @@ import com.tencent.devops.common.db.utils.skipCheck import com.tencent.devops.common.pipeline.enums.ChannelCode import com.tencent.devops.model.process.Tables.T_PIPELINE_TIMER import com.tencent.devops.model.process.tables.records.TPipelineTimerRecord +import org.jooq.Condition import org.jooq.DSLContext import org.jooq.Result import org.springframework.stereotype.Repository @@ -49,7 +50,8 @@ open class PipelineTimerDao { channelCode: ChannelCode, repoHashId: String?, branchs: String?, - noScm: Boolean? + noScm: Boolean?, + startParam: String? ): Int { return with(T_PIPELINE_TIMER) { dslContext.insertInto( @@ -62,7 +64,8 @@ open class PipelineTimerDao { CHANNEL, REPO_HASH_ID, BRANCHS, - NO_SCM + NO_SCM, + START_PARAM ).values( projectId, pipelineId, @@ -72,7 +75,8 @@ open class PipelineTimerDao { channelCode.name, repoHashId, branchs, - noScm + noScm, + startParam ) .onDuplicateKeyUpdate() .set(CREATE_TIME, LocalDateTime.now()) @@ -82,14 +86,15 @@ open class PipelineTimerDao { .set(REPO_HASH_ID, repoHashId) .set(BRANCHS, branchs) .set(NO_SCM, noScm) + .set(START_PARAM, startParam) .execute() } } - open fun get(dslContext: DSLContext, projectId: String, pipelineId: String): TPipelineTimerRecord? { + open fun get(dslContext: DSLContext, projectId: String, pipelineId: String, taskId: String): TPipelineTimerRecord? { return with(T_PIPELINE_TIMER) { dslContext.selectFrom(this) - .where(PIPELINE_ID.eq(pipelineId).and(PROJECT_ID.eq(projectId))) + .where(PIPELINE_ID.eq(pipelineId).and(PROJECT_ID.eq(projectId).and(TASK_ID.eq(taskId)))) .fetchAny() } } @@ -102,9 +107,75 @@ open class PipelineTimerDao { } } + open fun delete(dslContext: DSLContext, projectId: String, pipelineId: String, taskId: String): Int { + return with(T_PIPELINE_TIMER) { + dslContext.delete(this) + .where(PIPELINE_ID.eq(pipelineId).and(PROJECT_ID.eq(projectId).and(TASK_ID.eq(taskId)))) + .execute() + } + } + open fun list(dslContext: DSLContext, offset: Int, limit: Int): Result { return with(T_PIPELINE_TIMER) { dslContext.selectFrom(this).limit(offset, limit).skipCheck().fetch() } } + + fun list(dslContext: DSLContext, projectId: String, pipelineId: String): Result { + return with(T_PIPELINE_TIMER) { + dslContext.selectFrom(this).where( + PROJECT_ID.eq(projectId).and(PIPELINE_ID.eq(pipelineId)) + ).fetch() + } + } + + fun listPipeline( + dslContext: DSLContext, + projectId: String?, + pipelineId: String?, + offset: Int, + limit: Int + ): List> { + return with(T_PIPELINE_TIMER) { + val conditions = mutableListOf() + if (!projectId.isNullOrBlank()) { + conditions.add(PROJECT_ID.eq(projectId)) + } + if (!pipelineId.isNullOrBlank()) { + conditions.add(PIPELINE_ID.eq(pipelineId)) + } + dslContext.select(PROJECT_ID, PIPELINE_ID) + .from(this) + .where(conditions) + .groupBy(PROJECT_ID, PIPELINE_ID) + .orderBy(PROJECT_ID, PIPELINE_ID) + .limit(offset, limit) + .skipCheck() + .fetch() + .map { + it.value1() to it.value2() + } + } + } + + fun update( + dslContext: DSLContext, + projectId: String, + pipelineId: String, + taskId: String, + startParam: String? + ): Int { + return with(T_PIPELINE_TIMER) { + dslContext.update(this) + .set(TASK_ID, taskId) + .let { + if (!startParam.isNullOrBlank()) { + it.set(START_PARAM, startParam) + } + it + } + .where(PROJECT_ID.eq(projectId).and(PIPELINE_ID.eq(pipelineId))) + .execute() + } + } } diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/element/TimerTriggerElementBizPlugin.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/element/TimerTriggerElementBizPlugin.kt index c0562912a401..dfbf6a2969c3 100644 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/element/TimerTriggerElementBizPlugin.kt +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/element/TimerTriggerElementBizPlugin.kt @@ -27,12 +27,8 @@ package com.tencent.devops.process.plugin.trigger.element -import com.tencent.bkrepo.common.api.exception.NotFoundException -import com.tencent.devops.common.api.enums.RepositoryType import com.tencent.devops.common.api.enums.ScmType -import com.tencent.devops.common.api.enums.TriggerRepositoryType import com.tencent.devops.common.api.exception.ErrorCodeException -import com.tencent.devops.common.client.Client import com.tencent.devops.common.pipeline.container.Container import com.tencent.devops.common.pipeline.container.Stage import com.tencent.devops.common.pipeline.container.TriggerContainer @@ -40,24 +36,19 @@ 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.atom.ElementCheckResult import com.tencent.devops.common.pipeline.pojo.element.trigger.TimerTriggerElement -import com.tencent.devops.common.pipeline.utils.RepositoryConfigUtils import com.tencent.devops.process.constant.ProcessMessageCode import com.tencent.devops.process.constant.ProcessMessageCode.ERROR_TIMER_TRIGGER_SVN_BRANCH_NOT_EMPTY import com.tencent.devops.process.plugin.ElementBizPlugin import com.tencent.devops.process.plugin.annotation.ElementBiz import com.tencent.devops.process.plugin.trigger.service.PipelineTimerService -import com.tencent.devops.process.plugin.trigger.util.CronExpressionUtils +import com.tencent.devops.process.plugin.trigger.service.PipelineTimerTriggerTaskService import com.tencent.devops.process.pojo.pipeline.PipelineYamlVo -import com.tencent.devops.process.utils.PIPELINE_TIMER_DISABLE -import com.tencent.devops.repository.api.ServiceRepositoryResource -import com.tencent.devops.repository.pojo.Repository -import org.quartz.CronExpression import org.slf4j.LoggerFactory @ElementBiz class TimerTriggerElementBizPlugin constructor( private val pipelineTimerService: PipelineTimerService, - private val client: Client + private val timerTriggerTaskService: PipelineTimerTriggerTaskService ) : ElementBizPlugin { override fun elementClass(): Class { @@ -87,39 +78,18 @@ class TimerTriggerElementBizPlugin constructor( container: Container, yamlInfo: PipelineYamlVo? ) { - val crontabExpressions = mutableSetOf() val params = (container as TriggerContainer).params.associate { it.id to it.defaultValue.toString() } logger.info("[$pipelineId]|$userId| Timer trigger [${element.name}] enable=${element.elementEnabled()}") - /* - 在模板实例化时,有的流水线需要开启定时任务,有的流水线不需要开启,支持通过流水线变量控制定时任务的开启 - 通过参数禁用定时任务,在流水线参数上配置BK_CI_TIMER_DISABLE,禁用定时触发器插件 - */ - val isParamDisable = params[PIPELINE_TIMER_DISABLE]?.toBoolean() ?: false - if (element.elementEnabled() && !isParamDisable) { - - val eConvertExpressions = element.convertExpressions(params = params) - if (eConvertExpressions.isEmpty()) { - throw ErrorCodeException( - errorCode = ProcessMessageCode.ILLEGAL_TIMER_CRONTAB - ) - } - eConvertExpressions.forEach { cron -> - if (!CronExpression.isValidExpression(cron)) { - throw ErrorCodeException( - errorCode = ProcessMessageCode.ILLEGAL_TIMER_CRONTAB, - params = arrayOf(cron) - ) - } - if (!CronExpressionUtils.isValidTimeInterval(cron)) { - throw ErrorCodeException( - errorCode = ProcessMessageCode.ILLEGAL_TIMER_INTERVAL_CRONTAB, - params = arrayOf(cron) - ) - } - crontabExpressions.add(cron) - } - } - val repo = getRepo(projectId = projectId, element = element, params = params, yamlInfo = yamlInfo) + val crontabExpressions = timerTriggerTaskService.getCrontabExpressions( + params = params, + element = element + ) + val repo = timerTriggerTaskService.getRepo( + projectId = projectId, + element = element, + params = params, + yamlInfo = yamlInfo + ) // svn仓库分支必填 if (repo != null && repo.getScmType() == ScmType.CODE_SVN && element.branches.isNullOrEmpty()) { throw ErrorCodeException( @@ -135,7 +105,9 @@ class TimerTriggerElementBizPlugin constructor( channelCode = channelCode, repoHashId = repo?.repoHashId, branchs = element.branches?.toSet(), - noScm = element.noScm + noScm = element.noScm, + taskId = element.id ?: "", + startParam = element.startParam ) logger.info("[$pipelineId]|$userId| Update pipeline timer|crontab=$crontabExpressions") if (result.isNotOk()) { @@ -144,69 +116,18 @@ class TimerTriggerElementBizPlugin constructor( ) } } else { - pipelineTimerService.deleteTimer(projectId, pipelineId, userId) + pipelineTimerService.deleteTimer(projectId, pipelineId, userId, element.id ?: "") logger.info("[$pipelineId]|$userId| Delete pipeline timer") } } override fun beforeDelete(element: TimerTriggerElement, param: BeforeDeleteParam) { if (param.pipelineId.isNotBlank()) { - pipelineTimerService.deleteTimer(param.projectId, param.pipelineId, param.userId) + pipelineTimerService.deleteTimer(param.projectId, param.pipelineId, param.userId, element.id ?: "") pipelineTimerService.deleteTimerBranch(projectId = param.projectId, pipelineId = param.pipelineId) } } - private fun getRepo( - projectId: String, - element: TimerTriggerElement, - params: Map, - yamlInfo: PipelineYamlVo? - ): Repository? { - return when { - element.repositoryType == TriggerRepositoryType.SELF -> { - if (yamlInfo == null || yamlInfo.repoHashId.isBlank()) { - throw ErrorCodeException( - errorCode = ProcessMessageCode.ERROR_TIMER_TRIGGER_NEED_ENABLE_PAC - ) - } - try { - client.get(ServiceRepositoryResource::class).get( - projectId = projectId, - repositoryId = yamlInfo.repoHashId, - repositoryType = RepositoryType.ID - ).data - } catch (ignored: NotFoundException) { - throw ErrorCodeException( - errorCode = ProcessMessageCode.ERROR_TIMER_TRIGGER_REPO_NOT_FOUND - ) - } - } - - !element.repoHashId.isNullOrBlank() || !element.repoName.isNullOrBlank() -> { - val repositoryConfig = with(element) { - RepositoryConfigUtils.getRepositoryConfig( - repoHashId = repoHashId, - repoName = repoName, - repoType = TriggerRepositoryType.toRepositoryType(repositoryType), - variables = params - ) - } - try { - client.get(ServiceRepositoryResource::class).get( - projectId = projectId, - repositoryId = repositoryConfig.getURLEncodeRepositoryId(), - repositoryType = repositoryConfig.repositoryType - ).data - } catch (ignored: NotFoundException) { - throw ErrorCodeException( - errorCode = ProcessMessageCode.ERROR_TIMER_TRIGGER_REPO_NOT_FOUND - ) - } - } - else -> null - } - } - companion object { private val logger = LoggerFactory.getLogger(TimerTriggerElementBizPlugin::class.java) } diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/pojo/event/PipelineTimerBuildEvent.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/pojo/event/PipelineTimerBuildEvent.kt index bb070e320eb8..10f49cc227e8 100644 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/pojo/event/PipelineTimerBuildEvent.kt +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/pojo/event/PipelineTimerBuildEvent.kt @@ -45,6 +45,8 @@ data class PipelineTimerBuildEvent( override val pipelineId: String, override val userId: String, val channelCode: ChannelCode, + val taskId: String, + val startParam: Map?, override var actionType: ActionType = ActionType.START, override var delayMills: Int = 0 ) : IPipelineEvent(actionType, source, projectId, pipelineId, userId, delayMills) diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/pojo/event/PipelineTimerChangeEvent.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/pojo/event/PipelineTimerChangeEvent.kt index 71863f35e401..567d26f9ff88 100644 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/pojo/event/PipelineTimerChangeEvent.kt +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/pojo/event/PipelineTimerChangeEvent.kt @@ -44,6 +44,7 @@ data class PipelineTimerChangeEvent( override val pipelineId: String, override val userId: String, val crontabExpressionJson: String, + val taskId: String?, override var actionType: ActionType = ActionType.REFRESH, override var delayMills: Int = 0 ) : IPipelineEvent(actionType, source, projectId, pipelineId, userId, delayMills) diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/service/PipelineTimerService.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/service/PipelineTimerService.kt index 03bcc27be1ea..eef77db402b9 100644 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/service/PipelineTimerService.kt +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/service/PipelineTimerService.kt @@ -73,7 +73,9 @@ open class PipelineTimerService @Autowired constructor( channelCode: ChannelCode, repoHashId: String?, branchs: Set?, - noScm: Boolean? + taskId: String, + noScm: Boolean?, + startParam: Map? ): Result { val crontabJson = JsonUtil.toJson(crontabExpressions, formatted = false) return if (0 < pipelineTimerDao.save( @@ -85,7 +87,8 @@ open class PipelineTimerService @Autowired constructor( channelCode, repoHashId, branchs?.let { JsonUtil.toJson(it) }, - noScm + noScm, + startParam?.let { JsonUtil.toJson(it) } ) ) { pipelineEventDispatcher.dispatch( @@ -93,6 +96,7 @@ open class PipelineTimerService @Autowired constructor( source = "saveTimer", projectId = projectId, pipelineId = pipelineId, + taskId = taskId, userId = userId, crontabExpressionJson = crontabJson ) @@ -104,6 +108,7 @@ open class PipelineTimerService @Autowired constructor( source = "saveTimer_fail", projectId = projectId, pipelineId = pipelineId, + taskId = taskId, userId = userId, crontabExpressionJson = crontabJson, actionType = ActionType.TERMINATE @@ -119,17 +124,18 @@ open class PipelineTimerService @Autowired constructor( } } - open fun deleteTimer(projectId: String, pipelineId: String, userId: String): Result { + open fun deleteTimer(projectId: String, pipelineId: String, userId: String, taskId: String): Result { var count = 0 - val timerRecord = pipelineTimerDao.get(dslContext, projectId, pipelineId) + val timerRecord = pipelineTimerDao.get(dslContext, projectId, pipelineId, taskId) if (timerRecord != null) { - count = pipelineTimerDao.delete(dslContext, projectId, pipelineId) + count = pipelineTimerDao.delete(dslContext, projectId, pipelineId, taskId) // 终止定时器 pipelineEventDispatcher.dispatch( PipelineTimerChangeEvent( source = "deleteTimer", projectId = timerRecord.projectId, pipelineId = pipelineId, + taskId = taskId, userId = userId, crontabExpressionJson = timerRecord.crontab, actionType = ActionType.TERMINATE @@ -147,8 +153,8 @@ open class PipelineTimerService @Autowired constructor( ) } - open fun get(projectId: String, pipelineId: String): PipelineTimer? { - val timerRecord = pipelineTimerDao.get(dslContext, projectId, pipelineId) ?: return null + open fun get(projectId: String, pipelineId: String, taskId: String): PipelineTimer? { + val timerRecord = pipelineTimerDao.get(dslContext, projectId, pipelineId, taskId) ?: return null return convert(timerRecord) } @@ -173,7 +179,9 @@ open class PipelineTimerService @Autowired constructor( branchs = branchs?.let { JsonUtil.to(it, object : TypeReference>() {}) }, - noScm = noScm + noScm = noScm, + taskId = taskId, + startParam = startParam?.let { JsonUtil.to(it, object : TypeReference>() {}) } ) } } @@ -232,4 +240,39 @@ open class PipelineTimerService @Autowired constructor( pipelineId = pipelineId ) } + + fun listTimer(projectId: String, pipelineId: String): List { + return pipelineTimerDao.list( + dslContext = dslContext, + projectId = projectId, + pipelineId = pipelineId + ) + } + + fun listPipeline(projectId: String?, pipelineId: String?, limit: Int, offset: Int): List> { + return pipelineTimerDao.listPipeline( + dslContext = dslContext, + projectId = projectId, + pipelineId = pipelineId, + limit = limit, + offset = offset + ) + } + + fun updateTimer( + projectId: String, + pipelineId: String, + taskId: String, + startParam: Map? + ): Int { + return pipelineTimerDao.update( + dslContext = dslContext, + projectId = projectId, + pipelineId = pipelineId, + taskId = taskId, + startParam = startParam?.let { + JsonUtil.toJson(it, false) + } + ) + } } diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/service/PipelineTimerTriggerTaskService.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/service/PipelineTimerTriggerTaskService.kt new file mode 100644 index 000000000000..37d8bc3f5a5d --- /dev/null +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/service/PipelineTimerTriggerTaskService.kt @@ -0,0 +1,171 @@ +/* + * 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.plugin.trigger.service + +import com.tencent.bkrepo.common.api.exception.NotFoundException +import com.tencent.devops.common.api.enums.RepositoryType +import com.tencent.devops.common.api.enums.TriggerRepositoryType +import com.tencent.devops.common.api.exception.ErrorCodeException +import com.tencent.devops.common.client.Client +import com.tencent.devops.common.pipeline.Model +import com.tencent.devops.common.pipeline.pojo.element.trigger.TimerTriggerElement +import com.tencent.devops.common.pipeline.utils.RepositoryConfigUtils +import com.tencent.devops.process.constant.ProcessMessageCode +import com.tencent.devops.process.plugin.trigger.util.CronExpressionUtils +import com.tencent.devops.process.pojo.pipeline.PipelineYamlVo +import com.tencent.devops.process.utils.PIPELINE_TIMER_DISABLE +import com.tencent.devops.process.yaml.PipelineYamlFacadeService +import com.tencent.devops.repository.api.ServiceRepositoryResource +import com.tencent.devops.repository.pojo.Repository +import org.quartz.CronExpression +import org.slf4j.LoggerFactory +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.stereotype.Service + +/** + * 流水线定时服务 + * @version 1.0 + */ +@Service +open class PipelineTimerTriggerTaskService @Autowired constructor( + private val client: Client, + private val pipelineYamlFacadeService: PipelineYamlFacadeService +) { + fun getParams(model: Model) = model.getTriggerContainer() + .params.associate { it.id to it.defaultValue.toString() } + + fun getCrontabExpressions(params: Map, element: TimerTriggerElement): Set { + val crontabExpressions = mutableSetOf() + /* + 在模板实例化时,有的流水线需要开启定时任务,有的流水线不需要开启,支持通过流水线变量控制定时任务的开启 + 通过参数禁用定时任务,在流水线参数上配置BK_CI_TIMER_DISABLE,禁用定时触发器插件 + */ + val isParamDisable = params[PIPELINE_TIMER_DISABLE]?.toBoolean() ?: false + if (element.elementEnabled() && !isParamDisable) { + + val eConvertExpressions = element.convertExpressions(params = params) + if (eConvertExpressions.isEmpty()) { + throw ErrorCodeException( + errorCode = ProcessMessageCode.ILLEGAL_TIMER_CRONTAB + ) + } + eConvertExpressions.forEach { cron -> + if (!CronExpression.isValidExpression(cron)) { + throw ErrorCodeException( + errorCode = ProcessMessageCode.ILLEGAL_TIMER_CRONTAB, + params = arrayOf(cron) + ) + } + if (!CronExpressionUtils.isValidTimeInterval(cron)) { + throw ErrorCodeException( + errorCode = ProcessMessageCode.ILLEGAL_TIMER_INTERVAL_CRONTAB, + params = arrayOf(cron) + ) + } + crontabExpressions.add(cron) + } + } + return crontabExpressions + } + + fun getRepo( + projectId: String, + element: TimerTriggerElement, + params: Map, + yamlInfo: PipelineYamlVo? + ): Repository? { + return when { + element.repositoryType == TriggerRepositoryType.SELF -> { + if (yamlInfo == null || yamlInfo.repoHashId.isBlank()) { + throw ErrorCodeException( + errorCode = ProcessMessageCode.ERROR_TIMER_TRIGGER_NEED_ENABLE_PAC + ) + } + try { + client.get(ServiceRepositoryResource::class).get( + projectId = projectId, + repositoryId = yamlInfo.repoHashId, + repositoryType = RepositoryType.ID + ).data + } catch (ignored: NotFoundException) { + throw ErrorCodeException( + errorCode = ProcessMessageCode.ERROR_TIMER_TRIGGER_REPO_NOT_FOUND + ) + } + } + + !element.repoHashId.isNullOrBlank() || !element.repoName.isNullOrBlank() -> { + val repositoryConfig = with(element) { + RepositoryConfigUtils.getRepositoryConfig( + repoHashId = repoHashId, + repoName = repoName, + repoType = TriggerRepositoryType.toRepositoryType(repositoryType), + variables = params + ) + } + try { + client.get(ServiceRepositoryResource::class).get( + projectId = projectId, + repositoryId = repositoryConfig.getURLEncodeRepositoryId(), + repositoryType = repositoryConfig.repositoryType + ).data + } catch (ignored: NotFoundException) { + throw ErrorCodeException( + errorCode = ProcessMessageCode.ERROR_TIMER_TRIGGER_REPO_NOT_FOUND + ) + } + } + + else -> null + } + } + + fun getRepo( + projectId: String, + pipelineId: String, + element: TimerTriggerElement, + params: Map, + latestVersion: Int + ): Repository? { + val pipelineYamlVo = pipelineYamlFacadeService.getPipelineYamlInfo( + projectId = projectId, + pipelineId = pipelineId, + version = latestVersion + ) + return getRepo( + projectId = projectId, + element = element, + params = params, + yamlInfo = pipelineYamlVo + ) + } + + companion object { + private val logger = LoggerFactory.getLogger(PipelineTimerTriggerTaskService::class.java) + } +} diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/service/PipelineTimerUpgradeService.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/service/PipelineTimerUpgradeService.kt new file mode 100644 index 000000000000..8b21d13113a7 --- /dev/null +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/service/PipelineTimerUpgradeService.kt @@ -0,0 +1,163 @@ +/* + * 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.plugin.trigger.service + +import com.tencent.devops.common.pipeline.Model +import com.tencent.devops.common.pipeline.pojo.element.trigger.TimerTriggerElement +import com.tencent.devops.process.engine.pojo.PipelineInfo +import com.tencent.devops.process.engine.service.PipelineRepositoryService +import org.slf4j.LoggerFactory +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.stereotype.Service + +/** + * 流水线定时服务 + * @version 1.0 + */ +@Service +open class PipelineTimerUpgradeService @Autowired constructor( + val pipelineRepositoryService: PipelineRepositoryService, + val pipelineTimerService: PipelineTimerService, + val timerTriggerTaskService: PipelineTimerTriggerTaskService +) { + fun upgrade(userId: String, targetProjectId: String?, targetPipelineId: String?) { + logger.info("upgrade pipeline timer") + var offset = 0 + val limit = 100 + do { + val records = pipelineTimerService.listPipeline( + projectId = targetProjectId, + pipelineId = targetPipelineId, + offset = offset, + limit = limit + ) + records.forEach parseModel@{ (projectId, pipelineId) -> + val timerList = pipelineTimerService.listTimer(projectId, pipelineId) + val model = pipelineRepositoryService.getModel( + projectId = projectId, + pipelineId = pipelineId + ) + if (model == null) { + logger.warn("model is null|projectId=$projectId|pipelineId=$pipelineId") + return@parseModel + } + val pipelineInfo = pipelineRepositoryService.getPipelineInfo(projectId, pipelineId) + if (pipelineInfo == null) { + logger.warn("pipeline info is null|projectId=$projectId|pipelineId=$pipelineId") + return@parseModel + } + // 没有禁用的触发器 + val timerTriggerElements = getTimerTriggerConfig(model) + when { + // 功能发布后,添加了多个定时触发器 + timerList.size > 1 -> { + val containsEmptyTaskId = timerList.any { it.taskId.isNullOrBlank() } + // 存在空的taskId,则删掉重新添加定时任务 + if (containsEmptyTaskId) { + logger.info("contains empty taskId, save again|$projectId|$pipelineId") + timerList.forEach { + val result = pipelineTimerService.deleteTimer( + projectId = projectId, + pipelineId = pipelineId, + taskId = it.taskId, + userId = userId + ) + if (result.data != true) { + logger.error( + "delete timer fail|projectId=$projectId|" + + "pipelineId=$pipelineId|taskId=${it.taskId}" + ) + } + } + } + // 重新添加定时任务 + saveTimer(timerTriggerElements, model, projectId, pipelineId, pipelineInfo) + } + + // 正常情况 + timerList.size == 1 -> { + // 重新添加定时任务 + saveTimer(timerTriggerElements, model, projectId, pipelineId, pipelineInfo) + } + + else -> { + return@parseModel + } + } + } + val count = records.size + offset += limit + } while (count == 1000) + } + + private fun saveTimer( + timerTriggerElements: List, + model: Model, + projectId: String, + pipelineId: String, + pipelineInfo: PipelineInfo + ) { + timerTriggerElements.forEach { element -> + val params = timerTriggerTaskService.getParams(model) + val crontabExpressions = timerTriggerTaskService.getCrontabExpressions( + params = params, + element = element + ) + val repo = timerTriggerTaskService.getRepo( + projectId = projectId, + pipelineId = pipelineId, + element = element, + params = params, + latestVersion = model.latestVersion + ) + pipelineTimerService.saveTimer( + projectId = projectId, + pipelineId = pipelineId, + userId = pipelineInfo.lastModifyUser, + crontabExpressions = crontabExpressions, + channelCode = pipelineInfo.channelCode, + repoHashId = repo?.repoHashId, + branchs = element.branches?.toSet(), + noScm = element.noScm, + taskId = element.id ?: "", + startParam = element.startParam + ) + } + } + + /** + * 获取取定时触发器 + */ + fun getTimerTriggerConfig(model: Model) = model.getTriggerContainer() + .elements.filter { it is TimerTriggerElement && it.elementEnabled() }.map { it as TimerTriggerElement } + + + companion object { + private val logger = LoggerFactory.getLogger(PipelineTimerUpgradeService::class.java) + } +} diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/timer/listener/PipelineTimerBuildListener.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/timer/listener/PipelineTimerBuildListener.kt index 2b7261a2c2e0..bdc9dcb34801 100644 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/timer/listener/PipelineTimerBuildListener.kt +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/timer/listener/PipelineTimerBuildListener.kt @@ -79,7 +79,11 @@ class PipelineTimerBuildListener @Autowired constructor( override fun run(event: PipelineTimerBuildEvent) { val pipelineTimer = - pipelineTimerService.get(projectId = event.projectId, pipelineId = event.pipelineId) ?: return + pipelineTimerService.get( + projectId = event.projectId, + pipelineId = event.pipelineId, + taskId = event.taskId + ) ?: return with(pipelineTimer) { when { repoHashId.isNullOrBlank() -> @@ -107,7 +111,7 @@ class PipelineTimerBuildListener @Autowired constructor( // 如果是不存在的流水线,则直接删除定时任务,相当于给异常创建失败的定时流水线做清理 if (buildResult.data.isNullOrBlank()) { - pipelineTimerService.deleteTimer(projectId, pipelineId, userId) + pipelineTimerService.deleteTimer(projectId, pipelineId, userId, event.taskId) logger.warn("[$pipelineId]|pipeline not exist!${buildResult.message}") } else { logger.info("[$pipelineId]|TimerTrigger start| buildId=${buildResult.data}") diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/timer/listener/PipelineTimerChangerListener.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/timer/listener/PipelineTimerChangerListener.kt index c971011df832..1a391bd12c6d 100644 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/timer/listener/PipelineTimerChangerListener.kt +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/timer/listener/PipelineTimerChangerListener.kt @@ -64,12 +64,20 @@ class PipelineTimerChangerListener @Autowired constructor( try { crontabExpressions.forEach { crontab -> val md5 = DigestUtils.md5Hex(crontab) + listOf(pipelineId, md5, event.projectId, event.taskId) + // 旧的定时任务Key,功能发布后残留的job val comboKey = "${pipelineId}_${md5}_${event.projectId}" if (schedulerManager.checkExists(comboKey)) { + logger.info("clear residual scheduled tasks|jobKey=[$comboKey]") schedulerManager.deleteJob(comboKey) } + // 新的定时任务Key + val taskComboKey = "${pipelineId}_${md5}_${event.projectId}_${event.taskId}" + if (schedulerManager.checkExists(taskComboKey)) { + schedulerManager.deleteJob(taskComboKey) + } if (ActionType.REFRESH == (event.actionType)) { - val success = schedulerManager.addJob(comboKey, crontab, jobBeanClass) + val success = schedulerManager.addJob(taskComboKey, crontab, jobBeanClass) logger.info("[$pipelineId]|TimerChange|crontab=$crontab|success=$success") } } diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/timer/quartz/PipelineQuartzService.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/timer/quartz/PipelineQuartzService.kt index 5b60edf35e27..8a2b18547532 100644 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/timer/quartz/PipelineQuartzService.kt +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/timer/quartz/PipelineQuartzService.kt @@ -93,7 +93,11 @@ class PipelineQuartzService @Autowired constructor( list.forEach { timer -> logger.info("TIMER_RELOAD| load crontab($timer)") timer.crontabExpressions.forEach { crontab -> - addJob(projectId = timer.projectId, pipelineId = timer.pipelineId, crontab = crontab) + addJob(projectId = timer.projectId, + pipelineId = timer.pipelineId, + crontab = crontab, + taskId = timer.taskId + ) } } start += limit @@ -102,10 +106,10 @@ class PipelineQuartzService @Autowired constructor( logger.warn("TIMER_RELOAD| reload ok!") } - fun addJob(projectId: String, pipelineId: String, crontab: String) { + fun addJob(projectId: String, pipelineId: String, crontab: String, taskId: String) { try { val md5 = DigestUtils.md5Hex(crontab) - val comboKey = "${pipelineId}_${md5}_$projectId" + val comboKey = "${pipelineId}_${md5}_${projectId}_$taskId" schedulerManager.addJob( comboKey, crontab, jobBeanClass @@ -148,10 +152,12 @@ class PipelineJobBean( fun execute(context: JobExecutionContext?) { val jobKey = context?.jobDetail?.key ?: return val comboKey = jobKey.name + // 格式:pipelineId_{md5}_{projectId}_{taskId} val comboKeys = comboKey.split(Regex("_"), 3) val pipelineId = comboKeys[0] val crontabMd5 = comboKeys[1] val projectId = comboKeys[2] + val taskId = comboKeys.getOrElse(3) { "" } val watcher = Watcher(id = "timer|[$comboKey]") try { if (redisOperation.isMember(BkApiUtil.getApiAccessLimitPipelinesKey(), pipelineId)) { @@ -162,7 +168,7 @@ class PipelineJobBean( logger.warn("Project[$projectId] has restricted build permissions,please try again later!") return } - val pipelineTimer = pipelineTimerService.get(projectId, pipelineId) + val pipelineTimer = pipelineTimerService.get(projectId, pipelineId, taskId) if (null == pipelineTimer) { logger.info("[$comboKey]|PIPELINE_TIMER_EXPIRED|Timer is expire, delete it from queue!") schedulerManager.deleteJob(comboKey) @@ -197,6 +203,7 @@ class PipelineJobBean( try { logger.info("[$projectId]|$pipelineId|PIPELINE_TIMER|scheduledFireTime=$scheduledFireTime") watcher.start("dispatch") + // TODO: 补充启动参数 pipelineEventDispatcher.dispatch( PipelineTimerBuildEvent( source = "timer_trigger", @@ -206,7 +213,9 @@ class PipelineJobBean( projectId = projectId, pipelineId = pipelineId ) ?: pipelineTimer.startUser, - channelCode = pipelineTimer.channelCode + channelCode = pipelineTimer.channelCode, + taskId = taskId, + startParam = pipelineTimer.startParam ) ) } catch (ignored: Exception) { From d2f86c825d3e90ffe41b8559e888d0b0a415fec4 Mon Sep 17 00:00:00 2001 From: hejieehe <904696180@qq.com> Date: Fri, 29 Nov 2024 10:52:42 +0800 Subject: [PATCH 02/15] =?UTF-8?q?feat=EF=BC=9A=E5=AE=9A=E6=97=B6=E8=A7=A6?= =?UTF-8?q?=E5=8F=91=E5=99=A8=E6=94=AF=E6=8C=81=E8=AE=BE=E7=BD=AE=E5=90=AF?= =?UTF-8?q?=E5=8A=A8=E5=8F=98=E9=87=8F=20#10617?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../process/plugin/trigger/dao/PipelineTimerDao.kt | 10 +++++++--- .../plugin/trigger/service/PipelineTimerService.kt | 3 ++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/dao/PipelineTimerDao.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/dao/PipelineTimerDao.kt index cefeddd5124c..a4da6a3ef8af 100644 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/dao/PipelineTimerDao.kt +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/dao/PipelineTimerDao.kt @@ -51,7 +51,8 @@ open class PipelineTimerDao { repoHashId: String?, branchs: String?, noScm: Boolean?, - startParam: String? + startParam: String?, + taskId: String ): Int { return with(T_PIPELINE_TIMER) { dslContext.insertInto( @@ -65,7 +66,8 @@ open class PipelineTimerDao { REPO_HASH_ID, BRANCHS, NO_SCM, - START_PARAM + START_PARAM, + TASK_ID ).values( projectId, pipelineId, @@ -76,9 +78,11 @@ open class PipelineTimerDao { repoHashId, branchs, noScm, - startParam + startParam, + taskId ) .onDuplicateKeyUpdate() + .set(TASK_ID, taskId) .set(CREATE_TIME, LocalDateTime.now()) .set(CREATOR, userId) .set(CRONTAB, crontabExpression) diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/service/PipelineTimerService.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/service/PipelineTimerService.kt index eef77db402b9..647077b64209 100644 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/service/PipelineTimerService.kt +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/service/PipelineTimerService.kt @@ -88,7 +88,8 @@ open class PipelineTimerService @Autowired constructor( repoHashId, branchs?.let { JsonUtil.toJson(it) }, noScm, - startParam?.let { JsonUtil.toJson(it) } + startParam?.let { JsonUtil.toJson(it) }, + taskId ) ) { pipelineEventDispatcher.dispatch( From f75da4a38a499a310fc10e9643c87d021e13de0f Mon Sep 17 00:00:00 2001 From: hejieehe <904696180@qq.com> Date: Fri, 29 Nov 2024 11:33:36 +0800 Subject: [PATCH 03/15] =?UTF-8?q?feat=EF=BC=9A=E5=AE=9A=E6=97=B6=E8=A7=A6?= =?UTF-8?q?=E5=8F=91=E5=99=A8=E6=94=AF=E6=8C=81=E8=AE=BE=E7=BD=AE=E5=90=AF?= =?UTF-8?q?=E5=8A=A8=E5=8F=98=E9=87=8F=20#10617?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../devops/process/api/op/OpPipelineTimerResourceImpl.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/api/op/OpPipelineTimerResourceImpl.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/api/op/OpPipelineTimerResourceImpl.kt index ee86acf88bd4..7c50fd3fa307 100644 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/api/op/OpPipelineTimerResourceImpl.kt +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/api/op/OpPipelineTimerResourceImpl.kt @@ -57,8 +57,8 @@ class OpPipelineTimerResourceImpl @Autowired constructor( try { timerUpgradeService.upgrade( userId = userId, - targetPipelineId = projectId, - targetProjectId = pipelineId + targetPipelineId = pipelineId, + targetProjectId = projectId ) } catch (ignored: Exception) { logger.warn("Failed to update pipeline timer", ignored) From 937bd1203aad6076008782f619984a3c3d2f74df Mon Sep 17 00:00:00 2001 From: hejieehe <904696180@qq.com> Date: Mon, 2 Dec 2024 14:23:00 +0800 Subject: [PATCH 04/15] =?UTF-8?q?feat=EF=BC=9A=E5=AE=9A=E6=97=B6=E8=A7=A6?= =?UTF-8?q?=E5=8F=91=E5=99=A8=E6=94=AF=E6=8C=81=E8=AE=BE=E7=BD=AE=E5=90=AF?= =?UTF-8?q?=E5=8A=A8=E5=8F=98=E9=87=8F=20#10617?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../trigger/service/PipelineTimerService.kt | 40 +++++++++++---- .../service/PipelineTimerUpgradeService.kt | 50 ++++++++++++++++--- .../listener/PipelineTimerChangerListener.kt | 1 - .../timer/quartz/PipelineQuartzService.kt | 9 +++- 4 files changed, 78 insertions(+), 22 deletions(-) diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/service/PipelineTimerService.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/service/PipelineTimerService.kt index 647077b64209..705646f423b4 100644 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/service/PipelineTimerService.kt +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/service/PipelineTimerService.kt @@ -260,20 +260,38 @@ open class PipelineTimerService @Autowired constructor( ) } + /** + * 修改定时任务record,并更新quartz定时任务 + */ fun updateTimer( projectId: String, pipelineId: String, taskId: String, - startParam: Map? - ): Int { - return pipelineTimerDao.update( - dslContext = dslContext, - projectId = projectId, - pipelineId = pipelineId, - taskId = taskId, - startParam = startParam?.let { - JsonUtil.toJson(it, false) - } - ) + userId: String, + startParam: Map?, + crontabExpressionJson: String + ): Result { + return if (pipelineTimerDao.update( + dslContext = dslContext, + projectId = projectId, + pipelineId = pipelineId, + taskId = taskId, + startParam = startParam?.let { + JsonUtil.toJson(it, false) + } + ) > 0 + ) { + pipelineEventDispatcher.dispatch( + PipelineTimerChangeEvent( + source = "saveTimer", + projectId = projectId, + pipelineId = pipelineId, + taskId = taskId, + userId = userId, + crontabExpressionJson = crontabExpressionJson + ) + ) + return Result(true) + } else Result(false) } } diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/service/PipelineTimerUpgradeService.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/service/PipelineTimerUpgradeService.kt index 8b21d13113a7..6b093b237446 100644 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/service/PipelineTimerUpgradeService.kt +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/service/PipelineTimerUpgradeService.kt @@ -27,6 +27,7 @@ package com.tencent.devops.process.plugin.trigger.service +import com.tencent.devops.common.api.util.JsonUtil import com.tencent.devops.common.pipeline.Model import com.tencent.devops.common.pipeline.pojo.element.trigger.TimerTriggerElement import com.tencent.devops.process.engine.pojo.PipelineInfo @@ -71,8 +72,11 @@ open class PipelineTimerUpgradeService @Autowired constructor( logger.warn("pipeline info is null|projectId=$projectId|pipelineId=$pipelineId") return@parseModel } + // 默认参数 + val params = timerTriggerTaskService.getParams(model) // 没有禁用的触发器 val timerTriggerElements = getTimerTriggerConfig(model) + val lastModifyUser = pipelineInfo.lastModifyUser when { // 功能发布后,添加了多个定时触发器 timerList.size > 1 -> { @@ -85,7 +89,7 @@ open class PipelineTimerUpgradeService @Autowired constructor( projectId = projectId, pipelineId = pipelineId, taskId = it.taskId, - userId = userId + userId = lastModifyUser ) if (result.data != true) { logger.error( @@ -96,16 +100,46 @@ open class PipelineTimerUpgradeService @Autowired constructor( } } // 重新添加定时任务 - saveTimer(timerTriggerElements, model, projectId, pipelineId, pipelineInfo) + saveTimer( + timerTriggerElements= timerTriggerElements, + params = params, + latestVersion = model.latestVersion, + projectId = projectId, + pipelineId = pipelineId, + pipelineInfo = pipelineInfo + ) } // 正常情况 - timerList.size == 1 -> { - // 重新添加定时任务 - saveTimer(timerTriggerElements, model, projectId, pipelineId, pipelineInfo) + timerList.size == 1 && timerTriggerElements.size == 1 -> { + val timerRecord = timerList[0] + val timerTriggerElement = timerTriggerElements[0] + val crontab = JsonUtil.toJson( + timerTriggerTaskService.getCrontabExpressions( + params = params, + element = timerTriggerElement + ), + false + ) + // 填充taskId 和 startParam + if (timerRecord.taskId.isNullOrBlank() && timerRecord.crontab == crontab) { + // 更新定时任务 + pipelineTimerService.updateTimer( + projectId = projectId, + pipelineId = pipelineId, + taskId = timerTriggerElement.id ?: "", + userId = lastModifyUser, + startParam = timerTriggerElement.startParam, + crontabExpressionJson = crontab + ) + } } else -> { + logger.warn( + "skip upgrade|projectId=$projectId|pipelineId=$pipelineId|" + + "timerCount[${timerList.size}]|timerTriggerCount[${timerTriggerElements.size}]" + ) return@parseModel } } @@ -117,13 +151,13 @@ open class PipelineTimerUpgradeService @Autowired constructor( private fun saveTimer( timerTriggerElements: List, - model: Model, + params: Map, + latestVersion: Int, projectId: String, pipelineId: String, pipelineInfo: PipelineInfo ) { timerTriggerElements.forEach { element -> - val params = timerTriggerTaskService.getParams(model) val crontabExpressions = timerTriggerTaskService.getCrontabExpressions( params = params, element = element @@ -133,7 +167,7 @@ open class PipelineTimerUpgradeService @Autowired constructor( pipelineId = pipelineId, element = element, params = params, - latestVersion = model.latestVersion + latestVersion = latestVersion ) pipelineTimerService.saveTimer( projectId = projectId, diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/timer/listener/PipelineTimerChangerListener.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/timer/listener/PipelineTimerChangerListener.kt index 1a391bd12c6d..8267ee415c57 100644 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/timer/listener/PipelineTimerChangerListener.kt +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/timer/listener/PipelineTimerChangerListener.kt @@ -64,7 +64,6 @@ class PipelineTimerChangerListener @Autowired constructor( try { crontabExpressions.forEach { crontab -> val md5 = DigestUtils.md5Hex(crontab) - listOf(pipelineId, md5, event.projectId, event.taskId) // 旧的定时任务Key,功能发布后残留的job val comboKey = "${pipelineId}_${md5}_${event.projectId}" if (schedulerManager.checkExists(comboKey)) { diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/timer/quartz/PipelineQuartzService.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/timer/quartz/PipelineQuartzService.kt index 8a2b18547532..e5aac72c06cc 100644 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/timer/quartz/PipelineQuartzService.kt +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/timer/quartz/PipelineQuartzService.kt @@ -109,9 +109,14 @@ class PipelineQuartzService @Autowired constructor( fun addJob(projectId: String, pipelineId: String, crontab: String, taskId: String) { try { val md5 = DigestUtils.md5Hex(crontab) - val comboKey = "${pipelineId}_${md5}_${projectId}_$taskId" + val comboKey = "${pipelineId}_${md5}_${projectId}" + val taskComboKey = "${pipelineId}_${md5}_${projectId}_$taskId" + // 移除旧的定时任务key + if (schedulerManager.checkExists(comboKey)) { + schedulerManager.deleteJob(comboKey) + } schedulerManager.addJob( - comboKey, crontab, + taskComboKey, crontab, jobBeanClass ) } catch (ignore: Exception) { From 95780da5b1231fa3ba58e128127d4c6f72437e95 Mon Sep 17 00:00:00 2001 From: hejieehe <904696180@qq.com> Date: Mon, 2 Dec 2024 16:38:13 +0800 Subject: [PATCH 05/15] =?UTF-8?q?feat=EF=BC=9A=E5=AE=9A=E6=97=B6=E8=A7=A6?= =?UTF-8?q?=E5=8F=91=E5=99=A8=E6=94=AF=E6=8C=81=E8=AE=BE=E7=BD=AE=E5=90=AF?= =?UTF-8?q?=E5=8A=A8=E5=8F=98=E9=87=8F=20#10617?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plugin/trigger/timer/quartz/PipelineQuartzService.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/timer/quartz/PipelineQuartzService.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/timer/quartz/PipelineQuartzService.kt index e5aac72c06cc..a41722fc3bb4 100644 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/timer/quartz/PipelineQuartzService.kt +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/timer/quartz/PipelineQuartzService.kt @@ -158,7 +158,7 @@ class PipelineJobBean( val jobKey = context?.jobDetail?.key ?: return val comboKey = jobKey.name // 格式:pipelineId_{md5}_{projectId}_{taskId} - val comboKeys = comboKey.split(Regex("_"), 3) + val comboKeys = comboKey.split(Regex("_"), 4) val pipelineId = comboKeys[0] val crontabMd5 = comboKeys[1] val projectId = comboKeys[2] From 08dedf70130e4d2ff3c7f9b73461ff8e440b9d5f Mon Sep 17 00:00:00 2001 From: hejieehe <904696180@qq.com> Date: Mon, 2 Dec 2024 17:18:37 +0800 Subject: [PATCH 06/15] =?UTF-8?q?feat=EF=BC=9A=E5=AE=9A=E6=97=B6=E8=A7=A6?= =?UTF-8?q?=E5=8F=91=E5=99=A8=E6=94=AF=E6=8C=81=E8=AE=BE=E7=BD=AE=E5=90=AF?= =?UTF-8?q?=E5=8A=A8=E5=8F=98=E9=87=8F=20#10617?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../listener/PipelineTimerBuildListener.kt | 31 +++++++++++++------ .../timer/quartz/PipelineQuartzService.kt | 9 ++++-- 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/timer/listener/PipelineTimerBuildListener.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/timer/listener/PipelineTimerBuildListener.kt index bdc9dcb34801..201647ab69f4 100644 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/timer/listener/PipelineTimerBuildListener.kt +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/timer/listener/PipelineTimerBuildListener.kt @@ -87,7 +87,7 @@ class PipelineTimerBuildListener @Autowired constructor( with(pipelineTimer) { when { repoHashId.isNullOrBlank() -> - timerTrigger(event = event) + timerTrigger(event = event, params = event.startParam ?: mapOf()) else -> repoTimerTrigger( @@ -151,22 +151,31 @@ class PipelineTimerBuildListener @Autowired constructor( messages.add(I18nUtil.getCodeLanMessage(ERROR_PIPELINE_TIMER_BRANCH_IS_EMPTY)) return } + // 填充触发器启动参数 + val startParams = mutableMapOf() + event.startParam?.let { + startParams.putAll(it) + } finalBranchs.forEach { branch -> if (noScm == true) { branchTimerTrigger( event = event, repoHashId = repoHashId!!, branch = branch, - branchMessages = branchMessages + branchMessages = branchMessages, + startParams = startParams ) } else { - timerTrigger( - event = event, - params = mapOf( + startParams.putAll( + mapOf( BK_REPO_WEBHOOK_HASH_ID to repoHashId!!, PIPELINE_WEBHOOK_BRANCH to branch ) ) + timerTrigger( + event = event, + params = startParams + ) } } } catch (ignored: Exception) { @@ -196,7 +205,8 @@ class PipelineTimerBuildListener @Autowired constructor( event: PipelineTimerBuildEvent, repoHashId: String, branch: String, - branchMessages: MutableMap> + branchMessages: MutableMap>, + startParams: MutableMap ) { val repositoryConfig = RepositoryConfig( repositoryHashId = repoHashId, @@ -225,12 +235,15 @@ class PipelineTimerBuildListener @Autowired constructor( branch = branch ) if (timerBranch == null || timerBranch.revision != revision) { - val buildId = timerTrigger( - event = event, - params = mapOf( + startParams.putAll( + mapOf( BK_REPO_WEBHOOK_HASH_ID to repoHashId, PIPELINE_WEBHOOK_BRANCH to branch ) + ) + val buildId = timerTrigger( + event = event, + params = startParams ) ?: return logger.info("success to build by time trigger|$projectId|$pipelineId|$repoHashId|$branch|$buildId") pipelineTimerService.saveTimerBranch( diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/timer/quartz/PipelineQuartzService.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/timer/quartz/PipelineQuartzService.kt index a41722fc3bb4..1c87177eff4b 100644 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/timer/quartz/PipelineQuartzService.kt +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/timer/quartz/PipelineQuartzService.kt @@ -109,14 +109,17 @@ class PipelineQuartzService @Autowired constructor( fun addJob(projectId: String, pipelineId: String, crontab: String, taskId: String) { try { val md5 = DigestUtils.md5Hex(crontab) - val comboKey = "${pipelineId}_${md5}_${projectId}" - val taskComboKey = "${pipelineId}_${md5}_${projectId}_$taskId" + val comboKey = if (taskId.isEmpty()) { + "${pipelineId}_${md5}_${projectId}" + } else { + "${pipelineId}_${md5}_${projectId}_$taskId" + } // 移除旧的定时任务key if (schedulerManager.checkExists(comboKey)) { schedulerManager.deleteJob(comboKey) } schedulerManager.addJob( - taskComboKey, crontab, + comboKey, crontab, jobBeanClass ) } catch (ignore: Exception) { From 722a08bc23c9f506a4b0da1e8a95c9e19056535a Mon Sep 17 00:00:00 2001 From: hejieehe <904696180@qq.com> Date: Mon, 2 Dec 2024 18:04:08 +0800 Subject: [PATCH 07/15] =?UTF-8?q?feat=EF=BC=9A=E5=AE=9A=E6=97=B6=E8=A7=A6?= =?UTF-8?q?=E5=8F=91=E5=99=A8=E6=94=AF=E6=8C=81=E8=AE=BE=E7=BD=AE=E5=90=AF?= =?UTF-8?q?=E5=8A=A8=E5=8F=98=E9=87=8F=20#10617?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plugin/trigger/service/PipelineTimerUpgradeService.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/service/PipelineTimerUpgradeService.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/service/PipelineTimerUpgradeService.kt index 6b093b237446..c1d5dbc5c782 100644 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/service/PipelineTimerUpgradeService.kt +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/service/PipelineTimerUpgradeService.kt @@ -79,7 +79,7 @@ open class PipelineTimerUpgradeService @Autowired constructor( val lastModifyUser = pipelineInfo.lastModifyUser when { // 功能发布后,添加了多个定时触发器 - timerList.size > 1 -> { + timerTriggerElements.size > 1 -> { val containsEmptyTaskId = timerList.any { it.taskId.isNullOrBlank() } // 存在空的taskId,则删掉重新添加定时任务 if (containsEmptyTaskId) { From e47338b17e902b59bbbe7398c4bd7f6812743ba4 Mon Sep 17 00:00:00 2001 From: hejieehe <904696180@qq.com> Date: Tue, 3 Dec 2024 09:58:40 +0800 Subject: [PATCH 08/15] =?UTF-8?q?feat=EF=BC=9A=E5=AE=9A=E6=97=B6=E8=A7=A6?= =?UTF-8?q?=E5=8F=91=E5=99=A8=E6=94=AF=E6=8C=81=E8=AE=BE=E7=BD=AE=E5=90=AF?= =?UTF-8?q?=E5=8A=A8=E5=8F=98=E9=87=8F=20#10617?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tencent/devops/process/yaml/transfer/ElementTransfer.kt | 3 ++- .../tencent/devops/process/yaml/transfer/TriggerTransfer.kt | 3 ++- .../tencent/devops/process/yaml/v3/models/on/SchedulesRule.kt | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/backend/ci/core/common/common-pipeline-yaml/src/main/kotlin/com/tencent/devops/process/yaml/transfer/ElementTransfer.kt b/src/backend/ci/core/common/common-pipeline-yaml/src/main/kotlin/com/tencent/devops/process/yaml/transfer/ElementTransfer.kt index dd70ab9e1712..0b39ba010836 100644 --- a/src/backend/ci/core/common/common-pipeline-yaml/src/main/kotlin/com/tencent/devops/process/yaml/transfer/ElementTransfer.kt +++ b/src/backend/ci/core/common/common-pipeline-yaml/src/main/kotlin/com/tencent/devops/process/yaml/transfer/ElementTransfer.kt @@ -182,7 +182,8 @@ class ElementTransfer @Autowired(required = false) constructor( repoName = repoName, branches = element.branches, always = (element.noScm != true).nullIfDefault(false), - enable = element.elementEnabled().nullIfDefault(true) + enable = element.elementEnabled().nullIfDefault(true), + startParam = element.startParam ) ) return@forEach 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 41a6a32348dd..443fa15d8ab9 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 @@ -736,7 +736,8 @@ class TriggerTransfer @Autowired(required = false) constructor( branches = timer.branches, newExpression = timer.newExpression, advanceExpression = timer.advanceExpression, - noScm = timer.always != true + noScm = timer.always != true, + startParam = timer.startParam ).checkTriggerElementEnable(timer.enable) ) } diff --git a/src/backend/ci/core/common/common-pipeline-yaml/src/main/kotlin/com/tencent/devops/process/yaml/v3/models/on/SchedulesRule.kt b/src/backend/ci/core/common/common-pipeline-yaml/src/main/kotlin/com/tencent/devops/process/yaml/v3/models/on/SchedulesRule.kt index dcada0d2f90f..20252223992a 100644 --- a/src/backend/ci/core/common/common-pipeline-yaml/src/main/kotlin/com/tencent/devops/process/yaml/v3/models/on/SchedulesRule.kt +++ b/src/backend/ci/core/common/common-pipeline-yaml/src/main/kotlin/com/tencent/devops/process/yaml/v3/models/on/SchedulesRule.kt @@ -61,7 +61,8 @@ data class SchedulesRule( @JsonIgnore var newExpression: List? = null, @JsonIgnore - var advanceExpression: List? = null + var advanceExpression: List? = null, + val startParam: Map? = null ) { data class Interval( val week: List, From 8296349d8daa79135ffa43e4b6c4142da7b5a0cc Mon Sep 17 00:00:00 2001 From: hejieehe <904696180@qq.com> Date: Tue, 3 Dec 2024 16:03:22 +0800 Subject: [PATCH 09/15] =?UTF-8?q?feat=EF=BC=9A=E5=AE=9A=E6=97=B6=E8=A7=A6?= =?UTF-8?q?=E5=8F=91=E5=99=A8=E6=94=AF=E6=8C=81=E8=AE=BE=E7=BD=AE=E5=90=AF?= =?UTF-8?q?=E5=8A=A8=E5=8F=98=E9=87=8F=20#10617=20=E8=A1=A5=E5=85=85SQL?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sql/1001_ci_process_ddl_mysql.sql | 5 ++-- .../2030_ci_process-update_v3.0_mysql.sql | 28 +++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/support-files/sql/1001_ci_process_ddl_mysql.sql b/support-files/sql/1001_ci_process_ddl_mysql.sql index 32afeb6823db..73db168e8b2b 100644 --- a/support-files/sql/1001_ci_process_ddl_mysql.sql +++ b/support-files/sql/1001_ci_process_ddl_mysql.sql @@ -482,6 +482,7 @@ CREATE TABLE IF NOT EXISTS `T_PIPELINE_SETTING` ( CREATE TABLE IF NOT EXISTS `T_PIPELINE_TIMER` ( `PROJECT_ID` varchar(32) NOT NULL COMMENT '项目ID', `PIPELINE_ID` varchar(34) NOT NULL COMMENT '流水线ID', + `TASK_ID` varchar(64) DEFAULT '' COMMENT '插件ID', `CRONTAB` varchar(2048) NOT NULL COMMENT '任务ID', `CREATOR` varchar(64) NOT NULL COMMENT '创建者', `CREATE_TIME` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', @@ -489,8 +490,8 @@ CREATE TABLE IF NOT EXISTS `T_PIPELINE_TIMER` ( `REPO_HASH_ID` varchar(64) COMMENT '代码库HASH ID', `BRANCHS` text COMMENT '分支列表', `NO_SCM` bit(1) DEFAULT FALSE COMMENT '源代码未更新则不触发构建', - PRIMARY KEY (`PROJECT_ID`,`PIPELINE_ID`), - UNIQUE KEY `IDX_PIPELINE_ID` (`PIPELINE_ID`) + `START_PARAM` text COMMENT '启动参数', + PRIMARY KEY (`PROJECT_ID`,`PIPELINE_ID`,`TASK_ID`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=''; -- ---------------------------- diff --git a/support-files/sql/2004_v3.x/2030_ci_process-update_v3.0_mysql.sql b/support-files/sql/2004_v3.x/2030_ci_process-update_v3.0_mysql.sql index 339ba1faaf8a..e3a041aa8f7e 100644 --- a/support-files/sql/2004_v3.x/2030_ci_process-update_v3.0_mysql.sql +++ b/support-files/sql/2004_v3.x/2030_ci_process-update_v3.0_mysql.sql @@ -96,6 +96,34 @@ BEGIN ADD COLUMN `MAX_CON_RUNNING_QUEUE_SIZE` int(11) DEFAULT NULL COMMENT '并发构建数量限制,值为-1时表示取系统默认值。'; END IF; + + IF EXISTS(SELECT 1 + FROM information_schema.statistics + WHERE TABLE_SCHEMA = db + AND TABLE_NAME = 'T_PIPELINE_TIMER' + AND INDEX_NAME = 'IDX_PIPELINE_ID') THEN + ALTER TABLE T_PIPELINE_TIMER DROP INDEX `IDX_PIPELINE_ID`; + END IF; + + IF NOT EXISTS(SELECT 1 + FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = db + AND TABLE_NAME = 'T_PIPELINE_TIMER' + AND COLUMN_NAME = 'TASK_ID') THEN + ALTER TABLE `T_PIPELINE_TIMER` + ADD COLUMN `TASK_ID` varchar(64) DEFAULT '' COMMENT '插件ID' AFTER PIPELINE_ID, + DROP PRIMARY KEY, ADD PRIMARY KEY (`PROJECT_ID`, `PIPELINE_ID`, `TASK_ID`); + END IF; + + IF NOT EXISTS(SELECT 1 + FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = db + AND TABLE_NAME = 'T_PIPELINE_TIMER' + AND COLUMN_NAME = 'START_PARAM') THEN + ALTER TABLE `T_PIPELINE_TIMER` + ADD COLUMN `START_PARAM` text NULL COMMENT '插件启动参数'; + END IF; + COMMIT; END From 132556e1eb781953e4969ca0baa107ee292d693a Mon Sep 17 00:00:00 2001 From: hejieehe <904696180@qq.com> Date: Tue, 3 Dec 2024 17:23:28 +0800 Subject: [PATCH 10/15] =?UTF-8?q?feat=EF=BC=9A=E5=AE=9A=E6=97=B6=E8=A7=A6?= =?UTF-8?q?=E5=8F=91=E5=99=A8=E6=94=AF=E6=8C=81=E8=AE=BE=E7=BD=AE=E5=90=AF?= =?UTF-8?q?=E5=8A=A8=E5=8F=98=E9=87=8F=20#10617?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tencent/devops/process/yaml/transfer/ElementTransfer.kt | 2 +- .../tencent/devops/process/yaml/transfer/TriggerTransfer.kt | 2 +- .../tencent/devops/process/yaml/v3/models/on/SchedulesRule.kt | 3 ++- .../pipeline/pojo/element/trigger/TimerTriggerElement.kt | 2 +- .../plugin/trigger/element/TimerTriggerElementBizPlugin.kt | 2 +- .../plugin/trigger/service/PipelineTimerUpgradeService.kt | 4 ++-- 6 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/backend/ci/core/common/common-pipeline-yaml/src/main/kotlin/com/tencent/devops/process/yaml/transfer/ElementTransfer.kt b/src/backend/ci/core/common/common-pipeline-yaml/src/main/kotlin/com/tencent/devops/process/yaml/transfer/ElementTransfer.kt index 0b39ba010836..eacac3b3b815 100644 --- a/src/backend/ci/core/common/common-pipeline-yaml/src/main/kotlin/com/tencent/devops/process/yaml/transfer/ElementTransfer.kt +++ b/src/backend/ci/core/common/common-pipeline-yaml/src/main/kotlin/com/tencent/devops/process/yaml/transfer/ElementTransfer.kt @@ -183,7 +183,7 @@ class ElementTransfer @Autowired(required = false) constructor( branches = element.branches, always = (element.noScm != true).nullIfDefault(false), enable = element.elementEnabled().nullIfDefault(true), - startParam = element.startParam + startParams = element.startParams ) ) return@forEach 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 443fa15d8ab9..c10584e6711f 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 @@ -737,7 +737,7 @@ class TriggerTransfer @Autowired(required = false) constructor( newExpression = timer.newExpression, advanceExpression = timer.advanceExpression, noScm = timer.always != true, - startParam = timer.startParam + startParams = timer.startParams ).checkTriggerElementEnable(timer.enable) ) } diff --git a/src/backend/ci/core/common/common-pipeline-yaml/src/main/kotlin/com/tencent/devops/process/yaml/v3/models/on/SchedulesRule.kt b/src/backend/ci/core/common/common-pipeline-yaml/src/main/kotlin/com/tencent/devops/process/yaml/v3/models/on/SchedulesRule.kt index 20252223992a..e2eab504e7ab 100644 --- a/src/backend/ci/core/common/common-pipeline-yaml/src/main/kotlin/com/tencent/devops/process/yaml/v3/models/on/SchedulesRule.kt +++ b/src/backend/ci/core/common/common-pipeline-yaml/src/main/kotlin/com/tencent/devops/process/yaml/v3/models/on/SchedulesRule.kt @@ -62,7 +62,8 @@ data class SchedulesRule( var newExpression: List? = null, @JsonIgnore var advanceExpression: List? = null, - val startParam: Map? = null + @get:Schema(title = "start-params") + val startParams: Map? = null ) { data class Interval( val week: List, diff --git a/src/backend/ci/core/common/common-pipeline/src/main/kotlin/com/tencent/devops/common/pipeline/pojo/element/trigger/TimerTriggerElement.kt b/src/backend/ci/core/common/common-pipeline/src/main/kotlin/com/tencent/devops/common/pipeline/pojo/element/trigger/TimerTriggerElement.kt index 3905b24c715c..1e73c9a4591b 100644 --- a/src/backend/ci/core/common/common-pipeline/src/main/kotlin/com/tencent/devops/common/pipeline/pojo/element/trigger/TimerTriggerElement.kt +++ b/src/backend/ci/core/common/common-pipeline/src/main/kotlin/com/tencent/devops/common/pipeline/pojo/element/trigger/TimerTriggerElement.kt @@ -64,7 +64,7 @@ data class TimerTriggerElement( @get:Schema(title = "指定代码库别名", required = false) val repoName: String? = null, @get:Schema(title = "定时启动参数", required = false) - val startParam: Map? = null + val startParams: Map? = null ) : Element(name, id, status) { companion object { const val classType = "timerTrigger" diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/element/TimerTriggerElementBizPlugin.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/element/TimerTriggerElementBizPlugin.kt index dfbf6a2969c3..6750c91778e5 100644 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/element/TimerTriggerElementBizPlugin.kt +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/element/TimerTriggerElementBizPlugin.kt @@ -107,7 +107,7 @@ class TimerTriggerElementBizPlugin constructor( branchs = element.branches?.toSet(), noScm = element.noScm, taskId = element.id ?: "", - startParam = element.startParam + startParam = element.startParams ) logger.info("[$pipelineId]|$userId| Update pipeline timer|crontab=$crontabExpressions") if (result.isNotOk()) { diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/service/PipelineTimerUpgradeService.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/service/PipelineTimerUpgradeService.kt index c1d5dbc5c782..ad2bc5c1a684 100644 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/service/PipelineTimerUpgradeService.kt +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/service/PipelineTimerUpgradeService.kt @@ -129,7 +129,7 @@ open class PipelineTimerUpgradeService @Autowired constructor( pipelineId = pipelineId, taskId = timerTriggerElement.id ?: "", userId = lastModifyUser, - startParam = timerTriggerElement.startParam, + startParam = timerTriggerElement.startParams, crontabExpressionJson = crontab ) } @@ -179,7 +179,7 @@ open class PipelineTimerUpgradeService @Autowired constructor( branchs = element.branches?.toSet(), noScm = element.noScm, taskId = element.id ?: "", - startParam = element.startParam + startParam = element.startParams ) } } From c401bf7ce75f4418eb856f112469ab05dd125ded Mon Sep 17 00:00:00 2001 From: hejieehe <904696180@qq.com> Date: Wed, 4 Dec 2024 14:14:27 +0800 Subject: [PATCH 11/15] =?UTF-8?q?feat=EF=BC=9A=E5=AE=9A=E6=97=B6=E8=A7=A6?= =?UTF-8?q?=E5=8F=91=E5=99=A8=E6=94=AF=E6=8C=81=E8=AE=BE=E7=BD=AE=E5=90=AF?= =?UTF-8?q?=E5=8A=A8=E5=8F=98=E9=87=8F=20#10617?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../process/yaml/v3/models/on/SchedulesRule.kt | 1 + .../src/main/resources/schema/V3_0/ci.json | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/src/backend/ci/core/common/common-pipeline-yaml/src/main/kotlin/com/tencent/devops/process/yaml/v3/models/on/SchedulesRule.kt b/src/backend/ci/core/common/common-pipeline-yaml/src/main/kotlin/com/tencent/devops/process/yaml/v3/models/on/SchedulesRule.kt index e2eab504e7ab..bf88a91b0486 100644 --- a/src/backend/ci/core/common/common-pipeline-yaml/src/main/kotlin/com/tencent/devops/process/yaml/v3/models/on/SchedulesRule.kt +++ b/src/backend/ci/core/common/common-pipeline-yaml/src/main/kotlin/com/tencent/devops/process/yaml/v3/models/on/SchedulesRule.kt @@ -63,6 +63,7 @@ data class SchedulesRule( @JsonIgnore var advanceExpression: List? = null, @get:Schema(title = "start-params") + @JsonProperty("start-params") val startParams: Map? = null ) { data class Interval( 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 4edadcaff148..3d952f90977b 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 @@ -318,6 +318,9 @@ }, "always" : { "type" : "boolean" + }, + "start-params" : { + "type" : "object" } } } @@ -374,6 +377,9 @@ }, "always" : { "type" : "boolean" + }, + "start-params" : { + "type" : "object" } } } ] @@ -1009,6 +1015,9 @@ }, "always" : { "type" : "boolean" + }, + "start-params" : { + "type" : "object" } } } @@ -1065,6 +1074,9 @@ }, "always" : { "type" : "boolean" + }, + "start-params" : { + "type" : "object" } } } ] From 71dcd8f0519a1dd39850462a4576677705ef1400 Mon Sep 17 00:00:00 2001 From: hejieehe <904696180@qq.com> Date: Wed, 4 Dec 2024 14:40:40 +0800 Subject: [PATCH 12/15] =?UTF-8?q?feat=EF=BC=9A=E5=AE=9A=E6=97=B6=E8=A7=A6?= =?UTF-8?q?=E5=8F=91=E5=99=A8=E6=94=AF=E6=8C=81=E8=AE=BE=E7=BD=AE=E5=90=AF?= =?UTF-8?q?=E5=8A=A8=E5=8F=98=E9=87=8F=20#10617?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/pipeline/pojo/element/trigger/TimerTriggerElement.kt | 2 +- .../com/tencent/devops/process/engine/pojo/PipelineTimer.kt | 2 +- .../devops/process/api/op/OpPipelineTimerResourceImpl.kt | 1 - .../plugin/trigger/pojo/event/PipelineTimerBuildEvent.kt | 2 +- .../process/plugin/trigger/service/PipelineTimerService.kt | 2 +- .../plugin/trigger/service/PipelineTimerUpgradeService.kt | 2 +- .../plugin/trigger/timer/listener/PipelineTimerBuildListener.kt | 2 +- 7 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/backend/ci/core/common/common-pipeline/src/main/kotlin/com/tencent/devops/common/pipeline/pojo/element/trigger/TimerTriggerElement.kt b/src/backend/ci/core/common/common-pipeline/src/main/kotlin/com/tencent/devops/common/pipeline/pojo/element/trigger/TimerTriggerElement.kt index 1e73c9a4591b..1527bab18ee5 100644 --- a/src/backend/ci/core/common/common-pipeline/src/main/kotlin/com/tencent/devops/common/pipeline/pojo/element/trigger/TimerTriggerElement.kt +++ b/src/backend/ci/core/common/common-pipeline/src/main/kotlin/com/tencent/devops/common/pipeline/pojo/element/trigger/TimerTriggerElement.kt @@ -64,7 +64,7 @@ data class TimerTriggerElement( @get:Schema(title = "指定代码库别名", required = false) val repoName: String? = null, @get:Schema(title = "定时启动参数", required = false) - val startParams: Map? = null + val startParams: Map? = null ) : Element(name, id, status) { companion object { const val classType = "timerTrigger" diff --git a/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/engine/pojo/PipelineTimer.kt b/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/engine/pojo/PipelineTimer.kt index 85c1b11b8f88..22dc5844963f 100644 --- a/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/engine/pojo/PipelineTimer.kt +++ b/src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/engine/pojo/PipelineTimer.kt @@ -39,5 +39,5 @@ data class PipelineTimer( val branchs: List?, val noScm: Boolean?, val taskId: String, - val startParam: Map? + val startParam: Map? ) diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/api/op/OpPipelineTimerResourceImpl.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/api/op/OpPipelineTimerResourceImpl.kt index 7c50fd3fa307..c381ea515195 100644 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/api/op/OpPipelineTimerResourceImpl.kt +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/api/op/OpPipelineTimerResourceImpl.kt @@ -70,7 +70,6 @@ class OpPipelineTimerResourceImpl @Autowired constructor( return Result(true) } - companion object { private val logger = LoggerFactory.getLogger(OpPipelineTimerResourceImpl::class.java) } diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/pojo/event/PipelineTimerBuildEvent.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/pojo/event/PipelineTimerBuildEvent.kt index 10f49cc227e8..153d994d4828 100644 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/pojo/event/PipelineTimerBuildEvent.kt +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/pojo/event/PipelineTimerBuildEvent.kt @@ -46,7 +46,7 @@ data class PipelineTimerBuildEvent( override val userId: String, val channelCode: ChannelCode, val taskId: String, - val startParam: Map?, + val startParam: Map?, override var actionType: ActionType = ActionType.START, override var delayMills: Int = 0 ) : IPipelineEvent(actionType, source, projectId, pipelineId, userId, delayMills) diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/service/PipelineTimerService.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/service/PipelineTimerService.kt index 705646f423b4..1d9eb5dd20e3 100644 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/service/PipelineTimerService.kt +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/service/PipelineTimerService.kt @@ -75,7 +75,7 @@ open class PipelineTimerService @Autowired constructor( branchs: Set?, taskId: String, noScm: Boolean?, - startParam: Map? + startParam: Map? ): Result { val crontabJson = JsonUtil.toJson(crontabExpressions, formatted = false) return if (0 < pipelineTimerDao.save( diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/service/PipelineTimerUpgradeService.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/service/PipelineTimerUpgradeService.kt index ad2bc5c1a684..d056316aa00d 100644 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/service/PipelineTimerUpgradeService.kt +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/service/PipelineTimerUpgradeService.kt @@ -101,7 +101,7 @@ open class PipelineTimerUpgradeService @Autowired constructor( } // 重新添加定时任务 saveTimer( - timerTriggerElements= timerTriggerElements, + timerTriggerElements = timerTriggerElements, params = params, latestVersion = model.latestVersion, projectId = projectId, diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/timer/listener/PipelineTimerBuildListener.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/timer/listener/PipelineTimerBuildListener.kt index 201647ab69f4..97d227a7f455 100644 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/timer/listener/PipelineTimerBuildListener.kt +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/timer/listener/PipelineTimerBuildListener.kt @@ -152,7 +152,7 @@ class PipelineTimerBuildListener @Autowired constructor( return } // 填充触发器启动参数 - val startParams = mutableMapOf() + val startParams = mutableMapOf() event.startParam?.let { startParams.putAll(it) } From 305d787536f5407a1207bf2ea53982840583760f Mon Sep 17 00:00:00 2001 From: hejieehe <904696180@qq.com> Date: Mon, 6 Jan 2025 11:01:22 +0800 Subject: [PATCH 13/15] =?UTF-8?q?feat=EF=BC=9A=E5=AE=9A=E6=97=B6=E8=A7=A6?= =?UTF-8?q?=E5=8F=91=E5=99=A8=E6=94=AF=E6=8C=81=E8=AE=BE=E7=BD=AE=E5=90=AF?= =?UTF-8?q?=E5=8A=A8=E5=8F=98=E9=87=8F=20#10617?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plugin/trigger/service/PipelineTimerUpgradeService.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/service/PipelineTimerUpgradeService.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/service/PipelineTimerUpgradeService.kt index d056316aa00d..cfaf5899e40d 100644 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/service/PipelineTimerUpgradeService.kt +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/service/PipelineTimerUpgradeService.kt @@ -46,8 +46,9 @@ open class PipelineTimerUpgradeService @Autowired constructor( val pipelineTimerService: PipelineTimerService, val timerTriggerTaskService: PipelineTimerTriggerTaskService ) { + @SuppressWarnings("NestedBlockDepth") fun upgrade(userId: String, targetProjectId: String?, targetPipelineId: String?) { - logger.info("upgrade pipeline timer") + logger.info("upgrade pipeline timer||targetProjectId=$targetProjectId|targetPipelineId=$targetPipelineId") var offset = 0 val limit = 100 do { From 08886911d9f05f45aba8e662fd8e081b753473b4 Mon Sep 17 00:00:00 2001 From: hejieehe <904696180@qq.com> Date: Mon, 6 Jan 2025 11:10:49 +0800 Subject: [PATCH 14/15] =?UTF-8?q?feat=EF=BC=9A=E5=AE=9A=E6=97=B6=E8=A7=A6?= =?UTF-8?q?=E5=8F=91=E5=99=A8=E6=94=AF=E6=8C=81=E8=AE=BE=E7=BD=AE=E5=90=AF?= =?UTF-8?q?=E5=8A=A8=E5=8F=98=E9=87=8F=20#10617?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plugin/trigger/service/PipelineTimerUpgradeService.kt | 3 +-- .../plugin/trigger/timer/quartz/PipelineQuartzService.kt | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/service/PipelineTimerUpgradeService.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/service/PipelineTimerUpgradeService.kt index cfaf5899e40d..fea1f40c91f8 100644 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/service/PipelineTimerUpgradeService.kt +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/service/PipelineTimerUpgradeService.kt @@ -48,7 +48,7 @@ open class PipelineTimerUpgradeService @Autowired constructor( ) { @SuppressWarnings("NestedBlockDepth") fun upgrade(userId: String, targetProjectId: String?, targetPipelineId: String?) { - logger.info("upgrade pipeline timer||targetProjectId=$targetProjectId|targetPipelineId=$targetPipelineId") + logger.info("upgrade pipeline timer|targetProjectId=$targetProjectId|targetPipelineId=$targetPipelineId") var offset = 0 val limit = 100 do { @@ -191,7 +191,6 @@ open class PipelineTimerUpgradeService @Autowired constructor( fun getTimerTriggerConfig(model: Model) = model.getTriggerContainer() .elements.filter { it is TimerTriggerElement && it.elementEnabled() }.map { it as TimerTriggerElement } - companion object { private val logger = LoggerFactory.getLogger(PipelineTimerUpgradeService::class.java) } diff --git a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/timer/quartz/PipelineQuartzService.kt b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/timer/quartz/PipelineQuartzService.kt index 1c87177eff4b..777e1428133f 100644 --- a/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/timer/quartz/PipelineQuartzService.kt +++ b/src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/plugin/trigger/timer/quartz/PipelineQuartzService.kt @@ -110,7 +110,7 @@ class PipelineQuartzService @Autowired constructor( try { val md5 = DigestUtils.md5Hex(crontab) val comboKey = if (taskId.isEmpty()) { - "${pipelineId}_${md5}_${projectId}" + "${pipelineId}_${md5}_$projectId" } else { "${pipelineId}_${md5}_${projectId}_$taskId" } From 0a23a7bfda2c9515bf38debb6d4488e18adcc49d Mon Sep 17 00:00:00 2001 From: hejieehe <904696180@qq.com> Date: Tue, 7 Jan 2025 17:39:09 +0800 Subject: [PATCH 15/15] =?UTF-8?q?feat=EF=BC=9A=E5=AE=9A=E6=97=B6=E8=A7=A6?= =?UTF-8?q?=E5=8F=91=E5=99=A8=E6=94=AF=E6=8C=81=E8=AE=BE=E7=BD=AE=E5=90=AF?= =?UTF-8?q?=E5=8A=A8=E5=8F=98=E9=87=8F=20#10617?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sql/5001_init_dml/5001_ci_store-init_dml_mysql.sql | 2 ++ 1 file changed, 2 insertions(+) diff --git a/support-files/sql/5001_init_dml/5001_ci_store-init_dml_mysql.sql b/support-files/sql/5001_init_dml/5001_ci_store-init_dml_mysql.sql index 8337aa9505d5..bef638b136eb 100755 --- a/support-files/sql/5001_init_dml/5001_ci_store-init_dml_mysql.sql +++ b/support-files/sql/5001_init_dml/5001_ci_store-init_dml_mysql.sql @@ -3,6 +3,8 @@ use devops_ci_store; 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 ('0a1c7837b53e4c459c50f3228f0ed317', 'Timer', 'timerTrigger', 'timerTrigger', '', 'AGENT', '[ \"LINUX\", \"MACOS\", \"WINDOWS\" ]', 'e1bea5430f574f9ea3e0312dc7de9efa', '', 0, 7, NULL, 'The pipeline can be started through background timing tasks, supporting fast timing and linux crontab advanced timing', '可The pipeline can be started through background timing tasks, supporting fast timing and linux crontab advanced timing', 0, '1.0.0', '/ms/artifactory/api/user/artifactories/file/download?filePath=%2Ffile%2Fpng%2FtimerTrigger.png&logo=true', NULL, True, True, False, NULL, NULL, False, '1.0', '{\"newExpression\":{\"label\":\"Basic Rules\",\"required\":true,\"component\":\"cron-timer\"},\"advanceExpression\":{\"label\":\"Scheduled task rules\",\"required\":false,\"component\":\"vuex-textarea\"},\"noScm\":{\"component\":\"atom-checkbox\",\"required\":false}}', '{}', 'BlueKing', 8, 'system', 'system', '2019-03-04 18:09:39', '2019-04-18 13:41:48', 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 + ('550e8400e29b41d4a716446655440000', 'Timer', 'timerTrigger', 'timerTrigger', '', 'AGENT', '[ \"LINUX\", \"MACOS\", \"WINDOWS\" ]', 'e1bea5430f574f9ea3e0312dc7de9efa', '', 0, 7, NULL, 'The pipeline can be started through background timing tasks, supporting fast timing and linux crontab advanced timing', '可The pipeline can be started through background timing tasks, supporting fast timing and linux crontab advanced timing', 0, '2.0.0', '/ms/artifactory/api/user/artifactories/file/download?filePath=%2Ffile%2Fpng%2FtimerTrigger.png&logo=true', NULL, False, True, False, NULL, NULL, False, '1.0', '{\"newExpression\":{\"label\":\"BasicRules\",\"required\":true,\"component\":\"cron-timer\"},\"advanceExpression\":{\"label\":\"Scheduledtaskrules\",\"required\":false,\"component\":\"vuex-textarea\"},\"noScm\":{\"component\":\"atom-checkbox\",\"required\":false},\"startParam\":{\"component\":\"sub-parameter\",\"required\":false}}', '{}', 'BlueKing', 8, 'system', 'system', '2019-03-04 18:09:39', '2019-04-18 13:41:48', 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 ('6868f24a5b14479683dcd6d63fdb9b42', 'Review', 'manualReviewUserTask', 'manualReviewUserTask', '[ \"pipeline\" ]', 'AGENT', '[ \"LINUX\", \"MACOS\", \"WINDOWS\" ]', 'e5de5b6e525e4b0abf6b1d88d2242fe7', '', '0', '7', NULL, '', '', '1', '1.0.0', '/ms/artifactory/api/user/artifactories/file/download?filePath=%2Ffile%2Fpng%2FmanualReviewUserTask.png&logo=true', NULL, b'1', b'1', b'1', NULL, NULL, b'0', '1.0', '{\"reviewUsers\":{\"rule\":{},\"required\":true,\"label\":\"Reviewer\",\"component\":\"user-input\",\"placeholder\":\"withing set {var}, separate multiple reviewers with commas\",\"default\":[]}}', '{}', 'BlueKing', '1', 'system', 'system', '2019-03-04 18:09:42', '2019-08-08 18:04:38', '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