diff --git a/orca-front50/src/main/groovy/com/netflix/spinnaker/orca/front50/spring/DependentPipelineExecutionListener.groovy b/orca-front50/src/main/groovy/com/netflix/spinnaker/orca/front50/spring/DependentPipelineExecutionListener.groovy index 6b6a8aab79..3c3af95f6a 100644 --- a/orca-front50/src/main/groovy/com/netflix/spinnaker/orca/front50/spring/DependentPipelineExecutionListener.groovy +++ b/orca-front50/src/main/groovy/com/netflix/spinnaker/orca/front50/spring/DependentPipelineExecutionListener.groovy @@ -74,37 +74,50 @@ class DependentPipelineExecutionListener implements ExecutionListener { // Resolve templated pipelines if enabled. allPipelines = allPipelines.collect { pipeline -> if (V2Util.isV2Pipeline(pipeline)) { - return V2Util.planPipeline(contextParameterProcessor, executionPreprocessors, pipeline) + try { + return V2Util.planPipeline(contextParameterProcessor, executionPreprocessors, pipeline) + } catch (Exception e) { + log.error("Failed to plan V2 templated pipeline {}", pipeline.getOrDefault("id", ""), e) + return null + } } else { return pipeline } } } - allPipelines.findAll { !it.disabled } + allPipelines.findAll { (it != null) && (!it.disabled) } .each { it.triggers.each { trigger -> - if (trigger.enabled && - trigger.type == 'pipeline' && - trigger.pipeline && - trigger.pipeline == execution.pipelineConfigId && - trigger.status.contains(status) - ) { - User authenticatedUser = null + try { + if (trigger.enabled && + trigger.type == 'pipeline' && + trigger.pipeline && + trigger.pipeline == execution.pipelineConfigId && + trigger.status.contains(status) + ) { + User authenticatedUser = null - if (fiatStatus.enabled && trigger.runAsUser) { - authenticatedUser = new User() - authenticatedUser.setEmail(trigger.runAsUser) - } + if (fiatStatus.enabled && trigger.runAsUser) { + authenticatedUser = new User() + authenticatedUser.setEmail(trigger.runAsUser) + } - dependentPipelineStarter.trigger( - it, - execution.trigger?.user as String, - execution, - [:], - null, - authenticatedUser - ) + dependentPipelineStarter.trigger( + it, + execution.trigger?.user as String, + execution, + [:], + null, + authenticatedUser + ) + } + } + catch (Exception e) { + log.error( + "Failed to process triggers for pipeline {} while triggering dependent pipelines", + it.getOrDefault("id", ""), + e) } } } diff --git a/orca-front50/src/test/groovy/com/netflix/spinnaker/orca/front50/spring/DependentPipelineExecutionListenerSpec.groovy b/orca-front50/src/test/groovy/com/netflix/spinnaker/orca/front50/spring/DependentPipelineExecutionListenerSpec.groovy index c0deb4505b..c4f32d3457 100644 --- a/orca-front50/src/test/groovy/com/netflix/spinnaker/orca/front50/spring/DependentPipelineExecutionListenerSpec.groovy +++ b/orca-front50/src/test/groovy/com/netflix/spinnaker/orca/front50/spring/DependentPipelineExecutionListenerSpec.groovy @@ -106,6 +106,30 @@ class DependentPipelineExecutionListenerSpec extends Specification { status << [ExecutionStatus.SUCCEEDED, ExecutionStatus.TERMINAL] } + def "should trigger downstream v2 templated pipeline even when templates are invalid"() { + given: + pipeline.stages.each { + it.status = ExecutionStatus.SUCCEEDED + it.tasks = [Mock(Task)] + } + + pipeline.pipelineConfigId = "97c435a0-0faf-11e5-a62b-696d38c37faa" + front50Service.getAllPipelines() >> [ + v2MptPipelineConfig, v2MptPipelineConfig + ] + GroovyMock(V2Util, global: true) + V2Util.planPipeline(_, _, v2MptPipelineConfig) >> + {throw new Exception("planning failed")} >> + v2MptPipelineConfig + V2Util.isV2Pipeline(_) >> true + + when: + listener.afterExecution(null, pipeline, null, true) + + then: + 1 * dependentPipelineStarter.trigger(_, _, _, _, _, _) + } + def "should not trigger downstream pipeline when conditions don't match"() { given: pipeline.stages.each { @@ -113,7 +137,6 @@ class DependentPipelineExecutionListenerSpec extends Specification { it.tasks = [Mock(Task)] } - pipeline.pipelineConfigId = id pipelineConfig.triggers.first().status = ['successful']