diff --git a/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/expressions/functions/ArtifactExpressionFunctionProvider.java b/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/expressions/functions/ArtifactExpressionFunctionProvider.java index 24f5926a1b..941b467b12 100644 --- a/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/expressions/functions/ArtifactExpressionFunctionProvider.java +++ b/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/expressions/functions/ArtifactExpressionFunctionProvider.java @@ -23,7 +23,10 @@ import com.netflix.spinnaker.kork.expressions.ExpressionFunctionProvider; import com.netflix.spinnaker.kork.expressions.SpelHelperFunctionException; import com.netflix.spinnaker.orca.api.pipeline.models.PipelineExecution; +import java.util.Collections; +import java.util.List; import java.util.function.Predicate; +import java.util.stream.Collectors; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.springframework.stereotype.Component; @@ -42,16 +45,21 @@ public Functions getFunctions() { return new Functions( new FunctionDefinition( "triggerResolvedArtifact", - "Looks up the an artifact in current execution given its name. If multiple artifacts are found, only 1 will be returned.", + "Looks up a resolved artifact in the current execution trigger given its name. If multiple artifacts are found, only 1 will be returned.", new FunctionParameter( PipelineExecution.class, "execution", "The execution to search for artifacts"), new FunctionParameter(String.class, "name", "The name of the resolved artifact")), new FunctionDefinition( "triggerResolvedArtifactByType", - "Looks up the an artifact in current execution given its type. If multiple artifacts are found, only 1 will be returned.", + "Looks up a resolved artifact in the current execution trigger given its type. If multiple artifacts are found, only 1 will be returned.", new FunctionParameter( PipelineExecution.class, "execution", "The execution to search for artifacts"), - new FunctionParameter(String.class, "type", "The type of the resolved artifact"))); + new FunctionParameter(String.class, "type", "The type of the resolved artifact")), + new FunctionDefinition( + "resolvedArtifacts", + "Looks up resolved artifacts in the current execution.", + new FunctionParameter( + PipelineExecution.class, "execution", "The execution to search for artifacts"))); } public static Artifact triggerResolvedArtifact(PipelineExecution execution, String name) { @@ -78,4 +86,16 @@ private static Artifact triggerResolvedArtifactBy( "Unable to locate resolved artifact %s in trigger execution %s.", nameOrType, execution.getId()))); } + + private static List resolvedArtifacts(PipelineExecution execution) { + return execution.getStages().stream() + .flatMap( + stageExecution -> + ((List) + stageExecution + .getOutputs() + .getOrDefault("artifacts", Collections.emptyList())) + .stream()) + .collect(Collectors.toList()); + } } diff --git a/orca-core/src/test/groovy/com/netflix/spinnaker/orca/pipeline/expressions/functions/ArtifactExpressionFunctionProviderSpec.groovy b/orca-core/src/test/groovy/com/netflix/spinnaker/orca/pipeline/expressions/functions/ArtifactExpressionFunctionProviderSpec.groovy index 7397f546a5..0af424fca7 100644 --- a/orca-core/src/test/groovy/com/netflix/spinnaker/orca/pipeline/expressions/functions/ArtifactExpressionFunctionProviderSpec.groovy +++ b/orca-core/src/test/groovy/com/netflix/spinnaker/orca/pipeline/expressions/functions/ArtifactExpressionFunctionProviderSpec.groovy @@ -25,7 +25,9 @@ import spock.lang.Specification import static com.netflix.spinnaker.orca.pipeline.expressions.functions.ArtifactExpressionFunctionProvider.triggerResolvedArtifact import static com.netflix.spinnaker.orca.pipeline.expressions.functions.ArtifactExpressionFunctionProvider.triggerResolvedArtifactByType +import static com.netflix.spinnaker.orca.pipeline.expressions.functions.ArtifactExpressionFunctionProvider.resolvedArtifacts import static com.netflix.spinnaker.orca.test.model.ExecutionBuilder.pipeline +import static com.netflix.spinnaker.orca.test.model.ExecutionBuilder.stage class ArtifactExpressionFunctionProviderSpec extends Specification { @@ -38,6 +40,34 @@ class ArtifactExpressionFunctionProviderSpec extends Specification { trigger.resolvedExpectedArtifacts = [ ExpectedArtifact.builder().matchArtifact(matchArtifact1).boundArtifact(boundArtifact).build() ] + + stage { + id = "1" + refId = "1" + name = "Stage 1" + outputs = [artifacts: [Artifact.builder().type("type1").name("name1").reference("ref1").build()] ] + } + + stage { + id = "2" + refId = "2" + name = "Stage 2" + outputs = [artifacts: [Artifact.builder().type("type2").name("name2").reference("ref2").build()] ] + } + + stage { + id = "3" + refId = "3" + name = "Stage 3" + outputs = [artifacts: [Artifact.builder().type("type3").name("name3").reference("ref3").build()] ] + } + + stage { + id = "4" + refId = "4" + name = "Stage 4" + outputs = [artifacts: [Artifact.builder().type("type4").name("name4").reference("ref4").build()] ] + } } def "triggerResolvedArtifact returns resolved trigger artifact by name"() { @@ -74,4 +104,14 @@ class ArtifactExpressionFunctionProviderSpec extends Specification { then: thrown(SpelHelperFunctionException) } + + def "resolvedArtifacts returns artifacts in execution"() { + when: + def artifacts = resolvedArtifacts(pipeline1) + + then: + artifacts.collect { it.name } == [ "name1", "name2", "name3", "name4" ] + artifacts.collect { it.type } == [ "type1", "type2", "type3", "type4" ] + artifacts.collect { it.reference } == [ "ref1", "ref2", "ref3", "ref4" ] + } }