diff --git a/bin/blt b/bin/blt
index 274414a83..1c87f57ea 100755
--- a/bin/blt
+++ b/bin/blt
@@ -18,6 +18,7 @@ $robo_namespaces = [
'vm',
];
$robo_commands = [
+ 'doctor'
];
$params_string = implode(' ', array_slice($argv, 1));
diff --git a/phing/tasks/blt.xml b/phing/tasks/blt.xml
index 102155ce2..da5686ac3 100644
--- a/phing/tasks/blt.xml
+++ b/phing/tasks/blt.xml
@@ -63,25 +63,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Copying files from BLT's template into your project...
diff --git a/scripts/drupal-vm/post-provision.sh b/scripts/drupal-vm/post-provision.sh
index 86d9c5690..47318aa70 100755
--- a/scripts/drupal-vm/post-provision.sh
+++ b/scripts/drupal-vm/post-provision.sh
@@ -7,6 +7,8 @@ then
VAGRANT_MACHINE_NAME=$(grep vagrant_machine_name: "$CONFIG_FILE" | cut -d' ' -f 2)
REPO_ROOT=/var/www/${VAGRANT_MACHINE_NAME}
cd ${REPO_ROOT}
+else
+ echo "Could not find repo root!"
fi
# Add blt alias to front of .bashrc so that it applies to non-interactive shells.
diff --git a/src/Robo/Commands/Blt/DoctorCommand.php b/src/Robo/Commands/Blt/DoctorCommand.php
new file mode 100644
index 000000000..df639eaee
--- /dev/null
+++ b/src/Robo/Commands/Blt/DoctorCommand.php
@@ -0,0 +1,90 @@
+getInspector()->isDrupalVmLocallyInitialized() && $this->getInspector()->isDrupalVmBooted()) {
+ $result = $this->executeDoctorInsideVm();
+ if ($result->wasSuccessful()) {
+ return $result;
+ }
+ }
+
+ // Try BLT doctor with default alias. This might be a Drupal VM alias.
+ $alias = $this->getConfigValue('drush.alias');
+ $result = $this->executeDoctorOnHost($alias);
+
+ // If default alias failed, try again using @self alias.
+ if (!$result->wasSuccessful() && $alias != 'self') {
+ $this->logger->warning("Unable to run the doctor using @$alias. Trying with @self...");
+ $this->executeDoctorOnHost('self');
+ }
+
+ return $result;
+ }
+
+ /**
+ * Executes `blt doctor` inside Drupal VM.
+ *
+ * @return \Robo\Result
+ * The command result.
+ */
+ protected function executeDoctorInsideVm() {
+ $drupal_vm_config = Yaml::parse(file_get_contents($this->getConfigValue('repo.root') . '/box/config.yml'));
+ $repo_root = $drupal_vm_config['vagrant_synced_folders'][0]['destination'];
+ $this->say("Drupal VM was detected. Running blt doctor inside of VM...");
+ $command = "cd $repo_root && $repo_root/vendor/bin/drush cc drush && $repo_root/vendor/bin/drush --include=$repo_root/vendor/acquia/blt/drush blt-doctor -r $repo_root/docroot";
+
+ return $this->executeCommandInDrupalVm($command);
+ }
+
+ /**
+ * Executes a command inside of Drupal VM.
+ *
+ * @param string $command
+ * The command to execute.
+ *
+ * @return \Robo\Result
+ * The command result.
+ */
+ protected function executeCommandInDrupalVm($command) {
+ $result = $this->taskExec("vagrant exec '$command'")
+ ->dir($this->getConfigValue('repo.root'))
+ ->detectInteractive()
+ ->run();
+
+ return $result;
+ }
+
+ /**
+ * Executes `blt doctor` on host machine.
+ *
+ * @return \Robo\Result
+ * The command result.
+ */
+ protected function executeDoctorOnHost($alias) {
+ $drush_bin = $this->getConfigValue('composer.bin') . '/drush';
+ $include_dir = $this->getConfigValue('blt.root') . '/drush';
+ $result = $this->taskExec("$drush_bin @$alias --include=$include_dir blt-doctor")
+ ->dir($this->getConfigValue('docroot'))
+ ->detectInteractive()
+ ->run();
+
+ return $result;
+ }
+
+}
diff --git a/src/Robo/Commands/BltReleaseCommand.php b/src/Robo/Commands/BltReleaseCommand.php
index f413ff42a..a5dfe87a6 100644
--- a/src/Robo/Commands/BltReleaseCommand.php
+++ b/src/Robo/Commands/BltReleaseCommand.php
@@ -25,6 +25,8 @@ class BltReleaseCommand extends BltTasks {
*
* @option $update-changelog Update CHANGELOG.md. Defaults to true.
*
+ * @hidden
+ *
* @return int
* The CLI status code.
*/
diff --git a/src/Robo/Commands/Setup/BuildCommand.php b/src/Robo/Commands/Setup/BuildCommand.php
index 53290c902..db8f260b3 100644
--- a/src/Robo/Commands/Setup/BuildCommand.php
+++ b/src/Robo/Commands/Setup/BuildCommand.php
@@ -15,9 +15,11 @@ class BuildCommand extends BltTasks {
* Install dependencies, builds docroot, installs Drupal.
*
* @command setup
+ *
+ * @aliases setup:all
*/
public function setup() {
- $this->say("Setting up local environment");
+ $this->say("Setting up local environment...");
$status_code = $this->invokeCommands([
'setup:build',
'setup:hash-salt',
@@ -107,7 +109,7 @@ public function build() {
}
/**
- * Installs composer dependencies.
+ * Installs Composer dependencies.
*
* @command setup:composer:install
*/
diff --git a/src/Robo/Commands/Setup/CloudHooksCommand.php b/src/Robo/Commands/Setup/CloudHooksCommand.php
index 3f8b4225b..2fb07c8d5 100644
--- a/src/Robo/Commands/Setup/CloudHooksCommand.php
+++ b/src/Robo/Commands/Setup/CloudHooksCommand.php
@@ -10,7 +10,7 @@
class CloudHooksCommand extends BltTasks {
/**
- * Installs Acquia cloud hooks to hooks.
+ * Installs Acquia cloud hooks.
*
* @command setup:cloud-hooks
*/
diff --git a/src/Robo/Commands/Setup/ConfigCommand.php b/src/Robo/Commands/Setup/ConfigCommand.php
index 57ecc5264..6069baf0c 100644
--- a/src/Robo/Commands/Setup/ConfigCommand.php
+++ b/src/Robo/Commands/Setup/ConfigCommand.php
@@ -21,7 +21,7 @@ public function update() {
}
/**
- * Import configuration from the config directory.
+ * Imports configuration from the config directory according to cm.strategy.
*
* @command setup:config-import
*/
@@ -52,49 +52,18 @@ public function import() {
switch ($strategy) {
case 'core-only':
- if (file_exists($this->getConfigValue("cm.core.dirs.$cm_core_key.path") . '/core.extension.yml')) {
- $task->exec("drush @$drush_alias config-import $cm_core_key --yes");
- }
+ $this->importCoreOnly($task, $drush_alias, $cm_core_key);
break;
case 'config-split':
- // We cannot use ${cm.core.dirs.${cm.core.key}.path} here because
- // cm.core.key may be 'vcs', which does not have a path defined in
- // BLT config. Perhaps this should be refactored.
- $core_config_file = $this->getConfigValue('docroot') . '/' . $this->getConfigValue('cm.core.dirs.sync.path') . '/core.extension.yml';
- if (file_exists($core_config_file)) {
- $task->exec("drush @$drush_alias pm-enable config_split --yes");
- $task->exec("drush @$drush_alias config-import sync --yes");
- }
+ $this->importConfigSplit($task, $drush_alias);
break;
case 'features':
- $task->exec("drush @$drush_alias config-import $cm_core_key --partial --yes");
- if ($this->getConfig()->has('cm.features.bundle"')) {
- $task->exec("drush @$drush_alias pm-enable features --yes");
- // Clear drush caches to register features drush commands.
- $task->exec("drush cc drush --yes");
- foreach ($this->getConfigValue('cm.features.bundle') as $bundle) {
- $task->exec("drush @$drush_alias features-revert-all --bundle=$bundle --yes");
- // Revert all features again!
- // @see https://www.drupal.org/node/2851532
- $task->exec("drush @$drush_alias features-revert-all --bundle=$bundle --yes");
- }
- }
- if ($this->getConfigValue('cm.features.no-overrides')) {
- $this->say("Checking for features overrides...");
- if ($this->getConfig()->has('cm.features.bundle')) {
- foreach ($this->getConfigValue('cm.features.bundle') as $bundle) {
- $features_overriden = $task->exec("drush fl --bundle=${bundle} | grep -Ei '(changed|conflicts|added)( *)$");
- // @todo emit:
- // A feature in the ${bundle} bundle is overridden. You must
- // re-export this feature to incorporate the changes.
- // @todo throw Exception.
- }
- }
- }
+ $this->importFeatures($task, $drush_alias, $cm_core_key);
break;
}
+
$task->exec("drush @$drush_alias cache-rebuild");
$task->run();
@@ -103,4 +72,67 @@ public function import() {
}
}
+ /**
+ * Import configuration using core config management only.
+ *
+ * @param $task
+ * @param $drush_alias
+ * @param $cm_core_key
+ */
+ protected function importCoreOnly($task, $drush_alias, $cm_core_key) {
+ if (file_exists($this->getConfigValue("cm.core.dirs.$cm_core_key.path") . '/core.extension.yml')) {
+ $task->exec("drush @$drush_alias config-import $cm_core_key --yes");
+ }
+ }
+
+ /**
+ * Import configuration using config_split module.
+ *
+ * @param $task
+ * @param $drush_alias
+ */
+ protected function importConfigSplit($task, $drush_alias) {
+ // We cannot use ${cm.core.dirs.${cm.core.key}.path} here because
+ // cm.core.key may be 'vcs', which does not have a path defined in
+ // BLT config. Perhaps this should be refactored.
+ $core_config_file = $this->getConfigValue('docroot') . '/' . $this->getConfigValue('cm.core.dirs.sync.path') . '/core.extension.yml';
+ if (file_exists($core_config_file)) {
+ $task->exec("drush @$drush_alias pm-enable config_split --yes");
+ $task->exec("drush @$drush_alias config-import sync --yes");
+ }
+ }
+
+ /**
+ * Import configuration using features module.
+ * @param $task
+ * @param $drush_alias
+ * @param $cm_core_key
+ */
+ protected function importFeatures($task, $drush_alias, $cm_core_key) {
+ $task->exec("drush @$drush_alias config-import $cm_core_key --partial --yes");
+ if ($this->getConfig()->has('cm.features.bundle"')) {
+ $task->exec("drush @$drush_alias pm-enable features --yes");
+ // Clear drush caches to register features drush commands.
+ $task->exec("drush cc drush --yes");
+ foreach ($this->getConfigValue('cm.features.bundle') as $bundle) {
+ $task->exec("drush @$drush_alias features-revert-all --bundle=$bundle --yes");
+ // Revert all features again!
+ // @see https://www.drupal.org/node/2851532
+ $task->exec("drush @$drush_alias features-revert-all --bundle=$bundle --yes");
+ }
+ }
+ if ($this->getConfigValue('cm.features.no-overrides')) {
+ $this->say("Checking for features overrides...");
+ if ($this->getConfig()->has('cm.features.bundle')) {
+ foreach ($this->getConfigValue('cm.features.bundle') as $bundle) {
+ $features_overriden = $task->exec("drush fl --bundle=${bundle} | grep -Ei '(changed|conflicts|added)( *)$");
+ // @todo emit:
+ // A feature in the ${bundle} bundle is overridden. You must
+ // re-export this feature to incorporate the changes.
+ // @todo throw Exception.
+ }
+ }
+ }
+ }
+
}
diff --git a/src/Robo/Commands/Setup/SettingsCommand.php b/src/Robo/Commands/Setup/SettingsCommand.php
index 8d2c25b23..2bd2f56e3 100644
--- a/src/Robo/Commands/Setup/SettingsCommand.php
+++ b/src/Robo/Commands/Setup/SettingsCommand.php
@@ -55,8 +55,9 @@ public function generateSiteConfigFiles() {
$this->taskFilesystemStack()
->chmod($multisite_dir, 0777)
+ // @todo Might need to check that this file exists before chmoding it.
+ ->chmod($project_settings_file, 0777)
->copy($project_default_settings_file, $project_settings_file)
- ->copy($project_settings_file, 0777)
->copy($blt_local_settings_file, $default_local_settings_file)
->copy($default_local_settings_file, $project_local_settings_file)
->copy($blt_local_drush_file, $default_local_drush_file)
@@ -87,7 +88,7 @@ public function generateSiteConfigFiles() {
* @command setup:behat
*/
public function behat() {
- $this->say("Generating Behat configuration files");
+ $this->say("Generating Behat configuration files...");
$this->taskFilesystemStack()
->copy($this->defaultBehatLocalConfigFile, $this->projectBehatLocalConfigFile)
->stopOnFail()
@@ -97,7 +98,7 @@ public function behat() {
}
/**
- * Installs git hooks to local .git/hooks directory.
+ * Installs BLT git hooks to local .git/hooks directory.
*
* @command setup:git-hooks
*/
@@ -117,7 +118,7 @@ public function gitHooks() {
*/
protected function installGitHook($hook) {
if ($this->getConfigValue('git.hooks.' . $hook)) {
- $this->say("Installing $hook git hook");
+ $this->say("Installing $hook git hook...");
$source = $this->getConfigValue('git.hooks.' . $hook) . "/$hook";
$dest = $this->getConfigValue('repo.root') . "/.git/hooks/$hook";
diff --git a/src/Robo/Commands/Vm/VmCommand.php b/src/Robo/Commands/Vm/VmCommand.php
index 7fc86d7f4..e2691bbea 100644
--- a/src/Robo/Commands/Vm/VmCommand.php
+++ b/src/Robo/Commands/Vm/VmCommand.php
@@ -45,6 +45,8 @@ public function initialize() {
*
* @command vm
*
+ * @aliases vm:all
+ *
* @options no-boot
*/
public function vm($options = ['no-boot' => FALSE]) {
@@ -137,13 +139,13 @@ public function config() {
$this->getConfig()->expandFileProperties($this->projectDrupalVmConfigFile);
- $this->say("BLT has created default configuration for your Drupal VM");
- $this->say("The configuration file is {$this->projectDrupalVmConfigFile}.");
+ $this->say("BLT has created default configuration for your Drupal VM.");
+ $this->say("The configuration file is {$this->projectDrupalVmConfigFile}.");
- $this->say("To customize the VM, follow the Quick Start Guide in Drupal VM's README.");
- $this->say("https://github.com/geerlingguy/drupal-vm#quick-start-guide");
+ $this->say("To customize the VM, follow the Quick Start Guide in Drupal VM's README:");
+ $this->say("https://github.com/geerlingguy/drupal-vm#quick-start-guide");
- $this->say("To run drush commands against the VM, use the {$this->drupalVmAlias} alias.");
+ $this->say("To run drush commands against the VM, use the @{$this->drupalVmAlias} alias.");
$this->yell("From now on, please use vagrant commands to manage your virtual machine.");
}
@@ -166,8 +168,8 @@ protected function localInitialize() {
$yaml = Yaml::dump($contents, 3, 2);
file_put_contents($filename, $yaml);
- $this->say("$filename was modified");
- $this->say("BLT will now use @{$contents['drush']['default_alias']} as the default drush alias for all commands.");
+ $this->say("$filename was modified.");
+ $this->say("BLT will now use @{$contents['drush']['default_alias']} as the default drush alias for all commands.");
}
/**
@@ -176,11 +178,24 @@ protected function localInitialize() {
protected function boot() {
$confirm = $this->confirm("Do you want to boot Drupal VM?", TRUE);
if ($confirm) {
- $this->say("In future, run `vagrant up` to boot the VM");
- $this->taskExec("vagrant up")
+ $this->say("In future, run vagrant up to boot the VM");
+ $result = $this->taskExec("vagrant up")
->dir($this->getConfigValue('repo.root'))
->printOutput(TRUE)
->run();
+ if (!$result->wasSuccessful()) {
+ $this->logger->error("Drupal VM failed to boot. Read Drupal VM's previous output for more information.");
+ $confirm = $this->confirm("Do you want to try to re-provision the VM? Sometimes this works.", TRUE);
+ if ($confirm) {
+ $result = $this->taskExec("vagrant provision")
+ ->dir($this->getConfigValue('repo.root'))
+ ->printOutput(TRUE)
+ ->run();
+ }
+ }
+ else {
+ $this->yell("Drupal VM booted successfully. Please use vagrant commands to interact with your VM from now on.");
+ }
}
}
@@ -229,6 +244,11 @@ protected function checkRequirements() {
$this->logger->warning("The vagrant-hostsupdater plugin is not installed! Attempting to install it...");
$this->taskExec("vagrant plugin install vagrant-hostsupdater")->run();
}
+ $vagrant_exec_plugin_installed = (bool) $this->taskExec("vagrant plugin list | grep vagrant-exec")->run()->getOutputData();
+ if ($vagrant_exec_plugin_installed) {
+ $this->logger->warning("The vagrant-exec plugin is not installed! Attempting to install it...");
+ $this->taskExec("vagrant plugin install vagrant-exec")->run();
+ }
}
}
diff --git a/src/Robo/Common/Executor.php b/src/Robo/Common/Executor.php
index 63c91c4bb..79217eaab 100644
--- a/src/Robo/Common/Executor.php
+++ b/src/Robo/Common/Executor.php
@@ -76,7 +76,8 @@ public function drush($command) {
// @todo Set to silent if verbosity is less than very verbose.
$bin = $this->getConfigValue('composer.bin');
/** @var \Robo\Common\ProcessExecutor $process_executor */
- $process_executor = Robo::process(new Process("$bin/drush $command"));
+ $drush_alias = $this->getConfigValue('drush.alias');
+ $process_executor = Robo::process(new Process("$bin/drush @$drush_alias $command"));
return $process_executor->dir($this->getConfigValue('docroot'))
->interactive(FALSE)
->printOutput(FALSE)
diff --git a/src/Robo/Inspector/Inspector.php b/src/Robo/Inspector/Inspector.php
index b031dbc6a..602c58419 100644
--- a/src/Robo/Inspector/Inspector.php
+++ b/src/Robo/Inspector/Inspector.php
@@ -224,6 +224,23 @@ public function isDrupalVmLocallyInitialized() {
return $drush_local_alias == $expected_vm_alias;
}
+ /**
+ * Determines if Drupal VM is booted.
+ *
+ * @return bool
+ * TRUE if Drupal VM is booted.
+ */
+ public function isDrupalVmBooted() {
+ $result = $this->executor->execute("vagrant status")
+ ->printOutput(FALSE)
+ ->printMetadata(FALSE)
+ ->interactive(FALSE)
+ ->run();
+ $output = $result->getOutputData();
+
+ return !strstr($output, "poweroff");
+ }
+
/**
* Determines if the current PHP process is being executed inside VM.
*