diff --git a/.travis.yml b/.travis.yml
index ac88aecdd8..aa9361e777 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -15,10 +15,10 @@ php:
- '7.1'
- '7.2'
- '7.3'
+ - '7.4'
env:
- TEST_SUITE=functional-ce
- - TEST_SUITE=functional-ee
- TEST_SUITE=functional-ee FUNCTIONAL_INDEX=1
- TEST_SUITE=functional-ee FUNCTIONAL_INDEX=2
- TEST_SUITE=functional-ee FUNCTIONAL_INDEX=3
@@ -32,17 +32,7 @@ stages:
jobs:
exclude:
- php: '7.1'
- env: TEST_SUITE=functional-ee FUNCTIONAL_INDEX=1
- - php: '7.1'
- env: TEST_SUITE=functional-ee FUNCTIONAL_INDEX=2
- - php: '7.1'
- env: TEST_SUITE=functional-ee FUNCTIONAL_INDEX=3
- - php: '7.1'
- env: TEST_SUITE=functional-ee FUNCTIONAL_INDEX=4
- - php: '7.1'
- env: TEST_SUITE=functional-ee FUNCTIONAL_INDEX=5
- - php: '7.1'
- env: TEST_SUITE=functional-ee FUNCTIONAL_INDEX=6
+ env: TEST_SUITE=functional-ee
- php: '7.2'
env: TEST_SUITE=functional-ee
@@ -50,12 +40,16 @@ jobs:
- php: '7.3'
env: TEST_SUITE=functional-ee
+ - php: '7.4'
+ env: TEST_SUITE=functional-ee
+
install:
- composer config http-basic.repo.magento.com ${REPO_USERNAME_CE} ${REPO_PASSWORD_CE}
- composer config github-oauth.github.com ${GITHUB_TOKEN}
- if [ -n "${MCC_VERSION}" ]; then composer config repositories.mcc git git@github.com:magento/magento-cloud-components.git && composer require "magento/magento-cloud-components:${MCC_VERSION}" --no-update; fi;
- if [ -n "${MCD_VERSION}" ]; then composer config repositories.mcd git git@github.com:magento/magento-cloud-docker.git && composer require "magento/magento-cloud-docker:${MCD_VERSION}" --no-update; fi;
- if [ -n "${MCP_VERSION}" ]; then composer config repositories.mcp git git@github.com:magento/magento-cloud-patches.git && composer require "magento/magento-cloud-patches:${MCP_VERSION}" --no-update; fi;
+ - if [ -n "${MQP_VERSION}" ]; then composer config repositories.mqp git git@github.com:magento/quality-patches.git && composer require "magento/quality-patches:${MQP_VERSION}" --no-update; fi;
- composer update -n --no-suggest
before_script:
diff --git a/codeception.dist.yml b/codeception.dist.yml
index 710cb3498a..2badeb2381 100644
--- a/codeception.dist.yml
+++ b/codeception.dist.yml
@@ -20,6 +20,7 @@ modules:
mcd_repo: "https://github.com/magento/magento-cloud-docker.git"
mcc_repo: "https://github.com/magento/magento-cloud-components.git"
mcp_repo: "https://github.com/magento/magento-cloud-patches.git"
+ mqp_repo: "https://github.com/magento/quality-patches.git"
composer_magento_username: "%REPO_USERNAME%"
composer_magento_password: "%REPO_PASSWORD%"
composer_github_token: "%GITHUB_TOKEN%"
diff --git a/composer.json b/composer.json
index 87edd1f136..fd950ee5f0 100755
--- a/composer.json
+++ b/composer.json
@@ -2,7 +2,7 @@
"name": "magento/ece-tools",
"description": "Provides tools to build and deploy Magento 2 Enterprise Edition",
"type": "magento2-component",
- "version": "2002.1.1",
+ "version": "2002.1.2",
"license": "OSL-3.0",
"repositories": {
"repo.magento.com": {
@@ -21,9 +21,9 @@
"graylog2/gelf-php": "^1.4.2",
"guzzlehttp/guzzle": "^6.2",
"illuminate/config": "^5.5",
- "magento/magento-cloud-components": "^1.0.1",
+ "magento/magento-cloud-components": "^1.0.6",
"magento/magento-cloud-docker": "^1.0.0",
- "magento/magento-cloud-patches": "^1.0.0",
+ "magento/magento-cloud-patches": "^1.0.6",
"monolog/monolog": "^1.16",
"nesbot/carbon": "^1.0||^2.0",
"psr/container": "^1.0",
diff --git a/config/schema.error.yaml b/config/schema.error.yaml
new file mode 100644
index 0000000000..137685c180
--- /dev/null
+++ b/config/schema.error.yaml
@@ -0,0 +1,604 @@
+!php/const Magento\MagentoCloud\App\Error::BUILD_ENV_PHP_IS_NOT_WRITABLE:
+ title: 'Cannot write to the `./app/etc/env.php` file'
+ suggestion: 'Deployment script cannot make required changes to the `/app/etc/env.php` file. Check your filesystem permissions.'
+ stage: build
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::BUILD_CONFIG_NOT_DEFINED:
+ title: 'Configuration isn''t defined in the `schema.yaml` file'
+ suggestion: 'Configuration is not defined in the `./vendor/magento/ece-tools/config/schema.yaml` file. Check that the config variable name is correct, and that it is defined.'
+ stage: build
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::BUILD_CONFIG_PARSE_FAILED:
+ title: 'Failed to parse the `.magento.env.yaml` file'
+ suggestion: 'The `./.magento.env.yaml` file format is invalid. Use a YAML parser to check the syntax and fix any errors.'
+ stage: build
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::BUILD_CONFIG_UNABLE_TO_READ:
+ title: 'Unable to read the `.magento.env.yaml` file'
+ suggestion: 'Unable to read the `./.magento.env.yaml` file. Check file permissions.'
+ stage: build
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::BUILD_CONFIG_UNABLE_TO_READ_SCHEMA_YAML:
+ title: 'Unable to read the `.schema.yaml` file'
+ suggestion: 'Unable to read the `./vendor/magento/ece-tools/config/magento.env.yaml` file. Check file permissions and redeploy (`magento-cloud environment:redeploy`).'
+ stage: build
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::BUILD_CONFIG_PHP_IS_NOT_WRITABLE:
+ step: refresh-modules
+ title: 'Cannot write to the `./app/etc/config.php` file'
+ suggestion: 'The deployment script cannot make required changes to the `/app/etc/config.php` file. Check your filesystem permissions.'
+ stage: build
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::BUILD_CANT_READ_COMPOSER_JSON:
+ step: validate-config
+ title: 'Cannot read the `composer.json` file'
+ suggestion: 'Unable to read the `./composer.json` file. Check file permissions.'
+ stage: build
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::BUILD_COMPOSER_MISSED_REQUIRED_AUTOLOAD:
+ step: validate-config
+ title: 'Composer.json is missing required autoload section'
+ suggestion: 'Required `autoload` section is missing from the `composer.json` file. Compare the autoload section to the `composer.json` file in the Magento Cloud template, and add the missing configuration.'
+ stage: build
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::BUILD_WRONG_CONFIGURATION_MAGENTO_ENV_YAML:
+ step: validate-config
+ title: 'The file `.magento.env.yaml` contains an option that is not declared in the schema, or an option configured with an invalid value or stage'
+ suggestion: 'The `./.magento.env.yaml` file contains invalid configuration. Check the error log for detailed info.'
+ stage: build
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::BUILD_MODULE_ENABLE_COMMAND_FAILED:
+ step: refresh-modules
+ title: 'Command failed: `/bin/magento module:enable --all`'
+ suggestion: 'Try to run `composer update` locally. Then, commit and push the updated `composer.lock` file. Also check the `cloud.log` for more information. For more detailed command output, add the `VERBOSE_COMMANDS: ''-vvv''` option to the `.magento.env.yaml` file.'
+ stage: build
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::BUILD_PATCH_APPLYING_FAILED:
+ step: apply-patches
+ title: 'Failed to apply patch'
+ suggestion: ''
+ stage: build
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::BUILD_FILE_LOCAL_XML_IS_NOT_WRITABLE:
+ step: set-report-dir-nesting-level
+ title: 'Cannot write to the file `/pub/errors/local.xml`'
+ suggestion: ''
+ stage: build
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::BUILD_FAILED_COPY_SAMPLE_DATA:
+ step: copy-sample-data
+ title: 'Failed to copy sample data files'
+ suggestion: ''
+ stage: build
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::BUILD_DI_COMPILATION_FAILED:
+ step: compile-di
+ title: 'Command failed: `/bin/magento setup:di:compile`'
+ suggestion: 'Check the `cloud.log` for more information. Add `VERBOSE_COMMANDS: ''-vvv''` into `.magento.env.yaml` for more detailed command output.'
+ stage: build
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::BUILD_COMPOSER_DUMP_AUTOLOAD_FAILED:
+ step: dump-autoload
+ title: 'Command failed: `composer dump-autoload`'
+ suggestion: 'The `composer dump-autoload` command failed. Check the `cloud.log` for more information.'
+ stage: build
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::BUILD_BALER_NOT_FOUND:
+ step: run-baler
+ title: 'The command to run `Baler` for Javascript bundling failed'
+ suggestion: 'Check the `SCD_USE_BALER` environment variable to verify that the Baler module is configured and enabled for JS bundling. If you do not need the Baler module, set `SCD_USE_BALER: false`.'
+ stage: build
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::BUILD_UTILITY_NOT_FOUND:
+ step: compress-static-content
+ title: 'Required utility wasn''t found (timeout, bash)'
+ suggestion: ''
+ stage: build
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::BUILD_SCD_FAILED:
+ step: deploy-static-content
+ title: 'Command `/bin/magento setup:static-content:deploy` failed'
+ suggestion: 'Check the `cloud.log` for more information. For more detailed command output, add the `VERBOSE_COMMANDS: ''-vvv''` option to the `.magento.env.yaml` file.'
+ stage: build
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::BUILD_SCD_COMPRESSION_FAILED:
+ step: compress-static-content
+ title: 'Static content compression failed'
+ suggestion: 'Check the `cloud.log` for more information.'
+ stage: build
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::BUILD_SCD_COPYING_FAILED:
+ step: 'backup-data: static-content'
+ title: 'Failed to copy static content into the `init` directory'
+ suggestion: 'Check the `cloud.log` for more information.'
+ stage: build
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::BUILD_WRITABLE_DIRECTORY_COPYING_FAILED:
+ step: 'backup-data: writable-dirs'
+ title: 'Failed to copy some writable directories into the `init` directory'
+ suggestion: 'Failed to copy writable directories into the `./init` folder. Check your filesystem permissions.'
+ stage: build
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::BUILD_UNABLE_TO_CREATE_LOGGER:
+ title: 'Unable to create a logger object'
+ suggestion: ''
+ stage: build
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::BUILD_CLEAN_INIT_PUB_STATIC_FAILED:
+ step: 'backup-data: static-content'
+ title: 'Failed to clean the `./init/pub/static/` directory'
+ suggestion: 'Failed to clean `./init/pub/static` folder. Check your filesystem permissions.'
+ stage: build
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::BUILD_COMPOSER_PACKAGE_NOT_FOUND:
+ title: 'Cannot find the Composer package'
+ suggestion: 'If you installed the Magento application version directly from the Magento git repository, verify that the `DEPLOYED_MAGENTO_VERSION_FROM_GIT` environment variable is configured.'
+ stage: build
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::BUILD_WRONG_BRAINTREE_VARIABLE:
+ step: validate-config
+ title: 'Remove Magento Braintree module configuration which is no longer supported in Magento 2.4 and later versions.'
+ suggestion: 'Support for the Braintree module is no longer included with Magento 2.4.0 and later. Remove the CONFIG__STORES__DEFAULT__PAYMENT__BRAINTREE__CHANNEL variable from the variables section of the .magento.app.yaml file. For Braintree payment support, use an official extension from the Magento Marketplace instead.'
+ stage: build
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::DEPLOY_WRONG_CACHE_CONFIGURATION:
+ step: 'pre-deploy: cache'
+ title: 'Incorrect cache configuration (missing port or host)'
+ suggestion: 'Cache configuration is missing required parameters `server` or `port`. Check the `cloud.log` for more information.'
+ stage: deploy
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::DEPLOY_ENV_PHP_IS_NOT_WRITABLE:
+ title: 'Cannot write to the `./app/etc/env.php` file'
+ suggestion: 'Deployment script cannot make required changes to the `/app/etc/env.php` file. Check your filesystem permissions.'
+ stage: deploy
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::DEPLOY_CONFIG_NOT_DEFINED:
+ title: 'Configuration isn''t defined in the `schema.yaml` file'
+ suggestion: 'Configuration is not defined in the `./vendor/magento/ece-tools/config/schema.yaml` file. Check that the config variable name is correct, and that it is defined.'
+ stage: deploy
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::DEPLOY_CONFIG_PARSE_FAILED:
+ title: 'Failed to parse the `.magento.env.yaml` file'
+ suggestion: 'Configuration is not defined in the `./vendor/magento/ece-tools/config/schema.yaml` file. Check that the config variable name is correct, and that it is defined.'
+ stage: deploy
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::DEPLOY_CONFIG_UNABLE_TO_READ:
+ title: 'Unable to read the `.magento.env.yaml` file'
+ suggestion: 'Unable to read the `./.magento.env.yaml` file. Check file permissions.'
+ stage: deploy
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::DEPLOY_CONFIG_UNABLE_TO_READ_SCHEMA_YAML:
+ title: 'Unable to read the `.schema.yaml` file'
+ suggestion: ''
+ stage: deploy
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::DEPLOY_REDIS_CACHE_CLEAN_FAILED:
+ title: 'Failed to clean the Redis cache'
+ suggestion: 'Failed to clean the Redis cache. Check that the Redis cache configuration is correct and that the Redis service is available. See [Setup Redis service](https://devdocs.magento.com/cloud/project/project-conf-files_services-redis.html).'
+ step: 'pre-deploy: clean-redis-cache'
+ stage: deploy
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::DEPLOY_MAINTENANCE_MODE_ENABLING_FAILED:
+ step: 'pre-deploy: set-production-mode'
+ title: 'Command `/bin/magento maintenance:enable` failed'
+ suggestion: 'Check the `cloud.log` for more information. For more detailed command output, add the `VERBOSE_COMMANDS: ''-vvv''` option to the `.magento.env.yaml` file.'
+ stage: deploy
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::DEPLOY_WRONG_CONFIGURATION_DB:
+ step: validate-config
+ title: 'Incorrect database configuration'
+ suggestion: 'Check that the the `DATABASE_CONFIGURATION` environment variable is configured correctly.'
+ stage: deploy
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::DEPLOY_WRONG_CONFIGURATION_SESSION:
+ step: validate-config
+ title: 'Incorrect session configuration'
+ suggestion: 'Check that the `SESSION_CONFIGURATION` environment variable is configured correctly. The configuration must contain at least the `save` parameter.'
+ stage: deploy
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::DEPLOY_WRONG_CONFIGURATION_SEARCH:
+ step: validate-config
+ title: 'Incorrect search configuration'
+ suggestion: 'Check that the `SEARCH_CONFIGURATION` environment variable is configured correctly. The configuration must contain at least the `engine` parameter.'
+ stage: deploy
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::DEPLOY_WRONG_CONFIGURATION_RESOURCE:
+ step: validate-config
+ title: 'Incorrect resource configuration'
+ suggestion: 'Check that the `RESOURCE_CONFIGURATION` environment variable is configured correctly. The configuration must contain at least `connection` parameter.'
+ stage: deploy
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::DEPLOY_ELASTIC_SUITE_WITHOUT_ES:
+ step: 'validate-config:elasticsuite-integrity'
+ title: 'ElasticSuite is installed, but the ElasticSearch service is not available'
+ suggestion: 'Check that the `SEARCH_CONFIGURATION` environment variable is configured correctly, and verify that the Elasticsearch service is available.'
+ stage: deploy
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::DEPLOY_ELASTIC_SUITE_WRONG_ENGINE:
+ step: 'validate-config:elasticsuite-integrity'
+ title: 'ElasticSuite is installed, but another search engine is used'
+ suggestion: 'ElasticSuite is installed, but another search engine is configured. Update the `SEARCH_CONFIGURATION` environment variable to enable Elasticsearch, and verify the Elasticsearch service configuration in the `services.yaml` file.'
+ stage: deploy
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::DEPLOY_QUERY_EXECUTION_FAILED:
+ title: 'Database query execution failed'
+ suggestion: ''
+ stage: deploy
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::DEPLOY_INSTALL_COMMAND_FAILED:
+ step: 'install-update: setup'
+ title: 'Command `/bin/magento setup:install` failed'
+ suggestion: 'Check the `cloud.log` and `install_upgrade.log` for more information. For more detailed command output, add the `VERBOSE_COMMANDS: ''-vvv''` option to the `.magento.env.yaml` file.'
+ stage: deploy
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::DEPLOY_CONFIG_IMPORT_COMMAND_FAILED:
+ step: 'install-update: config-import'
+ title: 'Command `app:config:import` failed'
+ suggestion: 'Check the `cloud.log` for more information. For more detailed command output, add the `VERBOSE_COMMANDS: ''-vvv''` option to the `.magento.env.yaml` file.'
+ stage: deploy
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::DEPLOY_UTILITY_NOT_FOUND:
+ title: 'Required utility wasn''t found (timeout, bash)'
+ suggestion: ''
+ stage: deploy
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::DEPLOY_SCD_FAILED:
+ step: 'install-update: deploy-static-content'
+ title: 'Command `/bin/magento setup:static-content:deploy` failed'
+ suggestion: 'Check the `cloud.log` for more information. For more detailed command output, add the `VERBOSE_COMMANDS: ''-vvv''` option to the `.magento.env.yaml` file.'
+ stage: deploy
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::DEPLOY_SCD_COMPRESSION_FAILED:
+ step: compress-static-content
+ title: 'Static content compression failed'
+ suggestion: 'Check the `cloud.log` for more information.'
+ stage: deploy
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::DEPLOY_SCD_CANNOT_UPDATE_VERSION:
+ step: 'deploy-static-content:generate'
+ title: 'Cannot update the deployed version'
+ suggestion: 'Cannot update the `./pub/static/deployed_version.txt` file. Check your filesystem permissions.'
+ stage: deploy
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::DEPLOY_SCD_CLEAN_FAILED:
+ step: clean-static-content
+ title: 'Failed to clean static content files'
+ suggestion: ''
+ stage: deploy
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::DEPLOY_SPLIT_DB_COMMAND_FAILED:
+ step: 'install-update: split-db'
+ title: 'Command `/bin/magento setup:db-schema:split` failed'
+ suggestion: 'Check the `cloud.log` for more information. For more detailed command output, add the `VERBOSE_COMMANDS: ''-vvv''` option to the `.magento.env.yaml` file.'
+ stage: deploy
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::DEPLOY_VIEW_PREPROCESSED_CLEAN_FAILED:
+ step: clean-view-preprocessed
+ title: 'Failed to clean the `var/view_preprocessed` folder'
+ suggestion: 'Unable to clean the `./var/view_preprocessed` folder. Check your filesystem permissions.'
+ stage: deploy
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::DEPLOY_FILE_CREDENTIALS_EMAIL_NOT_WRITABLE:
+ step: 'install-update: reset-password'
+ title: 'Failed to update the `/var/credentials_email.txt` file'
+ suggestion: 'Failed to update the `/var/credentials_email.txt` file. Check your filesystem permissions.'
+ stage: deploy
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::DEPLOY_UPGRADE_COMMAND_FAILED:
+ step: 'install-update: update'
+ title: 'Command `/bin/magento setup:upgrade` failed'
+ suggestion: 'Check the `cloud.log` and `install_upgrade.log` for more information. For more detailed command output, add the `VERBOSE_COMMANDS: ''-vvv''` option to the `.magento.env.yaml` file.'
+ stage: deploy
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::DEPLOY_CACHE_FLUSH_COMMAND_FAILED:
+ step: clean-cache
+ title: 'Command `/bin/magento cache:flush` failed'
+ suggestion: 'Check the `cloud.log` for more information. For more detailed command output, add the `VERBOSE_COMMANDS: ''-vvv''` option to the `.magento.env.yaml` file.'
+ stage: deploy
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::DEPLOY_MAINTENANCE_MODE_DISABLING_FAILED:
+ step: disable-maintenance-mode
+ title: 'Command `/bin/magento maintenance:disable` failed'
+ suggestion: 'Check the `cloud.log` for more information. Add `VERBOSE_COMMANDS: ''-vvv''` into `.magento.env.yaml` for more detailed command output.'
+ stage: deploy
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::DEPLOY_UNABLE_TO_READ_RESET_PASSWORD_TMPL:
+ step: 'install-update: reset-password'
+ title: 'Unable to read reset password template'
+ suggestion: ''
+ stage: deploy
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::DEPLOY_CACHE_ENABLE_FAILED:
+ step: 'install-update: cache_type'
+ title: 'Command failed: `php ./bin/magento cache:enable`'
+ suggestion: 'Command `php ./bin/magento cache:enable` runs only when Magento was installed but `./app/etc/env.php` file was absent or empty at the beginning of the deployment. Check the `cloud.log` for more information. Add `VERBOSE_COMMANDS: ''-vvv''` into `.magento.env.yaml` for more detailed command output.'
+ stage: deploy
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::DEPLOY_CRYPT_KEY_IS_ABSENT:
+ step: install-update
+ title: 'The `crypt/key` key value does not exist in the `./app/etc/env.php` file or the `CRYPT_KEY` cloud environment variable'
+ suggestion: "This error occurs if the `./app/etc/env.php` file is not present when Magento deployment begins, or if the `crypt/key` value is undefined. If you migrated the database from another environment, retrieve the crypt key value from that environment. Then, add the value to the [CRYPT_KEY](https://devdocs.magento.com/cloud/env/variables-deploy.html#crypt_key) cloud environment variable in your current environment. See [Add the Magento encryption key](https://devdocs.magento.com/cloud/setup/first-time-setup-import-import.html#encryption-key). If you accidentally removed the `./app/etc/env.php` file, use the following command to restore it from the backup files created from a previous deployment: `./vendor/bin/ece-tools backup:restore` CLI command .\""
+ stage: deploy
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::DEPLOY_ES_CANNOT_CONNECT:
+ title: 'Can not connect to the Elasticsearch service'
+ suggestion: 'Check that credentials for elasticsearch are correct and service is running'
+ stage: deploy
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::DEPLOY_WRONG_BRAINTREE_VARIABLE:
+ step: validate-config
+ title: 'Remove Magento Braintree module configuration which is no longer supported in Magento 2.4 and later versions.'
+ suggestion: 'Support for the Braintree module is no longer included with Magento 2.4.0 and later. Remove the CONFIG__STORES__DEFAULT__PAYMENT__BRAINTREE__CHANNEL variable from the variables section of the .magento.app.yaml file. For Braintree support, use an official Braintree Payments extension from the Magento Marketplace instead.'
+ stage: deploy
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::DEPLOY_WRONG_SEARCH_ENGINE:
+ step: validate-config
+ title: 'Magento 2.4.0 requires Elasticsearch service to be installed'
+ suggestion: 'Install Elasticsearch service'
+ stage: deploy
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::PD_DEPLOY_IS_FAILED:
+ step: is-deploy-failed
+ title: 'Deploy stage failed'
+ suggestion: ''
+ stage: post-deploy
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::PD_ENV_PHP_IS_NOT_WRITABLE:
+ title: 'The `./app/etc/env.php` file is not writable'
+ suggestion: 'Deployment script cannot make required changes to the `/app/etc/env.php` file. Check your filesystem permissions.'
+ stage: post-deploy
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::PD_CONFIG_NOT_DEFINED:
+ title: 'Configuration isn''t defined in the `schema.yaml` file'
+ suggestion: 'Configuration is not defined in the `./vendor/magento/ece-tools/config/schema.yaml` file. Check that the config variable name is correct, and that it is defined.'
+ stage: post-deploy
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::PD_CONFIG_PARSE_FAILED:
+ title: 'Failed to parse the `.magento.env.yaml` file'
+ suggestion: 'The `./.magento.env.yaml` file format is invalid. Use a YAML parser to check the syntax and fix any errors.'
+ stage: post-deploy
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::PD_CONFIG_UNABLE_TO_READ:
+ title: 'Unable to read the `.magento.env.yaml` file'
+ suggestion: 'Check file permissions.'
+ stage: post-deploy
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::PD_CONFIG_UNABLE_TO_READ_SCHEMA_YAML:
+ title: 'Unable to read the `.schema.yaml` file'
+ suggestion: ''
+ stage: post-deploy
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::PD_DURING_PAGE_WARM_UP:
+ step: warm-up
+ title: 'Failed to warm-up some pages'
+ suggestion: ''
+ stage: post-deploy
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::PD_DURING_TIME_TO_FIRST_BYTE:
+ step: time-to-firs-byte
+ title: 'Failed to test time to first byte (TTFB)'
+ suggestion: ''
+ stage: post-deploy
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::PD_CACHE_FLUSH_COMMAND_FAILED:
+ step: clean-cache
+ title: 'Command `/bin/magento cache:flush` failed'
+ suggestion: 'Check the `cloud.log` for more information. Add `VERBOSE_COMMANDS: ''-vvv''` into `.magento.env.yaml` for more detailed command output.'
+ stage: post-deploy
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::GLOBAL_CONFIG_NOT_DEFINED:
+ title: 'Configuration is not defined in the `schema.yaml` file'
+ suggestion: 'Check that the config variable name is correct, and that it defined.'
+ stage: general
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::GLOBAL_CONFIG_PARSE_FAILED:
+ title: 'Failed to parse the `.magento.env.yaml` file'
+ suggestion: 'The `./.magento.env.yaml` file format is invalid. Use a YAML parser to check the syntax and fix any errors.'
+ stage: general
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::GLOBAL_CONFIG_UNABLE_TO_READ:
+ title: 'Unable to read the `.magento.env.yaml` file'
+ suggestion: 'Unable to read the `./.magento.env.yaml` file. Check file permissions.'
+ stage: general
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::GLOBAL_CONFIG_UNABLE_TO_READ_SCHEMA_YAML:
+ title: 'Unable to read the `.schema.yaml` file'
+ suggestion: ''
+ stage: general
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::WARN_CONFIG_PHP_NOT_EXISTS:
+ title: 'File app/etc/config.php does not exist'
+ stage: build
+ step: validate-config
+ type: warning
+!php/const Magento\MagentoCloud\App\Error::WARN_UNSUPPORTED_BUILDS_OPTION_INI:
+ title: 'The ./build_options.ini file is no longer supported'
+ stage: build
+ step: validate-config
+ type: warning
+!php/const Magento\MagentoCloud\App\Error::WARN_MISSED_MODULE_SECTION:
+ title: 'The modules section is missing from the shared config file'
+ stage: build
+ step: validate-config
+ type: warning
+!php/const Magento\MagentoCloud\App\Error::WARN_CONFIGURATION_VERSION_MISMATCH:
+ title: 'The configuration is not compatible with this version of Magento'
+ stage: build
+ step: validate-config
+ type: warning
+!php/const Magento\MagentoCloud\App\Error::WARN_SCD_OPTIONS_IGNORANCE:
+ title: 'SCD options ignored'
+ stage: build
+ step: validate-config
+ type: warning
+!php/const Magento\MagentoCloud\App\Error::WARN_CONFIGURATION_STATE_NOT_IDEAL:
+ title: 'The configured state is not ideal'
+ stage: build
+ step: validate-config
+ type: warning
+!php/const Magento\MagentoCloud\App\Error::WARN_BALER_CANNOT_BE_USED:
+ title: 'Baler JS bundling cannot be used'
+ stage: build
+ step: run-baler
+ type: warning
+!php/const Magento\MagentoCloud\App\Error::WARN_REDIS_SERVICE_NOT_AVAILABLE:
+ title: 'Cache is configured for a Redis service that is not available. Configuration will be ignored.'
+ stage: deploy
+ step: 'pre-deploy:cache'
+ type: warning
+!php/const Magento\MagentoCloud\App\Error::WARN_WRONG_SPLIT_DB_CONFIG:
+ title: 'The configured state is not ideal'
+ stage: deploy
+ step: validate-config
+ type: warning
+!php/const Magento\MagentoCloud\App\Error::WARN_DIR_NESTING_LEVEL_NOT_CONFIGURED:
+ title: 'The directory nesting level value for error reporting has not been configured'
+ stage: deploy
+ step: validate-config
+ type: warning
+!php/const Magento\MagentoCloud\App\Error::WARN_NOT_CORRECT_LOCAL_XML_FILE:
+ title: 'Invalid configuration in the ./pub/errors/local.xml file.'
+ stage: deploy
+ step: validate-config
+ type: warning
+!php/const Magento\MagentoCloud\App\Error::WARN_ADMIN_DATA_IGNORED:
+ title: 'Admin data is used to create an admin user during initial installation only. Any changes to Admin data are ignored during the upgrade process.'
+ suggestion: 'After the initial installation, you can remove admin data from the configuration.'
+ stage: deploy
+ step: validate-config
+ type: warning
+!php/const Magento\MagentoCloud\App\Error::WARN_ADMIN_EMAIL_NOT_SET:
+ title: 'Admin user was not created as admin email was not set'
+ suggestion: 'After installation, you can create an admin user manually: Use ssh to connect to your environment. Then, run the `bin/magento admin:user:create` command.'
+ stage: deploy
+ step: validate-config
+ type: warning
+!php/const Magento\MagentoCloud\App\Error::WARN_UPDATE_PHP_VERSION:
+ title: 'Update php version to recommended version'
+ stage: deploy
+ step: validate-config
+ type: warning
+!php/const Magento\MagentoCloud\App\Error::WARN_SOLR_DEPRECATED:
+ title: 'Solr support has been deprecated in Magento 2.1.'
+ stage: deploy
+ step: validate-config
+ type: warning
+!php/const Magento\MagentoCloud\App\Error::WARN_SOLR_NOT_SUPPORTED:
+ title: 'Solr is no longer supported by Magento 2.2 or later.'
+ stage: deploy
+ step: validate-config
+ type: warning
+!php/const Magento\MagentoCloud\App\Error::WARN_ES_INSTALLED_BUT_NOT_USED:
+ title: 'Elasticsearch service is installed at infrastructure layer, but it is not used as a search engine.'
+ suggestion: 'Consider removing the Elasticsearch service from the infrastructure layer to optimize resource usage.'
+ stage: deploy
+ step: validate-config
+ type: warning
+!php/const Magento\MagentoCloud\App\Error::WARN_ES_VERSION_MISMATCH:
+ title: 'Elasticsearch service version on infrastructure layer is not compatible with current version of the elasticsearch/elasticsearch module, used by your Magento application.'
+ stage: deploy
+ step: validate-config
+ type: warning
+!php/const Magento\MagentoCloud\App\Error::WARN_CONFIG_NOT_COMPATIBLE:
+ title: 'The current configuration is not compatible with this version of Magento'
+ stage: deploy
+ step: validate-config
+ type: warning
+!php/const Magento\MagentoCloud\App\Error::WARN_DEPLOY_SCD_OPTIONS_IGNORANCE:
+ title: 'SCD options ignored because the deploy process did not run on the build phase'
+ stage: deploy
+ step: validate-config
+ type: warning
+!php/const Magento\MagentoCloud\App\Error::WARN_DEPRECATED_VARIABLES:
+ title: 'The configuration contains deprecated variables or values'
+ stage: deploy
+ step: validate-config
+ type: warning
+!php/const Magento\MagentoCloud\App\Error::WARN_ENVIRONMENT_CONFIG_NOT_VALID:
+ title: 'Environment configuration is not valid'
+ stage: deploy
+ step: validate-config
+ type: warning
+!php/const Magento\MagentoCloud\App\Error::WARN_CONFIG_WRONG_JSON_FORMAT:
+ title: 'JSON type configuration can not be decoded'
+ stage: deploy
+ step: validate-config
+ type: warning
+!php/const Magento\MagentoCloud\App\Error::WARN_SERVICE_VERSION_NOT_COMPATIBLE:
+ title: 'The current configuration is not compatible with this version of Magento'
+ stage: deploy
+ step: validate-config
+ type: warning
+!php/const Magento\MagentoCloud\App\Error::WARN_SERVICE_PASSED_EOL:
+ title: 'Some services have passed EOL'
+ stage: deploy
+ step: validate-config
+ type: warning
+!php/const Magento\MagentoCloud\App\Error::WARN_DEPRECATED_MYSQL_SEARCH_ENGINE:
+ title: 'The MySQL search configuration option is deprecated'
+ suggestion: 'Use Elasticsearch instead.'
+ stage: deploy
+ step: validate-config
+ type: warning
+!php/const Magento\MagentoCloud\App\Error::WARN_ENV_PHP_MISSED:
+ title: 'Magento installation completed, but the `app/etc/env.php` configuration file was missing or empty.'
+ suggestion: 'Required data will be restored from environment configurations and from .magento.env.yaml file.'
+ stage: deploy
+ step: install-update
+ type: warning
+!php/const Magento\MagentoCloud\App\Error::WARN_SPLIT_DB_CUSTOM_CONNECTION_USED:
+ title: 'For split databases used custom connections'
+ stage: deploy
+ step: 'install-update:db-connection'
+ type: warning
+!php/const Magento\MagentoCloud\App\Error::WARN_DB_CONFIG_NOT_COMPATIBLE_WITH_SLAVE:
+ title: 'You have changed to a database configuration that is not compatible with the slave connection.'
+ stage: deploy
+ step: 'install-update:db-connection'
+ type: warning
+!php/const Magento\MagentoCloud\App\Error::WARN_SPLIT_DB_ENABLING_SKIPPED:
+ title: 'Enabling a split database will be skipped.'
+ stage: deploy
+ step: 'install-update:split-db'
+ type: warning
+!php/const Magento\MagentoCloud\App\Error::WARN_NOT_ENOUGH_DATA_SPLIT_DB_VAR:
+ title: 'The SPLIT_DB variable is missing the configuration for split connection types.'
+ stage: deploy
+ step: 'install-update:split-db'
+ type: warning
+!php/const Magento\MagentoCloud\App\Error::WARN_SLAVE_CONNECTION_NOT_SET:
+ title: 'Slave connection not set.'
+ stage: deploy
+ step: 'install-update:split-db'
+ type: warning
+!php/const Magento\MagentoCloud\App\Error::WARN_COPY_MOUNTED_DIRS_FAILED:
+ title: 'Failed to restore some data generated during the build phase to the mounted directories'
+ stage: deploy
+ suggestion: 'Check the `cloud.log` for more information.'
+ step: 'pre-deploy:restore-writable-dirs'
+ type: warning
+!php/const Magento\MagentoCloud\App\Error::WARN_DEBUG_LOG_ENABLED:
+ title: 'Debug logging is enabled in Magento'
+ suggestion: 'To save disk space, do not enable debug logging for your production environments.'
+ stage: post-deploy
+ step: validate-config
+ type: warning
+!php/const Magento\MagentoCloud\App\Error::WARN_CANNOT_FETCH_STORE_URLS:
+ title: 'Can not fetch store urls'
+ stage: post-deploy
+ step: warm-up
+ type: warning
+!php/const Magento\MagentoCloud\App\Error::WARN_CANNOT_FETCH_STORE_URL:
+ title: 'Can not fetch store url'
+ stage: post-deploy
+ step: warm-up
+ type: warning
+!php/const Magento\MagentoCloud\App\Error::WARN_CREATE_CONFIG_BACKUP_FAILED:
+ title: 'Cannot create backup files'
+ stage: post-deploy
+ step: backup
+ type: warning
+!php/const Magento\MagentoCloud\App\Error::WARN_CANNOT_GET_PROC_COUNT:
+ title: 'Can not get system processor count:'
+ type: warning
+ stage: general
diff --git a/config/schema.yaml b/config/schema.yaml
index 148c4546e1..5d2748b05c 100644
--- a/config/schema.yaml
+++ b/config/schema.yaml
@@ -643,6 +643,20 @@ variables:
- stage:
global:
X_FRAME_CONFIGURATION: SAMEORIGIN
+ QUALITY_PATCHES:
+ description: Specify a list of Magento quality patches that will be applied during deployment.
+ type: array
+ stages:
+ - build
+ default:
+ build: []
+ examples:
+ - stage:
+ build:
+ QUALITY_PATCHES:
+ - MC-31387
+ - MDVA-4567
+ - MC-45634
# Environment variables
ENV_RELATIONSHIPS:
diff --git a/config/services.xml b/config/services.xml
index 2cc417b9d2..9a54e9333b 100644
--- a/config/services.xml
+++ b/config/services.xml
@@ -113,6 +113,7 @@
+
diff --git a/dist/error-codes.md b/dist/error-codes.md
new file mode 100644
index 0000000000..46d3fbef4c
--- /dev/null
+++ b/dist/error-codes.md
@@ -0,0 +1,182 @@
+
+
+## Critical Errors
+
+Critical errors indicate a problem with the Magento Commerce Cloud project configuration that causes deployment failure, for example incorrect, unsupported, or missing configuration for required settings. Before you can deploy, you must update the configuration to resolve these errors.
+
+### Build stage
+
+{:.error-table}
+| Error code | Build step | Error description (Title) | Suggested action |
+| - | - | - | - |
+| 2 | | Cannot write to the `./app/etc/env.php` file | Deployment script cannot make required changes to the `/app/etc/env.php` file. Check your filesystem permissions. |
+| 3 | | Configuration isn't defined in the `schema.yaml` file | Configuration is not defined in the `./vendor/magento/ece-tools/config/schema.yaml` file. Check that the config variable name is correct, and that it is defined. |
+| 4 | | Failed to parse the `.magento.env.yaml` file | The `./.magento.env.yaml` file format is invalid. Use a YAML parser to check the syntax and fix any errors. |
+| 5 | | Unable to read the `.magento.env.yaml` file | Unable to read the `./.magento.env.yaml` file. Check file permissions. |
+| 6 | | Unable to read the `.schema.yaml` file | Unable to read the `./vendor/magento/ece-tools/config/magento.env.yaml` file. Check file permissions and redeploy (`magento-cloud environment:redeploy`). |
+| 7 | refresh-modules | Cannot write to the `./app/etc/config.php` file | The deployment script cannot make required changes to the `/app/etc/config.php` file. Check your filesystem permissions. |
+| 8 | validate-config | Cannot read the `composer.json` file | Unable to read the `./composer.json` file. Check file permissions. |
+| 9 | validate-config | Composer.json is missing required autoload section | Required `autoload` section is missing from the `composer.json` file. Compare the autoload section to the `composer.json` file in the Magento Cloud template, and add the missing configuration. |
+| 10 | validate-config | The file `.magento.env.yaml` contains an option that is not declared in the schema, or an option configured with an invalid value or stage | The `./.magento.env.yaml` file contains invalid configuration. Check the error log for detailed info. |
+| 11 | refresh-modules | Command failed: `/bin/magento module:enable --all` | Try to run `composer update` locally. Then, commit and push the updated `composer.lock` file. Also check the `cloud.log` for more information. For more detailed command output, add the `VERBOSE_COMMANDS: '-vvv'` option to the `.magento.env.yaml` file. |
+| 12 | apply-patches | Failed to apply patch | |
+| 13 | set-report-dir-nesting-level | Cannot write to the file `/pub/errors/local.xml` | |
+| 14 | copy-sample-data | Failed to copy sample data files | |
+| 15 | compile-di | Command failed: `/bin/magento setup:di:compile` | Check the `cloud.log` for more information. Add `VERBOSE_COMMANDS: '-vvv'` into `.magento.env.yaml` for more detailed command output. |
+| 16 | dump-autoload | Command failed: `composer dump-autoload` | The `composer dump-autoload` command failed. Check the `cloud.log` for more information. |
+| 17 | run-baler | The command to run `Baler` for Javascript bundling failed | Check the `SCD_USE_BALER` environment variable to verify that the Baler module is configured and enabled for JS bundling. If you do not need the Baler module, set `SCD_USE_BALER: false`. |
+| 18 | compress-static-content | Required utility wasn't found (timeout, bash) | |
+| 19 | deploy-static-content | Command `/bin/magento setup:static-content:deploy` failed | Check the `cloud.log` for more information. For more detailed command output, add the `VERBOSE_COMMANDS: '-vvv'` option to the `.magento.env.yaml` file. |
+| 20 | compress-static-content | Static content compression failed | Check the `cloud.log` for more information. |
+| 21 | backup-data: static-content | Failed to copy static content into the `init` directory | Check the `cloud.log` for more information. |
+| 22 | backup-data: writable-dirs | Failed to copy some writable directories into the `init` directory | Failed to copy writable directories into the `./init` folder. Check your filesystem permissions. |
+| 23 | | Unable to create a logger object | |
+| 24 | backup-data: static-content | Failed to clean the `./init/pub/static/` directory | Failed to clean `./init/pub/static` folder. Check your filesystem permissions. |
+| 25 | | Cannot find the Composer package | If you installed the Magento application version directly from the Magento git repository, verify that the `DEPLOYED_MAGENTO_VERSION_FROM_GIT` environment variable is configured. |
+| 26 | validate-config | Remove Magento Braintree module configuration which is no longer supported in Magento 2.4 and later versions. | Support for the Braintree module is no longer included with Magento 2.4.0 and later. Remove the CONFIG__STORES__DEFAULT__PAYMENT__BRAINTREE__CHANNEL variable from the variables section of the .magento.app.yaml file. For Braintree payment support, use an official extension from the Magento Marketplace instead. |
+
+### Deploy stage
+
+{:.error-table}
+| Error code | Deploy step | Error description (Title) | Suggested action |
+| - | - | - | - |
+| 101 | pre-deploy: cache | Incorrect cache configuration (missing port or host) | Cache configuration is missing required parameters `server` or `port`. Check the `cloud.log` for more information. |
+| 102 | | Cannot write to the `./app/etc/env.php` file | Deployment script cannot make required changes to the `/app/etc/env.php` file. Check your filesystem permissions. |
+| 103 | | Configuration isn't defined in the `schema.yaml` file | Configuration is not defined in the `./vendor/magento/ece-tools/config/schema.yaml` file. Check that the config variable name is correct, and that it is defined. |
+| 104 | | Failed to parse the `.magento.env.yaml` file | Configuration is not defined in the `./vendor/magento/ece-tools/config/schema.yaml` file. Check that the config variable name is correct, and that it is defined. |
+| 105 | | Unable to read the `.magento.env.yaml` file | Unable to read the `./.magento.env.yaml` file. Check file permissions. |
+| 106 | | Unable to read the `.schema.yaml` file | |
+| 107 | pre-deploy: clean-redis-cache | Failed to clean the Redis cache | Failed to clean the Redis cache. Check that the Redis cache configuration is correct and that the Redis service is available. See [Setup Redis service](https://devdocs.magento.com/cloud/project/project-conf-files_services-redis.html). |
+| 108 | pre-deploy: set-production-mode | Command `/bin/magento maintenance:enable` failed | Check the `cloud.log` for more information. For more detailed command output, add the `VERBOSE_COMMANDS: '-vvv'` option to the `.magento.env.yaml` file. |
+| 109 | validate-config | Incorrect database configuration | Check that the the `DATABASE_CONFIGURATION` environment variable is configured correctly. |
+| 110 | validate-config | Incorrect session configuration | Check that the `SESSION_CONFIGURATION` environment variable is configured correctly. The configuration must contain at least the `save` parameter. |
+| 111 | validate-config | Incorrect search configuration | Check that the `SEARCH_CONFIGURATION` environment variable is configured correctly. The configuration must contain at least the `engine` parameter. |
+| 112 | validate-config | Incorrect resource configuration | Check that the `RESOURCE_CONFIGURATION` environment variable is configured correctly. The configuration must contain at least `connection` parameter. |
+| 113 | validate-config:elasticsuite-integrity | ElasticSuite is installed, but the ElasticSearch service is not available | Check that the `SEARCH_CONFIGURATION` environment variable is configured correctly, and verify that the Elasticsearch service is available. |
+| 114 | validate-config:elasticsuite-integrity | ElasticSuite is installed, but another search engine is used | ElasticSuite is installed, but another search engine is configured. Update the `SEARCH_CONFIGURATION` environment variable to enable Elasticsearch, and verify the Elasticsearch service configuration in the `services.yaml` file. |
+| 115 | | Database query execution failed | |
+| 116 | install-update: setup | Command `/bin/magento setup:install` failed | Check the `cloud.log` and `install_upgrade.log` for more information. For more detailed command output, add the `VERBOSE_COMMANDS: '-vvv'` option to the `.magento.env.yaml` file. |
+| 117 | install-update: config-import | Command `app:config:import` failed | Check the `cloud.log` for more information. For more detailed command output, add the `VERBOSE_COMMANDS: '-vvv'` option to the `.magento.env.yaml` file. |
+| 118 | | Required utility wasn't found (timeout, bash) | |
+| 119 | install-update: deploy-static-content | Command `/bin/magento setup:static-content:deploy` failed | Check the `cloud.log` for more information. For more detailed command output, add the `VERBOSE_COMMANDS: '-vvv'` option to the `.magento.env.yaml` file. |
+| 120 | compress-static-content | Static content compression failed | Check the `cloud.log` for more information. |
+| 121 | deploy-static-content:generate | Cannot update the deployed version | Cannot update the `./pub/static/deployed_version.txt` file. Check your filesystem permissions. |
+| 122 | clean-static-content | Failed to clean static content files | |
+| 123 | install-update: split-db | Command `/bin/magento setup:db-schema:split` failed | Check the `cloud.log` for more information. For more detailed command output, add the `VERBOSE_COMMANDS: '-vvv'` option to the `.magento.env.yaml` file. |
+| 124 | clean-view-preprocessed | Failed to clean the `var/view_preprocessed` folder | Unable to clean the `./var/view_preprocessed` folder. Check your filesystem permissions. |
+| 125 | install-update: reset-password | Failed to update the `/var/credentials_email.txt` file | Failed to update the `/var/credentials_email.txt` file. Check your filesystem permissions. |
+| 126 | install-update: update | Command `/bin/magento setup:upgrade` failed | Check the `cloud.log` and `install_upgrade.log` for more information. For more detailed command output, add the `VERBOSE_COMMANDS: '-vvv'` option to the `.magento.env.yaml` file. |
+| 127 | clean-cache | Command `/bin/magento cache:flush` failed | Check the `cloud.log` for more information. For more detailed command output, add the `VERBOSE_COMMANDS: '-vvv'` option to the `.magento.env.yaml` file. |
+| 128 | disable-maintenance-mode | Command `/bin/magento maintenance:disable` failed | Check the `cloud.log` for more information. Add `VERBOSE_COMMANDS: '-vvv'` into `.magento.env.yaml` for more detailed command output. |
+| 129 | install-update: reset-password | Unable to read reset password template | |
+| 130 | install-update: cache_type | Command failed: `php ./bin/magento cache:enable` | Command `php ./bin/magento cache:enable` runs only when Magento was installed but `./app/etc/env.php` file was absent or empty at the beginning of the deployment. Check the `cloud.log` for more information. Add `VERBOSE_COMMANDS: '-vvv'` into `.magento.env.yaml` for more detailed command output. |
+| 131 | install-update | The `crypt/key` key value does not exist in the `./app/etc/env.php` file or the `CRYPT_KEY` cloud environment variable | This error occurs if the `./app/etc/env.php` file is not present when Magento deployment begins, or if the `crypt/key` value is undefined. If you migrated the database from another environment, retrieve the crypt key value from that environment. Then, add the value to the [CRYPT_KEY](https://devdocs.magento.com/cloud/env/variables-deploy.html#crypt_key) cloud environment variable in your current environment. See [Add the Magento encryption key](https://devdocs.magento.com/cloud/setup/first-time-setup-import-import.html#encryption-key). If you accidentally removed the `./app/etc/env.php` file, use the following command to restore it from the backup files created from a previous deployment: `./vendor/bin/ece-tools backup:restore` CLI command ." |
+| 132 | | Can not connect to the Elasticsearch service | Check that credentials for elasticsearch are correct and service is running |
+| 133 | validate-config | Remove Magento Braintree module configuration which is no longer supported in Magento 2.4 and later versions. | Support for the Braintree module is no longer included with Magento 2.4.0 and later. Remove the CONFIG__STORES__DEFAULT__PAYMENT__BRAINTREE__CHANNEL variable from the variables section of the .magento.app.yaml file. For Braintree support, use an official Braintree Payments extension from the Magento Marketplace instead. |
+| 134 | validate-config | Magento 2.4.0 requires Elasticsearch service to be installed | Install Elasticsearch service |
+
+### Post-deploy stage
+
+{:.error-table}
+| Error code | Post-deploy step | Error description (Title) | Suggested action |
+| - | - | - | - |
+| 201 | is-deploy-failed | Deploy stage failed | |
+| 202 | | The `./app/etc/env.php` file is not writable | Deployment script cannot make required changes to the `/app/etc/env.php` file. Check your filesystem permissions. |
+| 203 | | Configuration isn't defined in the `schema.yaml` file | Configuration is not defined in the `./vendor/magento/ece-tools/config/schema.yaml` file. Check that the config variable name is correct, and that it is defined. |
+| 204 | | Failed to parse the `.magento.env.yaml` file | The `./.magento.env.yaml` file format is invalid. Use a YAML parser to check the syntax and fix any errors. |
+| 205 | | Unable to read the `.magento.env.yaml` file | Check file permissions. |
+| 206 | | Unable to read the `.schema.yaml` file | |
+| 207 | warm-up | Failed to warm-up some pages | |
+| 208 | time-to-firs-byte | Failed to test time to first byte (TTFB) | |
+| 227 | clean-cache | Command `/bin/magento cache:flush` failed | Check the `cloud.log` for more information. Add `VERBOSE_COMMANDS: '-vvv'` into `.magento.env.yaml` for more detailed command output. |
+
+### General
+
+{:.error-table}
+| Error code | General step | Error description (Title) | Suggested action |
+| - | - | - | - |
+| 243 | | Configuration is not defined in the `schema.yaml` file | Check that the config variable name is correct, and that it defined. |
+| 244 | | Failed to parse the `.magento.env.yaml` file | The `./.magento.env.yaml` file format is invalid. Use a YAML parser to check the syntax and fix any errors. |
+| 245 | | Unable to read the `.magento.env.yaml` file | Unable to read the `./.magento.env.yaml` file. Check file permissions. |
+| 246 | | Unable to read the `.schema.yaml` file | |
+
+## Warning Errors
+
+Warning errors indicate a problem with the Magento Commerce Cloud project configuration such as incorrect, deprecated, unsupported, or missing configuration settings for optional features that can affect site operation. Although a warning does not cause deployment failure, you should review warning messages and update the configuration to resolve them.
+
+### Build stage
+
+{:.error-table}
+| Error code | Build step | Error description (Title) | Suggested action |
+| - | - | - | - |
+| 1001 | validate-config | File app/etc/config.php does not exist | |
+| 1002 | validate-config | The ./build_options.ini file is no longer supported | |
+| 1003 | validate-config | The modules section is missing from the shared config file | |
+| 1004 | validate-config | The configuration is not compatible with this version of Magento | |
+| 1005 | validate-config | SCD options ignored | |
+| 1006 | validate-config | The configured state is not ideal | |
+| 1007 | run-baler | Baler JS bundling cannot be used | |
+
+### Deploy stage
+
+{:.error-table}
+| Error code | Deploy step | Error description (Title) | Suggested action |
+| - | - | - | - |
+| 2001 | pre-deploy:cache | Cache is configured for a Redis service that is not available. Configuration will be ignored. | |
+| 2002 | validate-config | The configured state is not ideal | |
+| 2003 | validate-config | The directory nesting level value for error reporting has not been configured | |
+| 2004 | validate-config | Invalid configuration in the ./pub/errors/local.xml file. | |
+| 2005 | validate-config | Admin data is used to create an admin user during initial installation only. Any changes to Admin data are ignored during the upgrade process. | After the initial installation, you can remove admin data from the configuration. |
+| 2006 | validate-config | Admin user was not created as admin email was not set | After installation, you can create an admin user manually: Use ssh to connect to your environment. Then, run the `bin/magento admin:user:create` command. |
+| 2007 | validate-config | Update php version to recommended version | |
+| 2008 | validate-config | Solr support has been deprecated in Magento 2.1. | |
+| 2009 | validate-config | Solr is no longer supported by Magento 2.2 or later. | |
+| 2010 | validate-config | Elasticsearch service is installed at infrastructure layer, but it is not used as a search engine. | Consider removing the Elasticsearch service from the infrastructure layer to optimize resource usage. |
+| 2011 | validate-config | Elasticsearch service version on infrastructure layer is not compatible with current version of the elasticsearch/elasticsearch module, used by your Magento application. | |
+| 2012 | validate-config | The current configuration is not compatible with this version of Magento | |
+| 2013 | validate-config | SCD options ignored because the deploy process did not run on the build phase | |
+| 2014 | validate-config | The configuration contains deprecated variables or values | |
+| 2015 | validate-config | Environment configuration is not valid | |
+| 2016 | validate-config | JSON type configuration can not be decoded | |
+| 2017 | validate-config | The current configuration is not compatible with this version of Magento | |
+| 2018 | validate-config | Some services have passed EOL | |
+| 2019 | validate-config | The MySQL search configuration option is deprecated | Use Elasticsearch instead. |
+| 2020 | install-update | Magento installation completed, but the `app/etc/env.php` configuration file was missing or empty. | Required data will be restored from environment configurations and from .magento.env.yaml file. |
+| 2021 | install-update:db-connection | For split databases used custom connections | |
+| 2022 | install-update:db-connection | You have changed to a database configuration that is not compatible with the slave connection. | |
+| 2023 | install-update:split-db | Enabling a split database will be skipped. | |
+| 2024 | install-update:split-db | The SPLIT_DB variable is missing the configuration for split connection types. | |
+| 2025 | install-update:split-db | Slave connection not set. | |
+| 2026 | pre-deploy:restore-writable-dirs | Failed to restore some data generated data during the build phase to the mounted directories. | Check the `cloud.log` for more information. |
+
+### Post-deploy stage
+
+{:.error-table}
+| Error code | Post-deploy step | Error description (Title) | Suggested action |
+| - | - | - | - |
+| 3001 | validate-config | Debug logging is enabled in Magento | To save disk space, do not enable debug logging for your production environments. |
+| 3002 | warm-up | Can not fetch store urls | |
+| 3003 | warm-up | Can not fetch store url | |
+| 3004 | backup | Cannot create backup files | |
+
+### General
+
+{:.error-table}
+| Error code | General step | Error description (Title) | Suggested action |
+| - | - | - | - |
+| 4001 | | Can not get system processor count: | |
+
+
+
+
+
+
diff --git a/scenario/build/generate.xml b/scenario/build/generate.xml
index ec06ea622e..29909e169f 100644
--- a/scenario/build/generate.xml
+++ b/scenario/build/generate.xml
@@ -10,6 +10,7 @@
-
- Magento\MagentoCloud\Config\Validator\Build\ComposerFile
- Magento\MagentoCloud\Config\Validator\Build\StageConfig
+ - Magento\MagentoCloud\Config\Validator\Build\MagentoAppYaml
-
- Magento\MagentoCloud\Config\Validator\Build\ConfigFileExists
diff --git a/scenario/deploy.xml b/scenario/deploy.xml
index 788fa1c5df..5e9e719762 100644
--- a/scenario/deploy.xml
+++ b/scenario/deploy.xml
@@ -5,6 +5,7 @@
Psr\Log\LoggerInterface
+ - Magento\MagentoCloud\Step\Deploy\PreDeploy\RestorePatchLog
- Magento\MagentoCloud\Step\Deploy\PreDeploy\CheckState
- Magento\MagentoCloud\Step\Deploy\PreDeploy\ConfigUpdate\Cache
- Magento\MagentoCloud\Step\Deploy\PreDeploy\CleanStaticContent
@@ -23,6 +24,7 @@
Psr\Log\LoggerInterface
-
+
- Magento\MagentoCloud\Config\Validator\Deploy\EnvironmentVariables
- Magento\MagentoCloud\Config\Validator\Deploy\DatabaseConfiguration
- Magento\MagentoCloud\Config\Validator\Deploy\SearchConfiguration
- Magento\MagentoCloud\Config\Validator\Deploy\ResourceConfiguration
diff --git a/src/App/Error.php b/src/App/Error.php
index 895dd87ad3..7b478c942a 100644
--- a/src/App/Error.php
+++ b/src/App/Error.php
@@ -12,6 +12,8 @@
*/
class Error
{
+ public const DEFAULT_ERROR = 1;
+
public const BUILD_ENV_PHP_IS_NOT_WRITABLE = 2;
public const BUILD_CONFIG_NOT_DEFINED = 3;
public const BUILD_CONFIG_PARSE_FAILED = 4;
@@ -36,6 +38,7 @@ class Error
public const BUILD_UNABLE_TO_CREATE_LOGGER = 23;
public const BUILD_CLEAN_INIT_PUB_STATIC_FAILED = 24;
public const BUILD_COMPOSER_PACKAGE_NOT_FOUND = 25;
+ public const BUILD_WRONG_BRAINTREE_VARIABLE = 26;
public const DEPLOY_WRONG_CACHE_CONFIGURATION = 101;
public const DEPLOY_ENV_PHP_IS_NOT_WRITABLE = 102;
@@ -68,6 +71,9 @@ class Error
public const DEPLOY_UNABLE_TO_READ_RESET_PASSWORD_TMPL = 129;
public const DEPLOY_CACHE_ENABLE_FAILED = 130;
public const DEPLOY_CRYPT_KEY_IS_ABSENT = 131;
+ public const DEPLOY_ES_CANNOT_CONNECT = 132;
+ public const DEPLOY_WRONG_BRAINTREE_VARIABLE = 133;
+ public const DEPLOY_WRONG_SEARCH_ENGINE = 134;
public const PD_DEPLOY_IS_FAILED = 201;
public const PD_ENV_PHP_IS_NOT_WRITABLE = 202;
@@ -83,4 +89,58 @@ class Error
public const GLOBAL_CONFIG_PARSE_FAILED = 244;
public const GLOBAL_CONFIG_UNABLE_TO_READ = 245;
public const GLOBAL_CONFIG_UNABLE_TO_READ_SCHEMA_YAML = 246;
+
+ /**
+ * Build
+ */
+ public const WARN_CONFIG_PHP_NOT_EXISTS = 1001;
+ public const WARN_UNSUPPORTED_BUILDS_OPTION_INI = 1002;
+ public const WARN_MISSED_MODULE_SECTION = 1003;
+ public const WARN_CONFIGURATION_VERSION_MISMATCH = 1004;
+ public const WARN_SCD_OPTIONS_IGNORANCE = 1005;
+ public const WARN_CONFIGURATION_STATE_NOT_IDEAL = 1006;
+ public const WARN_BALER_CANNOT_BE_USED = 1007;
+
+ /**
+ * Deploy
+ */
+ public const WARN_REDIS_SERVICE_NOT_AVAILABLE = 2001;
+ public const WARN_WRONG_SPLIT_DB_CONFIG = 2002;
+ public const WARN_DIR_NESTING_LEVEL_NOT_CONFIGURED = 2003;
+ public const WARN_NOT_CORRECT_LOCAL_XML_FILE = 2004;
+ public const WARN_ADMIN_DATA_IGNORED = 2005;
+ public const WARN_ADMIN_EMAIL_NOT_SET = 2006;
+ public const WARN_UPDATE_PHP_VERSION = 2007;
+ public const WARN_SOLR_DEPRECATED = 2008;
+ public const WARN_SOLR_NOT_SUPPORTED = 2009;
+ public const WARN_ES_INSTALLED_BUT_NOT_USED = 2010;
+ public const WARN_ES_VERSION_MISMATCH = 2011;
+ public const WARN_CONFIG_NOT_COMPATIBLE = 2012;
+ public const WARN_DEPLOY_SCD_OPTIONS_IGNORANCE = 2013;
+ public const WARN_DEPRECATED_VARIABLES = 2014;
+ public const WARN_ENVIRONMENT_CONFIG_NOT_VALID = 2015;
+ public const WARN_CONFIG_WRONG_JSON_FORMAT = 2016;
+ public const WARN_SERVICE_VERSION_NOT_COMPATIBLE = 2017;
+ public const WARN_SERVICE_PASSED_EOL = 2018;
+ public const WARN_DEPRECATED_MYSQL_SEARCH_ENGINE = 2019;
+ public const WARN_ENV_PHP_MISSED = 2020;
+ public const WARN_SPLIT_DB_CUSTOM_CONNECTION_USED = 2021;
+ public const WARN_DB_CONFIG_NOT_COMPATIBLE_WITH_SLAVE = 2022;
+ public const WARN_SPLIT_DB_ENABLING_SKIPPED = 2023;
+ public const WARN_NOT_ENOUGH_DATA_SPLIT_DB_VAR = 2024;
+ public const WARN_SLAVE_CONNECTION_NOT_SET = 2025;
+ public const WARN_COPY_MOUNTED_DIRS_FAILED = 2026;
+
+ /**
+ * Post-deploy
+ */
+ public const WARN_DEBUG_LOG_ENABLED = 3001;
+ public const WARN_CANNOT_FETCH_STORE_URLS = 3002;
+ public const WARN_CANNOT_FETCH_STORE_URL = 3003;
+ public const WARN_CREATE_CONFIG_BACKUP_FAILED = 3004;
+
+ /**
+ * General
+ */
+ public const WARN_CANNOT_GET_PROC_COUNT = 4001;
}
diff --git a/src/App/ErrorInfo.php b/src/App/ErrorInfo.php
new file mode 100644
index 0000000000..60e127dd2a
--- /dev/null
+++ b/src/App/ErrorInfo.php
@@ -0,0 +1,73 @@
+file = $file;
+ $this->fileList = $fileList;
+ }
+
+ /**
+ * Returns info about error based on passed error code
+ *
+ * @param int $errorCode
+ * @return array
+ * @throws FileSystemException
+ */
+ public function get(int $errorCode): array
+ {
+ $this->loadErrors();
+
+ return $this->errors[$errorCode] ?? [];
+ }
+
+ /**
+ * Fetches all errors from schema.error.yaml file and caches them
+ *
+ * @throws FileSystemException
+ */
+ private function loadErrors(): void
+ {
+ if (empty($this->errors)) {
+ $this->errors = Yaml::parse(
+ $this->file->fileGetContents($this->fileList->getErrorSchema()),
+ Yaml::PARSE_CONSTANT
+ );
+ }
+ }
+}
diff --git a/src/App/Logger/Error/Reader.php b/src/App/Logger/Error/Reader.php
new file mode 100644
index 0000000000..ace94673be
--- /dev/null
+++ b/src/App/Logger/Error/Reader.php
@@ -0,0 +1,53 @@
+fileList = $fileList;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function read(): array
+ {
+ try {
+ $handle = @fopen($this->fileList->getCloudErrorLog(), 'r');
+ if (!$handle) {
+ return [];
+ }
+ $logs = [];
+ while (($line = fgets($handle)) !== false) {
+ $error = json_decode($line, true);
+ $logs[$error['errorCode']] = $error;
+ }
+ fclose($handle);
+
+ return $logs;
+ } catch (UndefinedPackageException $e) {
+ return [];
+ }
+ }
+}
diff --git a/src/App/Logger/Error/ReaderInterface.php b/src/App/Logger/Error/ReaderInterface.php
new file mode 100644
index 0000000000..9c84de9c4e
--- /dev/null
+++ b/src/App/Logger/Error/ReaderInterface.php
@@ -0,0 +1,16 @@
+container = $container;
+ }
+
+ /**
+ * @return JsonErrorFormatter
+ */
+ public function create(): JsonErrorFormatter
+ {
+ return new JsonErrorFormatter(
+ $this->container->get(ErrorInfo::class),
+ $this->container->get(ReaderInterface::class),
+ JsonFormatter::BATCH_MODE_JSON,
+ true
+ );
+ }
+}
diff --git a/src/App/Logger/Formatter/JsonErrorFormatter.php b/src/App/Logger/Formatter/JsonErrorFormatter.php
new file mode 100644
index 0000000000..3abab27252
--- /dev/null
+++ b/src/App/Logger/Formatter/JsonErrorFormatter.php
@@ -0,0 +1,103 @@
+errorInfo = $errorInfo;
+ $this->reader = $reader;
+ }
+
+ /**
+ * Format record, skip logging if ErrorCode isn't passed.
+ *
+ * {@inheritDoc}
+ */
+ public function format(array $record)
+ {
+ try {
+ if (!isset($record['context']['errorCode'])) {
+ return false;
+ }
+
+ $loggedErrors = $this->reader->read();
+
+ if (isset($loggedErrors[$record['context']['errorCode']])) {
+ return false;
+ }
+
+ return parent::format($this->formatLog($record));
+ } catch (\Exception $e) {
+ return false;
+ }
+ }
+
+ /**
+ * Returns error info data based on errorCode.
+ *
+ * @param array $record
+ * @return array
+ * @throws FileSystemException
+ */
+ private function formatLog(array $record): array
+ {
+ $errorCode = $record['context']['errorCode'];
+ $errorInfo = $this->errorInfo->get($errorCode);
+
+ if (empty($errorInfo)) {
+ $errorInfo = [
+ 'errorCode' => $errorCode,
+ 'title' => $record['message'] ?? ''
+ ];
+ } else {
+ $errorInfo['errorCode'] = $errorCode;
+ if (!empty($record['message'])) {
+ $errorInfo['title'] = $record['message'];
+ }
+ }
+
+ if (!empty($record['context']['suggestion'])) {
+ $errorInfo['suggestion'] = $record['context']['suggestion'];
+ }
+
+ ksort($errorInfo);
+ return $errorInfo;
+ }
+}
diff --git a/src/App/Logger/Formatter/LineFormatter.php b/src/App/Logger/Formatter/LineFormatter.php
new file mode 100644
index 0000000000..195587fe0d
--- /dev/null
+++ b/src/App/Logger/Formatter/LineFormatter.php
@@ -0,0 +1,46 @@
+format = self::FORMAT_BASE_ERROR;
+ } else {
+ $this->format = self::FORMAT_BASE;
+ }
+
+ if (isset($record['message']) && !empty($record['context']['suggestion'])) {
+ $record['message'] .= PHP_EOL . $record['context']['suggestion'];
+ }
+
+ return parent::format($record);
+ }
+}
diff --git a/src/App/Logger/LineFormatterFactory.php b/src/App/Logger/LineFormatterFactory.php
index 7983dc2364..ebc8972ad3 100644
--- a/src/App/Logger/LineFormatterFactory.php
+++ b/src/App/Logger/LineFormatterFactory.php
@@ -7,18 +7,32 @@
namespace Magento\MagentoCloud\App\Logger;
-use Monolog\Formatter\LineFormatter;
+use Magento\MagentoCloud\App\ContainerInterface;
+use Magento\MagentoCloud\App\Logger\Formatter\LineFormatter;
/**
* The factory for LineFormatter.
*/
class LineFormatterFactory
{
+ /**
+ * @var ContainerInterface
+ */
+ private $container;
+
+ /**
+ * @param ContainerInterface $container
+ */
+ public function __construct(ContainerInterface $container)
+ {
+ $this->container = $container;
+ }
+
/**
* @return LineFormatter
*/
public function create(): LineFormatter
{
- return new LineFormatter("[%datetime%] %level_name%: %message% %context% %extra%\n", null, true, true);
+ return new LineFormatter(LineFormatter::FORMAT_BASE, null, true, true);
}
}
diff --git a/src/App/Logger/Pool.php b/src/App/Logger/Pool.php
index c75812c80c..901c50172c 100644
--- a/src/App/Logger/Pool.php
+++ b/src/App/Logger/Pool.php
@@ -70,7 +70,9 @@ public function getHandlers(): array
foreach ($this->logConfig->getHandlers() as $handlerName => $handlerConfig) {
$handler = $this->handlerFactory->create($handlerName);
- if (empty($handlerConfig['use_default_formatter'])) {
+ if (!empty($handlerConfig['formatter'])) {
+ $handler->setFormatter($handlerConfig['formatter']);
+ } elseif (empty($handlerConfig['use_default_formatter'])) {
$handler->setFormatter($this->lineFormatterFactory->create());
}
diff --git a/src/Application.php b/src/Application.php
index 7d43ad26f3..ff0c510c9e 100644
--- a/src/Application.php
+++ b/src/Application.php
@@ -62,6 +62,7 @@ protected function getDefaultCommands()
$this->container->create(Command\BackupList::class),
$this->container->create(Command\ApplyPatches::class),
$this->container->create(Command\Dev\UpdateComposer::class),
+ $this->container->create(Command\Dev\GenerateSchemaError::class),
$this->container->create(Command\Wizard\ScdOnDemand::class),
$this->container->create(Command\Wizard\ScdOnBuild::class),
$this->container->create(Command\Wizard\ScdOnDeploy::class),
@@ -75,7 +76,8 @@ protected function getDefaultCommands()
$this->container->create(Command\CronUnlock::class),
$this->container->create(Command\ConfigShow::class),
$this->container->create(Command\RunCommand::class),
- $this->container->create(Command\GenerateSchema::class)
+ $this->container->create(Command\GenerateSchema::class),
+ $this->container->create(Command\ErrorShow::class)
]);
}
}
diff --git a/src/Command/Dev/GenerateSchemaError.php b/src/Command/Dev/GenerateSchemaError.php
new file mode 100644
index 0000000000..6a38625677
--- /dev/null
+++ b/src/Command/Dev/GenerateSchemaError.php
@@ -0,0 +1,179 @@
+
+
+
+
+
+EOT;
+
+ /**
+ *
+ * @param File $file
+ * @param FileList $fileList
+ */
+ public function __construct(File $file, FileList $fileList)
+ {
+ $this->file = $file;
+ $this->fileList = $fileList;
+
+ parent::__construct();
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function configure(): void
+ {
+ $this->setName(static::NAME)
+ ->setDescription('Generates dist/error-codes.md file from schema.error.yaml');
+
+ parent::configure();
+ }
+
+ /**
+ * @param InputInterface $input
+ * @param OutputInterface $output
+ * @return int|void
+ * @throws \Magento\MagentoCloud\Filesystem\FileSystemException
+ *
+ * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+ */
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ $errors = Yaml::parse(
+ $this->file->fileGetContents($this->fileList->getErrorSchema()),
+ Yaml::PARSE_CONSTANT
+ );
+
+ $errors = $this->groupErrors($errors);
+
+ $docs = $this->generateDocs($errors);
+
+ $this->file->filePutContents($this->fileList->getErrorDistConfig(), $docs);
+
+ $output->writeln(sprintf('File %s was generated', $this->fileList->getErrorDistConfig()));
+ }
+
+ /**
+ * Groups errors by type and stage
+ *
+ * @param array $errors
+ * @return array
+ */
+ private function groupErrors(array $errors): array
+ {
+ $groupedErrors = [];
+
+ foreach ($errors as $errorCode => $errorData) {
+ $groupedErrors[$errorData['type']][$errorData['stage']][$errorCode] = $errorData;
+ }
+
+ return $groupedErrors;
+ }
+
+ /**
+ * @param array $errors
+ * @return string
+ */
+ private function generateDocs(array $errors): string
+ {
+ $result = '';
+ $result .= "\n";
+
+ foreach ($errors as $type => $typeErrors) {
+ $result .= sprintf("\n## %s Errors\n", ucfirst($type));
+ $result .= sprintf("\n%s\n", $this->getErrorTypeDescription()[$type]);
+
+ foreach ($typeErrors as $stage => $stageErrors) {
+ $result .= sprintf("\n### %s%s\n", ucfirst($stage), $stage === 'general' ? '' : ' stage');
+
+ $table = "\n{:.error-table}\n";
+ $table .= sprintf(
+ "| Error code | %s step | Error description (Title) | Suggested action |\n",
+ ucfirst($stage)
+ );
+ $table .= "| - | - | - | - |\n";
+ foreach ($stageErrors as $errorCode => $errorData) {
+ $table .= sprintf(
+ "| %d | %s | %s | %s |\n",
+ $errorCode,
+ $errorData['step'] ?? '',
+ $errorData['title'] ?? '',
+ $errorData['suggestion'] ?? ''
+ );
+ }
+
+ $result .= $table;
+ }
+ }
+
+ return $result . self::FOOTER_SCRIPTS;
+ }
+
+ /**
+ * Returns an array of error types description (warning and critical)
+ *
+ * @return array
+ */
+ public function getErrorTypeDescription(): array
+ {
+ return [
+ 'critical' => 'Critical errors indicate a problem with the Magento Commerce Cloud project configuration ' .
+ 'that causes deployment failure, for example incorrect, unsupported, or missing configuration for ' .
+ 'required settings. Before you can deploy, you must update the configuration to resolve these errors.',
+ 'warning' => 'Warning errors indicate a problem with the Magento Commerce Cloud project configuration ' .
+ 'such as incorrect, deprecated, unsupported, or missing configuration settings for optional features ' .
+ 'that can affect site operation. Although a warning does not cause deployment failure, you ' .
+ 'should review warning messages and update the configuration to resolve them.',
+ ];
+ }
+}
diff --git a/src/Command/Dev/UpdateComposer/ComposerGenerator.php b/src/Command/Dev/UpdateComposer/ComposerGenerator.php
index da95c93062..2800fd0627 100644
--- a/src/Command/Dev/UpdateComposer/ComposerGenerator.php
+++ b/src/Command/Dev/UpdateComposer/ComposerGenerator.php
@@ -17,6 +17,16 @@
*/
class ComposerGenerator
{
+ /**
+ * Types of supported Magento component packages
+ */
+ private const COMPONENT_PACKAGE_TYPES = [
+ 'magento2-module',
+ 'magento2-theme',
+ 'magento2-language',
+ 'magento2-library'
+ ];
+
/**
* @var DirectoryList
*/
@@ -81,10 +91,13 @@ public function generate(array $repoOptions): array
$baseRepoFolder = $this->directoryList->getMagentoRoot() . '/' . $repoDir;
$dirComposerJson = $baseRepoFolder . '/composer.json';
+ $isModuleRoot = false;
if ($this->file->isExists($dirComposerJson)) {
$dirPackageInfo = json_decode($this->file->fileGetContents($dirComposerJson), true);
- if (isset($dirPackageInfo['type']) && $dirPackageInfo['type'] == 'project') {
+ if ($this->isProjectPackage($dirPackageInfo)) {
$composer['require'] = array_merge($composer['require'], $dirPackageInfo['require']);
+ } elseif ($this->isComponentPackage($dirPackageInfo)) {
+ $isModuleRoot = true;
}
}
@@ -99,12 +112,16 @@ public function generate(array $repoOptions): array
];
$composer['require'][$packageName] = '*@dev';
}
- $excludeRepoStr = empty($repoPackages) ? '' : "--exclude='" . join("' --exclude='", $repoPackages) . "' ";
- $preparePackagesScripts[] = sprintf(
- "rsync -azhm --stats $excludeRepoStr--exclude='dev/tests' --exclude='.git' " .
- "--exclude='composer.json' --exclude='composer.lock' ./%s/ ./",
- $repoDir
- );
+ if (!$isModuleRoot) {
+ $excludeRepoStr = empty($repoPackages)
+ ? ''
+ : "--exclude='" . join("' --exclude='", $repoPackages) . "' ";
+ $preparePackagesScripts[] = sprintf(
+ "rsync -azhm --stats $excludeRepoStr--exclude='dev/tests' --exclude='.git' " .
+ "--exclude='composer.json' --exclude='composer.lock' ./%s/ ./",
+ $repoDir
+ );
+ }
}
$composer['scripts']['prepare-packages'] = $preparePackagesScripts;
$composer['scripts']['post-install-cmd'] = ['@prepare-packages'];
@@ -122,15 +139,24 @@ public function getInstallFromGitScripts(array $repoOptions): array
$installFromGitScripts[] = 'rm -rf ' . implode(' ', array_keys($repoOptions));
foreach ($repoOptions as $repoName => $gitOption) {
- $gitRef = $gitOption['ref'] ?? $gitOption['branch'];
- $installFromGitScripts[] = sprintf(
- 'git clone %s "%s" && git --git-dir="%s/.git" --work-tree="%s" checkout %s',
- $gitOption['repo'],
- $repoName,
- $repoName,
- $repoName,
- $gitRef
- );
+ if (!empty($gitOption['ref'])) {
+ $script = sprintf(
+ 'git clone %s "%s" && git --git-dir="%s/.git" --work-tree="%s" checkout %s',
+ $gitOption['repo'],
+ $repoName,
+ $repoName,
+ $repoName,
+ $gitOption['ref']
+ );
+ } else {
+ $script = sprintf(
+ 'git clone -b %s --single-branch --depth 1 %s %s',
+ $gitOption['branch'],
+ $gitOption['repo'],
+ $repoName
+ );
+ }
+ $installFromGitScripts[] = $script;
}
return $installFromGitScripts;
@@ -199,7 +225,6 @@ private function getBaseComposer(array $repoOptions): array
private function findPackages(string $path)
{
$path = rtrim($path, '\\/');
- $packageTypes = ['magento2-module', 'magento2-theme', 'magento2-language', 'magento2-library'];
$pathLength = strlen($path . '/');
$dirIterator = $this->file->getRecursiveFileIterator(
@@ -210,11 +235,33 @@ private function findPackages(string $path)
$packages = [];
foreach ($dirIterator as $currentFileInfo) {
$packageInfo = json_decode($this->file->fileGetContents($currentFileInfo->getPathName()), true);
- if (isset($packageInfo['type']) && in_array($packageInfo['type'], $packageTypes)) {
+ if ($this->isComponentPackage($packageInfo)) {
$packages[$packageInfo['name']] = substr($currentFileInfo->getPath(), $pathLength);
}
}
return $packages;
}
+
+ /**
+ * Check if provided package info belongs to a Magento component package
+ *
+ * @param array $packageInfo
+ * @return bool
+ */
+ private function isComponentPackage(array $packageInfo): bool
+ {
+ return isset($packageInfo['type']) && in_array($packageInfo['type'], self::COMPONENT_PACKAGE_TYPES);
+ }
+
+ /**
+ * Check if provided package info belongs to a Magento project package
+ *
+ * @param array $packageInfo
+ * @return bool
+ */
+ private function isProjectPackage(array $packageInfo): bool
+ {
+ return isset($packageInfo['type']) && $packageInfo['type'] == 'project';
+ }
}
diff --git a/src/Command/ErrorShow.php b/src/Command/ErrorShow.php
new file mode 100644
index 0000000000..54e2320068
--- /dev/null
+++ b/src/Command/ErrorShow.php
@@ -0,0 +1,128 @@
+errorInfo = $errorInfo;
+ $this->reader = $reader;
+ parent::__construct();
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function configure()
+ {
+ $this->setName(self::NAME)
+ ->setDescription('Display info about error by error id or info about all errors from the last deployment')
+ ->addArgument(
+ self::ARGUMENT_ERROR_CODE,
+ InputArgument::OPTIONAL,
+ 'Error code, if not passed command display info about all errors from the last deployment'
+ )
+ ->addOption(
+ self::OPTION_JSON_FORMAT,
+ 'j',
+ InputOption::VALUE_NONE,
+ 'Used for getting result in JSON format'
+ );
+ }
+
+ /**
+ * Display info about particular error or info about all errors from the last deployment
+ *
+ * {@inheritDoc}
+ */
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ $errorCode = (int)$input->getArgument(self::ARGUMENT_ERROR_CODE);
+ if ($errorCode) {
+ $errorInfo = $this->errorInfo->get($errorCode);
+ if (empty($errorInfo)) {
+ $output->writeln(sprintf('Error with code %s is not registered in the error schema', $errorCode));
+
+ return 1;
+ }
+ $errorInfo['errorCode'] = $errorCode;
+ $errors = [$errorCode => $errorInfo];
+ } else {
+ $errors = $this->reader->read();
+ if (empty($errors)) {
+ $output->writeln('The error log is empty or does not exist');
+
+ return 1;
+ }
+ }
+
+ if ($input->getOption(self::OPTION_JSON_FORMAT)) {
+ $output->writeln(json_encode($errors));
+
+ return 0;
+ }
+
+ $errorCount = count($errors);
+ $i = 0;
+ foreach ($errors as $errorInfo) {
+ $i++;
+ $output->write($this->formatMessage($errorInfo));
+ if ($errorCount !== $i) {
+ $output->writeln(str_repeat('-', 15) . PHP_EOL);
+ }
+ }
+ }
+
+ /**
+ * @param array $errorInfo
+ * @return string
+ */
+ private function formatMessage(array $errorInfo): string
+ {
+ ksort($errorInfo);
+ $result = '';
+
+ foreach ($errorInfo as $key => $value) {
+ $result .= sprintf('%s: %s' . PHP_EOL, $key, $value);
+ }
+
+ return $result;
+ }
+}
diff --git a/src/Config/Factory/Cache.php b/src/Config/Factory/Cache.php
index ee902494f6..eb7cf5b196 100644
--- a/src/Config/Factory/Cache.php
+++ b/src/Config/Factory/Cache.php
@@ -254,7 +254,7 @@ private function isConfigurationCompatibleWithSlaveConnection(
private function getUnsyncedConfigStructure(string $envCacheBackendModel, array $redisConfig): array
{
return [
- 'backend' => addslashes($envCacheBackendModel),
+ 'backend' => $envCacheBackendModel,
'backend_options' => [
'server' => $redisConfig['host'],
'port' => $redisConfig['port'],
@@ -272,9 +272,9 @@ private function getUnsyncedConfigStructure(string $envCacheBackendModel, array
private function getSynchronizedConfigStructure(string $envCacheBackendModel, array $redisConfig): array
{
return [
- 'backend' => addslashes($envCacheBackendModel),
+ 'backend' => $envCacheBackendModel,
'backend_options' => [
- 'remote_backend' => addslashes('\Magento\Framework\Cache\Backend\Redis'),
+ 'remote_backend' => '\Magento\Framework\Cache\Backend\Redis',
'remote_backend_options' => [
'server' => $redisConfig['host'],
'port' => $redisConfig['port'],
diff --git a/src/Config/Log.php b/src/Config/Log.php
index 6e73768204..60fbf421de 100644
--- a/src/Config/Log.php
+++ b/src/Config/Log.php
@@ -8,6 +8,7 @@
namespace Magento\MagentoCloud\Config;
use Illuminate\Contracts\Config\Repository;
+use Magento\MagentoCloud\App\Logger\Formatter\ErrorFormatterFactory;
use Magento\MagentoCloud\Filesystem\FileList;
use Magento\MagentoCloud\Config\Environment\ReaderInterface;
use Magento\MagentoCloud\App\Logger\HandlerFactory;
@@ -54,16 +55,27 @@ class Log
*/
private $repositoryFactory;
+ /**
+ * @var ErrorFormatterFactory
+ */
+ private $errorFormatterFactory;
+
/**
* @param FileList $fileList
* @param ReaderInterface $reader
* @param RepositoryFactory $repositoryFactory
+ * @param ErrorFormatterFactory $errorFormatterFactory
*/
- public function __construct(FileList $fileList, ReaderInterface $reader, RepositoryFactory $repositoryFactory)
- {
+ public function __construct(
+ FileList $fileList,
+ ReaderInterface $reader,
+ RepositoryFactory $repositoryFactory,
+ ErrorFormatterFactory $errorFormatterFactory
+ ) {
$this->fileList = $fileList;
$this->reader = $reader;
$this->repositoryFactory = $repositoryFactory;
+ $this->errorFormatterFactory = $errorFormatterFactory;
}
/**
@@ -110,7 +122,8 @@ private function getConfig(): array
HandlerFactory::HANDLER_FILE => ['file' => $this->fileList->getCloudLog()],
HandlerFactory::HANDLER_FILE_ERROR => [
'file' => $this->fileList->getCloudErrorLog(),
- 'min_level' => self::LEVEL_WARNING
+ 'min_level' => self::LEVEL_WARNING,
+ 'formatter' => $this->errorFormatterFactory->create()
],
],
$this->reader->read()[static::SECTION_CONFIG] ?? []
diff --git a/src/Config/Schema/Validator/SplitDb.php b/src/Config/Schema/Validator/SplitDb.php
index e6ffb4d91e..8416f6e9f4 100644
--- a/src/Config/Schema/Validator/SplitDb.php
+++ b/src/Config/Schema/Validator/SplitDb.php
@@ -37,7 +37,7 @@ public function validate(string $key, $value): ResultInterface
if (array_diff($value, DeployInterface::SPLIT_DB_VALUES)) {
return $this->resultFactory->error(sprintf(
'The %s variable contains the invalid value. '
- . 'It should be array with next available values: [%s].',
+ . 'It should be an array with following values: [%s].',
$key,
implode(', ', DeployInterface::SPLIT_DB_VALUES)
));
diff --git a/src/Config/SearchEngine.php b/src/Config/SearchEngine.php
index 86c5c040a9..c0d3c69b11 100644
--- a/src/Config/SearchEngine.php
+++ b/src/Config/SearchEngine.php
@@ -84,6 +84,7 @@ public function __construct(
* Returns search engine configuration. At least contains 'engine' option.
*
* @return array
+ * @throws ServiceException
*/
public function getConfig(): array
{
@@ -115,6 +116,7 @@ public function getConfig(): array
/**
* @return string
+ * @throws ServiceException
*/
public function getName(): string
{
@@ -125,6 +127,7 @@ public function getName(): string
* Checks if search engine is a prt of ElasticSearch family (i.e. ElasticSuite).
*
* @return bool
+ * @throws ServiceException
*/
public function isESFamily(): bool
{
diff --git a/src/Config/Stage/BuildInterface.php b/src/Config/Stage/BuildInterface.php
index 7e374edcf8..6b8f852b00 100644
--- a/src/Config/Stage/BuildInterface.php
+++ b/src/Config/Stage/BuildInterface.php
@@ -22,7 +22,12 @@ interface BuildInterface extends StageConfigInterface
public const VAR_ERROR_REPORT_DIR_NESTING_LEVEL = 'ERROR_REPORT_DIR_NESTING_LEVEL';
/**
- * Perfom Baler JS bundling
+ * Perform Baler JS bundling
*/
public const VAR_SCD_USE_BALER = 'SCD_USE_BALER';
+
+ /**
+ * Magento quality patches list
+ */
+ public const VAR_QUALITY_PATCHES = 'QUALITY_PATCHES';
}
diff --git a/src/Config/Validator/Build/AppropriateVersion.php b/src/Config/Validator/Build/AppropriateVersion.php
index fa25de4758..4675772295 100644
--- a/src/Config/Validator/Build/AppropriateVersion.php
+++ b/src/Config/Validator/Build/AppropriateVersion.php
@@ -7,6 +7,7 @@
namespace Magento\MagentoCloud\Config\Validator\Build;
+use Magento\MagentoCloud\App\Error;
use Magento\MagentoCloud\Config\Stage\BuildInterface;
use Magento\MagentoCloud\Config\StageConfigInterface;
use Magento\MagentoCloud\Config\Validator;
@@ -69,7 +70,8 @@ public function validate(): Validator\ResultInterface
if ($errors) {
return $this->resultFactory->error(
'The current configuration is not compatible with this version of Magento',
- implode(PHP_EOL, $errors)
+ implode(PHP_EOL, $errors),
+ Error::WARN_CONFIGURATION_VERSION_MISMATCH
);
}
diff --git a/src/Config/Validator/Build/BalerSupport.php b/src/Config/Validator/Build/BalerSupport.php
index 5a358f13f9..f2f18d6edb 100644
--- a/src/Config/Validator/Build/BalerSupport.php
+++ b/src/Config/Validator/Build/BalerSupport.php
@@ -4,6 +4,7 @@
namespace Magento\MagentoCloud\Config\Validator\Build;
+use Magento\MagentoCloud\App\Error;
use Magento\MagentoCloud\Config\Magento\Shared\ReaderInterface;
use Magento\MagentoCloud\Config\Validator;
use Magento\MagentoCloud\Config\ValidatorInterface;
@@ -79,7 +80,8 @@ public function validate(): Validator\ResultInterface
? $this->resultFactory->success()
: $this->resultFactory->error(
'Baler JS bundling cannot be used because of the following issues:',
- implode(PHP_EOL, $errors)
+ implode(PHP_EOL, $errors),
+ Error::WARN_BALER_CANNOT_BE_USED
);
}
}
diff --git a/src/Config/Validator/Build/ConfigFileExists.php b/src/Config/Validator/Build/ConfigFileExists.php
index f0ed8abfae..4205ef7afd 100644
--- a/src/Config/Validator/Build/ConfigFileExists.php
+++ b/src/Config/Validator/Build/ConfigFileExists.php
@@ -7,6 +7,7 @@
namespace Magento\MagentoCloud\Config\Validator\Build;
+use Magento\MagentoCloud\App\Error;
use Magento\MagentoCloud\Config\Validator;
use Magento\MagentoCloud\Config\ValidatorInterface;
use Magento\MagentoCloud\Filesystem\FileList;
@@ -69,13 +70,7 @@ public function validate(): Validator\ResultInterface
]
);
- return $this->resultFactory->create(
- Validator\ResultInterface::ERROR,
- [
- 'error' => $error,
- 'suggestion' => $suggestion
- ]
- );
+ return $this->resultFactory->error($error, $suggestion, Error::WARN_CONFIG_PHP_NOT_EXISTS);
}
return $this->resultFactory->create(Validator\ResultInterface::SUCCESS);
diff --git a/src/Config/Validator/Build/MagentoAppYaml.php b/src/Config/Validator/Build/MagentoAppYaml.php
new file mode 100644
index 0000000000..cbd28d1ea1
--- /dev/null
+++ b/src/Config/Validator/Build/MagentoAppYaml.php
@@ -0,0 +1,74 @@
+= 2.4.0
+ *
+ */
+class MagentoAppYaml implements ValidatorInterface
+{
+ /**
+ * @var Environment
+ */
+ private $environment;
+
+ /**
+ * @var MagentoVersion
+ */
+ private $magentoVersion;
+
+ /**
+ * @var Validator\ResultFactory
+ */
+ private $resultFactory;
+
+ /**
+ *
+ * @param Environment $environment
+ * @param MagentoVersion $magentoVersion
+ * @param Validator\ResultFactory $resultFactory
+ */
+ public function __construct(
+ Environment $environment,
+ MagentoVersion $magentoVersion,
+ Validator\ResultFactory $resultFactory
+ ) {
+ $this->environment = $environment;
+ $this->magentoVersion = $magentoVersion;
+ $this->resultFactory = $resultFactory;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function validate(): Validator\ResultInterface
+ {
+ try {
+ if ($this->magentoVersion->satisfies('>= 2.4.0')) {
+ $appData = $this->environment->getApplication();
+ if (isset($appData['variables']['env']['CONFIG__STORES__DEFAULT__PAYMENT__BRAINTREE__CHANNEL'])) {
+ return $this->resultFactory->errorByCode(AppError::BUILD_WRONG_BRAINTREE_VARIABLE);
+ }
+ }
+
+ return $this->resultFactory->success();
+ } catch (\Exception $e) {
+ throw new ValidatorException($e->getMessage(), $e->getCode(), $e);
+ }
+ }
+}
diff --git a/src/Config/Validator/Build/ModulesExists.php b/src/Config/Validator/Build/ModulesExists.php
index a5503161a5..882d583a09 100644
--- a/src/Config/Validator/Build/ModulesExists.php
+++ b/src/Config/Validator/Build/ModulesExists.php
@@ -7,6 +7,7 @@
namespace Magento\MagentoCloud\Config\Validator\Build;
+use Magento\MagentoCloud\App\Error;
use Magento\MagentoCloud\Config\Magento\Shared\ReaderInterface;
use Magento\MagentoCloud\Config\Validator;
use Magento\MagentoCloud\Config\ValidatorInterface;
@@ -43,6 +44,10 @@ public function validate(): Validator\ResultInterface
{
return isset($this->reader->read()['modules'])
? $this->resultFactory->success()
- : $this->resultFactory->error('The modules section is missing from the shared config file.');
+ : $this->resultFactory->error(
+ 'The modules section is missing from the shared config file.',
+ '',
+ Error::WARN_MISSED_MODULE_SECTION
+ );
}
}
diff --git a/src/Config/Validator/Build/ScdOptionsIgnorance.php b/src/Config/Validator/Build/ScdOptionsIgnorance.php
index ebd41e9cf4..7075cfc092 100644
--- a/src/Config/Validator/Build/ScdOptionsIgnorance.php
+++ b/src/Config/Validator/Build/ScdOptionsIgnorance.php
@@ -7,6 +7,7 @@
namespace Magento\MagentoCloud\Config\Validator\Build;
+use Magento\MagentoCloud\App\Error;
use Magento\MagentoCloud\Config\StageConfigInterface;
use Magento\MagentoCloud\Config\Validator;
use Magento\MagentoCloud\Config\ValidatorInterface;
@@ -70,12 +71,16 @@ public function validate(): Validator\ResultInterface
}
if (count($configuredScdVariables)) {
- return $this->resultFactory->error(sprintf(
- 'When %s, static content deployment does not run during the build phase ' .
- 'and the following variables are ignored: %s',
- $scdOnBuildResult->getError(),
- implode(', ', $configuredScdVariables)
- ));
+ return $this->resultFactory->error(
+ sprintf(
+ 'When %s, static content deployment does not run during the build phase ' .
+ 'and the following variables are ignored: %s',
+ $scdOnBuildResult->getError(),
+ implode(', ', $configuredScdVariables)
+ ),
+ '',
+ Error::WARN_SCD_OPTIONS_IGNORANCE
+ );
}
}
diff --git a/src/Config/Validator/Build/UnsupportedBuildOptionsIni.php b/src/Config/Validator/Build/UnsupportedBuildOptionsIni.php
index 013697d914..7d752b8f23 100644
--- a/src/Config/Validator/Build/UnsupportedBuildOptionsIni.php
+++ b/src/Config/Validator/Build/UnsupportedBuildOptionsIni.php
@@ -7,6 +7,7 @@
namespace Magento\MagentoCloud\Config\Validator\Build;
+use Magento\MagentoCloud\App\Error;
use Magento\MagentoCloud\Config\Validator;
use Magento\MagentoCloud\Config\Validator\ResultFactory;
use Magento\MagentoCloud\Config\ValidatorInterface;
@@ -58,7 +59,8 @@ public function validate(): Validator\ResultInterface
sprintf(
'Modify your configuration to specify build options in the %s file',
basename($this->fileList->getEnvConfig())
- )
+ ),
+ Error::WARN_UNSUPPORTED_BUILDS_OPTION_INI
);
}
diff --git a/src/Config/Validator/Deploy/AdminData.php b/src/Config/Validator/Deploy/AdminData.php
index 19d15ce80c..57a3e1340a 100644
--- a/src/Config/Validator/Deploy/AdminData.php
+++ b/src/Config/Validator/Deploy/AdminData.php
@@ -7,6 +7,7 @@
namespace Magento\MagentoCloud\Config\Validator\Deploy;
+use Magento\MagentoCloud\App\Error;
use Magento\MagentoCloud\Config\AdminDataInterface;
use Magento\MagentoCloud\Config\State;
use Magento\MagentoCloud\Config\ValidatorInterface;
@@ -72,7 +73,9 @@ public function validate(): ResultInterface
if ($this->state->isInstalled() && $data) {
return $this->resultFactory->error(
'The following admin data is required to create an admin user during initial installation'
- . ' only and is ignored during upgrade process: ' . implode(', ', $data)
+ . ' only and is ignored during upgrade process: ' . implode(', ', $data),
+ '',
+ Error::WARN_ADMIN_DATA_IGNORED
);
}
@@ -80,14 +83,15 @@ public function validate(): ResultInterface
return $this->resultFactory->error(
'The following admin data was ignored and an admin was not created '
. 'because admin email is not set: ' . implode(', ', $data),
- 'Create an admin user via ssh manually: bin/magento admin:user:create'
+ 'Create an admin user via ssh manually: bin/magento admin:user:create',
+ Error::WARN_ADMIN_EMAIL_NOT_SET
);
}
}
return $this->resultFactory->success();
} catch (\Exception $e) {
- // Exception on this step is not critical and can be only logged without interraption of the process
+ // Exception on this step is not critical and can be only logged without interruption of the process
return $this->resultFactory->error($e->getMessage());
}
}
diff --git a/src/Config/Validator/Deploy/AppropriateVersion.php b/src/Config/Validator/Deploy/AppropriateVersion.php
index 1e438f81ec..236e22146e 100644
--- a/src/Config/Validator/Deploy/AppropriateVersion.php
+++ b/src/Config/Validator/Deploy/AppropriateVersion.php
@@ -7,6 +7,7 @@
namespace Magento\MagentoCloud\Config\Validator\Deploy;
+use Magento\MagentoCloud\App\Error;
use Magento\MagentoCloud\Config\Stage\DeployInterface;
use Magento\MagentoCloud\Config\Validator;
use Magento\MagentoCloud\Config\ValidatorInterface;
@@ -83,7 +84,8 @@ public function validate(): Validator\ResultInterface
if ($errors) {
return $this->resultFactory->error(
'The current configuration is not compatible with this version of Magento',
- implode(PHP_EOL, $errors)
+ implode(PHP_EOL, $errors),
+ Error::WARN_CONFIG_NOT_COMPATIBLE
);
}
diff --git a/src/Config/Validator/Deploy/DatabaseSplitConnection.php b/src/Config/Validator/Deploy/DatabaseSplitConnection.php
index 3d4af0836b..e7ec38889e 100644
--- a/src/Config/Validator/Deploy/DatabaseSplitConnection.php
+++ b/src/Config/Validator/Deploy/DatabaseSplitConnection.php
@@ -7,6 +7,7 @@
namespace Magento\MagentoCloud\Config\Validator\Deploy;
+use Magento\MagentoCloud\App\Error;
use Magento\MagentoCloud\Config\ConfigException;
use Magento\MagentoCloud\Config\Database\DbConfig;
use Magento\MagentoCloud\Config\Stage\DeployInterface;
@@ -69,7 +70,8 @@ public function validate(): Validator\ResultInterface
. 'Magento Cloud does not support a custom split database configuration,'
. ' such configurations will be ignored',
DeployInterface::VAR_DATABASE_CONFIGURATION,
- implode(PHP_EOL, $messageItem)
+ implode(PHP_EOL, $messageItem),
+ Error::WARN_WRONG_SPLIT_DB_CONFIG
));
}
}
diff --git a/src/Config/Validator/Deploy/DebugLogging.php b/src/Config/Validator/Deploy/DebugLogging.php
index 1eae7d5a30..e5a21d4a13 100644
--- a/src/Config/Validator/Deploy/DebugLogging.php
+++ b/src/Config/Validator/Deploy/DebugLogging.php
@@ -7,6 +7,7 @@
namespace Magento\MagentoCloud\Config\Validator\Deploy;
+use Magento\MagentoCloud\App\Error;
use Magento\MagentoCloud\Config\Magento\SystemInterface;
use Magento\MagentoCloud\Config\ValidatorInterface;
use Magento\MagentoCloud\Config\Environment;
@@ -65,8 +66,8 @@ public function validate(): ResultInterface
return $this->resultFactory->error(
'Debug logging is enabled in Magento',
- 'To save space in Magento Cloud, '
- . 'debug logging should not be enabled for your production environments.'
+ 'To save space in Magento Cloud, disable debug logging for your production environments.',
+ Error::WARN_DEBUG_LOG_ENABLED
);
}
}
diff --git a/src/Config/Validator/Deploy/DeprecatedSearchEngine.php b/src/Config/Validator/Deploy/DeprecatedSearchEngine.php
index dda3f1db92..9369ef24b3 100644
--- a/src/Config/Validator/Deploy/DeprecatedSearchEngine.php
+++ b/src/Config/Validator/Deploy/DeprecatedSearchEngine.php
@@ -7,6 +7,7 @@
namespace Magento\MagentoCloud\Config\Validator\Deploy;
+use Magento\MagentoCloud\App\Error;
use Magento\MagentoCloud\Config\SearchEngine;
use Magento\MagentoCloud\Config\Validator;
use Magento\MagentoCloud\Config\ValidatorInterface;
@@ -43,7 +44,9 @@ public function validate(): Validator\ResultInterface
{
if (SearchEngine::ENGINE_MYSQL === $this->searchEngine->getName()) {
return $this->resultFactory->error(
- 'The MySQL search configuration option is deprecated. Use Elasticsearch instead.'
+ 'The MySQL search configuration option is deprecated. Use Elasticsearch instead.',
+ '',
+ Error::WARN_DEPRECATED_MYSQL_SEARCH_ENGINE
);
}
diff --git a/src/Config/Validator/Deploy/DeprecatedVariables.php b/src/Config/Validator/Deploy/DeprecatedVariables.php
index 006f7305d9..ddce2716a5 100644
--- a/src/Config/Validator/Deploy/DeprecatedVariables.php
+++ b/src/Config/Validator/Deploy/DeprecatedVariables.php
@@ -7,6 +7,7 @@
namespace Magento\MagentoCloud\Config\Validator\Deploy;
+use Magento\MagentoCloud\App\Error;
use Magento\MagentoCloud\Config\Environment;
use Magento\MagentoCloud\Config\Stage\DeployInterface;
use Magento\MagentoCloud\Config\Validator;
@@ -63,7 +64,8 @@ public function validate(): Validator\ResultInterface
'The %s variable contains deprecated value. Use one of the next values: %s.',
DeployInterface::VAR_VERBOSE_COMMANDS,
implode(',', ['-v', '-vv', '-vvv'])
- )
+ ),
+ Error::WARN_DEPRECATED_VARIABLES
);
}
diff --git a/src/Config/Validator/Deploy/ElasticSearchIntegrity.php b/src/Config/Validator/Deploy/ElasticSearchIntegrity.php
index ab2a3be9b5..67f0fe1cd4 100644
--- a/src/Config/Validator/Deploy/ElasticSearchIntegrity.php
+++ b/src/Config/Validator/Deploy/ElasticSearchIntegrity.php
@@ -7,9 +7,11 @@
namespace Magento\MagentoCloud\Config\Validator\Deploy;
+use Magento\MagentoCloud\App\Error;
use Magento\MagentoCloud\Config\Validator;
use Magento\MagentoCloud\Config\ValidatorException;
use Magento\MagentoCloud\Config\ValidatorInterface;
+use Magento\MagentoCloud\Filesystem\FileSystemException;
use Magento\MagentoCloud\Package\MagentoVersion;
use Magento\MagentoCloud\Package\UndefinedPackageException;
use Magento\MagentoCloud\Service\ElasticSearch;
@@ -58,9 +60,9 @@ public function validate(): Validator\ResultInterface
if ($this->magentoVersion->isGreaterOrEqual('2.4.0')
&& !$this->elasticsearch->isInstalled()
) {
- return $this->resultFactory->error('Magento 2.4.0 requires Elasticsearch service to be installed.');
+ return $this->resultFactory->errorByCode(Error::DEPLOY_WRONG_SEARCH_ENGINE);
}
- } catch (UndefinedPackageException $exception) {
+ } catch (UndefinedPackageException | FileSystemException $exception) {
throw new ValidatorException($exception->getMessage(), $exception->getCode(), $exception);
}
diff --git a/src/Config/Validator/Deploy/ElasticSearchUsage.php b/src/Config/Validator/Deploy/ElasticSearchUsage.php
index 4873acf92a..67c25a9558 100644
--- a/src/Config/Validator/Deploy/ElasticSearchUsage.php
+++ b/src/Config/Validator/Deploy/ElasticSearchUsage.php
@@ -7,10 +7,13 @@
namespace Magento\MagentoCloud\Config\Validator\Deploy;
+use Magento\MagentoCloud\App\Error;
use Magento\MagentoCloud\Config\Validator;
+use Magento\MagentoCloud\Config\ValidatorException;
use Magento\MagentoCloud\Config\ValidatorInterface;
use Magento\MagentoCloud\Config\SearchEngine;
use Magento\MagentoCloud\Service\ElasticSearch;
+use Magento\MagentoCloud\Service\ServiceException;
/**
* Validates that different search engine configured when elasticsearch service is installed.
@@ -53,21 +56,26 @@ public function __construct(
* configured as elasticsearch or elasticsuite.
* Otherwise returns error.
*
- * @return Validator\ResultInterface
+ * {@inheritDoc}
*/
public function validate(): Validator\ResultInterface
{
- if (!$this->elasticSearch->isInstalled()) {
- return $this->resultFactory->success();
- }
+ try {
+ if (!$this->elasticSearch->isInstalled()) {
+ return $this->resultFactory->success();
+ }
- if ($this->searchEngine->isESFamily()) {
- return $this->resultFactory->success();
+ if ($this->searchEngine->isESFamily()) {
+ return $this->resultFactory->success();
+ }
+ } catch (ServiceException $e) {
+ throw new ValidatorException($e->getMessage(), $e->getCode(), $e);
}
return $this->resultFactory->error(
'Elasticsearch service is installed at infrastructure layer but is not used as a search engine.',
- 'Consider removing elasticsearch service from infrastructure layer for optimized resource usage.'
+ 'Consider removing the Elasticsearch service from the infrastructure layer for optimized resource usage.',
+ Error::WARN_ES_INSTALLED_BUT_NOT_USED
);
}
}
diff --git a/src/Config/Validator/Deploy/ElasticSearchVersion.php b/src/Config/Validator/Deploy/ElasticSearchVersion.php
index ab772decfd..941a0a09d6 100644
--- a/src/Config/Validator/Deploy/ElasticSearchVersion.php
+++ b/src/Config/Validator/Deploy/ElasticSearchVersion.php
@@ -9,6 +9,7 @@
use Composer\Semver\Comparator;
use Composer\Semver\Semver;
+use Magento\MagentoCloud\App\Error;
use Magento\MagentoCloud\Config\SearchEngine;
use Magento\MagentoCloud\Config\Validator;
use Magento\MagentoCloud\Config\ValidatorException;
@@ -132,8 +133,8 @@ public function validate(): Validator\ResultInterface
try {
$esServiceVersion = $this->elasticSearch->getVersion();
- } catch (ServiceException $exception) {
- throw new ValidatorException($exception->getMessage(), $exception->getCode(), $exception);
+ } catch (ServiceException $e) {
+ throw new ValidatorException($e->getMessage(), $e->getCode(), $e);
}
if (!$this->searchEngine->isESFamily()) {
@@ -202,6 +203,6 @@ private function generateError(
];
}
- return $this->resultFactory->error($error, implode(PHP_EOL, $suggestion));
+ return $this->resultFactory->error($error, implode(PHP_EOL, $suggestion), Error::WARN_ES_VERSION_MISMATCH);
}
}
diff --git a/src/Config/Validator/Deploy/EnvironmentVariables.php b/src/Config/Validator/Deploy/EnvironmentVariables.php
new file mode 100644
index 0000000000..f9c0b007fa
--- /dev/null
+++ b/src/Config/Validator/Deploy/EnvironmentVariables.php
@@ -0,0 +1,70 @@
+= 2.4.0
+ */
+class EnvironmentVariables implements ValidatorInterface
+{
+ /**
+ * @var Environment
+ */
+ private $environment;
+
+ /**
+ * @var Validator\ResultFactory
+ */
+ private $resultFactory;
+
+ /**
+ * @var MagentoVersion
+ */
+ private $magentoVersion;
+
+ /**
+ * @param Environment $environment
+ * @param MagentoVersion $magentoVersion
+ * @param Validator\ResultFactory $resultFactory
+ */
+ public function __construct(
+ Environment $environment,
+ MagentoVersion $magentoVersion,
+ Validator\ResultFactory $resultFactory
+ ) {
+ $this->environment = $environment;
+ $this->magentoVersion = $magentoVersion;
+ $this->resultFactory = $resultFactory;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function validate(): Validator\ResultInterface
+ {
+ try {
+ if ($this->magentoVersion->satisfies('>= 2.4.0')
+ && $this->environment->getEnv('CONFIG__STORES__DEFAULT__PAYMENT__BRAINTREE__CHANNEL')
+ ) {
+ return $this->resultFactory->errorByCode(Error::DEPLOY_WRONG_BRAINTREE_VARIABLE);
+ }
+
+ return $this->resultFactory->success();
+ } catch (\Exception $e) {
+ throw new ValidatorException($e->getMessage(), $e->getCode(), $e);
+ }
+ }
+}
diff --git a/src/Config/Validator/Deploy/JsonFormatVariable.php b/src/Config/Validator/Deploy/JsonFormatVariable.php
index f9aa3f744f..c555b99673 100644
--- a/src/Config/Validator/Deploy/JsonFormatVariable.php
+++ b/src/Config/Validator/Deploy/JsonFormatVariable.php
@@ -7,6 +7,7 @@
namespace Magento\MagentoCloud\Config\Validator\Deploy;
+use Magento\MagentoCloud\App\Error;
use Magento\MagentoCloud\Config\Schema;
use Magento\MagentoCloud\Config\Stage\Deploy\MergedConfig;
use Magento\MagentoCloud\Config\StageConfigInterface;
@@ -74,7 +75,11 @@ public function validate(): Validator\ResultInterface
}
if ($errors) {
- return $this->resultFactory->error('Next variables can\'t be decoded: ' . implode(', ', $errors));
+ return $this->resultFactory->error(
+ 'Next variables can\'t be decoded: ' . implode(', ', $errors),
+ '',
+ Error::WARN_CONFIG_WRONG_JSON_FORMAT
+ );
}
} catch (\Exception $e) {
return $this->resultFactory->error('Can\'t read merged configuration: ' . $e->getMessage());
diff --git a/src/Config/Validator/Deploy/MagentoCloudVariables.php b/src/Config/Validator/Deploy/MagentoCloudVariables.php
index 4abb7edd47..a0a1e477cc 100644
--- a/src/Config/Validator/Deploy/MagentoCloudVariables.php
+++ b/src/Config/Validator/Deploy/MagentoCloudVariables.php
@@ -7,6 +7,7 @@
namespace Magento\MagentoCloud\Config\Validator\Deploy;
+use Magento\MagentoCloud\App\Error;
use Magento\MagentoCloud\Config\Environment;
use Magento\MagentoCloud\Config\Stage\DeployInterface;
use Magento\MagentoCloud\Config\Validator;
@@ -63,7 +64,8 @@ public function validate(): Validator\ResultInterface
if ($errors) {
return $this->resultFactory->error(
'Environment configuration is not valid',
- implode(PHP_EOL, $errors)
+ implode(PHP_EOL, $errors),
+ Error::WARN_ENVIRONMENT_CONFIG_NOT_VALID
);
}
diff --git a/src/Config/Validator/Deploy/PhpVersion.php b/src/Config/Validator/Deploy/PhpVersion.php
index 9086cadbbe..cce3091d51 100644
--- a/src/Config/Validator/Deploy/PhpVersion.php
+++ b/src/Config/Validator/Deploy/PhpVersion.php
@@ -10,6 +10,7 @@
use Composer\Composer;
use Composer\Package\Version\VersionParser;
use Composer\Semver\Constraint\ConstraintInterface;
+use Magento\MagentoCloud\App\Error;
use Magento\MagentoCloud\Config\GlobalSection;
use Magento\MagentoCloud\Config\ValidatorInterface;
use Magento\MagentoCloud\Config\Validator;
@@ -101,7 +102,8 @@ public function validate(): Validator\ResultInterface
$currentPhpConstraint->getPrettyString()
),
"Change the version of PHP to the version that satisfies the restriction conditions.\n"
- . 'Change the PHP version in the .magento.app.yaml file or create a support ticket'
+ . 'Change the PHP version in the .magento.app.yaml file, or create a support ticket',
+ Error::WARN_UPDATE_PHP_VERSION
);
}
} catch (\Exception $e) {
diff --git a/src/Config/Validator/Deploy/ReportDirNestingLevel.php b/src/Config/Validator/Deploy/ReportDirNestingLevel.php
index 90df3536a6..d51efce546 100644
--- a/src/Config/Validator/Deploy/ReportDirNestingLevel.php
+++ b/src/Config/Validator/Deploy/ReportDirNestingLevel.php
@@ -7,6 +7,7 @@
namespace Magento\MagentoCloud\Config\Validator\Deploy;
+use Magento\MagentoCloud\App\Error;
use Magento\MagentoCloud\Config\Environment;
use Magento\MagentoCloud\Config\ValidatorInterface;
use Magento\MagentoCloud\Filesystem\ConfigFileList;
@@ -84,18 +85,24 @@ public function validate(): Validator\ResultInterface
return $this->resultFactory->error(
'The directory nesting level value for error reporting has not been configured.',
- 'You can configure the setting using the `config.report.dir_nesting_level`'
- . ' in the file ' . $reportConfigFile
+ 'You can configure the setting using the `config.report.dir_nesting_level` variable'
+ . ' in the file ' . $reportConfigFile,
+ Error::WARN_DIR_NESTING_LEVEL_NOT_CONFIGURED
);
} catch (FileSystemException $exception) {
return $this->resultFactory->error($exception->getMessage());
} catch (NotEncodableValueException $exception) {
- $message = sprintf('Config of the file %s is invalid. ', $reportConfigFile);
- $message .= $exception->getMessage();
+ $message = sprintf(
+ 'Invalid configuration in the %s file. %s',
+ $reportConfigFile,
+ $exception->getMessage()
+ );
+
return $this->resultFactory->error(
$message,
'Fix the directory nesting level configuration for error reporting in the file '
- . $reportConfigFile
+ . $reportConfigFile,
+ Error::WARN_NOT_CORRECT_LOCAL_XML_FILE
);
}
}
diff --git a/src/Config/Validator/Deploy/ScdOptionsIgnorance.php b/src/Config/Validator/Deploy/ScdOptionsIgnorance.php
index fe2dab2448..2793f41138 100644
--- a/src/Config/Validator/Deploy/ScdOptionsIgnorance.php
+++ b/src/Config/Validator/Deploy/ScdOptionsIgnorance.php
@@ -7,6 +7,7 @@
namespace Magento\MagentoCloud\Config\Validator\Deploy;
+use Magento\MagentoCloud\App\Error;
use Magento\MagentoCloud\Config\StageConfigInterface;
use Magento\MagentoCloud\Config\Validator;
use Magento\MagentoCloud\Config\ValidatorInterface;
@@ -69,12 +70,16 @@ public function validate(): Validator\ResultInterface
}
if (count($configuredScdVariables)) {
- return $this->resultFactory->error(sprintf(
- 'When %s, static content deployment does not run during the deploy phase ' .
- 'and the following variables are ignored: %s',
- $scdOnDeployResult->getError(),
- implode(', ', $configuredScdVariables)
- ));
+ return $this->resultFactory->error(
+ sprintf(
+ 'When %s, static content deployment does not run during the deploy phase ' .
+ 'and the following variables are ignored: %s',
+ $scdOnDeployResult->getError(),
+ implode(', ', $configuredScdVariables)
+ ),
+ '',
+ Error::WARN_DEPLOY_SCD_OPTIONS_IGNORANCE
+ );
}
}
diff --git a/src/Config/Validator/Deploy/ServiceEol.php b/src/Config/Validator/Deploy/ServiceEol.php
index 0288e4fc82..f1c270b739 100644
--- a/src/Config/Validator/Deploy/ServiceEol.php
+++ b/src/Config/Validator/Deploy/ServiceEol.php
@@ -7,6 +7,7 @@
namespace Magento\MagentoCloud\Config\Validator\Deploy;
+use Magento\MagentoCloud\App\Error;
use Magento\MagentoCloud\Config\Validator;
use Magento\MagentoCloud\Filesystem\FileSystemException;
use Magento\MagentoCloud\Service\EolValidator as EOLValidator;
@@ -65,7 +66,8 @@ public function validate(): Validator\ResultInterface
'Some services are approaching EOL.';
return $this->resultFactory->error(
$message,
- implode(PHP_EOL, $errors[$this->errorLevel])
+ implode(PHP_EOL, $errors[$this->errorLevel]),
+ $this->errorLevel == ValidatorInterface::LEVEL_WARNING ? Error::WARN_SERVICE_PASSED_EOL : null
);
}
} catch (ServiceMismatchException $e) {
diff --git a/src/Config/Validator/Deploy/ServiceVersion.php b/src/Config/Validator/Deploy/ServiceVersion.php
index 2bc3de2e76..4170186b7b 100644
--- a/src/Config/Validator/Deploy/ServiceVersion.php
+++ b/src/Config/Validator/Deploy/ServiceVersion.php
@@ -7,6 +7,7 @@
namespace Magento\MagentoCloud\Config\Validator\Deploy;
+use Magento\MagentoCloud\App\Error;
use Magento\MagentoCloud\App\GenericException;
use Magento\MagentoCloud\Service\ServiceInterface;
use Magento\MagentoCloud\Service\ServiceFactory;
@@ -78,7 +79,8 @@ public function validate(): Validator\ResultInterface
if ($errors) {
return $this->resultFactory->error(
'The current configuration is not compatible with this version of Magento',
- implode(PHP_EOL, $errors)
+ implode(PHP_EOL, $errors),
+ Error::WARN_SERVICE_VERSION_NOT_COMPATIBLE
);
}
} catch (GenericException $e) {
diff --git a/src/Config/Validator/Deploy/SolrIntegrity.php b/src/Config/Validator/Deploy/SolrIntegrity.php
index 4b060d9eeb..499c5be99b 100644
--- a/src/Config/Validator/Deploy/SolrIntegrity.php
+++ b/src/Config/Validator/Deploy/SolrIntegrity.php
@@ -7,6 +7,7 @@
namespace Magento\MagentoCloud\Config\Validator\Deploy;
+use Magento\MagentoCloud\App\Error;
use Magento\MagentoCloud\Config\Environment;
use Magento\MagentoCloud\Config\ValidatorInterface;
use Magento\MagentoCloud\Config\Validator\ResultFactory;
@@ -62,12 +63,14 @@ public function validate(): ResultInterface
if ($this->magentoVersion->satisfies('2.1.*')) {
$args['suggestion'] = 'Solr support has been deprecated in Magento 2.1. ' .
- 'Update your search engine to Elasticsearch and remove this relationship.';
+ 'Remove this relationship and use Elasticsearch.';
+ $args['errorCode'] = Error::WARN_SOLR_DEPRECATED;
}
if ($this->magentoVersion->satisfies('>=2.2')) {
$args['suggestion'] = 'Solr is no longer supported by Magento 2.2 or later. ' .
'Remove this relationship and use Elasticsearch.';
+ $args['errorCode'] = Error::WARN_SOLR_NOT_SUPPORTED;
}
return $this->resultFactory->create(ResultInterface::ERROR, $args);
diff --git a/src/Config/Validator/IdealState.php b/src/Config/Validator/IdealState.php
index 312008d3d1..b13483b608 100644
--- a/src/Config/Validator/IdealState.php
+++ b/src/Config/Validator/IdealState.php
@@ -53,7 +53,11 @@ public function validate(): ResultInterface
return $suggestion . PHP_EOL;
}, '');
- return $this->resultFactory->error('The configured state is not ideal', trim($suggestion));
+ return $this->resultFactory->error(
+ 'The configured state is not ideal',
+ trim($suggestion),
+ \Magento\MagentoCloud\App\Error::WARN_CONFIGURATION_STATE_NOT_IDEAL
+ );
}
return $this->resultFactory->success();
diff --git a/src/Config/Validator/ResultFactory.php b/src/Config/Validator/ResultFactory.php
index bd7a781348..1d4a8a0e6c 100644
--- a/src/Config/Validator/ResultFactory.php
+++ b/src/Config/Validator/ResultFactory.php
@@ -7,14 +7,29 @@
namespace Magento\MagentoCloud\Config\Validator;
+use Magento\MagentoCloud\App\ErrorInfo;
use Magento\MagentoCloud\Config\Validator\Result\Error;
use Magento\MagentoCloud\Config\Validator\Result\Success;
+use Magento\MagentoCloud\Filesystem\FileSystemException;
/**
* Creates instance of ResultInterface object
*/
class ResultFactory
{
+ /**
+ * @var ErrorInfo
+ */
+ private $errorInfo;
+
+ /**
+ * @param ErrorInfo $errorInfo
+ */
+ public function __construct(ErrorInfo $errorInfo)
+ {
+ $this->errorInfo = $errorInfo;
+ }
+
/**
* Creates instance of ResultInterface object
*
@@ -53,4 +68,23 @@ public function error(string $message, string $suggestion = '', int $code = null
{
return new Error($message, $suggestion, $code);
}
+
+ /**
+ * Creates Error object, fetches info about error from .schema.error.yaml file by code.
+ * Uses for errors with static error message and suggestion.
+ *
+ * @param int $code
+ * @return Error
+ * @throws FileSystemException
+ */
+ public function errorByCode(int $code): Error
+ {
+ $errorData = $this->errorInfo->get($code);
+
+ return new Error(
+ $errorData['title'] ?? '',
+ $errorData['suggestion'] ?? '',
+ $code
+ );
+ }
}
diff --git a/src/DB/Data/ConnectionFactory.php b/src/DB/Data/ConnectionFactory.php
index b6fbed30f9..8050093763 100644
--- a/src/DB/Data/ConnectionFactory.php
+++ b/src/DB/Data/ConnectionFactory.php
@@ -68,7 +68,7 @@ public function create(string $connectionType): ConnectionInterface
return $this->getConnectionData(DbConfig::CONNECTION_SALES, false);
default:
throw new RuntimeException(
- sprintf('Connection with type %s doesn\'t exist', $connectionType)
+ sprintf('Connection with type %s does not exist', $connectionType)
);
}
}
diff --git a/src/DB/Data/RelationshipConnectionFactory.php b/src/DB/Data/RelationshipConnectionFactory.php
index 083ee7de9e..4f1db41519 100644
--- a/src/DB/Data/RelationshipConnectionFactory.php
+++ b/src/DB/Data/RelationshipConnectionFactory.php
@@ -66,7 +66,7 @@ public function create(string $connectionType): ConnectionInterface
break;
default:
throw new \RuntimeException(
- sprintf('Connection with type %s doesn\'t exist', $connectionType)
+ sprintf('Connection with type %s does not exist', $connectionType)
);
}
diff --git a/src/Filesystem/DirectoryCopier/CopyStrategy.php b/src/Filesystem/DirectoryCopier/CopyStrategy.php
index 92757f5b51..7a1042f77c 100644
--- a/src/Filesystem/DirectoryCopier/CopyStrategy.php
+++ b/src/Filesystem/DirectoryCopier/CopyStrategy.php
@@ -43,7 +43,7 @@ public function copy(string $fromDirectory, string $toDirectory): bool
{
if (!$this->file->isExists($fromDirectory)) {
throw new FileSystemException(
- sprintf('Can\'t copy directory %s. Directory does not exist.', $fromDirectory)
+ sprintf('Cannot copy directory %s. Directory does not exist.', $fromDirectory)
);
}
diff --git a/src/Filesystem/DirectoryCopier/CopySubFolderStrategy.php b/src/Filesystem/DirectoryCopier/CopySubFolderStrategy.php
index fd841c3e6c..72a93cee6d 100644
--- a/src/Filesystem/DirectoryCopier/CopySubFolderStrategy.php
+++ b/src/Filesystem/DirectoryCopier/CopySubFolderStrategy.php
@@ -48,7 +48,7 @@ public function copy(string $fromDirectory, string $toDirectory): bool
{
if (!$this->file->isExists($fromDirectory)) {
throw new FileSystemException(
- sprintf('Can\'t copy directory %s. Directory does not exist.', $fromDirectory)
+ sprintf('Cannot copy directory %s. Directory does not exist.', $fromDirectory)
);
}
diff --git a/src/Filesystem/DirectoryCopier/StrategyFactory.php b/src/Filesystem/DirectoryCopier/StrategyFactory.php
index c57f266c96..bfde92e512 100644
--- a/src/Filesystem/DirectoryCopier/StrategyFactory.php
+++ b/src/Filesystem/DirectoryCopier/StrategyFactory.php
@@ -49,7 +49,7 @@ public function create(string $strategy): StrategyInterface
break;
default:
throw new \RuntimeException(
- sprintf('Strategy "%s" doesn\'t exist', $strategy)
+ sprintf('Strategy "%s" does not exist', $strategy)
);
}
diff --git a/src/Filesystem/DirectoryCopier/SubSymlinkStrategy.php b/src/Filesystem/DirectoryCopier/SubSymlinkStrategy.php
index cae85f6edd..bb6d1343fc 100644
--- a/src/Filesystem/DirectoryCopier/SubSymlinkStrategy.php
+++ b/src/Filesystem/DirectoryCopier/SubSymlinkStrategy.php
@@ -52,7 +52,7 @@ public function copy(string $fromDirectory, string $toDirectory): bool
if ($fromDirectory === false || !$this->file->isExists($fromDirectory)) {
throw new FileSystemException(
- sprintf('Can\'t copy directory "%s". Directory does not exist.', $fromDirectory)
+ sprintf('Cannot copy directory "%s". Directory does not exist.', $fromDirectory)
);
}
diff --git a/src/Filesystem/DirectoryCopier/SymlinkStrategy.php b/src/Filesystem/DirectoryCopier/SymlinkStrategy.php
index 901002def6..5c451387bd 100644
--- a/src/Filesystem/DirectoryCopier/SymlinkStrategy.php
+++ b/src/Filesystem/DirectoryCopier/SymlinkStrategy.php
@@ -49,7 +49,7 @@ public function copy(string $fromDirectory, string $toDirectory): bool
if (!$this->file->isExists($fromDirectory)) {
throw new FileSystemException(
- sprintf('Can\'t copy directory %s. Directory does not exist.', $fromDirectory)
+ sprintf('Cannot copy directory %s. Directory does not exist.', $fromDirectory)
);
}
diff --git a/src/Filesystem/FileList.php b/src/Filesystem/FileList.php
index 3964c7b36a..bf4481b479 100644
--- a/src/Filesystem/FileList.php
+++ b/src/Filesystem/FileList.php
@@ -179,4 +179,32 @@ public function getErrorSchema(): string
{
return $this->directoryList->getRoot() . '/config/schema.error.yaml';
}
+
+ /**
+ * @return string
+ * @throws UndefinedPackageException
+ */
+ public function getPatchLog(): string
+ {
+ return $this->directoryList->getLog() . '/patch.log';
+ }
+
+ /**
+ * @return string
+ * @throws UndefinedPackageException
+ */
+ public function getInitPatchLog(): string
+ {
+ return $this->directoryList->getInit() . '/var/log/patch.log';
+ }
+
+ /**
+ * Returns path to doc file generated from schema.error.yaml
+ *
+ * @return string
+ */
+ public function getErrorDistConfig(): string
+ {
+ return $this->directoryList->getRoot() . '/dist/error-codes.md';
+ }
}
diff --git a/src/Filesystem/RecoverableDirectoryList.php b/src/Filesystem/RecoverableDirectoryList.php
index e45169a71d..5c9590253f 100644
--- a/src/Filesystem/RecoverableDirectoryList.php
+++ b/src/Filesystem/RecoverableDirectoryList.php
@@ -7,12 +7,15 @@
namespace Magento\MagentoCloud\Filesystem;
+use Magento\MagentoCloud\Config\ConfigException;
use Magento\MagentoCloud\Config\Environment;
use Magento\MagentoCloud\Config\GlobalSection;
use Magento\MagentoCloud\Config\Stage\DeployInterface;
use Magento\MagentoCloud\Filesystem\DirectoryCopier\StrategyInterface;
+use Magento\MagentoCloud\Filesystem\Flag\ConfigurationMismatchException;
use Magento\MagentoCloud\Filesystem\Flag\Manager as FlagManager;
use Magento\MagentoCloud\Package\MagentoVersion;
+use Magento\MagentoCloud\Package\UndefinedPackageException;
/**
* Returns list of recoverable directories
@@ -81,6 +84,10 @@ public function __construct(
* Returns list of recoverable directories with recover strategy types.
*
* @return array
+ *
+ * @throws ConfigException
+ * @throws ConfigurationMismatchException
+ * @throws UndefinedPackageException
*/
public function getList(): array
{
diff --git a/src/Patch/Manager.php b/src/Patch/Manager.php
index ef80f74bb5..d74a2f3696 100644
--- a/src/Patch/Manager.php
+++ b/src/Patch/Manager.php
@@ -56,16 +56,16 @@ public function __construct(
*/
public function apply(): void
{
- $this->logger->notice('Applying patches');
-
- $command = 'php ./vendor/bin/ece-patches apply';
-
if ($this->globalSection->get(GlobalSection::VAR_DEPLOYED_MAGENTO_VERSION_FROM_GIT)) {
- $command .= ' --git-installation 1';
+ $this->logger->info('Git-based installation. Skipping patches applying');
+
+ return;
}
+ $this->logger->notice('Applying patches');
+
try {
- $this->shell->execute($command);
+ $this->shell->execute('php ./vendor/bin/ece-patches apply --no-interaction');
} catch (ShellException $exception) {
$this->logger->error($exception->getMessage());
throw $exception;
diff --git a/src/Scenario/Processor.php b/src/Scenario/Processor.php
index e6ac71824a..ad66fadec1 100644
--- a/src/Scenario/Processor.php
+++ b/src/Scenario/Processor.php
@@ -10,7 +10,6 @@
use Magento\MagentoCloud\OnFail\Action\ActionException;
use Magento\MagentoCloud\OnFail\Action\ActionInterface;
use Magento\MagentoCloud\Package\Manager;
-use Magento\MagentoCloud\Step\StepException;
use Magento\MagentoCloud\Step\StepInterface;
use Magento\MagentoCloud\Scenario\Exception\ProcessorException;
use Psr\Log\LoggerInterface;
@@ -64,11 +63,19 @@ public function execute(array $scenarios): void
implode(', ', $scenarios),
$this->packageManager->getPrettyInfo()
));
+ $steps = [];
try {
$this->mergedScenarios = $this->merger->merge($scenarios);
$steps = $this->mergedScenarios['steps'];
+ } catch (Throwable $exception) {
+ $this->handleException(
+ $exception,
+ sprintf('Unhandled error: %s', $exception->getMessage())
+ );
+ }
+ try {
array_walk($steps, function (StepInterface $step, string $name) {
$this->logger->debug('Running step: ' . $name);
@@ -76,31 +83,35 @@ public function execute(array $scenarios): void
$this->logger->debug(sprintf('Step "%s" finished', $name));
});
- } catch (StepException $stepException) {
- try {
- $actions = $this->mergedScenarios['actions'];
-
- array_walk($actions, function (ActionInterface $action, string $name) {
- $this->logger->debug('Running on fail action: ' . $name);
-
- $action->execute();
-
- $this->logger->debug(sprintf('On fail action "%s" finished', $name));
- });
- } catch (ActionException $actionException) {
- $this->logger->error($actionException->getMessage());
- }
+ } catch (Throwable $stepException) {
+ $this->runActions();
$this->handleException($stepException);
- } catch (Throwable $exception) {
- $this->handleException(
- $exception,
- sprintf('Unhandled error: [%d] %s', $exception->getCode(), $exception->getMessage())
- );
}
$this->logger->info('Scenario(s) finished');
}
+ /**
+ * Run scenario actions.
+ * @return void
+ */
+ private function runActions(): void
+ {
+ try {
+ $actions = $this->mergedScenarios['actions'];
+
+ array_walk($actions, function (ActionInterface $action, string $name) {
+ $this->logger->debug('Running on fail action: ' . $name);
+
+ $action->execute();
+
+ $this->logger->debug(sprintf('On fail action "%s" finished', $name));
+ });
+ } catch (ActionException $actionException) {
+ $this->logger->error($actionException->getMessage());
+ }
+ }
+
/**
* Logs error message and throws ProcessorException
*
@@ -111,9 +122,9 @@ public function execute(array $scenarios): void
private function handleException(Throwable $exception, string $message = ''): void
{
if (empty($message)) {
- $message = sprintf('[%d] %s', $exception->getCode(), $exception->getMessage());
+ $message = sprintf('%s', $exception->getMessage());
}
- $this->logger->error($message);
+ $this->logger->error($message, ['errorCode' => $exception->getCode()]);
throw new ProcessorException(
$message,
diff --git a/src/Service/ElasticSearch.php b/src/Service/ElasticSearch.php
index 4579a7e497..045af64275 100644
--- a/src/Service/ElasticSearch.php
+++ b/src/Service/ElasticSearch.php
@@ -8,6 +8,7 @@
namespace Magento\MagentoCloud\Service;
use Composer\Semver\Semver;
+use Magento\MagentoCloud\App\Error;
use Magento\MagentoCloud\Config\Environment;
use Magento\MagentoCloud\Http\ClientFactory;
use Psr\Log\LoggerInterface;
@@ -101,7 +102,10 @@ public function getVersion(): string
$this->version = $esConfiguration['version']['number'];
} catch (Throwable $exception) {
- throw new ServiceException('Can\'t get version of elasticsearch: ' . $exception->getMessage());
+ throw new ServiceException(
+ 'Can\'t get version of elasticsearch: ' . $exception->getMessage(),
+ Error::DEPLOY_ES_CANNOT_CONNECT
+ );
}
}
diff --git a/src/Service/Validator.php b/src/Service/Validator.php
index 9c5c296af6..5a9fed8f88 100644
--- a/src/Service/Validator.php
+++ b/src/Service/Validator.php
@@ -49,8 +49,8 @@ class Validator
'<2.2.0' => '~1.7.0 || ~2.4.0',
'>=2.2.0 <2.2.8 || 2.3.0' => '~1.7.0 || ~2.4.0 || ~5.2.0',
'>=2.2.8 <2.3.0 || >=2.3.1 <2.3.5' => '~1.7.0 || ~2.4.0 || ~5.2.0 || ~6.5.0',
- '>=2.3.5 <2.4.0' => '~1.7.0 || ~2.4.0 || ~5.2.0 || ~6.5.0 || ~6.8.0|| ~7.4.0 || ~7.5.0 || ~7.6.0 || ~7.7.0',
- '>=2.4.0' => '~7.4.0 || ~7.5.0 || ~7.6.0 || ~7.7.0',
+ '>=2.3.5 <2.4.0' => '~1.7.0 || ~2.4.0 || ~5.2.0 || ~6.5.0 || ~6.8.0 || ~7.5.0 || ~7.6.0 || ~7.7.0',
+ '>=2.4.0' => '~7.5.0 || ~7.6.0 || ~7.7.0',
],
ServiceInterface::NAME_RABBITMQ => [
'<2.3.0' => '~3.5.0',
diff --git a/src/StaticContent/ThreadCountOptimizer.php b/src/StaticContent/ThreadCountOptimizer.php
index ff16c47fa0..fcf398db8a 100644
--- a/src/StaticContent/ThreadCountOptimizer.php
+++ b/src/StaticContent/ThreadCountOptimizer.php
@@ -9,6 +9,7 @@
use Magento\MagentoCloud\Config\StageConfigInterface;
use Magento\MagentoCloud\Package\MagentoVersion;
+use Magento\MagentoCloud\Package\UndefinedPackageException;
use Magento\MagentoCloud\Util\Cpu;
use Psr\Log\LoggerInterface;
@@ -65,6 +66,7 @@ public function __construct(LoggerInterface $logger, MagentoVersion $magentoVers
* @param int $threads
* @param string $strategy
* @return int
+ * @throws UndefinedPackageException
*/
public function optimize(int $threads, string $strategy): int
{
diff --git a/src/Step/Build/DeployStaticContent.php b/src/Step/Build/DeployStaticContent.php
index 3f5f1cfa42..98ab752e15 100644
--- a/src/Step/Build/DeployStaticContent.php
+++ b/src/Step/Build/DeployStaticContent.php
@@ -10,6 +10,7 @@
use Magento\MagentoCloud\Config\Validator\GlobalStage\ScdOnBuild;
use Magento\MagentoCloud\Config\Validator\Result\Error;
use Magento\MagentoCloud\Filesystem\Flag\Manager as FlagManager;
+use Magento\MagentoCloud\Step\StepException;
use Magento\MagentoCloud\Step\StepInterface;
use Psr\Log\LoggerInterface;
@@ -61,23 +62,29 @@ public function __construct(
*/
public function execute()
{
- $this->flagManager->delete(FlagManager::FLAG_STATIC_CONTENT_DEPLOY_IN_BUILD);
+ try {
+ $this->flagManager->delete(FlagManager::FLAG_STATIC_CONTENT_DEPLOY_IN_BUILD);
- $result = $this->scdOnBuild->validate();
+ $result = $this->scdOnBuild->validate();
- if ($result instanceof Error) {
- $this->logger->notice('Skipping static content deploy: ' . $result->getError());
+ if ($result instanceof Error) {
+ $this->logger->notice('Skipping static content deploy: ' . $result->getError());
- return;
- }
+ return;
+ }
- $this->logger->notice('Generating fresh static content');
+ $this->logger->notice('Generating fresh static content');
- foreach ($this->steps as $step) {
- $step->execute();
- }
+ foreach ($this->steps as $step) {
+ $step->execute();
+ }
- $this->flagManager->set(FlagManager::FLAG_STATIC_CONTENT_DEPLOY_IN_BUILD);
- $this->logger->notice('End of generating fresh static content');
+ $this->flagManager->set(FlagManager::FLAG_STATIC_CONTENT_DEPLOY_IN_BUILD);
+ $this->logger->notice('End of generating fresh static content');
+ } catch (StepException $e) {
+ throw $e;
+ } catch (\Exception $e) {
+ throw new StepException($e->getMessage(), $e->getCode(), $e);
+ }
}
}
diff --git a/src/Step/Build/DeployStaticContent/Generate.php b/src/Step/Build/DeployStaticContent/Generate.php
index 545d122e19..940d30ee7a 100644
--- a/src/Step/Build/DeployStaticContent/Generate.php
+++ b/src/Step/Build/DeployStaticContent/Generate.php
@@ -8,7 +8,7 @@
namespace Magento\MagentoCloud\Step\Build\DeployStaticContent;
use Magento\MagentoCloud\App\Error;
-use Magento\MagentoCloud\Config\ConfigException;
+use Magento\MagentoCloud\App\GenericException;
use Magento\MagentoCloud\Config\Stage\BuildInterface;
use Magento\MagentoCloud\Step\StepException;
use Magento\MagentoCloud\Step\StepInterface;
@@ -74,18 +74,18 @@ public function __construct(
*/
public function execute(): void
{
- $locales = $this->buildOption->getLocales();
- $threadCount = $this->buildOption->getThreadCount();
+ try {
+ $locales = $this->buildOption->getLocales();
+ $threadCount = $this->buildOption->getThreadCount();
- $logMessage = 'Generating static content for locales: ' . implode(' ', $locales);
+ $logMessage = 'Generating static content for locales: ' . implode(' ', $locales);
- if ($threadCount) {
- $logMessage .= PHP_EOL . 'Using ' . $threadCount . ' Threads';
- }
+ if ($threadCount) {
+ $logMessage .= PHP_EOL . 'Using ' . $threadCount . ' Threads';
+ }
- $this->logger->info($logMessage);
+ $this->logger->info($logMessage);
- try {
$commands = $this->commandFactory->matrix(
$this->buildOption,
$this->buildConfig->get(BuildInterface::VAR_SCD_MATRIX)
@@ -96,7 +96,7 @@ public function execute(): void
}
} catch (ShellException $e) {
throw new StepException($e->getMessage(), Error::BUILD_SCD_FAILED, $e);
- } catch (ConfigException $e) {
+ } catch (GenericException $e) {
throw new StepException($e->getMessage(), $e->getCode(), $e);
}
}
diff --git a/src/Step/Build/PreBuild.php b/src/Step/Build/PreBuild.php
index 0d082c7d30..b40e32a33d 100644
--- a/src/Step/Build/PreBuild.php
+++ b/src/Step/Build/PreBuild.php
@@ -10,6 +10,7 @@
use Magento\MagentoCloud\Filesystem\DirectoryList;
use Magento\MagentoCloud\Filesystem\Driver\File;
use Magento\MagentoCloud\Filesystem\Flag\Manager as FlagManager;
+use Magento\MagentoCloud\Step\StepException;
use Magento\MagentoCloud\Step\StepInterface;
use Magento\MagentoCloud\Config\Stage\BuildInterface;
use Psr\Log\LoggerInterface;
@@ -70,29 +71,33 @@ public function __construct(
*/
public function execute()
{
- $verbosityLevel = $this->stageConfig->get(BuildInterface::VAR_VERBOSE_COMMANDS);
+ try {
+ $verbosityLevel = $this->stageConfig->get(BuildInterface::VAR_VERBOSE_COMMANDS);
- $generatedCode = $this->directoryList->getGeneratedCode();
- $generatedMetadata = $this->directoryList->getGeneratedMetadata();
+ $generatedCode = $this->directoryList->getGeneratedCode();
+ $generatedMetadata = $this->directoryList->getGeneratedMetadata();
- $this->logger->info('Verbosity level is ' . ($verbosityLevel ?: 'not set'));
+ $this->logger->info('Verbosity level is ' . ($verbosityLevel ?: 'not set'));
- $this->flagManager->delete(FlagManager::FLAG_STATIC_CONTENT_DEPLOY_IN_BUILD);
+ $this->flagManager->delete(FlagManager::FLAG_STATIC_CONTENT_DEPLOY_IN_BUILD);
- if ($this->file->isExists($generatedCode)) {
- $this->logger->info(
- 'Generated code exists from an old deployment - clearing it now.',
- ['metadataPath' => $generatedCode]
- );
- $this->file->clearDirectory($generatedCode);
- }
+ if ($this->file->isExists($generatedCode)) {
+ $this->logger->info(
+ 'Generated code exists from an old deployment - clearing it now.',
+ ['metadataPath' => $generatedCode]
+ );
+ $this->file->clearDirectory($generatedCode);
+ }
- if ($this->file->isExists($generatedMetadata)) {
- $this->logger->info(
- 'Generated metadata exists from an old deployment - clearing it now.',
- ['metadataPath' => $generatedMetadata]
- );
- $this->file->clearDirectory($generatedMetadata);
+ if ($this->file->isExists($generatedMetadata)) {
+ $this->logger->info(
+ 'Generated metadata exists from an old deployment - clearing it now.',
+ ['metadataPath' => $generatedMetadata]
+ );
+ $this->file->clearDirectory($generatedMetadata);
+ }
+ } catch (\Exception $e) {
+ throw new StepException($e->getMessage(), $e->getCode(), $e);
}
}
}
diff --git a/src/Step/Build/RunBaler.php b/src/Step/Build/RunBaler.php
index 4bc38af12f..a0ed82511a 100644
--- a/src/Step/Build/RunBaler.php
+++ b/src/Step/Build/RunBaler.php
@@ -86,7 +86,7 @@ public function execute()
$result = $this->validator->validate();
if ($result instanceof Result\Error) {
- $this->logger->warning($result->getError());
+ $this->logger->warning($result->getError(), ['errorCode' => $result->getErrorCode()]);
foreach (explode(PHP_EOL, $result->getSuggestion()) as $detail) {
$this->logger->warning(' - ' . $detail);
diff --git a/src/Step/Deploy/InstallUpdate.php b/src/Step/Deploy/InstallUpdate.php
index acdd8c2d10..4fcd694f9a 100644
--- a/src/Step/Deploy/InstallUpdate.php
+++ b/src/Step/Deploy/InstallUpdate.php
@@ -7,6 +7,7 @@
namespace Magento\MagentoCloud\Step\Deploy;
+use Magento\MagentoCloud\App\Error;
use Magento\MagentoCloud\App\GenericException;
use Magento\MagentoCloud\Config\State;
use Magento\MagentoCloud\Filesystem\Flag\Manager as FlagManager;
@@ -78,10 +79,13 @@ public function execute()
$this->logger->notice('End of install.');
} else {
if ($this->flagManager->exists(FlagManager::FLAG_ENV_FILE_ABSENCE)) {
- $this->logger->warning('Magento state indicated as installed'
+ $this->logger->warning(
+ 'Magento state indicated as installed'
. ' but configuration file app/etc/env.php was empty or did not exist.'
. ' Required data will be restored from environment configurations'
- . ' and from .magento.env.yaml file.');
+ . ' and from .magento.env.yaml file.',
+ ['errorCode' => Error::WARN_ENV_PHP_MISSED]
+ );
}
$this->logger->notice('Starting update.');
diff --git a/src/Step/Deploy/InstallUpdate/ConfigUpdate/Amqp.php b/src/Step/Deploy/InstallUpdate/ConfigUpdate/Amqp.php
index 806f75e874..e6e6f90cbe 100644
--- a/src/Step/Deploy/InstallUpdate/ConfigUpdate/Amqp.php
+++ b/src/Step/Deploy/InstallUpdate/ConfigUpdate/Amqp.php
@@ -7,6 +7,10 @@
namespace Magento\MagentoCloud\Step\Deploy\InstallUpdate\ConfigUpdate;
+use Magento\MagentoCloud\App\Error;
+use Magento\MagentoCloud\App\GenericException;
+use Magento\MagentoCloud\Filesystem\FileSystemException;
+use Magento\MagentoCloud\Step\StepException;
use Magento\MagentoCloud\Step\StepInterface;
use Magento\MagentoCloud\Config\Magento\Env\ReaderInterface as ConfigReader;
use Magento\MagentoCloud\Config\Magento\Env\WriterInterface as ConfigWriter;
@@ -69,17 +73,25 @@ public function __construct(
*/
public function execute()
{
- $config = $this->configReader->read();
- $amqpConfig = $this->amqpConfig->get();
+ try {
+ $config = $this->configReader->read();
+ $amqpConfig = $this->amqpConfig->get();
+ } catch (GenericException $e) {
+ throw new StepException($e->getMessage(), $e->getCode(), $e);
+ }
- if (count($amqpConfig)) {
- $this->logger->info('Updating env.php AMQP configuration.');
- $config['queue'] = $amqpConfig;
- $this->configWriter->create($config);
- } elseif (isset($config['queue'])) {
- $this->logger->info('Removing queue configuration from env.php.');
- unset($config['queue']);
- $this->configWriter->create($config);
+ try {
+ if (count($amqpConfig)) {
+ $this->logger->info('Updating env.php AMQP configuration.');
+ $config['queue'] = $amqpConfig;
+ $this->configWriter->create($config);
+ } elseif (isset($config['queue'])) {
+ $this->logger->info('Removing queue configuration from env.php.');
+ unset($config['queue']);
+ $this->configWriter->create($config);
+ }
+ } catch (FileSystemException $e) {
+ throw new StepException($e->getMessage(), Error::DEPLOY_ENV_PHP_IS_NOT_WRITABLE, $e);
}
}
}
diff --git a/src/Step/Deploy/InstallUpdate/ConfigUpdate/CronConsumersRunner.php b/src/Step/Deploy/InstallUpdate/ConfigUpdate/CronConsumersRunner.php
index 2de14f5ffb..03531c7c1d 100644
--- a/src/Step/Deploy/InstallUpdate/ConfigUpdate/CronConsumersRunner.php
+++ b/src/Step/Deploy/InstallUpdate/ConfigUpdate/CronConsumersRunner.php
@@ -7,12 +7,16 @@
namespace Magento\MagentoCloud\Step\Deploy\InstallUpdate\ConfigUpdate;
+use Magento\MagentoCloud\App\Error;
+use Magento\MagentoCloud\App\GenericException;
use Magento\MagentoCloud\Config\Environment;
use Magento\MagentoCloud\Config\Magento\Env\ReaderInterface as ConfigReader;
use Magento\MagentoCloud\Config\Magento\Env\WriterInterface as ConfigWriter;
use Magento\MagentoCloud\Config\RepositoryFactory;
use Magento\MagentoCloud\Config\Stage\DeployInterface;
+use Magento\MagentoCloud\Filesystem\FileSystemException;
use Magento\MagentoCloud\Package\MagentoVersion;
+use Magento\MagentoCloud\Step\StepException;
use Magento\MagentoCloud\Step\StepInterface;
use Psr\Log\LoggerInterface;
@@ -93,22 +97,30 @@ public function __construct(
*/
public function execute()
{
- if (!$this->magentoVersion->isGreaterOrEqual('2.2')) {
- return;
- }
-
- $this->logger->info('Updating env.php cron consumers runner configuration.');
- $config = $this->configReader->read();
- $runnerConfig = $this->repositoryFactory->create(
- $this->stageConfig->get(DeployInterface::VAR_CRON_CONSUMERS_RUNNER)
- );
+ try {
+ if (!$this->magentoVersion->isGreaterOrEqual('2.2')) {
+ return;
+ }
+
+ $this->logger->info('Updating env.php cron consumers runner configuration.');
+ $config = $this->configReader->read();
+ $runnerConfig = $this->repositoryFactory->create(
+ $this->stageConfig->get(DeployInterface::VAR_CRON_CONSUMERS_RUNNER)
+ );
- $config['cron_consumers_runner'] = [
- 'cron_run' => $runnerConfig->get('cron_run') === true,
- 'max_messages' => $runnerConfig->get('max_messages', static::DEFAULT_MAX_MESSAGES),
- 'consumers' => $runnerConfig->get('consumers', []),
- ];
+ $config['cron_consumers_runner'] = [
+ 'cron_run' => $runnerConfig->get('cron_run') === true,
+ 'max_messages' => $runnerConfig->get('max_messages', static::DEFAULT_MAX_MESSAGES),
+ 'consumers' => $runnerConfig->get('consumers', []),
+ ];
+ } catch (GenericException $e) {
+ throw new StepException($e->getMessage(), $e->getCode(), $e);
+ }
- $this->configWriter->create($config);
+ try {
+ $this->configWriter->create($config);
+ } catch (FileSystemException $e) {
+ throw new StepException($e->getMessage(), Error::DEPLOY_ENV_PHP_IS_NOT_WRITABLE, $e);
+ }
}
}
diff --git a/src/Step/Deploy/InstallUpdate/ConfigUpdate/DbConnection.php b/src/Step/Deploy/InstallUpdate/ConfigUpdate/DbConnection.php
index 4985e63326..571cc29163 100644
--- a/src/Step/Deploy/InstallUpdate/ConfigUpdate/DbConnection.php
+++ b/src/Step/Deploy/InstallUpdate/ConfigUpdate/DbConnection.php
@@ -7,6 +7,8 @@
namespace Magento\MagentoCloud\Step\Deploy\InstallUpdate\ConfigUpdate;
+use Magento\MagentoCloud\App\Error;
+use Magento\MagentoCloud\App\GenericException;
use Magento\MagentoCloud\Config\ConfigException;
use Magento\MagentoCloud\Config\ConfigMerger;
use Magento\MagentoCloud\Config\Database\DbConfig;
@@ -18,11 +20,14 @@
use Magento\MagentoCloud\Filesystem\FileSystemException;
use Magento\MagentoCloud\Filesystem\Flag\ConfigurationMismatchException;
use Magento\MagentoCloud\Filesystem\Flag\Manager as FlagManager;
+use Magento\MagentoCloud\Step\StepException;
use Magento\MagentoCloud\Step\StepInterface;
use Psr\Log\LoggerInterface;
/**
* Updates DB connection configuration.
+ *
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class DbConnection implements StepInterface
{
@@ -129,49 +134,53 @@ public function __construct(
*/
public function execute()
{
- $dbConfig = $this->getDbConfigData();
+ try {
+ $dbConfig = $this->getDbConfigData();
+
+ if (!isset($dbConfig[DbConfig::KEY_CONNECTION])) {
+ /**
+ * Is calling only in case when database relationship configuration doesn't exist and
+ * database is not configured through .magento.env.yaml or env variable.
+ * It's workaround for scenarios when magento was installed by raw setup:install command
+ * not by deploy scripts.
+ */
+ $this->logger->notice(
+ 'Database relationship configuration does not exist'
+ . ' and database is not configured through .magento.env.yaml or env variable.'
+ . ' Will be applied the previous database configuration.'
+ );
+ return;
+ }
- if (!isset($dbConfig[DbConfig::KEY_CONNECTION])) {
- /**
- * Is calling only in case when database relationship configuration doesn't exist and
- * database is not configured through .magento.env.yaml or env variable.
- * It's workaround for scenarios when magento was installed by raw setup:install command
- * not by deploy scripts.
- */
- $this->logger->notice(
- 'Database relationship configuration doesn\'t exist'
- . ' and database is not configured through .magento.env.yaml or env variable.'
- . ' Will be applied the previous database configuration.'
- );
- return;
- }
+ $this->logger->info('Updating env.php DB connection configuration.');
- $this->logger->info('Updating env.php DB connection configuration.');
+ $mageSplitConnectionsConfig = $this->getMageSplitConnectionsConfig();
- $mageSplitConnectionsConfig = $this->getMageSplitConnectionsConfig();
+ $useSlave = $this->stageConfig->get(DeployInterface::VAR_MYSQL_USE_SLAVE_CONNECTION);
- $useSlave = $this->stageConfig->get(DeployInterface::VAR_MYSQL_USE_SLAVE_CONNECTION);
+ if (empty($mageSplitConnectionsConfig)) {
+ $this->setOnlyMainConnectionsConfig($useSlave);
+ return;
+ }
- if (empty($mageSplitConnectionsConfig)) {
- $this->setOnlyMainConnectionsConfig($useSlave);
- return;
- }
+ $customSplitConnections = $this->getDifferentConnections(
+ $mageSplitConnectionsConfig,
+ $dbConfig[DbConfig::KEY_CONNECTION]
+ );
- $customSplitConnections = $this->getDifferentConnections(
- $mageSplitConnectionsConfig,
- $dbConfig[DbConfig::KEY_CONNECTION]
- );
+ if (!empty($customSplitConnections)) {
+ $this->logger->warning(
+ sprintf('For split databases used custom connections: %s', implode(', ', $customSplitConnections)),
+ ['errorCode' => Error::WARN_SPLIT_DB_CUSTOM_CONNECTION_USED]
+ );
+ $this->flagManager->set(FlagManager::FLAG_IGNORE_SPLIT_DB);
+ return;
+ }
- if (!empty($customSplitConnections)) {
- $this->logger->warning(sprintf(
- 'For split databases used custom connections: %s',
- implode(', ', $customSplitConnections)
- ));
- $this->flagManager->set(FlagManager::FLAG_IGNORE_SPLIT_DB);
- return;
+ $this->updateConnectionsConfig($mageSplitConnectionsConfig, $useSlave);
+ } catch (GenericException $e) {
+ throw new StepException($e->getMessage(), $e->getCode(), $e);
}
-
- $this->updateConnectionsConfig($mageSplitConnectionsConfig, $useSlave);
}
/**
@@ -318,10 +327,13 @@ private function addLoggingAboutSlaveConnection(array $dbConfig)
DbConfig::CONNECTION_DEFAULT,
$connectionData
)) {
- $this->logger->warning(sprintf(
- 'You have changed db configuration that not compatible with %s slave connection.',
- DbConfig::CONNECTION_DEFAULT
- ));
+ $this->logger->warning(
+ sprintf(
+ 'You have changed db configuration that not compatible with %s slave connection.',
+ DbConfig::CONNECTION_DEFAULT
+ ),
+ ['errorCode' => Error::WARN_DB_CONFIG_NOT_COMPATIBLE_WITH_SLAVE]
+ );
} elseif (!empty($dbConfig[DbConfig::KEY_SLAVE_CONNECTION][DbConfig::CONNECTION_DEFAULT])) {
$this->logger->info(sprintf('Set DB slave connection for %s connection.', DbConfig::CONNECTION_DEFAULT));
} else {
diff --git a/src/Step/Deploy/InstallUpdate/ConfigUpdate/DocumentRoot.php b/src/Step/Deploy/InstallUpdate/ConfigUpdate/DocumentRoot.php
index 398cda3c2d..fcd9422706 100644
--- a/src/Step/Deploy/InstallUpdate/ConfigUpdate/DocumentRoot.php
+++ b/src/Step/Deploy/InstallUpdate/ConfigUpdate/DocumentRoot.php
@@ -7,6 +7,9 @@
namespace Magento\MagentoCloud\Step\Deploy\InstallUpdate\ConfigUpdate;
+use Magento\MagentoCloud\App\Error;
+use Magento\MagentoCloud\Filesystem\FileSystemException;
+use Magento\MagentoCloud\Step\StepException;
use Magento\MagentoCloud\Step\StepInterface;
use Psr\Log\LoggerInterface;
use Magento\MagentoCloud\Config\Magento\Env\WriterInterface as ConfigWriter;
@@ -43,7 +46,11 @@ public function __construct(
*/
public function execute()
{
- $this->logger->info('The value of the property \'directories/document_root_is_pub\' set as \'true\'');
- $this->configWriter->update(['directories' => ['document_root_is_pub' => true]]);
+ try {
+ $this->logger->info('The value of the property \'directories/document_root_is_pub\' set as \'true\'');
+ $this->configWriter->update(['directories' => ['document_root_is_pub' => true]]);
+ } catch (FileSystemException $e) {
+ throw new StepException($e->getMessage(), Error::DEPLOY_ENV_PHP_IS_NOT_WRITABLE, $e);
+ }
}
}
diff --git a/src/Step/Deploy/InstallUpdate/ConfigUpdate/Lock.php b/src/Step/Deploy/InstallUpdate/ConfigUpdate/Lock.php
index 6e66577854..d806b3911c 100644
--- a/src/Step/Deploy/InstallUpdate/ConfigUpdate/Lock.php
+++ b/src/Step/Deploy/InstallUpdate/ConfigUpdate/Lock.php
@@ -7,6 +7,8 @@
namespace Magento\MagentoCloud\Step\Deploy\InstallUpdate\ConfigUpdate;
+use Magento\MagentoCloud\App\GenericException;
+use Magento\MagentoCloud\Step\StepException;
use Magento\MagentoCloud\Step\StepInterface;
use Magento\MagentoCloud\Config\Magento\Env\ReaderInterface as ConfigReader;
use Magento\MagentoCloud\Config\Magento\Env\WriterInterface as ConfigWriter;
@@ -72,15 +74,19 @@ public function __construct(
*/
public function execute()
{
- /**
- * Since Magento 2.2.5 we can configure lock providers.
- */
- if ($this->magentoVersion->isGreaterOrEqual('2.2.5')) {
- $lockConfig = $this->lockConfig->get();
- $config = $this->configReader->read();
- $config['lock'] = $lockConfig;
- $this->configWriter->create($config);
- $this->logger->info(sprintf('The lock provider "%s" was set.', $lockConfig['provider']));
+ try {
+ /**
+ * Since Magento 2.2.5 we can configure lock providers.
+ */
+ if ($this->magentoVersion->isGreaterOrEqual('2.2.5')) {
+ $lockConfig = $this->lockConfig->get();
+ $config = $this->configReader->read();
+ $config['lock'] = $lockConfig;
+ $this->configWriter->create($config);
+ $this->logger->info(sprintf('The lock provider "%s" was set.', $lockConfig['provider']));
+ }
+ } catch (GenericException $e) {
+ throw new StepException($e->getMessage(), $e->getCode(), $e);
}
}
}
diff --git a/src/Step/Deploy/InstallUpdate/ConfigUpdate/Session.php b/src/Step/Deploy/InstallUpdate/ConfigUpdate/Session.php
index b21a6a4b42..ec5e7cb752 100644
--- a/src/Step/Deploy/InstallUpdate/ConfigUpdate/Session.php
+++ b/src/Step/Deploy/InstallUpdate/ConfigUpdate/Session.php
@@ -7,7 +7,11 @@
namespace Magento\MagentoCloud\Step\Deploy\InstallUpdate\ConfigUpdate;
+use Magento\MagentoCloud\App\Error;
+use Magento\MagentoCloud\App\GenericException;
+use Magento\MagentoCloud\Filesystem\FileSystemException;
use Magento\MagentoCloud\Step\Deploy\InstallUpdate\ConfigUpdate\Session\Config;
+use Magento\MagentoCloud\Step\StepException;
use Magento\MagentoCloud\Step\StepInterface;
use Magento\MagentoCloud\Config\Magento\Env\ReaderInterface as ConfigReader;
use Magento\MagentoCloud\Config\Magento\Env\WriterInterface as ConfigWriter;
@@ -63,17 +67,25 @@ public function __construct(
*/
public function execute()
{
- $config = $this->configReader->read();
- $sessionConfig = $this->sessionConfig->get();
+ try {
+ $config = $this->configReader->read();
+ $sessionConfig = $this->sessionConfig->get();
- if (!empty($sessionConfig)) {
- $this->logger->info('Updating session configuration.');
- $config['session'] = $sessionConfig;
- } else {
- $this->logger->info('Removing session configuration from env.php.');
- $config['session'] = ['save' => 'db'];
+ if (!empty($sessionConfig)) {
+ $this->logger->info('Updating session configuration.');
+ $config['session'] = $sessionConfig;
+ } else {
+ $this->logger->info('Removing session configuration from env.php.');
+ $config['session'] = ['save' => 'db'];
+ }
+ } catch (GenericException $e) {
+ throw new StepException($e->getMessage(), $e->getCode(), $e);
}
- $this->configWriter->create($config);
+ try {
+ $this->configWriter->create($config);
+ } catch (FileSystemException $e) {
+ throw new StepException($e->getMessage(), Error::DEPLOY_ENV_PHP_IS_NOT_WRITABLE, $e);
+ }
}
}
diff --git a/src/Step/Deploy/InstallUpdate/ConfigUpdate/Urls.php b/src/Step/Deploy/InstallUpdate/ConfigUpdate/Urls.php
index 00a31a0be8..222673b002 100644
--- a/src/Step/Deploy/InstallUpdate/ConfigUpdate/Urls.php
+++ b/src/Step/Deploy/InstallUpdate/ConfigUpdate/Urls.php
@@ -7,10 +7,12 @@
namespace Magento\MagentoCloud\Step\Deploy\InstallUpdate\ConfigUpdate;
+use Magento\MagentoCloud\App\GenericException;
use Magento\MagentoCloud\Config\Environment;
use Magento\MagentoCloud\Config\Stage\DeployInterface;
use Magento\MagentoCloud\Step\Deploy\InstallUpdate\ConfigUpdate\Urls\Database;
use Magento\MagentoCloud\Step\Deploy\InstallUpdate\ConfigUpdate\Urls\Environment as EnvironmentUrl;
+use Magento\MagentoCloud\Step\StepException;
use Magento\MagentoCloud\Step\StepInterface;
use Psr\Log\LoggerInterface;
@@ -70,28 +72,32 @@ public function __construct(
* Always run if FORCE_UPDATE_URLS set to true
* Skip url updates if master branch is detected or UPDATE_URLS set to false
*
- * @inheritdoc
+ * {@inheritdoc}
*/
public function execute()
{
- if (!$this->stageConfig->get(DeployInterface::VAR_FORCE_UPDATE_URLS)) {
- if ($this->environment->isMasterBranch()) {
- $this->logger->info(
- 'Skipping URL updates because we are deploying to a Production or Staging environment.'
- . ' You can override this behavior by setting the FORCE_URL_UPDATES variable to true.'
- );
- return;
- }
+ try {
+ if (!$this->stageConfig->get(DeployInterface::VAR_FORCE_UPDATE_URLS)) {
+ if ($this->environment->isMasterBranch()) {
+ $this->logger->info(
+ 'Skipping URL updates because we are deploying to a Production or Staging environment.'
+ . ' You can override this behavior by setting the FORCE_URL_UPDATES variable to true.'
+ );
+ return;
+ }
- if (!$this->stageConfig->get(DeployInterface::VAR_UPDATE_URLS)) {
- $this->logger->info('Skipping URL updates because the URL_UPDATES variable is set to false.');
- return;
+ if (!$this->stageConfig->get(DeployInterface::VAR_UPDATE_URLS)) {
+ $this->logger->info('Skipping URL updates because the URL_UPDATES variable is set to false.');
+ return;
+ }
}
- }
- $this->logger->info('Updating secure and unsecure URLs');
+ $this->logger->info('Updating secure and unsecure URLs');
- $this->databaseUrl->execute();
- $this->environmentUrl->execute();
+ $this->databaseUrl->execute();
+ $this->environmentUrl->execute();
+ } catch (GenericException $e) {
+ throw new StepException($e->getMessage(), $e->getCode(), $e);
+ }
}
}
diff --git a/src/Step/Deploy/PreDeploy/CleanRedisCache.php b/src/Step/Deploy/PreDeploy/CleanRedisCache.php
index a4dd127e6c..2527ee087a 100644
--- a/src/Step/Deploy/PreDeploy/CleanRedisCache.php
+++ b/src/Step/Deploy/PreDeploy/CleanRedisCache.php
@@ -64,7 +64,7 @@ public function execute(): void
}
foreach ($cacheConfigs['frontend'] as $cacheType => $cacheConfig) {
- $backend = stripslashes($cacheConfig['backend']);
+ $backend = $cacheConfig['backend'];
if (!in_array($backend, CacheConfig::AVAILABLE_REDIS_BACKEND, true)) {
continue;
diff --git a/src/Step/Deploy/PreDeploy/ConfigUpdate/Cache.php b/src/Step/Deploy/PreDeploy/ConfigUpdate/Cache.php
index cbd98b9628..6ab704eaa2 100644
--- a/src/Step/Deploy/PreDeploy/ConfigUpdate/Cache.php
+++ b/src/Step/Deploy/PreDeploy/ConfigUpdate/Cache.php
@@ -79,7 +79,7 @@ public function execute()
if (isset($cacheConfig['frontend'])) {
$cacheConfig['frontend'] = array_filter($cacheConfig['frontend'], function ($cacheFrontend) {
- $backend = stripslashes($cacheFrontend['backend']);
+ $backend = $cacheFrontend['backend'];
$this->checkBackendModel($backend);
if (!in_array($backend, CacheFactory::AVAILABLE_REDIS_BACKEND, true)) {
@@ -99,7 +99,8 @@ public function execute()
unset($config['cache']);
} elseif (empty($cacheConfig['frontend'])) {
$this->logger->warning(
- 'Cache is configured for a Redis service that is not available. Configuration will be ignored.'
+ 'Cache is configured for a Redis service that is not available. Configuration will be ignored.',
+ ['errorCode' => Error::WARN_REDIS_SERVICE_NOT_AVAILABLE]
);
unset($config['cache']);
} else {
@@ -127,7 +128,7 @@ private function checkBackendModel(string $backend): void
];
try {
- if (in_array($backend, $notAllowedBackend, true) && !$this->magentoVersion->isGreaterOrEqual('2.3.5')) {
+ if (in_array($backend, $notAllowedBackend, true) && !$this->magentoVersion->isGreaterOrEqual('2.3.0')) {
throw new StepException(
sprintf(
'Magento version \'%s\' does not support Redis backend model \'%s\'',
diff --git a/src/Step/Deploy/PreDeploy/RestorePatchLog.php b/src/Step/Deploy/PreDeploy/RestorePatchLog.php
new file mode 100644
index 0000000000..e38d1a1ec2
--- /dev/null
+++ b/src/Step/Deploy/PreDeploy/RestorePatchLog.php
@@ -0,0 +1,86 @@
+logger = $logger;
+ $this->directoryList = $directoryList;
+ $this->file = $file;
+ $this->fileList = $fileList;
+ }
+
+ /**
+ * Restores patch log file from build phase if needed.
+ *
+ * @return void
+ * @throws StepException
+ */
+ public function execute()
+ {
+ try {
+ $buildPhaseLogPath = $this->fileList->getInitPatchLog();
+ if ($this->file->isExists($buildPhaseLogPath)) {
+ $this->logger->info('Restoring patch log file');
+ $this->file->createDirectory($this->directoryList->getLog());
+ $buildPhaseLogContent = $this->file->fileGetContents($buildPhaseLogPath);
+ $this->file->filePutContents(
+ $this->fileList->getPatchLog(),
+ $buildPhaseLogContent,
+ FILE_APPEND
+ );
+ }
+ } catch (FileSystemException | UndefinedPackageException $exception) {
+ throw new StepException($exception->getMessage(), $exception->getCode(), $exception);
+ }
+ }
+}
diff --git a/src/Step/Deploy/PreDeploy/RestoreWritableDirectories.php b/src/Step/Deploy/PreDeploy/RestoreWritableDirectories.php
index 253a59879f..589201cbc7 100644
--- a/src/Step/Deploy/PreDeploy/RestoreWritableDirectories.php
+++ b/src/Step/Deploy/PreDeploy/RestoreWritableDirectories.php
@@ -7,8 +7,10 @@
namespace Magento\MagentoCloud\Step\Deploy\PreDeploy;
+use Magento\MagentoCloud\App\GenericException;
use Magento\MagentoCloud\Filesystem\Flag\Manager as FlagManager;
use Magento\MagentoCloud\Filesystem\RecoverableDirectoryList;
+use Magento\MagentoCloud\Step\StepException;
use Magento\MagentoCloud\Step\StepInterface;
use Magento\MagentoCloud\Util\BuildDirCopier;
use Psr\Log\LoggerInterface;
@@ -57,21 +59,23 @@ public function __construct(
}
/**
- * Executes the process.
- *
- * @return void
+ * @inheritdoc
*/
public function execute()
{
- foreach ($this->recoverableDirectoryList->getList() as $dirOptions) {
- $this->buildDirCopier->copy(
- $dirOptions[RecoverableDirectoryList::OPTION_DIRECTORY],
- $dirOptions[RecoverableDirectoryList::OPTION_STRATEGY]
- );
- }
+ try {
+ foreach ($this->recoverableDirectoryList->getList() as $dirOptions) {
+ $this->buildDirCopier->copy(
+ $dirOptions[RecoverableDirectoryList::OPTION_DIRECTORY],
+ $dirOptions[RecoverableDirectoryList::OPTION_STRATEGY]
+ );
+ }
- // Restore mounted directories.
- $this->logger->notice('Recoverable directories were copied back.');
- $this->flagManager->delete(FlagManager::FLAG_REGENERATE);
+ // Restore mounted directories.
+ $this->logger->notice('Recoverable directories were copied back.');
+ $this->flagManager->delete(FlagManager::FLAG_REGENERATE);
+ } catch (GenericException $e) {
+ throw new StepException($e->getMessage(), $e->getCode(), $e);
+ }
}
}
diff --git a/src/Step/Deploy/RemoveDeployFailedFlag.php b/src/Step/Deploy/RemoveDeployFailedFlag.php
index e39e8f40d2..b66b78486a 100644
--- a/src/Step/Deploy/RemoveDeployFailedFlag.php
+++ b/src/Step/Deploy/RemoveDeployFailedFlag.php
@@ -43,7 +43,6 @@ public function __construct(
File $fileDriver,
FileList $fileList
) {
-
$this->manager = $manager;
$this->fileDriver = $fileDriver;
$this->fileList = $fileList;
@@ -58,9 +57,25 @@ public function execute()
$this->manager->delete(Manager::FLAG_DEPLOY_HOOK_IS_FAILED);
$this->manager->delete(Manager::FLAG_IGNORE_SPLIT_DB);
$this->manager->delete(Manager::FLAG_ENV_FILE_ABSENCE);
- $this->fileDriver->deleteFile($this->fileList->getCloudErrorLog());
+
+ $this->removeErrorLogFile();
} catch (\Exception $e) {
throw new StepException($e->getMessage(), $e->getCode(), $e);
}
}
+
+ /**
+ * Removes cloud.error.log file and copies it from init directory if exists.
+ *
+ * @throws \Magento\MagentoCloud\Package\UndefinedPackageException
+ */
+ private function removeErrorLogFile()
+ {
+ $errorLogFilePath = $this->fileList->getCloudErrorLog();
+ $buildPhaseErrorLogPath = $this->fileList->getInitCloudErrorLog();
+ $this->fileDriver->deleteFile($errorLogFilePath);
+ if ($this->fileDriver->isExists($buildPhaseErrorLogPath)) {
+ $this->fileDriver->copy($buildPhaseErrorLogPath, $errorLogFilePath);
+ }
+ }
}
diff --git a/src/Step/Deploy/SetCryptKey.php b/src/Step/Deploy/SetCryptKey.php
index 50fd9bbcd8..887434863b 100644
--- a/src/Step/Deploy/SetCryptKey.php
+++ b/src/Step/Deploy/SetCryptKey.php
@@ -7,6 +7,7 @@
namespace Magento\MagentoCloud\Step\Deploy;
+use Magento\MagentoCloud\App\Error;
use Magento\MagentoCloud\Config\Magento\Env\ReaderInterface as ConfigReader;
use Magento\MagentoCloud\Config\Magento\Env\WriterInterface as ConfigWriter;
use Magento\MagentoCloud\Config\Environment;
@@ -85,7 +86,7 @@ public function execute(): void
try {
$this->configWriter->update($config);
} catch (FileSystemException $exception) {
- throw new StepException($exception->getMessage(), $exception->getCode(), $exception);
+ throw new StepException($exception->getMessage(), Error::DEPLOY_ENV_PHP_IS_NOT_WRITABLE, $exception);
}
}
}
diff --git a/src/Step/Deploy/SplitDbConnection.php b/src/Step/Deploy/SplitDbConnection.php
index e644215074..d8c13c328e 100644
--- a/src/Step/Deploy/SplitDbConnection.php
+++ b/src/Step/Deploy/SplitDbConnection.php
@@ -12,6 +12,7 @@
use Magento\MagentoCloud\Config\Database\DbConfig;
use Magento\MagentoCloud\Config\Magento\Env\ReaderInterface as ConfigReader;
use Magento\MagentoCloud\Config\Stage\DeployInterface;
+use Magento\MagentoCloud\Filesystem\FileSystemException;
use Magento\MagentoCloud\Filesystem\Flag\Manager as FlagManager;
use Magento\MagentoCloud\Shell\MagentoShell;
use Magento\MagentoCloud\Shell\ShellException;
@@ -23,6 +24,10 @@
/**
* Enables split database
+ *
+ * {@inheritDoc}
+ *
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class SplitDbConnection implements StepInterface
{
@@ -107,55 +112,71 @@ public function __construct(
/**
* Starts the database splitting process
* Updates the configuration of slave connections for split connections
+ *
+ * {@inheritDoc}
*/
public function execute()
{
- if ($this->flagManager->exists(FlagManager::FLAG_IGNORE_SPLIT_DB)) {
- $this->logger->info(sprintf(
- 'Enabling a split database will be skipped. The flag %s was detected.',
- FlagManager::FLAG_IGNORE_SPLIT_DB
- ));
- $this->flagManager->delete(FlagManager::FLAG_IGNORE_SPLIT_DB);
- return;
- }
+ try {
+ if ($this->flagManager->exists(FlagManager::FLAG_IGNORE_SPLIT_DB)) {
+ $this->logger->info(sprintf(
+ 'Enabling a split database will be skipped. The flag %s was detected.',
+ FlagManager::FLAG_IGNORE_SPLIT_DB
+ ));
+ $this->flagManager->delete(FlagManager::FLAG_IGNORE_SPLIT_DB);
+ return;
+ }
- $splitTypes = $this->stageConfig->get(DeployInterface::VAR_SPLIT_DB);
+ $splitTypes = $this->stageConfig->get(DeployInterface::VAR_SPLIT_DB);
- $dbConfig = $this->dbConfig->get();
- $notAvailableSplitTypes = $this->getMissedSplitTypes(
- $splitTypes,
- $dbConfig[DbConfig::KEY_CONNECTION] ?? []
- );
+ $dbConfig = $this->dbConfig->get();
+ $notAvailableSplitTypes = $this->getMissedSplitTypes(
+ $splitTypes,
+ $dbConfig[DbConfig::KEY_CONNECTION] ?? []
+ );
- if (!empty($notAvailableSplitTypes)) {
- $this->logger->error(sprintf(
- 'Enabling a split database will be skipped.'
- . ' Relationship do not have configuration for next types: %s',
- implode(', ', $notAvailableSplitTypes)
- ));
- return;
- }
+ if (!empty($notAvailableSplitTypes)) {
+ $this->logger->warning(
+ sprintf(
+ 'Enabling a split database will be skipped.'
+ . ' Relationship do not have configuration for next types: %s',
+ implode(', ', $notAvailableSplitTypes)
+ ),
+ ['errorCode' => Error::WARN_SPLIT_DB_ENABLING_SKIPPED]
+ );
+ return;
+ }
- $mageConfig = $this->configReader->read();
+ $mageConfig = $this->configReader->read();
- $enabledSplitTypes = array_values(array_intersect_key(
- self::SPLIT_CONNECTION_MAP,
- $this->getSplitConnectionsConfig($mageConfig[DbConfig::KEY_DB][DbConfig::KEY_CONNECTION])
- ));
+ $enabledSplitTypes = array_values(array_intersect_key(
+ self::SPLIT_CONNECTION_MAP,
+ $this->getSplitConnectionsConfig($mageConfig[DbConfig::KEY_DB][DbConfig::KEY_CONNECTION])
+ ));
- $missedSplitTypes = array_diff($enabledSplitTypes, $splitTypes);
+ $missedSplitTypes = array_diff($enabledSplitTypes, $splitTypes);
- if (!empty($missedSplitTypes)) {
- $this->logger->warning(
- 'Variable SPLIT_DB does not have data which were already split types: '
- . implode(', ', $missedSplitTypes)
- );
- return;
+ if (!empty($missedSplitTypes)) {
+ $this->logger->warning(
+ 'The SPLIT_DB variable is missing the configuration for split connection types: '
+ . implode(', ', $missedSplitTypes),
+ ['errorCode' => Error::WARN_NOT_ENOUGH_DATA_SPLIT_DB_VAR]
+ );
+ return;
+ }
+ } catch (GenericException $e) {
+ throw new StepException($e->getMessage(), $e->getCode(), $e);
}
- if (!empty($splitTypes)) {
- $this->enableSplitConnections(array_diff($splitTypes, $enabledSplitTypes), $dbConfig);
+
+ try {
+ if (!empty($splitTypes)) {
+ $this->enableSplitConnections(array_diff($splitTypes, $enabledSplitTypes), $dbConfig);
+ }
+ $this->slaveConnection->update();
+ } catch (FileSystemException $e) {
+ $message = 'Cannot write slave connection(s) to the `./app/etc/env.php`';
+ throw new StepException($message, Error::DEPLOY_ENV_PHP_IS_NOT_WRITABLE, $e);
}
- $this->slaveConnection->update();
}
/**
diff --git a/src/Step/Deploy/SplitDbConnection/SlaveConnection.php b/src/Step/Deploy/SplitDbConnection/SlaveConnection.php
index e67235f41f..cff4c3feab 100644
--- a/src/Step/Deploy/SplitDbConnection/SlaveConnection.php
+++ b/src/Step/Deploy/SplitDbConnection/SlaveConnection.php
@@ -7,6 +7,7 @@
namespace Magento\MagentoCloud\Step\Deploy\SplitDbConnection;
+use Magento\MagentoCloud\App\Error;
use Magento\MagentoCloud\Config\ConfigException;
use Magento\MagentoCloud\Config\Database\DbConfig;
use Magento\MagentoCloud\Config\Magento\Env\ReaderInterface as ConfigReader;
@@ -92,11 +93,15 @@ public function update()
foreach ($mageSplitConnections as $mageConnectionName) {
if (!isset($dbConfig[DbConfig::KEY_SLAVE_CONNECTION][$mageConnectionName])) {
- $this->logger->warning(sprintf(
- 'Slave connection for \'%s\' connection not set. '
- . 'Relationships do not have the configuration for this slave connection',
- $mageConnectionName
- ));
+ $this->logger->warning(
+ sprintf(
+ 'Slave connection for \'%s\' connection not set. '
+ . 'The `relationships` configuration in the .magento.app.yaml file '
+ . 'is missing the configuration for this slave connection',
+ $mageConnectionName
+ ),
+ ['errorCode' => Error::WARN_SLAVE_CONNECTION_NOT_SET]
+ );
continue;
}
$connectionConfig = $dbConfig[DbConfig::KEY_SLAVE_CONNECTION][$mageConnectionName];
diff --git a/src/Step/PostDeploy/Backup.php b/src/Step/PostDeploy/Backup.php
index 21de9bf164..7f56e31e50 100644
--- a/src/Step/PostDeploy/Backup.php
+++ b/src/Step/PostDeploy/Backup.php
@@ -7,6 +7,9 @@
namespace Magento\MagentoCloud\Step\PostDeploy;
+use Magento\MagentoCloud\App\Error;
+use Magento\MagentoCloud\App\GenericException;
+use Magento\MagentoCloud\Step\StepException;
use Magento\MagentoCloud\Step\StepInterface;
use Magento\MagentoCloud\Filesystem\BackupList;
use Magento\MagentoCloud\Filesystem\Driver\File;
@@ -53,17 +56,28 @@ public function __construct(
*/
public function execute()
{
- $this->logger->info('Create backup of important files.');
+ try {
+ $this->logger->info('Create backup of important files.');
- foreach ($this->backupList->getList() as $file) {
- if (!$this->file->isExists($file)) {
- $this->logger->notice(sprintf('File %s does not exist. Skipped.', $file));
- continue;
- }
+ foreach ($this->backupList->getList() as $file) {
+ if (!$this->file->isExists($file)) {
+ $this->logger->notice(sprintf('File %s does not exist. Skipped.', $file));
+ continue;
+ }
- $backup = $file . BackupList::BACKUP_SUFFIX;
- $this->file->copy($file, $backup);
- $this->logger->info(sprintf('Backup %s for %s was created.', $backup, $file));
+ $backup = $file . BackupList::BACKUP_SUFFIX;
+ $result = $this->file->copy($file, $backup);
+ if (!$result) {
+ $this->logger->warning(
+ sprintf('Failed to create backup %s for %s.', $backup, $file),
+ ['errorCode' => Error::WARN_CREATE_CONFIG_BACKUP_FAILED]
+ );
+ } else {
+ $this->logger->info(sprintf('Successfully created backup %s for %s.', $backup, $file));
+ }
+ }
+ } catch (GenericException $e) {
+ throw new StepException($e->getMessage(), $e->getCode(), $e);
}
}
}
diff --git a/src/Step/SetProductionMode.php b/src/Step/SetProductionMode.php
index 33bec688b9..bc9694f277 100644
--- a/src/Step/SetProductionMode.php
+++ b/src/Step/SetProductionMode.php
@@ -46,12 +46,13 @@ public function __construct(
*/
public function execute()
{
- $this->logger->info('Set Magento application mode to \'production\'');
-
try {
+ $this->logger->info('Set Magento application mode to \'production\'');
$this->writer->update(['MAGE_MODE' => 'production']);
} catch (FileSystemException $e) {
throw new StepException($e->getMessage(), Error::BUILD_ENV_PHP_IS_NOT_WRITABLE, $e);
+ } catch (\Exception $e) {
+ throw new StepException($e->getMessage(), $e->getCode(), $e);
}
}
}
diff --git a/src/Step/SkipStep.php b/src/Step/SkipStep.php
index e77cfa7c78..a8a3039ae1 100644
--- a/src/Step/SkipStep.php
+++ b/src/Step/SkipStep.php
@@ -38,7 +38,7 @@ public function __construct(LoggerInterface $logger, string $stepName)
/**
* Logs the information about step skipping.
*
- * @return void
+ * {@inheritDoc}
*/
public function execute()
{
diff --git a/src/Step/ValidateConfiguration.php b/src/Step/ValidateConfiguration.php
index 9de0a7daf5..551be7f692 100644
--- a/src/Step/ValidateConfiguration.php
+++ b/src/Step/ValidateConfiguration.php
@@ -7,6 +7,7 @@
namespace Magento\MagentoCloud\Step;
+use Magento\MagentoCloud\App\Error as AppError;
use Magento\MagentoCloud\App\Logger;
use Magento\MagentoCloud\Config\Validator\Result\Error;
use Magento\MagentoCloud\Config\ValidatorException;
@@ -49,19 +50,25 @@ public function execute(): void
$errors = $this->collectErrors();
- ksort($errors);
- /** @var Error[] $levelErrors */
- foreach ($errors as $level => $levelErrors) {
- $message = $this->createErrorMessage($levelErrors);
+ if (!empty($errors)) {
+ ksort($errors);
- if ($level >= ValidatorInterface::LEVEL_CRITICAL) {
- throw new StepException(
- $message,
- array_values($levelErrors)[0]->getErrorCode()
- );
- }
+ $this->logger->notice('Fix configuration with given suggestions:');
+
+ /** @var Error[] $levelErrors */
+ foreach ($errors as $level => $levelErrors) {
+ foreach ($levelErrors as $error) {
+ $this->logger->log($level, $error->getError(), [
+ 'errorCode' => $error->getErrorCode(),
+ 'suggestion' => $error->getSuggestion()
+ ]);
+ }
- $this->logger->log($level, $message);
+ if ($level >= ValidatorInterface::LEVEL_CRITICAL) {
+ $error = array_values($levelErrors)[0];
+ throw new StepException($error->getError(), $error->getErrorCode() ?: AppError::DEFAULT_ERROR);
+ }
+ }
}
$this->logger->notice('End of validation');
@@ -103,28 +110,4 @@ private function collectErrors(): array
return $errors;
}
-
- /**
- * Convert array of Errors to string message
- *
- * @param array $errors
- * @return string
- */
- private function createErrorMessage(array $errors): string
- {
- $messages = [];
- foreach ($errors as $error) {
- $messages[] = '- ' . $error->getError();
- if ($suggestion = $error->getSuggestion()) {
- $messages[] = implode(PHP_EOL, array_map(
- static function ($line) {
- return ' ' . $line;
- },
- explode(PHP_EOL, $suggestion)
- ));
- }
- }
-
- return 'Fix configuration with given suggestions:' . PHP_EOL . implode(PHP_EOL, $messages);
- }
}
diff --git a/src/Test/Functional/Acceptance/AbstractCest.php b/src/Test/Functional/Acceptance/AbstractCest.php
index 67cc17e688..2ff196e6be 100644
--- a/src/Test/Functional/Acceptance/AbstractCest.php
+++ b/src/Test/Functional/Acceptance/AbstractCest.php
@@ -18,6 +18,11 @@ abstract class AbstractCest
*/
protected $removeEs = true;
+ /**
+ * @var boolean
+ */
+ protected $runComposerUpdate = true;
+
/**
* @var string
*/
@@ -51,12 +56,12 @@ protected function convertEnvFromArrayToJson(array $data): string
/**
* @param \CliTester $I
- * @param string $version
+ * @param string $templateVersion
*/
- protected function prepareWorkplace(\CliTester $I, string $version): void
+ protected function prepareWorkplace(\CliTester $I, string $templateVersion): void
{
$I->cleanupWorkDir();
- $I->cloneTemplateToWorkDir($version);
+ $I->cloneTemplateToWorkDir($templateVersion);
$I->createAuthJson();
$I->createArtifactsDir();
$I->createArtifactCurrentTestedCode('ece-tools', '2002.1.99');
@@ -65,6 +70,7 @@ protected function prepareWorkplace(\CliTester $I, string $version): void
$I->addEceDockerGitRepoToComposer();
$I->addCloudComponentsGitRepoToComposer();
$I->addCloudPatchesGitRepoToComposer();
+ $I->addQualityPatchesGitRepoToComposer();
$I->addDependencyToComposer(
'magento/magento-cloud-docker',
$I->getDependencyVersion('magento/magento-cloud-docker')
@@ -77,16 +83,40 @@ protected function prepareWorkplace(\CliTester $I, string $version): void
'magento/magento-cloud-patches',
$I->getDependencyVersion('magento/magento-cloud-patches')
);
- $I->composerUpdate();
- $this->removeESIfExists($I);
+ $I->addDependencyToComposer(
+ 'magento/quality-patches',
+ $I->getDependencyVersion('magento/quality-patches')
+ );
+
+ if ($this->runComposerUpdate) {
+ $I->composerUpdate();
+ }
+
+ $this->removeESIfExists($I, $templateVersion);
+ }
+
+ /**
+ * Checks if we can remove ES configuration for tests.
+ *
+ * @param string $templateVersion
+ * @return bool
+ */
+ protected function canESbeRemoved(string $templateVersion): bool
+ {
+ if ($templateVersion === 'master') {
+ return false;
+ }
+
+ return (bool)version_compare($templateVersion, '2.4.0', '<');
}
/**
* @param \CliTester $I
+ * @param string $templateVersion
*/
- protected function removeESIfExists(\CliTester $I): void
+ protected function removeESIfExists(\CliTester $I, string $templateVersion): void
{
- if ($this->removeEs) {
+ if ($this->removeEs && $this->canESbeRemoved($templateVersion)) {
$services = $I->readServicesYaml();
if (isset($services['elasticsearch'])) {
diff --git a/src/Test/Functional/Acceptance/AcceptanceCe71Cest.php b/src/Test/Functional/Acceptance/AcceptanceCe71Cest.php
new file mode 100644
index 0000000000..e04a446664
--- /dev/null
+++ b/src/Test/Functional/Acceptance/AcceptanceCe71Cest.php
@@ -0,0 +1,26 @@
+removeDependencyFromComposer('magento/magento-cloud-metapackage');
- $I->addDependencyToComposer('magento/product-community-edition', '@stable');
+ $I->addDependencyToComposer(
+ 'magento/product-community-edition',
+ $this->magentoCloudTemplate === 'master' ? '@stable' : $this->magentoCloudTemplate
+ );
$I->composerUpdate();
}
diff --git a/src/Test/Functional/Acceptance/AcceptanceCest.php b/src/Test/Functional/Acceptance/AcceptanceCest.php
index 74fb8922f1..d7b3b221d4 100644
--- a/src/Test/Functional/Acceptance/AcceptanceCest.php
+++ b/src/Test/Functional/Acceptance/AcceptanceCest.php
@@ -20,6 +20,8 @@
* 2. Test content presence
* 3. Test config dump
* 4. Test content presence
+ *
+ * @group php74
*/
class AcceptanceCest extends AbstractCest
{
diff --git a/src/Test/Functional/Acceptance/AdminCredential22Cest.php b/src/Test/Functional/Acceptance/AdminCredential22Cest.php
new file mode 100644
index 0000000000..ade58dc811
--- /dev/null
+++ b/src/Test/Functional/Acceptance/AdminCredential22Cest.php
@@ -0,0 +1,19 @@
+ '2.3.4'],
+ ];
+ }
+}
diff --git a/src/Test/Functional/Acceptance/BackupDbCest.php b/src/Test/Functional/Acceptance/BackupDbCest.php
index 7b4f5fc5c2..0d432a2961 100644
--- a/src/Test/Functional/Acceptance/BackupDbCest.php
+++ b/src/Test/Functional/Acceptance/BackupDbCest.php
@@ -14,6 +14,7 @@
/**
* Checks database backup functionality
+ * @group php74
*/
class BackupDbCest extends AbstractCest
{
@@ -71,7 +72,6 @@ protected function dataProviderMagentoCloudVersions(): array
{
return [
['version' => 'master'],
- ['version' => '2.3.4'],
];
}
diff --git a/src/Test/Functional/Acceptance/Cron23Php73Cest.php b/src/Test/Functional/Acceptance/Cron23Php73Cest.php
new file mode 100644
index 0000000000..958af2139a
--- /dev/null
+++ b/src/Test/Functional/Acceptance/Cron23Php73Cest.php
@@ -0,0 +1,41 @@
+ '2.3.4',
+ 'variables' => [
+ 'MAGENTO_CLOUD_VARIABLES' => [
+ 'ADMIN_EMAIL' => 'admin@example.com',
+ 'ADMIN_LOCALE' => 'fr_FR'
+ ],
+ ],
+ ],
+ [
+ 'version' => '2.3.3',
+ 'variables' => [
+ 'MAGENTO_CLOUD_VARIABLES' => [
+ 'ADMIN_EMAIL' => 'admin@example.com',
+ 'ADMIN_LOCALE' => 'fr_FR'
+ ],
+ ],
+ ],
+ ];
+ }
+}
diff --git a/src/Test/Functional/Acceptance/CronCest.php b/src/Test/Functional/Acceptance/CronCest.php
index 6cbb537e12..0efa857b8c 100644
--- a/src/Test/Functional/Acceptance/CronCest.php
+++ b/src/Test/Functional/Acceptance/CronCest.php
@@ -9,6 +9,8 @@
/**
* This test runs on the latest version of PHP
+ *
+ * @group php74
*/
class CronCest extends AbstractCest
{
@@ -132,16 +134,7 @@ protected function cronDataProvider(): array
{
return [
[
- 'version' => '2.3.4',
- 'variables' => [
- 'MAGENTO_CLOUD_VARIABLES' => [
- 'ADMIN_EMAIL' => 'admin@example.com',
- 'ADMIN_LOCALE' => 'fr_FR'
- ],
- ],
- ],
- [
- 'version' => '2.3.3',
+ 'version' => '2.4.0',
'variables' => [
'MAGENTO_CLOUD_VARIABLES' => [
'ADMIN_EMAIL' => 'admin@example.com',
diff --git a/src/Test/Functional/Acceptance/CronUnlockCest.php b/src/Test/Functional/Acceptance/CronUnlockCest.php
index 326f90b5c9..1aeefc98d1 100644
--- a/src/Test/Functional/Acceptance/CronUnlockCest.php
+++ b/src/Test/Functional/Acceptance/CronUnlockCest.php
@@ -9,6 +9,8 @@
/**
* Test for cron:unlock.
+ *
+ * @group php74
*/
class CronUnlockCest extends AbstractCest
{
diff --git a/src/Test/Functional/Acceptance/DataTypesOptionValidationCest.php b/src/Test/Functional/Acceptance/DataTypesOptionValidationCest.php
index 960ec088af..ceaad8b25a 100644
--- a/src/Test/Functional/Acceptance/DataTypesOptionValidationCest.php
+++ b/src/Test/Functional/Acceptance/DataTypesOptionValidationCest.php
@@ -9,6 +9,8 @@
/**
* This test runs on the latest version of PHP
+ *
+ * @group php74
*/
class DataTypesOptionValidationCest extends AbstractCest
{
diff --git a/src/Test/Functional/Acceptance/DatabaseConfigurationCest.php b/src/Test/Functional/Acceptance/DatabaseConfigurationCest.php
index fbb7ee287c..af6d510acd 100644
--- a/src/Test/Functional/Acceptance/DatabaseConfigurationCest.php
+++ b/src/Test/Functional/Acceptance/DatabaseConfigurationCest.php
@@ -9,6 +9,8 @@
/**
* This test runs on the latest version of PHP
+ *
+ * @group php74
*/
class DatabaseConfigurationCest extends AbstractCest
{
diff --git a/src/Test/Functional/Acceptance/ElasticSearch22Cest.php b/src/Test/Functional/Acceptance/ElasticSearch22Cest.php
index 6e930c6f3b..04b28d3f7d 100644
--- a/src/Test/Functional/Acceptance/ElasticSearch22Cest.php
+++ b/src/Test/Functional/Acceptance/ElasticSearch22Cest.php
@@ -12,17 +12,6 @@
*/
class ElasticSearch22Cest extends ElasticSearchCest
{
- /**
- * @param \CliTester $I
- * @param \Codeception\Example $data
- * @throws \Robo\Exception\TaskException
- * @skip Skip Need to fix ElasticSearch containers
- */
- public function testElastic(\CliTester $I, \Codeception\Example $data): void
- {
- parent::testElastic($I, $data); // TODO: Change the autogenerated stub
- }
-
/**
* @return array
*/
diff --git a/src/Test/Functional/Acceptance/ElasticSearch23Php72Cest.php b/src/Test/Functional/Acceptance/ElasticSearch23Php72Cest.php
index 00fa8491a7..d5f40ce2e8 100644
--- a/src/Test/Functional/Acceptance/ElasticSearch23Php72Cest.php
+++ b/src/Test/Functional/Acceptance/ElasticSearch23Php72Cest.php
@@ -12,17 +12,6 @@
*/
class ElasticSearch23Php72Cest extends ElasticSearchCest
{
- /**
- * @param \CliTester $I
- * @param \Codeception\Example $data
- * @throws \Robo\Exception\TaskException
- * @skip Skip Need to fix ElasticSearch containers
- */
- public function testElastic(\CliTester $I, \Codeception\Example $data): void
- {
- parent::testElastic($I, $data); // TODO: Change the autogenerated stub
- }
-
/**
* @return array
*/
diff --git a/src/Test/Functional/Acceptance/ElasticSearch23Php73Cest.php b/src/Test/Functional/Acceptance/ElasticSearch23Php73Cest.php
new file mode 100644
index 0000000000..6488538bf2
--- /dev/null
+++ b/src/Test/Functional/Acceptance/ElasticSearch23Php73Cest.php
@@ -0,0 +1,37 @@
+ '2.3.4',
+ 'removeES' => true,
+ 'expectedResult' => ['engine' => 'mysql'],
+ ],
+ [
+ 'magento' => '2.3.4',
+ 'removeES' => false,
+ 'expectedResult' => [
+ 'engine' => 'elasticsearch6',
+ 'elasticsearch6_server_hostname' => 'elasticsearch',
+ 'elasticsearch6_server_port' => '9200'
+ ],
+ ],
+ ];
+ }
+}
diff --git a/src/Test/Functional/Acceptance/ElasticSearchCest.php b/src/Test/Functional/Acceptance/ElasticSearchCest.php
index dc59cdde79..928596e561 100644
--- a/src/Test/Functional/Acceptance/ElasticSearchCest.php
+++ b/src/Test/Functional/Acceptance/ElasticSearchCest.php
@@ -11,14 +11,11 @@
/**
* This test runs on the latest version of PHP
+ *
+ * @group php74
*/
class ElasticSearchCest extends AbstractCest
{
- /**
- * @var boolean
- */
- protected $removeEs = false;
-
/**
* @param \CliTester $I
*/
@@ -115,12 +112,7 @@ protected function elasticDataProvider(): array
{
return [
[
- 'magento' => '2.3.4',
- 'removeES' => true,
- 'expectedResult' => ['engine' => 'mysql'],
- ],
- [
- 'magento' => '2.3.4',
+ 'magento' => 'master',
'removeES' => false,
'expectedResult' => [
'engine' => 'elasticsearch6',
diff --git a/src/Test/Functional/Acceptance/ErrorCodes23Cest.php b/src/Test/Functional/Acceptance/ErrorCodes23Cest.php
new file mode 100644
index 0000000000..8d127b259f
--- /dev/null
+++ b/src/Test/Functional/Acceptance/ErrorCodes23Cest.php
@@ -0,0 +1,24 @@
+runEceDockerCommand('build:compose --mode=production');
+ $I->copyFileToWorkDir('files/error_codes/.magento.env.fail.yaml', '.magento.env.yaml');
+
+ $I->runDockerComposeCommand('run build cloud-build');
+ $I->startEnvironment();
+ $I->assertFalse($I->runDockerComposeCommand('run deploy cloud-deploy'));
+ $I->seeInOutput(sprintf(
+ '[%d] Variable DATABASE_CONFIGURATION is not configured properly',
+ Error::DEPLOY_WRONG_CONFIGURATION_DB
+ ));
+ $I->seeInOutput('returned non-zero exit status ' . Error::DEPLOY_WRONG_CONFIGURATION_DB);
+
+ $errorLog = $I->grabFileContent('/var/log/cloud.error.log');
+
+ $errors = $this->getErrors($errorLog);
+
+ $I->assertArrayHasKey(Error::WARN_MISSED_MODULE_SECTION, $errors);
+ $I->assertArrayHasKey(Error::WARN_CONFIGURATION_STATE_NOT_IDEAL, $errors);
+ $I->assertArrayHasKey(Error::DEPLOY_WRONG_CONFIGURATION_DB, $errors);
+
+ $I->runDockerComposeCommand('run deploy ece-command error:show');
+ $I->seeInOutput('errorCode: ' . Error::WARN_MISSED_MODULE_SECTION);
+ $I->seeInOutput('errorCode: ' . Error::WARN_CONFIGURATION_STATE_NOT_IDEAL);
+ $I->seeInOutput('errorCode: ' . Error::DEPLOY_WRONG_CONFIGURATION_DB);
+ $I->seeInOutput('type: critical');
+ }
+
+ /**
+ * @param \CliTester $I
+ * @throws \Robo\Exception\TaskException
+ */
+ public function testDeploySuccess(\CliTester $I): void
+ {
+ $I->runEceDockerCommand('build:compose --mode=production');
+ $I->copyFileToWorkDir('files/error_codes/.magento.env.success.yaml', '.magento.env.yaml');
+
+ $I->runDockerComposeCommand('run build cloud-build');
+ $I->startEnvironment();
+ $I->assertTrue($I->runDockerComposeCommand('run deploy cloud-deploy'));
+ $I->assertTrue($I->runDockerComposeCommand('run deploy cloud-post-deploy'));
+ $I->doNotSeeInOutput('returned non-zero exit status');
+
+ $errorLog = $I->grabFileContent('/var/log/cloud.error.log');
+
+ $errors = $this->getErrors($errorLog);
+
+ $I->assertArrayHasKey(Error::WARN_MISSED_MODULE_SECTION, $errors);
+ $I->assertArrayHasKey(Error::WARN_CONFIGURATION_STATE_NOT_IDEAL, $errors);
+
+ $I->runDockerComposeCommand('run deploy ece-command error:show');
+ $I->seeInOutput('errorCode: ' . Error::WARN_MISSED_MODULE_SECTION);
+ $I->seeInOutput('errorCode: ' . Error::WARN_CONFIGURATION_STATE_NOT_IDEAL);
+ $I->doNotSeeInOutput('type: critical');
+ }
+
+ /**
+ * @param string $errorLog
+ * @return array
+ */
+ private function getErrors(string $errorLog): array
+ {
+ $errors = [];
+
+ foreach (explode("\n", $errorLog) as $errorLine) {
+ $error = json_decode(trim($errorLine), true);
+ if (json_last_error() !== JSON_ERROR_NONE) {
+ continue;
+ }
+ $errors[$error['errorCode']] = $error;
+ }
+
+ return $errors;
+ }
+}
diff --git a/src/Test/Functional/Acceptance/ErrorMessageCest.php b/src/Test/Functional/Acceptance/ErrorMessageCest.php
index 483059da51..e4fa0ac62f 100644
--- a/src/Test/Functional/Acceptance/ErrorMessageCest.php
+++ b/src/Test/Functional/Acceptance/ErrorMessageCest.php
@@ -11,6 +11,8 @@
/**
* This test runs on the latest version of PHP
+ *
+ * @group php74
*/
class ErrorMessageCest extends AbstractCest
{
diff --git a/src/Test/Functional/Acceptance/PostDeployCest.php b/src/Test/Functional/Acceptance/PostDeployCest.php
index b993a568b3..220f5564ec 100644
--- a/src/Test/Functional/Acceptance/PostDeployCest.php
+++ b/src/Test/Functional/Acceptance/PostDeployCest.php
@@ -9,6 +9,8 @@
/**
* This test runs on the latest version of PHP
+ *
+ * @group php74
*/
class PostDeployCest extends AbstractCest
{
diff --git a/src/Test/Functional/Acceptance/RedisCest.php b/src/Test/Functional/Acceptance/RedisCest.php
index d58295c164..03f4a9cce3 100644
--- a/src/Test/Functional/Acceptance/RedisCest.php
+++ b/src/Test/Functional/Acceptance/RedisCest.php
@@ -11,6 +11,8 @@
/**
* Checks Redis configuration
+ *
+ * @group php74
*/
class RedisCest extends AbstractCest
{
@@ -97,12 +99,6 @@ public function testDefaultConfiguration(\CliTester $I, \Codeception\Example $da
protected function defaultConfigurationDataProvider(): array
{
return [
- [
- 'version' => '2.3.4',
- ],
- [
- 'version' => '2.3.5',
- ],
[
'version' => 'master',
],
@@ -113,7 +109,7 @@ protected function defaultConfigurationDataProvider(): array
* @param \CliTester $I
* @param \Codeception\Example $data
* @throws \Robo\Exception\TaskException
- * @dataProvider wrongConfigurationData
+ * @dataProvider wrongConfigurationDataProvider
*/
public function testWrongConfiguration(\CliTester $I, \Codeception\Example $data): void
{
@@ -135,7 +131,7 @@ public function testWrongConfiguration(\CliTester $I, \Codeception\Example $data
/**
* @return array
*/
- protected function wrongConfigurationData(): array
+ protected function wrongConfigurationDataProvider(): array
{
return [
[
@@ -155,36 +151,6 @@ protected function wrongConfigurationData(): array
. ' \Magento\Framework\Cache\Backend\RemoteSynchronizedCache.',
'errorDeployMessage' => '',
],
- [
- 'version' => '2.3.4',
- 'wrongConfiguration' => [
- 'stage' => [
- 'deploy' => [
- 'REDIS_BACKEND' => '\Magento\Framework\Cache\Backend\Redis'
- ]
- ]
- ],
- 'buildSuccess' => true,
- 'deploySuccess' => false,
- 'errorBuildMessage' => '',
- 'errorDeployMessage' => 'does not support Redis backend model '
- . '\'\Magento\Framework\Cache\Backend\Redis\'',
- ],
- [
- 'version' => '2.3.4',
- 'wrongConfiguration' => [
- 'stage' => [
- 'deploy' => [
- 'REDIS_BACKEND' => '\Magento\Framework\Cache\Backend\RemoteSynchronizedCache'
- ]
- ]
- ],
- 'buildSuccess' => true,
- 'deploySuccess' => false,
- 'errorBuildMessage' => '',
- 'errorDeployMessage' => 'does not support Redis backend model '
- . '\'\Magento\Framework\Cache\Backend\RemoteSynchronizedCache\'',
- ],
];
}
@@ -233,70 +199,6 @@ public function testGoodConfiguration(\CliTester $I, \Codeception\Example $data)
protected function goodConfigurationDataProvider(): array
{
return [
- [
- 'version' => '2.3.4',
- 'backendModel' => [
- 'stage' => [
- 'deploy' => [
- 'REDIS_BACKEND' => 'Cm_Cache_Backend_Redis',
- ],
- ],
- ],
- 'expectedBackend' => 'Cm_Cache_Backend_Redis',
- 'expectedConfig' => [
- 'backend_options' => [
- 'server' => 'redis',
- 'port' => '6379',
- 'database' => 1,
- ],
- ],
- ],
- [
- 'version' => '2.3.5',
- 'backendModel' => [
- 'stage' => [
- 'deploy' => [
- 'REDIS_BACKEND' => '\Magento\Framework\Cache\Backend\Redis',
- ],
- ],
- ],
- 'expectedBackend' => '\\\Magento\\\Framework\\\Cache\\\Backend\\\Redis',
- 'expectedConfig' => [
- 'backend_options' => [
- 'server' => 'redis',
- 'port' => '6379',
- 'database' => 1,
- ],
- ],
- ],
- [
- 'version' => '2.3.5',
- 'backendModel' => [
- 'stage' => [
- 'deploy' => [
- 'REDIS_BACKEND' => '\Magento\Framework\Cache\Backend\RemoteSynchronizedCache',
- ],
- ],
- ],
- 'expectedBackend' => '\\\Magento\\\Framework\\\Cache\\\Backend\\\RemoteSynchronizedCache',
- 'expectedConfig' => [
- 'backend_options' => [
- 'remote_backend' => '\\\Magento\\\Framework\\\Cache\\\Backend\\\Redis',
- 'remote_backend_options' => [
- 'persistent' => 0,
- 'server' => 'redis',
- 'database' => 1,
- 'port' => '6379',
- 'password' => '',
- 'compress_data' => '1',
- ],
- 'local_backend' => 'Cm_Cache_Backend_File',
- 'local_backend_options' => [
- 'cache_dir' => '/dev/shm/',
- ]
- ]
- ],
- ],
[
'version' => 'master',
'backendModel' => [
@@ -306,7 +208,7 @@ protected function goodConfigurationDataProvider(): array
],
],
],
- 'expectedBackend' => '\\\Magento\\\Framework\\\Cache\\\Backend\\\Redis',
+ 'expectedBackend' => '\Magento\Framework\Cache\Backend\Redis',
'expectedConfig' => [
'backend_options' => [
'server' => 'redis',
@@ -324,10 +226,10 @@ protected function goodConfigurationDataProvider(): array
],
],
],
- 'expectedBackend' => '\\\Magento\\\Framework\\\Cache\\\Backend\\\RemoteSynchronizedCache',
+ 'expectedBackend' => '\Magento\Framework\Cache\Backend\RemoteSynchronizedCache',
'expectedConfig' => [
'backend_options' => [
- 'remote_backend' => '\\\Magento\\\Framework\\\Cache\\\Backend\\\Redis',
+ 'remote_backend' => '\Magento\Framework\Cache\Backend\Redis',
'remote_backend_options' => [
'persistent' => 0,
'server' => 'redis',
diff --git a/src/Test/Functional/Acceptance/RedisPhp71Cest.php b/src/Test/Functional/Acceptance/RedisPhp71Cest.php
new file mode 100644
index 0000000000..bd2cf63d95
--- /dev/null
+++ b/src/Test/Functional/Acceptance/RedisPhp71Cest.php
@@ -0,0 +1,93 @@
+ '2.2.11',
+ ],
+ ];
+ }
+
+ /**
+ * @return array
+ */
+ protected function wrongConfigurationDataProvider(): array
+ {
+ return [
+ [
+ 'version' => '2.2.11',
+ 'wrongConfiguration' => [
+ 'stage' => [
+ 'deploy' => [
+ 'REDIS_BACKEND' => '\Magento\Framework\Cache\Backend\Redis'
+ ]
+ ]
+ ],
+ 'buildSuccess' => true,
+ 'deploySuccess' => false,
+ 'errorBuildMessage' => '',
+ 'errorDeployMessage' => 'does not support Redis backend model '
+ . '\'\Magento\Framework\Cache\Backend\Redis\'',
+ ],
+ [
+ 'version' => '2.2.11',
+ 'wrongConfiguration' => [
+ 'stage' => [
+ 'deploy' => [
+ 'REDIS_BACKEND' => '\Magento\Framework\Cache\Backend\RemoteSynchronizedCache'
+ ]
+ ]
+ ],
+ 'buildSuccess' => true,
+ 'deploySuccess' => false,
+ 'errorBuildMessage' => '',
+ 'errorDeployMessage' => 'does not support Redis backend model '
+ . '\'\Magento\Framework\Cache\Backend\RemoteSynchronizedCache\'',
+ ],
+ ];
+ }
+
+ /**
+ * @return array
+ * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
+ */
+ protected function goodConfigurationDataProvider(): array
+ {
+ return [
+ [
+ 'version' => '2.2.11',
+ 'backendModel' => [
+ 'stage' => [
+ 'deploy' => [
+ 'REDIS_BACKEND' => 'Cm_Cache_Backend_Redis',
+ ],
+ ],
+ ],
+ 'expectedBackend' => 'Cm_Cache_Backend_Redis',
+ 'expectedConfig' => [
+ 'backend_options' => [
+ 'server' => 'redis',
+ 'port' => '6379',
+ 'database' => 1,
+ ],
+ ],
+ ],
+ ];
+ }
+}
diff --git a/src/Test/Functional/Acceptance/RedisPhp72Cest.php b/src/Test/Functional/Acceptance/RedisPhp72Cest.php
new file mode 100644
index 0000000000..6d14d45c3e
--- /dev/null
+++ b/src/Test/Functional/Acceptance/RedisPhp72Cest.php
@@ -0,0 +1,241 @@
+ '2.3.0',
+ ],
+ [
+ 'version' => '2.3.1',
+ ],
+ [
+ 'version' => '2.3.2',
+ ],
+ ];
+ }
+
+ /**
+ * @return array
+ */
+ protected function wrongConfigurationDataProvider(): array
+ {
+ return [
+ [
+ 'version' => '2.3.0',
+ 'wrongConfiguration' => [
+ 'stage' => [
+ 'deploy' => [
+ 'REDIS_BACKEND' => 'TestRedisModel'
+ ]
+ ]
+ ],
+ 'buildSuccess' => false,
+ 'deploySuccess' => false,
+ 'errorBuildMessage' => 'The REDIS_BACKEND variable contains an invalid value TestRedisModel.'
+ . ' Use one of the available value options: Cm_Cache_Backend_Redis,'
+ . ' \Magento\Framework\Cache\Backend\Redis,'
+ . ' \Magento\Framework\Cache\Backend\RemoteSynchronizedCache.',
+ 'errorDeployMessage' => '',
+ ],
+ [
+ 'version' => '2.3.2',
+ 'wrongConfiguration' => [
+ 'stage' => [
+ 'deploy' => [
+ 'REDIS_BACKEND' => 'TestRedisModel'
+ ]
+ ]
+ ],
+ 'buildSuccess' => false,
+ 'deploySuccess' => false,
+ 'errorBuildMessage' => 'The REDIS_BACKEND variable contains an invalid value TestRedisModel.'
+ . ' Use one of the available value options: Cm_Cache_Backend_Redis,'
+ . ' \Magento\Framework\Cache\Backend\Redis,'
+ . ' \Magento\Framework\Cache\Backend\RemoteSynchronizedCache.',
+ 'errorDeployMessage' => '',
+ ],
+ ];
+ }
+
+ /**
+ * @return array
+ * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
+ */
+ protected function goodConfigurationDataProvider(): array
+ {
+ return [
+ [
+ 'version' => '2.3.0',
+ 'backendModel' => [
+ 'stage' => [
+ 'deploy' => [
+ 'REDIS_BACKEND' => 'Cm_Cache_Backend_Redis',
+ ],
+ ],
+ ],
+ 'expectedBackend' => 'Cm_Cache_Backend_Redis',
+ 'expectedConfig' => [
+ 'backend_options' => [
+ 'server' => 'redis',
+ 'port' => '6379',
+ 'database' => 1,
+ ],
+ ],
+ ],
+ [
+ 'version' => '2.3.0',
+ 'backendModel' => [
+ 'stage' => [
+ 'deploy' => [
+ 'REDIS_BACKEND' => '\Magento\Framework\Cache\Backend\Redis',
+ ],
+ ],
+ ],
+ 'expectedBackend' => '\Magento\Framework\Cache\Backend\Redis',
+ 'expectedConfig' => [
+ 'backend_options' => [
+ 'server' => 'redis',
+ 'port' => '6379',
+ 'database' => 1,
+ ],
+ ],
+ ],
+ [
+ 'version' => '2.3.0',
+ 'backendModel' => [
+ 'stage' => [
+ 'deploy' => [
+ 'REDIS_BACKEND' => '\Magento\Framework\Cache\Backend\RemoteSynchronizedCache',
+ ],
+ ],
+ ],
+ 'expectedBackend' => '\Magento\Framework\Cache\Backend\RemoteSynchronizedCache',
+ 'expectedConfig' => [
+ 'backend_options' => [
+ 'remote_backend' => '\Magento\Framework\Cache\Backend\Redis',
+ 'remote_backend_options' => [
+ 'persistent' => 0,
+ 'server' => 'redis',
+ 'database' => 1,
+ 'port' => '6379',
+ 'password' => '',
+ 'compress_data' => '1',
+ ],
+ 'local_backend' => 'Cm_Cache_Backend_File',
+ 'local_backend_options' => [
+ 'cache_dir' => '/dev/shm/',
+ ]
+ ]
+ ],
+ ],
+ [
+ 'version' => '2.3.1',
+ 'backendModel' => [
+ 'stage' => [
+ 'deploy' => [
+ 'REDIS_BACKEND' => '\Magento\Framework\Cache\Backend\Redis',
+ ],
+ ],
+ ],
+ 'expectedBackend' => '\Magento\Framework\Cache\Backend\Redis',
+ 'expectedConfig' => [
+ 'backend_options' => [
+ 'server' => 'redis',
+ 'port' => '6379',
+ 'database' => 1,
+ ],
+ ],
+ ],
+ [
+ 'version' => '2.3.1',
+ 'backendModel' => [
+ 'stage' => [
+ 'deploy' => [
+ 'REDIS_BACKEND' => '\Magento\Framework\Cache\Backend\RemoteSynchronizedCache',
+ ],
+ ],
+ ],
+ 'expectedBackend' => '\Magento\Framework\Cache\Backend\RemoteSynchronizedCache',
+ 'expectedConfig' => [
+ 'backend_options' => [
+ 'remote_backend' => '\Magento\Framework\Cache\Backend\Redis',
+ 'remote_backend_options' => [
+ 'persistent' => 0,
+ 'server' => 'redis',
+ 'database' => 1,
+ 'port' => '6379',
+ 'password' => '',
+ 'compress_data' => '1',
+ ],
+ 'local_backend' => 'Cm_Cache_Backend_File',
+ 'local_backend_options' => [
+ 'cache_dir' => '/dev/shm/',
+ ]
+ ]
+ ],
+ ],
+ [
+ 'version' => '2.3.2',
+ 'backendModel' => [
+ 'stage' => [
+ 'deploy' => [
+ 'REDIS_BACKEND' => '\Magento\Framework\Cache\Backend\Redis',
+ ],
+ ],
+ ],
+ 'expectedBackend' => '\Magento\Framework\Cache\Backend\Redis',
+ 'expectedConfig' => [
+ 'backend_options' => [
+ 'server' => 'redis',
+ 'port' => '6379',
+ 'database' => 1,
+ ],
+ ],
+ ],
+ [
+ 'version' => '2.3.2',
+ 'backendModel' => [
+ 'stage' => [
+ 'deploy' => [
+ 'REDIS_BACKEND' => '\Magento\Framework\Cache\Backend\RemoteSynchronizedCache',
+ ],
+ ],
+ ],
+ 'expectedBackend' => '\Magento\Framework\Cache\Backend\RemoteSynchronizedCache',
+ 'expectedConfig' => [
+ 'backend_options' => [
+ 'remote_backend' => '\Magento\Framework\Cache\Backend\Redis',
+ 'remote_backend_options' => [
+ 'persistent' => 0,
+ 'server' => 'redis',
+ 'database' => 1,
+ 'port' => '6379',
+ 'password' => '',
+ 'compress_data' => '1',
+ ],
+ 'local_backend' => 'Cm_Cache_Backend_File',
+ 'local_backend_options' => [
+ 'cache_dir' => '/dev/shm/',
+ ]
+ ]
+ ],
+ ],
+ ];
+ }
+}
diff --git a/src/Test/Functional/Acceptance/RedisPhp73Cest.php b/src/Test/Functional/Acceptance/RedisPhp73Cest.php
new file mode 100644
index 0000000000..9071f35af3
--- /dev/null
+++ b/src/Test/Functional/Acceptance/RedisPhp73Cest.php
@@ -0,0 +1,144 @@
+ '2.3.4',
+ ],
+ [
+ 'version' => '2.3.5',
+ ],
+ ];
+ }
+
+ /**
+ * @return array
+ */
+ protected function wrongConfigurationData(): array
+ {
+ return [
+ [
+ 'version' => '2.3.4',
+ 'wrongConfiguration' => [
+ 'stage' => [
+ 'deploy' => [
+ 'REDIS_BACKEND' => '\Magento\Framework\Cache\Backend\Redis'
+ ]
+ ]
+ ],
+ 'buildSuccess' => true,
+ 'deploySuccess' => false,
+ 'errorBuildMessage' => '',
+ 'errorDeployMessage' => 'does not support Redis backend model '
+ . '\'\Magento\Framework\Cache\Backend\Redis\'',
+ ],
+ [
+ 'version' => '2.3.4',
+ 'wrongConfiguration' => [
+ 'stage' => [
+ 'deploy' => [
+ 'REDIS_BACKEND' => '\Magento\Framework\Cache\Backend\RemoteSynchronizedCache'
+ ]
+ ]
+ ],
+ 'buildSuccess' => true,
+ 'deploySuccess' => false,
+ 'errorBuildMessage' => '',
+ 'errorDeployMessage' => 'does not support Redis backend model '
+ . '\'\Magento\Framework\Cache\Backend\RemoteSynchronizedCache\'',
+ ],
+ ];
+ }
+
+ /**
+ * @return array
+ * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
+ */
+ protected function goodConfigurationDataProvider(): array
+ {
+ return [
+ [
+ 'version' => '2.3.4',
+ 'backendModel' => [
+ 'stage' => [
+ 'deploy' => [
+ 'REDIS_BACKEND' => 'Cm_Cache_Backend_Redis',
+ ],
+ ],
+ ],
+ 'expectedBackend' => 'Cm_Cache_Backend_Redis',
+ 'expectedConfig' => [
+ 'backend_options' => [
+ 'server' => 'redis',
+ 'port' => '6379',
+ 'database' => 1,
+ ],
+ ],
+ ],
+ [
+ 'version' => '2.3.5',
+ 'backendModel' => [
+ 'stage' => [
+ 'deploy' => [
+ 'REDIS_BACKEND' => '\Magento\Framework\Cache\Backend\Redis',
+ ],
+ ],
+ ],
+ 'expectedBackend' => '\Magento\Framework\Cache\Backend\Redis',
+ 'expectedConfig' => [
+ 'backend_options' => [
+ 'server' => 'redis',
+ 'port' => '6379',
+ 'database' => 1,
+ ],
+ ],
+ ],
+ [
+ 'version' => '2.3.5',
+ 'backendModel' => [
+ 'stage' => [
+ 'deploy' => [
+ 'REDIS_BACKEND' => '\Magento\Framework\Cache\Backend\RemoteSynchronizedCache',
+ ],
+ ],
+ ],
+ 'expectedBackend' => '\Magento\Framework\Cache\Backend\RemoteSynchronizedCache',
+ 'expectedConfig' => [
+ 'backend_options' => [
+ 'remote_backend' => '\Magento\Framework\Cache\Backend\Redis',
+ 'remote_backend_options' => [
+ 'persistent' => 0,
+ 'server' => 'redis',
+ 'database' => 1,
+ 'port' => '6379',
+ 'password' => '',
+ 'compress_data' => '1',
+ ],
+ 'local_backend' => 'Cm_Cache_Backend_File',
+ 'local_backend_options' => [
+ 'cache_dir' => '/dev/shm/',
+ ]
+ ]
+ ],
+ ],
+ ];
+ }
+}
diff --git a/src/Test/Functional/Acceptance/ReportDirNestingLevelCest.php b/src/Test/Functional/Acceptance/ReportDirNestingLevelCest.php
index 7349342584..1919688403 100644
--- a/src/Test/Functional/Acceptance/ReportDirNestingLevelCest.php
+++ b/src/Test/Functional/Acceptance/ReportDirNestingLevelCest.php
@@ -11,6 +11,8 @@
/**
* This test runs on the latest version of PHP
+ *
+ * @group php74
*/
class ReportDirNestingLevelCest extends AbstractCest
{
@@ -163,11 +165,11 @@ public function testErrorReportDirNestingLevelNotSet(\CliTester $I): void
$log
);
$I->assertContains(
- '- The directory nesting level value for error reporting has not been configured.',
+ 'The directory nesting level value for error reporting has not been configured.',
$log
);
$I->assertContains(
- 'You can configure the setting using the `config.report.dir_nesting_level`'
+ 'You can configure the setting using the `config.report.dir_nesting_level` variable'
. ' in the file ' . $this->expectedPathLocalXml,
$log
);
@@ -200,7 +202,7 @@ public function testWithInvalidLocalXmlFile(\CliTester $I): void
$log
);
$I->assertContains(
- "- Config of the file {$this->expectedPathLocalXml} is invalid.",
+ "Invalid configuration in the {$this->expectedPathLocalXml} file.",
$log
);
$I->assertContains(
diff --git a/src/Test/Functional/Acceptance/ScdMatrixCest.php b/src/Test/Functional/Acceptance/ScdMatrixCest.php
index aaea6effec..767c5c6641 100644
--- a/src/Test/Functional/Acceptance/ScdMatrixCest.php
+++ b/src/Test/Functional/Acceptance/ScdMatrixCest.php
@@ -9,6 +9,8 @@
/**
* This test runs on the latest version of PHP
+ *
+ * @group php74
*/
class ScdMatrixCest extends AbstractCest
{
diff --git a/src/Test/Functional/Acceptance/ScdStrategyCest.php b/src/Test/Functional/Acceptance/ScdStrategyCest.php
index 5bdb2dea5b..ffc18f74e3 100644
--- a/src/Test/Functional/Acceptance/ScdStrategyCest.php
+++ b/src/Test/Functional/Acceptance/ScdStrategyCest.php
@@ -9,6 +9,8 @@
/**
* This test runs on the latest version of PHP
+ *
+ * @group php74
*/
class ScdStrategyCest extends AbstractCest
{
diff --git a/src/Test/Functional/Acceptance/ScenarioExtensibilityCest.php b/src/Test/Functional/Acceptance/ScenarioExtensibilityCest.php
index 9573f97ff9..5d93283247 100644
--- a/src/Test/Functional/Acceptance/ScenarioExtensibilityCest.php
+++ b/src/Test/Functional/Acceptance/ScenarioExtensibilityCest.php
@@ -11,6 +11,8 @@
/**
* Tests extensibility base deployment scenarios
+ *
+ * @group php74
*/
class ScenarioExtensibilityCest extends AbstractCest
{
diff --git a/src/Test/Functional/Acceptance/SessionConfigurationCest.php b/src/Test/Functional/Acceptance/SessionConfigurationCest.php
index 9bf788d0ae..6939ea0ff1 100644
--- a/src/Test/Functional/Acceptance/SessionConfigurationCest.php
+++ b/src/Test/Functional/Acceptance/SessionConfigurationCest.php
@@ -10,6 +10,8 @@
/**
* This scenario checks that session can be configured through environment variable SESSION_CONFIGURATION
* Zephyr ID MAGECLOUD-46
+ *
+ * @group php74
*/
class SessionConfigurationCest extends AbstractCest
{
diff --git a/src/Test/Functional/Acceptance/SplitDb73Cest.php b/src/Test/Functional/Acceptance/SplitDb73Cest.php
new file mode 100644
index 0000000000..fffd7d5b61
--- /dev/null
+++ b/src/Test/Functional/Acceptance/SplitDb73Cest.php
@@ -0,0 +1,31 @@
+ '2.3.4'],
+ ];
+ }
+}
diff --git a/src/Test/Functional/Acceptance/SplitDbCest.php b/src/Test/Functional/Acceptance/SplitDbCest.php
index 2bf2dd9b4b..0818f832ef 100644
--- a/src/Test/Functional/Acceptance/SplitDbCest.php
+++ b/src/Test/Functional/Acceptance/SplitDbCest.php
@@ -14,6 +14,8 @@
/**
* Checks split database functionality
+ *
+ * @group php74
*/
class SplitDbCest extends AbstractCest
{
@@ -51,7 +53,7 @@ public function testSplitDb(CliTester $I, Example $data)
$this->setSplitDbTypesIntoMagentoEnvYaml($I, ['quote', 'sales']);
$this->runDeploy($I);
$I->seeInOutput(
- 'ERROR: Enabling a split database will be skipped.'
+ 'Enabling a split database will be skipped.'
. ' Relationship do not have configuration for next types: sales, quote'
);
$this->checkEnvPhpConfig($I, [], ['checkout', 'sales']);
@@ -103,7 +105,6 @@ protected function dataProviderMagentoCloudVersions(): array
{
return [
['version' => 'master'],
- ['version' => '2.3.4'],
];
}
@@ -116,7 +117,7 @@ private function variationsDataPartWithoutSplitDbArch(): array
'Deploy \'Split Db\' with the wrong Split Db type' => [
'messages' => [
'Fix configuration with given suggestions:',
- '- Environment configuration is not valid.',
+ 'Environment configuration is not valid.',
'Correct the following items in your .magento.env.yaml file:',
'The SPLIT_DB variable contains an invalid value of type string. Use the following type: array.',
],
@@ -125,20 +126,20 @@ private function variationsDataPartWithoutSplitDbArch(): array
'Deploy \'Split Db\' with the invalid Split Db label' => [
'messages' => [
'Fix configuration with given suggestions:',
- '- Environment configuration is not valid.',
+ 'Environment configuration is not valid.',
'Correct the following items in your .magento.env.yaml file:',
'The SPLIT_DB variable contains the invalid value.',
- 'It should be array with next available values: [quote, sales].'
+ 'It should be an array with following values: [quote, sales].'
],
'splitDbTypes' => ['checkout'],
],
'Deploy \'Split Db\' with the invalid and valid Split Db labels' => [
'messages' => [
'Fix configuration with given suggestions:',
- '- Environment configuration is not valid.',
+ 'Environment configuration is not valid.',
'Correct the following items in your .magento.env.yaml file:',
'The SPLIT_DB variable contains the invalid value.',
- 'It should be array with next available values: [quote, sales].',
+ 'It should be an array with following values: [quote, sales].',
],
'splitDbTypes' => ['quote', 'checkout'],
]
@@ -162,13 +163,13 @@ private function variationsDataPartWithSplitDbArch(): array
],
'Split Db type was deleted' => [
'splitDbTypes' => null,
- 'messages' => 'WARNING: Variable SPLIT_DB does not have data which were already split types: quote',
+ 'messages' => 'The SPLIT_DB variable is missing the configuration for split connection types: quote',
'expectedExists' => ['checkout'],
'expectedNotExist' => ['sales'],
],
'Split Db current type was deleted and new type added' => [
'splitDbTypes' => ['sales'],
- 'messages' => 'WARNING: Variable SPLIT_DB does not have data which were already split types: quote',
+ 'messages' => 'The SPLIT_DB variable is missing the configuration for split connection types: quote',
'expectedExists' => ['checkout'],
'expectedNotExist' => ['sales'],
],
diff --git a/src/Test/Functional/Acceptance/SplitDbWizard73Cest.php b/src/Test/Functional/Acceptance/SplitDbWizard73Cest.php
new file mode 100644
index 0000000000..ba49a66329
--- /dev/null
+++ b/src/Test/Functional/Acceptance/SplitDbWizard73Cest.php
@@ -0,0 +1,31 @@
+ '2.3.4'],
+ ['version' => '2.3.5'],
+ ];
+ }
+}
diff --git a/src/Test/Functional/Acceptance/SplitDbWizardCest.php b/src/Test/Functional/Acceptance/SplitDbWizardCest.php
index a7f2971f03..6206f83774 100644
--- a/src/Test/Functional/Acceptance/SplitDbWizardCest.php
+++ b/src/Test/Functional/Acceptance/SplitDbWizardCest.php
@@ -13,6 +13,8 @@
/**
* Checks split database wizard functionality
+ *
+ * @group php74
*/
class SplitDbWizardCest extends AbstractCest
{
@@ -43,7 +45,7 @@ public function testSplitDbWizard(CliTester $I, Example $data)
$I->runDockerComposeCommand('run deploy ece-command wizard:split-db-state');
$I->seeInOutput([
'DB is not split',
- '- DB cannot be split on this environment'
+ 'DB cannot be split on this environment'
]);
$I->stopEnvironment(true);
@@ -76,7 +78,7 @@ private function variationsData(): array
'splitDbTypes' => null,
'messages' => [
'DB is not split',
- '- You may split DB using SPLIT_DB variable in .magento.env.yaml file'
+ 'You may split DB using SPLIT_DB variable in .magento.env.yaml file'
]
],
'Running Split Db wizard in an environment with Split Db architecture'
@@ -99,7 +101,6 @@ protected function dataProviderMagentoCloudVersions(): array
{
return [
['version' => 'master'],
- ['version' => '2.3.4'],
];
}
diff --git a/src/Test/Functional/Acceptance/Upgrade21Cest.php b/src/Test/Functional/Acceptance/Upgrade21Cest.php
index 6bbcbaad3c..bf7ac05207 100644
--- a/src/Test/Functional/Acceptance/Upgrade21Cest.php
+++ b/src/Test/Functional/Acceptance/Upgrade21Cest.php
@@ -10,8 +10,51 @@
/**
* @group php71
*/
-class Upgrade21Cest extends UpgradeCest
+class Upgrade21Cest extends AbstractCest
{
+ /**
+ * @param \CliTester $I
+ */
+ public function _before(\CliTester $I): void
+ {
+ // Do nothing...
+ }
+
+ /**
+ * @param \CliTester $I
+ * @param \Codeception\Example $data
+ * @throws \Robo\Exception\TaskException
+ * @dataProvider testProvider
+ */
+ public function test(\CliTester $I, \Codeception\Example $data): void
+ {
+ $this->prepareWorkplace($I, $data['from']);
+ $I->runEceDockerCommand('build:compose --mode=production');
+ $this->assert($I);
+ $I->assertTrue($I->cleanDirectories(['/vendor/*', '/setup/*']));
+ $I->stopEnvironment(true);
+ $I->addDependencyToComposer('magento/magento-cloud-metapackage', $data['to']);
+ $I->composerUpdate();
+ $this->assert($I);
+ }
+
+ /**
+ * @param \CliTester $I
+ * @throws \Robo\Exception\TaskException
+ */
+ protected function assert(\CliTester $I): void
+ {
+
+ $I->runDockerComposeCommand('run build cloud-build');
+ $I->startEnvironment();
+ $I->runDockerComposeCommand('run deploy cloud-deploy');
+ $I->runDockerComposeCommand('run deploy cloud-post-deploy');
+
+ $I->amOnPage('/');
+ $I->see('Home page');
+ $I->see('CMS homepage content goes here.');
+ }
+
/**
* @return array
*/
diff --git a/src/Test/Functional/Acceptance/Upgrade22Cest.php b/src/Test/Functional/Acceptance/Upgrade22Cest.php
index 1a1913e742..033e5dcf7b 100644
--- a/src/Test/Functional/Acceptance/Upgrade22Cest.php
+++ b/src/Test/Functional/Acceptance/Upgrade22Cest.php
@@ -10,7 +10,7 @@
/**
* @group php71
*/
-class Upgrade22Cest extends UpgradeCest
+class Upgrade22Cest extends Upgrade21Cest
{
/**
* @return array
diff --git a/src/Test/Functional/Acceptance/Upgrade23Cest.php b/src/Test/Functional/Acceptance/Upgrade23Cest.php
new file mode 100644
index 0000000000..71118df21a
--- /dev/null
+++ b/src/Test/Functional/Acceptance/Upgrade23Cest.php
@@ -0,0 +1,27 @@
+ '2.3.0', 'to' => '>=2.3.1 <2.3.2'],
+ ['from' => '2.3.3', 'to' => '>=2.3.4 <2.3.5'],
+ ];
+ }
+}
diff --git a/src/Test/Functional/Acceptance/UpgradeCest.php b/src/Test/Functional/Acceptance/UpgradeCest.php
index 77b9b746fb..9d0ac24b2b 100644
--- a/src/Test/Functional/Acceptance/UpgradeCest.php
+++ b/src/Test/Functional/Acceptance/UpgradeCest.php
@@ -10,63 +10,22 @@
/**
* This test runs on the latest version of PHP
*
- * @group php72
+ * @group php73
*/
-class UpgradeCest extends AbstractCest
+class UpgradeCest extends Upgrade21Cest
{
/**
- * @param \CliTester $I
+ * @var boolean
*/
- public function _before(\CliTester $I): void
- {
- // Do nothing...
- }
-
- /**
- * @param \CliTester $I
- * @param \Codeception\Example $data
- * @throws \Robo\Exception\TaskException
- * @dataProvider testProvider
- */
- public function test(\CliTester $I, \Codeception\Example $data): void
- {
- $this->prepareWorkplace($I, $data['from']);
- $I->runEceDockerCommand('build:compose --mode=production');
- $this->assert($I);
- $I->assertTrue($I->cleanDirectories(['/vendor/*', '/setup/*']));
- $I->stopEnvironment(true);
- $I->addDependencyToComposer('magento/magento-cloud-metapackage', $data['to']);
- $I->composerUpdate();
- $this->assert($I);
- }
-
- /**
- * @param \CliTester $I
- * @throws \Robo\Exception\TaskException
- */
- protected function assert(\CliTester $I): void
- {
-
- $I->runDockerComposeCommand('run build cloud-build');
- $I->startEnvironment();
- $I->runDockerComposeCommand('run deploy cloud-deploy');
- $I->runDockerComposeCommand('run deploy cloud-post-deploy');
-
- $I->amOnPage('/');
- $I->see('Home page');
- $I->see('CMS homepage content goes here.');
- }
+ protected $removeEs = false;
/**
* @return array
*/
protected function testProvider(): array
{
- // @TODO change version to 2.3.* after fix in magento core.
- // https://magento2.atlassian.net/browse/MAGECLOUD-3725
return [
- ['from' => '2.3.0', 'to' => '>=2.3.1 <2.3.2'],
- ['from' => '2.3.3', 'to' => '>=2.3.4 <2.3.5'],
+ ['from' => '2.3.5', 'to' => '>=2.4.0 <2.4.1'],
];
}
}
diff --git a/src/Test/Functional/Acceptance/WizardScdCest.php b/src/Test/Functional/Acceptance/WizardScdCest.php
index 29afae5ca3..ff29aa54de 100644
--- a/src/Test/Functional/Acceptance/WizardScdCest.php
+++ b/src/Test/Functional/Acceptance/WizardScdCest.php
@@ -9,9 +9,15 @@
/**
* This test runs on the latest version of PHP
+ *
+ * @group php74
*/
class WizardScdCest extends AbstractCest
{
+ /**
+ * @param \CliTester $I
+ * @throws \Robo\Exception\TaskException
+ */
public function _before(\CliTester $I): void
{
parent::_before($I);
diff --git a/src/Test/Integration/Schema/ValidatorTest.php b/src/Test/Integration/Schema/ValidatorTest.php
index 60af5e173d..87dd4d5c96 100644
--- a/src/Test/Integration/Schema/ValidatorTest.php
+++ b/src/Test/Integration/Schema/ValidatorTest.php
@@ -320,7 +320,7 @@ public function validateDataProvider(): array
DeployInterface::VAR_SPLIT_DB,
['wrong'],
new Error(
- 'The SPLIT_DB variable contains the invalid value. It should be array with next available values: '
+ 'The SPLIT_DB variable contains the invalid value. It should be an array with following values: '
. '[quote, sales].'
)
],
@@ -328,7 +328,7 @@ public function validateDataProvider(): array
DeployInterface::VAR_SPLIT_DB,
['wrong', DeployInterface::SPLIT_DB_VALUE_QUOTE],
new Error(
- 'The SPLIT_DB variable contains the invalid value. It should be array with next available values: '
+ 'The SPLIT_DB variable contains the invalid value. It should be an array with following values: '
. '[quote, sales].'
)
],
diff --git a/src/Test/Unit/App/ErrorInfoTest.php b/src/Test/Unit/App/ErrorInfoTest.php
new file mode 100644
index 0000000000..5c49a2c3de
--- /dev/null
+++ b/src/Test/Unit/App/ErrorInfoTest.php
@@ -0,0 +1,92 @@
+fileListMock = $this->createMock(FileList::class);
+ $this->fileMock = $this->createMock(File::class);
+
+ $this->errorInfo = new ErrorInfo($this->fileMock, $this->fileListMock);
+ }
+
+ /**
+ * @throws \Magento\MagentoCloud\Filesystem\FileSystemException
+ * @dataProvider getErrorDataProvider
+ */
+ public function testGetError(int $errorCode, array $expected)
+ {
+ $filePath = __DIR__ . '/_file/schema.error.yaml';
+ $this->fileListMock->expects($this->once())
+ ->method('getErrorSchema')
+ ->willReturn($filePath);
+ $this->fileMock->expects($this->once())
+ ->method('fileGetContents')
+ ->with($filePath)
+ ->willReturn(file_get_contents($filePath));
+
+ $this->assertEquals($expected, $this->errorInfo->get($errorCode));
+ }
+
+ /**
+ * @return array
+ */
+ public function getErrorDataProvider(): array
+ {
+ return [
+ [
+ 12,
+ [],
+ ],
+ [
+ 2,
+ [
+ 'title' => 'Critical error',
+ 'suggestion' => 'Critical error suggestion',
+ 'stage' => 'build',
+ 'type' => 'critical',
+ ]
+ ],
+ [
+ 1001,
+ [
+ 'title' => 'Warning error',
+ 'suggestion' => 'Warning error suggestion',
+ 'stage' => 'build',
+ 'type' => 'warning',
+ ]
+ ]
+ ];
+ }
+}
diff --git a/src/Test/Unit/App/Logger/Error/ReaderTest.php b/src/Test/Unit/App/Logger/Error/ReaderTest.php
new file mode 100644
index 0000000000..81674488e8
--- /dev/null
+++ b/src/Test/Unit/App/Logger/Error/ReaderTest.php
@@ -0,0 +1,83 @@
+fileListMock = $this->createMock(FileList::class);
+
+ $this->reader = new Reader($this->fileListMock);
+ }
+
+ public function testRead()
+ {
+ $this->fileListMock->expects($this->once())
+ ->method('getCloudErrorLog')
+ ->willReturn(__DIR__ . '/_file/cloud.error.log');
+
+ $this->assertEquals(
+ [
+ 2007 => [
+ 'errorCode' => 2007,
+ 'stage' => 'deploy',
+ 'step' => 'validate-config',
+ 'suggestion' => 'warning suggestion',
+ 'title' => 'warning message',
+ 'type' => 'warning',
+ ],
+ 109 => [
+ 'errorCode' => 109,
+ 'stage' => 'deploy',
+ 'step' => 'validate-config',
+ 'suggestion' => 'critical suggestion 1',
+ 'title' => 'critical message 1',
+ 'type' => 'critical',
+ ],
+ 111 => [
+ 'errorCode' => 111,
+ 'stage' => 'deploy',
+ 'step' => 'validate-config',
+ 'suggestion' => 'critical suggestion 2',
+ 'title' => 'critical message 2',
+ 'type' => 'critical',
+ ]
+ ],
+ $this->reader->read()
+ );
+ }
+
+ public function testReadWithException()
+ {
+ $this->fileListMock->expects($this->once())
+ ->method('getCloudErrorLog')
+ ->willThrowException(new UndefinedPackageException('some error'));
+
+ $this->assertEquals([], $this->reader->read());
+ }
+}
diff --git a/src/Test/Unit/App/Logger/Error/_file/cloud.error.log b/src/Test/Unit/App/Logger/Error/_file/cloud.error.log
new file mode 100644
index 0000000000..84d600aae8
--- /dev/null
+++ b/src/Test/Unit/App/Logger/Error/_file/cloud.error.log
@@ -0,0 +1,3 @@
+{"errorCode":2007,"stage":"deploy","step":"validate-config","suggestion":"warning suggestion","title":"warning message","type":"warning"}
+{"errorCode":109,"stage":"deploy","step":"validate-config","suggestion":"critical suggestion 1","title":"critical message 1","type":"critical"}
+{"errorCode":111,"stage":"deploy","step":"validate-config","suggestion":"critical suggestion 2","title":"critical message 2","type":"critical"}
diff --git a/src/Test/Unit/App/Logger/Formatter/ErrorFormatterFactoryTest.php b/src/Test/Unit/App/Logger/Formatter/ErrorFormatterFactoryTest.php
new file mode 100644
index 0000000000..2872d0f56e
--- /dev/null
+++ b/src/Test/Unit/App/Logger/Formatter/ErrorFormatterFactoryTest.php
@@ -0,0 +1,59 @@
+containerMock = $this->createMock(ContainerInterface::class);
+
+ $this->errorFormatterFactory = new ErrorFormatterFactory($this->containerMock);
+ }
+
+ public function testCreate()
+ {
+ $this->containerMock->expects($this->exactly(2))
+ ->method('get')
+ ->withConsecutive(
+ [ErrorInfo::class],
+ [ReaderInterface::class]
+ )
+ ->willReturnOnConsecutiveCalls(
+ $this->createMock(ErrorInfo::class),
+ $this->getMockForAbstractClass(ReaderInterface::class)
+ );
+
+ $errorFormatter = $this->errorFormatterFactory->create();
+ $this->assertInstanceOf(JsonErrorFormatter::class, $errorFormatter);
+ }
+}
diff --git a/src/Test/Unit/App/Logger/Formatter/JsonErrorFormatterTest.php b/src/Test/Unit/App/Logger/Formatter/JsonErrorFormatterTest.php
new file mode 100644
index 0000000000..3bf3a5f5be
--- /dev/null
+++ b/src/Test/Unit/App/Logger/Formatter/JsonErrorFormatterTest.php
@@ -0,0 +1,122 @@
+errorInfoMock = $this->createMock(ErrorInfo::class);
+ $this->readerMock = $this->getMockForAbstractClass(ReaderInterface::class);
+
+ $this->jsonErrorFormatter = new JsonErrorFormatter(
+ $this->errorInfoMock,
+ $this->readerMock
+ );
+ }
+
+ public function testFormat()
+ {
+ $this->readerMock->expects($this->once())
+ ->method('read')
+ ->willReturn([]);
+ $this->errorInfoMock->expects($this->once())
+ ->method('get')
+ ->with(11)
+ ->willReturn([
+ 'title' => 'some custom title',
+ 'type' => 'warning'
+ ]);
+
+ $this->assertEquals(
+ '{"errorCode":11,"title":"some error","type":"warning"}' . PHP_EOL,
+ $this->jsonErrorFormatter->format(['message' => 'some error', 'context' => ['errorCode' => 11]])
+ );
+ }
+
+ public function testFormatEmptyError()
+ {
+ $this->readerMock->expects($this->once())
+ ->method('read')
+ ->willReturn([]);
+ $this->errorInfoMock->expects($this->once())
+ ->method('get')
+ ->with(11)
+ ->willReturn([]);
+
+ $this->assertEquals(
+ '{"errorCode":11,"suggestion":"some suggestion","title":"some error"}' . PHP_EOL,
+ $this->jsonErrorFormatter->format([
+ 'message' => 'some error',
+ 'context' => ['errorCode' => 11, 'suggestion' => 'some suggestion']
+ ])
+ );
+ }
+
+ public function testFormatMessageAlreadyLogged()
+ {
+ $this->readerMock->expects($this->once())
+ ->method('read')
+ ->willReturn([
+ 11 => ['message' => 'some error']
+ ]);
+ $this->errorInfoMock->expects($this->never())
+ ->method('get');
+
+ $this->assertFalse(
+ $this->jsonErrorFormatter->format(['message' => 'some error', 'context' => ['errorCode' => 11]])
+ );
+ }
+
+ public function testFormatNoErrorCode()
+ {
+ $this->readerMock->expects($this->never())
+ ->method('read');
+ $this->errorInfoMock->expects($this->never())
+ ->method('get');
+
+ $this->assertFalse($this->jsonErrorFormatter->format(['message' => 'test']));
+ }
+
+ public function testFormatWithException()
+ {
+ $this->readerMock->expects($this->once())
+ ->method('read')
+ ->willThrowException(new FileSystemException('error'));
+
+ $this->assertFalse($this->jsonErrorFormatter->format(['message' => 'test', 'context' => ['errorCode' => 11]]));
+ }
+}
diff --git a/src/Test/Unit/App/Logger/Formatter/LineFormatterTest.php b/src/Test/Unit/App/Logger/Formatter/LineFormatterTest.php
new file mode 100644
index 0000000000..8dddb5b707
--- /dev/null
+++ b/src/Test/Unit/App/Logger/Formatter/LineFormatterTest.php
@@ -0,0 +1,76 @@
+lineFormatter = new LineFormatter(LineFormatter::FORMAT_BASE, null, true, true);
+ }
+
+ /**
+ * @dataProvider formatDataProvider
+ * @param string $expected
+ * @param array $record
+ */
+ public function testFormat(string $expected, array $record)
+ {
+ $this->assertEquals($expected, $this->lineFormatter->format($record));
+ }
+
+ /**
+ * @return array
+ */
+ public function formatDataProvider(): array
+ {
+ return [
+ [
+ '[%datetime%] WARNING: test' . PHP_EOL,
+ [
+ 'message' => 'test',
+ 'level_name' => 'WARNING',
+ 'extra' => [],
+ 'context' => [],
+ ]
+ ],
+ [
+ '[%datetime%] WARNING: [111] test' . PHP_EOL,
+ [
+ 'message' => 'test',
+ 'level_name' => 'WARNING',
+ 'extra' => [],
+ 'context' => ['errorCode' => 111],
+ ]
+ ],
+ [
+ '[%datetime%] WARNING: [111] test' . PHP_EOL . 'some suggestion' . PHP_EOL,
+ [
+ 'message' => 'test',
+ 'level_name' => 'WARNING',
+ 'extra' => [],
+ 'context' => ['errorCode' => 111, 'suggestion' => 'some suggestion'],
+ ]
+ ],
+ ];
+ }
+}
diff --git a/src/Test/Unit/App/Logger/LineFormatterFactoryTest.php b/src/Test/Unit/App/Logger/LineFormatterFactoryTest.php
index 74afaa9362..ab5c09fb94 100644
--- a/src/Test/Unit/App/Logger/LineFormatterFactoryTest.php
+++ b/src/Test/Unit/App/Logger/LineFormatterFactoryTest.php
@@ -7,8 +7,10 @@
namespace Magento\MagentoCloud\Test\Unit\App\Logger;
+use Magento\MagentoCloud\App\ContainerInterface;
use Magento\MagentoCloud\App\Logger\LineFormatterFactory;
use Monolog\Formatter\LineFormatter;
+use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
/**
@@ -16,8 +18,14 @@
*/
class LineFormatterFactoryTest extends TestCase
{
- public function testCreate()
+ public function testCreate(): void
{
- $this->assertInstanceOf(LineFormatter::class, (new LineFormatterFactory())->create());
+ /** @var ContainerInterface|MockObject $containerMock */
+ $containerMock = $this->getMockForAbstractClass(ContainerInterface::class);
+
+ $this->assertInstanceOf(
+ LineFormatter::class,
+ (new LineFormatterFactory($containerMock))->create()
+ );
}
}
diff --git a/src/Test/Unit/App/Logger/PoolTest.php b/src/Test/Unit/App/Logger/PoolTest.php
index 5cbac93fbf..ab02653754 100644
--- a/src/Test/Unit/App/Logger/PoolTest.php
+++ b/src/Test/Unit/App/Logger/PoolTest.php
@@ -8,10 +8,11 @@
namespace Magento\MagentoCloud\Test\Unit\App\Logger;
use Magento\MagentoCloud\App\Error;
+use Magento\MagentoCloud\App\Logger\Formatter\JsonErrorFormatter;
use Magento\MagentoCloud\App\Logger\Pool;
use Magento\MagentoCloud\App\Logger\LineFormatterFactory;
use Magento\MagentoCloud\App\LoggerException;
-use Monolog\Formatter\LineFormatter;
+use Magento\MagentoCloud\App\Logger\Formatter\LineFormatter;
use Magento\MagentoCloud\App\Logger\HandlerFactory;
use Monolog\Handler\HandlerInterface;
use Magento\MagentoCloud\Config\Log as LogConfig;
@@ -61,12 +62,14 @@ protected function setUp()
*/
public function testGetHandlers()
{
+ $jsonErrorFormatterMock = $this->createMock(JsonErrorFormatter::class);
$this->logConfigMock->expects($this->once())
->method('getHandlers')
->willReturn([
'slack' => [],
'email' => ['use_default_formatter' => false],
- 'syslog' => ['use_default_formatter' => true]
+ 'syslog' => ['use_default_formatter' => true],
+ 'error-logger' => ['formatter' => $jsonErrorFormatterMock]
]);
$formatterMock = $this->createMock(LineFormatter::class);
@@ -87,11 +90,16 @@ public function testGetHandlers()
$syslogHandler = $this->getMockForAbstractClass(HandlerInterface::class);
$syslogHandler->expects($this->never())
->method('setFormatter');
+ $errorHandler = $this->getMockForAbstractClass(HandlerInterface::class);
+ $errorHandler->expects($this->once())
+ ->method('setFormatter')
+ ->with($jsonErrorFormatterMock)
+ ->willReturnSelf();
- $this->handlerFactoryMock->expects($this->exactly(3))
+ $this->handlerFactoryMock->expects($this->exactly(4))
->method('create')
- ->withConsecutive(['slack'], ['email'], ['syslog'])
- ->willReturnOnConsecutiveCalls($slackHandlerMock, $emailHandlerMock, $syslogHandler);
+ ->withConsecutive(['slack'], ['email'], ['syslog'], ['error-logger'])
+ ->willReturnOnConsecutiveCalls($slackHandlerMock, $emailHandlerMock, $syslogHandler, $errorHandler);
$this->pool->getHandlers();
// Lazy load.
@@ -110,4 +118,17 @@ public function testWithParseException()
$this->pool->getHandlers();
}
+
+ public function testWithException()
+ {
+ $this->expectExceptionMessage('some error');
+ $this->expectExceptionCode(101);
+ $this->expectException(LoggerException::class);
+
+ $this->logConfigMock->expects($this->once())
+ ->method('getHandlers')
+ ->willThrowException(new \Exception('some error', 101));
+
+ $this->pool->getHandlers();
+ }
}
diff --git a/src/Test/Unit/App/LoggerTest.php b/src/Test/Unit/App/LoggerTest.php
index 271678566f..f2fb630428 100644
--- a/src/Test/Unit/App/LoggerTest.php
+++ b/src/Test/Unit/App/LoggerTest.php
@@ -14,6 +14,7 @@
use Magento\MagentoCloud\Filesystem\FileList;
use Magento\MagentoCloud\Filesystem\Driver\File;
use Magento\MagentoCloud\App\Logger\Pool;
+use Magento\MagentoCloud\Package\UndefinedPackageException;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Magento\MagentoCloud\App\Logger\Processor\SanitizeProcessor;
@@ -180,4 +181,26 @@ public function executeDataProvider(): array
],
];
}
+
+ /**
+ * @throws LoggerException
+ */
+ public function testWithLoggerException()
+ {
+ $this->expectException(LoggerException::class);
+ $this->expectExceptionMessage('some error');
+
+ $this->fileListMock->expects($this->once())
+ ->method('getCloudLog')
+ ->willThrowException(new UndefinedPackageException('some error'));
+
+ new Logger(
+ $this->fileMock,
+ $this->directoryListMock,
+ $this->fileListMock,
+ $this->poolMock,
+ $this->sanitizeProcessorMock,
+ $this->errorLogFileMock
+ );
+ }
}
diff --git a/src/Test/Unit/App/_file/schema.error.yaml b/src/Test/Unit/App/_file/schema.error.yaml
new file mode 100644
index 0000000000..4fee4a0b2e
--- /dev/null
+++ b/src/Test/Unit/App/_file/schema.error.yaml
@@ -0,0 +1,10 @@
+2:
+ title: 'Critical error'
+ suggestion: 'Critical error suggestion'
+ stage: build
+ type: critical
+1001:
+ title: 'Warning error'
+ suggestion: 'Warning error suggestion'
+ stage: build
+ type: warning
diff --git a/src/Test/Unit/ApplicationTest.php b/src/Test/Unit/ApplicationTest.php
index f216644d65..bdc2a95577 100644
--- a/src/Test/Unit/ApplicationTest.php
+++ b/src/Test/Unit/ApplicationTest.php
@@ -68,6 +68,7 @@ class ApplicationTest extends TestCase
Command\BackupList::NAME => Command\BackupList::class,
Command\ApplyPatches::NAME => Command\ApplyPatches::class,
Command\Dev\UpdateComposer::NAME => Command\Dev\UpdateComposer::class,
+ Command\Dev\GenerateSchemaError::NAME => Command\Dev\GenerateSchemaError::class,
Command\Wizard\ScdOnBuild::NAME => Command\Wizard\ScdOnBuild::class,
Command\Wizard\ScdOnDeploy::NAME => Command\Wizard\ScdOnDeploy::class,
Command\Wizard\ScdOnDemand::NAME => Command\Wizard\ScdOnDemand::class,
@@ -81,6 +82,7 @@ class ApplicationTest extends TestCase
Command\ConfigShow::NAME => Command\ConfigShow::class,
Command\RunCommand::NAME => Command\RunCommand::class,
Command\GenerateSchema::NAME => Command\GenerateSchema::class,
+ Command\ErrorShow::NAME => Command\ErrorShow::class,
];
/**
diff --git a/src/Test/Unit/Command/Dev/UpdateComposer/ComposerGeneratorTest.php b/src/Test/Unit/Command/Dev/UpdateComposer/ComposerGeneratorTest.php
index addca2e1b7..4fa0c95767 100644
--- a/src/Test/Unit/Command/Dev/UpdateComposer/ComposerGeneratorTest.php
+++ b/src/Test/Unit/Command/Dev/UpdateComposer/ComposerGeneratorTest.php
@@ -29,16 +29,24 @@ class ComposerGeneratorTest extends TestCase
],
'repo2' => [
'repo' => 'path_to_repo2',
+ 'ref' => '',
'branch' => '2.0.0',
],
'repo3' => [
'repo' => 'path_to_repo3',
+ 'ref' => 'ref3',
'branch' => '3.0.0',
],
'repo4' => [
'repo' => 'path_to_repo4',
+ 'ref' => 'ref4',
'branch' => '4.0.0',
- ]
+ ],
+ 'repo5' => [
+ 'repo' => 'path_to_repo5',
+ 'ref' => 'ref5',
+ 'branch' => '5.0.0',
+ ],
];
/**
@@ -80,7 +88,9 @@ protected function setUp()
public function testGetInstallFromGitScripts()
{
- $this->assertInstallFromGitScripts($this->composerGenerator->getInstallFromGitScripts($this->repoOptions));
+ $expected = include(__DIR__ . '/_files/expected_composer.php');
+ $actual = $this->composerGenerator->getInstallFromGitScripts($this->repoOptions);
+ $this->assertEquals($expected['scripts']['install-from-git'], $actual);
}
public function testGenerate(): void
@@ -93,24 +103,4 @@ public function testGenerate(): void
$this->assertEquals($value, $composer[$key]);
}
}
-
- /**
- * @param array $actual
- *
- * @return void
- */
- private function assertInstallFromGitScripts(array $actual): void
- {
- $this->assertEquals(
- [
- 'php -r"@mkdir(__DIR__ . \'/app/etc\', 0777, true);"',
- 'rm -rf repo1 repo2 repo3 repo4',
- 'git clone path_to_repo1 "repo1" && git --git-dir="repo1/.git" --work-tree="repo1" checkout 1.0.0',
- 'git clone path_to_repo2 "repo2" && git --git-dir="repo2/.git" --work-tree="repo2" checkout 2.0.0',
- 'git clone path_to_repo3 "repo3" && git --git-dir="repo3/.git" --work-tree="repo3" checkout 3.0.0',
- 'git clone path_to_repo4 "repo4" && git --git-dir="repo4/.git" --work-tree="repo4" checkout 4.0.0',
- ],
- $actual
- );
- }
}
diff --git a/src/Test/Unit/Command/Dev/UpdateComposer/_files/app/repo5/composer.json b/src/Test/Unit/Command/Dev/UpdateComposer/_files/app/repo5/composer.json
new file mode 100644
index 0000000000..3bcfea6805
--- /dev/null
+++ b/src/Test/Unit/Command/Dev/UpdateComposer/_files/app/repo5/composer.json
@@ -0,0 +1,4 @@
+{
+ "name": "vendor/module-module5",
+ "type": "magento2-module"
+}
diff --git a/src/Test/Unit/Command/Dev/UpdateComposer/_files/expected_composer.php b/src/Test/Unit/Command/Dev/UpdateComposer/_files/expected_composer.php
index 6f2d849612..2f9399afd1 100644
--- a/src/Test/Unit/Command/Dev/UpdateComposer/_files/expected_composer.php
+++ b/src/Test/Unit/Command/Dev/UpdateComposer/_files/expected_composer.php
@@ -33,21 +33,30 @@
'symlink' => false,
],
],
+ 'vendor/module-module5' => [
+ 'type' => 'path',
+ 'url' => 'repo5/',
+ 'options' => [
+ 'symlink' => false,
+ ],
+ ],
],
'require' => [
'package' => '*',
'vendor/library1' => '*@dev',
'vendor/theme1' => '*@dev',
'vendor/module-module1' => '*@dev',
+ 'vendor/module-module5' => '*@dev',
],
'scripts' =>[
'install-from-git' => [
'php -r"@mkdir(__DIR__ . \'/app/etc\', 0777, true);"',
- 'rm -rf repo1 repo2 repo3 repo4',
- 'git clone path_to_repo1 "repo1" && git --git-dir="repo1/.git" --work-tree="repo1" checkout 1.0.0',
- 'git clone path_to_repo2 "repo2" && git --git-dir="repo2/.git" --work-tree="repo2" checkout 2.0.0',
- 'git clone path_to_repo3 "repo3" && git --git-dir="repo3/.git" --work-tree="repo3" checkout 3.0.0',
- 'git clone path_to_repo4 "repo4" && git --git-dir="repo4/.git" --work-tree="repo4" checkout 4.0.0',
+ 'rm -rf repo1 repo2 repo3 repo4 repo5',
+ 'git clone -b 1.0.0 --single-branch --depth 1 path_to_repo1 repo1',
+ 'git clone -b 2.0.0 --single-branch --depth 1 path_to_repo2 repo2',
+ 'git clone path_to_repo3 "repo3" && git --git-dir="repo3/.git" --work-tree="repo3" checkout ref3',
+ 'git clone path_to_repo4 "repo4" && git --git-dir="repo4/.git" --work-tree="repo4" checkout ref4',
+ 'git clone path_to_repo5 "repo5" && git --git-dir="repo5/.git" --work-tree="repo5" checkout ref5',
],
'pre-install-cmd' => [
'@install-from-git',
diff --git a/src/Test/Unit/Command/ErrorShowTest.php b/src/Test/Unit/Command/ErrorShowTest.php
new file mode 100644
index 0000000000..d6dff0829b
--- /dev/null
+++ b/src/Test/Unit/Command/ErrorShowTest.php
@@ -0,0 +1,158 @@
+errorInfoMock = $this->createMock(ErrorInfo::class);
+ $this->readerMock = $this->getMockForAbstractClass(ReaderInterface::class);
+
+ $this->command = new ErrorShow($this->errorInfoMock, $this->readerMock);
+ }
+
+ public function testExecuteWithCode()
+ {
+ $this->errorInfoMock->expects($this->once())
+ ->method('get')
+ ->with(12)
+ ->willReturn([
+ 'title' => 'some error',
+ 'suggestion' => 'some suggestion',
+ 'stage' => 'deploy'
+ ]);
+ $this->readerMock->expects($this->never())
+ ->method('read');
+
+ $tester = new CommandTester($this->command);
+ $tester->execute([ErrorShow::ARGUMENT_ERROR_CODE => '12']);
+
+ $message = implode(PHP_EOL, [
+ 'errorCode: 12',
+ 'stage: deploy',
+ 'suggestion: some suggestion',
+ 'title: some error'
+ ]);
+ $this->assertContains($message, $tester->getDisplay());
+ }
+
+ public function testExecuteWithWrongErrorCode()
+ {
+ $this->errorInfoMock->expects($this->once())
+ ->method('get')
+ ->with(1111)
+ ->willReturn([]);
+ $this->readerMock->expects($this->never())
+ ->method('read');
+
+ $tester = new CommandTester($this->command);
+ $tester->execute([ErrorShow::ARGUMENT_ERROR_CODE => '1111']);
+
+ $this->assertContains('Error with code 1111 is not registered in the error schema', $tester->getDisplay());
+ }
+
+ public function testExecuteWithoutCode()
+ {
+ $this->errorInfoMock->expects($this->never())
+ ->method('get');
+ $this->readerMock->expects($this->once())
+ ->method('read')
+ ->willReturn([
+ [
+ 'errorCode: 12',
+ 'stage' => 'deploy',
+ 'suggestion' => 'some suggestion',
+ 'title' => 'some warning error',
+ 'type' => 'warning'
+ ],
+ [
+ 'errorCode' => '13',
+ 'stage' => 'deploy',
+ 'suggestion' => 'some suggestion',
+ 'title' => 'some critical error',
+ 'type' => 'critical'
+ ],
+ ]);
+
+ $tester = new CommandTester($this->command);
+ $tester->execute([]);
+
+ $this->assertContains('errorCode: 13', $tester->getDisplay());
+ $this->assertContains('errorCode: 12', $tester->getDisplay());
+ }
+
+ public function testExecuteWithoutCodeJsonFormat()
+ {
+ $errors = [
+ [
+ 'errorCode: 12',
+ 'stage' => 'deploy',
+ 'suggestion' => 'some suggestion',
+ 'title' => 'some warning error',
+ 'type' => 'warning'
+ ],
+ [
+ 'errorCode' => '13',
+ 'stage' => 'deploy',
+ 'suggestion' => 'some suggestion',
+ 'title' => 'some critical error',
+ 'type' => 'critical'
+ ],
+ ];
+ $this->errorInfoMock->expects($this->never())
+ ->method('get');
+ $this->readerMock->expects($this->once())
+ ->method('read')
+ ->willReturn($errors);
+
+ $tester = new CommandTester($this->command);
+ $tester->execute(['--json' => true]);
+
+ $this->assertContains(json_encode($errors), $tester->getDisplay());
+ }
+
+ public function testExecuteWithoutCodeEmptyLog()
+ {
+ $this->errorInfoMock->expects($this->never())
+ ->method('get');
+ $this->readerMock->expects($this->once())
+ ->method('read')
+ ->willReturn([]);
+
+ $tester = new CommandTester($this->command);
+ $tester->execute([]);
+
+ $this->assertContains('The error log is empty or does not exist', $tester->getDisplay());
+ }
+}
diff --git a/src/Test/Unit/Config/Factory/CacheTest.php b/src/Test/Unit/Config/Factory/CacheTest.php
index 4dfbf828ee..197396f74a 100644
--- a/src/Test/Unit/Config/Factory/CacheTest.php
+++ b/src/Test/Unit/Config/Factory/CacheTest.php
@@ -220,18 +220,14 @@ public function getFromRelationshipsDataProvider()
],
];
$resultMasterOnlyConnectionRedisCache = $resultMasterOnlyConnection;
- $resultMasterOnlyConnectionRedisCache['frontend']['default']['backend'] = addslashes(
- Cache::REDIS_BACKEND_REDIS_CACHE
- );
- $resultMasterOnlyConnectionRedisCache['frontend']['page_cache']['backend'] = addslashes(
- Cache::REDIS_BACKEND_REDIS_CACHE
- );
+ $resultMasterOnlyConnectionRedisCache['frontend']['default']['backend'] = Cache::REDIS_BACKEND_REDIS_CACHE;
+ $resultMasterOnlyConnectionRedisCache['frontend']['page_cache']['backend'] = Cache::REDIS_BACKEND_REDIS_CACHE;
$resultMasterOnlyConnectionSyncCache = [
'frontend' => [
'default' => [
- 'backend' => addslashes(Cache::REDIS_BACKEND_REMOTE_SYNCHRONIZED_CACHE),
+ 'backend' => Cache::REDIS_BACKEND_REMOTE_SYNCHRONIZED_CACHE,
'backend_options' => [
- 'remote_backend' => addslashes(Cache::REDIS_BACKEND_REDIS_CACHE),
+ 'remote_backend' => Cache::REDIS_BACKEND_REDIS_CACHE,
'remote_backend_options' => [
'server' => 'master.host',
'port' => 'master.port',
@@ -287,12 +283,8 @@ public function getFromRelationshipsDataProvider()
$slaveConfiguration
);
$resultMasterSlaveConnectionRedisCache = $resultMasterSlaveConnection;
- $resultMasterSlaveConnectionRedisCache['frontend']['default']['backend'] = addslashes(
- Cache::REDIS_BACKEND_REDIS_CACHE
- );
- $resultMasterSlaveConnectionRedisCache['frontend']['page_cache']['backend'] = addslashes(
- Cache::REDIS_BACKEND_REDIS_CACHE
- );
+ $resultMasterSlaveConnectionRedisCache['frontend']['default']['backend'] = Cache::REDIS_BACKEND_REDIS_CACHE;
+ $resultMasterSlaveConnectionRedisCache['frontend']['page_cache']['backend'] = Cache::REDIS_BACKEND_REDIS_CACHE;
$resultMasterSlaveConnectionSyncCache = $resultMasterOnlyConnectionSyncCache;
$resultMasterSlaveConnectionSyncCache['frontend']['default'] = array_merge_recursive(
$resultMasterSlaveConnectionSyncCache['frontend']['default'],
@@ -302,12 +294,10 @@ public function getFromRelationshipsDataProvider()
$resultMasterSlaveConnectionWithMergedValue = $resultMasterSlaveConnection;
$resultMasterSlaveConnectionWithMergedValue['frontend']['default']['backend_options']['value'] = 'key';
$resultMasterSlaveConnectionWithMergedValueRedisCache = $resultMasterSlaveConnectionWithMergedValue;
- $resultMasterSlaveConnectionWithMergedValueRedisCache['frontend']['default']['backend'] = addslashes(
- Cache::REDIS_BACKEND_REDIS_CACHE
- );
- $resultMasterSlaveConnectionWithMergedValueRedisCache['frontend']['page_cache']['backend'] = addslashes(
- Cache::REDIS_BACKEND_REDIS_CACHE
- );
+ $resultMasterSlaveConnectionWithMergedValueRedisCache['frontend']['default']['backend'] =
+ Cache::REDIS_BACKEND_REDIS_CACHE;
+ $resultMasterSlaveConnectionWithMergedValueRedisCache['frontend']['page_cache']['backend'] =
+ Cache::REDIS_BACKEND_REDIS_CACHE;
$resultMasterSlaveConnectionWithMergedValueSyncCache = $resultMasterSlaveConnectionSyncCache;
$resultMasterSlaveConnectionWithMergedValueSyncCache['frontend']['default']['backend_options']['value'] = 'key';
@@ -315,12 +305,10 @@ public function getFromRelationshipsDataProvider()
$resultMasterSlaveConnectionWithDiffHost['frontend']['default']['backend_options']['value'] = 'key';
$resultMasterSlaveConnectionWithDiffHost['frontend']['default']['backend_options']['server'] = 'new.host';
$resultMasterSlaveConnectionWithDiffHostRedisCache = $resultMasterSlaveConnectionWithDiffHost;
- $resultMasterSlaveConnectionWithDiffHostRedisCache['frontend']['default']['backend'] = addslashes(
- Cache::REDIS_BACKEND_REDIS_CACHE
- );
- $resultMasterSlaveConnectionWithDiffHostRedisCache['frontend']['page_cache']['backend'] = addslashes(
- Cache::REDIS_BACKEND_REDIS_CACHE
- );
+ $resultMasterSlaveConnectionWithDiffHostRedisCache['frontend']['default']['backend'] =
+ Cache::REDIS_BACKEND_REDIS_CACHE;
+ $resultMasterSlaveConnectionWithDiffHostRedisCache['frontend']['page_cache']['backend'] =
+ Cache::REDIS_BACKEND_REDIS_CACHE;
$resultMasterSlaveConnectionWithDiffHostSyncCache = $resultMasterOnlyConnectionSyncCache;
$remoteBackendOptionsDiffHostSync = [
'frontend' => [
diff --git a/src/Test/Unit/Config/LogTest.php b/src/Test/Unit/Config/LogTest.php
index 4e6f5708f9..3cd99c522f 100644
--- a/src/Test/Unit/Config/LogTest.php
+++ b/src/Test/Unit/Config/LogTest.php
@@ -8,6 +8,8 @@
namespace Magento\MagentoCloud\Test\Unit\Config;
use Illuminate\Contracts\Config\Repository;
+use Magento\MagentoCloud\App\Logger\Formatter\ErrorFormatterFactory;
+use Magento\MagentoCloud\App\Logger\Formatter\JsonErrorFormatter;
use Magento\MagentoCloud\Config\Log as LogConfig;
use Magento\MagentoCloud\Config\RepositoryFactory;
use Magento\MagentoCloud\Filesystem\FileList;
@@ -46,6 +48,15 @@ class LogTest extends TestCase
*/
private $repositoryMock;
+ /**
+ * @var ErrorFormatterFactory|MockObject
+ */
+ private $errorFormatterFactoryMock;
+ /**
+ * @var JsonErrorFormatter|MockObject
+ */
+ private $errorFormatterMock;
+
/**
* @inheritdoc
*/
@@ -55,15 +66,21 @@ protected function setUp()
$this->readerMock = $this->createMock(Reader::class);
$this->repositoryFactoryMock = $this->createMock(RepositoryFactory::class);
$this->repositoryMock = $this->createMock(Repository::class);
+ $this->errorFormatterFactoryMock = $this->createMock(ErrorFormatterFactory::class);
+ $this->errorFormatterMock = $this->createMock(JsonErrorFormatter::class);
$this->repositoryFactoryMock->expects($this->any())
->method('create')
->willReturn($this->repositoryMock);
+ $this->errorFormatterFactoryMock->expects($this->any())
+ ->method('create')
+ ->willReturn($this->errorFormatterMock);
$this->logConfig = new LogConfig(
$this->fileListMock,
$this->readerMock,
- $this->repositoryFactoryMock
+ $this->repositoryFactoryMock,
+ $this->errorFormatterFactoryMock
);
}
@@ -84,6 +101,8 @@ public function testGetHandlers(array $config, array $expectedResult): void
->method('read')
->willReturn($config);
+ $expectedResult[HandlerFactory::HANDLER_FILE_ERROR]['formatter'] = $this->errorFormatterMock;
+
$this->assertSame($expectedResult, $this->logConfig->getHandlers());
}
@@ -98,7 +117,10 @@ public function getHandlersDataProvider(): array
'expectedResult' => [
HandlerFactory::HANDLER_STREAM => ['stream' => 'php://stdout'],
HandlerFactory::HANDLER_FILE => ['file' => 'somePath'],
- HandlerFactory::HANDLER_FILE_ERROR => ['file' => 'somePathErrorLog', 'min_level' => 'warning'],
+ HandlerFactory::HANDLER_FILE_ERROR => [
+ 'file' => 'somePathErrorLog',
+ 'min_level' => 'warning',
+ ],
]
],
[
diff --git a/src/Test/Unit/Config/Schema/Validator/RangeTest.php b/src/Test/Unit/Config/Schema/Validator/RangeTest.php
index 2dfe1bc4cc..1d39da709c 100644
--- a/src/Test/Unit/Config/Schema/Validator/RangeTest.php
+++ b/src/Test/Unit/Config/Schema/Validator/RangeTest.php
@@ -7,6 +7,7 @@
namespace Magento\MagentoCloud\Test\Unit\Config\Schema\Validator;
+use Magento\MagentoCloud\App\ErrorInfo;
use Magento\MagentoCloud\Config\Schema\Validator\Range;
use Magento\MagentoCloud\Config\Validator\Result\Error;
use Magento\MagentoCloud\Config\Validator\Result\Success;
@@ -27,9 +28,14 @@ class RangeTest extends TestCase
/**
* @inheritDoc
*/
- protected function setUp()
+ protected function setUp(): void
{
- $this->resultFactoryMock = $this->createTestProxy(ResultFactory::class);
+ $this->resultFactoryMock = $this->createTestProxy(
+ ResultFactory::class,
+ [
+ $this->createMock(ErrorInfo::class)
+ ]
+ );
}
public function testValidate(): void
diff --git a/src/Test/Unit/Config/Schema/Validator/SplitDbTest.php b/src/Test/Unit/Config/Schema/Validator/SplitDbTest.php
index 52344784b9..f237592708 100644
--- a/src/Test/Unit/Config/Schema/Validator/SplitDbTest.php
+++ b/src/Test/Unit/Config/Schema/Validator/SplitDbTest.php
@@ -32,9 +32,9 @@ class SplitDbTest extends TestCase
/**
* @inheritDoc
*/
- protected function setUp()
+ protected function setUp(): void
{
- $this->resultFactoryMock = $this->createTestProxy(ResultFactory::class);
+ $this->resultFactoryMock = $this->createMock(ResultFactory::class);
$this->validator = new SplitDb(
$this->resultFactoryMock
@@ -43,16 +43,23 @@ protected function setUp()
public function testValidate(): void
{
- $this->assertEquals(new Success(), $this->validator->validate('SOME_VARIABLE', ['sales', 'quote']));
+ $this->assertInstanceOf(
+ Success::class,
+ $this->validator->validate('SOME_VARIABLE', ['sales', 'quote'])
+ );
}
public function testValidateWithError(): void
{
- $this->assertEquals(
- new Error(
+ $this->resultFactoryMock->expects($this->once())
+ ->method('error')
+ ->with(
'The SOME_VARIABLE variable contains the invalid value.'
- .' It should be array with next available values: [quote, sales].'
- ),
+ .' It should be an array with following values: [quote, sales].'
+ );
+
+ $this->assertInstanceOf(
+ Error::class,
$this->validator->validate('SOME_VARIABLE', ['invalid_value'])
);
}
diff --git a/src/Test/Unit/Config/Schema/ValidatorTest.php b/src/Test/Unit/Config/Schema/ValidatorTest.php
index a231f03b3f..dbcbfd9da2 100644
--- a/src/Test/Unit/Config/Schema/ValidatorTest.php
+++ b/src/Test/Unit/Config/Schema/ValidatorTest.php
@@ -7,6 +7,7 @@
namespace Magento\MagentoCloud\Test\Unit\Config\Schema;
+use Magento\MagentoCloud\App\ErrorInfo;
use Magento\MagentoCloud\Config\Schema;
use Magento\MagentoCloud\Config\Schema\Validator;
use Magento\MagentoCloud\Config\StageConfigInterface;
@@ -45,10 +46,10 @@ class ValidatorTest extends TestCase
/**
* @inheritDoc
*/
- protected function setUp()
+ protected function setUp(): void
{
$this->schemaMock = $this->createMock(Schema::class);
- $this->resultFactoryMock = $this->createTestProxy(ResultFactory::class);
+ $this->resultFactoryMock = $this->createTestProxy(ResultFactory::class, [$this->createMock(ErrorInfo::class)]);
$this->validatorFactoryMock = $this->createMock(Validator\ValidatorFactory::class);
$this->validator = new Validator(
diff --git a/src/Test/Unit/Config/SchemaTest.php b/src/Test/Unit/Config/SchemaTest.php
index d90f739bc8..fba9691931 100644
--- a/src/Test/Unit/Config/SchemaTest.php
+++ b/src/Test/Unit/Config/SchemaTest.php
@@ -77,6 +77,7 @@ public function testGetDefaultsForBuild(): void
BuildInterface::VAR_SCD_MAX_EXEC_TIME => null,
BuildInterface::VAR_ERROR_REPORT_DIR_NESTING_LEVEL => 1,
BuildInterface::VAR_SCD_USE_BALER => false,
+ BuildInterface::VAR_QUALITY_PATCHES => []
],
$this->schema->getDefaults(StageConfigInterface::STAGE_BUILD)
);
diff --git a/src/Test/Unit/Config/Validator/Build/ConfigFileExistsTest.php b/src/Test/Unit/Config/Validator/Build/ConfigFileExistsTest.php
index 408b9d5c0e..2a9664dfd0 100644
--- a/src/Test/Unit/Config/Validator/Build/ConfigFileExistsTest.php
+++ b/src/Test/Unit/Config/Validator/Build/ConfigFileExistsTest.php
@@ -88,17 +88,15 @@ public function testRunFileNotExists(): void
->willReturn(false);
$resultMock = $this->createMock(Error::class);
$this->resultFactoryMock->expects($this->once())
- ->method('create')
+ ->method('error')
->with(
- ResultInterface::ERROR,
- [
- 'error' => 'File app/etc/config.php does not exist',
- 'suggestion' => 'Please run the following commands:' . PHP_EOL
- . '1. bin/magento module:enable --all' . PHP_EOL
- . '2. git add -f app/etc/config.php' . PHP_EOL
- . '3. git commit -m \'Adding config.php\'' . PHP_EOL
- . '4. git push'
- ]
+ 'File app/etc/config.php does not exist',
+ 'Please run the following commands:' . PHP_EOL
+ . '1. bin/magento module:enable --all' . PHP_EOL
+ . '2. git add -f app/etc/config.php' . PHP_EOL
+ . '3. git commit -m \'Adding config.php\'' . PHP_EOL
+ . '4. git push',
+ \Magento\MagentoCloud\App\Error::WARN_CONFIG_PHP_NOT_EXISTS
)
->willReturn($resultMock);
diff --git a/src/Test/Unit/Config/Validator/Build/MagentoAppYamlTest.php b/src/Test/Unit/Config/Validator/Build/MagentoAppYamlTest.php
new file mode 100644
index 0000000000..8c442e6cac
--- /dev/null
+++ b/src/Test/Unit/Config/Validator/Build/MagentoAppYamlTest.php
@@ -0,0 +1,139 @@
+magentoVersionMock = $this->createMock(MagentoVersion::class);
+ $this->environmentMock = $this->createMock(Environment::class);
+ $this->resultFactoryMock = $this->createMock(ResultFactory::class);
+
+ $this->validator = new MagentoAppYaml(
+ $this->environmentMock,
+ $this->magentoVersionMock,
+ $this->resultFactoryMock
+ );
+ }
+
+ public function testSuccessVersion(): void
+ {
+ $this->magentoVersionMock->expects($this->once())
+ ->method('satisfies')
+ ->with('>= 2.4.0')
+ ->willReturn(false);
+ $this->resultFactoryMock->expects($this->never())
+ ->method('errorByCode');
+
+ $this->assertInstanceOf(
+ Success::class,
+ $this->validator->validate()
+ );
+ }
+
+ public function testSuccessNoVariable(): void
+ {
+ $this->magentoVersionMock->expects($this->once())
+ ->method('satisfies')
+ ->with('>= 2.4.0')
+ ->willReturn(true);
+ $this->environmentMock->expects($this->once())
+ ->method('getApplication')
+ ->willReturn([
+ 'variables' => [
+ 'env' => [
+ 'some_variable' => 'some_value'
+ ]
+ ]
+ ]);
+ $this->resultFactoryMock->expects($this->never())
+ ->method('errorByCode');
+
+ $this->assertInstanceOf(
+ Success::class,
+ $this->validator->validate()
+ );
+ }
+
+ public function testError(): void
+ {
+ $this->magentoVersionMock->expects($this->once())
+ ->method('satisfies')
+ ->with('>= 2.4.0')
+ ->willReturn(true);
+ $this->environmentMock->expects($this->once())
+ ->method('getApplication')
+ ->willReturn([
+ 'variables' => [
+ 'env' => [
+ 'CONFIG__STORES__DEFAULT__PAYMENT__BRAINTREE__CHANNEL' => 'Magento_Enterprise_Cloud_BT'
+ ]
+ ]
+ ]);
+ $this->resultFactoryMock->expects($this->once())
+ ->method('errorByCode')
+ ->with(AppError::BUILD_WRONG_BRAINTREE_VARIABLE);
+
+ $this->assertInstanceOf(
+ Error::class,
+ $this->validator->validate()
+ );
+ }
+
+ public function testWithException(): void
+ {
+ $this->expectException(ValidatorException::class);
+ $this->expectExceptionMessage('some error');
+
+ $this->magentoVersionMock->expects($this->once())
+ ->method('satisfies')
+ ->with('>= 2.4.0')
+ ->willThrowException(new UndefinedPackageException('some error'));
+
+ $this->validator->validate();
+ }
+}
diff --git a/src/Test/Unit/Config/Validator/Deploy/ElasticSearchVersionTest.php b/src/Test/Unit/Config/Validator/Deploy/ElasticSearchVersionTest.php
index b060247c5c..5ff69f9ea7 100644
--- a/src/Test/Unit/Config/Validator/Deploy/ElasticSearchVersionTest.php
+++ b/src/Test/Unit/Config/Validator/Deploy/ElasticSearchVersionTest.php
@@ -135,10 +135,10 @@ public function testValidatePackageNotExists(): void
$this->managerMock->expects($this->once())
->method('get')
->with('elasticsearch/elasticsearch')
- ->willThrowException(new UndefinedPackageException('package doesn\'t exist'));
+ ->willThrowException(new UndefinedPackageException('package does not exist'));
$this->loggerMock->expects($this->once())
->method('warning')
- ->with('Can\'t validate version of elasticsearch: package doesn\'t exist');
+ ->with('Can\'t validate version of elasticsearch: package does not exist');
$this->resultFactoryMock->expects($this->once())
->method('success');
diff --git a/src/Test/Unit/Config/Validator/Deploy/ElasticsearchIntegrityTest.php b/src/Test/Unit/Config/Validator/Deploy/ElasticsearchIntegrityTest.php
index bead27b12a..3effc2fce5 100644
--- a/src/Test/Unit/Config/Validator/Deploy/ElasticsearchIntegrityTest.php
+++ b/src/Test/Unit/Config/Validator/Deploy/ElasticsearchIntegrityTest.php
@@ -7,6 +7,7 @@
namespace Magento\MagentoCloud\Test\Unit\Config\Validator\Deploy;
+use Magento\MagentoCloud\App\Error;
use Magento\MagentoCloud\Config\Validator\Deploy\ElasticSearchIntegrity;
use Magento\MagentoCloud\Config\Validator\ResultFactory;
use Magento\MagentoCloud\Config\ValidatorException;
@@ -84,7 +85,8 @@ public function testValidateNoElasticSearch(): void
->method('isInstalled')
->willReturn(false);
$this->resultFactoryMock->expects($this->once())
- ->method('error');
+ ->method('errorByCode')
+ ->with(Error::DEPLOY_WRONG_SEARCH_ENGINE);
$this->validator->validate();
}
diff --git a/src/Test/Unit/Config/Validator/Deploy/EnvironmentVariablesTest.php b/src/Test/Unit/Config/Validator/Deploy/EnvironmentVariablesTest.php
new file mode 100644
index 0000000000..250969db2c
--- /dev/null
+++ b/src/Test/Unit/Config/Validator/Deploy/EnvironmentVariablesTest.php
@@ -0,0 +1,129 @@
+magentoVersionMock = $this->createMock(MagentoVersion::class);
+ $this->environmentMock = $this->createMock(Environment::class);
+ $this->resultFactoryMock = $this->createMock(ResultFactory::class);
+
+ $this->validator = new EnvironmentVariables(
+ $this->environmentMock,
+ $this->magentoVersionMock,
+ $this->resultFactoryMock
+ );
+ }
+
+ public function testSuccessVersion(): void
+ {
+ $this->magentoVersionMock->expects($this->once())
+ ->method('satisfies')
+ ->with('>= 2.4.0')
+ ->willReturn(false);
+ $this->resultFactoryMock->expects($this->never())
+ ->method('errorByCode');
+
+ $this->assertInstanceOf(
+ Success::class,
+ $this->validator->validate()
+ );
+ }
+
+ public function testSuccessNoVariable(): void
+ {
+ $this->magentoVersionMock->expects($this->once())
+ ->method('satisfies')
+ ->with('>= 2.4.0')
+ ->willReturn(true);
+ $this->environmentMock->expects($this->once())
+ ->method('getEnv')
+ ->with('CONFIG__STORES__DEFAULT__PAYMENT__BRAINTREE__CHANNEL')
+ ->willReturn(false);
+ $this->resultFactoryMock->expects($this->never())
+ ->method('errorByCode');
+
+ $this->assertInstanceOf(
+ Success::class,
+ $this->validator->validate()
+ );
+ }
+
+ public function testError(): void
+ {
+ $this->magentoVersionMock->expects($this->once())
+ ->method('satisfies')
+ ->with('>= 2.4.0')
+ ->willReturn(true);
+ $this->environmentMock->expects($this->once())
+ ->method('getEnv')
+ ->with('CONFIG__STORES__DEFAULT__PAYMENT__BRAINTREE__CHANNEL')
+ ->willReturn('Magento_Enterprise_Cloud_BT');
+ $this->resultFactoryMock->expects($this->once())
+ ->method('errorByCode')
+ ->with(AppError::DEPLOY_WRONG_BRAINTREE_VARIABLE);
+
+ $this->assertInstanceOf(
+ Error::class,
+ $this->validator->validate()
+ );
+ }
+
+ public function testWithException(): void
+ {
+ $this->expectException(ValidatorException::class);
+ $this->expectExceptionMessage('some error');
+
+ $this->magentoVersionMock->expects($this->once())
+ ->method('satisfies')
+ ->with('>= 2.4.0')
+ ->willThrowException(new UndefinedPackageException('some error'));
+
+ $this->validator->validate();
+ }
+}
diff --git a/src/Test/Unit/Config/Validator/Deploy/ReportDirNestingLevelTest.php b/src/Test/Unit/Config/Validator/Deploy/ReportDirNestingLevelTest.php
index 9e6510cdcc..06d1905729 100644
--- a/src/Test/Unit/Config/Validator/Deploy/ReportDirNestingLevelTest.php
+++ b/src/Test/Unit/Config/Validator/Deploy/ReportDirNestingLevelTest.php
@@ -140,7 +140,7 @@ public function testValidateWithoutEnvVarWithoutConfigValue()
->method('error')
->with(
'The directory nesting level value for error reporting has not been configured.',
- 'You can configure the setting using the `config.report.dir_nesting_level`'
+ 'You can configure the setting using the `config.report.dir_nesting_level` variable'
. ' in the file ' . $this->reportConfigFile
);
@@ -166,7 +166,7 @@ public function testValidateWithoutEnvVarWithInvalidConfigFile()
$this->resultFactoryMock->expects($this->once())
->method('error')
->with(
- sprintf('Config of the file %s is invalid. Invalid xml', $this->reportConfigFile),
+ sprintf('Invalid configuration in the %s file. Invalid xml', $this->reportConfigFile),
'Fix the directory nesting level configuration for error reporting in the file '
. $this->reportConfigFile
);
diff --git a/src/Test/Unit/Config/Validator/Deploy/SolrIntegrityTest.php b/src/Test/Unit/Config/Validator/Deploy/SolrIntegrityTest.php
index e8f556a3a9..965a6c6c7f 100644
--- a/src/Test/Unit/Config/Validator/Deploy/SolrIntegrityTest.php
+++ b/src/Test/Unit/Config/Validator/Deploy/SolrIntegrityTest.php
@@ -111,7 +111,8 @@ public function testConfigSolr21()
[
'error' => 'Configuration for Solr was found in .magento.app.yaml.',
'suggestion' => 'Solr support has been deprecated in Magento 2.1. ' .
- 'Update your search engine to Elasticsearch and remove this relationship.',
+ 'Remove this relationship and use Elasticsearch.',
+ 'errorCode' => \Magento\MagentoCloud\App\Error::WARN_SOLR_DEPRECATED
]
)->willReturn($this->createMock(Error::class));
@@ -149,6 +150,7 @@ public function testConfigSolr22()
'error' => 'Configuration for Solr was found in .magento.app.yaml.',
'suggestion' => 'Solr is no longer supported by Magento 2.2 or later. ' .
'Remove this relationship and use Elasticsearch.',
+ 'errorCode' => \Magento\MagentoCloud\App\Error::WARN_SOLR_NOT_SUPPORTED
]
)->willReturn($this->createMock(Error::class));
diff --git a/src/Test/Unit/Config/Validator/ResultFactoryTest.php b/src/Test/Unit/Config/Validator/ResultFactoryTest.php
index ad24eeea3a..65a5745a4a 100644
--- a/src/Test/Unit/Config/Validator/ResultFactoryTest.php
+++ b/src/Test/Unit/Config/Validator/ResultFactoryTest.php
@@ -7,9 +7,12 @@
namespace Magento\MagentoCloud\Test\Unit\Config\Validator;
+use Magento\MagentoCloud\App\Error;
+use Magento\MagentoCloud\App\ErrorInfo;
use Magento\MagentoCloud\Config\Validator\Result;
use Magento\MagentoCloud\Config\Validator\ResultFactory;
use Magento\MagentoCloud\Config\Validator\ResultInterface;
+use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
/**
@@ -17,20 +20,33 @@
*/
class ResultFactoryTest extends TestCase
{
- public function testCreateSuccessResult(): void
+ /**
+ * @var ResultFactory
+ */
+ private $resultFactory;
+
+ /**
+ * @var ErrorInfo|MockObject
+ */
+ private $errorInfoMock;
+
+ protected function setUp(): void
{
- $resultFactory = new ResultFactory();
+ $this->errorInfoMock = $this->createMock(ErrorInfo::class);
+
+ $this->resultFactory = new ResultFactory($this->errorInfoMock);
+ }
- $result = $resultFactory->create(ResultInterface::SUCCESS);
+ public function testCreateSuccessResult(): void
+ {
+ $result = $this->resultFactory->create(ResultInterface::SUCCESS);
$this->assertInstanceOf(Result\Success::class, $result);
}
public function testCreateErrorResult(): void
{
- $resultFactory = new ResultFactory();
-
- $result = $resultFactory->create(ResultInterface::ERROR, [
+ $result = $this->resultFactory->create(ResultInterface::ERROR, [
'error' => 'some error',
'suggestion' => 'some suggestion',
'errorCode' => 10
@@ -41,4 +57,22 @@ public function testCreateErrorResult(): void
$this->assertEquals($result->getSuggestion(), 'some suggestion');
$this->assertEquals($result->getErrorCode(), 10);
}
+
+ public function testCreateErrorByCode(): void
+ {
+ $this->errorInfoMock->expects($this->once())
+ ->method('get')
+ ->with(Error::DEPLOY_WRONG_BRAINTREE_VARIABLE)
+ ->willReturn([
+ 'title' => 'some title',
+ 'suggestion' => 'some suggestion'
+ ]);
+
+ $result = $this->resultFactory->errorByCode(Error::DEPLOY_WRONG_BRAINTREE_VARIABLE);
+
+ $this->assertInstanceOf(Result\Error::class, $result);
+ $this->assertEquals($result->getError(), 'some title');
+ $this->assertEquals($result->getSuggestion(), 'some suggestion');
+ $this->assertEquals($result->getErrorCode(), Error::DEPLOY_WRONG_BRAINTREE_VARIABLE);
+ }
}
diff --git a/src/Test/Unit/DB/Data/ConnectionFactoryTest.php b/src/Test/Unit/DB/Data/ConnectionFactoryTest.php
index 063b505582..8666d009c3 100644
--- a/src/Test/Unit/DB/Data/ConnectionFactoryTest.php
+++ b/src/Test/Unit/DB/Data/ConnectionFactoryTest.php
@@ -67,7 +67,7 @@ public function testCreateSlaveAsMain()
public function testCreateWithException()
{
$this->expectException(\RuntimeException::class);
- $this->expectExceptionMessage('Connection with type dummy doesn\'t exist');
+ $this->expectExceptionMessage('Connection with type dummy does not exist');
$this->factory->create('dummy');
}
}
diff --git a/src/Test/Unit/DB/Data/RelationshipConnectionFactoryTest.php b/src/Test/Unit/DB/Data/RelationshipConnectionFactoryTest.php
index 71cd8d9a70..cbf96ac53d 100644
--- a/src/Test/Unit/DB/Data/RelationshipConnectionFactoryTest.php
+++ b/src/Test/Unit/DB/Data/RelationshipConnectionFactoryTest.php
@@ -93,7 +93,7 @@ public function dataProvider(): array
public function testCreateWithException()
{
$this->expectException(\RuntimeException::class);
- $this->expectExceptionMessage('Connection with type dummy doesn\'t exist');
+ $this->expectExceptionMessage('Connection with type dummy does not exist');
$this->factory->create('dummy');
}
diff --git a/src/Test/Unit/Filesystem/DirectoryCopier/CopyStrategyTest.php b/src/Test/Unit/Filesystem/DirectoryCopier/CopyStrategyTest.php
index 2ec6c4723d..58e11c0982 100644
--- a/src/Test/Unit/Filesystem/DirectoryCopier/CopyStrategyTest.php
+++ b/src/Test/Unit/Filesystem/DirectoryCopier/CopyStrategyTest.php
@@ -100,7 +100,7 @@ public function testCopyToDirectoryIsLink(): void
public function testCopyFromDirNotExists(): void
{
$this->expectException(FileSystemException::class);
- $this->expectExceptionMessage('Can\'t copy directory fromDir. Directory does not exist.');
+ $this->expectExceptionMessage('Cannot copy directory fromDir. Directory does not exist.');
$this->fileMock->expects($this->once())
->method('isExists')
diff --git a/src/Test/Unit/Filesystem/DirectoryCopier/CopySubFolderStrategyTest.php b/src/Test/Unit/Filesystem/DirectoryCopier/CopySubFolderStrategyTest.php
index 7049fe0472..00469648ec 100644
--- a/src/Test/Unit/Filesystem/DirectoryCopier/CopySubFolderStrategyTest.php
+++ b/src/Test/Unit/Filesystem/DirectoryCopier/CopySubFolderStrategyTest.php
@@ -103,7 +103,7 @@ public function testCopyToDirectoryIsLink()
public function testCopyFromDirNotExists()
{
$this->expectException(FileSystemException::class);
- $this->expectExceptionMessage('Can\'t copy directory fromDir. Directory does not exist.');
+ $this->expectExceptionMessage('Cannot copy directory fromDir. Directory does not exist.');
$this->fileMock->expects($this->once())
->method('isExists')
diff --git a/src/Test/Unit/Filesystem/DirectoryCopier/StrategyFactoryTest.php b/src/Test/Unit/Filesystem/DirectoryCopier/StrategyFactoryTest.php
index 585a54417d..20788a131d 100644
--- a/src/Test/Unit/Filesystem/DirectoryCopier/StrategyFactoryTest.php
+++ b/src/Test/Unit/Filesystem/DirectoryCopier/StrategyFactoryTest.php
@@ -88,7 +88,7 @@ public function createDataProvider(): array
public function testCopyFromDirNotExists(): void
{
$this->expectException(\RuntimeException::class);
- $this->expectExceptionMessage('Strategy "not_exists_strategy" doesn\'t exist');
+ $this->expectExceptionMessage('Strategy "not_exists_strategy" does not exist');
$this->strategyFactory->create('not_exists_strategy');
}
diff --git a/src/Test/Unit/Filesystem/DirectoryCopier/SubSymlinkStrategyTest.php b/src/Test/Unit/Filesystem/DirectoryCopier/SubSymlinkStrategyTest.php
index ccc29a7561..30e9b29b3b 100644
--- a/src/Test/Unit/Filesystem/DirectoryCopier/SubSymlinkStrategyTest.php
+++ b/src/Test/Unit/Filesystem/DirectoryCopier/SubSymlinkStrategyTest.php
@@ -90,7 +90,7 @@ public function testCopy(): void
public function testCopyFromDirNotExists(): void
{
$this->expectException(FileSystemException::class);
- $this->expectExceptionMessage('Can\'t copy directory "realFromDir". Directory does not exist.');
+ $this->expectExceptionMessage('Cannot copy directory "realFromDir". Directory does not exist.');
$this->fileMock->expects($this->once())
->method('isExists')
->with('realFromDir')
diff --git a/src/Test/Unit/Filesystem/DirectoryCopier/SymlinkStrategyTest.php b/src/Test/Unit/Filesystem/DirectoryCopier/SymlinkStrategyTest.php
index 0a32cbe9eb..f0c48209ed 100644
--- a/src/Test/Unit/Filesystem/DirectoryCopier/SymlinkStrategyTest.php
+++ b/src/Test/Unit/Filesystem/DirectoryCopier/SymlinkStrategyTest.php
@@ -170,7 +170,7 @@ public function testIsEmptyDirectory(): void
public function testCopyFromDirNotExists(): void
{
$this->expectException(FileSystemException::class);
- $this->expectExceptionMessage('Can\'t copy directory realFromDir. Directory does not exist.');
+ $this->expectExceptionMessage('Cannot copy directory realFromDir. Directory does not exist.');
$this->fileMock->expects($this->once())
->method('isExists')
diff --git a/src/Test/Unit/Patch/ManagerTest.php b/src/Test/Unit/Patch/ManagerTest.php
index 98a65e8dba..226806b656 100644
--- a/src/Test/Unit/Patch/ManagerTest.php
+++ b/src/Test/Unit/Patch/ManagerTest.php
@@ -58,7 +58,7 @@ protected function setUp()
}
/**
- * @throws ShellException
+ * Tests patch applying.
*/
public function testApply(): void
{
@@ -70,7 +70,7 @@ public function testApply(): void
$processMock = $this->getMockForAbstractClass(ProcessInterface::class);
$this->shellMock->expects($this->once())
->method('execute')
- ->with('php ./vendor/bin/ece-patches apply')
+ ->with('php ./vendor/bin/ece-patches apply --no-interaction')
->willReturn($processMock);
$this->loggerMock->method('notice')
->withConsecutive(
@@ -82,53 +82,62 @@ public function testApply(): void
}
/**
- * @throws ShellException
+ * Tests with git-based Magento.
*/
- public function testApplyWithException(): void
+ public function testApplyGit(): void
{
- $this->expectException(ShellException::class);
- $this->expectExceptionMessage('Some error');
-
$this->globalSectionMock->expects($this->once())
->method('get')
->with(GlobalSection::VAR_DEPLOYED_MAGENTO_VERSION_FROM_GIT)
- ->willReturn(false);
+ ->willReturn(true);
- $this->shellMock->expects($this->once())
- ->method('execute')
- ->with('php ./vendor/bin/ece-patches apply')
- ->willThrowException(new ShellException('Some error'));
- $this->loggerMock->method('notice')
- ->withConsecutive(
- ['Applying patches']
- );
+ $this->shellMock->expects($this->never())
+ ->method('execute');
$this->loggerMock->expects($this->once())
- ->method('error')
- ->with('Some error');
+ ->method('info')
+ ->with('Git-based installation. Skipping patches applying');
$this->manager->apply();
}
+ /**
+ * @return array[]
+ */
+ public function applyDataProvider(): array
+ {
+ return [
+ [
+ 'deploymentFromGit' => false,
+ 'qualityPatches' => [],
+ 'expectedCommand' => 'php ./vendor/bin/ece-patches apply --no-interaction'
+ ]
+ ];
+ }
+
/**
* @throws ShellException
*/
- public function testApplyDeployedFromGitAndNoCopy(): void
+ public function testApplyWithException(): void
{
+ $this->expectException(ShellException::class);
+ $this->expectExceptionMessage('Some error');
+
$this->globalSectionMock->expects($this->once())
->method('get')
->with(GlobalSection::VAR_DEPLOYED_MAGENTO_VERSION_FROM_GIT)
- ->willReturn(true);
+ ->willReturn(false);
- $processMock = $this->getMockForAbstractClass(ProcessInterface::class);
$this->shellMock->expects($this->once())
->method('execute')
- ->with('php ./vendor/bin/ece-patches apply --git-installation 1')
- ->willReturn($processMock);
+ ->with('php ./vendor/bin/ece-patches apply --no-interaction')
+ ->willThrowException(new ShellException('Some error'));
$this->loggerMock->method('notice')
->withConsecutive(
- ['Applying patches'],
- ['End of applying patches']
+ ['Applying patches']
);
+ $this->loggerMock->expects($this->once())
+ ->method('error')
+ ->with('Some error');
$this->manager->apply();
}
diff --git a/src/Test/Unit/Scenario/Collector/ScenarioTest.php b/src/Test/Unit/Scenario/Collector/ScenarioTest.php
index 2527c8f913..9771c1b462 100644
--- a/src/Test/Unit/Scenario/Collector/ScenarioTest.php
+++ b/src/Test/Unit/Scenario/Collector/ScenarioTest.php
@@ -85,7 +85,7 @@ public function testCollect()
public function testCollectWithException()
{
$this->expectException(ValidationException::class);
- $this->expectExceptionMessage('File doesn\'t exist');
+ $this->expectExceptionMessage('File does not exist');
$scenario = '/path/to/scenario';
@@ -95,7 +95,7 @@ public function testCollectWithException()
->willReturn($scenario);
$this->fileMock->expects($this->once())
->method('fileGetContents')
- ->willThrowException(new FileSystemException('File doesn\'t exist'));
+ ->willThrowException(new FileSystemException('File does not exist'));
$this->scenarioCollector->collect($scenario);
}
diff --git a/src/Test/Unit/Scenario/ProcessorTest.php b/src/Test/Unit/Scenario/ProcessorTest.php
index 561e0b41bf..8f8d1bd966 100644
--- a/src/Test/Unit/Scenario/ProcessorTest.php
+++ b/src/Test/Unit/Scenario/ProcessorTest.php
@@ -166,7 +166,7 @@ public function testExecuteWithStepException(): void
['On fail action "on-fail" finished']
);
$this->loggerMock->method('error')
- ->withConsecutive(['[201] Some error']);
+ ->withConsecutive(['Some error']);
$this->processor->execute($scenarios);
}
@@ -178,7 +178,7 @@ public function testExecuteWithStepException(): void
public function testExecuteWithStepAndActionException(): void
{
$this->expectException(ProcessorException::class);
- $this->expectExceptionMessage('[11] Step error');
+ $this->expectExceptionMessage('Step error');
$this->expectExceptionCode(11);
$scenarios = [
@@ -224,7 +224,7 @@ public function testExecuteWithStepAndActionException(): void
$this->loggerMock->method('error')
->withConsecutive(
['Action error'],
- ['[11] Step error']
+ ['Step error']
);
$this->processor->execute($scenarios);
@@ -237,33 +237,18 @@ public function testExecuteWithStepAndActionException(): void
public function testExecuteWithRuntimeException(): void
{
$this->expectException(ProcessorException::class);
- $this->expectExceptionMessage('Unhandled error: [10] Some error');
+ $this->expectExceptionMessage('Unhandled error: Some error');
$scenarios = [
'some/scenario.xml'
];
- $step1 = $this->getMockForAbstractClass(StepInterface::class);
-
- $step1->expects($this->once())
- ->method('execute')
- ->willThrowException(new \RuntimeException('Some error', 10));
-
- $steps = [
- 'step1' => $step1
- ];
-
- $action = $this->getMockForAbstractClass(ActionInterface::class);
- $action->expects($this->never())
- ->method('execute');
-
$this->packageManagerMock->expects($this->once())
->method('getPrettyInfo')
->willReturn('1.0.0');
$this->mergerMock->expects($this->once())
->method('merge')
- ->with($scenarios)
- ->willReturn(['steps' => $steps, 'actions' => ['on-fail' => $action]]);
+ ->willThrowException(new \RuntimeException('Some error', 10));
$this->loggerMock->method('info')
->withConsecutive(
[
@@ -273,12 +258,19 @@ public function testExecuteWithRuntimeException(): void
)
]
);
- $this->loggerMock->method('debug')
- ->withConsecutive(
- ['Running step: step1']
- );
+
+ $step1 = $this->getMockForAbstractClass(StepInterface::class);
+ $step1->expects($this->never())
+ ->method('execute');
+
+ $action = $this->getMockForAbstractClass(ActionInterface::class);
+ $action->expects($this->never())
+ ->method('execute');
+
+ $this->loggerMock->expects($this->never())
+ ->method('debug');
$this->loggerMock->method('error')
- ->withConsecutive(['Unhandled error: [10] Some error']);
+ ->withConsecutive(['Unhandled error: Some error']);
$this->processor->execute($scenarios);
}
diff --git a/src/Test/Unit/Service/ValidatorTest.php b/src/Test/Unit/Service/ValidatorTest.php
index 37b063712c..fa42ad192c 100644
--- a/src/Test/Unit/Service/ValidatorTest.php
+++ b/src/Test/Unit/Service/ValidatorTest.php
@@ -175,7 +175,7 @@ public function validateVersionsDataProvider(): array
ServiceInterface::NAME_NGINX => '1.9',
ServiceInterface::NAME_VARNISH => '6.2',
ServiceInterface::NAME_REDIS => '5.0',
- ServiceInterface::NAME_ELASTICSEARCH => '7.4', // wrong
+ ServiceInterface::NAME_ELASTICSEARCH => '7.5',
ServiceInterface::NAME_RABBITMQ => '3.8'
],
0
diff --git a/src/Test/Unit/Step/Build/ApplyPatchesTest.php b/src/Test/Unit/Step/Build/ApplyPatchesTest.php
index 99ac1c0116..57bed9d3b8 100644
--- a/src/Test/Unit/Step/Build/ApplyPatchesTest.php
+++ b/src/Test/Unit/Step/Build/ApplyPatchesTest.php
@@ -9,6 +9,7 @@
use Magento\MagentoCloud\App\Error;
use Magento\MagentoCloud\Config\ConfigException;
+use Magento\MagentoCloud\Config\Stage\BuildInterface;
use Magento\MagentoCloud\Patch\Manager;
use Magento\MagentoCloud\Shell\ShellException;
use Magento\MagentoCloud\Step\Build\ApplyPatches;
diff --git a/src/Test/Unit/Step/Build/DeployStaticContent/GenerateTest.php b/src/Test/Unit/Step/Build/DeployStaticContent/GenerateTest.php
index bc803b419f..b1a5fbceb3 100644
--- a/src/Test/Unit/Step/Build/DeployStaticContent/GenerateTest.php
+++ b/src/Test/Unit/Step/Build/DeployStaticContent/GenerateTest.php
@@ -8,6 +8,7 @@
namespace Magento\MagentoCloud\Test\Unit\Step\Build\DeployStaticContent;
use Magento\MagentoCloud\App\Error;
+use Magento\MagentoCloud\App\GenericException;
use Magento\MagentoCloud\Config\Stage\BuildInterface;
use Magento\MagentoCloud\Step\Build\DeployStaticContent\Generate;
use Magento\MagentoCloud\Step\StepException;
@@ -114,7 +115,7 @@ public function testExecute()
/**
* @throws StepException
*/
- public function testExecuteWithException()
+ public function testExecuteWithShellException()
{
$this->expectException(StepException::class);
$this->expectExceptionMessage('Some error');
@@ -149,4 +150,24 @@ public function testExecuteWithException()
$this->step->execute();
}
+
+ /**
+ * @throws StepException
+ */
+ public function testExecuteWithGenericException()
+ {
+ $exceptionMessage = 'Some error';
+ $exceptionCode = 111;
+ $this->expectException(StepException::class);
+ $this->expectExceptionMessage($exceptionMessage);
+ $this->expectExceptionCode($exceptionCode);
+
+ $this->optionMock->expects($this->once())
+ ->method('getLocales')
+ ->willReturn(['ua_UA', 'fr_FR', 'es_ES', 'en_US']);
+ $this->optionMock->expects($this->once())
+ ->method('getThreadCount')
+ ->willThrowException(new GenericException($exceptionMessage, $exceptionCode));
+ $this->step->execute();
+ }
}
diff --git a/src/Test/Unit/Step/Build/DeployStaticContentTest.php b/src/Test/Unit/Step/Build/DeployStaticContentTest.php
index 3a3b342d6d..cee511a5e9 100644
--- a/src/Test/Unit/Step/Build/DeployStaticContentTest.php
+++ b/src/Test/Unit/Step/Build/DeployStaticContentTest.php
@@ -106,4 +106,47 @@ public function testExecuteWithError()
$this->step->execute();
}
+
+ public function testExecuteWithException()
+ {
+ $exceptionMsg = 'Error';
+ $exceptionCode = 102;
+
+ $this->expectException(StepException::class);
+ $this->expectExceptionMessage($exceptionMsg);
+ $this->expectExceptionCode($exceptionCode);
+
+ $this->flagManagerMock->expects($this->once())
+ ->method('delete')
+ ->with(FlagManager::FLAG_STATIC_CONTENT_DEPLOY_IN_BUILD);
+ $this->scdOnBuildMock->expects($this->once())
+ ->method('validate')
+ ->willThrowException(new \Exception($exceptionMsg, $exceptionCode));
+
+ $this->step->execute();
+ }
+
+ /**
+ * @throws StepException
+ */
+ public function testExecuteWithStepException()
+ {
+ $e = new StepException('Error Message', 111);
+ $this->expectExceptionObject($e);
+
+ $this->flagManagerMock->expects($this->once())
+ ->method('delete')
+ ->with(FlagManager::FLAG_STATIC_CONTENT_DEPLOY_IN_BUILD);
+ $this->scdOnBuildMock->expects($this->once())
+ ->method('validate')
+ ->willReturn(new Result\Success());
+ $this->loggerMock->expects($this->once())
+ ->method('notice')
+ ->with('Generating fresh static content');
+ $this->stepMock->expects($this->once())
+ ->method('execute')
+ ->willThrowException($e);
+
+ $this->step->execute();
+ }
}
diff --git a/src/Test/Unit/Step/Build/PreBuildTest.php b/src/Test/Unit/Step/Build/PreBuildTest.php
index 9fa5c552c4..6d3cafb0d0 100644
--- a/src/Test/Unit/Step/Build/PreBuildTest.php
+++ b/src/Test/Unit/Step/Build/PreBuildTest.php
@@ -7,11 +7,13 @@
namespace Magento\MagentoCloud\Test\Unit\Step\Build;
+use Magento\MagentoCloud\App\GenericException;
use Magento\MagentoCloud\Config\Stage\BuildInterface;
use Magento\MagentoCloud\Filesystem\DirectoryList;
use Magento\MagentoCloud\Filesystem\Driver\File;
use Magento\MagentoCloud\Filesystem\Flag\Manager as FlagManager;
use Magento\MagentoCloud\Step\Build\PreBuild;
+use Magento\MagentoCloud\Step\StepException;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;
@@ -153,4 +155,20 @@ public function executeClearDirectoriesDataProvider(): array
['isExist' => false, 'clearDirectories' => 0],
];
}
+
+ public function testExecuteWithException()
+ {
+ $exceptionCode = 111;
+ $exceptionMsg = 'Error message';
+
+ $this->expectException(StepException::class);
+ $this->expectExceptionMessage($exceptionMsg);
+ $this->expectExceptionCode($exceptionCode);
+
+ $this->flagManagerMock->expects($this->once())
+ ->method('delete')
+ ->willThrowException(new GenericException($exceptionMsg, $exceptionCode));
+
+ $this->step->execute();
+ }
}
diff --git a/src/Test/Unit/Step/Deploy/InstallUpdate/ConfigUpdate/AmqpTest.php b/src/Test/Unit/Step/Deploy/InstallUpdate/ConfigUpdate/AmqpTest.php
index da13667140..1c29ff6f2e 100644
--- a/src/Test/Unit/Step/Deploy/InstallUpdate/ConfigUpdate/AmqpTest.php
+++ b/src/Test/Unit/Step/Deploy/InstallUpdate/ConfigUpdate/AmqpTest.php
@@ -7,6 +7,9 @@
namespace Magento\MagentoCloud\Test\Unit\Step\Deploy\InstallUpdate\ConfigUpdate;
+use Magento\MagentoCloud\App\Error;
+use Magento\MagentoCloud\App\GenericException;
+use Magento\MagentoCloud\Filesystem\FileSystemException;
use Magento\MagentoCloud\Step\StepException;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
@@ -153,4 +156,45 @@ public function testExecuteRemoveAmqp(): void
$this->step->execute();
}
+
+ /**
+ * @throws StepException
+ */
+ public function testExecuteWithExceptionInRead()
+ {
+ $exceptionMsg = 'Error';
+ $exceptionCode = 111;
+
+ $this->expectException(StepException::class);
+ $this->expectExceptionMessage($exceptionMsg);
+ $this->expectExceptionCode($exceptionCode);
+
+ $this->configReaderMock->expects($this->once())
+ ->method('read')
+ ->willThrowException(new GenericException($exceptionMsg, $exceptionCode));
+
+ $this->step->execute();
+ }
+
+ /**
+ * @throws StepException
+ */
+ public function testExecuteWithExceptionInWrite()
+ {
+ $exceptionMsg = 'Some error';
+ $exceptionCode = 11111;
+ $this->expectException(StepException::class);
+ $this->expectExceptionCode(Error::DEPLOY_ENV_PHP_IS_NOT_WRITABLE);
+ $this->expectExceptionMessage($exceptionMsg);
+
+ $this->configReaderMock->expects($this->once())
+ ->method('read')
+ ->willReturn(['queue' => ['some data']]);
+
+ $this->configWriterMock->expects($this->once())
+ ->method('create')
+ ->willThrowException(new FileSystemException($exceptionMsg, $exceptionCode));
+
+ $this->step->execute();
+ }
}
diff --git a/src/Test/Unit/Step/Deploy/InstallUpdate/ConfigUpdate/CronConsumersRunnerTest.php b/src/Test/Unit/Step/Deploy/InstallUpdate/ConfigUpdate/CronConsumersRunnerTest.php
index c5a91547ea..5951b7951e 100644
--- a/src/Test/Unit/Step/Deploy/InstallUpdate/ConfigUpdate/CronConsumersRunnerTest.php
+++ b/src/Test/Unit/Step/Deploy/InstallUpdate/ConfigUpdate/CronConsumersRunnerTest.php
@@ -7,12 +7,15 @@
namespace Magento\MagentoCloud\Test\Unit\Step\Deploy\InstallUpdate\ConfigUpdate;
+use Magento\MagentoCloud\App\Error;
+use Magento\MagentoCloud\App\GenericException;
use Magento\MagentoCloud\Config\Magento\Env\ReaderInterface as ConfigReader;
use Magento\MagentoCloud\Config\Magento\Env\WriterInterface as ConfigWriter;
use Magento\MagentoCloud\Config\Environment;
use Illuminate\Config\Repository;
use Magento\MagentoCloud\Config\RepositoryFactory;
use Magento\MagentoCloud\Config\Stage\DeployInterface;
+use Magento\MagentoCloud\Filesystem\FileSystemException;
use Magento\MagentoCloud\Package\MagentoVersion;
use Magento\MagentoCloud\Step\Deploy\InstallUpdate\ConfigUpdate\CronConsumersRunner;
use Magento\MagentoCloud\Step\StepException;
@@ -22,6 +25,8 @@
/**
* @inheritdoc
+ *
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class CronConsumersRunnerTest extends TestCase
{
@@ -265,4 +270,60 @@ public function testSkipExecute(): void
$this->cronConsumersRunner->execute();
}
+
+ /**
+ * @throws StepException
+ */
+ public function testExecuteWithGenericException()
+ {
+ $exceptionMsg = 'Error';
+ $exceptionCode = 111;
+
+ $this->expectException(StepException::class);
+ $this->expectExceptionMessage($exceptionMsg);
+ $this->expectExceptionCode($exceptionCode);
+
+ $this->magentoVersionMock->expects($this->once())
+ ->method('isGreaterOrEqual')
+ ->willThrowException(new GenericException($exceptionMsg, $exceptionCode));
+
+ $this->cronConsumersRunner->execute();
+ }
+
+ /**
+ * @throws StepException
+ */
+ public function testExecuteWithFileSystemExceptionInCreate()
+ {
+ $exceptionMsg = 'Some error';
+ $exceptionCode = 11111;
+ $this->expectException(StepException::class);
+ $this->expectExceptionCode(Error::DEPLOY_ENV_PHP_IS_NOT_WRITABLE);
+ $this->expectExceptionMessage($exceptionMsg);
+
+ $this->magentoVersionMock->expects($this->once())
+ ->method('isGreaterOrEqual')
+ ->with('2.2')
+ ->willReturn(true);
+
+ $this->configReaderMock->expects($this->once())
+ ->method('read')
+ ->willReturn([]);
+
+ $this->repositoryFactoryMock->expects($this->once())
+ ->method('create')
+ ->with([])
+ ->willReturn(new Repository([]));
+
+ $this->stageConfigMock->expects($this->once())
+ ->method('get')
+ ->with(DeployInterface::VAR_CRON_CONSUMERS_RUNNER)
+ ->willReturn([]);
+
+ $this->configWriterMock->expects($this->once())
+ ->method('create')
+ ->willThrowException(new FileSystemException($exceptionMsg, $exceptionCode));
+
+ $this->cronConsumersRunner->execute();
+ }
}
diff --git a/src/Test/Unit/Step/Deploy/InstallUpdate/ConfigUpdate/DbConnectionTest.php b/src/Test/Unit/Step/Deploy/InstallUpdate/ConfigUpdate/DbConnectionTest.php
index 429080d7a4..33205abd68 100644
--- a/src/Test/Unit/Step/Deploy/InstallUpdate/ConfigUpdate/DbConnectionTest.php
+++ b/src/Test/Unit/Step/Deploy/InstallUpdate/ConfigUpdate/DbConnectionTest.php
@@ -166,7 +166,7 @@ public function testExecuteWithoutDbConfigInEnvironment()
->willReturn([]);
$this->loggerMock->expects($this->once())
->method('notice')
- ->with('Database relationship configuration doesn\'t exist'
+ ->with('Database relationship configuration does not exist'
. ' and database is not configured through .magento.env.yaml or env variable.'
. ' Will be applied the previous database configuration.');
$this->flagManagerMock->expects($this->never())
diff --git a/src/Test/Unit/Step/Deploy/InstallUpdate/ConfigUpdate/DocumentRootTest.php b/src/Test/Unit/Step/Deploy/InstallUpdate/ConfigUpdate/DocumentRootTest.php
index 64e910bfab..97f98572cd 100644
--- a/src/Test/Unit/Step/Deploy/InstallUpdate/ConfigUpdate/DocumentRootTest.php
+++ b/src/Test/Unit/Step/Deploy/InstallUpdate/ConfigUpdate/DocumentRootTest.php
@@ -7,6 +7,8 @@
namespace Magento\MagentoCloud\Test\Unit\Step\Deploy\InstallUpdate\ConfigUpdate;
+use Magento\MagentoCloud\App\Error;
+use Magento\MagentoCloud\Filesystem\FileSystemException;
use Magento\MagentoCloud\Step\Deploy\InstallUpdate\ConfigUpdate\DocumentRoot;
use Magento\MagentoCloud\Step\StepException;
use PHPUnit\Framework\MockObject\MockObject;
@@ -62,4 +64,26 @@ public function testExecute(): void
$this->step->execute();
}
+
+ /**
+ * @throws StepException
+ */
+ public function testExecuteWithException()
+ {
+ $exceptionMsg = 'Error';
+ $exceptionCode = 111;
+
+ $this->expectException(StepException::class);
+ $this->expectExceptionMessage($exceptionMsg);
+ $this->expectExceptionCode(Error::DEPLOY_ENV_PHP_IS_NOT_WRITABLE);
+
+ $this->loggerMock->expects($this->once())
+ ->method('info')
+ ->with('The value of the property \'directories/document_root_is_pub\' set as \'true\'');
+ $this->configWriterMock->expects($this->once())
+ ->method('update')
+ ->willThrowException(new FileSystemException($exceptionMsg, $exceptionCode));
+
+ $this->step->execute();
+ }
}
diff --git a/src/Test/Unit/Step/Deploy/InstallUpdate/ConfigUpdate/LockTest.php b/src/Test/Unit/Step/Deploy/InstallUpdate/ConfigUpdate/LockTest.php
index 1a16f3896f..21715a6165 100644
--- a/src/Test/Unit/Step/Deploy/InstallUpdate/ConfigUpdate/LockTest.php
+++ b/src/Test/Unit/Step/Deploy/InstallUpdate/ConfigUpdate/LockTest.php
@@ -7,6 +7,7 @@
namespace Magento\MagentoCloud\Test\Unit\Step\Deploy\InstallUpdate\ConfigUpdate;
+use Magento\MagentoCloud\App\GenericException;
use Magento\MagentoCloud\Step\Deploy\InstallUpdate\ConfigUpdate\Lock;
use Magento\MagentoCloud\Config\Magento\Env\ReaderInterface as ConfigReader;
use Magento\MagentoCloud\Config\Magento\Env\WriterInterface as ConfigWriter;
@@ -128,4 +129,23 @@ public function testExecuteMagentoLess225(): void
$this->lock->execute();
}
+
+ /**
+ * @throws StepException
+ */
+ public function testExecuteWithException()
+ {
+ $exceptionMsg = 'Error';
+ $exceptionCode = 111;
+
+ $this->expectException(StepException::class);
+ $this->expectExceptionMessage($exceptionMsg);
+ $this->expectExceptionCode($exceptionCode);
+
+ $this->magentoVersionMock->expects($this->once())
+ ->method('isGreaterOrEqual')
+ ->willThrowException(new GenericException($exceptionMsg, $exceptionCode));
+
+ $this->lock->execute();
+ }
}
diff --git a/src/Test/Unit/Step/Deploy/InstallUpdate/ConfigUpdate/SessionTest.php b/src/Test/Unit/Step/Deploy/InstallUpdate/ConfigUpdate/SessionTest.php
index 8be5da3c5f..67117b5a8d 100644
--- a/src/Test/Unit/Step/Deploy/InstallUpdate/ConfigUpdate/SessionTest.php
+++ b/src/Test/Unit/Step/Deploy/InstallUpdate/ConfigUpdate/SessionTest.php
@@ -7,6 +7,9 @@
namespace Magento\MagentoCloud\Test\Unit\Step\Deploy\InstallUpdate\ConfigUpdate;
+use Magento\MagentoCloud\App\Error;
+use Magento\MagentoCloud\App\GenericException;
+use Magento\MagentoCloud\Filesystem\FileSystemException;
use Magento\MagentoCloud\Step\Deploy\InstallUpdate\ConfigUpdate\Session;
use Magento\MagentoCloud\Step\StepException;
use PHPUnit\Framework\MockObject\MockObject;
@@ -116,4 +119,41 @@ public function testExecuteEmptyConfig(): void
$this->step->execute();
}
+
+ /**
+ * @throws StepException
+ */
+ public function testExecuteWithException()
+ {
+ $exceptionMsg = 'Error';
+ $exceptionCode = 111;
+
+ $this->expectException(StepException::class);
+ $this->expectExceptionMessage($exceptionMsg);
+ $this->expectExceptionCode($exceptionCode);
+
+ $this->configReaderMock->expects($this->once())
+ ->method('read')
+ ->willThrowException(new GenericException($exceptionMsg, $exceptionCode));
+
+ $this->step->execute();
+ }
+
+ /**
+ * @throws StepException
+ */
+ public function testExecuteWithExceptionInCreate()
+ {
+ $exceptionMsg = 'Some error';
+ $exceptionCode = 11111;
+ $this->expectException(StepException::class);
+ $this->expectExceptionCode(Error::DEPLOY_ENV_PHP_IS_NOT_WRITABLE);
+ $this->expectExceptionMessage($exceptionMsg);
+
+ $this->configWriterMock->expects($this->once())
+ ->method('create')
+ ->willThrowException(new FileSystemException($exceptionMsg, $exceptionCode));
+
+ $this->step->execute();
+ }
}
diff --git a/src/Test/Unit/Step/Deploy/InstallUpdate/ConfigUpdate/UrlsTest.php b/src/Test/Unit/Step/Deploy/InstallUpdate/ConfigUpdate/UrlsTest.php
index e6e8cad971..e1e547dafe 100644
--- a/src/Test/Unit/Step/Deploy/InstallUpdate/ConfigUpdate/UrlsTest.php
+++ b/src/Test/Unit/Step/Deploy/InstallUpdate/ConfigUpdate/UrlsTest.php
@@ -7,9 +7,11 @@
namespace Magento\MagentoCloud\Test\Unit\Step\Deploy\InstallUpdate\ConfigUpdate;
+use Magento\MagentoCloud\App\GenericException;
use Magento\MagentoCloud\Config\Environment;
use Magento\MagentoCloud\Config\Stage\DeployInterface;
use Magento\MagentoCloud\Step\Deploy\InstallUpdate\ConfigUpdate\Urls;
+use Magento\MagentoCloud\Step\StepException;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;
@@ -153,4 +155,27 @@ public function testExecuteSkippedUpdateUrlsIsFalse()
$this->step->execute();
}
+
+ /**
+ * @throws StepException
+ */
+ public function testExecuteWithException()
+ {
+ $exceptionMsg = 'Error';
+ $exceptionCode = 111;
+
+ $this->expectException(StepException::class);
+ $this->expectExceptionMessage($exceptionMsg);
+ $this->expectExceptionCode($exceptionCode);
+
+ $this->stageConfigMock->expects($this->once())
+ ->method('get')
+ ->with(DeployInterface::VAR_FORCE_UPDATE_URLS)
+ ->willReturn(true);
+ $this->databaseUrlMock->expects($this->once())
+ ->method('execute')
+ ->willThrowException(new GenericException($exceptionMsg, $exceptionCode));
+
+ $this->step->execute();
+ }
}
diff --git a/src/Test/Unit/Step/Deploy/PreDeploy/ConfigUpdate/CacheTest.php b/src/Test/Unit/Step/Deploy/PreDeploy/ConfigUpdate/CacheTest.php
index c569b78583..c260b41a0f 100644
--- a/src/Test/Unit/Step/Deploy/PreDeploy/ConfigUpdate/CacheTest.php
+++ b/src/Test/Unit/Step/Deploy/PreDeploy/ConfigUpdate/CacheTest.php
@@ -113,7 +113,7 @@ public function testExecute(array $config, bool $isGreaterOrEqual)
{
$this->magentoVersion->expects($this->any())
->method('isGreaterOrEqual')
- ->with('2.3.5')
+ ->with('2.3.0')
->willReturn($isGreaterOrEqual);
$this->configReaderMock->expects($this->once())
->method('read')
@@ -157,7 +157,7 @@ public function executeDataProvider(): array
'config' => [
'frontend' => [
'frontName' => [
- 'backend' => addslashes(CacheFactory::REDIS_BACKEND_REMOTE_SYNCHRONIZED_CACHE),
+ 'backend' => CacheFactory::REDIS_BACKEND_REMOTE_SYNCHRONIZED_CACHE,
'backend_options' => [
'remote_backend_options' => [
'server' => 'localhost',
@@ -243,11 +243,11 @@ public function testExecuteMixedBackends()
'backend_options' => ['server' => 'redis.server', 'port' => 6379],
],
'frontName2' => [
- 'backend' => addslashes(CacheFactory::REDIS_BACKEND_REDIS_CACHE),
+ 'backend' => CacheFactory::REDIS_BACKEND_REDIS_CACHE,
'backend_options' => ['server' => 'redis.server', 'port' => 6379],
],
'frontName3' => [
- 'backend' => addslashes(CacheFactory::REDIS_BACKEND_REMOTE_SYNCHRONIZED_CACHE),
+ 'backend' => CacheFactory::REDIS_BACKEND_REMOTE_SYNCHRONIZED_CACHE,
'backend_options' => [
'remote_backend_options' => ['server' => 'redis.server', 'port' => 6379],],
],
@@ -259,7 +259,7 @@ public function testExecuteMixedBackends()
$this->magentoVersion->expects($this->exactly(2))
->method('isGreaterOrEqual')
- ->with('2.3.5')
+ ->with('2.3.0')
->willReturn(true);
$this->socketCreateMock->expects($this->exactly(3))
->with(AF_INET, SOCK_STREAM, SOL_TCP)
@@ -275,7 +275,7 @@ public function testExecuteMixedBackends()
->with(['cache' => [
'frontend' => [
'frontName2' => [
- 'backend' => addslashes(CacheFactory::REDIS_BACKEND_REDIS_CACHE),
+ 'backend' => CacheFactory::REDIS_BACKEND_REDIS_CACHE,
'backend_options' => ['server' => 'redis.server', 'port' => 6379],
],
'frontName1' => [
@@ -283,7 +283,7 @@ public function testExecuteMixedBackends()
'backend_options' => ['server' => 'redis.server', 'port' => 6379],
],
'frontName3' => [
- 'backend' => addslashes(CacheFactory::REDIS_BACKEND_REMOTE_SYNCHRONIZED_CACHE),
+ 'backend' => CacheFactory::REDIS_BACKEND_REMOTE_SYNCHRONIZED_CACHE,
'backend_options' => [
'remote_backend_options' => ['server' => 'redis.server', 'port' => 6379],],
],
diff --git a/src/Test/Unit/Step/Deploy/PreDeploy/RestorePatchLogTest.php b/src/Test/Unit/Step/Deploy/PreDeploy/RestorePatchLogTest.php
new file mode 100644
index 0000000000..6989b4a51c
--- /dev/null
+++ b/src/Test/Unit/Step/Deploy/PreDeploy/RestorePatchLogTest.php
@@ -0,0 +1,153 @@
+loggerMock = $this->getMockBuilder(LoggerInterface::class)
+ ->getMockForAbstractClass();
+ $this->fileMock = $this->createMock(File::class);
+ $this->directoryListMock = $this->createMock(DirectoryList::class);
+ $this->fileListMock = $this->createMock(FileList::class);
+
+ $this->step = new RestorePatchLog(
+ $this->loggerMock,
+ $this->directoryListMock,
+ $this->fileMock,
+ $this->fileListMock
+ );
+ }
+
+ public function testExecute(): void
+ {
+ $this->fileListMock->expects($this->once())
+ ->method('getInitPatchLog')
+ ->willReturn(self::INIT_PATCH_LOG_PATH);
+ $this->fileListMock->expects($this->once())
+ ->method('getPatchLog')
+ ->willReturn(self::PATCH_LOG_PATH);
+ $this->fileMock->expects($this->once())
+ ->method('isExists')
+ ->with(self::INIT_PATCH_LOG_PATH)
+ ->willReturn(true);
+ $this->loggerMock->expects($this->once())
+ ->method('info')
+ ->with('Restoring patch log file');
+ $this->directoryListMock->expects($this->once())
+ ->method('getLog')
+ ->willReturn('/path/to/dir/log');
+ $this->fileMock->expects($this->once())
+ ->method('createDirectory')
+ ->with('/path/to/dir/log');
+ $this->fileMock->expects($this->once())
+ ->method('fileGetContents')
+ ->with(self::INIT_PATCH_LOG_PATH)
+ ->willReturn('content');
+ $this->fileMock->expects($this->once())
+ ->method('filePutContents')
+ ->with(self::PATCH_LOG_PATH, 'content');
+
+ $this->step->execute();
+ }
+
+ public function testExecutePatchLogFileNotExist(): void
+ {
+ $this->fileListMock->expects($this->once())
+ ->method('getInitPatchLog')
+ ->willReturn(self::INIT_PATCH_LOG_PATH);
+ $this->fileMock->expects($this->once())
+ ->method('isExists')
+ ->with(self::INIT_PATCH_LOG_PATH)
+ ->willReturn(false);
+ $this->fileMock->expects($this->never())
+ ->method('fileGetContents');
+ $this->fileMock->expects($this->never())
+ ->method('createDirectory');
+ $this->fileMock->expects($this->never())
+ ->method('filePutContents');
+
+ $this->step->execute();
+ }
+
+ public function testExecuteWithUndefinedPackageException(): void
+ {
+ $this->fileListMock->expects($this->once())
+ ->method('getInitPatchLog')
+ ->willThrowException(new UndefinedPackageException(''));
+ $this->fileMock->expects($this->never())
+ ->method('isExists');
+
+ $this->expectException(StepException::class);
+ $this->step->execute();
+ }
+
+ public function testExecuteWithFilesystemException(): void
+ {
+ $this->fileListMock->expects($this->once())
+ ->method('getInitPatchLog')
+ ->willReturn(self::INIT_PATCH_LOG_PATH);
+ $this->fileMock->expects($this->once())
+ ->method('isExists')
+ ->with(self::INIT_PATCH_LOG_PATH)
+ ->willReturn(true);
+ $this->fileMock->expects($this->once())
+ ->method('fileGetContents')
+ ->willThrowException(new FileSystemException(''));
+
+ $this->expectException(StepException::class);
+ $this->step->execute();
+ }
+}
diff --git a/src/Test/Unit/Step/Deploy/PreDeploy/RestoreWritableDirectoriesTest.php b/src/Test/Unit/Step/Deploy/PreDeploy/RestoreWritableDirectoriesTest.php
index 4fae3d83c6..b5a53984b9 100644
--- a/src/Test/Unit/Step/Deploy/PreDeploy/RestoreWritableDirectoriesTest.php
+++ b/src/Test/Unit/Step/Deploy/PreDeploy/RestoreWritableDirectoriesTest.php
@@ -7,9 +7,11 @@
namespace Magento\MagentoCloud\Test\Unit\Step\Deploy\PreDeploy;
+use Magento\MagentoCloud\App\GenericException;
use Magento\MagentoCloud\Filesystem\Flag\Manager as FlagManager;
use Magento\MagentoCloud\Filesystem\RecoverableDirectoryList;
use Magento\MagentoCloud\Step\Deploy\PreDeploy\RestoreWritableDirectories;
+use Magento\MagentoCloud\Step\StepException;
use Magento\MagentoCloud\Util\BuildDirCopier;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
@@ -89,4 +91,26 @@ public function testExecute(): void
$this->step->execute();
}
+
+ /**
+ * @throws StepException
+ */
+ public function testExecuteWithException()
+ {
+ $exceptionMsg = 'Error';
+ $exceptionCode = 111;
+
+ $this->expectException(StepException::class);
+ $this->expectExceptionMessage($exceptionMsg);
+ $this->expectExceptionCode($exceptionCode);
+
+ $this->recoverableDirectoryListMock->expects($this->once())
+ ->method('getList')
+ ->willReturn([]);
+ $this->flagManagerMock->expects($this->once())
+ ->method('delete')
+ ->willThrowException(new GenericException($exceptionMsg, $exceptionCode));
+
+ $this->step->execute();
+ }
}
diff --git a/src/Test/Unit/Step/Deploy/RemoveDeployFailedFlagTest.php b/src/Test/Unit/Step/Deploy/RemoveDeployFailedFlagTest.php
index 1d22e37d1d..398708204e 100644
--- a/src/Test/Unit/Step/Deploy/RemoveDeployFailedFlagTest.php
+++ b/src/Test/Unit/Step/Deploy/RemoveDeployFailedFlagTest.php
@@ -72,6 +72,9 @@ public function testExecute(): void
$this->fileListMock->expects($this->once())
->method('getCloudErrorLog')
->willReturn($filePath);
+ $this->fileMock->expects($this->once())
+ ->method('isExists')
+ ->willReturn(false);
$this->fileMock->expects($this->once())
->method('deleteFile')
->with($filePath);
@@ -79,6 +82,36 @@ public function testExecute(): void
$this->step->execute();
}
+ /**
+ * @throws StepException
+ */
+ public function testExecuteCopyBuildErrorLogFile(): void
+ {
+ $deployErrorLogFilePath = 'var/log/cloud.error.log';
+ $buildErrorLogFilePath = 'init/var/log/cloud.error.log';
+ $this->fileListMock->expects($this->once())
+ ->method('getCloudErrorLog')
+ ->willReturn($deployErrorLogFilePath);
+ $this->fileListMock->expects($this->once())
+ ->method('getInitCloudErrorLog')
+ ->willReturn($buildErrorLogFilePath);
+ $this->fileMock->expects($this->once())
+ ->method('isExists')
+ ->with($buildErrorLogFilePath)
+ ->willReturn(true);
+ $this->fileMock->expects($this->once())
+ ->method('deleteFile')
+ ->with($deployErrorLogFilePath);
+ $this->fileMock->expects($this->once())
+ ->method('copy')
+ ->with($buildErrorLogFilePath, $deployErrorLogFilePath);
+
+ $this->step->execute();
+ }
+
+ /**
+ * @throws StepException
+ */
public function testExceptionType()
{
$this->expectException(StepException::class);
diff --git a/src/Test/Unit/Step/Deploy/SetCryptKeyTest.php b/src/Test/Unit/Step/Deploy/SetCryptKeyTest.php
index dbaf89d8de..38ea510564 100644
--- a/src/Test/Unit/Step/Deploy/SetCryptKeyTest.php
+++ b/src/Test/Unit/Step/Deploy/SetCryptKeyTest.php
@@ -7,6 +7,7 @@
namespace Magento\MagentoCloud\Test\Unit\Step\Deploy;
+use Magento\MagentoCloud\App\Error;
use Magento\MagentoCloud\Config\Magento\Env\ReaderInterface as ConfigReader;
use Magento\MagentoCloud\Config\Magento\Env\WriterInterface as ConfigWriter;
use Magento\MagentoCloud\Config\Environment;
@@ -95,8 +96,12 @@ public function testConfigUpdate(): void
*/
public function testConfigUpdateWithError(): void
{
+ $errorMsg = 'Some error';
+ $errorCode = 11111;
+ $exception = new FileSystemException($errorMsg, $errorCode);
$this->expectException(StepException::class);
- $this->expectExceptionMessage('Some error');
+ $this->expectExceptionCode(Error::DEPLOY_ENV_PHP_IS_NOT_WRITABLE);
+ $this->expectExceptionMessage($errorMsg);
$this->configReaderMock->expects($this->once())
->method('read')
@@ -113,7 +118,7 @@ public function testConfigUpdateWithError(): void
$this->configWriterMock->expects($this->once())
->method('update')
->with(['crypt' => ['key' => 'TWFnZW50byBSb3g=']])
- ->willThrowException(new FileSystemException('Some error'));
+ ->willThrowException($exception);
$this->step->execute();
}
diff --git a/src/Test/Unit/Step/Deploy/SplitDbConnection/SlaveConnectionTest.php b/src/Test/Unit/Step/Deploy/SplitDbConnection/SlaveConnectionTest.php
index c1153fd29c..0ab96d3797 100644
--- a/src/Test/Unit/Step/Deploy/SplitDbConnection/SlaveConnectionTest.php
+++ b/src/Test/Unit/Step/Deploy/SplitDbConnection/SlaveConnectionTest.php
@@ -194,11 +194,13 @@ public function testUpdateSlaveConnectionsNotAvailable()
->withConsecutive(
[
'Slave connection for \'checkout\' connection not set.'
- . ' Relationships do not have the configuration for this slave connection'
+ . ' The `relationships` configuration in the .magento.app.yaml file'
+ . ' is missing the configuration for this slave connection'
],
[
'Slave connection for \'sales\' connection not set.'
- . ' Relationships do not have the configuration for this slave connection'
+ . ' The `relationships` configuration in the .magento.app.yaml file'
+ . ' is missing the configuration for this slave connection'
]
);
$this->configWriterMock->create($mageConfig);
diff --git a/src/Test/Unit/Step/Deploy/SplitDbConnectionTest.php b/src/Test/Unit/Step/Deploy/SplitDbConnectionTest.php
index 5ef222e379..0dd36862fd 100644
--- a/src/Test/Unit/Step/Deploy/SplitDbConnectionTest.php
+++ b/src/Test/Unit/Step/Deploy/SplitDbConnectionTest.php
@@ -7,8 +7,11 @@
namespace Magento\MagentoCloud\Test\Unit\Step\Deploy;
+use Magento\MagentoCloud\App\Error;
+use Magento\MagentoCloud\Filesystem\FileSystemException;
use Magento\MagentoCloud\Step\Deploy\SplitDbConnection;
use Magento\MagentoCloud\Step\Deploy\SplitDbConnection\SlaveConnection;
+use Magento\MagentoCloud\Step\StepException;
use Magento\MagentoCloud\Util\UpgradeProcess;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
@@ -21,6 +24,8 @@
/**
* @inheritdoc
+ *
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class SplitDbConnectionTest extends TestCase
{
@@ -181,7 +186,7 @@ public function testExecuteRelationshipNotHaveConfigurations(array $dbConfig, ar
->method('get')
->willReturn($dbConfig);
$this->loggerMock->expects($this->once())
- ->method('error')
+ ->method('warning')
->with(
'Enabling a split database will be skipped.'
. ' Relationship do not have configuration for next types: ' . implode(', ', $splitTypes)
@@ -250,7 +255,7 @@ public function testExecuteVarSplitDbDoesNotHaveSplitTypes(
$this->loggerMock->expects($this->once())
->method('warning')
->with(
- 'Variable SPLIT_DB does not have data which were already split types: '
+ 'The SPLIT_DB variable is missing the configuration for split connection types: '
. implode(', ', $splitTypes)
);
$this->magentoShellMock->expects($this->never())
@@ -387,4 +392,68 @@ public function testExecuteOnlyUpdateSlaveConnections()
$this->step->execute();
}
+
+ public function testExecuteWithFileSystemExceptionInRead()
+ {
+ $errorMsg = 'Some error';
+ $errorCode = 111;
+ $exception = new FileSystemException($errorMsg, $errorCode);
+ $this->expectException(StepException::class);
+ $this->expectExceptionCode($errorCode);
+ $this->expectExceptionMessage($errorMsg);
+
+ $this->flagManagerMock->expects($this->once())
+ ->method('exists')
+ ->with(FlagManager::FLAG_IGNORE_SPLIT_DB)
+ ->willReturn(false);
+
+ $this->stageConfigMock->expects($this->once())
+ ->method('get')
+ ->with(DeployInterface::VAR_SPLIT_DB)
+ ->willReturn(DeployInterface::SPLIT_DB_VALUES);
+
+ $this->dbConfigMock->expects($this->once())
+ ->method('get')
+ ->willReturn(['connection' => self::CONNECTION]);
+
+ $this->configReaderMock->expects($this->once())
+ ->method('read')
+ ->willThrowException($exception);
+
+ $this->step->execute();
+ }
+
+ public function testExecuteWithFileSystemExceptionInSlaveUpdate()
+ {
+ $errorMsg = 'Some error';
+ $errorCode = 111;
+ $exception = new FileSystemException($errorMsg, $errorCode);
+ $this->expectException(StepException::class);
+ $this->expectExceptionCode(Error::DEPLOY_ENV_PHP_IS_NOT_WRITABLE);
+ $this->expectExceptionMessage('Cannot write slave connection(s) to the `./app/etc/env.php`');
+
+ $this->flagManagerMock->expects($this->once())
+ ->method('exists')
+ ->with(FlagManager::FLAG_IGNORE_SPLIT_DB)
+ ->willReturn(false);
+
+ $this->stageConfigMock->expects($this->once())
+ ->method('get')
+ ->with(DeployInterface::VAR_SPLIT_DB)
+ ->willReturn(DeployInterface::SPLIT_DB_VALUES);
+
+ $this->dbConfigMock->expects($this->once())
+ ->method('get')
+ ->willReturn(['connection' => self::CONNECTION]);
+
+ $this->configReaderMock->expects($this->once())
+ ->method('read')
+ ->willReturn(['db' => ['connection' => []]]);
+
+ $this->slaveConnectionMock->expects($this->once())
+ ->method('update')
+ ->willThrowException($exception);
+
+ $this->step->execute();
+ }
}
diff --git a/src/Test/Unit/Step/PostDeploy/BackupTest.php b/src/Test/Unit/Step/PostDeploy/BackupTest.php
index 1f6ce8c622..af2298ec7b 100644
--- a/src/Test/Unit/Step/PostDeploy/BackupTest.php
+++ b/src/Test/Unit/Step/PostDeploy/BackupTest.php
@@ -83,11 +83,38 @@ public function testExecute(): void
->method('info')
->withConsecutive(
['Create backup of important files.'],
- ['Backup ' . $envPath . BackupList::BACKUP_SUFFIX . ' for ' . $envPath . ' was created.']
+ ['Successfully created backup ' . $envPath . BackupList::BACKUP_SUFFIX . ' for ' . $envPath . '.']
);
$this->fileMock->expects($this->once())
->method('copy')
- ->with($envPath, $envPath . BackupList::BACKUP_SUFFIX);
+ ->with($envPath, $envPath . BackupList::BACKUP_SUFFIX)
+ ->willReturn(true);
+
+ $this->backup->execute();
+ }
+
+ /**
+ * @throws StepException
+ */
+ public function testExecuteFailed()
+ {
+ $envPath = 'path/env.php';
+ $this->backupListMock->expects($this->once())
+ ->method('getList')
+ ->willReturn([
+ 'env.php' => $envPath,
+ ]);
+ $this->fileMock->expects($this->once())
+ ->method('isExists')
+ ->willReturn(true);
+
+ $this->fileMock->expects($this->once())
+ ->method('copy')
+ ->willReturn(false);
+
+ $this->loggerMock->expects($this->once())
+ ->method('warning')
+ ->with('Failed to create backup ' . $envPath . BackupList::BACKUP_SUFFIX . ' for ' . $envPath . '.');
$this->backup->execute();
}
diff --git a/src/Test/Unit/Step/ValidateConfigurationTest.php b/src/Test/Unit/Step/ValidateConfigurationTest.php
index eb27e1f946..20736dad3d 100644
--- a/src/Test/Unit/Step/ValidateConfigurationTest.php
+++ b/src/Test/Unit/Step/ValidateConfigurationTest.php
@@ -7,6 +7,7 @@
namespace Magento\MagentoCloud\Test\Unit\Step;
+use Magento\MagentoCloud\App\Error;
use Magento\MagentoCloud\App\Logger;
use Magento\MagentoCloud\Config\Validator\Result;
use Magento\MagentoCloud\Config\ValidatorInterface;
@@ -59,18 +60,22 @@ public function testExecuteWithoutValidators(): void
public function testExecuteWithCriticalError(): void
{
$this->expectException(StepException::class);
- $this->expectExceptionMessage('Fix configuration with given suggestions');
+ $this->expectExceptionMessage('some error');
$this->expectExceptionCode(127);
$warningValidator = $this->getMockForAbstractClass(ValidatorInterface::class);
$warningValidator->expects($this->once())
->method('validate');
- $this->loggerMock->expects($this->once())
+ $this->loggerMock->expects($this->exactly(2))
->method('notice')
- ->with('Validating configuration');
- $this->loggerMock->expects($this->never())
- ->method('log');
+ ->withConsecutive(
+ ['Validating configuration'],
+ ['Fix configuration with given suggestions:']
+ );
+ $this->loggerMock->expects($this->once())
+ ->method('log')
+ ->with(ValidatorInterface::LEVEL_CRITICAL, 'some error');
$step = new ValidateConfiguration(
$this->loggerMock,
@@ -86,30 +91,59 @@ public function testExecuteWithCriticalError(): void
$step->execute();
}
+ /**
+ * @throws StepException
+ */
+ public function testExecuteWithCriticalErrorAndEmptyErrorCode(): void
+ {
+ $this->expectException(StepException::class);
+ $this->expectExceptionMessage('some error');
+ $this->expectExceptionCode(Error::DEFAULT_ERROR);
+
+ $this->loggerMock->expects($this->once())
+ ->method('log')
+ ->with(ValidatorInterface::LEVEL_CRITICAL, 'some error');
+
+ $step = new ValidateConfiguration(
+ $this->loggerMock,
+ [
+ ValidatorInterface::LEVEL_CRITICAL => [
+ $this->createValidatorWithError('some error', 'some suggestion'),
+ ],
+ ]
+ );
+
+ $step->execute();
+ }
+
/**
* @throws StepException
*/
public function testExecuteWithWarningMessage(): void
{
- $this->loggerMock->expects($this->exactly(2))
+ $this->loggerMock->expects($this->exactly(3))
->method('notice')
->withConsecutive(
['Validating configuration'],
+ ['Fix configuration with given suggestions:'],
['End of validation']
);
$this->loggerMock->expects($this->once())
->method('log')
->with(
ValidatorInterface::LEVEL_WARNING,
- 'Fix configuration with given suggestions:'
- . PHP_EOL . "- some warning\n some warning suggestion"
+ 'some warning',
+ [
+ 'suggestion' => 'some warning suggestion',
+ 'errorCode' => 1001
+ ]
);
$step = new ValidateConfiguration(
$this->loggerMock,
[
ValidatorInterface::LEVEL_WARNING => [
- $this->createValidatorWithError('some warning', 'some warning suggestion'),
+ $this->createValidatorWithError('some warning', 'some warning suggestion', 1001),
],
]
);
@@ -122,21 +156,42 @@ public function testExecuteWithWarningMessage(): void
public function testExecuteWithWarningAndCriticalMessage(): void
{
$this->expectException(StepException::class);
- $this->expectExceptionMessage('Fix configuration with given suggestions');
+ $this->expectExceptionMessage('Critical error');
$this->expectExceptionCode(1);
- $this->loggerMock->expects($this->once())
+ $this->loggerMock->expects($this->exactly(2))
->method('notice')
- ->with('Validating configuration');
- $this->loggerMock->expects($this->once())
+ ->withConsecutive(
+ ['Validating configuration'],
+ ['Fix configuration with given suggestions:']
+ );
+ $this->loggerMock->expects($this->exactly(3))
->method('log')
- ->with(
- Logger::WARNING,
- 'Fix configuration with given suggestions:'
- . PHP_EOL . '- some warning'
- . PHP_EOL . ' some warning suggestion'
- . PHP_EOL . '- some warning 2'
- . PHP_EOL . ' some warning suggestion 2'
+ ->withConsecutive(
+ [
+ Logger::WARNING,
+ 'some warning',
+ [
+ 'suggestion' => 'some warning suggestion',
+ 'errorCode' => 2001
+ ],
+ ],
+ [
+ Logger::WARNING,
+ 'some warning 2',
+ [
+ 'suggestion' => 'some warning suggestion 2',
+ 'errorCode' => 2002
+ ],
+ ],
+ [
+ Logger::CRITICAL,
+ 'Critical error',
+ [
+ 'suggestion' => 'some critical suggestion',
+ 'errorCode' => 1
+ ],
+ ]
);
$step = new ValidateConfiguration(
@@ -146,11 +201,12 @@ public function testExecuteWithWarningAndCriticalMessage(): void
$this->createValidatorWithError('Critical error', 'some critical suggestion', 1),
],
ValidatorInterface::LEVEL_WARNING => [
- $this->createValidatorWithError('some warning', 'some warning suggestion'),
- $this->createValidatorWithError('some warning 2', 'some warning suggestion 2'),
+ $this->createValidatorWithError('some warning', 'some warning suggestion', 2001),
+ $this->createValidatorWithError('some warning 2', 'some warning suggestion 2', 2002),
],
]
);
+
$step->execute();
}
@@ -160,26 +216,41 @@ public function testExecuteWithWarningAndCriticalMessage(): void
public function testExecuteTypeStringLevel(): void
{
$this->expectException(StepException::class);
- $this->expectExceptionMessage('Fix configuration with given suggestions');
+ $this->expectExceptionMessage('Critical error');
$this->expectExceptionCode(10);
- $this->loggerMock->expects($this->once())
- ->method('notice')
- ->with('Validating configuration');
$this->loggerMock->expects($this->exactly(2))
+ ->method('notice')
+ ->withConsecutive(
+ ['Validating configuration'],
+ ['Fix configuration with given suggestions:']
+ );
+ $this->loggerMock->expects($this->exactly(3))
->method('log')
->withConsecutive(
[
Logger::NOTICE,
- 'Fix configuration with given suggestions:'
- . PHP_EOL . '- some notice'
- . PHP_EOL . ' some notice suggestion'
+ 'some notice',
+ [
+ 'suggestion' => 'some notice suggestion',
+ 'errorCode' => null
+ ]
],
[
Logger::WARNING,
- 'Fix configuration with given suggestions:'
- . PHP_EOL . '- some warning'
- . PHP_EOL . ' some warning suggestion'
+ 'some warning',
+ [
+ 'suggestion' => 'some warning suggestion',
+ 'errorCode' => 1001
+ ]
+ ],
+ [
+ Logger::CRITICAL,
+ 'Critical error',
+ [
+ 'suggestion' => 'some critical suggestion',
+ 'errorCode' => 10
+ ]
]
);
@@ -190,7 +261,7 @@ public function testExecuteTypeStringLevel(): void
$this->createValidatorWithError('Critical error', 'some critical suggestion', 10),
],
'warning' => [
- $this->createValidatorWithError('some warning', 'some warning suggestion'),
+ $this->createValidatorWithError('some warning', 'some warning suggestion', 1001),
],
'notice' => [
$this->createValidatorWithError('some notice', 'some notice suggestion'),
@@ -212,7 +283,7 @@ private function createValidatorWithError(string $error, string $suggestion, int
$warningValidator = $this->getMockForAbstractClass(ValidatorInterface::class);
$warningResultMock = $this->createMock(Result\Error::class);
- $warningResultMock->expects($this->once())
+ $warningResultMock->expects($this->any())
->method('getError')
->willReturn($error);
$warningResultMock->expects($this->once())
diff --git a/src/Test/Unit/Util/BuildDirCopierTest.php b/src/Test/Unit/Util/BuildDirCopierTest.php
index fbd6e0327b..4fc65f6357 100644
--- a/src/Test/Unit/Util/BuildDirCopierTest.php
+++ b/src/Test/Unit/Util/BuildDirCopierTest.php
@@ -7,6 +7,7 @@
namespace Magento\MagentoCloud\Test\Unit\Util;
+use Magento\MagentoCloud\App\Error;
use Magento\MagentoCloud\Filesystem\DirectoryCopier\CopyStrategy;
use Magento\MagentoCloud\Filesystem\DirectoryCopier\StrategyFactory;
use Magento\MagentoCloud\Filesystem\DirectoryList;
@@ -110,8 +111,8 @@ public function copyDataProvider(): array
],
[
false,
- 'notice',
- 'Can\'t copy directory dir with strategy: copy',
+ 'warning',
+ 'Cannot copy directory dir with strategy: copy',
],
];
}
@@ -178,7 +179,7 @@ public function testCopyWithFilesSystemException(): void
->method('copy')
->with($fromDirectory, $toDirectory)
->willThrowException(
- new FileSystemException('Can\'t copy directory /path/to/root/not-exist-dir. Directory does not exist.')
+ new FileSystemException('Cannot copy directory /path/to/root/not-exist-dir. Directory does not exist.')
);
$this->strategyFactory->expects($this->once())
->method('create')
@@ -191,8 +192,11 @@ public function testCopyWithFilesSystemException(): void
->method('getInit')
->willReturn($initDir);
$this->loggerMock->expects($this->once())
- ->method('notice')
- ->with('Can\'t copy directory /path/to/root/not-exist-dir. Directory does not exist.');
+ ->method('warning')
+ ->with(
+ 'Cannot copy directory /path/to/root/not-exist-dir. Directory does not exist.',
+ ['errorCode' => Error::WARN_COPY_MOUNTED_DIRS_FAILED]
+ );
$this->copier->copy($dir, $strategy);
}
diff --git a/src/Util/BuildDirCopier.php b/src/Util/BuildDirCopier.php
index 4b89d1e636..839d7b8ea4 100644
--- a/src/Util/BuildDirCopier.php
+++ b/src/Util/BuildDirCopier.php
@@ -7,9 +7,11 @@
namespace Magento\MagentoCloud\Util;
+use Magento\MagentoCloud\App\Error;
use Magento\MagentoCloud\Filesystem\DirectoryCopier\StrategyFactory;
use Magento\MagentoCloud\Filesystem\DirectoryList;
use Magento\MagentoCloud\Filesystem\FileSystemException;
+use Magento\MagentoCloud\Package\UndefinedPackageException;
use Psr\Log\LoggerInterface;
/**
@@ -51,6 +53,8 @@ public function __construct(
* @param string $dir The directory to copy. Pass in its normal location relative to Magento root with no prepending
* or trailing slashes
* @param string $strategyName Name of strategy that will be used for copying directories
+ *
+ * @throws UndefinedPackageException
*/
public function copy(string $dir, string $strategyName)
{
@@ -73,16 +77,17 @@ public function copy(string $dir, string $strategyName)
)
);
} else {
- $this->logger->notice(
+ $this->logger->warning(
sprintf(
- 'Can\'t copy directory %s with strategy: %s',
+ 'Cannot copy directory %s with strategy: %s',
$dir,
$strategyName
- )
+ ),
+ ['errorCode' => Error::WARN_COPY_MOUNTED_DIRS_FAILED]
);
}
} catch (FileSystemException $e) {
- $this->logger->notice($e->getMessage());
+ $this->logger->warning($e->getMessage(), ['errorCode' => Error::WARN_COPY_MOUNTED_DIRS_FAILED]);
}
}
}
diff --git a/src/Util/Cpu.php b/src/Util/Cpu.php
index 13eaca5a40..bcea7164d6 100644
--- a/src/Util/Cpu.php
+++ b/src/Util/Cpu.php
@@ -7,6 +7,7 @@
namespace Magento\MagentoCloud\Util;
+use Magento\MagentoCloud\App\Error;
use Magento\MagentoCloud\Shell\ShellException;
use Magento\MagentoCloud\Shell\ShellInterface;
use Psr\Log\LoggerInterface;
@@ -48,7 +49,10 @@ public function getThreadsCount(): int
$result = $this->shell->execute('nproc');
$threadCount = max((int)$result->getOutput(), 1);
} catch (ShellException $e) {
- $this->logger->error('Can\'t get system processor count: ' . $e->getMessage());
+ $this->logger->warning(
+ 'Can\'t get system processor count: ' . $e->getMessage(),
+ ['errorCode' => Error::WARN_CANNOT_GET_PROC_COUNT]
+ );
$threadCount = 1;
}
diff --git a/src/Util/UrlManager.php b/src/Util/UrlManager.php
index 22b5cb20ab..0a387f0831 100644
--- a/src/Util/UrlManager.php
+++ b/src/Util/UrlManager.php
@@ -7,6 +7,7 @@
namespace Magento\MagentoCloud\Util;
+use Magento\MagentoCloud\App\Error;
use Magento\MagentoCloud\Config\Environment;
use Magento\MagentoCloud\Shell\ShellException;
use Magento\MagentoCloud\Shell\MagentoShell;
@@ -209,7 +210,10 @@ private function loadStoreBaseUrls(): void
$this->storeBaseUrls = $baseUrls;
}
} catch (ShellException $e) {
- $this->logger->error('Can\'t fetch store urls. ' . $e->getMessage());
+ $this->logger->warning(
+ 'Can\'t fetch store urls. ' . $e->getMessage(),
+ ['errorCode' => Error::WARN_CANNOT_FETCH_STORE_URLS]
+ );
}
}
}
@@ -234,7 +238,10 @@ public function getStoreBaseUrl(string $storeId): ?string
return $this->storeBaseUrls[$storeId] = $process->getOutput();
} catch (ShellException $e) {
- $this->logger->error(sprintf('Can\'t fetch store with store code "%s". ', $storeId) . $e->getMessage());
+ $this->logger->warning(
+ sprintf('Can\'t fetch store url with store code "%s". %s', $storeId, $e->getMessage()),
+ ['errorCode' => Error::WARN_CANNOT_FETCH_STORE_URL]
+ );
return null;
}
diff --git a/tests/functional/_data/files/error_codes/.magento.env.fail.yaml b/tests/functional/_data/files/error_codes/.magento.env.fail.yaml
new file mode 100644
index 0000000000..ed5ed4f750
--- /dev/null
+++ b/tests/functional/_data/files/error_codes/.magento.env.fail.yaml
@@ -0,0 +1,8 @@
+stage:
+ build:
+ SCD_THREADS: 3
+ global:
+ SCD_ON_DEMAND: true
+ deploy:
+ DATABASE_CONFIGURATION:
+ host:
diff --git a/tests/functional/_data/files/error_codes/.magento.env.success.yaml b/tests/functional/_data/files/error_codes/.magento.env.success.yaml
new file mode 100644
index 0000000000..a86f0ce2b0
--- /dev/null
+++ b/tests/functional/_data/files/error_codes/.magento.env.success.yaml
@@ -0,0 +1,3 @@
+stage:
+ global:
+ SCD_ON_DEMAND: true
diff --git a/tests/travis/functional_ce.sh b/tests/travis/functional_ce.sh
index 989ae722df..9d737da442 100755
--- a/tests/travis/functional_ce.sh
+++ b/tests/travis/functional_ce.sh
@@ -8,12 +8,15 @@ trap '>&2 echo Error: Command \`$BASH_COMMAND\` on line $LINENO failed with exit
case $TRAVIS_PHP_VERSION in
7.1)
- ./vendor/bin/codecept run -g edition-ce --steps
+ ./vendor/bin/codecept run -g edition-ce -x php72 -x php73 -x php74 --steps
;;
7.2)
- ./vendor/bin/codecept run -g edition-ce --steps
+ ./vendor/bin/codecept run -g edition-ce -x php71 -x php73 -x php74 --steps
;;
7.3)
- ./vendor/bin/codecept run -g edition-ce --steps
+ ./vendor/bin/codecept run -g edition-ce -x php72 -x php71 -x php74 --steps
+ ;;
+ 7.4)
+ ./vendor/bin/codecept run -g edition-ce -x php72 -x php71 -x php73 --steps
;;
esac
diff --git a/tests/travis/functional_ee.sh b/tests/travis/functional_ee.sh
index f5547bd58c..08b2b55de2 100755
--- a/tests/travis/functional_ee.sh
+++ b/tests/travis/functional_ee.sh
@@ -6,14 +6,4 @@
set -e
trap '>&2 echo Error: Command \`$BASH_COMMAND\` on line $LINENO failed with exit code $?' ERR
-case $TRAVIS_PHP_VERSION in
- 7.1)
- ./vendor/bin/codecept run -g php71 -x edition-ce --steps
- ;;
- 7.2)
- ./vendor/bin/codecept run -g parallel_"$FUNCTIONAL_INDEX" -x edition-ce --steps
- ;;
- 7.3)
- ./vendor/bin/codecept run -g parallel_"$FUNCTIONAL_INDEX" -x php72 -x edition-ce --steps
- ;;
-esac
+./vendor/bin/codecept run -g parallel_"${TRAVIS_PHP_VERSION//./}"_"$FUNCTIONAL_INDEX" --steps
diff --git a/tests/travis/prepare_functional_parallel.sh b/tests/travis/prepare_functional_parallel.sh
index f67a62d60e..a99f80e5b2 100755
--- a/tests/travis/prepare_functional_parallel.sh
+++ b/tests/travis/prepare_functional_parallel.sh
@@ -6,7 +6,9 @@
set -e
trap '>&2 echo Error: Command \`$BASH_COMMAND\` on line $LINENO failed with exit code $?' ERR
-readarray -t test_set_list <<< "$(grep -RL 'php71' --exclude='*AcceptanceCest.php' src/Test/Functional/Acceptance | sort)"
+php_version="${TRAVIS_PHP_VERSION//./}"
+
+readarray -t test_set_list <<< "$(grep -Rl php${php_version} --exclude='*AcceptanceCest.php' --exclude='*AcceptanceCeCest.php' --exclude='*AcceptanceCe71Cest.php' --exclude='*AcceptanceCe72Cest.php' --exclude='*AcceptanceCe73Cest.php' --exclude='*AbstractCest.php' src/Test/Functional/Acceptance | sort)"
group_count=6
if [ $(( ${#test_set_list[@]} % group_count )) -eq 0 ]; then
@@ -17,18 +19,23 @@ fi
cp codeception.dist.yml codeception.yml
echo "groups:" >> codeception.yml
-echo " parallel_*: tests/functional/_data/parallel_*" >> codeception.yml
+echo " parallel_${php_version}_*: tests/functional/_data/parallel_${php_version}_*" >> codeception.yml
-echo "Total = ${#test_set_list[@]};"
-echo "Batch #1 = Acceptance"
-echo "src/Test/Functional/Acceptance/AcceptanceCest.php" >> "tests/functional/_data/parallel_1.yml"
+if [ $php_version == "74" ]; then
+ echo "Total = ${#test_set_list[@]};"
+ echo "Batch #1 = Acceptance"
+ echo "src/Test/Functional/Acceptance/AcceptanceCest.php" >> "tests/functional/_data/parallel_${php_version}_1.yml"
+ start_group_id=2
+else
+ start_group_id=1
+fi
-for((i=0, group_id=2; i < ${#test_set_list[@]}; i+=element_in_group, group_id++))
+for((i=0, group_id=start_group_id; i < ${#test_set_list[@]}; i+=element_in_group, group_id++))
do
test_file_group=( "${test_set_list[@]:i:element_in_group}" )
echo "Batch #${group_id} = ${#test_file_group[@]}"
- group_file="tests/functional/_data/parallel_$group_id.yml"
+ group_file="tests/functional/_data/parallel_${php_version}_$group_id.yml"
for test_file in "${test_file_group[@]}"
do