diff --git a/.travis.yml b/.travis.yml index 7f5a8efcc..2a7de8c14 100644 --- a/.travis.yml +++ b/.travis.yml @@ -87,14 +87,19 @@ script: - blt acsf:init # Deploy build artifact. - blt deploy:build + # Ensure that the doctor doesn't report any problems at this point. + # We must temporarily move acquia/blt to require to appease the Doctor. It must then be removed so deploy cannot resolve the symlink later. + - composer remove acquia/blt --no-update --dev + - composer require acquia/blt --no-update + - composer global require "hirak/prestissimo:^0.3" + - blt doctor + - composer remove acquia/blt --no-update # Add Drupal VM config to repo. - blt vm:init # Switch back to 'blt' directory. - cd ../blt # Run 'blt' phpunit tests, excluding deploy-push tests. - phpunit tests/phpunit --group blt --exclude-group deploy-push - # Execute 'blt update' just to ensure that there isn't a non-zero exit code. - # - blt update deploy: provider: script diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2c5f842c1..00a290bb8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,13 +2,12 @@ Please feel free to contribute to the project or file issues via the GitHub issue queue. When doing so, please keep the following points in mind: + * BLT is distributed under the GPLv2 license; WITHOUT ANY WARRANTY. * The project maintainers make no commitment to respond to support requests, feature requests, or pull requests. * All contributions to BLT will be reviewed for compliance with Drupal Coding Standards and best practices as defined by the project maintainer. -* Feature that are part of the [Road Map](https://github.com/acquia/blt/wiki/Road-Map) - will be prioritized for inclusion. BLT work is currently being tracked in the [BLT GitHub issue queue](https://github.com/acquia/blt/issues) and organized via a [Waffle.io Kanban Board](https://waffle.io/acquia/blt). @@ -26,8 +25,6 @@ cd blt-project git init composer install ./vendor/bin/blt install-alias -blt init -blt configure rm -rf vendor composer update git add -A diff --git a/composer.json b/composer.json index eeaaf0b7d..bdc81be1a 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,8 @@ "symfony/console": "~2", "symfony/twig-bridge": "~2", "php": ">=5.6", - "composer-plugin-api": "^1.0.0" + "composer-plugin-api": "^1.0.0", + "dflydev/dot-access-data": "^1.0" }, "autoload": { "psr-4": { diff --git a/composer.lock b/composer.lock index f0d1ccbc5..25e6fd7fd 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "de6f11ac98767d7792617f93306f9f95", - "content-hash": "c8ec97172ce549b9d70b47e626d0453a", + "hash": "d6fb083a9a345b61a1ead6b26b1f1d85", + "content-hash": "535430afdcc8784fa1178cf93357df0e", "packages": [ { "name": "alchemy/zippy", @@ -176,6 +176,60 @@ ], "time": "2016-08-13 20:53:52" }, + { + "name": "dflydev/dot-access-data", + "version": "v1.0.1", + "source": { + "type": "git", + "url": "https://github.com/dflydev/dflydev-dot-access-data.git", + "reference": "7a0960d088119818ce7687d200c363b01d183cbe" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dflydev/dflydev-dot-access-data/zipball/7a0960d088119818ce7687d200c363b01d183cbe", + "reference": "7a0960d088119818ce7687d200c363b01d183cbe", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-0": { + "Dflydev\\DotAccessData": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Dragonfly Development Inc.", + "email": "info@dflydev.com", + "homepage": "http://dflydev.com" + }, + { + "name": "Beau Simensen", + "email": "beau@dflydev.com", + "homepage": "http://beausimensen.com" + } + ], + "description": "Given a deep data structure, access data by dot notation.", + "homepage": "https://github.com/dflydev/dflydev-dot-access-data", + "keywords": [ + "access", + "data", + "dot", + "notation" + ], + "time": "2015-08-13 03:51:18" + }, { "name": "dflydev/placeholder-resolver", "version": "v1.0.2", diff --git a/mkdocs.yml b/mkdocs.yml index 15f82c1b5..c516dc9bc 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -36,5 +36,6 @@ pages: - Release notes: 'scripts/release-notes/README.md' - Setting up continuous integration: 'readme/ci.md' - Open source contribution: 'readme/os-contribution.md' + - Troubleshooting & Support: 'readme/support.md' - Extending / Overriding BLT: 'readme/extending-blt.md' - Contributing: 'CONTRIBUTING.md' diff --git a/phing/tasks/deploy.xml b/phing/tasks/deploy.xml index 93c407e59..d557fcb1c 100644 --- a/phing/tasks/deploy.xml +++ b/phing/tasks/deploy.xml @@ -13,6 +13,7 @@ + diff --git a/readme/support.md b/readme/support.md new file mode 100644 index 000000000..8fc751ca4 --- /dev/null +++ b/readme/support.md @@ -0,0 +1,14 @@ +If you experience issues with a local BLT build, try using Dr. BLT to diagnose your problem: + + blt doctor + +If that isn't helpful, please post an issue on the [GitHub issue queue](https://github.com/acquia/blt/issues) including the following information: + +- Your version of BLT, `composer info acquia/blt` +- Your operating system +- The full log output of your BLT command, wrapped in a [codeblock](https://help.github.com/articles/basic-writing-and-formatting-syntax/#quoting-code). + +In seeking help, please keep the following points in mind: + +* BLT is distributed under the GPLv2 license; WITHOUT ANY WARRANTY. +* The project maintainers are under no obligation to respond to support requests, feature requests, or pull requests. diff --git a/scripts/blt/alias b/scripts/blt/alias index bae4ac926..29c5d558a 100644 --- a/scripts/blt/alias +++ b/scripts/blt/alias @@ -10,5 +10,6 @@ function blt() { $GIT_ROOT/vendor/bin/blt "$@" else echo "You must run this command from within a BLT-generated project repository." + exit 1 fi } diff --git a/scripts/blt/ignore-existing.txt b/scripts/blt/ignore-existing.txt index 5391d51e8..7722442a4 100644 --- a/scripts/blt/ignore-existing.txt +++ b/scripts/blt/ignore-existing.txt @@ -1,7 +1,6 @@ # These files from template dir will be included if they do not yet exist. They will not overwrite # existing files. .gitattributes -.travis.yml project.yml composer.json README.md diff --git a/src/Drush/Command/BltDoctorCommand.php b/src/Drush/Command/BltDoctorCommand.php index 30c13b02f..7f2633dd4 100644 --- a/src/Drush/Command/BltDoctorCommand.php +++ b/src/Drush/Command/BltDoctorCommand.php @@ -7,36 +7,169 @@ namespace Acquia\Blt\Drush\Command; +use Dflydev\DotAccessData\Data; +use Symfony\Component\Yaml\Yaml; +use Drupal\Core\Installer\Exception\AlreadyInstalledException; + class BltDoctor { + /** @var string */ protected $localSettingsPath; - protected $statusTable; + /** @var array */ + protected $statusTable = []; + /** @var bool */ + protected $ciEnabled = FALSE; + /** @var array */ + protected $composerJson = []; + /** @var bool */ + protected $drupalVmEnabled = FALSE; + /** @var bool */ + protected $devDesktopEnabled = FALSE; + /** @var array */ + protected $config = []; /** * BoltDoctor constructor. */ public function __construct() { - $this->statusTable = drush_core_status(); - $this->localSettingsPath = $this->statusTable['root'] . '/' . $this->statusTable['site'] . '/settings/' . 'local.settings.php'; + $this->setStatusTable(); + $this->docroot = $this->statusTable['root']; + $this->repoRoot = $this->statusTable['root'] . '/../'; + + if (!$this->coreExists()) { + return FALSE; + } + + $this->siteRoot = $this->docroot . '/' . $this->statusTable['site']; + $this->uri = $this->getUri(); + $this->localSettingsPath = $this->siteRoot . '/settings/' . 'local.settings.php'; + $this->localDrushRcPath = $this->siteRoot . '/local.drushrc.php'; + $this->setProjectConfig(); + $this->setCiEnabled(); + $this->setStacksEnabled(); + $this->setComposerJson(); + } + + /** + * Sets $this->statusTable using drush internals. + * + * @return array + */ + public function setStatusTable() { + $status_table = drush_core_status(); + $status_table['php-mysql'] = ini_get('pdo_mysql.default_socket'); + $this->statusTable = $status_table; + + return $status_table; + } + + /** + * Sets $this->config from project.yml. + * + * @return array|bool|mixed + */ + protected function setProjectConfig() { + $filepath = $this->repoRoot . '/project.yml'; + if (!file_exists($filepath)) { + drush_set_error("project.yml is missing from the repository root directory!"); + + return []; + } + + $this->config = Yaml::parse(file_get_contents($filepath)); + + return $this->config; + } + + /** + * Sets $this->composerJson using root composer.json file. + * + * @return array + */ + protected function setComposerJson() { + if (file_exists($this->repoRoot . '/composer.json')) { + $composer_json = json_decode(file_get_contents($this->repoRoot . '/composer.json'), TRUE); + $this->composerJson = $composer_json; + + return $composer_json; + } + + return []; + } + + /** + * Gets site URI from drush status table. + * + * @return mixed|null + */ + public function getUri() { + if (!empty($this->statusTable['uri'])) { + return $this->statusTable['uri']; + } + return NULL; + } + + /** + * Sets which local *AMP stacks are initialized. + */ + protected function setStacksEnabled() { + $file_contents = file_get_contents($this->docroot . '/sites/default/settings.php'); + if (strstr($file_contents, 'DDSETTINGS')) { + $this->devDesktopEnabled = TRUE; + } + + if (file_exists($this->repoRoot . '/Vagrantfile')) { + $this->drupalVmEnabled = TRUE; + } + } + + /** + * Sets which CI solutions are initialized. + */ + protected function setCiEnabled() { + if (file_exists($this->repoRoot . '/.travis.yml')) { + $this->travisCiEnabled = TRUE; + $this->ciEnabled = TRUE; + } + if (file_exists($this->repoRoot . '/acquia-pipelines.yml') || file_exists($this->repoRoot . '/acquia-pipelines.yaml')) { + $this->pipelinesEnabled = TRUE; + $this->ciEnabled = TRUE; + } } /** * Performs all checks. */ public function checkAll() { + $this->checkCoreExists(); + if (!$this->coreExists()) { + return FALSE; + } + + $this->checkSettingsFile(); $this->checkLocalSettingsFile(); + $this->checkLocalDrushFile(); $this->checkUriResponse(); $this->checkHttps(); + $this->checkFileSystem(); $this->checkDbConnection(); + $this->checkDrupalBootstrapped(); + $this->checkDrupalInstalled(); + //$this->checkDatabaseUpdates(); $this->checkCachingConfig(); $this->checkNvmExists(); - //$this->checkDatabaseUpdates(); + $this->checkDevDesktopConfig(); + $this->checkCiConfig(); + $this->checkComposerConfig(); + $this->checkBehatConfig(); + $this->checkProjectYml(); - // @todo Check if Drupal is installed. - // @todo Check if files directory exists. // @todo Check error_level. // @todo Check if theme dependencies have been built. - // @todo Check if composer dependencies have been built. + // @todo Check that if drupal/acsf is in composer.json, acsf is initialized. + // @todo If using lightning, check lightning.extend.yml exists, check for $config['profile'] = 'lighting'; + // @todo Check for existence of deprecated BLT files. + // @todo Check is PhantomJS bin matches OS. } /** @@ -44,7 +177,7 @@ public function checkAll() { */ protected function checkLocalSettingsFile() { if (!file_exists($this->localSettingsPath)) { - drush_log("Could not find local settings file!", 'error'); + drush_set_error("Could not find local settings file!"); drush_print("Your local settings file should exist at $this->localSettingsPath", 2); } else { @@ -55,29 +188,75 @@ protected function checkLocalSettingsFile() { } /** - * Checks that configured $base_url responds to requests. + * Checks active settings.php file. + */ + protected function checkSettingsFile() { + if (!file_exists($this->statusTable['drupal-settings-file'])) { + drush_set_error("Could not find settings.php for this site!"); + } + + $settings_file_path = $this->docroot . '/' . $this->statusTable['drupal-settings-file']; + $settings_file_contents = file_get_contents($settings_file_path); + if (strstr($settings_file_contents, '/../vendor/acquia/blt/settings/blt.settings.php')) { + drush_log("BLT settings are included in settings file:", 'success'); + drush_print($settings_file_path, 2); + } + if (strstr($settings_file_contents, '/sites/default/settings/blt.settings.php')) { + drush_set_error("Your settings file contains a deprecated statement for including BLT settings."); + drush_print("Please remove the line containing \"/sites/default/settings/blt.settings.php\" in $settings_file_path.", 2); + } + drush_print(); + } + + /** + * Checks local.drushrc.php file. + */ + protected function checkLocalDrushFile() { + if (!file_exists($this->localDrushRcPath)) { + drush_set_error("$this->localDrushRcPath does not exist"); + drush_print("Run `blt setup:drush` to generate it automatically.", 2); + } + else { + drush_log("Found your local drush settings file at:", 'success'); + drush_print($this->localDrushRcPath, 2); + } + drush_print(); + } + + /** + * Checks that configured URI responds to requests. */ protected function checkUriResponse() { - $site_available = drush_shell_exec("curl -I --insecure %s", $this->statusTable['uri']); + if (!$this->uri) { + drush_set_error("Site URI is not set"); + drush_print("Is \$options['uri'] set correctly in $this->localDrushRcPath?", 2); + + return FALSE; + } + + $site_available = drush_shell_exec("curl -I --insecure %s", $this->uri); if (!$site_available) { - drush_log("Did not get response from $this->statusTable['uri']", 'error'); + drush_set_error("Did not get a response from $this->uri"); drush_print("Is your *AMP stack running?", 2); - drush_print("Is your \$base_url set correctly in $this->localSettingsPath?", 2); + drush_print("Is your web server configured to serve this URI from $this->docroot?", 2); + drush_print("Is \$options['uri'] set correctly in $this->localDrushRcPath?", 2); + drush_print(); + drush_print("To generate settings files and install Drupal, run `blt local:setup`", 2); } else { - drush_log("Received response from site:", 'success'); + drush_log("Received a response from site:", 'success'); drush_print($this->statusTable['uri'], 2); } drush_print(); } /** - * Checks that SSL cert is valid for $base_url. + * Checks that SSL cert is valid for configured URI. */ protected function checkHttps() { if (strstr($this->statusTable['uri'], 'https')) { if (!drush_shell_exec('curl -cacert %s', $this->statusTable['uri'])) { - drush_log('The SSL certificate for your local site appears to be invalid:', 'error'); + drush_set_error('The SSL certificate for your local site appears to be invalid:'); drush_print($this->statusTable['uri'], 2); drush_print(); } @@ -85,38 +264,52 @@ protected function checkHttps() { } /** - * Checks that drush is able to bootstrap and connect to database. + * Checks that drush is able to connect to database. */ protected function checkDbConnection() { - if (empty($this->statusTable['bootstrap']) || $this->statusTable['bootstrap'] != 'Successful') { - drush_log('Could not bootstrap Drupal!', 'error'); - drush_print("Is your *AMP stack running?", 2); - drush_print('Are your database credentials correct?', 2); - drush_blt_print_status_rows($this->statusTable, array( - 'db-driver', - 'db-hostname', - 'db-username', - 'db-password', - 'db-name', - 'db-port', - )); - - drush_print('Is the active PHP binary the same one that is associated with your database service?'); - drush_blt_print_status_rows($this->statusTable, array( - 'php-os', - 'php-bin', - 'php-conf', - )); - - drush_print('Are you using the correct site and settings.php file?'); - drush_blt_print_status_rows($this->statusTable, array( - 'site', - 'drupal-settings-file', - )); + + $connection = @mysqli_connect($this->statusTable['db-hostname'], $this->statusTable['db-username'], $this->statusTable['db-password'], $this->statusTable['db-database'], $this->statusTable['db-port']); + if ($connection) { + mysqli_close($connection); + drush_log('Connected to database.', 'success'); + + return TRUE; } - else { - drush_log('Bootstrapped Drupal and connected to database.', 'success'); + + drush_set_error('Could not connect to MySQL database.'); + drush_print("Is your *AMP stack running?", 2); + drush_print('Are your database credentials correct?', 2); + drush_blt_print_status_rows($this->statusTable, array( + 'db-driver', + 'db-hostname', + 'db-username', + 'db-password', + 'db-name', + 'db-port', + )); + + if ($this->statusTable['db-driver'] == 'mysql') { + drush_print("To verify your mysql credentials, run `mysql -u {$this->statusTable['db-username']} -h {$this->statusTable['db-hostname']} -p{$this->statusTable['db-password']} -P {$this->statusTable['db-port']}`", 2); + drush_print(); } + + drush_print('Are you using the correct PHP binary?', 2); + drush_print('Is PHP using the correct MySQL socket?', 2); + drush_blt_print_status_rows($this->statusTable, array( + 'php-os', + 'php-bin', + 'php-conf', + 'php-mysql' + )); + drush_print("To verify, run `drush sqlc`", 2); + drush_print(); + + drush_print('Are you using the correct site and settings.php file?'); + drush_blt_print_status_rows($this->statusTable, array( + 'site', + 'drupal-settings-file', + )); + drush_print(); } @@ -128,7 +321,7 @@ protected function checkDatabaseUpdates() { $pending = update_main(); if ($pending) { - drush_log("There are pending database updates", 'error'); + drush_set_error("There are pending database updates"); drush_print("Run `drush updb` to execute the updates.", 2); } else { @@ -138,7 +331,7 @@ protected function checkDatabaseUpdates() { } /** - * Checks that nvm exists. + * Checks that NVM exists. * * Note that this does not check if `nvm use` has been invoked for the correct * node version. @@ -146,7 +339,7 @@ protected function checkDatabaseUpdates() { protected function checkNvmExists() { $home = getenv("HOME"); if (!file_exists("$home/.nvm")) { - drush_log('NVM does not exist. Install using the following commands:', 'error'); + drush_log('NVM does not exist. Using NVM will help you manage multiple versions of NodeJS on one machine. Install using the following commands:', 'warning'); drush_print('curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.0/install.sh | bash', 2); drush_print('source ~/.bashrc', 2); drush_print('nvm install 0.12.7', 2); @@ -158,6 +351,202 @@ protected function checkNvmExists() { } } + /** + * Indicates whether Drupal core files exist in the docroot. + * + * @return bool + */ + protected function coreExists() { + return file_exists($this->docroot . '/core/includes/install.core.inc'); + } + + /** + * Checks that Drupal core files exist in the docroot. + */ + protected function checkCoreExists() { + if (!$this->coreExists()) { + drush_set_error("Drupal core is missing!"); + drush_print("Check and re-install your composer dependencies.", 2); + } + else { + drush_log("Drupal core exists.", 'success'); + } + } + + /** + * Checks that drush is able to bootstrap Drupal Core. + * + * This is only possible if Drupal is installed. + */ + protected function checkDrupalBootstrapped() { + if (empty($this->statusTable['bootstrap']) || $this->statusTable['bootstrap'] != 'Successful') { + drush_log('Could not bootstrap Drupal via drush.', 'warning'); + } + else { + drush_log('Bootstrapped Drupal via drush.', 'success'); + } + } + + /** + * Checks that Drupal is installed. + */ + protected function checkDrupalInstalled() { + require $this->docroot . '/core/includes/install.core.inc'; + require $this->docroot . '/core/includes/install.inc'; + require $this->docroot . '/core/modules/system/system.install'; + try { + install_verify_database_ready(); + drush_log("Drupal is not installed.", 'warning'); + drush_print('Run `blt local:setup` to install Drupal locally.', 2); + } + catch (AlreadyInstalledException $e) { + drush_log("Drupal is installed.", 'success'); + } + catch (\Exception $e) { + + } + } + + /** + * Checks that configured file system paths exist and are writable. + */ + protected function checkFileSystem() { + $paths = [ + '%files' => 'Public files directory', + '%private' => 'Private files directory', + '%tmp' => 'Temporary files directory', + ]; + + foreach ($paths as $key => $title) { + $path = $this->statusTable['%paths'][$key]; + if (substr($path, 0, 1) == '/') { + $full_path = $path; + } + else { + $full_path = $this->docroot . "/$path"; + } + + if (file_exists($full_path)) { + drush_log("$title exists.", 'success'); + + if (is_writable($full_path)) { + drush_log("$title is writable.", 'success'); + } + else { + drush_set_error("$title is not writable."); + drush_print("Change the permissions on $full_path", 2); + } + } + else { + drush_set_error("$title does not exist."); + drush_print("Create $full_path", 2); + } + } + } + + /** + * Checks that Dev Desktop is configured correctly. + */ + protected function checkDevDesktopConfig() { + if ($this->devDesktopEnabled) { + if (empty($ENV['DEVDESKTOP_DRUPAL_SETTINGS_DIR'])) { + drush_set_error("DevDesktop usage is enabled, but \$DEVDESKTOP_DRUPAL_SETTINGS_DIR is not set in your environmental variables."); + drush_print("Add `export DEVDESKTOP_DRUPAL_SETTINGS_DIR=\"\$HOME/.acquia/DevDesktop/DrupalSettings\"` to ~/.bash_profile or equivalent for your system.`", 2); + drush_print(); + } + elseif (strstr($ENV['DEVDESKTOP_DRUPAL_SETTINGS_DIR'], '~')) { + drush_set_error("\$DEVDESKTOP_DRUPAL_SETTINGS_DIR contains a '~'. This does not always expand to your home directory."); + drush_print("Add `export DEVDESKTOP_DRUPAL_SETTINGS_DIR=\"\$HOME/.acquia/DevDesktop/DrupalSettings\"` to ~/.bash_profile or equivalent for your system.`", 2); + drush_print(); + } + + $variables_order = ini_get('variables_order'); + $php_ini_file = php_ini_loaded_file(); + if (!strstr($variables_order, 'E')) { + drush_set_error("DevDesktop usage is enabled, but variables_order does support environmental variables."); + drush_print("Define variables_order = \"EGPCS\" in $php_ini_file", 2); + drush_print(); + } + } + } + + /** + * Checks Drupal VM configuration. + */ + protected function checkDrupalVmConfig() { + if ($this->drupalVmEnabled) { + // @todo Verify that box directory exists and contains config. + // @todo Check config. + } + } + + /** + * Checks Behat configuration in local.yml. + * + * @return bool + */ + protected function checkBehatConfig() { + if (!file_exists($this->repoRoot . '/tests/behat/local.yml')) { + drush_set_error("tests/behat/local.yml is missing!"); + + drush_print("Run `blt setup:behat` to generate it from example.local.yml.", 2); + return FALSE; + } + + $this->behatDefaultLocalConfig = Yaml::parse(file_get_contents($this->repoRoot . '/tests/behat/local.yml')); + if ($this->drupalVmEnabled) { + $behat_drupal_root = $this->behatDefaultLocalConfig['local']['extensions']['Drupal\DrupalExtension']['drupal']['drupal_root']; + if (strstr($behat_drupal_root, '/var/www/')) { + drush_set_error("You have DrupalVM initialized, but drupal_root in tests/behat/local.yml does not reference the DrupalVM docroot."); + } + } + + $behat_base_url = $this->behatDefaultLocalConfig['local']['extensions']['Behat\MinkExtension']['base_url']; + if ($behat_base_url != $this->getUri()) { + drush_set_error("base_url in tests/behat/local.yml does not match the site URI. It is set to \"$behat_base_url\"."); + drush_print("Set base_url to {$this->getUri()}", 2); + } + } + + + /** + * Checks TravisCI configuration. + */ + protected function checkTravisCiConfig() { + // @todo Check that known hosts is set. + // @todo Check that deployment is enabled. + } + + /** + * Check that general CI configuration is set correctly. + */ + protected function checkCiConfig() { + if ($this->ciEnabled) { + if (empty($this->config['git']['remotes'])) { + drush_set_error("Git repositories are not defined in project.yml."); + drush_print("Add values for git.remotes to project.yml to enabled automated deployment.", 2); + } + } + } + + /** + * Checks that composer.json is configured correctly. + */ + protected function checkComposerConfig() { + if (!empty($this->composerJson['require-dev']['acquia/blt'])) { + drush_set_error("acquia/blt is defined as a development dependency in composer.json"); + drush_print("Move acquia/blt out of the require-dev object and into the require object in composer.json.", 2); + drush_print("This is necessary for BLT settings files to be available at runtime in production.", 2); + } + + $prestissimo_intalled = drush_shell_exec("composer global show | grep hirak/prestissimo"); + if (!$prestissimo_intalled) { + drush_set_error("prestissimo plugin for composer is not installed."); + drush_print("Run `composer global require hirak/prestissimo:^0.3` to install it.", 2); + drush_print("This will improve composer install/update performance by parallelizing the download of dependency information.", 2); + } + } + /** * Checks that caching is configured for local development. */ @@ -186,14 +575,37 @@ protected function checkCachingConfig() { } } + /** + * Check that the contributed modules directory exists. + */ protected function checkContribExists() { - if (!file_exists($this->statusTable['root'] . '/sites/all/modules/contrib')) { - drush_log("Contributed module dependencies are missing.", 'error'); - drush_print("Run `./task.sh setup:build:all to build all contributed dependencies.", 2); + if (!file_exists($this->docroot . '/sites/all/modules/contrib')) { + drush_set_error("Contributed module dependencies are missing."); + drush_print("Run `blt setup:build to build all contributed dependencies.", 2); drush_print(); } else { drush_log("Contributed module dependencies are present."); } } + + /** + * Checks that is configured correctly at a high level. + */ + protected function checkProjectYml() { + $deprecated_keys = [ + 'project.hash_salt', + 'project.profile.contrib', + 'project.vendor', + 'project.description', + 'project.themes', + ]; + + $config = new Data($this->config); + foreach ($deprecated_keys as $deprecated_key) { + if ($config->get($deprecated_key)) { + drush_log("The $deprecated_key key is deprecated. Please remove it from project.yml.", 'warning'); + } + } + } } diff --git a/template/.gitignore b/template/.gitignore index 433c0fc5b..c62def578 100644 --- a/template/.gitignore +++ b/template/.gitignore @@ -105,3 +105,8 @@ nbproject/* # DrupalVM .vagrant/ + +#Exports +*.gz +*.sql +*.zip