diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 62ab6f4..0eeab95 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -25,7 +25,7 @@ jobs: - "6.5.1" - "6.6.1" - "6.7.1" - - "6.8" + - "6.8.3" runs-on: ubuntu-latest @@ -47,7 +47,7 @@ jobs: run: | echo "GRADLE_PUBLISH_KEY=${{secrets.PUBLISH_KEY}}" >> $GITHUB_ENV echo "GRADLE_PUBLISH_SECRET=${{ secrets.PUBLISH_SECRET }}" >> $GITHUB_ENV - if: startsWith(github.ref, 'refs/tags/v') && matrix.GRADLE_VERSION == '6.8' + if: startsWith(github.ref, 'refs/tags/v') && matrix.GRADLE_VERSION == '6.8.3' - name: Publish run: ./gradlew publishPlugins "-Pgradle.publish.key=${GRADLE_PUBLISH_KEY}" "-Pgradle.publish.secret=${GRADLE_PUBLISH_SECRET}" - if: startsWith(github.ref, 'refs/tags/v') && matrix.GRADLE_VERSION == '6.8' + if: startsWith(github.ref, 'refs/tags/v') && matrix.GRADLE_VERSION == '6.8.3' diff --git a/docs/ccv2-validation.md b/docs/ccv2-validation.md index a0c88c4..8fd900e 100644 --- a/docs/ccv2-validation.md +++ b/docs/ccv2-validation.md @@ -170,6 +170,14 @@ to configure and enable web extensions. - [Manifest Components Reference](https://help.sap.com/viewer/1be46286b36a4aa48205be5a96240672/latest/en-US/3d562b85b37a460a92d32ec991459133.html) +## :red_circle: E-018 Invalid Solr version + +The Solr version in the manifest must be two numbers separated by a dot (`.`). + +### Relevant Documentation + +- [Manifest Components Reference](https://help.sap.com/viewer/1be46286b36a4aa48205be5a96240672/latest/en-US/3d562b85b37a460a92d32ec991459133.html) + ## :warning: W-001 Property `` is a managed property The build process preconfigures certain properties with optimal values for a high-performance cloud @@ -200,5 +208,16 @@ If you use the Cloud Hot Fodlers feature of the Commerce cloud, you also have to - [Enabling and Configuring Hot Folders](https://help.sap.com/viewer/403d43bf9c564f5a985913d1fbfbf8d7/latest/en-US/6e23a26fe9c8472380f9101e8a9fe1c3.html) +## :warning: W-004 Solr customization without pinned Solr version + +If you customize your Solr configuration, it is recommended that you pin the Solr version in your `manifest.json`. + +A SAP Commerce patch release may change the default Solr version, leading to deployment errors if your customization is not +compatible with the new Solr version. + +### Relevant Documentation + +- [Solr Server Version Selection](https://help.sap.com/viewer/1be46286b36a4aa48205be5a96240672/latest/en-US/b35bc14a62aa4950bdba451a5f40fc61.html#loiod7294323e5e542b7b37f48dd83565321) + [aspects]: https://help.sap.com/viewer/1be46286b36a4aa48205be5a96240672/latest/en-US/8f494fb9617346188ddf21a971db84fc.htm [reuse]: https://help.sap.com/viewer/1be46286b36a4aa48205be5a96240672/latest/en-US/2311d89eef9344fc81ef168ac9668307.html diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index da9702f..442d913 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.8-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/src/integrationTest/groovy/mpern/sap/commerce/ccv2/validation/SolrVersionValidatorSpec.groovy b/src/integrationTest/groovy/mpern/sap/commerce/ccv2/validation/SolrVersionValidatorSpec.groovy new file mode 100644 index 0000000..ff98300 --- /dev/null +++ b/src/integrationTest/groovy/mpern/sap/commerce/ccv2/validation/SolrVersionValidatorSpec.groovy @@ -0,0 +1,28 @@ +package mpern.sap.commerce.ccv2.validation + +import groovy.json.JsonSlurper +import spock.lang.Specification + +import mpern.sap.commerce.ccv2.model.Manifest +import mpern.sap.commerce.ccv2.validation.impl.SolrVersionValidator + +class SolrVersionValidatorSpec extends Specification { + def "solrVersion version must a valid Solr major.minor version"() { + given: + def rawManifest = new JsonSlurper().parseText(''' + { + "commerceSuiteVersion": "2011", + "solrVersion": "8.6.3" + } + ''') as Map + Manifest manifest = Manifest.fromMap(rawManifest) + def validator = new SolrVersionValidator(); + + when: + def faultySolr = validator.validate(manifest) + + then: + faultySolr.size() == 1 + faultySolr.any{ it.location == "solrVersion" && it.level == Level.ERROR } + } +} diff --git a/src/integrationTest/groovy/mpern/sap/commerce/ccv2/validation/UseConfigValidatorSpec.groovy b/src/integrationTest/groovy/mpern/sap/commerce/ccv2/validation/UseConfigValidatorSpec.groovy index 43bd104..91e201d 100644 --- a/src/integrationTest/groovy/mpern/sap/commerce/ccv2/validation/UseConfigValidatorSpec.groovy +++ b/src/integrationTest/groovy/mpern/sap/commerce/ccv2/validation/UseConfigValidatorSpec.groovy @@ -211,17 +211,30 @@ class UseConfigValidatorSpec extends Specification { } } ''') as Map - Manifest manifest = Manifest.fromMap(rawManifest) + Manifest manifestWithoutVersion = Manifest.fromMap(rawManifest) testProjectDir.newFolder("solr") + rawManifest = new JsonSlurper().parseText(''' + { + "commerceSuiteVersion": "2011", + "solrVersion": "8.6", + "useConfig": { + "solr": { + "location": "solr" + } + } + } + ''') as Map + Manifest manifestWithVersion = Manifest.fromMap(rawManifest) when: - def missingFolder = validator.validate(manifest) + def missingFolder = validator.validate(manifestWithoutVersion) testProjectDir.newFolder("solr", "server", "solr", "configsets", "default", "conf") - def folderExists = validator.validate(manifest) + def folderExists = validator.validate(manifestWithVersion) then: - missingFolder.size() == 1 + missingFolder.size() == 2 missingFolder.any{ it.location == "useConfig.solr.location" && it.message.contains("server/solr/configsets/default/conf")} + missingFolder.any{ it.location == "solrVersion" && it.level == Level.WARNING} folderExists.isEmpty() } } diff --git a/src/main/java/mpern/sap/commerce/ccv2/model/Manifest.java b/src/main/java/mpern/sap/commerce/ccv2/model/Manifest.java index 5797d76..d2f4418 100644 --- a/src/main/java/mpern/sap/commerce/ccv2/model/Manifest.java +++ b/src/main/java/mpern/sap/commerce/ccv2/model/Manifest.java @@ -7,6 +7,7 @@ public class Manifest { public final String commerceSuiteVersion; + public final String solrVersion; public final boolean useCloudExtensionPack; public final boolean enableImageProcessingService; @@ -29,11 +30,13 @@ public class Manifest { public final TestConfiguration webTests; - public Manifest(String commerceSuiteVersion, boolean useCloudExtensionPack, boolean enableImageProcessingService, - boolean troubleshootingModeEnabled, boolean disableImageReuse, UseConfig useConfig, - List extensionPacks, Set extensions, List storefrontAddons, - List properties, List aspects, TestConfiguration tests, TestConfiguration webTests) { + public Manifest(String commerceSuiteVersion, String solrVersion, boolean useCloudExtensionPack, + boolean enableImageProcessingService, boolean troubleshootingModeEnabled, boolean disableImageReuse, + UseConfig useConfig, List extensionPacks, Set extensions, + List storefrontAddons, List properties, List aspects, TestConfiguration tests, + TestConfiguration webTests) { this.commerceSuiteVersion = commerceSuiteVersion; + this.solrVersion = solrVersion; this.useCloudExtensionPack = useCloudExtensionPack; this.enableImageProcessingService = enableImageProcessingService; this.troubleshootingModeEnabled = troubleshootingModeEnabled; @@ -52,6 +55,11 @@ public static Manifest fromMap(Map jsonMap) { String version = validateNullOrWhitespace((String) jsonMap.get("commerceSuiteVersion"), "Manifest.commerceSuiteVersion must have a value"); + String solrVersion = (String) jsonMap.get("solrVersion"); + if (solrVersion == null) { + solrVersion = ""; + } + Object rawBool = jsonMap.get("useCloudExtensionPack"); boolean useExtensionPack = parseBoolean(rawBool, "useCloudExtensionPack"); @@ -108,8 +116,9 @@ public static Manifest fromMap(Map jsonMap) { TestConfiguration webTests = Optional.ofNullable(rawConfig).map(TestConfiguration::fromMap) .orElse(TestConfiguration.NO_VALUE); - return new Manifest(version, useExtensionPack, enableImageProcessingService, troubleshootingModeEnabled, - disableImageReuse, useConfig, extensionPacks, extensions, addons, properties, aspects, tests, webTests); + return new Manifest(version, solrVersion, useExtensionPack, enableImageProcessingService, + troubleshootingModeEnabled, disableImageReuse, useConfig, extensionPacks, extensions, addons, + properties, aspects, tests, webTests); } // necessary to shadow groovy method getProperties diff --git a/src/main/java/mpern/sap/commerce/ccv2/tasks/ValidateManifest.java b/src/main/java/mpern/sap/commerce/ccv2/tasks/ValidateManifest.java index db11b66..f0df726 100644 --- a/src/main/java/mpern/sap/commerce/ccv2/tasks/ValidateManifest.java +++ b/src/main/java/mpern/sap/commerce/ccv2/tasks/ValidateManifest.java @@ -44,6 +44,7 @@ public void validateManifest() throws Exception { validators.add(new CloudHotfolderValidator(projectDir, resolver)); validators.add(new MediaConversionValidator(resolver)); validators.add(new WebrootValidator(projectDir)); + validators.add(new SolrVersionValidator()); boolean deepInspection = false; if (Files.exists(projectDir.resolve("hybris/bin/platform"))) { deepInspection = true; diff --git a/src/main/java/mpern/sap/commerce/ccv2/validation/impl/SolrVersionValidator.java b/src/main/java/mpern/sap/commerce/ccv2/validation/impl/SolrVersionValidator.java new file mode 100644 index 0000000..fcac1eb --- /dev/null +++ b/src/main/java/mpern/sap/commerce/ccv2/validation/impl/SolrVersionValidator.java @@ -0,0 +1,26 @@ +package mpern.sap.commerce.ccv2.validation.impl; + +import java.util.Collections; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import mpern.sap.commerce.ccv2.model.Manifest; +import mpern.sap.commerce.ccv2.validation.Error; +import mpern.sap.commerce.ccv2.validation.Validator; + +public class SolrVersionValidator implements Validator { + private static final Pattern SOLR_VERSION = Pattern.compile("^\\d+\\.\\d+$"); + + @Override + public List validate(Manifest manifest) throws Exception { + if (!manifest.solrVersion.isEmpty()) { + final Matcher matcher = SOLR_VERSION.matcher(manifest.solrVersion); + if (!matcher.matches()) { + return Collections.singletonList(new Error.Builder().setLocation("solrVersion").setCode("E-018") + .setMessage("Invalid Solr version").createError()); + } + } + return Collections.emptyList(); + } +} diff --git a/src/main/java/mpern/sap/commerce/ccv2/validation/impl/UseConfigValidator.java b/src/main/java/mpern/sap/commerce/ccv2/validation/impl/UseConfigValidator.java index 2418ed7..ccec0e3 100644 --- a/src/main/java/mpern/sap/commerce/ccv2/validation/impl/UseConfigValidator.java +++ b/src/main/java/mpern/sap/commerce/ccv2/validation/impl/UseConfigValidator.java @@ -146,6 +146,11 @@ private List validateSolr(Manifest manifest) { "Location `%s` does not contain the required folder structure `server/solr/configsets/default/conf`", solrCustom).setCode("E-013").createError()); } + if (manifest.solrVersion.isEmpty()) { + errors.add(new Error.Builder().setLocation("solrVersion").setLevel(Level.WARNING).setMessage( + "Solr customization without pinned Solr version.\nThis may lead to unexpected build errors if a patch releases changes the Solr version.") + .setCode("W-004").createError()); + } } } return errors;