Skip to content

Commit

Permalink
feat: 流水线插件高级特性:即使前面有插件运行失败也运行,即使被取消也运行 TencentBlueKing#1156
Browse files Browse the repository at this point in the history
  • Loading branch information
carlyin0801 committed Jul 31, 2021
1 parent de16e0a commit 20df37d
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import com.tencent.devops.common.pipeline.enums.BuildStatus
import com.tencent.devops.common.pipeline.enums.StartType
import com.tencent.devops.common.pipeline.pojo.BuildFormProperty
import com.tencent.devops.common.pipeline.pojo.element.Element
import com.tencent.devops.common.pipeline.pojo.element.RunCondition
import com.tencent.devops.common.pipeline.utils.ModelUtils
import com.tencent.devops.common.redis.RedisOperation
import com.tencent.devops.process.dao.BuildDetailDao
Expand Down Expand Up @@ -202,7 +203,8 @@ class PipelineBuildDetailService @Autowired constructor(
update = true
}
// #3138 状态实时刷新
if (status.isRunning() && container.containPostTaskFlag != true) {
if (status.isRunning() && container.elements[0].status.isNullOrBlank() &&
container.containPostTaskFlag != true) {
container.status = buildStatus.name
}
return Traverse.CONTINUE
Expand All @@ -211,28 +213,34 @@ class PipelineBuildDetailService @Autowired constructor(
override fun onFindElement(index: Int, e: Element, c: Container): Traverse {
if (e.status == BuildStatus.RUNNING.name || e.status == BuildStatus.REVIEWING.name) {
val status = if (e.status == BuildStatus.RUNNING.name) {
BuildStatus.CANCELED.name
val runCondition = e.additionalOptions?.runCondition
// 当task的runCondition为PRE_TASK_FAILED_EVEN_CANCEL,点击取消还需要运行
if (runCondition == RunCondition.PRE_TASK_FAILED_EVEN_CANCEL) {
BuildStatus.RUNNING.name
} else {
BuildStatus.CANCELED.name
}
} else buildStatus.name
e.status = status
if (e.status != BuildStatus.RUNNING.name && c.containPostTaskFlag != true) {
if (c.containPostTaskFlag != true) {
c.status = status
}

if (e.startEpoch != null) {
e.elapsed = System.currentTimeMillis() - e.startEpoch!!
}

var elementElapsed = 0L
run lit@{
c.elements.forEach {
elementElapsed += it.elapsed ?: 0
if (it == e) {
return@lit
if (BuildStatus.parse(status).isFinish()) {
if (e.startEpoch != null) {
e.elapsed = System.currentTimeMillis() - e.startEpoch!!
}
var elementElapsed = 0L
run lit@{
c.elements.forEach {
elementElapsed += it.elapsed ?: 0
if (it == e) {
return@lit
}
}
}
}

c.elementElapsed = elementElapsed
c.elementElapsed = elementElapsed
}

update = true
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -383,10 +383,11 @@ class TaskBuildDetailService(
for (i in startIndex..endIndex) {
val element = elements[i]
val taskId = element.id
val runCondition = element.additionalOptions?.runCondition
// 排除构建状态为结束态的构建任务和runCondition不为PRE_TASK_FAILED_EVEN_CANCEL的任务
if (taskId != null && runCondition != RunCondition.PRE_TASK_FAILED_EVEN_CANCEL &&
!BuildStatus.parse(element.status).isFinish()) {
val additionalOptions = element.additionalOptions
// 排除构建状态为结束态的构建任务
if (taskId != null && !BuildStatus.parse(element.status).isFinish() &&
additionalOptions?.elementPostInfo == null
) {
val unExecBuildStatus = BuildStatus.UNEXEC
element.status = unExecBuildStatus.name
updateTaskStatusInfos?.add(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ object ContainerUtils {
containerId: String
) = "container:startup:$pipelineId:$buildId:$containerId"

fun getContainerRunEvenCancelTaskKey(
pipelineId: String,
buildId: String,
containerId: String
) = "container:taskEvenCancel:$pipelineId:$buildId:$containerId"

fun isNormalContainerEnable(normalContainer: NormalContainer): Boolean {
return if (normalContainer.jobControlOption != null) {
normalContainer.jobControlOption!!.enable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
import java.time.LocalDateTime

@Suppress("LongParameterList")
@Service
class BuildCancelControl @Autowired constructor(
private val mutexControl: MutexControl,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import com.tencent.devops.common.api.util.timestampmilli
import com.tencent.devops.common.event.dispatcher.pipeline.PipelineEventDispatcher
import com.tencent.devops.common.event.enums.ActionType
import com.tencent.devops.common.pipeline.enums.BuildStatus
import com.tencent.devops.common.pipeline.pojo.element.RunCondition
import com.tencent.devops.common.redis.RedisOperation
import com.tencent.devops.common.service.utils.LogUtils
import com.tencent.devops.process.engine.atom.AtomResponse
Expand Down Expand Up @@ -124,7 +125,11 @@ class TaskControl @Autowired constructor(
// 构建机的任务不在此运行
if (taskAtomService.runByVmTask(buildTask!!)) {
// 构建机上运行中任务目前无法直接后台干预,便在此处设置状态,使流程继续
if (actionType.isEnd()) {
val additionalOptions = buildTask.additionalOptions
val runCondition = additionalOptions?.runCondition
val failedEvenCancelFlag = runCondition == RunCondition.PRE_TASK_FAILED_EVEN_CANCEL
if (actionType.isTerminate() ||
(actionType == ActionType.END && !failedEvenCancelFlag)) {
LOG.info("ENGINE|$buildId|$source|ATOM_$actionType|$stageId|j($containerId)|t($taskId)|code=$errorCode")
val buildStatus = if (actionType.isTerminate()) { // 区分系统终止还是用户手动终止
BuildStatus.TERMINATE
Expand Down Expand Up @@ -171,7 +176,11 @@ class TaskControl @Autowired constructor(
*/
private fun runTask(userId: String, actionType: ActionType, buildTask: PipelineBuildTask) = when {
buildTask.status.isReadyToRun() -> { // 准备启动执行
if (actionType.isEnd()) { // #2400 因任务终止&结束的事件命令而未执行的原子设置为UNEXEC,而不是SKIP
val runCondition = buildTask.additionalOptions?.runCondition
if (actionType.isTerminate() ||
(actionType == ActionType.END && runCondition != RunCondition.PRE_TASK_FAILED_EVEN_CANCEL)
) {
// #2400 因任务终止&结束的事件命令而未执行的原子设置为UNEXEC,而不是SKIP
pipelineRuntimeService.updateTaskStatus(
task = buildTask, userId = userId, buildStatus = BuildStatus.UNEXEC
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,11 @@ import com.tencent.devops.common.event.enums.ActionType
import com.tencent.devops.common.log.utils.BuildLogPrinter
import com.tencent.devops.common.pipeline.enums.BuildStatus
import com.tencent.devops.common.pipeline.pojo.element.ElementPostInfo
import com.tencent.devops.common.pipeline.pojo.element.RunCondition
import com.tencent.devops.common.pipeline.utils.BuildStatusSwitcher
import com.tencent.devops.common.redis.RedisOperation
import com.tencent.devops.common.service.utils.MessageCodeUtil
import com.tencent.devops.process.engine.common.Timeout
import com.tencent.devops.process.engine.common.VMUtils
import com.tencent.devops.process.engine.control.ControlUtils
import com.tencent.devops.process.engine.control.FastKillUtils
Expand All @@ -45,6 +48,7 @@ import com.tencent.devops.process.engine.pojo.PipelineTaskStatusInfo
import com.tencent.devops.process.engine.pojo.event.PipelineBuildAtomTaskEvent
import com.tencent.devops.process.engine.service.PipelineRuntimeService
import com.tencent.devops.process.engine.service.detail.TaskBuildDetailService
import com.tencent.devops.process.engine.utils.ContainerUtils
import com.tencent.devops.process.pojo.mq.PipelineBuildContainerEvent
import com.tencent.devops.process.service.PipelineContextService
import com.tencent.devops.process.service.PipelineTaskService
Expand All @@ -53,9 +57,10 @@ import com.tencent.devops.store.pojo.common.ATOM_POST_EXECUTE_TIP
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Service

@Suppress("TooManyFunctions")
@Suppress("TooManyFunctions", "LongParameterList")
@Service
class StartActionTaskContainerCmd(
private val redisOperation: RedisOperation,
private val pipelineRuntimeService: PipelineRuntimeService,
private val taskBuildDetailService: TaskBuildDetailService,
private val pipelineEventDispatcher: PipelineEventDispatcher,
Expand Down Expand Up @@ -85,9 +90,12 @@ class StartActionTaskContainerCmd(
val fastKill = FastKillUtils.isFastKillCode(commandContext.event.errorCode)
if (!fastKill && actionType.isTerminate() && !commandContext.buildStatus.isFailure()) {
commandContext.buildStatus = BuildStatus.FAILED
} else {
setContextBuildStatus(commandContext)
}
commandContext.latestSummary += "| status=${commandContext.buildStatus}"
} else {
doWaitToDoTaskBus(waitToDoTask, actionType, commandContext)
sendTask(event = commandContext.event, task = waitToDoTask)
}
}
Expand All @@ -98,6 +106,48 @@ class StartActionTaskContainerCmd(
}
}

private fun setContextBuildStatus(commandContext: ContainerContext) {
val container = commandContext.container
val runEvenCancelTaskIdKey = ContainerUtils.getContainerRunEvenCancelTaskKey(
pipelineId = container.pipelineId,
buildId = container.buildId,
containerId = container.containerId
)
if (redisOperation.get(runEvenCancelTaskIdKey) != null) {
/**
* 当前的job如果包含runCondition为PRE_TASK_FAILED_EVEN_CANCEL的task,运行到最后如果状态为SUCCEED,
* 则需要置为CANCELED
*/
if (commandContext.buildStatus == BuildStatus.SUCCEED) {
commandContext.buildStatus = BuildStatus.CANCELED
}
redisOperation.delete(runEvenCancelTaskIdKey)
}
}

private fun doWaitToDoTaskBus(
waitToDoTask: PipelineBuildTask,
actionType: ActionType,
commandContext: ContainerContext
) {
// 当task的runCondition为PRE_TASK_FAILED_EVEN_CANCEL且task被用户取消时则写入标志到redis中
val runCondition = waitToDoTask.additionalOptions?.runCondition
val failedEvenCancelFlag = runCondition == RunCondition.PRE_TASK_FAILED_EVEN_CANCEL
if (actionType == ActionType.END && failedEvenCancelFlag) {
val container = commandContext.container
val timeOut = container.controlOption?.jobControlOption?.timeout ?: Timeout.MAX_MINUTES
redisOperation.set(
key = ContainerUtils.getContainerRunEvenCancelTaskKey(
pipelineId = waitToDoTask.pipelineId,
buildId = waitToDoTask.buildId,
containerId = waitToDoTask.containerId
),
value = waitToDoTask.taskId,
expiredInSecond = timeOut * 60L
)
}
}

/**
* 寻找能下发的任务:
* 如遇到[BuildStatus.isRunning]的任务,如果没有出现错误,则本次不做任何处理,返回null, 使用[CmdFlowState.BREAK]中断后续执行
Expand Down

0 comments on commit 20df37d

Please sign in to comment.