Skip to content

Commit

Permalink
Allow aws commands to use aws environment variables for auth (#223)
Browse files Browse the repository at this point in the history
* Allow aws commands to use aws environment variables for auth

Do not assume credential file creation will have valid credentials.
Begin to move away from deprecated ->io constructs.
Improve flow of event signaling in refresh tasks
Streamline s3 request configuration; remove duplicate calls
Don't run cron or cache clears on a site with no data
Persist credentials through restarts

Resolves #222
  • Loading branch information
apotek authored Oct 31, 2024
1 parent b44323c commit 47db092
Show file tree
Hide file tree
Showing 5 changed files with 239 additions and 130 deletions.
2 changes: 1 addition & 1 deletion phpstan.neon
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
parameters:
checkMissingIterableValueType: false
customRulesetUsed: true
ignoreErrors:
- identifier: missingType.iterableValue
- message: '#\Call to deprecated method io\(\) of class Robo\\Tasks#'
paths:
- 'src/'
Expand Down
138 changes: 85 additions & 53 deletions src/Robo/Plugin/Commands/DevelopmentModeCommands.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Robo\Exception\TaskException;
use Robo\Result;
use Robo\ResultData;
use Robo\Symfony\ConsoleIO;
use Robo\Tasks;
use Symfony\Component\Yaml\Yaml;
use Usher\Robo\Plugin\Enums\LocalDevEnvironmentTypes;
Expand Down Expand Up @@ -76,11 +77,13 @@ public function __construct()
* @aliases magic
*/
public function devRefresh(
ConsoleIO $io,
string $siteName = 'default',
array $options = ['db' => '', 'environment-type' => 'ddev'],
): Result {
): Result|ResultData {
['db' => $dbPath, 'environment-type' => $environmentType] = $options;
return $this->devRefreshDrupal(
io: $io,
environmentType: LocalDevEnvironmentTypes::from($environmentType),
siteName: $siteName,
databasePath: $dbPath,
Expand All @@ -103,20 +106,28 @@ public function devRefresh(
* Specify alternative (supported) environment type. See LocalDevEnvironmentTypes enum.
*/
public function devRefreshAll(
ConsoleIO $io,
array $options = ['skip-sites' => '', 'environment-type' => 'ddev']
): Result {
): Result|ResultData {
['skip-sites' => $skipSites, 'environment-type' => $environmentType] = $options;
$siteNames = $this->getAllSiteNames();
$result = null;
$result = ResultData::message('No sites were refreshed because all sites were configured to be skipped.');
foreach ($siteNames as $siteName) {
if (in_array($siteName, explode(separator: ',', string: (string) $skipSites), true)) {
continue;
}
/** @var Result|ResultData $result */
$result = $this->devRefreshDrupal(
$io,
environmentType: LocalDevEnvironmentTypes::from($environmentType),
siteName: $siteName,
);
if ($result->wasCancelled()) {
$io->say("Cancelling the refresh for all sites.");
return $result;
}
}

return $result;
}

Expand All @@ -128,34 +139,50 @@ public function devRefreshAll(
* @option db
* Provide a path to a database dump to be used instead of downloading the latest dump.
*/
public function databaseRefreshDdev(string $siteName = 'default', array $options = ['db' => '']): Result
{
// @todo: Update this method to not be DDEV specific.
$this->io()->title('DDEV database refresh.');
public function databaseRefreshDdev(
ConsoleIO $io,
string $siteName = 'default',
array $options = ['db' => '']
): Result|ResultData {
$io->title('DDEV database refresh.');

['db' => $dbPath] = $options;
// Track whether a database path was provided by the user or not.
$dbPathProvidedByUser = $dbPath !== '';

if (!$dbPathProvidedByUser) {
$dbPath = $this->databaseDownload($siteName);
try {
$dbPath = $this->databaseDownload($io, $siteName);
} catch (TaskException $e) {
$resultData = new ResultData(ResultData::EXITCODE_ERROR, $e->getMessage());
$io->yell("$siteName: No database configured. Download/import skipped.");
// @todo: Should we run a site-install by default? The "common"
// site ends up here, but we could change that.
return $resultData;
}
// If we don't have a file path string here, the action was
// cancelled and we should respond with the cancellation.
if (!is_string($dbPath)) {
return $dbPath;
}
}

$this->io()->section("refreshing $siteName database.");
$this->say("Dropping existing database for $siteName");
$io->section("refreshing $siteName database.");
$io->say("Dropping existing database for $siteName");
$this->taskExec('drush')
->arg('sql:drop')
->option('uri', $siteName)
->option('yes')
->run();
$this->say("Importing $dbPath");
$io->say("Importing $dbPath");
$this->_exec("zcat '$dbPath' | drush sql:cli --uri=$siteName");
// If a database was downloaded as part of this process, delete it.
if (!$dbPathProvidedByUser) {
$this->deleteDatabase($dbPath);
}

return $this->drushDeployWith(
io: $io,
localEnvironmentType: LocalDevEnvironmentTypes::DDEV,
siteDir: $siteName,
);
Expand All @@ -164,23 +191,24 @@ public function databaseRefreshDdev(string $siteName = 'default', array $options
/**
* Refresh database on Tugboat.
*/
public function databaseRefreshTugboat(): ResultData
public function databaseRefreshTugboat(ConsoleIO $io): ResultData
{
$this->io()->title('refresh tugboat databases.');
$io->title('refresh tugboat databases.');
$resultData = new ResultData();

foreach (array_keys($this->getAllSitesConfig()) as $siteName) {
$dbPath = '';
try {
$dbPath = $this->databaseDownload($siteName);
$dbPath = $this->databaseDownload($io, $siteName);
} catch (TaskException $e) {
$this->yell("$siteName: No database configured. Download/import skipped.");
$io->yell("$siteName: No database configured. Download/import skipped.");
$resultData->append($e->getMessage());
// @todo: Should we run a site-install by default?
// @todo: Should we run a site-install by default? The "common"
// site ends up here, but we could change that.
continue;
}
if (!is_string($dbPath) || $dbPath === '') {
$this->yell("'$siteName' database path not found.");
$io->yell("'$siteName' database path not found.");
$resultData->append("'$siteName' database path not found.");
continue;
}
Expand All @@ -198,7 +226,7 @@ public function databaseRefreshTugboat(): ResultData
->option('-e', "drop database if exists $dbName; create database $dbName;")
->run();
$resultData->append($taskResult);
$this->io()->section("import $siteName database.");
$io->section("import $siteName database.");
$taskResult = $this->taskExec("zcat $dbPath | $dbDriver -h mariadb -u tugboat -ptugboat $dbName")
->run();
$resultData->append($taskResult);
Expand All @@ -216,16 +244,17 @@ public function databaseRefreshTugboat(): ResultData
* @aliases uli
*
* @param string $environmentType
* Specify local development enviroment: ddev. This value is a string instead of LocalDevEnvironmentTypes since
* Specify local development environment: ddev. This value is a string instead of LocalDevEnvironmentTypes since
* it is a public command that can be called from the command line.
* @param string $siteDir
* The Drupal site directory name.
*/
public function drupalLoginLink(
ConsoleIO $io,
string $environmentType,
string $siteDir = 'default',
): Result {
$this->io()->section("create login link.");
$io->section("create login link.");
$uid = $this->getDrupalSiteAdminUid(siteName: $siteDir);
if ($environmentType === 'ddev') {
return $this->taskExec('drush')
Expand Down Expand Up @@ -254,22 +283,22 @@ public function drupalLoginLink(
*
* @option boolean $yes Default answers to yes.
* @aliases fedd
*
* @return \Robo\Result
* The result of the set of tasks.
*/
public function frontendDevDisable(string $siteDir = 'default', array $opts = ['yes|y' => false])
{
public function frontendDevDisable(
ConsoleIO $io,
string $siteDir = 'default',
array $opts = ['yes|y' => false]
): Result|ResultData {
$devSettingsPath = "$this->drupalRoot/sites/$siteDir/settings.local.php";
if (!$opts['yes']) {
$this->yell("This command will overwrite any customizations you have made to $devSettingsPath and
$io->yell("This command will overwrite any customizations you have made to $devSettingsPath and
$this->devServicesPath.");
$yes = $this->io()->confirm('This command is destructive. Do you wish to continue?');
$yes = $io->confirm('This command is destructive. Do you wish to continue?');
if (!$yes) {
return Result::cancelled();
}
}
$this->io()->title('disabling front-end development mode.');
$io->title('disabling front-end development mode.');
return $this->collectionBuilder()
->taskFilesystemStack()
->remove($devSettingsPath)
Expand All @@ -281,23 +310,26 @@ public function frontendDevDisable(string $siteDir = 'default', array $opts = ['
* Refreshes a development environment based upon the Drupal version.
*/
protected function devRefreshDrupal(
ConsoleIO $io,
LocalDevEnvironmentTypes $environmentType,
string $siteName = 'default',
string $databasePath = '',
): Result {
$this->io()->title('development environment refresh. 🦄✨');
$result = $this->taskComposerInstall()->run();

): Result|ResultData {
$io->title('development environment refresh. 🦄✨');
$this->taskComposerInstall()->run();
// There isn't a great way to call a command in one class from another.
// https://github.com/consolidation/Robo/issues/743
// For now, it seems like calling robo from within robo works.
$result = $this->taskExec("composer robo theme:build $siteName")
$this->taskExec("composer robo theme:build $siteName")
->run();
$result = $this->frontendDevEnable($siteName, ['yes' => true]);

$result = $this->databaseRefreshDdev(siteName: $siteName, options: ['db' => $databasePath]);
$this->frontendDevEnable($io, $siteName, ['yes' => true]);
/** @var Result|ResultData $result */
$result = $this->databaseRefreshDdev($io, siteName: $siteName, options: ['db' => $databasePath]);
if ($result->wasCancelled() || $result->getExitCode() !== ResultData::EXITCODE_OK) {
return $result;
}

return $this->drupalLoginLink($environmentType->value, $siteName);
return $this->drupalLoginLink($io, $environmentType->value, $siteName);
}

/**
Expand All @@ -306,10 +338,11 @@ protected function devRefreshDrupal(
* @see https://www.drush.org/deploycommand
*/
protected function drushDeployWith(
ConsoleIO $io,
LocalDevEnvironmentTypes $localEnvironmentType,
string $siteDir = 'default',
): Result {
$this->io()->section('drush deploy.');
$io->section('drush deploy.');
if (!class_exists(\Drush\Commands\core\DeployCommands::class)) {
throw new TaskException(
$this,
Expand Down Expand Up @@ -341,30 +374,30 @@ protected function drushDeployWith(
*
* @option boolean $yes Default answers to yes.
* @aliases fede
*
* @return \Robo\Result
* The result of the set of tasks.
*/
public function frontendDevEnable(string $siteDir = 'default', array $opts = ['yes|y' => false])
{
public function frontendDevEnable(
ConsoleIO $io,
string $siteDir = 'default',
array $opts = ['yes|y' => false],
): Result|ResultData {
$devSettingsPath = "$this->drupalRoot/sites/$siteDir/settings.local.php";

if (!$opts['yes']) {
$this->yell("This command will overwrite any customizations you have made to $devSettingsPath and
$io->yell("This command will overwrite any customizations you have made to $devSettingsPath and
$this->devServicesPath.");
$yes = $this->io()->confirm('This command is destructive. Do you wish to continue?');
$yes = $io->confirm('This command is destructive. Do you wish to continue?');
if (!$yes) {
return Result::cancelled();
}
}

$this->io()->title('enabling front-end development mode.');
$this->say("copying settings.local.php and development.services.yml into sites/$siteDir.");
$io->title('enabling front-end development mode.');
$io->say("copying settings.local.php and development.services.yml into sites/$siteDir.");

// Copy the example local settings file.
$example_local_settings_file = "$this->drupalRoot/sites/example.settings.local.php";
if (file_exists($example_local_settings_file)) {
$result = $this->taskFilesystemStack()
$this->taskFilesystemStack()
->copy($example_local_settings_file, $devSettingsPath)
->run();
} else {
Expand All @@ -376,7 +409,7 @@ public function frontendDevEnable(string $siteDir = 'default', array $opts = ['y
// Copy the development services file.
$development_services_file = "$this->drupalRoot/sites/development.services.yml";
if (file_exists($development_services_file)) {
$result = $this->taskFilesystemStack()
$this->taskFilesystemStack()
->copy($development_services_file, $this->devServicesPath, true)
->run();
} else {
Expand All @@ -386,17 +419,17 @@ public function frontendDevEnable(string $siteDir = 'default', array $opts = ['y
);
}

$this->say("optimizing twig for front-end development in development services yml config.");
$io->say("optimizing twig for front-end development in development services yml config.");
$devServices = Yaml::parseFile($this->devServicesPath);
$devServices['parameters']['twig.config'] = [
'debug' => true,
'auto_reload' => true,
'cache' => false,
];
$this->writeYaml($this->devServicesPath, $devServices);
$this->say("disabling render and dynamic_page_cache in settings.local.php.");
$io->say("disabling render and dynamic_page_cache in settings.local.php.");
// https://github.com/consolidation/robo/issues/1059#issuecomment-967732068
$result = $this->collectionBuilder()
return $this->collectionBuilder()
->taskReplaceInFile($devSettingsPath)
->from('/sites/development.services.yml')
->to("/sites/fe.development.services.yml")
Expand All @@ -417,6 +450,5 @@ public function frontendDevEnable(string $siteDir = 'default', array $opts = ['y
->line(' */')
->line('$config[\'advagg.settings\'][\'enabled\'] = FALSE;')
->run();
return $result;
}
}
2 changes: 1 addition & 1 deletion src/Robo/Plugin/Commands/ThemeCommands.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public function themeBuild(string $siteName = 'default'): Result
try {
$themeBuildConfiguration = $this->getSiteConfigItem('theme_build', $siteName);
} catch (TaskException) {
$this->say("'$siteName' theme_build confguration not set.");
$this->say("'$siteName' theme_build configuration not set.");
return $this->taskExec('echo skipping')->run();
}
foreach ($themeBuildConfiguration as $themeConfig) {
Expand Down
Loading

0 comments on commit 47db092

Please sign in to comment.