summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Pugh2017-11-17 17:08:41 (GMT)
committerJon Pugh2017-11-17 17:08:41 (GMT)
commitc20b7a1ea174d66bb69a262adaf0da7945657ee7 (patch)
treea83c813ea4ea94520369ec856f17c70379a90905
parentee30bc32886b9b80c39e6364658810593ef5d663 (diff)
Using BuilderAwareTrait to allow Robo-command style task() building in Provision and Context classes.
-rw-r--r--src/Context.php10
-rw-r--r--src/Provision.php14
-rw-r--r--src/Robo/ProvisionExecutor.php235
-rw-r--r--src/Robo/ProvisionTasks.php (renamed from src/ProvisionTasks.php)40
4 files changed, 259 insertions, 40 deletions
diff --git a/src/Context.php b/src/Context.php
index 5b594e3..4640b8f 100644
--- a/src/Context.php
+++ b/src/Context.php
@@ -10,6 +10,8 @@ use Aegir\Provision\Console\Config;
use Consolidation\AnnotatedCommand\CommandFileDiscovery;
use Drupal\Console\Core\Style\DrupalStyle;
use Psr\Log\LoggerInterface;
+use Robo\Common\BuilderAwareTrait;
+use Robo\Contract\BuilderAwareInterface;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\Processor;
use Symfony\Component\Filesystem\Exception\IOException;
@@ -24,9 +26,11 @@ use Symfony\Component\Yaml\Yaml;
*
* @package Aegir\Provision
*/
-class Context
+class Context implements BuilderAwareInterface
{
+ use BuilderAwareTrait;
+
/**
* @var string
* Name for saving aliases and referencing.
@@ -83,6 +87,10 @@ class Context
$this->application = $application;
$this->loadContextConfig($options);
$this->prepareServices();
+
+ if ($this->application) {
+ $this->setBuilder($this->application->provision->getBuilder());
+ }
}
/**
diff --git a/src/Provision.php b/src/Provision.php
index fe42446..fc2e38d 100644
--- a/src/Provision.php
+++ b/src/Provision.php
@@ -6,14 +6,18 @@ namespace Aegir\Provision;
use Aegir\Provision\Console\Config;
use Aegir\Provision\Commands\ExampleCommands;
+use Aegir\Provision\Robo\ProvisionExecutor;
+use Aegir\Provision\Robo\ProvisionTasks;
use League\Container\Container;
use League\Container\ContainerAwareInterface;
use League\Container\ContainerAwareTrait;
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerAwareTrait;
use Robo\Collection\CollectionBuilder;
+use Robo\Common\BuilderAwareTrait;
use Robo\Common\ConfigAwareTrait;
use Robo\Common\IO;
+use Robo\Contract\BuilderAwareInterface;
use Robo\Contract\ConfigAwareInterface;
use Robo\Contract\IOAwareInterface;
use Robo\Robo;
@@ -21,12 +25,13 @@ use Robo\Runner as RoboRunner;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
-class Provision implements ConfigAwareInterface, ContainerAwareInterface, LoggerAwareInterface, IOAwareInterface {
+class Provision implements ConfigAwareInterface, ContainerAwareInterface, LoggerAwareInterface, IOAwareInterface, BuilderAwareInterface {
const APPLICATION_NAME = 'Aegir Provision';
const VERSION = '4.x-dev';
const REPOSITORY = 'aegir-project/provision';
+ use BuilderAwareTrait;
use ConfigAwareTrait;
use ContainerAwareTrait;
use LoggerAwareTrait;
@@ -57,7 +62,7 @@ class Provision implements ConfigAwareInterface, ContainerAwareInterface, Logger
$this->setConfig($config);
$this->setInput($input);
$this->setOutput($output);
-
+
// Create Application.
$application = new Application(self::APPLICATION_NAME, self::VERSION, $this);
// $application->setConfig($consoleConfig);
@@ -74,6 +79,8 @@ class Provision implements ConfigAwareInterface, ContainerAwareInterface, Logger
$this->runner->setContainer($container);
$this->runner->setSelfUpdateRepository(self::REPOSITORY);
+
+ $this->setBuilder($container->get('builder'));
}
public function run(InputInterface $input, OutputInterface $output) {
@@ -96,7 +103,8 @@ class Provision implements ConfigAwareInterface, ContainerAwareInterface, Logger
$builder = new CollectionBuilder($tasks);
$tasks->setBuilder($builder);
$container->add('builder', $builder);
-
+ $container->add('executor', ProvisionExecutor::class)
+ ->withArgument('builder');
}
/**
diff --git a/src/Robo/ProvisionExecutor.php b/src/Robo/ProvisionExecutor.php
new file mode 100644
index 0000000..50d3ca6
--- /dev/null
+++ b/src/Robo/ProvisionExecutor.php
@@ -0,0 +1,235 @@
+<?php
+
+namespace Aegir\Provision\Robo;
+
+use GuzzleHttp\Client;
+use Psr\Log\LoggerAwareInterface;
+use Psr\Log\LoggerAwareTrait;
+use Robo\Collection\CollectionBuilder;
+use Robo\Common\ConfigAwareTrait;
+use Robo\Common\IO;
+use Robo\Contract\VerbosityThresholdInterface;
+use Robo\Robo;
+use Robo\Contract\ConfigAwareInterface;
+use Robo\Contract\IOAwareInterface;
+use Symfony\Component\Process\Process;
+
+/**
+ * A class for executing commands.
+ *
+ * This allows non-Robo-command classes to execute commands easily.
+ */
+class ProvisionExecutor implements ConfigAwareInterface, IOAwareInterface, LoggerAwareInterface {
+
+ use ConfigAwareTrait;
+ use IO;
+ use LoggerAwareTrait;
+
+ /**
+ * A copy of the Robo builder.
+ *
+ * @var \Aegir\Provision\Robo\ProvisionTasks
+ */
+ protected $builder;
+
+ /**
+ * Executor constructor.
+ *
+ * @param \Robo\Collection\CollectionBuilder $builder
+ * This is a copy of the collection builder, required for calling various
+ * Robo tasks from non-command files.
+ */
+ public function __construct(CollectionBuilder $builder) {
+ $this->builder = $builder;
+ }
+
+ /**
+ * Returns $this->builder.
+ *
+ * @return \Aegir\Provision\Robo\ProvisionTasks
+ * The builder.
+ */
+ public function getBuilder() {
+ return $this->builder;
+ }
+
+ /**
+ * Wrapper for taskExec().
+ *
+ * @param string $command
+ * The command to execute.
+ *
+ * @return \Robo\Task\Base\Exec
+ * The task. You must call run() on this to execute it!
+ */
+ public function taskExec($command) {
+ return $this->builder->taskExec($command);
+ }
+
+// /**
+// * Executes a drush command.
+// *
+// * @param string $command
+// * The command to execute, without "drush" prefix.
+// *
+// * @return \Robo\Common\ProcessExecutor
+// * The unexecuted process.
+// */
+// 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 */
+// $drush_alias = $this->getConfigValue('drush.alias');
+// if (!empty($drush_alias)) {
+// $drush_alias = "@$drush_alias";
+// }
+//
+// $command_string = "'$bin/drush' $drush_alias $command";
+//
+// if ($this->input()->hasOption('yes') && $this->input()->getOption('yes')) {
+// $command_string .= ' -y';
+// }
+//
+// $process_executor = Robo::process(new Process($command_string));
+//
+// return $process_executor->dir($this->getConfigValue('docroot'))
+// ->interactive(FALSE)
+// ->printOutput(TRUE)
+// ->printMetadata(TRUE)
+// ->setVerbosityThreshold(VerbosityThresholdInterface::VERBOSITY_VERY_VERBOSE);
+// }
+
+ /**
+ * Executes a command.
+ *
+ * @param string $command
+ * The command.
+ *
+ * @return \Robo\Common\ProcessExecutor
+ * The unexecuted command.
+ */
+ public function execute($command) {
+ /** @var \Robo\Common\ProcessExecutor $process_executor */
+ $process_executor = Robo::process(new Process($command));
+ return $process_executor->dir($this->getConfigValue('repo.root'))
+ ->printOutput(FALSE)
+ ->printMetadata(FALSE)
+ ->interactive(FALSE);
+ }
+
+ /**
+ * Kills all system processes that are using a particular port.
+ *
+ * @param string $port
+ * The port number.
+ */
+ public function killProcessByPort($port) {
+ $this->logger->info("Killing all processes on port '$port'...");
+ // This is allowed to fail.
+ // @todo Replace with standardized call to Symfony Process.
+ exec("command -v lsof && lsof -ti tcp:$port | xargs kill l 2>&1");
+ exec("pkill -f $port 2>&1");
+ }
+
+ /**
+ * Kills all system processes containing a particular string.
+ *
+ * @param string $name
+ * The name of the process.
+ */
+ public function killProcessByName($name) {
+ $this->logger->info("Killing all processing containing string '$name'...");
+ // This is allowed to fail.
+ // @todo Replace with standardized call to Symfony Process.
+ exec("ps aux | grep -i $name | grep -v grep | awk '{print $2}' | xargs kill -9 2>&1");
+ // exec("ps aux | awk '/$name/ {print $2}' 2>&1 | xargs kill -9");.
+ }
+
+ /**
+ * Waits until a given URL responds with a non-50x response.
+ *
+ * This does have a maximum timeout, defined in wait().
+ *
+ * @param string $url
+ * The URL to wait for.
+ */
+ public function waitForUrlAvailable($url) {
+ $this->wait([$this, 'checkUrl'], [$url], "Waiting for response from $url...");
+ }
+
+ /**
+ * Waits until a given callable returns TRUE.
+ *
+ * This does have a maximum timeout.
+ *
+ * @param callable $callable
+ * The method/function to wait for a TRUE response from.
+ * @param array $args
+ * Arguments to pass to $callable.
+ * @param string $message
+ * The message to display when this function is called.
+ *
+ * @return bool
+ * TRUE if callable returns TRUE.
+ *
+ * @throws \Exception
+ */
+ public function wait(callable $callable, array $args, $message = '') {
+ $maxWait = 60 * 1000;
+ $checkEvery = 1 * 1000;
+ $start = microtime(TRUE) * 1000;
+ $end = $start + $maxWait;
+
+ if (!$message) {
+ $method_name = is_array($callable) ? $callable[1] : $callable;
+ $message = "Waiting for $method_name() to return true.";
+ }
+
+ // For some reason we can't reuse $start here.
+ while (microtime(TRUE) * 1000 < $end) {
+ $this->logger->info($message);
+ try {
+ if (call_user_func_array($callable, $args)) {
+ return TRUE;
+ }
+ }
+ catch (\Exception $e) {
+ $this->logger->error($e->getMessage());
+ }
+ usleep($checkEvery * 1000);
+ }
+
+ throw new BltException("Timed out.");
+ }
+
+ /**
+ * Checks a URL for a non-50x response.
+ *
+ * @param string $url
+ * The URL to check.
+ *
+ * @return bool
+ * TRUE if URL responded with a non-50x response.
+ */
+ public function checkUrl($url) {
+ try {
+ $client = new Client();
+ $res = $client->request('GET', $url, [
+ 'connection_timeout' => 2,
+ 'timeout' => 2,
+ 'exceptions' => FALSE,
+ ]);
+ if ($res->getStatusCode() && substr($res->getStatusCode(), 0, 1) != '5') {
+ return TRUE;
+ }
+ else {
+ return FALSE;
+ }
+ }
+ catch (\Exception $e) {
+
+ }
+ return FALSE;
+ }
+
+}
diff --git a/src/ProvisionTasks.php b/src/Robo/ProvisionTasks.php
index f490118..144d598 100644
--- a/src/ProvisionTasks.php
+++ b/src/Robo/ProvisionTasks.php
@@ -1,6 +1,6 @@
<?php
-namespace Aegir\Provision;
+namespace Aegir\Provision\Robo;
use Consolidation\Config\ConfigInterface;
use League\Container\ContainerAwareInterface;
@@ -13,49 +13,17 @@ use Robo\Common\IO;
use Robo\Contract\BuilderAwareInterface;
use Robo\Contract\ConfigAwareInterface;
use Robo\Contract\IOAwareInterface;
-use Robo\Task\Base\loadTasks;
+use Robo\LoadAllTasks;
/**
* Base class for BLT Robo commands.
*/
-class ProvisionTasks implements ConfigAwareInterface, LoggerAwareInterface, BuilderAwareInterface, IOAwareInterface, ContainerAwareInterface
-{
+class ProvisionTasks implements ConfigAwareInterface, LoggerAwareInterface, BuilderAwareInterface, IOAwareInterface, ContainerAwareInterface {
use ContainerAwareTrait;
- use loadTasks;
-
+ use LoadAllTasks;
use ConfigAwareTrait;
// use InspectorAwareTrait;
use IO;
use LoggerAwareTrait;
-
- /**
- * Set the config reference
- *
- * @param ConfigInterface $config
- *
- * @return $this
- */
- public function setConfig(ConfigInterface $config) {
- $this->config = $config;
- }
-
- /**
- * Get the config reference
- *
- * @return ConfigInterface
- */
- public function getConfig() {
- return $this->config;
- }
-
- public function getBuilder()
- {
- return $this->builder;
- }
-
- public function setBuilder(CollectionBuilder $builder)
- {
- $this->builder = $builder;
- }
}