From d57d74a6b6c2ef93fb9d177a286b4e38ebbba7f8 Mon Sep 17 00:00:00 2001 From: Adam Jordens Date: Fri, 23 Feb 2018 21:40:41 -0800 Subject: [PATCH] fix(core): Correctly handle artifact matching with multiple packages This appears to have been broken when the global context was removed. --- .../orca/pipeline/util/PackageInfo.java | 29 +++++++++---- .../orca/pipeline/util/PackageInfoSpec.groovy | 43 ++++++++++++++++++- 2 files changed, 62 insertions(+), 10 deletions(-) diff --git a/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/util/PackageInfo.java b/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/util/PackageInfo.java index 7aa7a93f61..db973f5807 100644 --- a/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/util/PackageInfo.java +++ b/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/util/PackageInfo.java @@ -41,7 +41,7 @@ public class PackageInfo { private final boolean extractBuildDetails; private final boolean extractVersion; private final BuildDetailExtractor buildDetailExtractor; - private final Pattern packageFilePattern; + private final List packageFilePatterns = new ArrayList<>(); public PackageInfo(Stage stage, String packageType, String versionDelimiter, boolean extractBuildDetails, boolean extractVersion, ObjectMapper mapper) { this.stage = stage; @@ -52,7 +52,15 @@ public PackageInfo(Stage stage, String packageType, String versionDelimiter, boo this.mapper = mapper; this.buildDetailExtractor = new BuildDetailExtractor(); - packageFilePattern = Pattern.compile(format("%s.*\\.%s", stage.getContext().get("package"), packageType)); + // can be a space separated set of packages + if (stage.getContext().containsKey("package")) { + String packages = stage.getContext().get("package").toString(); + for (String p : packages.split(" ")) { + packageFilePatterns.add( + Pattern.compile(format("%s.*\\.%s", p, packageType)) + ); + } + } } @VisibleForTesting @@ -73,7 +81,7 @@ public Map findTargetPackage(boolean allowMissingPackageInstalla } if (buildInfo == null || (buildInfo.get("artifacts") != null && !((Collection) buildInfo.get("artifacts")).isEmpty())) { - Map upstreamBuildInfo = findBuildInfoInUpstreamStage(stage, packageFilePattern); + Map upstreamBuildInfo = findBuildInfoInUpstreamStage(stage, packageFilePatterns); if (!upstreamBuildInfo.isEmpty()) { buildInfo = upstreamBuildInfo; } @@ -263,23 +271,28 @@ private Map filterRPMArtifacts(List> artifac .orElse(emptyMap()); } - private static Map findBuildInfoInUpstreamStage(Stage currentStage, Pattern packageFilePattern) { + private static Map findBuildInfoInUpstreamStage(Stage currentStage, + List packageFilePatterns) { Stage upstreamStage = currentStage .ancestors() .stream() .filter(it -> { Map buildInfo = (Map) it.getOutputs().get("buildInfo"); return buildInfo != null && - artifactMatch((List>) buildInfo.get("artifacts"), packageFilePattern); + artifactMatch((List>) buildInfo.get("artifacts"), packageFilePatterns); }) .findFirst() .orElse(null); return upstreamStage != null ? (Map) upstreamStage.getOutputs().get("buildInfo") : emptyMap(); } - private static boolean artifactMatch(List> artifacts, Pattern pattern) { + private static boolean artifactMatch(List> artifacts, List patterns) { return artifacts != null && - artifacts.stream() - .anyMatch((Map artifact) -> pattern.matcher(String.valueOf(artifact.get("fileName"))).matches()); + artifacts + .stream() + .anyMatch((Map artifact) -> patterns + .stream() + .anyMatch(p -> p.matcher(String.valueOf(artifact.get("fileName"))).matches()) + ); } } diff --git a/orca-core/src/test/groovy/com/netflix/spinnaker/orca/pipeline/util/PackageInfoSpec.groovy b/orca-core/src/test/groovy/com/netflix/spinnaker/orca/pipeline/util/PackageInfoSpec.groovy index 4ca72bdb2c..eacca44bbc 100644 --- a/orca-core/src/test/groovy/com/netflix/spinnaker/orca/pipeline/util/PackageInfoSpec.groovy +++ b/orca-core/src/test/groovy/com/netflix/spinnaker/orca/pipeline/util/PackageInfoSpec.groovy @@ -44,7 +44,7 @@ class PackageInfoSpec extends Specification { def artifacts = artifactFilenames.collect { [fileName: it] } expect: - PackageInfo.artifactMatch(artifacts, pattern) == expectedMatch + PackageInfo.artifactMatch(artifacts, [pattern]) == expectedMatch where: artifactPattern || artifactFilenames || expectedMatch @@ -309,7 +309,7 @@ class PackageInfoSpec extends Specification { def pattern = Pattern.compile("api.*") when: - def buildInfo = packageInfo.findBuildInfoInUpstreamStage(bakeStage, pattern) + def buildInfo = packageInfo.findBuildInfoInUpstreamStage(bakeStage, [pattern]) then: noExceptionThrown() @@ -525,4 +525,43 @@ class PackageInfoSpec extends Specification { } ] } + + def "should fetch artifacts from upstream stage when not specified on pipeline trigger"() { + given: + def jenkinsTrigger = new JenkinsTrigger("master", "job", 1, "propertyFile") + jenkinsTrigger.buildInfo = new BuildInfo("name", 0, "url", [], [], false, "result") + + def pipeline = pipeline { + trigger = jenkinsTrigger // has no artifacts! + stage { + refId = "1" + outputs = [ + buildInfo: [ + "artifacts": [ + ["fileName": "spinnaker_0.2.0-114_all.deb"], + ["fileName": "spinnakerdeps_0.1.0-114_all.deb"] + ] + ] + ] + } + stage { + id = "2" + requisiteStageRefIds = ["1"] + + stage { + id = "3" + context = [ + "package": "spinnakerdeps spinnaker" + ] + parentStageId = "2" + } + } + } + + and: + def packageInfo = new PackageInfo(pipeline.stageById("3"), "deb", "_", false, false, new ObjectMapper()) + + expect: + packageInfo.findTargetPackage(false).package == "spinnakerdeps_0.1.0-114_all spinnaker_0.2.0-114_all" + } }