Skip to content
Snippets Groups Projects
Commit 8c69572d authored by jurgenhaas's avatar jurgenhaas
Browse files

docker/l3d#58 Move project settings out of composer.json

parent 7b0ef1e2
No related branches found
No related tags found
No related merge requests found
ahoyapi: v2
commands:
d4d:
imports:
- ahoy.yml
usage: Docker for Drupal
live:
imports:
- ahoy.live.yml
usage: Interact with the live site
debug:
imports:
- ahoy.debug.yml
usage: PHP debugging
......@@ -27,10 +27,8 @@
"ext-json": "*",
"php": ">=7.2",
"composer-plugin-api": "^1||^2",
"lakedrops/composer-json-utils": "^1.5.0",
"lakedrops/docker-traefik": "^1.2.0",
"lakedrops/dotenv": "^1.2.2",
"twig/twig": "^1.23.1"
"lakedrops/composer-json-utils": "^1.7||dev-master",
"lakedrops/docker-traefik": "^1.3||dev-master"
},
"require-dev": {
"composer/composer": "^1||^2",
......@@ -44,22 +42,6 @@
}
},
"extra": {
"class": "LakeDrops\\Docker4Drupal\\Plugin",
"lakedrops": {
"ahoy": {
"d4d": {
"usage": "Docker for Drupal",
"imports": ["ahoy.yml"]
},
"live": {
"usage": "Interact with the live site",
"imports": ["ahoy.live.yml"]
},
"debug": {
"usage": "PHP debugging",
"imports": ["ahoy.debug.yml"]
}
}
}
"class": "LakeDrops\\Docker4Drupal\\Plugin"
}
}
......@@ -4,12 +4,9 @@ namespace LakeDrops\Docker4Drupal;
use Exception;
use LakeDrops\Component\Composer\BaseHandler;
use LakeDrops\Component\Dotenv\Dotenv;
use LakeDrops\DockerTraefik\Traefik;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Yaml\Yaml;
use Twig_Environment;
use Twig_Loader_Array;
/**
* Class Handler.
......@@ -19,36 +16,154 @@ use Twig_Loader_Array;
class Handler extends BaseHandler {
/**
* @var array
* {@inheritdoc}
*/
protected $options;
public function configId(): string {
return 'docker4drupal';
}
/**
* {@inheritdoc}
*/
protected function configDefault(): array {
$projectname = getenv('COMPOSE_PROJECT_NAME');
if (empty($projectname)) {$projectname = str_replace([' ', '-', '_', '.'], '', basename(getcwd()));
$this->env->put('COMPOSE_PROJECT_NAME', $projectname);
}
$options = [
'projectname' => $projectname,
'ci_home' => '/home/gitlab-runner',
'docker0' => [
'ip' => ($this->isCiContext() || $this->isLocalDevMode()) ?
$this->getDockerGateway() :
$this->getLocalIpv4('docker0'),
],
'live' => [
'root' => '',
'uri' => '',
'host' => '',
'user' => $this->env->receive('live_host_username', 'Remote username for host of the live site', getenv('USER')),
],
'drush' => [
'sql' => [
'tables' => [
'structure' => [
'cache',
'cachetags',
'cache_*',
'history',
'search_*',
'sessions',
'watchdog',
],
'skip' => [
'migration_*',
],
],
],
],
'drupal' => [
'version' => '8',
],
'php' => [
'version' => $this->env->receiveGlobal('PHP_VERSION', 'PHP version', '7.3'),
'xdebug' => $this->env->receiveGlobal('PHP_DEBUG', 'PHP debug', '0'),
],
'webserver' => [
'type' => 'apache',
'overwriteconfig' => FALSE,
],
'varnish' => [
'enable' => 0,
],
'redis' => [
'version' => '4.0',
],
'dbbrowser' => [
'type' => 'pma',
],
'solr' => [
'enable' => 0,
'version' => '6.6',
],
'node' => [
'enable' => 0,
'key' => '',
'path' => '',
],
'memcached' => [
'enable' => 0,
],
'rsyslog' => [
'enable' => 0,
],
'athenapdf' => [
'enable' => 0,
'key' => '',
],
'blackfire' => [
'enable' => 0,
'id' => '',
'token' => '',
],
'webgrind' => [
'enable' => 0,
],
'wkhtmltox' => [
'enable' => 0,
],
];
if ($this->isCiContext() || $this->isLocalDevMode()) {
$projectRoot = $this->getDockerMountSource(getenv('CI_PROJECT_DIR'));
}
else {
$projectRoot = getcwd();
}
// Check if SSH auth sockets are supported.
$ssh_auth_sock = getenv('SSH_AUTH_SOCK');
$options['php']['ssh'] = !empty($ssh_auth_sock);
if ($options['php']['ssh']) {
$options['php']['ssh_auth_sock'] = ($this->isCiContext() || $this->isLocalDevMode()) ?
$this->getDockerMountSource('/ssh-agent') :
'$SSH_AUTH_SOCK';
}
$options['projectroot'] = $projectRoot;
return $options;
}
/**
* {@inheritdoc}
*/
protected function postInit(): void {
$this->env->put('PHP_VERSION', $this->config->readValue('php/version'), TRUE);
}
/**
* Configure Drupal Project for Docker.
*
* @param bool $overwrite
* Whether to overwrite existing config files.
*
* @throws \Twig\Error\LoaderError
* @throws \Twig\Error\RuntimeError
* @throws \Twig\Error\SyntaxError
*/
public function configureProject($overwrite = FALSE) {
public function configureProject($overwrite = FALSE): void {
// We only do the fancy stuff for developers.
if (!$this->isDevMode()) {
return;
}
$options = $this->getOptions();
$fs = new Filesystem();
$installationManager = $this->composer->getInstallationManager();
if (isset($options['webroot'])) {
if (!$fs->exists($options['webroot'])) {
$webRoot = $this->config->readValue('webroot');
if ($webRoot !== NULL) {
if (!$fs->exists($webRoot)) {
return;
}
$webRoot = $options['webroot'];
}
else {
$drupalCorePackage = $this->getDrupalCorePackage();
......@@ -78,33 +193,27 @@ class Handler extends BaseHandler {
}
// Provide all the required files.
$twig_loader = new Twig_Loader_Array([]);
$twig = new Twig_Environment($twig_loader);
$options['webRoot'] = $webRoot . '/';
$orig_ignored = FALSE;
foreach ($this->getFiles($projectRoot, $webRoot, $settingsPath, $options) as $template => $def) {
foreach ($this->getFiles($projectRoot, $webRoot, $settingsPath) as $template => $def) {
if (isset($def['condition']) && !$def['condition']) {
continue;
}
if (!$fs->exists($def['dest'])) {
$fs->mkdir($def['dest']);
}
$twig_loader->setTemplate($template, $template);
$filename = $twig->render($template, $options);
$filename = $this->config->render($template, $template);
$file = $def['dest'] . '/' . $filename;
if (($overwrite && empty($def['add2git'])) || !$fs->exists($file)) {
$twig_loader->setTemplate($filename, file_get_contents($pluginRoot . '/templates/' . ($def['source'] ?? '') . $template . '.twig'));
$rendered = $twig->render($filename, $options);
if (!empty($def['add2yaml']) && isset($options[$filename])) {
$rendered = $this->config->render($filename, file_get_contents($pluginRoot . '/templates/' . ($def['source'] ?? '') . $template . '.twig'));
$extraOptions = $this->config->readValue($filename);
if (!empty($def['add2yaml']) && $extraOptions !== NULL) {
$yaml = Yaml::parse($rendered);
/** @noinspection SlowArrayOperationsInLoopInspection */
$yaml = array_merge_recursive($yaml, $options[$filename]);
$yaml = array_merge_recursive($yaml, $extraOptions);
$rendered = Yaml::dump($yaml, 9, 2);
// Render the string again so that custom content can also use variables
$twig_loader->setTemplate($filename, $rendered);
$rendered = $twig->render($filename, $options);
$rendered = $this->config->render($filename, $rendered);
}
if ($fs->exists($file)) {
if (md5_file($file) === md5($rendered)) {
......@@ -150,7 +259,7 @@ class Handler extends BaseHandler {
$this->gitIgnore('tests/backstop/backstop_data/html_report');
$this->gitLFS('tests/backstop/**/*.png');
$traefik = new Traefik($options['projectname']);
$traefik = new Traefik($this->config->readValue('projectname'));
$traefik->update();
// Set permissions, see https://wodby.com/stacks/drupal/docs/local/permissions
......@@ -167,13 +276,11 @@ class Handler extends BaseHandler {
* Name of the web's root directory.
* @param string $settingsPath
* Name of the settings directory.
* @param array $options
* Keyed array with all current options.
*
* @return array
* List of files.
*/
protected function getFiles($projectRoot, $webRoot, $settingsPath, $options): array {
protected function getFiles(string $projectRoot, string $webRoot, string $settingsPath): array {
return [
'settings.docker.php' => [
'dest' => $projectRoot . '/' . $settingsPath,
......@@ -205,139 +312,11 @@ class Handler extends BaseHandler {
],
'vhost.conf' => [
'dest' => $projectRoot . '/apache',
'condition' => $options['webserver']['overwriteconfig'],
'condition' => $this->config->readValue('webserver/overwriteconfig'),
],
];
}
/**
* Retrieve options from composer.json "extra" configuration.
*
* @param null $key
* Optional name of an option to be received instead of the full set of options.
*
* @return array|string
* The options.
*/
public function getOptions($key = NULL) {
if ($this->options === NULL) {
$env = new Dotenv('docker4drupal', $this->io);
$projectname = getenv('COMPOSE_PROJECT_NAME');
if (empty($projectname)) {$projectname = str_replace([' ', '-', '_', '.'], '', basename(getcwd()));
$env->put('COMPOSE_PROJECT_NAME', $projectname);
}
$extra = $this->composer->getPackage()->getExtra() + ['docker4drupal' => []];
$options = NestedArray::mergeDeep([
'projectname' => $projectname,
'ci_home' => '/home/gitlab-runner',
'docker0' => [
'ip' => ($this->isCiContext() || $this->isLocalDevMode()) ?
$this->getDockerGateway() :
$this->getLocalIpv4('docker0'),
],
'live' => [
'root' => '',
'uri' => '',
'host' => '',
'user' => $env->receive('live_host_username', 'Remote username for host of the live site', getenv('USER')),
],
'drush' => [
'sql' => [
'tables' => [
'structure' => [
'cache',
'cachetags',
'cache_*',
'history',
'search_*',
'sessions',
'watchdog',
],
'skip' => [
'migration_*',
],
],
],
],
'drupal' => [
'version' => '8',
],
'php' => [
'version' => $env->receiveGlobal('PHP_VERSION', 'PHP version', '7.3'),
'xdebug' => $env->receiveGlobal('PHP_DEBUG', 'PHP debug', '0'),
],
'webserver' => [
'type' => 'apache',
'overwriteconfig' => FALSE,
],
'varnish' => [
'enable' => 0,
],
'redis' => [
'version' => '4.0',
],
'dbbrowser' => [
'type' => 'pma',
],
'solr' => [
'enable' => 0,
'version' => '6.6',
],
'node' => [
'enable' => 0,
'key' => '',
'path' => '',
],
'memcached' => [
'enable' => 0,
],
'rsyslog' => [
'enable' => 0,
],
'athenapdf' => [
'enable' => 0,
'key' => '',
],
'blackfire' => [
'enable' => 0,
'id' => '',
'token' => '',
],
'webgrind' => [
'enable' => 0,
],
'wkhtmltox' => [
'enable' => 0,
],
], $extra['docker4drupal']);
if ($this->isCiContext() || $this->isLocalDevMode()) {
$projectRoot = $this->getDockerMountSource(getenv('CI_PROJECT_DIR'));
}
else {
$projectRoot = getcwd();
}
// Check if SSH auth sockets are supported.
$ssh_auth_sock = getenv('SSH_AUTH_SOCK');
$options['php']['ssh'] = !empty($ssh_auth_sock);
if ($options['php']['ssh']) {
$options['php']['ssh_auth_sock'] = ($this->isCiContext() || $this->isLocalDevMode()) ?
$this->getDockerMountSource('/ssh-agent') :
'$SSH_AUTH_SOCK';
}
$options['projectroot'] = $projectRoot;
$this->options = $env->replaceEnvironmentVariables($options);
$env->put('PHP_VERSION', $this->options['php']['version'], TRUE);
}
if ($key !== NULL) {
return $this->options[$key];
}
return $this->options;
}
/**
* Determine local ipv4 address.
*
......@@ -399,7 +378,10 @@ class Handler extends BaseHandler {
return getcwd();
}
private function readContainerConfig() {
/**
* @return array
*/
private function readContainerConfig(): array {
try {
$output = [];
exec('basename "$(cat /proc/1/cpuset)"', $output);
......
<?php
namespace LakeDrops\Docker4Drupal;
/**
* Class NestedArray.
*
* @package LakeDrops\Docker4Drupal
*/
class NestedArray {
/**
* Deeply merges arrays. Borrowed from drupal.org/project/core.
*
* @return array
* The merged array.
*/
public static function mergeDeep(): array {
return self::mergeDeepArray(func_get_args());
}
/**
* Deeply merges arrays. Borrowed from drupal.org/project/core.
*
* @param array $arrays
* An array of array that will be merged.
* @param bool $preserve_integer_keys
* Whether to preserve integer keys.
*
* @return array
* The merged array.
*/
public static function mergeDeepArray(array $arrays, $preserve_integer_keys = FALSE): array {
$result = [];
foreach ($arrays as $array) {
foreach ($array as $key => $value) {
if (is_int($key) && !$preserve_integer_keys) {
$result[] = $value;
}
/** @noinspection NotOptimalIfConditionsInspection */
elseif (isset($result[$key]) && is_array($result[$key]) && is_array($value)) {
$result[$key] = self::mergeDeepArray([$result[$key], $value], $preserve_integer_keys);
}
else {
$result[$key] = $value;
}
}
}
return $result;
}
}
......@@ -4,6 +4,7 @@ namespace LakeDrops\Docker4Drupal;
use Composer\Script\Event;
use Composer\Script\ScriptEvents;
use LakeDrops\Component\Composer\BaseHandlerInterface;
use LakeDrops\Component\Composer\BasePlugin;
/**
......@@ -14,7 +15,7 @@ class Plugin extends BasePlugin {
/**
* {@inheritdoc}
*/
public function getHandlerClass() {
public function getHandlerClass(): BaseHandlerInterface {
return Handler::class;
}
......
......@@ -3,6 +3,7 @@
namespace LakeDrops\Docker4Drupal;
use LakeDrops\Component\Composer\BaseCommand;
use LakeDrops\Component\Composer\BaseHandlerInterface;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
......@@ -19,7 +20,7 @@ class UpdateCommand extends BaseCommand {
/**
* {@inheritdoc}
*/
public function getHandlerClass() {
public function getHandlerClass(): BaseHandlerInterface {
return Handler::class;
}
......@@ -30,11 +31,12 @@ class UpdateCommand extends BaseCommand {
* @throws \Twig\Error\RuntimeError
* @throws \Twig\Error\SyntaxError
*/
protected function execute(InputInterface $input, OutputInterface $output) {
protected function execute(InputInterface $input, OutputInterface $output): int {
parent::execute($input, $output);
/** @var Handler $handler */
$handler = $this->handler;
$handler->configureProject(TRUE);
return 0;
}
}
dev:
root: '/var/www/html/{{ webRoot }}'
root: '/var/www/html/{{ webRoot }}/'
uri: '{{ projectname }}.docker.localhost:8000'
behat:
root: '/var/www/html/{{ webRoot }}'
root: '/var/www/html/{{ webRoot }}/'
uri: '{{ webserver.type }}'
live:
root: '{{ live.root }}'
......
......@@ -76,7 +76,7 @@ services:
{% endif %}
{% endif %}
{{ webserver.type|upper }}_BACKEND_HOST: php
{{ webserver.type|upper }}_SERVER_ROOT: /var/www/html/{{ webRoot }}
{{ webserver.type|upper }}_SERVER_ROOT: /var/www/html/{{ webRoot }}/
volumes:
- {{ projectroot }}:/var/www/html
labels:
......
<VirtualHost *:80>
DocumentRoot "/var/www/html/{{ webRoot }}"
DocumentRoot "/var/www/html/{{ webRoot }}/"
ServerName default
Include conf/preset.conf
<Location />
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment