From 11ee7f554faa9228538548407bc11d9ae4722dd0 Mon Sep 17 00:00:00 2001 From: Alex Skrypnyk Date: Wed, 19 Nov 2025 11:38:18 +1100 Subject: [PATCH] [#2014] Allow to select modules in the installer. --- .env | 7 + .vortex/docs/static/img/installer.json | 342 ++++++------ .vortex/docs/static/img/installer.svg | 2 +- .vortex/installer/composer.json | 6 +- .vortex/installer/composer.lock | 14 +- .../src/Prompts/Handlers/ModulePrefix.php | 2 +- .../src/Prompts/Handlers/Modules.php | 178 ++++++ .../installer/src/Prompts/PromptManager.php | 8 +- .../installer/src/Utils/JsonManipulator.php | 10 +- .../scripts/custom/provision-10-example.sh | 2 - .../modules_no_admin_toolbar/composer.json | 8 + .../scripts/custom/provision-10-example.sh | 9 + .../install/modules_no_coffee/composer.json | 8 + .../scripts/custom/provision-10-example.sh | 9 + .../modules_no_config_split/composer.json | 8 + .../scripts/custom/provision-10-example.sh | 9 + .../Drupal/EnvironmentSettingsTest.php | 24 + .../phpunit/Drupal/SwitchableSettingsTest.php | 94 ++++ .../modules/-settings.config_split.php | 0 .../modules_no_config_update/composer.json | 8 + .../scripts/custom/provision-10-example.sh | 9 + .../composer.json | 8 + .../scripts/custom/provision-10-example.sh | 9 + .../Drupal/EnvironmentSettingsTest.php | 60 ++ .../phpunit/Drupal/SwitchableSettingsTest.php | 72 +++ .../-settings.environment_indicator.php | 0 .../install/modules_no_pathauto/composer.json | 8 + .../scripts/custom/provision-10-example.sh | 9 + .../install/modules_no_redirect/composer.json | 8 + .../scripts/custom/provision-10-example.sh | 9 + .../modules_no_robotstxt/composer.json | 8 + .../scripts/custom/provision-10-example.sh | 9 + .../tests/behat/features/-robotstxt.feature | 0 .../Drupal/EnvironmentSettingsTest.php | 40 ++ .../includes/modules/-settings.robotstxt.php | 0 .../install/modules_no_seckit/composer.json | 8 + .../Drupal/EnvironmentSettingsTest.php | 27 + .../includes/modules/-settings.seckit.php | 0 .../.env | 16 + .../composer.json | 10 + .../docker-compose.yml | 10 + .../scripts/custom/provision-10-example.sh | 9 + .../Drupal/EnvironmentSettingsTest.php | 52 ++ .../phpunit/Drupal/SwitchableSettingsTest.php | 366 ++++++++++++ .../includes/modules/-settings.seckit.php | 0 .../includes/modules/-settings.shield.php | 0 .../modules/-settings.stage_file_proxy.php | 0 .../Fixtures/install/modules_no_shield/.env | 14 + .../install/modules_no_shield/composer.json | 8 + .../modules_no_shield/docker-compose.yml | 10 + .../scripts/custom/provision-10-example.sh | 9 + .../Drupal/EnvironmentSettingsTest.php | 40 ++ .../phpunit/Drupal/SwitchableSettingsTest.php | 239 ++++++++ .../includes/modules/-settings.shield.php | 0 .../install/modules_no_stage_file_proxy/.env | 13 + .../modules_no_stage_file_proxy/composer.json | 8 + .../scripts/custom/provision-10-example.sh | 9 + .../phpunit/Drupal/SwitchableSettingsTest.php | 134 +++++ .../modules/-settings.stage_file_proxy.php | 0 .../tests/Fixtures/install/modules_none/.env | 16 + .../install/modules_none/composer.json | 24 + .../install/modules_none/docker-compose.yml | 10 + .../scripts/custom/provision-10-example.sh | 10 + .../tests/behat/features/-robotstxt.feature | 0 .../Drupal/EnvironmentSettingsTest.php | 85 +++ .../phpunit/Drupal/SwitchableSettingsTest.php | 525 ++++++++++++++++++ .../modules/-settings.config_split.php | 0 .../-settings.environment_indicator.php | 0 .../includes/modules/-settings.robotstxt.php | 0 .../includes/modules/-settings.seckit.php | 0 .../includes/modules/-settings.shield.php | 0 .../modules/-settings.stage_file_proxy.php | 0 .../scripts/custom/provision-10-example.sh | 8 +- .../scripts/custom/provision-10-example.sh | 2 +- .../scripts/custom/provision-10-example.sh | 2 +- .../scripts/custom/provision-10-example.sh | 2 +- .../scripts/custom/provision-10-example.sh | 2 +- .../scripts/custom/provision-10-example.sh | 4 +- .../scripts/custom/provision-10-example.sh | 4 +- .../Handlers/ModulesInstallTest.php | 148 +++++ .../AbstractPromptManagerTestCase.php | 3 + .../Handlers/ModulesPromptManagerTest.php | 134 +++++ docker-compose.yml | 2 + scripts/custom/provision-10-example.sh | 4 +- .../phpunit/Drupal/SwitchableSettingsTest.php | 11 + 85 files changed, 2769 insertions(+), 206 deletions(-) create mode 100644 .vortex/installer/src/Prompts/Handlers/Modules.php create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_admin_toolbar/composer.json create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_admin_toolbar/scripts/custom/provision-10-example.sh create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_coffee/composer.json create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_coffee/scripts/custom/provision-10-example.sh create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_config_split/composer.json create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_config_split/scripts/custom/provision-10-example.sh create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_config_split/tests/phpunit/Drupal/EnvironmentSettingsTest.php create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_config_split/tests/phpunit/Drupal/SwitchableSettingsTest.php create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_config_split/web/sites/default/includes/modules/-settings.config_split.php create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_config_update/composer.json create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_config_update/scripts/custom/provision-10-example.sh create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_environment_indicator/composer.json create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_environment_indicator/scripts/custom/provision-10-example.sh create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_environment_indicator/tests/phpunit/Drupal/EnvironmentSettingsTest.php create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_environment_indicator/tests/phpunit/Drupal/SwitchableSettingsTest.php create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_environment_indicator/web/sites/default/includes/modules/-settings.environment_indicator.php create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_pathauto/composer.json create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_pathauto/scripts/custom/provision-10-example.sh create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_redirect/composer.json create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_redirect/scripts/custom/provision-10-example.sh create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_robotstxt/composer.json create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_robotstxt/scripts/custom/provision-10-example.sh create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_robotstxt/tests/behat/features/-robotstxt.feature create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_robotstxt/tests/phpunit/Drupal/EnvironmentSettingsTest.php create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_robotstxt/web/sites/default/includes/modules/-settings.robotstxt.php create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_seckit/composer.json create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_seckit/tests/phpunit/Drupal/EnvironmentSettingsTest.php create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_seckit/web/sites/default/includes/modules/-settings.seckit.php create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_seckit_shield_stage_file_proxy/.env create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_seckit_shield_stage_file_proxy/composer.json create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_seckit_shield_stage_file_proxy/docker-compose.yml create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_seckit_shield_stage_file_proxy/scripts/custom/provision-10-example.sh create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_seckit_shield_stage_file_proxy/tests/phpunit/Drupal/EnvironmentSettingsTest.php create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_seckit_shield_stage_file_proxy/tests/phpunit/Drupal/SwitchableSettingsTest.php create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_seckit_shield_stage_file_proxy/web/sites/default/includes/modules/-settings.seckit.php create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_seckit_shield_stage_file_proxy/web/sites/default/includes/modules/-settings.shield.php create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_seckit_shield_stage_file_proxy/web/sites/default/includes/modules/-settings.stage_file_proxy.php create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_shield/.env create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_shield/composer.json create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_shield/docker-compose.yml create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_shield/scripts/custom/provision-10-example.sh create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_shield/tests/phpunit/Drupal/EnvironmentSettingsTest.php create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_shield/tests/phpunit/Drupal/SwitchableSettingsTest.php create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_shield/web/sites/default/includes/modules/-settings.shield.php create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_stage_file_proxy/.env create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_stage_file_proxy/composer.json create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_stage_file_proxy/scripts/custom/provision-10-example.sh create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_stage_file_proxy/tests/phpunit/Drupal/SwitchableSettingsTest.php create mode 100644 .vortex/installer/tests/Fixtures/install/modules_no_stage_file_proxy/web/sites/default/includes/modules/-settings.stage_file_proxy.php create mode 100644 .vortex/installer/tests/Fixtures/install/modules_none/.env create mode 100644 .vortex/installer/tests/Fixtures/install/modules_none/composer.json create mode 100644 .vortex/installer/tests/Fixtures/install/modules_none/docker-compose.yml create mode 100644 .vortex/installer/tests/Fixtures/install/modules_none/scripts/custom/provision-10-example.sh create mode 100644 .vortex/installer/tests/Fixtures/install/modules_none/tests/behat/features/-robotstxt.feature create mode 100644 .vortex/installer/tests/Fixtures/install/modules_none/tests/phpunit/Drupal/EnvironmentSettingsTest.php create mode 100644 .vortex/installer/tests/Fixtures/install/modules_none/tests/phpunit/Drupal/SwitchableSettingsTest.php create mode 100644 .vortex/installer/tests/Fixtures/install/modules_none/web/sites/default/includes/modules/-settings.config_split.php create mode 100644 .vortex/installer/tests/Fixtures/install/modules_none/web/sites/default/includes/modules/-settings.environment_indicator.php create mode 100644 .vortex/installer/tests/Fixtures/install/modules_none/web/sites/default/includes/modules/-settings.robotstxt.php create mode 100644 .vortex/installer/tests/Fixtures/install/modules_none/web/sites/default/includes/modules/-settings.seckit.php create mode 100644 .vortex/installer/tests/Fixtures/install/modules_none/web/sites/default/includes/modules/-settings.shield.php create mode 100644 .vortex/installer/tests/Fixtures/install/modules_none/web/sites/default/includes/modules/-settings.stage_file_proxy.php create mode 100644 .vortex/installer/tests/Functional/Handlers/ModulesInstallTest.php create mode 100644 .vortex/installer/tests/Unit/Handlers/ModulesPromptManagerTest.php diff --git a/.env b/.env index 4c7e3c6fe..ef9571c92 100644 --- a/.env +++ b/.env @@ -61,14 +61,21 @@ DRUPAL_THEME=your_site_theme # Drupal maintenance theme name. DRUPAL_MAINTENANCE_THEME=your_site_theme + +#;< MODULE_STAGE_FILE_PROXY # Stage file proxy origin. +#;< MODULE_SHIELD # # If using Shield, the HTTP authentication credentials will be automatically # added to the origin URL. +#;> MODULE_SHIELD DRUPAL_STAGE_FILE_PROXY_ORIGIN=https://www.your-site-domain.example +#;> MODULE_STAGE_FILE_PROXY +#;< MODULE_SHIELD # Shield message. DRUPAL_SHIELD_PRINT="Restricted access." +#;> MODULE_SHIELD #;< SERVICE_REDIS # Enable Redis integration. diff --git a/.vortex/docs/static/img/installer.json b/.vortex/docs/static/img/installer.json index 8cc3db7e8..99b617144 100644 --- a/.vortex/docs/static/img/installer.json +++ b/.vortex/docs/static/img/installer.json @@ -1,176 +1,166 @@ -{"version": 2, "width": 120, "height": 36, "timestamp": 1763034775, "env": {"SHELL": "/opt/homebrew/opt/bash/bin/bash", "TERM": "xterm-256color"}, "title": "Vortex Installer Demo"} -[0.579142, "o", "\r\r\n \u001b[36m──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────\u001b[39m\r\r\n \u001b[36m\u001b[39m\r\r\n \u001b[36m\u001b[39m\r\r\n \u001b[36m ██╗ ██╗ ██████╗ ██████╗ ████████╗ ███████╗ ██╗ ██╗\u001b[39m\r\r\n \u001b[36m ██║ ██║ ██╔═══██╗ ██╔══██╗ ╚══██╔══╝ ██╔════╝ ╚██╗██╔╝\u001b[39m\r\r\n \u001b[36m ██║ ██║ ██║ ██║ ██████╔╝ ██║ █████╗ ╚███╔╝\u001b[39m\r\r\n \u001b[36m ╚██╗ ██╔╝ █"] -[0.579256, "o", "█║ "] -[0.57933, "o", " ██║ ██╔══██╗ ██║ ██╔══╝ ██╔██╗\u001b[39m\r\r\n \u001b[36m ╚████╔╝ ╚██████╔╝ ██║ ██║ ██║ ███████╗ ██╔╝ ██╗\u001b[39m\r\r\n \u001b[36m ╚═══╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚══════╝ ╚═╝ ╚═╝\u001b[39m\r\r\n \u001b[36m\u001b[39m\r\r\n \u001b[36m Drupal project template\u001b[39m\r\r\n \u001b[36m\u001b[39m\r\r\n \u001b[36m by DrevOps\u001b[39m\r\r\n \u001b[36m\u001b[39m\r\r\n \u001b[36m────────────────────────────────────────────────────────────────────────────────────────────────────────────────"] -[0.579345, "o", "──────\u001b[39m\r\r\n \u001b[2m Installer version: development\u001b[22m\r\r\n\r\r\n"] -[0.584152, "o", "\r\r\n \u001b[90m┌──────────────────────────────────────────────────────────────────────────────────────┐\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[32mWelcome to the Vortex interactive installer\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[32m───────────────────────────────────────────\u001b[39m\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m This tool will guide you through installing the latest \u001b[4mstable\u001b[0m version of Vortex into\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m your project.\u001b[39m\u001b[39m "] -[0.584223, "o", " "] -[0.58429, "o", " \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m You will be asked a few questions to tailor the configuration to your site.\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m No changes will be made until you confirm everything at the end.\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Press \u001b[33mCtrl+C\u001b[39m at any time to exit the installer.\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Press \u001b[33mCtrl+U\u001b[39m at any time to go back to the previous step.\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m└─────────"] -[0.584351, "o", "─────────────────────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n \u001b[2mPress any key to continue...\u001b[22m\r\r\n"] -[3.648125, "o", "\r\r\n \u001b[46m\u001b[30m General information \u001b[39m\u001b[49m\r\r\n\r\r\n"] -[3.675104, "o", "\u001b[?25l"] -[3.698732, "o", "\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mSite name \u001b[2m(1/27)\u001b[22m\u001b[39m \u001b[90m────────────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m star wars\u001b[7m \u001b[27m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m We will use this name in the project and documentation.\u001b[39m\r\r\n"] -[4.840832, "o", "\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mSite name \u001b[2m(1/27)\u001b[22m\u001b[39m \u001b[90m────────────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m\u001b[7mE\u001b[27m.g. My Site\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m We will use this name in the project and documentation.\u001b[39m\r\r\n"] -[5.266867, "o", "\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mSite name \u001b[2m(1/27)\u001b[22m\u001b[39m \u001b[90m────────────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m S\u001b[7m \u001b[27m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m We will use this name in the project and documentation.\u001b[39m\r\r\n\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mSite name \u001b[2m(1/27)\u001b[22m\u001b[39m \u001b[90m────────────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m St\u001b[7m \u001b[27m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └─────────────────────────────────────"] -[5.266984, "o", "──"] -[5.267007, "o", "───────────────────────┘\u001b[39m\r\r\n\u001b[90m We will use this name in the project and documentation.\u001b[39m\r\r\n"] -[6.270381, "o", "\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mSite name \u001b[2m(1/27)\u001b[22m\u001b[39m \u001b[90m────────────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m Star Wars\u001b[7m \u001b[27m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m We will use this name in the project and documentation.\u001b[39m\r\r\n"] -[6.273572, "o", "\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mSite name \u001b[2m(1/27)\u001b[22m\u001b[22m \u001b[90m────────────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m Star Wars \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n"] -[6.273716, "o", "\u001b[?25h"] -[6.291523, "o", "\u001b[?25l"] -[6.297639, "o", "\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mSite machine name \u001b[2m(2/27)\u001b[22m\u001b[39m \u001b[90m────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m star_wars\u001b[7m \u001b[27m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m We will use this name for the project directory and in the code.\u001b[39m\r\r\n"] -[7.304912, "o", "\u001b[1G\u001b[5A\u001b[J"] -[7.304999, "o", "\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mSite machine name \u001b[2m(2/27)\u001b[22m\u001b[22m \u001b[90m────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m star_wars \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h"] -[7.3248, "o", "\u001b[?25l"] -[7.330169, "o", "\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mOrganization name \u001b[2m(3/27)\u001b[22m\u001b[39m \u001b[90m────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m Star Wars Org\u001b[7m \u001b[27m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m We will use this name in the project and documentation.\u001b[39m\r\r\n"] -[7.48444, "o", "\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mOrganization name \u001b[2m(3/27)\u001b[22m\u001b[39m \u001b[90m────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m Star Wars\u001b[7m \u001b[27m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m We will use this name in the project and documentation.\u001b[39m\r\r\n\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mOrganization name \u001b[2m(3/27)\u001b[22m\u001b[39m \u001b[90m────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m\u001b[7mE\u001b[27m.g. My Org\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └────────────────────────────────────────────"] -[7.484487, "o", "───"] -[8.411256, "o", "───────────────┘\u001b[39m\r\r\n\u001b[90m We will use this name in the project and documentation.\u001b[39m\r\r\n\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mOrganization name \u001b[2m(3/27)\u001b[22m\u001b[39m \u001b[90m────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m R\u001b[7m \u001b[27m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m We will use this name in the project and documentation.\u001b[39m\r\r\n\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mOrganization name \u001b[2m(3/27)\u001b[22m\u001b[39m \u001b[90m────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m Re\u001b[7m \u001b[27m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └─────"] -[8.41139, "o", "────"] -[8.411448, "o", "─────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m We will use this name in the project and documentation.\u001b[39m\r\r\n"] -[9.416236, "o", "\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mOrganization name \u001b[2m(3/27)\u001b[22m\u001b[39m \u001b[90m────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m Rebellion\u001b[7m \u001b[27m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m We will use this name in the project and documentation.\u001b[39m\r\r\n"] -[10.420483, "o", "\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mOrganization name \u001b[2m(3/27)\u001b[22m\u001b[22m \u001b[90m────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m Rebellion \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mOrganization machine name \u001b[2m(4/27)\u001b[22m\u001b[39m \u001b[90m────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m rebellion\u001b[7m \u001b[27m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m We will use this name in the co"] -[10.420586, "o", "de.\u001b[39m\r"] -[10.420599, "o", "\r\r\n"] -[11.421022, "o", "\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mOrganization machine name \u001b[2m(4/27)\u001b[22m\u001b[22m \u001b[90m────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m rebellion \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mPublic domain \u001b[2m(5/27)\u001b[22m\u001b[39m \u001b[90m────────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m star-wars.com\u001b[7m \u001b[27m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m Domain name without pro"] -[11.42111, "o", "tocol and"] -[11.421121, "o", " trailing slash.\u001b[39m\r\r\n"] -[12.421992, "o", "\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mPublic domain \u001b[2m(5/27)\u001b[22m\u001b[22m \u001b[90m────────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m star-wars.com \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h\r\r\n \u001b[46m\u001b[30m Drupal \u001b[39m\u001b[49m\r\r\n\r\r\n\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mHow would you like your site to be created on the first run? \u001b[2m(6/27)\u001b[22m\u001b[39m \u001b[90m┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Choose how your site will be created the first time after this \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m installer finishes: \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m "] -[12.42209, "o", " "] -[12.422238, "o", " \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m ○ \u001b[1mDrupal, installed from profile\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Creates a new site by \u001b[4mpopulating a fresh database\u001b[0m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m from one of the standard Drupal installation profiles. \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m ○ \u001b[1mDrupal CMS, installed from profile\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Creates a new site by \u001b[4mpopulating a fresh database\u001b[0m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m from the Drupal CMS recipe. \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m ○ \u001b[1mDrupal, loaded from the demo database\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Creates a site by \u001b[4mloadin"] -[12.422259, "o", "g an exist"] -[13.425932, "o", "ing demo database\u001b[0m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m provided with the installer. \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m ├─────────────────────────────────────────────────────────────────────┤\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mDrupal, installed from profile\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mDrupal CMS, installed from profile\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m›\u001b[39m \u001b[36m●\u001b[39m Drupal, loaded from the demo database \u001b[90m│\u001b[39m\r\r\n\u001b[90m └────────────────────────────────────────────────────────────"] -[13.426036, "o", "──"] -[13.426147, "o", "───────┘\u001b[39m\r\r\n\u001b[90m Use ⬆ and ⬇. Applies only on the first run of the installer.\u001b[39m\r\r\n"] -[14.435423, "o", "\u001b[1G\u001b[24A\u001b[J"] -[14.435525, "o", "\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mHow would you like your site to be created on the first run? \u001b[2m(6/27)\u001b[22m\u001b[22m \u001b[90m┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Choose how your site will be created the first time after this \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m installer finishes: \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m ○ \u001b[1mDrupal, installed from profile\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Creates a new site by \u001b[4mpopulating a fresh database\u001b[0m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m from one of the standard Drupal installation profiles. \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m ○ \u001b[1mDrupal CMS, installed from profile\u001b[22m "] -[14.43556, "o", " \u001b[90m│\u001b"] -[14.435647, "o", "[39m\r\r\n\u001b[90m │\u001b[39m Creates a new site by \u001b[4mpopulating a fresh database\u001b[0m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m from the Drupal CMS recipe. \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m ○ \u001b[1mDrupal, loaded from the demo database\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Creates a site by \u001b[4mloading an existing demo database\u001b[0m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m provided with the installer. \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m ├─────────────────────────────────────────────────────────────────────┤\u001b[39m\r\r\n\u001b[90m │\u001b[39m Drupal, loaded from the demo database "] -[14.435687, "o", " "] -[14.435736, "o", " \u001b[90m│\u001b[39m\r\r\n\u001b[90m └─────────────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h"] -[15.436284, "o", "\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mProfile \u001b[2m(7/27)\u001b[22m\u001b[39m \u001b[90m──────────────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m›\u001b[39m \u001b[36m●\u001b[39m Standard \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mMinimal\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mDemo Umami\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mCustom (next prompt)\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m Use ⬆ and ⬇ to select which Drupal profile to use.\u001b[39m\r\r\n"] -[16.440753, "o", "\u001b[1G\u001b[8A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mProfile \u001b[2m(7/27)\u001b[22m\u001b[22m \u001b[90m──────────────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m Standard \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mModule prefix \u001b[2m(8/27)\u001b[22m\u001b[39m \u001b[90m────────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m sw\u001b[7m \u001b[27m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b["] -[16.440842, "o", "39m\r\r\n\u001b[9"] -[16.440853, "o", "0m We will use this name in custom modules\u001b[39m\r\r\n"] -[17.444068, "o", "\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mModule prefix \u001b[2m(8/27)\u001b[22m\u001b[22m \u001b[90m────────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m sw \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mTheme \u001b[2m(9/27)\u001b[22m\u001b[39m \u001b[90m────────────────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mOlivero\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mClaro\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mStark\u001b[22m "] -[17.444162, "o", " "] -[17.444191, "o", " \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m›\u001b[39m \u001b[36m●\u001b[39m Custom (next prompt) \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m Use ⬆ and ⬇ to select which Drupal theme to use.\u001b[39m\r\r\n"] -[18.446403, "o", "\u001b[1G\u001b[8A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mTheme \u001b[2m(9/27)\u001b[22m\u001b[22m \u001b[90m────────────────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m Custom (next prompt) \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mCustom theme machine name \u001b[2m(10/27)\u001b[22m\u001b[39m \u001b[90m───────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m star_wars\u001b[7m \u001b[27m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m We will u"] -[18.446511, "o", "se this n"] -[18.446546, "o", "ame as a custom theme name\u001b[39m\r\r\n"] -[19.450423, "o", "\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mCustom theme machine name \u001b[2m(10/27)\u001b[22m\u001b[22m \u001b[90m───────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m star_wars \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h\r\r\n \u001b[46m\u001b[30m Code repository \u001b[39m\u001b[49m\r\r\n\r\r\n\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mRepository provider \u001b[2m(11/27)\u001b[22m\u001b[39m \u001b[90m─────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Vortex offers full automation with GitHub, while support for \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m other providers is limited. \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m "] -[19.450723, "o", " "] -[19.451288, "o", " \u001b[90m│\u001b[39m\r\r\n\u001b[90m ├──────────────────────────────────────────────────────────────┤\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m›\u001b[39m \u001b[36m●\u001b[39m GitHub \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mOther\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m Use ⬆ and ⬇ to select your code repository provider.\u001b[39m\r\r\n"] -[20.45485, "o", "\u001b[1G\u001b[11A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mRepository provider \u001b[2m(11/27)\u001b[22m\u001b[22m \u001b[90m─────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Vortex offers full automation with GitHub, while support for \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m other providers is limited. \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m ├──────────────────────────────────────────────────────────────┤\u001b[39m\r\r\n\u001b[90m │\u001b[39m GitHub \u001b[90m│\u001b[39m\r\r\n\u001b[90m └────────────────────────────────────────────────────"] -[20.454949, "o", "───"] -[20.454992, "o", "───────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h"] -[21.458789, "o", "\r\r\n \u001b[46m\u001b[30m Environment \u001b[39m\u001b[49m\r\r\n\r\r\n\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mTimezone \u001b[2m(12/27)\u001b[22m\u001b[39m \u001b[90m────────────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m UTC\u001b[7m \u001b[27m \u001b[90m│\u001b[39m\r\r\n\u001b[90m ├──────────────────────────────────────────────────────────────┤\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2mUTC\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m Use ⬆ and ⬇, or start typing to select the timezone for your project.\u001b[39m\r\r\n\u001b[1G\u001b[7A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mTimezone \u001b[2m(12/27)\u001b[22m\u001b[22m \u001b[90m"] -[21.458881, "o", "────"] -[21.458894, "o", "────────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m UTC \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h"] -[22.46069, "o", "\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mServices \u001b[2m(13/27)\u001b[22m\u001b[39m \u001b[90m────────────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m› ◼\u001b[39m ClamAV \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m◼\u001b[39m \u001b[2mSolr\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m◼\u001b[39m \u001b[2mRedis\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m Use ⬆, ⬇ and Space bar to select one or more services.\u001b[39m\r\r\n\u001b[1G\u001b[7A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mServices \u001b[2m(13/27)\u001b[22m\u001b[22m \u001b[90m────────────────────────────────────────────┐\u001b"] -[22.460788, "o", "[39m\r\r\n\u001b["] -[22.460871, "o", "90m │\u001b[39m ClamAV \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Solr \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Redis \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h"] -[23.463192, "o", "\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mDevelopment tools \u001b[2m(14/27)\u001b[22m\u001b[39m \u001b[90m───────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m› ◼\u001b[39m PHP CodeSniffer \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m◼\u001b[39m \u001b[2mPHPStan\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m◼\u001b[39m \u001b[2mRector\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m◼\u001b[39m \u001b[2mPHP Mess Detector\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m◼\u001b[39m \u001b[2mPHPUnit\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m◼\u001b[39m \u001b[2mBehat\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └───────────────────────────────────────────────────"] -[23.463282, "o", "───"] -[23.463328, "o", "────────┘\u001b[39m\r\r\n\u001b[90m Use ⬆, ⬇ and Space bar to select one or more tools.\u001b[39m\r\r\n"] -[24.467279, "o", "\u001b[1G\u001b[10A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mDevelopment tools \u001b[2m(14/27)\u001b[22m\u001b[22m \u001b[90m───────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m PHP CodeSniffer \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m PHPStan \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Rector \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m PHP Mess Detector \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m PHPUnit \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Behat \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n"] -[24.467363, "o", "\u001b[?25h"] -[25.47182, "o", "\r\r\n \u001b[46m\u001b[30m Hosting \u001b[39m\u001b[49m\r\r\n\r\r\n\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mHosting provider \u001b[2m(15/27)\u001b[22m\u001b[39m \u001b[90m────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mAcquia Cloud\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mLagoon\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mOther\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m›\u001b[39m \u001b[36m●\u001b[39m None \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m Use ⬆, ⬇ and Space bar to select your hosting provider.\u001b[39m\r\r\n"] -[26.472987, "o", "\u001b[1G\u001b[8A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mHosting provider \u001b[2m(15/27)\u001b[22m\u001b[22m \u001b[90m────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m None \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mCustom web root directory \u001b[2m(16/27)\u001b[22m\u001b[39m \u001b[90m───────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m web\u001b[7m \u001b[27m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m Custom directory where the web se"] -[26.473081, "o", "rver serv"] -[26.47317, "o", "es the site.\u001b[39m\r\r\n"] -[27.475631, "o", "\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mCustom web root directory \u001b[2m(16/27)\u001b[22m\u001b[22m \u001b[90m───────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m web \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h\r\r\n \u001b[46m\u001b[30m Deployment \u001b[39m\u001b[49m\r\r\n\r\r\n\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mDeployment types \u001b[2m(17/27)\u001b[22m\u001b[39m \u001b[90m────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m›\u001b[39m ◻ Code artifact \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m◻\u001b[22m \u001b[2mLagoon webhook\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m◻\u001b[22m \u001b[2mContainer image\u001b[22m "] -[27.475756, "o", " \u001b[9"] -[27.475826, "o", "0m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m◼\u001b[39m \u001b[2mCustom webhook\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m Use ⬆, ⬇ and Space bar to select one or more deployment types.\u001b[39m\r\r\n"] -[28.480641, "o", "\u001b[1G\u001b[8A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mDeployment types \u001b[2m(17/27)\u001b[22m\u001b[22m \u001b[90m────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m Custom webhook \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h\r\r\n \u001b[46m\u001b[30m Workflow \u001b[39m\u001b[49m\r\r\n\r\r\n\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mProvision type \u001b[2m(18/27)\u001b[22m\u001b[39m \u001b[90m──────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Provisioning sets up the site in an environment using an \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m already assembled codebase. \u001b[90m│\u001b[39m\r\r\n\u001b[90m │"] -[28.480732, "o", "\u001b[39m "] -[28.481051, "o", " \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m ○ \u001b[1mImport from database dump\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Provisions the site by importing a database dump \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m typically copied from production into lower \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m environments. \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m ○ \u001b[1mInstall from profile\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Provisions the site by installing a fresh Drupal \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m site from a profile every time an environment is \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m created. \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m ├─"] -[28.481248, "o", "───"] -[29.485921, "o", "──────────────────────────────────────────────────────────┤\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m›\u001b[39m \u001b[36m●\u001b[39m Import from database dump \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mInstall from profile\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m Use ⬆ and ⬇ to select the provision type.\u001b[39m\r\r\n\u001b[1G\u001b[21A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mProvision type \u001b[2m(18/27)\u001b[22m\u001b[22m \u001b[90m──────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Provisioning sets up the site in an e"] -[29.48775, "o", "nvironment"] -[29.490208, "o", " using an \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m already assembled codebase. \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m ○ \u001b[1mImport from database dump\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Provisions the site by importing a database dump \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m typically copied from production into lower \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m environments. \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m ○ \u001b[1mInstall from profile\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Provisions the site by installing a fresh Drupal \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m site from a profile every time an environment is \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m created. "] -[29.491452, "o", " "] -[30.494997, "o", " \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m ├──────────────────────────────────────────────────────────────┤\u001b[39m\r\r\n\u001b[90m │\u001b[39m Import from database dump \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mDatabase source \u001b[2m(19/27)\u001b[22m\u001b[39m \u001b[90m─────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m›\u001b[39m \u001b[36m●\u001b[39m URL download \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mFTP download\u001b[22m "] -[30.495293, "o", " "] -[30.495346, "o", " \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mAcquia backup\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mLagoon environment\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mContainer registry\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mNone\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m Use ⬆ and ⬇ to select the database download source.\u001b[39m\r\r\n"] -[31.504342, "o", "\u001b[1G\u001b[10A\u001b[J"] -[31.504377, "o", "\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mDatabase source \u001b[2m(19/27)\u001b[22m\u001b[22m \u001b[90m─────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m URL download \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h"] -[32.50703, "o", "\r\r\n \u001b[46m\u001b[30m Notifications \u001b[39m\u001b[49m\r\r\n\r\r\n\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mNotification channels \u001b[2m(20/27)\u001b[22m\u001b[39m \u001b[90m───────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m› ◼\u001b[39m Email \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m◻\u001b[22m \u001b[2mGitHub\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m◻\u001b[22m \u001b[2mJIRA\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m◻\u001b[22m \u001b[2mNew Relic\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m◻\u001b[22m \u001b[2mSlack\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m◻\u001b[22m \u001b[2mWebhook\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └────────────────────────────────────────"] -[32.507595, "o", "──────────────────────┘\u001b[39m\r\r\n\u001b[90m Use ⬆, ⬇ and Space bar to select one or more notification channels.\u001b[39m\r\r\n"] -[33.511725, "o", "\u001b[1G\u001b[10A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mNotification channels \u001b[2m(20/27)\u001b[22m\u001b[22m \u001b[90m───────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m Email \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h\r\r\n \u001b[46m\u001b[30m Continuous Integration \u001b[39m\u001b[49m\r\r\n\r\r\n\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mContinuous Integration provider \u001b[2m(21/27)\u001b[22m\u001b[39m \u001b[90m─────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m›\u001b[39m \u001b[36m●\u001b[39m GitHub Actions \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mCircleCI\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mNone\u001b[22m "] -[33.512011, "o", " \u001b["] -[33.512161, "o", "90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m Use ⬆ and ⬇ to select the CI provider.\u001b[39m\r\r\n"] -[34.514225, "o", "\u001b[1G\u001b[7A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mContinuous Integration provider \u001b[2m(21/27)\u001b[22m\u001b[22m \u001b[90m─────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m GitHub Actions \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h\r\r\n \u001b[46m\u001b[30m Automations \u001b[39m\u001b[49m\r\r\n\r\r\n\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mDependency updates provider \u001b[2m(22/27)\u001b[22m\u001b[39m \u001b[90m─────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m›\u001b[39m \u001b[36m●\u001b[39m Renovate GitHub app \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mRenovate self-hosted in CI\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mNone\u001b[22m \u001b[90m│\u001b[39m\r"] -[34.514529, "o", "\r\n\u001b[90m └"] -[34.514712, "o", "──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m Use ⬆ and ⬇ to select the dependency updates provider.\u001b[39m\r\r\n"] -[35.51803, "o", "\u001b[1G\u001b[7A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mDependency updates provider \u001b[2m(22/27)\u001b[22m\u001b[22m \u001b[90m─────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m Renovate GitHub app \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mAuto-assign the author to their PR? \u001b[2m(23/27)\u001b[22m\u001b[39m \u001b[90m─────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[32m●\u001b[39m Yes \u001b[2m/ ○ No\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m Helps to keep the PRs organized.\u001b[39m\r\r\n"] -[36.522266, "o", "\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mAuto-assign the author to their PR? \u001b[2m(23/27)\u001b[22m\u001b[22m \u001b[90m─────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m Yes \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mAuto-add a CONFLICT label to a PR when conflicts occur? \u001b[2m(24/27)\u001b[22m\u001b[39m \u001b[90m┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[32m●\u001b[39m Yes \u001b[2m/ ○ No\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └─────────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m Helps to keep quickly identify PRs that need attention.\u001b[39m\r\r\n"] -[37.52596, "o", "\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mAuto-add a CONFLICT label to a PR when conflicts occur? \u001b[2m(24/27)\u001b[22m\u001b[22m \u001b[90m┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m Yes \u001b[90m│\u001b[39m\r\r\n\u001b[90m └─────────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h\r\r\n \u001b[46m\u001b[30m Documentation \u001b[39m\u001b[49m\r\r\n\r\r\n\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mPreserve project documentation? \u001b[2m(25/27)\u001b[22m\u001b[39m \u001b[90m─────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[32m●\u001b[39m Yes \u001b[2m/ ○ No\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m Helps to maintain the project documentation"] -[37.526151, "o", " within the "] -[37.526257, "o", "repository.\u001b[39m\r\r\n"] -[38.535335, "o", "\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mPreserve project documentation? \u001b[2m(25/27)\u001b[22m\u001b[22m \u001b[90m─────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m Yes \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h\r\r\n \u001b[46m\u001b[30m AI \u001b[39m\u001b[49m\r\r\n\r\r\n\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mAI code assistant instructions \u001b[2m(26/27)\u001b[22m\u001b[39m \u001b[90m──────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mAnthropic Claude\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m›\u001b[39m \u001b[36m●\u001b[39m None \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────"] -[38.536773, "o", "────"] -[38.537746, "o", "────────────────────┘\u001b[39m\r\r\n\u001b[90m Provides AI coding assistants with better context about the project.\u001b[39m\r\r\n"] -[39.541063, "o", "\u001b[1G\u001b[6A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mAI code assistant instructions \u001b[2m(26/27)\u001b[22m\u001b[22m \u001b[90m──────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m None \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h\r\r\n \u001b[46m\u001b[30m \u001b[39m\u001b[49m\r\r\n \u001b[46m\u001b[30m Installation summary \u001b[39m\u001b[49m\r\r\n \u001b[46m\u001b[30m \u001b[39m\u001b[49m\r\r\n\r\r\n\r\r\n \u001b[90m┌────────────────────────────────────┬─────────────────────────────────────────┐\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[36m\u001b[1mGeneral information\u001b[22m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[90m"] -[39.541352, "o", "│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Site name \u001b[39m\u001b[90m│\u001b[39m\u001b[39m Star Wars \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Site machine name \u001b[39m\u001b[90m│\u001b[39m\u001b[39m star_wars \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Organization name \u001b[39m\u001b[90m│\u001b[39m\u001b[39m Rebellion \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Organization machine name \u001b[39m\u001b[90m│\u001b[39m\u001b[39m rebellion \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Public domain \u001b[39m\u001b[90m│\u001b[39m\u001b[39m star-wars.com \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[36m\u001b[1mDrupal\u001b[22m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Starter \u001b[39m\u001b[90m│\u001b[39m\u001b[39m load_demodb \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m"] -[39.541771, "o", "\u001b[39m Webroot "] -[40.544451, "o", " \u001b[39m\u001b[90m│\u001b[39m\u001b[39m web \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Profile \u001b[39m\u001b[90m│\u001b[39m\u001b[39m standard \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Module prefix \u001b[39m\u001b[90m│\u001b[39m\u001b[39m sw \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Theme machine name \u001b[39m\u001b[90m│\u001b[39m\u001b[39m star_wars \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[36m\u001b[1mCode repository\u001b[22m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Code provider \u001b[39m\u001b[90m│\u001b[39m\u001b[39m github \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[36m\u001b[1mEnvironment\u001b[22m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Timezone "] -[40.544754, "o", " "] -[40.544988, "o", " \u001b[39m\u001b[90m│\u001b[39m\u001b[39m UTC \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Services \u001b[39m\u001b[90m│\u001b[39m\u001b[39m clamav, redis, solr \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Tools \u001b[39m\u001b[90m│\u001b[39m\u001b[39m phpcs, phpmd, phpstan, rector, phpunit,\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\u001b[39m behat \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[36m\u001b[1mHosting\u001b[22m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Hosting provider \u001b[39m\u001b[90m│\u001b[39m\u001b[39m none \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[36m\u001b[1mDeployment\u001b[22m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Deployment types "] -[40.545279, "o", " \u001b[39m\u001b[90m│\u001b[39m\u001b[39m webhook \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[36m\u001b[1mWorkflow\u001b[22m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Provision type \u001b[39m\u001b[90m│\u001b[39m\u001b[39m database \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Database source \u001b[39m\u001b[90m│\u001b[39m\u001b[39m url \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[36m\u001b[1mNotifications\u001b[22m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Channels \u001b[39m\u001b[90m│\u001b[39m\u001b[39m email \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[36m\u001b[1mContinuous Integration\u001b[22m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m CI provi"] -[40.545426, "o", "der "] -[40.545562, "o", " \u001b[39m\u001b[90m│\u001b[39m\u001b[39m gha \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[36m\u001b[1mAutomations\u001b[22m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Dependency updates provider \u001b[39m\u001b[90m│\u001b[39m\u001b[39m renovatebot_app \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Auto-assign PR author \u001b[39m\u001b[90m│\u001b[39m\u001b[39m Yes \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Auto-add a CONFLICT label to PRs \u001b[39m\u001b[90m│\u001b[39m\u001b[39m Yes \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[36m\u001b[1mDocumentation\u001b[22m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Preserve project documentation \u001b[39m\u001b[90m│\u001b[39m\u001b[39m Yes \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[36m\u001b[1mAI\u001b[22m\u001b[39m "] -[40.545694, "o", " "] -[40.545951, "o", " \u001b[39m\u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m AI code assistant instructions \u001b[39m\u001b[90m│\u001b[39m\u001b[39m none \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[36m\u001b[1mLocations\u001b[22m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Current directory \u001b[39m\u001b[90m│\u001b[39m\u001b[39m /home/user/www/demo \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Destination directory \u001b[39m\u001b[90m│\u001b[39m\u001b[39m /home/user/www/demo/star_wars \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Vortex repository \u001b[39m\u001b[90m│\u001b[39m\u001b[39m https://github.com/drevops/vortex.git \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Vortex reference \u001b[39m\u001b[90m│\u001b[39m\u001b[39m stable \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m└──────────────────"] -[40.546053, "o", "──"] -[40.54618, "o", "────────────────┴─────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n Vortex will be installed into your project's directory \"/home/user/www/demo/star_wars\"\r\r\n"] -[42.55137, "o", "\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mProceed with installing Vortex?\u001b[39m \u001b[90m─────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[32m●\u001b[39m Yes \u001b[2m/ ○ No\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n"] -[44.553849, "o", "\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mProceed with installing Vortex?\u001b[22m \u001b[90m─────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m Yes \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h\r\r\n \u001b[46m\u001b[30m Starting project installation \u001b[39m\u001b[49m\r\r\n\r\r\n\u001b[?25l\r\r\n \u001b[36m⠂\u001b[39m \u001b[33mDownloading Vortex\u001b[39m\r\r\n\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠒\u001b[39m \u001b[33mDownloading Vortex\u001b[39m\r\r\n\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠐\u001b[39m \u001b[33mDownloading Vortex\u001b[39m\r\r\n\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠰\u001b[39m \u001b[33mDownloading Vortex\u001b[39m\r\r\n\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠠\u001b[39m \u001b[33mDownloading Vortex\u001b[39m\r\r\n\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠤\u001b[39m \u001b[33mDownloading Vortex\u001b[39m\r\r\n\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠄\u001b[39m \u001b[33mDownloading Vortex\u001b[39m\r\r\n\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠆\u001b[39m \u001b[33mDownloading Vortex\u001b[39m\r\r\n\u001b[1G\u001b[2A"] -[44.554149, "o", "\u001b[J\r\r\n \u001b[36m⠂\u001b[39m \u001b[33"] -[45.554536, "o", "mDownloading Vortex\u001b[39m\r\r\n\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠒\u001b[39m \u001b[33mDownloading Vortex\u001b[39m\r\r\n\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠐\u001b[39m \u001b[33mDownloading Vortex\u001b[39m\r\r\n\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠰\u001b[39m \u001b[33mDownloading Vortex\u001b[39m\r\r\n\u001b[999D\u001b[2A\u001b[J\u001b[?25h\r\r\n \u001b[34m✦ Downloading Vortex\u001b[39m\r\r\n\r\r\n\r\r\n \u001b[A\u001b[A\u001b[A\u001b[A\u001b[A\r\r\n\r\r\n\r\r\n \u001b[2mDownloading from \"https://github.com/drevops/vortex.git\" repository at commit \"HEAD\"\u001b[22m\r\r\n\r\r\n\r\r\n \u001b[A\u001b[A\u001b[A\u001b[A\u001b[A\r\r\n\r\r\n\r\r\n \u001b[32m✓ Vortex downloaded (25.10.0)\u001b[39m\r\r\n\r\r\n\r\r\n \u001b[A\u001b[A\u001b[A\u001b[A\r\r\n\r\r\n\u001b[?25l\r\r\n \u001b[36m⠂\u001b[39m \u001b[33mCustomizing Vortex for your project\u001b[39m\r\r\n\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠒\u001b[39m \u001b[33mCustomizing Vortex for your project\u001b[39m\r\r\n\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠐\u001b[39m \u001b[33mCustomizing Vortex for your project\u001b[39m\r\r\n\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠰\u001b[39m \u001b[33mCustomizing Vortex for your project\u001b[39m\r\r\n\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠠\u001b[39m \u001b[33mCustomizing Vortex for your project\u001b[39m\r\r\n\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠤\u001b[39m \u001b[33mCustomizing Vortex for your project\u001b[39m\r\r\n\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠄\u001b[39m \u001b[33mCustomizing Vortex for your project\u001b["] -[45.554617, "o", "39m\r\r\n\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠆\u001b[39m \u001b[33m"] -[45.554722, "o", "Customizing Vortex for your project\u001b[39m\r\r\n"] -[45.63342, "o", "\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠂\u001b[39m \u001b[33mCustomizing Vortex for your project\u001b[39m\r\r\n"] -[45.712063, "o", "\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠒\u001b[39m \u001b[33mCustomizing Vortex for your project\u001b[39m\r\r\n"] -[45.790926, "o", "\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠐\u001b[39m \u001b[33mCustomizing Vortex for your project\u001b[39m\r\r\n"] -[45.869807, "o", "\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠰\u001b[39m \u001b[33mCustomizing Vortex for your project\u001b[39m\r\r\n"] -[45.949883, "o", "\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠠\u001b[39m \u001b[33mCustomizing Vortex for your project\u001b[39m\r\r\n"] -[46.02831, "o", "\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠤\u001b[39m \u001b[33mCustomizing Vortex for your project\u001b[39m\r\r\n"] -[46.108501, "o", "\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠄\u001b[39m \u001b[33mCustomizing Vortex for your project\u001b[39m\r\r\n"] -[46.187345, "o", "\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠆\u001b[39m \u001b[33mCustomizing Vortex for your project\u001b[39m\r\r\n"] -[46.266539, "o", "\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠂\u001b[39m \u001b[33mCustomizing Vortex for your project\u001b[39m\r\r\n"] -[46.299203, "o", "\u001b[999D\u001b[2A\u001b[J\u001b[?25h"] -[46.29923, "o", "\r\r\n \u001b[34m✦ Customizing Vortex for your project\u001b[39m\r\r\n\r\r\n\r\r\n \u001b[A\u001b[A\u001b[A\u001b[A\u001b[A\r\r\n\r\r\n"] -[46.299304, "o", "\r\r\n \u001b[32m✓ Vortex was customized for your project\u001b[39m\r\r\n\r\r\n"] -[46.299416, "o", "\r\r\n \u001b[A\u001b[A\u001b[A\u001b[A\r\r\n\r\r\n\u001b[?25l"] -[46.303776, "o", "\r\r\n \u001b[36m⠂\u001b[39m \u001b[33mPreparing destination directory\u001b[39m\r\r\n"] -[46.33237, "o", "\u001b[999D\u001b[2A\u001b[J\u001b[?25h"] -[46.332487, "o", "\r\r\n \u001b[34m✦ Preparing destination directory\u001b[39m\r\r\n\r\r\n\r\r\n \u001b[A\u001b[A\u001b[A\u001b[A\u001b[A\r\r\n\r\r\n"] -[46.332635, "o", "\r\r\n \u001b[2mCreated directory \"/home/user/www/demo/star_wars\".\u001b[22m\r\r\n\r\r\n\r\r\n \u001b[A\u001b[A\u001b[A\u001b[A\u001b[A\r\r\n\r\r\n\r\r\n \u001b[2mInitialising a new Git repository in directory \"/home/user/www/demo/star_wars\".\u001b[22m\r\r\n\r\r\n\r\r\n \u001b[A\u001b[A\u001b[A\u001b[A\u001b[A\r\r\n\r\r\n"] -[46.332673, "o", "\r\r\n \u001b[32m✓ Destination directory is ready\u001b[39m\r\r\n\r\r\n"] -[46.332734, "o", "\r\r\n \u001b[A\u001b[A\u001b[A\u001b[A\r\r\n\r\r\n"] -[46.332879, "o", "\u001b[?25l"] -[46.337626, "o", "\r\r\n \u001b[36m⠂\u001b[39m \u001b[33mCopying files to the destination directory\u001b[39m\r\r\n"] -[46.455592, "o", "\u001b[999D\u001b[2A\u001b[J"] -[46.455748, "o", "\u001b[?25h"] -[46.456007, "o", "\r\r\n \u001b[34m✦ Copying files to the destination directory\u001b[39m\r\r\n\r\r\n\r\r\n \u001b[A\u001b[A\u001b[A\u001b[A\u001b[A\r\r\n\r\r\n\r\r\n \u001b[32m✓ Files copied to destination directory\u001b[39m\r\r\n\r\r\n\r\r\n \u001b[A\u001b[A\u001b[A\u001b[A\r\r\n\r\r\n"] -[46.456145, "o", "\u001b[?25l"] -[46.458554, "o", "\r\r\n \u001b[36m⠂\u001b[39m \u001b[33mPreparing demo content\u001b[39m\r\r\n"] -[46.634213, "o", "\u001b[1G\u001b[2A\u001b[J"] -[46.634317, "o", "\r\r\n \u001b[36m⠒\u001b[39m \u001b[33mPreparing demo content\u001b[39m\r\r\n"] -[46.713087, "o", "\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠐\u001b[39m \u001b[33mPreparing demo content\u001b[39m\r\r\n"] -[46.791982, "o", "\u001b[1G\u001b[2A\u001b[J"] -[46.792101, "o", "\r\r\n \u001b[36m⠰\u001b[39m \u001b[33mPreparing demo content\u001b[39m\r\r\n"] -[46.871601, "o", "\u001b[1G\u001b[2A\u001b[J"] -[46.871826, "o", "\r\r\n \u001b[36m⠠\u001b[39m \u001b[33mPreparing demo content\u001b[39m\r\r\n"] -[46.951923, "o", "\u001b[1G\u001b[2A\u001b[J"] -[46.952041, "o", "\r\r\n \u001b[36m⠤\u001b[39m \u001b[33mPreparing demo content\u001b[39m\r\r\n"] -[47.029657, "o", "\u001b[999D\u001b[2A\u001b[J\u001b[?25h"] -[47.029876, "o", "\r\r\n \u001b[34m✦ Preparing demo content\u001b[39m\r\r\n\r\r\n\r\r\n \u001b[A\u001b[A\u001b[A\u001b[A\u001b[A\r\r\n\r\r\n"] -[47.030052, "o", "\r\r\n \u001b[2mCreated data directory \"/home/user/www/demo/star_wars/.data\".\u001b[22m\r\r\n\r\r\n\r\r\n \u001b[A\u001b[A\u001b[A\u001b[A\u001b[A\r\r\n\r\r\n\r\r\n \u001b[2mNo database dump file was found in \"/home/user/www/demo/star_wars/.data\" directory.\u001b[22m\r\r\n\r\r\n\r\r\n \u001b[A\u001b[A\u001b[A\u001b[A\u001b[A\r\r\n\r\r\n\r\r\n \u001b[2mDownloaded demo database from https://github.com/drevops/vortex/releases/download/25.4.0/db_d11.demo.sql.\u001b[22m\r\r\n\r\r\n\r\r\n \u001b[A\u001b[A\u001b[A\u001b[A\u001b[A\r\r\n\r\r\n"] -[47.030235, "o", "\r\r\n \u001b[32m✓ Demo content prepared\u001b[39m\r\r\n\r\r\n\r\r\n \u001b[A\u001b[A\u001b[A\u001b[A\r\r\n\r\r\n"] -[47.0502, "o", "\r\r\n \u001b[90m┌──────────────────────────────────────────────────────────────────────────┐\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[32mFinished installing Vortex\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[32m──────────────────────────\u001b[39m\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Next steps:\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Add and commit all files:\u001b[39m\u001b[39m \u001b[39"] -[47.05032, "o", "m\u001b[90m"] -[47.050451, "o", "│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m cd /home/user/www/demo/star_wars\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m git add -A\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m git commit -m \"Initial commit.\"\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Build project locally:\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m ahoy build\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Setup integration with your hosting and CI/CD providers:\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m "] -[47.050475, "o", " See htt"] -[47.050541, "o", "ps://www.vortextemplate.com/docs/getting-started/installation\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m└──────────────────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n"] +{"version": 2, "width": 120, "height": 36, "timestamp": 1763520577, "env": {"SHELL": "/opt/homebrew/opt/bash/bin/bash", "TERM": "xterm-256color"}, "title": "Vortex Installer Demo"} +[0.3682, "o", "\r\r\n \u001b[36m──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────\u001b[39m\r\r\n \u001b[36m\u001b[39m\r\r\n \u001b[36m\u001b[39m\r\r\n \u001b[36m ██╗ ██╗ ██████╗ ██████╗ ████████╗ ███████╗ ██╗ ██╗\u001b[39m\r\r\n \u001b[36m ██║ ██║ ██╔═══██╗ ██╔══██╗ ╚══██╔══╝ ██╔════╝ ╚██╗██╔╝\u001b[39m\r\r\n \u001b[36m ██║ ██║ ██║ ██║ ██████╔╝ ██║ █████╗ ╚███╔╝\u001b[39m\r\r\n \u001b[36m ╚██╗ ██╔╝ █"] +[0.368354, "o", "█║ "] +[0.368439, "o", " ██║ ██╔══██╗ ██║ ██╔══╝ ██╔██╗\u001b[39m\r\r\n \u001b[36m ╚████╔╝ ╚██████╔╝ ██║ ██║ ██║ ███████╗ ██╔╝ ██╗\u001b[39m\r\r\n \u001b[36m ╚═══╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚══════╝ ╚═╝ ╚═╝\u001b[39m\r\r\n \u001b[36m\u001b[39m\r\r\n \u001b[36m Drupal project template\u001b[39m\r\r\n \u001b[36m\u001b[39m\r\r\n \u001b[36m by DrevOps\u001b[39m\r\r\n \u001b[36m\u001b[39m\r\r\n \u001b[36m────────────────────────────────────────────────────────────────────────────────────────────────────────────────"] +[0.368493, "o", "──────\u001b[39m\r\r\n \u001b[2m Installer version: development\u001b[22m\r\r\n\r\r\n"] +[0.371455, "o", "\r\r\n \u001b[90m┌──────────────────────────────────────────────────────────────────────────────────────┐\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[32mWelcome to the Vortex interactive installer\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[32m───────────────────────────────────────────\u001b[39m\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m This tool will guide you through installing the latest \u001b[4mstable\u001b[0m version of Vortex into\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m your project.\u001b[39m\u001b[39m "] +[0.371524, "o", " \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m You will be asked a few questions to tailor the configuration to your site.\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m No changes will be made until you confirm everything at the end.\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Press \u001b[33mCtrl+C\u001b[39m at any time to exit the installer.\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Press \u001b[33mCtrl+U\u001b[39m at any time to go back to the previous step.\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m└───────"] +[0.3716, "o", "─────"] +[0.37163, "o", "──────────────────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n \u001b[2mPress any key to continue...\u001b[22m\r\r\n"] +[3.384641, "o", "\r\r\n \u001b[46m\u001b[30m General information \u001b[39m\u001b[49m\r\r\n\r\r\n"] +[3.397304, "o", "\u001b[?25l"] +[3.401106, "o", "\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mSite name \u001b[2m(1/28)\u001b[22m\u001b[39m \u001b[90m────────────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m star wars\u001b[7m \u001b[27m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m We will use this name in the project and documentation.\u001b[39m\r\r\n"] +[3.556054, "o", "\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mSite name \u001b[2m(1/28)\u001b[22m\u001b[39m \u001b[90m────────────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m star w\u001b[7m \u001b[27m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m We will use this name in the project and documentation.\u001b[39m\r\r\n\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mSite name \u001b[2m(1/28)\u001b[22m\u001b[39m \u001b[90m────────────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m\u001b[7mE\u001b[27m.g. My Site\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────"] +[3.55812, "o", "──"] +[4.632076, "o", "──────────────────────────┘\u001b[39m\r\r\n\u001b[90m We will use this name in the project and documentation.\u001b[39m\r\r\n\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mSite name \u001b[2m(1/28)\u001b[22m\u001b[39m \u001b[90m────────────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m S\u001b[7m \u001b[27m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m We will use this name in the project and documentation.\u001b[39m\r\r\n\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mSite name \u001b[2m(1/28)\u001b[22m\u001b[39m \u001b[90m────────────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m St\u001b[7m \u001b[27m "] +[4.632806, "o", " "] +[4.633255, "o", " \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m We will use this name in the project and documentation.\u001b[39m\r\r\n"] +[5.638545, "o", "\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mSite name \u001b[2m(1/28)\u001b[22m\u001b[39m \u001b[90m────────────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m Star Wars\u001b[7m \u001b[27m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m We will use this name in the project and documentation.\u001b[39m\r\r\n"] +[5.645494, "o", "\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mSite name \u001b[2m(1/28)\u001b[22m\u001b[22m \u001b[90m────────────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m Star Wars \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n"] +[5.645565, "o", "\u001b[?25h"] +[5.663436, "o", "\u001b[?25l"] +[5.666447, "o", "\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mSite machine name \u001b[2m(2/28)\u001b[22m\u001b[39m \u001b[90m────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m star_wars\u001b[7m \u001b[27m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m We will use this name for the project directory and in the code.\u001b[39m\r\r\n"] +[6.678807, "o", "\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mSite machine name \u001b[2m(2/28)\u001b[22m\u001b[22m \u001b[90m────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m star_wars \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n"] +[6.678912, "o", "\u001b[?25h"] +[6.695466, "o", "\u001b[?25l"] +[6.698491, "o", "\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mOrganization name \u001b[2m(3/28)\u001b[22m\u001b[39m \u001b[90m────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m Star Wars Org\u001b[7m \u001b[27m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m We will use this name in the project and documentation.\u001b[39m\r\r\n"] +[6.853341, "o", "\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mOrganization name \u001b[2m(3/28)\u001b[22m\u001b[39m \u001b[90m────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m Star Wars O\u001b[7m \u001b[27m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m We will use this name in the project and documentation.\u001b[39m\r\r\n\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mOrganization name \u001b[2m(3/28)\u001b[22m\u001b[39m \u001b[90m────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m\u001b[7mE\u001b[27m.g. My Org\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └────────────────────────────────────────────"] +[6.853758, "o", "───"] +[7.741694, "o", "───────────────┘\u001b[39m\r\r\n\u001b[90m We will use this name in the project and documentation.\u001b[39m\r\r\n\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mOrganization name \u001b[2m(3/28)\u001b[22m\u001b[39m \u001b[90m────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m R\u001b[7m \u001b[27m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m We will use this name in the project and documentation.\u001b[39m\r\r\n\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mOrganization name \u001b[2m(3/28)\u001b[22m\u001b[39m \u001b[90m────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m Re\u001b[7m \u001b[27m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └─────"] +[7.742027, "o", "────"] +[7.74238, "o", "─────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m We will use this name in the project and documentation.\u001b[39m\r\r\n"] +[8.747491, "o", "\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mOrganization name \u001b[2m(3/28)\u001b[22m\u001b[39m \u001b[90m────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m Rebellion\u001b[7m \u001b[27m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m We will use this name in the project and documentation.\u001b[39m\r\r\n"] +[9.752128, "o", "\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mOrganization name \u001b[2m(3/28)\u001b[22m\u001b[22m \u001b[90m────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m Rebellion \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mOrganization machine name \u001b[2m(4/28)\u001b[22m\u001b[39m \u001b[90m────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m rebellion\u001b[7m \u001b[27m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m We will use this name in the co"] +[9.753078, "o", "de.\u001b[39m\r\r\r\n"] +[10.759939, "o", "\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mOrganization machine name \u001b[2m(4/28)\u001b[22m\u001b[22m \u001b[90m────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m rebellion \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mPublic domain \u001b[2m(5/28)\u001b[22m\u001b[39m \u001b[90m────────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m star-wars.com\u001b[7m \u001b[27m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m Domain name without pro"] +[10.761208, "o", "tocol and"] +[10.763318, "o", " trailing slash.\u001b[39m\r\r\n"] +[11.768542, "o", "\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mPublic domain \u001b[2m(5/28)\u001b[22m\u001b[22m \u001b[90m────────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m star-wars.com \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h\r\r\n \u001b[46m\u001b[30m Drupal \u001b[39m\u001b[49m\r\r\n\r\r\n\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mHow would you like your site to be created on the first run? \u001b[2m(6/28)\u001b[22m\u001b[39m \u001b[90m┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Choose how your site will be created the first time after this \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m installer finishes: \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m "] +[11.76905, "o", " "] +[11.778925, "o", " \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m ○ \u001b[1mDrupal, installed from profile\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Creates a new site by \u001b[4mpopulating a fresh database\u001b[0m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m from one of the standard Drupal installation profiles. \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m ○ \u001b[1mDrupal CMS, installed from profile\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Creates a new site by \u001b[4mpopulating a fresh database\u001b[0m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m from the Drupal CMS recipe. \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m ○ \u001b[1mDrupal, loaded from the demo database\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Creates a site by \u001b[4mloadin"] +[11.779036, "o", "g an exist"] +[12.775708, "o", "ing demo database\u001b[0m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m provided with the installer. \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m ├─────────────────────────────────────────────────────────────────────┤\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mDrupal, installed from profile\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mDrupal CMS, installed from profile\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m›\u001b[39m \u001b[36m●\u001b[39m Drupal, loaded from the demo database \u001b[90m│\u001b[39m\r\r\n\u001b[90m └────────────────────────────────────────────────────────────"] +[12.775988, "o", "──"] +[12.776756, "o", "───────┘\u001b[39m\r\r\n\u001b[90m Use ⬆ and ⬇. Applies only on the first run of the installer.\u001b[39m\r\r\n"] +[13.784284, "o", "\u001b[1G\u001b[24A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mHow would you like your site to be created on the first run? \u001b[2m(6/28)\u001b[22m\u001b[22m \u001b[90m┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Choose how your site will be created the first time after this \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m installer finishes: \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m ○ \u001b[1mDrupal, installed from profile\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Creates a new site by \u001b[4mpopulating a fresh database\u001b[0m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m from one of the standard Drupal installation profiles. \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m ○ \u001b[1mDrupal CMS, installed from profile\u001b[22m "] +[13.784379, "o", " "] +[13.784575, "o", " \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Creates a new site by \u001b[4mpopulating a fresh database\u001b[0m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m from the Drupal CMS recipe. \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m ○ \u001b[1mDrupal, loaded from the demo database\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Creates a site by \u001b[4mloading an existing demo database\u001b[0m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m provided with the installer. \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m ├─────────────────────────────────────────────────────────────────────┤\u001b[39m\r\r\n\u001b[90m │\u001b[39m Drupal, loaded from the demo database "] +[13.784596, "o", " \u001b[90m│\u001b[39m\r\r\n\u001b[90m └─────────────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h"] +[14.789798, "o", "\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mProfile \u001b[2m(7/28)\u001b[22m\u001b[39m \u001b[90m──────────────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m›\u001b[39m \u001b[36m●\u001b[39m Standard \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mMinimal\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mDemo Umami\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mCustom (next prompt)\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m Use ⬆ and ⬇ to select which Drupal profile to use.\u001b[39m\r\r\n"] +[15.793177, "o", "\u001b[1G\u001b[8A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mProfile \u001b[2m(7/28)\u001b[22m\u001b[22m \u001b[90m──────────────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m Standard \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mModules \u001b[2m(8/28)\u001b[22m\u001b[39m \u001b[90m──────────────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m› ◼\u001b[39m Admin toolbar \u001b[36m┃\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m◼\u001b[39m \u001b[2mCoffee\u001b[22m \u001b[90m│\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m◼\u001b[39m \u001b[2mConfig spli"] +[15.793566, "o", "t\u001b[22m "] +[15.797159, "o", " \u001b[90m│\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m◼\u001b[39m \u001b[2mConfig update\u001b[22m \u001b[90m│\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m◼\u001b[39m \u001b[2mEnvironment indicator\u001b[22m \u001b[90m│\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m◼\u001b[39m \u001b[2mPathauto\u001b[22m \u001b[90m│\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m◼\u001b[39m \u001b[2mRedirect\u001b[22m \u001b[90m│\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m◼\u001b[39m \u001b[2mRobots.txt\u001b[22m \u001b[90m│\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m◼\u001b[39m \u001b[2mSeckit\u001b[22m \u001b[90m│\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m◼\u001b[39m \u001b[2mShield\u001b[22m \u001b[90m│\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └───────────────────────"] +[15.797204, "o", "───"] +[16.798824, "o", "─────────────────────── 11 selected ┘\u001b[39m\r\r\n\u001b[90m Use ⬆, ⬇ and Space bar to select one or more modules.\u001b[39m\r\r\n\u001b[1G\u001b[14A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mModules \u001b[2m(8/28)\u001b[22m\u001b[22m \u001b[90m──────────────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m Admin toolbar \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Coffee \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Config split \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Config update \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Environment indicator \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Pathauto \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Redirect \u001b[90m│\u001b[39m\r"] +[16.799105, "o", "\r\n\u001b[90m │"] +[16.799395, "o", "\u001b[39m Robots.txt \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Seckit \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Shield \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Stage file proxy \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h"] +[17.806471, "o", "\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mCustom modules prefix \u001b[2m(9/28)\u001b[22m\u001b[39m \u001b[90m────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m sw\u001b[7m \u001b[27m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m We will use this name in custom modules\u001b[39m\r\r\n\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mCustom modules prefix \u001b[2m(9/28)\u001b[22m\u001b[22m \u001b[90m────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m sw \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b"] +[17.810916, "o", "[39m\r\r\n\r\r\n"] +[17.8111, "o", "\u001b[?25h"] +[18.816824, "o", "\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mTheme \u001b[2m(10/28)\u001b[22m\u001b[39m \u001b[90m───────────────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mOlivero\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mClaro\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mStark\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m›\u001b[39m \u001b[36m●\u001b[39m Custom (next prompt) \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m Use ⬆ and ⬇ to select which Drupal theme to use.\u001b[39m\r\r\n\u001b[1G\u001b[8A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mTheme \u001b[2m(10/28)\u001b[22m\u001b[22m \u001b[90m──────"] +[18.817224, "o", "───"] +[18.828395, "o", "──────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m Custom (next prompt) \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h"] +[19.827665, "o", "\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mCustom theme machine name \u001b[2m(11/28)\u001b[22m\u001b[39m \u001b[90m───────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m star_wars\u001b[7m \u001b[27m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m We will use this name as a custom theme name\u001b[39m\r\r\n\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mCustom theme machine name \u001b[2m(11/28)\u001b[22m\u001b[22m \u001b[90m───────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m star_wars \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25"] +[19.828021, "o", "h\r\r\n \u001b[46m\u001b"] +[19.829441, "o", "[30m Code repository \u001b[39m\u001b[49m\r\r\n\r\r\n"] +[20.832389, "o", "\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mRepository provider \u001b[2m(12/28)\u001b[22m\u001b[39m \u001b[90m─────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Vortex offers full automation with GitHub, while support for \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m other providers is limited. \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m ├──────────────────────────────────────────────────────────────┤\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m›\u001b[39m \u001b[36m●\u001b[39m GitHub \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mOther\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └─────────"] +[20.83255, "o", "───"] +[20.832604, "o", "──────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m Use ⬆ and ⬇ to select your code repository provider.\u001b[39m\r\r\n"] +[21.861072, "o", "\u001b[1G\u001b[11A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mRepository provider \u001b[2m(12/28)\u001b[22m\u001b[22m \u001b[90m─────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Vortex offers full automation with GitHub, while support for \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m other providers is limited. \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m ├──────────────────────────────────────────────────────────────┤\u001b[39m\r\r\n\u001b[90m │\u001b[39m GitHub \u001b[90m│\u001b[39m\r\r\n\u001b[90m └────────────────────────────────────────────────────"] +[21.861204, "o", "───"] +[21.86122, "o", "───────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h"] +[22.866443, "o", "\r\r\n \u001b[46m\u001b[30m Environment \u001b[39m\u001b[49m\r\r\n\r\r\n\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mTimezone \u001b[2m(13/28)\u001b[22m\u001b[39m \u001b[90m────────────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m UTC\u001b[7m \u001b[27m \u001b[90m│\u001b[39m\r\r\n\u001b[90m ├──────────────────────────────────────────────────────────────┤\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2mUTC\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m Use ⬆ and ⬇, or start typing to select the timezone for your project.\u001b[39m\r\r\n"] +[23.87148, "o", "\u001b[1G\u001b[7A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mTimezone \u001b[2m(13/28)\u001b[22m\u001b[22m \u001b[90m────────────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m UTC \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mServices \u001b[2m(14/28)\u001b[22m\u001b[39m \u001b[90m────────────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m› ◼\u001b[39m ClamAV \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m◼\u001b[39m \u001b[2mSolr\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m◼\u001b[39m \u001b[2mRedis\u001b[22m "] +[23.871977, "o", " "] +[23.873174, "o", " \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m Use ⬆, ⬇ and Space bar to select one or more services.\u001b[39m\r\r\n"] +[24.877219, "o", "\u001b[1G\u001b[7A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mServices \u001b[2m(14/28)\u001b[22m\u001b[22m \u001b[90m────────────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m ClamAV \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Solr \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Redis \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mDevelopment tools \u001b[2m(15/28)\u001b[22m\u001b[39m \u001b[90m───────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m› ◼\u001b[39m PHP CodeSniffer \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m◼"] +[24.878163, "o", "\u001b[39m \u001b[2mPHPStan\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m◼\u001b[39m \u001b[2mRector\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m◼\u001b[39m \u001b[2mPHP Mess Detector\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m◼\u001b[39m \u001b[2mPHPUnit\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m◼\u001b[39m \u001b[2mBehat\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m Use ⬆, ⬇ and Space bar to select one or more tools.\u001b[39m\r\r\n"] +[25.883368, "o", "\u001b[1G\u001b[10A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mDevelopment tools \u001b[2m(15/28)\u001b[22m\u001b[22m \u001b[90m───────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m PHP CodeSniffer \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m PHPStan \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Rector \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m PHP Mess Detector \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m PHPUnit \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Behat \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h\r\r\n \u001b[46m\u001b[30m Hosting \u001b[39m\u001b[49m\r\r\n\r\r\n\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m"] +[25.886549, "o", " \u001b[36mHosting "] +[25.890107, "o", "provider \u001b[2m(16/28)\u001b[22m\u001b[39m \u001b[90m────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mAcquia Cloud\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mLagoon\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mOther\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m›\u001b[39m \u001b[36m●\u001b[39m None \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m Use ⬆, ⬇ and Space bar to select your hosting provider.\u001b[39m\r\r\n"] +[26.895206, "o", "\u001b[1G\u001b[8A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mHosting provider \u001b[2m(16/28)\u001b[22m\u001b[22m \u001b[90m────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m None \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mCustom web root directory \u001b[2m(17/28)\u001b[22m\u001b[39m \u001b[90m───────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m web\u001b[7m \u001b[27m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m Custom directory where the web se"] +[26.895469, "o", "rver serv"] +[26.895728, "o", "es the site.\u001b[39m\r\r\n"] +[27.899544, "o", "\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mCustom web root directory \u001b[2m(17/28)\u001b[22m\u001b[22m \u001b[90m───────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m web \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h\r\r\n \u001b[46m\u001b[30m Deployment \u001b[39m\u001b[49m\r\r\n\r\r\n\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mDeployment types \u001b[2m(18/28)\u001b[22m\u001b[39m \u001b[90m────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m›\u001b[39m ◻ Code artifact \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m◻\u001b[22m \u001b[2mLagoon webhook\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m◻\u001b[22m \u001b[2mContainer image\u001b[22m "] +[27.900007, "o", " \u001b[9"] +[27.900389, "o", "0m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m◼\u001b[39m \u001b[2mCustom webhook\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m Use ⬆, ⬇ and Space bar to select one or more deployment types.\u001b[39m\r\r\n"] +[28.906668, "o", "\u001b[1G\u001b[8A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mDeployment types \u001b[2m(18/28)\u001b[22m\u001b[22m \u001b[90m────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m Custom webhook \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h\r\r\n \u001b[46m\u001b[30m Workflow \u001b[39m\u001b[49m\r\r\n\r\r\n\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mProvision type \u001b[2m(19/28)\u001b[22m\u001b[39m \u001b[90m──────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Provisioning sets up the site in an environment using an \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m already assembled codebase. \u001b[90m│\u001b[39m\r\r\n\u001b[90m │"] +[28.912852, "o", "\u001b[39m "] +[28.915184, "o", " \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m ○ \u001b[1mImport from database dump\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Provisions the site by importing a database dump \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m typically copied from production into lower \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m environments. \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m ○ \u001b[1mInstall from profile\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Provisions the site by installing a fresh Drupal \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m site from a profile every time an environment is \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m created. \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m ├─"] +[28.915401, "o", "───"] +[29.920404, "o", "──────────────────────────────────────────────────────────┤\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m›\u001b[39m \u001b[36m●\u001b[39m Import from database dump \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mInstall from profile\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m Use ⬆ and ⬇ to select the provision type.\u001b[39m\r\r\n\u001b[1G\u001b[21A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mProvision type \u001b[2m(19/28)\u001b[22m\u001b[22m \u001b[90m──────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Provisioning sets up the site in an e"] +[29.920699, "o", "nvironment"] +[29.92103, "o", " using an \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m already assembled codebase. \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m ○ \u001b[1mImport from database dump\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Provisions the site by importing a database dump \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m typically copied from production into lower \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m environments. \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m ○ \u001b[1mInstall from profile\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Provisions the site by installing a fresh Drupal \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m site from a profile every time an environment is \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m created. "] +[29.921283, "o", " "] +[30.927338, "o", " \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m ├──────────────────────────────────────────────────────────────┤\u001b[39m\r\r\n\u001b[90m │\u001b[39m Import from database dump \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mDatabase source \u001b[2m(20/28)\u001b[22m\u001b[39m \u001b[90m─────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m›\u001b[39m \u001b[36m●\u001b[39m URL download \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mFTP download\u001b[22m "] +[30.927486, "o", " "] +[30.927648, "o", " \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mAcquia backup\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mLagoon environment\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mContainer registry\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mNone\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m Use ⬆ and ⬇ to select the database download source.\u001b[39m\r\r\n"] +[31.937407, "o", "\u001b[1G\u001b[10A\u001b[J"] +[31.937434, "o", "\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mDatabase source \u001b[2m(20/28)\u001b[22m\u001b[22m \u001b[90m─────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m URL download \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n"] +[31.937574, "o", "\u001b[?25h"] +[32.943415, "o", "\r\r\n \u001b[46m\u001b[30m Notifications \u001b[39m\u001b[49m\r\r\n\r\r\n\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mNotification channels \u001b[2m(21/28)\u001b[22m\u001b[39m \u001b[90m───────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m› ◼\u001b[39m Email \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m◻\u001b[22m \u001b[2mGitHub\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m◻\u001b[22m \u001b[2mJIRA\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m◻\u001b[22m \u001b[2mNew Relic\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m◻\u001b[22m \u001b[2mSlack\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m◻\u001b[22m \u001b[2mWebhook\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └────────────────────────────────────────"] +[32.943888, "o", "────"] +[32.944503, "o", "──────────────────┘\u001b[39m\r\r\n\u001b[90m Use ⬆, ⬇ and Space bar to select one or more notification channels.\u001b[39m\r\r\n"] +[33.949633, "o", "\u001b[1G\u001b[10A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mNotification channels \u001b[2m(21/28)\u001b[22m\u001b[22m \u001b[90m───────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m Email \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h\r\r\n \u001b[46m\u001b[30m Continuous Integration \u001b[39m\u001b[49m\r\r\n\r\r\n\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mContinuous Integration provider \u001b[2m(22/28)\u001b[22m\u001b[39m \u001b[90m─────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m›\u001b[39m \u001b[36m●\u001b[39m GitHub Actions \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mCircleCI\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mNone\u001b[22m "] +[33.950461, "o", " \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m Use ⬆ and ⬇ to select the CI provider.\u001b[39m\r\r\n"] +[34.956101, "o", "\u001b[1G\u001b[7A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mContinuous Integration provider \u001b[2m(22/28)\u001b[22m\u001b[22m \u001b[90m─────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m GitHub Actions \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h\r\r\n \u001b[46m\u001b[30m Automations \u001b[39m\u001b[49m\r\r\n\r\r\n\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mDependency updates provider \u001b[2m(23/28)\u001b[22m\u001b[39m \u001b[90m─────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m›\u001b[39m \u001b[36m●\u001b[39m Renovate GitHub app \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mRenovate self-hosted in CI\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mNone\u001b[22m \u001b[90m│\u001b[39m\r"] +[34.95688, "o", "\r\n\u001b[90m └"] +[34.961566, "o", "──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m Use ⬆ and ⬇ to select the dependency updates provider.\u001b[39m\r\r\n"] +[35.966209, "o", "\u001b[1G\u001b[7A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mDependency updates provider \u001b[2m(23/28)\u001b[22m\u001b[22m \u001b[90m─────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m Renovate GitHub app \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mAuto-assign the author to their PR? \u001b[2m(24/28)\u001b[22m\u001b[39m \u001b[90m─────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[32m●\u001b[39m Yes \u001b[2m/ ○ No\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m Helps to keep the PRs organized.\u001b[39m\r\r\n"] +[36.971467, "o", "\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mAuto-assign the author to their PR? \u001b[2m(24/28)\u001b[22m\u001b[22m \u001b[90m─────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m Yes \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mAuto-add a CONFLICT label to a PR when conflicts occur? \u001b[2m(25/28)\u001b[22m\u001b[39m \u001b[90m┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[32m●\u001b[39m Yes \u001b[2m/ ○ No\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └─────────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m Helps to keep quickly identify PRs that need attention.\u001b[39m\r\r\n"] +[37.978478, "o", "\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mAuto-add a CONFLICT label to a PR when conflicts occur? \u001b[2m(25/28)\u001b[22m\u001b[22m \u001b[90m┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m Yes \u001b[90m│\u001b[39m\r\r\n\u001b[90m └─────────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h\r\r\n \u001b[46m\u001b[30m Documentation \u001b[39m\u001b[49m\r\r\n\r\r\n\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mPreserve project documentation? \u001b[2m(26/28)\u001b[22m\u001b[39m \u001b[90m─────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[32m●\u001b[39m Yes \u001b[2m/ ○ No\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m Helps to maintain the project documentation"] +[37.9798, "o", " within the repository.\u001b[39m\r\r\n"] +[38.983741, "o", "\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mPreserve project documentation? \u001b[2m(26/28)\u001b[22m\u001b[22m \u001b[90m─────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m Yes \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h\r\r\n \u001b[46m\u001b[30m AI \u001b[39m\u001b[49m\r\r\n\r\r\n\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mAI code assistant instructions \u001b[2m(27/28)\u001b[22m\u001b[39m \u001b[90m──────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mAnthropic Claude\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m›\u001b[39m \u001b[36m●\u001b[39m None \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────"] +[38.984599, "o", "────"] +[38.986872, "o", "────────────────────┘\u001b[39m\r\r\n\u001b[90m Provides AI coding assistants with better context about the project.\u001b[39m\r\r\n"] +[39.993909, "o", "\u001b[1G\u001b[6A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mAI code assistant instructions \u001b[2m(27/28)\u001b[22m\u001b[22m \u001b[90m──────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m None \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h\r\r\n \u001b[46m\u001b[30m \u001b[39m\u001b[49m\r\r\n \u001b[46m\u001b[30m Installation summary \u001b[39m\u001b[49m\r\r\n \u001b[46m\u001b[30m \u001b[39m\u001b[49m\r\r\n\r\r\n\r\r\n \u001b[90m┌────────────────────────────────────┬─────────────────────────────────────────┐\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[36m\u001b[1mGeneral information\u001b[22m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[90m"] +[39.994102, "o", "│\u001b[39m\r\r\n \u001b"] +[39.994497, "o", "[90m│\u001b[39m\u001b[39m Site name \u001b[39m\u001b[90m│\u001b[39m\u001b[39m Star Wars \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Site machine name \u001b[39m\u001b[90m│\u001b[39m\u001b[39m star_wars \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Organization name \u001b[39m\u001b[90m│\u001b[39m\u001b[39m Rebellion \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Organization machine name \u001b[39m\u001b[90m│\u001b[39m\u001b[39m rebellion \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Public domain \u001b[39m\u001b[90m│\u001b[39m\u001b[39m star-wars.com \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[36m\u001b[1mDrupal\u001b[22m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Starter \u001b[39m\u001b[90m│\u001b[39m\u001b[39m load_demodb \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Modul"] +[39.995222, "o", "es "] +[41.000413, "o", " \u001b[39m\u001b[90m│\u001b[39m\u001b[39m admin_toolbar, coffee, config_split,\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\u001b[39m config_update, environment_indicator,\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\u001b[39m pathauto, redirect, robotstxt, seckit,\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\u001b[39m shield, stage_file_proxy \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Webroot \u001b[39m\u001b[90m│\u001b[39m\u001b[39m web \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Profile \u001b[39m\u001b[90m│\u001b[39m\u001b[39m standard \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Module prefix \u001b[39m\u001b[90m│\u001b[39m\u001b[39m sw \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Theme machine name "] +[41.001235, "o", " "] +[41.001633, "o", "\u001b[39m\u001b[90m│\u001b[39m\u001b[39m star_wars \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[36m\u001b[1mCode repository\u001b[22m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Code provider \u001b[39m\u001b[90m│\u001b[39m\u001b[39m github \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[36m\u001b[1mEnvironment\u001b[22m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Timezone \u001b[39m\u001b[90m│\u001b[39m\u001b[39m UTC \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Services \u001b[39m\u001b[90m│\u001b[39m\u001b[39m clamav, redis, solr \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Tools \u001b[39m\u001b[90m│\u001b[39m\u001b[39m phpcs, phpmd, phpstan, rector, phpunit,\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m "] +[41.001663, "o", " \u001b[3"] +[41.001842, "o", "9m\u001b[90m│\u001b[39m\u001b[39m behat \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[36m\u001b[1mHosting\u001b[22m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Hosting provider \u001b[39m\u001b[90m│\u001b[39m\u001b[39m none \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[36m\u001b[1mDeployment\u001b[22m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Deployment types \u001b[39m\u001b[90m│\u001b[39m\u001b[39m webhook \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[36m\u001b[1mWorkflow\u001b[22m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Provision type \u001b[39m\u001b[90m│\u001b[39m\u001b[39m database \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Database source "] +[41.002029, "o", " "] +[41.002247, "o", " \u001b[39m\u001b[90m│\u001b[39m\u001b[39m url \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[36m\u001b[1mNotifications\u001b[22m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Channels \u001b[39m\u001b[90m│\u001b[39m\u001b[39m email \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[36m\u001b[1mContinuous Integration\u001b[22m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m CI provider \u001b[39m\u001b[90m│\u001b[39m\u001b[39m gha \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[36m\u001b[1mAutomations\u001b[22m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Dependency updates provider \u001b[39m\u001b[90m│\u001b[39m\u001b[39m renovatebot_app \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Auto-assign PR au"] +[41.002527, "o", "thor "] +[41.002788, "o", " \u001b[39m\u001b[90m│\u001b[39m\u001b[39m Yes \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Auto-add a CONFLICT label to PRs \u001b[39m\u001b[90m│\u001b[39m\u001b[39m Yes \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[36m\u001b[1mDocumentation\u001b[22m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Preserve project documentation \u001b[39m\u001b[90m│\u001b[39m\u001b[39m Yes \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[36m\u001b[1mAI\u001b[22m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m AI code assistant instructions \u001b[39m\u001b[90m│\u001b[39m\u001b[39m none \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[36m\u001b[1mLocations\u001b[22m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Current dir"] +[41.003071, "o", "ectory "] +[41.003446, "o", " \u001b[39m\u001b[90m│\u001b[39m\u001b[39m /home/user/www/demo \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Destination directory \u001b[39m\u001b[90m│\u001b[39m\u001b[39m /home/user/www/demo/star_wars \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Vortex repository \u001b[39m\u001b[90m│\u001b[39m\u001b[39m https://github.com/drevops/vortex.git \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Vortex reference \u001b[39m\u001b[90m│\u001b[39m\u001b[39m stable \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m└────────────────────────────────────┴─────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n Vortex will be installed into your project's directory \"/home/user/www/demo/star_wars\"\r\r\n"] +[43.011408, "o", "\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mProceed with installing Vortex?\u001b[39m \u001b[90m─────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[32m●\u001b[39m Yes \u001b[2m/ ○ No\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n"] +[45.016565, "o", "\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mProceed with installing Vortex?\u001b[22m \u001b[90m─────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m Yes \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h\r\r\n \u001b[46m\u001b[30m Starting project installation \u001b[39m\u001b[49m\r\r\n\r\r\n\u001b[?25l\r\r\n \u001b[36m⠂\u001b[39m \u001b[33mDownloading Vortex\u001b[39m\r\r\n\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠒\u001b[39m \u001b[33mDownloading Vortex\u001b[39m\r\r\n\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠐\u001b[39m \u001b[33mDownloading Vortex\u001b[39m\r\r\n\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠰\u001b[39m \u001b[33mDownloading Vortex\u001b[39m\r\r\n\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠠\u001b[39m \u001b[33mDownloading Vortex\u001b[39m\r\r\n\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠤\u001b[39m \u001b[33mDownloading Vortex\u001b[39m\r\r\n\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠄\u001b[39m \u001b[33mDownloading Vortex\u001b[39m\r\r\n\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠆\u001b[39m \u001b[33mDownloading Vortex\u001b[39m\r\r\n\u001b[1G\u001b[2A"] +[45.016676, "o", "\u001b[J\r\r\n \u001b[36m⠂\u001b[39m \u001b[33"] +[46.021673, "o", "mDownloading Vortex\u001b[39m\r\r\n\u001b[999D\u001b[2A\u001b[J\u001b[?25h\r\r\n \u001b[34m✦ Downloading Vortex\u001b[39m\r\r\n\r\r\n\r\r\n \u001b[A\u001b[A\u001b[A\u001b[A\u001b[A\r\r\n\r\r\n\r\r\n \u001b[2mDownloading from \"https://github.com/drevops/vortex.git\" repository at commit \"HEAD\"\u001b[22m\r\r\n\r\r\n\r\r\n \u001b[A\u001b[A\u001b[A\u001b[A\u001b[A\r\r\n\r\r\n\r\r\n \u001b[32m✓ Vortex downloaded (25.10.0)\u001b[39m\r\r\n\r\r\n\r\r\n \u001b[A\u001b[A\u001b[A\u001b[A\r\r\n\r\r\n\u001b[?25l\r\r\n \u001b[36m⠂\u001b[39m \u001b[33mCustomizing Vortex for your project\u001b[39m\r\r\n\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠒\u001b[39m \u001b[33mCustomizing Vortex for your project\u001b[39m\r\r\n\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠐\u001b[39m \u001b[33mCustomizing Vortex for your project\u001b[39m\r\r\n\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠰\u001b[39m \u001b[33mCustomizing Vortex for your project\u001b[39m\r\r\n\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠠\u001b[39m \u001b[33mCustomizing Vortex for your project\u001b[39m\r\r\n\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠤\u001b[39m \u001b[33mCustomizing Vortex for your project\u001b[39m\r\r\n\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠄\u001b[39m \u001b[33mCustomizing Vortex for your project\u001b[39m\r\r\n\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠆\u001b[39m \u001b[33mCustomizing Vortex for your project\u001b[39m\r\r\n\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠂\u001b[39m \u001b[33mCustomizing Vortex for your project\u001b[39m\r\r\n\u001b[999D\u001b[2A\u001b[J\u001b[?25h\r"] +[46.021764, "o", "\r\n \u001b[34m✦ Customizing Vortex for you"] +[46.021891, "o", "r project\u001b[39m\r\r\n\r\r\n\r\r\n \u001b[A\u001b[A\u001b[A\u001b[A\u001b[A\r\r\n\r\r\n"] +[46.021942, "o", "\r\r\n \u001b[32m✓ Vortex was customized for your project\u001b[39m\r\r\n\r\r\n\r\r\n \u001b[A\u001b[A\u001b[A\u001b[A\r\r\n\r\r\n"] +[46.022023, "o", "\u001b[?25l"] +[46.024881, "o", "\r\r\n \u001b[36m⠂\u001b[39m \u001b[33mPreparing destination directory\u001b[39m\r\r\n"] +[46.055815, "o", "\u001b[999D\u001b[2A\u001b[J\u001b[?25h"] +[46.055926, "o", "\r\r\n \u001b[34m✦ Preparing destination directory\u001b[39m\r\r\n\r\r\n"] +[46.056037, "o", "\r\r\n \u001b[A\u001b[A\u001b[A\u001b[A\u001b[A\r\r\n\r\r\n\r\r\n \u001b[2mCreated directory \"/home/user/www/demo/star_wars\".\u001b[22m\r\r\n\r\r\n\r\r\n \u001b[A\u001b[A\u001b[A\u001b[A\u001b[A\r\r\n\r\r\n"] +[46.056108, "o", "\r\r\n \u001b[2mInitialising a new Git repository in directory \"/home/user/www/demo/star_wars\".\u001b[22m\r\r\n\r\r\n\r\r\n \u001b[A\u001b[A\u001b[A\u001b[A\u001b[A\r\r\n\r\r\n\r\r\n \u001b[32m✓ Destination directory is ready\u001b[39m\r\r\n\r\r\n\r\r\n \u001b[A\u001b[A\u001b[A\u001b[A\r\r\n\r\r\n"] +[46.0562, "o", "\u001b[?25l"] +[46.058822, "o", "\r\r\n \u001b[36m⠂\u001b[39m \u001b[33mCopying files to the destination directory\u001b[39m\r\r\n"] +[46.143299, "o", "\u001b[1G\u001b[2A\u001b[J"] +[46.14338, "o", "\r\r\n \u001b[36m⠒\u001b[39m \u001b[33mCopying files to the destination directory\u001b[39m\r\r\n"] +[46.161067, "o", "\u001b[999D\u001b[2A\u001b[J\u001b[?25h"] +[46.161387, "o", "\r\r\n \u001b[34m✦ Copying files to the destination directory\u001b[39m\r\r\n\r\r\n\r\r\n \u001b[A\u001b[A\u001b[A\u001b[A\u001b[A\r\r\n\r\r\n\r\r\n \u001b[32m✓ Files copied to destination directory\u001b[39m\r\r\n\r\r\n\r\r\n \u001b[A\u001b[A\u001b[A\u001b[A\r\r\n\r\r\n\u001b[?25l"] +[46.164554, "o", "\r\r\n \u001b[36m⠂\u001b[39m \u001b[33mPreparing demo content\u001b[39m\r\r\n"] +[46.248214, "o", "\u001b[1G\u001b[2A\u001b[J"] +[46.248338, "o", "\r\r\n \u001b[36m⠒\u001b[39m \u001b[33mPreparing demo content\u001b[39m\r\r\n"] +[46.326955, "o", "\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠐\u001b[39m \u001b[33mPreparing demo content\u001b[39m\r\r\n"] +[46.406374, "o", "\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠰\u001b[39m \u001b[33mPreparing demo content\u001b[39m\r\r\n"] +[46.485247, "o", "\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠠\u001b[39m \u001b[33mPreparing demo content\u001b[39m\r\r\n"] +[46.565915, "o", "\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠤\u001b[39m \u001b[33mPreparing demo content\u001b[39m\r\r\n"] +[46.643763, "o", "\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠄\u001b[39m \u001b[33mPreparing demo content\u001b[39m\r\r\n"] +[46.723354, "o", "\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠆\u001b[39m \u001b[33mPreparing demo content\u001b[39m\r\r\n"] +[46.776162, "o", "\u001b[999D\u001b[2A\u001b[J\u001b[?25h"] +[46.776265, "o", "\r\r\n \u001b[34m✦ Preparing demo content\u001b[39m\r\r\n\r\r\n\r\r\n \u001b[A\u001b[A\u001b[A\u001b[A\u001b[A\r\r\n\r\r\n\r\r\n \u001b[2mCreated data directory \"/home/user/www/demo/star_wars/.data\".\u001b[22m\r\r\n\r\r\n\r\r\n \u001b[A\u001b[A\u001b[A\u001b[A\u001b[A\r\r\n\r\r\n\r\r\n \u001b[2mNo database dump file was found in \"/home/user/www/demo/star_wars/.data\" directory.\u001b[22m\r\r\n\r\r\n\r\r\n \u001b[A\u001b[A\u001b[A\u001b[A\u001b[A\r\r\n\r\r\n\r\r\n \u001b[2mDownloaded demo database from https://github.com/drevops/vortex/releases/download/25.4.0/db_d11.demo.sql.\u001b[22m\r\r\n\r\r\n\r\r\n \u001b[A\u001b[A\u001b[A\u001b[A\u001b[A\r\r\n\r\r\n\r\r\n \u001b[32m✓ Demo content prepared\u001b[39m\r\r\n\r\r\n"] +[46.776339, "o", "\r\r\n \u001b[A\u001b[A\u001b[A\u001b[A\r\r\n\r\r\n"] +[46.794142, "o", "\r\r\n \u001b[90m┌──────────────────────────────────────────────────────────────────────────┐\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[32mFinished installing Vortex\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[32m──────────────────────────\u001b[39m\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Next steps:\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Add and commit all files:\u001b[39m\u001b[39m \u001b[39"] +[46.794251, "o", "m\u001b[90m"] +[46.794341, "o", "│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m cd /home/user/www/demo/star_wars\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m git add -A\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m git commit -m \"Initial commit.\"\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Build project locally:\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m ahoy build\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Setup integration with your hosting and CI/CD providers:\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m "] +[46.794385, "o", " See htt"] +[46.794445, "o", "ps://www.vortextemplate.com/docs/getting-started/installation\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m└──────────────────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n"] diff --git a/.vortex/docs/static/img/installer.svg b/.vortex/docs/static/img/installer.svg index 2172b18de..d0b0fadfc 100644 --- a/.vortex/docs/static/img/installer.svg +++ b/.vortex/docs/static/img/installer.svg @@ -1 +1 @@ -──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────██╗██╗██████╗██████╗████████╗███████╗██╗██╗██║██║██╔═══██╗██╔══██╗╚══██╔══╝██╔════╝╚██╗██╔╝██║██║██║██║██████╔╝██║█████╗╚███╔╝╚██╗██╔╝██║██║██╔══██╗██║██╔══╝██╔██╗╚████╔╝╚██████╔╝██║██║██║███████╗██╔╝██╗╚═══╝╚═════╝╚═╝╚═╝╚═╝╚══════╝╚═╝╚═╝DrupalprojecttemplatebyDrevOpsInstallerversion:development┌──────────────────────────────────────────────────────────────────────────────────────┐WelcometotheVortexinteractiveinstaller───────────────────────────────────────────ThistoolwillguideyouthroughinstallingthelateststableversionofVortexintoyourproject.yourproject.Youwillbeaskedafewquestionstotailortheconfigurationtoyoursite.Nochangeswillbemadeuntilyouconfirmeverythingattheend.PressCtrl+Catanytimetoexittheinstaller.PressCtrl+Uatanytimetogobacktothepreviousstep.└─────────└──────────────────────────────────────────────────────────────────────────────────────┘Pressanykeytocontinue... General information Sitename(1/27)────────────────────────────────────────────┐└──────────────────────────────────────────────────────────────┘Wewillusethisnameintheprojectanddocumentation.St Sitename(1/27)────────────────────────────────────────────┐StarWarsstar_wars Sitemachinename(2/27)────────────────────────────────────┐star_warsOrganizationname(3/27)────────────────────────────────────┐E.g.MyOrgRe Organizationname(3/27)────────────────────────────────────┐RebellionOrganizationmachinename(4/27)────────────────────────────┐rebellion Wewillusethisnameinthecode.Organizationmachinename(4/27)────────────────────────────┐rebellionPublicdomain(5/27)────────────────────────────────────────┐star-wars.com Publicdomain(5/27)────────────────────────────────────────┐star-wars.com Drupal Howwouldyoulikeyoursitetobecreatedonthefirstrun?(6/27)Choosehowyoursitewillbecreatedthefirsttimeafterthisinstallerfinishes:Drupal,installedfromprofileCreatesanewsitebypopulatingafreshdatabasefromoneofthestandardDrupalinstallationprofiles.DrupalCMS,installedfromprofilefromtheDrupalCMSrecipe.Drupal,loadedfromthedemodatabaseCreatesasitebyloadinganexistingdemodatabaseprovidedwiththeinstaller.├─────────────────────────────────────────────────────────────────────┤Drupal,installedfromprofileDrupalCMS,installedfromprofileDrupal,loadedfromthedemodatabase└─────────────────────────────────────────────────────────────────────┘Howwouldyoulikeyoursitetobecreatedonthefirstrun?(6/27)Drupal,loadedfromthedemodatabaseDrupal,loadedfromthedemodatabaseProfile(7/27)──────────────────────────────────────────────┐StandardModuleprefix(8/27)────────────────────────────────────────┐sw Moduleprefix(8/27)────────────────────────────────────────┐swTheme(9/27)────────────────────────────────────────────────┐OliveroClaroStarkTheme(9/27)────────────────────────────────────────────────┐Custom(nextprompt)Customthememachinename(10/27)───────────────────────────┐Customthememachinename(10/27)───────────────────────────┐ Code repository Repositoryprovider(11/27)─────────────────────────────────┐VortexoffersfullautomationwithGitHub,whilesupportforotherprovidersislimited.├──────────────────────────────────────────────────────────────┤OtherRepositoryprovider(11/27)─────────────────────────────────┐GitHub Environment Timezone(12/27)────────────────────────────────────────────┐UTCServices(13/27)────────────────────────────────────────────┐ClamAVSolrRedisDevelopmenttools(14/27)───────────────────────────────────┐PHPCodeSnifferPHPStanRectorPHPMessDetectorPHPUnitBehatDevelopmenttools(14/27)───────────────────────────────────┐PHPCodeSnifferPHPStanRectorPHPMessDetectorPHPUnitBehat Hosting NoneHostingprovider(15/27)────────────────────────────────────┐NoneCustomwebrootdirectory(16/27)───────────────────────────┐web Customwebrootdirectory(16/27)───────────────────────────┐web Deployment Deploymenttypes(17/27)────────────────────────────────────┐CodeartifactLagoonwebhookContainerimageDeploymenttypes(17/27)────────────────────────────────────┐Customwebhook Workflow Provisiontype(18/27)──────────────────────────────────────┐Provisioningsetsupthesiteinanenvironmentusinganalreadyassembledcodebase.ImportfromdatabasedumpProvisionsthesitebyimportingadatabasedumptypicallycopiedfromproductionintolowerenvironments.InstallfromprofileProvisionsthesitebyinstallingafreshDrupalsitefromaprofileeverytimeanenvironmentiscreated.Provisiontype(18/27)──────────────────────────────────────┐created.ImportfromdatabasedumpDatabasesource(19/27)─────────────────────────────────────┐URLdownloadFTPdownloadNoneDatabasesource(19/27)─────────────────────────────────────┐URLdownload Notifications Notificationchannels(20/27)───────────────────────────────┐EmailGitHubJIRANewRelicSlackWebhookNotificationchannels(20/27)───────────────────────────────┐Email Continuous Integration ContinuousIntegrationprovider(21/27)─────────────────────┐GitHubActionsCircleCINoneContinuousIntegrationprovider(21/27)─────────────────────┐GitHubActions Automations Dependencyupdatesprovider(22/27)─────────────────────────┐RenovateGitHubappRenovateself-hostedinCIDependencyupdatesprovider(22/27)─────────────────────────┐RenovateGitHubappYes/NoAuto-assigntheauthortotheirPR?(23/27)─────────────────┐Yes└─────────────────────────────────────────────────────────────────┘Auto-addaCONFLICTlabeltoaPRwhenconflictsoccur?(24/27)Yes Documentation Preserveprojectdocumentation?(25/27)─────────────────────┐Preserveprojectdocumentation?(25/27)─────────────────────┐ AI AIcodeassistantinstructions(26/27)──────────────────────┐AnthropicClaudeAIcodeassistantinstructions(26/27)──────────────────────┐ Installation summary ┌────────────────────────────────────┬─────────────────────────────────────────┐GeneralinformationSitenameStarWarsSitemachinenamestar_warsOrganizationnameRebellionOrganizationmachinenamerebellionPublicdomainstar-wars.comDrupalStarterload_demodbWebrootwebProfilestandardModuleprefixswThememachinenamestar_warsCoderepositoryCodeprovidergithubEnvironmentTimezoneTimezoneUTCServicesclamav,redis,solrToolsphpcs,phpmd,phpstan,rector,phpunit,behatHostingHostingprovidernoneDeploymentDeploymenttypeswebhookWorkflowProvisiontypedatabaseDatabasesourceurlNotificationsChannelsemailContinuousIntegrationCIproviderghaAutomationsDependencyupdatesproviderrenovatebot_appAuto-assignPRauthorYesAuto-addaCONFLICTlabeltoPRsYesDocumentationPreserveprojectdocumentationYesAIAIAIcodeassistantinstructionsnoneLocationsCurrentdirectory/home/user/www/demoDestinationdirectory/home/user/www/demo/star_warsVortexrepositoryhttps://github.com/drevops/vortex.gitVortexreferencestable└────────────────────────────────────┴─────────────────────────────────────────┘Vortexwillbeinstalledintoyourproject'sdirectory"/home/user/www/demo/star_wars"ProceedwithinstallingVortex?─────────────────────────────┐ Starting project installation DownloadingVortexDownloadingfrom"https://github.com/drevops/vortex.git"repositoryatcommit"HEAD"Vortexdownloaded(25.10.0)CustomizingVortexforyourprojectCustomizingVortexforyourprojectCustomizingVortexforyourprojectCustomizingVortexforyourprojectVortexwascustomizedforyourprojectPreparingdestinationdirectoryCreateddirectory"/home/user/www/demo/star_wars".InitialisinganewGitrepositoryindirectory"/home/user/www/demo/star_wars".DestinationdirectoryisreadyCopyingfilestothedestinationdirectoryFilescopiedtodestinationdirectoryPreparingdemocontentCreateddatadirectory"/home/user/www/demo/star_wars/.data".Nodatabasedumpfilewasfoundin"/home/user/www/demo/star_wars/.data"directory.Downloadeddemodatabasefromhttps://github.com/drevops/vortex/releases/download/25.4.0/db_d11.demo.sql.Democontentprepared┌──────────────────────────────────────────────────────────────────────────┐FinishedinstallingVortex──────────────────────────Nextsteps:Addandcommitallfiles:Addandcommitallfiles:cd/home/user/www/demo/star_warsgitadd-Agitcommit-m"Initialcommit."Buildprojectlocally:ahoybuildSetupintegrationwithyourhostingandCI/CDproviders:╚██╗██╔╝╚██╗██╔╝██║────────────────────────────────────────────────────────────────────────────────────────────────────────────────starwars E.g.MySite└─────────────────────────────────────└───────────────────────────────────────StarWars Sitemachinename(2/27)────────────────────────────────────┐Wewillusethisnamefortheprojectdirectoryandinthecode.StarWarsOrg └────────────────────────────────────────────└───────────────────────────────────────────────└─────Rebellion WewillusethisnameinthecoDomainnamewithoutproDomainnamewithoutprotocolandDomainnamewithoutprotocolandtrailingslash.CreatesasitebyloadinCreatesasitebyloadinganexist└────────────────────────────────────────────────────────────└──────────────────────────────────────────────────────────────Useand⬇.Appliesonlyonthefirstrunoftheinstaller.DrupalCMS,installedfromprofileProfile(7/27)──────────────────────────────────────────────┐StandardMinimalDemoUmamiCustom(nextprompt)UseandtoselectwhichDrupalprofiletouse.WewillusethisnameincustommodulesStarkCustom(nextprompt)UseandtoselectwhichDrupalthemetouse.WewilluWewillusethisnWewillusethisnameasacustomthemenameGitHubUseandtoselectyourcoderepositoryprovider.└────────────────────────────────────────────────────└───────────────────────────────────────────────────────Timezone(12/27)Timezone(12/27)────└───────────────────────────────────────────────────└──────────────────────────────────────────────────────Use⬆,andSpacebartoselectoneormoretools.Hostingprovider(15/27)────────────────────────────────────┐AcquiaCloudLagoonUse⬆,andSpacebartoselectyourhostingprovider.CustomdirectorywherethewebseCustomdirectorywherethewebserverservCustomdirectorywherethewebserverservesthesite.ContainerimageCustomwebhookUse⬆,andSpacebartoselectoneormoredeploymenttypes.├─├────ProvisioningsetsupthesiteinaneProvisioningsetsupthesiteinanenvironmentFTPdownloadAcquiabackupLagoonenvironmentContainerregistryUseandtoselectthedatabasedownloadsource.└────────────────────────────────────────Use⬆,andSpacebartoselectoneormorenotificationchannels.UseandtoselecttheCIprovider.Useandtoselectthedependencyupdatesprovider.Auto-assigntheauthortotheirPR?(23/27)─────────────────┐HelpstokeepthePRsorganized.Auto-addaCONFLICTlabeltoaPRwhenconflictsoccur?(24/27)Yes/NoHelpstokeepquicklyidentifyPRsthatneedattention.HelpstomaintaintheprojectdocumentationHelpstomaintaintheprojectdocumentationwithintheHelpstomaintaintheprojectdocumentationwithintherepository.└──────────────────────────────────────└──────────────────────────────────────────ProvidesAIcodingassistantswithbettercontextabouttheproject.GeneralinformationWebrootDeploymenttypesCIproviCIprovider└──────────────────└────────────────────ProceedwithinstallingVortex?─────────────────────────────┐DownloadingVortexCustomizingVortexforyourprojectCustomizingVortexforyourprojectCustomizingVortexforyourprojectCustomizingVortexforyourprojectCustomizingVortexforyourprojectPreparingdestinationdirectoryCopyingfilestothedestinationdirectoryPreparingdemocontentPreparingdemocontentPreparingdemocontentPreparingdemocontentPreparingdemocontentPreparingdemocontentSeehttSeehttps://www.vortextemplate.com/docs/getting-started/installation└──────────────────────────────────────────────────────────────────────────┘ \ No newline at end of file +──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────██╗██╗██████╗██████╗████████╗███████╗██╗██╗██║██║██╔═══██╗██╔══██╗╚══██╔══╝██╔════╝╚██╗██╔╝██║██║██║██║██████╔╝██║█████╗╚███╔╝╚██╗██╔╝██║██║██╔══██╗██║██╔══╝██╔██╗╚████╔╝╚██████╔╝██║██║██║███████╗██╔╝██╗╚═══╝╚═════╝╚═╝╚═╝╚═╝╚══════╝╚═╝╚═╝DrupalprojecttemplatebyDrevOpsInstallerversion:development┌──────────────────────────────────────────────────────────────────────────────────────┐WelcometotheVortexinteractiveinstaller───────────────────────────────────────────ThistoolwillguideyouthroughinstallingthelateststableversionofVortexintoyourproject.Youwillbeaskedafewquestionstotailortheconfigurationtoyoursite.Nochangeswillbemadeuntilyouconfirmeverythingattheend.PressCtrl+Catanytimetoexittheinstaller.PressCtrl+Uatanytimetogobacktothepreviousstep.└────────────└──────────────────────────────────────────────────────────────────────────────────────┘Pressanykeytocontinue... General information Sitename(1/28)────────────────────────────────────────────┐└──────────────────────────────────────────────────────────────┘Wewillusethisnameintheprojectanddocumentation.E.g.MySiteSt Sitename(1/28)────────────────────────────────────────────┐StarWarsSitemachinename(2/28)────────────────────────────────────┐star_warsOrganizationname(3/28)────────────────────────────────────┐E.g.MyOrg└────────────────────────────────────────────Re └─────────Organizationname(3/28)────────────────────────────────────┐RebellionOrganizationmachinename(4/28)────────────────────────────┐rebellion Organizationmachinename(4/28)────────────────────────────┐rebellionPublicdomain(5/28)────────────────────────────────────────┐star-wars.com Publicdomain(5/28)────────────────────────────────────────┐star-wars.com Drupal Howwouldyoulikeyoursitetobecreatedonthefirstrun?(6/28)Choosehowyoursitewillbecreatedthefirsttimeafterthisinstallerfinishes:Drupal,installedfromprofileCreatesanewsitebypopulatingafreshdatabasefromoneofthestandardDrupalinstallationprofiles.DrupalCMS,installedfromprofilefromtheDrupalCMSrecipe.Drupal,loadedfromthedemodatabaseCreatesasitebyloadinganexistingdemodatabaseprovidedwiththeinstaller.├─────────────────────────────────────────────────────────────────────┤Drupal,installedfromprofileDrupalCMS,installedfromprofileDrupal,loadedfromthedemodatabase└─────────────────────────────────────────────────────────────────────┘Howwouldyoulikeyoursitetobecreatedonthefirstrun?(6/28)DrupalCMS,installedfromprofileDrupal,loadedfromthedemodatabaseProfile(7/28)──────────────────────────────────────────────┐StandardModules(8/28)──────────────────────────────────────────────┐AdmintoolbarCoffeeConfigsplitConfigupdateEnvironmentindicatorPathautoRedirectRobots.txtSeckitShieldModules(8/28)──────────────────────────────────────────────┐AdmintoolbarCoffeeConfigsplitConfigupdateEnvironmentindicatorPathautoRedirectRobots.txtSeckitShieldStagefileproxyCustommodulesprefix(9/28)────────────────────────────────┐swTheme(10/28)───────────────────────────────────────────────┐Custom(nextprompt)Customthememachinename(11/28)───────────────────────────┐ Code repository Repositoryprovider(12/28)─────────────────────────────────┐VortexoffersfullautomationwithGitHub,whilesupportforotherprovidersislimited.├──────────────────────────────────────────────────────────────┤GitHubOtherRepositoryprovider(12/28)─────────────────────────────────┐GitHub Environment Timezone(13/28)────────────────────────────────────────────┐UTCServices(14/28)────────────────────────────────────────────┐ClamAVSolrRedisServices(14/28)────────────────────────────────────────────┐ClamAVSolrRedisDevelopmenttools(15/28)───────────────────────────────────┐PHPCodeSnifferDevelopmenttools(15/28)───────────────────────────────────┐PHPCodeSnifferPHPStanRectorPHPMessDetectorPHPUnitBehat Hosting NoneHostingprovider(16/28)────────────────────────────────────┐NoneCustomwebrootdirectory(17/28)───────────────────────────┐web Customwebrootdirectory(17/28)───────────────────────────┐web Deployment Deploymenttypes(18/28)────────────────────────────────────┐CodeartifactLagoonwebhookContainerimageDeploymenttypes(18/28)────────────────────────────────────┐Customwebhook Workflow Provisiontype(19/28)──────────────────────────────────────┐Provisioningsetsupthesiteinanenvironmentusinganalreadyassembledcodebase.ImportfromdatabasedumpProvisionsthesitebyimportingadatabasedumptypicallycopiedfromproductionintolowerenvironments.InstallfromprofileProvisionsthesitebyinstallingafreshDrupalsitefromaprofileeverytimeanenvironmentiscreated.Provisiontype(19/28)──────────────────────────────────────┐created.ImportfromdatabasedumpDatabasesource(20/28)─────────────────────────────────────┐URLdownloadFTPdownloadNoneDatabasesource(20/28)─────────────────────────────────────┐URLdownload Notifications Notificationchannels(21/28)───────────────────────────────┐EmailGitHubJIRANewRelicSlackWebhookNotificationchannels(21/28)───────────────────────────────┐Email Continuous Integration ContinuousIntegrationprovider(22/28)─────────────────────┐GitHubActionsCircleCIContinuousIntegrationprovider(22/28)─────────────────────┐GitHubActions Automations Dependencyupdatesprovider(23/28)─────────────────────────┐RenovateGitHubappRenovateself-hostedinCIDependencyupdatesprovider(23/28)─────────────────────────┐RenovateGitHubappYes/NoAuto-assigntheauthortotheirPR?(24/28)─────────────────┐Yes└─────────────────────────────────────────────────────────────────┘Auto-addaCONFLICTlabeltoaPRwhenconflictsoccur?(25/28)Yes Documentation Preserveprojectdocumentation?(26/28)─────────────────────┐Preserveprojectdocumentation?(26/28)─────────────────────┐ AI AIcodeassistantinstructions(27/28)──────────────────────┐AnthropicClaudeAIcodeassistantinstructions(27/28)──────────────────────┐ Installation summary ┌────────────────────────────────────┬─────────────────────────────────────────┐GeneralinformationSitenameStarWarsSitemachinenamestar_warsOrganizationnameRebellionOrganizationmachinenamerebellionPublicdomainstar-wars.comDrupalStarterload_demodbModulesadmin_toolbar,coffee,config_split,config_update,environment_indicator,pathauto,redirect,robotstxt,seckit,shield,stage_file_proxyWebrootwebProfilestandardModuleprefixswThememachinenameThememachinenamestar_warsCoderepositoryCodeprovidergithubEnvironmentTimezoneUTCServicesclamav,redis,solrToolsphpcs,phpmd,phpstan,rector,phpunit,behatHostingHostingprovidernoneDeploymentDeploymenttypeswebhookWorkflowProvisiontypedatabaseDatabasesourceDatabasesourceurlNotificationsChannelsemailContinuousIntegrationCIproviderghaAutomationsDependencyupdatesproviderrenovatebot_appAuto-assignPRauthorYesAuto-addaCONFLICTlabeltoPRsYesDocumentationPreserveprojectdocumentationYesAIAIcodeassistantinstructionsnoneLocationsCurrentdirectory/home/user/www/demoDestinationdirectory/home/user/www/demo/star_warsVortexrepositoryhttps://github.com/drevops/vortex.gitVortexreferencestable└────────────────────────────────────┴─────────────────────────────────────────┘Vortexwillbeinstalledintoyourproject'sdirectory"/home/user/www/demo/star_wars"ProceedwithinstallingVortex?─────────────────────────────┐ Starting project installation DownloadingVortexDownloadingfrom"https://github.com/drevops/vortex.git"repositoryatcommit"HEAD"Vortexdownloaded(25.10.0)CustomizingVortexforyourprojectVortexwascustomizedforyourprojectPreparingdestinationdirectoryCreateddirectory"/home/user/www/demo/star_wars".InitialisinganewGitrepositoryindirectory"/home/user/www/demo/star_wars".DestinationdirectoryisreadyCopyingfilestothedestinationdirectoryFilescopiedtodestinationdirectoryPreparingdemocontentCreateddatadirectory"/home/user/www/demo/star_wars/.data".Nodatabasedumpfilewasfoundin"/home/user/www/demo/star_wars/.data"directory.Downloadeddemodatabasefromhttps://github.com/drevops/vortex/releases/download/25.4.0/db_d11.demo.sql.Democontentprepared┌──────────────────────────────────────────────────────────────────────────┐FinishedinstallingVortex──────────────────────────Nextsteps:Addandcommitallfiles:Addandcommitallfiles:cd/home/user/www/demo/star_warsgitadd-Agitcommit-m"Initialcommit."Buildprojectlocally:ahoybuildSetupintegrationwithyourhostingandCI/CDproviders:╚██╗██╔╝╚██╗██╔╝██║────────────────────────────────────────────────────────────────────────────────────────────────────────────────yourproject.└───────starwars └──────────────────────────────────└────────────────────────────────────St StarWars Sitemachinename(2/28)────────────────────────────────────┐star_wars Wewillusethisnamefortheprojectdirectoryandinthecode.StarWarsOrg └───────────────────────────────────────────────└─────Rebellion WewillusethisnameinthecoWewillusethisnameinthecode.DomainnamewithoutproDomainnamewithoutprotocolandDomainnamewithoutprotocolandtrailingslash.CreatesasitebyloadinCreatesasitebyloadinganexist└────────────────────────────────────────────────────────────└──────────────────────────────────────────────────────────────Useand⬇.Appliesonlyonthefirstrunoftheinstaller.Drupal,loadedfromthedemodatabaseProfile(7/28)──────────────────────────────────────────────┐StandardMinimalDemoUmamiCustom(nextprompt)UseandtoselectwhichDrupalprofiletouse.ConfigspliConfigsplit└───────────────────────└──────────────────────────Theme(10/28)──────Theme(10/28)─────────Useandtoselectyourcoderepositoryprovider.└────────────────────────────────────────────────────└───────────────────────────────────────────────────────Timezone(13/28)────────────────────────────────────────────┐UTC UTCUseand⬇,orstarttypingtoselectthetimezoneforyourproject.RedisUse⬆,andSpacebartoselectoneormoreservices.PHPStanRectorPHPMessDetectorPHPUnitBehatUse⬆,andSpacebartoselectoneormoretools.HostingHostingprovider(16/28)────────────────────────────────────┐AcquiaCloudLagoonUse⬆,andSpacebartoselectyourhostingprovider.CustomdirectorywherethewebseCustomdirectorywherethewebserverservCustomdirectorywherethewebserverservesthesite.ContainerimageCustomwebhookUse⬆,andSpacebartoselectoneormoredeploymenttypes.├─├────ProvisioningsetsupthesiteinaneProvisioningsetsupthesiteinanenvironmentFTPdownloadAcquiabackupLagoonenvironmentContainerregistryUseandtoselectthedatabasedownloadsource.└────────────────────────────────────────Use⬆,andSpacebartoselectoneormorenotificationchannels.NoneUseandtoselecttheCIprovider.Useandtoselectthedependencyupdatesprovider.Auto-assigntheauthortotheirPR?(24/28)─────────────────┐HelpstokeepthePRsorganized.Auto-addaCONFLICTlabeltoaPRwhenconflictsoccur?(25/28)Yes/NoHelpstokeepquicklyidentifyPRsthatneedattention.HelpstomaintaintheprojectdocumentationHelpstomaintaintheprojectdocumentationwithintherepository.└──────────────────────────────────────└──────────────────────────────────────────ProvidesAIcodingassistantswithbettercontextabouttheproject.GeneralinformationModulModulesAuto-assignPRauAuto-assignPRauthorCurrentdirCurrentdirectoryProceedwithinstallingVortex?─────────────────────────────┐DownloadingVortexCustomizingVortexforyouPreparingdestinationdirectoryCopyingfilestothedestinationdirectoryCopyingfilestothedestinationdirectoryPreparingdemocontentPreparingdemocontentPreparingdemocontentPreparingdemocontentPreparingdemocontentPreparingdemocontentPreparingdemocontentPreparingdemocontentSeehttSeehttps://www.vortextemplate.com/docs/getting-started/installation└──────────────────────────────────────────────────────────────────────────┘ \ No newline at end of file diff --git a/.vortex/installer/composer.json b/.vortex/installer/composer.json index cc7406d58..d33f3d6ea 100644 --- a/.vortex/installer/composer.json +++ b/.vortex/installer/composer.json @@ -18,7 +18,7 @@ }, "require": { "php": ">=8.3", - "alexskrypnyk/file": "^0.13.1", + "alexskrypnyk/file": "^0.14", "alexskrypnyk/str2name": "^1.4", "composer/composer": "^2.9.1", "cweagans/composer-patches": "^2", @@ -88,10 +88,10 @@ "lint": [ "phpcs", "phpstan", - "rector --clear-cache --dry-run" + "rector --dry-run" ], "lint-fix": [ - "rector --clear-cache", + "rector", "phpcbf" ], "reset": "rm -Rf vendor vendor-bin", diff --git a/.vortex/installer/composer.lock b/.vortex/installer/composer.lock index a0cd9a970..53eb2087d 100644 --- a/.vortex/installer/composer.lock +++ b/.vortex/installer/composer.lock @@ -4,20 +4,20 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "158f2ed92ad9e92e72a28ee43f8acf54", + "content-hash": "ac421faa34c47854cab8b601cf202279", "packages": [ { "name": "alexskrypnyk/file", - "version": "0.13.1", + "version": "0.14.0", "source": { "type": "git", "url": "https://github.com/AlexSkrypnyk/file.git", - "reference": "d627d930109743bd6a3810d598114ed3ddf898fa" + "reference": "a565c253a4c2b6ff2628c05eb1254b91c55177ee" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/AlexSkrypnyk/file/zipball/d627d930109743bd6a3810d598114ed3ddf898fa", - "reference": "d627d930109743bd6a3810d598114ed3ddf898fa", + "url": "https://api.github.com/repos/AlexSkrypnyk/file/zipball/a565c253a4c2b6ff2628c05eb1254b91c55177ee", + "reference": "a565c253a4c2b6ff2628c05eb1254b91c55177ee", "shasum": "" }, "require": { @@ -27,8 +27,10 @@ "require-dev": { "alexskrypnyk/phpunit-helpers": "^0.13.0", "dealerdirect/phpcodesniffer-composer-installer": "^1", + "drevops/phpcs-standard": "^0.3", "drupal/coder": "^8.3", "ergebnis/composer-normalize": "^2.42", + "phpbench/phpbench": "^1.4", "phpstan/phpstan": "^2", "phpunit/phpunit": "^11", "rector/rector": "^2" @@ -70,7 +72,7 @@ "type": "patreon" } ], - "time": "2025-10-06T23:45:44+00:00" + "time": "2025-11-19T02:51:08+00:00" }, { "name": "alexskrypnyk/str2name", diff --git a/.vortex/installer/src/Prompts/Handlers/ModulePrefix.php b/.vortex/installer/src/Prompts/Handlers/ModulePrefix.php index 26e9c935f..6ccfd20e2 100644 --- a/.vortex/installer/src/Prompts/Handlers/ModulePrefix.php +++ b/.vortex/installer/src/Prompts/Handlers/ModulePrefix.php @@ -13,7 +13,7 @@ class ModulePrefix extends AbstractHandler { * {@inheritdoc} */ public function label(): string { - return 'Module prefix'; + return 'Custom modules prefix'; } /** diff --git a/.vortex/installer/src/Prompts/Handlers/Modules.php b/.vortex/installer/src/Prompts/Handlers/Modules.php new file mode 100644 index 000000000..2a8262b96 --- /dev/null +++ b/.vortex/installer/src/Prompts/Handlers/Modules.php @@ -0,0 +1,178 @@ +isInstalled()) { + return NULL; + } + + $composer_file = $this->dstDir . '/composer.json'; + $discovered_modules = $this->getModulesFromComposerFile($composer_file); + + if ($discovered_modules === NULL) { + return NULL; + } + + // Filter discovered modules to only include those in our available list. + $available_modules = array_keys(static::getAvailableModules()); + $modules = array_intersect($discovered_modules, $available_modules); + + sort($modules); + + return $modules; + } + + /** + * {@inheritdoc} + */ + public function process(): void { + $selected_modules = $this->getResponseAsArray(); + $all_modules = static::getAvailableModules(); + + $t = $this->tmpDir; + $w = $this->webroot; + + // Process each module that was NOT selected (remove them). + foreach (array_keys($all_modules) as $module_name) { + if (!in_array($module_name, $selected_modules)) { + // Remove from composer.json. + $pattern = '/\s*"drupal\/' . preg_quote($module_name, '/') . '":\s*"[^\"]+",?\n/'; + File::replaceContentInFile($t . '/composer.json', $pattern, "\n"); + + // Remove module from settings file. + File::remove($t . '/' . $w . '/sites/default/includes/modules/settings.' . $module_name . '.php'); + + // Remove module from the provision example file. + File::replaceContentCallbackInFile($t . '/scripts/custom/provision-10-example.sh', function (string $content) use ($module_name): string { + $pattern = '/^(\s*)(drush\s+pm:install.*\b' . preg_quote($module_name, '/') . '\b.*)$/m'; + $content = preg_replace_callback($pattern, function (array $matches) use ($module_name): string { + $indent = $matches[1]; + $line = $matches[2]; + $line = preg_replace('/\s+\b' . preg_quote($module_name, '/') . '\b/', '', $line); + $line = preg_replace('/\s{2,}/', ' ', $line) ?? $line; + return $indent . $line; + }, $content); + return $content ?? ''; + }); + + // Remove module from the Behat tests. + File::remove($t . '/tests/behat/features/' . $module_name . '.feature'); + + // Remove module from the config tests. + $pattern = '/\s*\$config\[\'' . preg_quote($module_name, '/') . '\..*;(\r?\n)?/'; + File::removeLine($t . '/tests/phpunit/Drupal/EnvironmentSettingsTest.php', $pattern); + + // Remove module tokens. + File::removeTokenAsync('MODULE_' . strtoupper($module_name)); + } + } + + if (count($selected_modules) === 0) { + File::removeTokenAsync('MODULE'); + } + } + + /** + * Get the full list of available Drupal contributed modules. + * + * This list excludes Drupal core modules and service modules. + * + * @return array + * Array of module machine names as keys and labels as values. + */ + public static function getAvailableModules(): array { + return [ + 'admin_toolbar' => 'Admin toolbar', + 'coffee' => 'Coffee', + 'config_split' => 'Config split', + 'config_update' => 'Config update', + 'environment_indicator' => 'Environment indicator', + 'pathauto' => 'Pathauto', + 'redirect' => 'Redirect', + 'robotstxt' => 'Robots.txt', + 'seckit' => 'Seckit', + 'shield' => 'Shield', + 'stage_file_proxy' => 'Stage file proxy', + ]; + } + + /** + * Extract Drupal contributed module names from a composer.json file. + * + * @param string $composer_file + * Path to the composer.json file. + * + * @return array|null + * Array of module machine names (without drupal/ prefix), or NULL on error. + */ + protected function getModulesFromComposerFile(string $composer_file): ?array { + if (!file_exists($composer_file)) { + return NULL; + } + + $cj = JsonManipulator::fromFile($composer_file); + + if (!$cj instanceof JsonManipulator) { + return NULL; + } + + $require = $cj->getProperty('require'); + + if (!is_array($require)) { + return NULL; + } + + $modules = []; + foreach (array_keys($require) as $package) { + // Only include drupal/* packages, excluding core packages. + if (str_starts_with((string) $package, 'drupal/') && !str_starts_with((string) $package, 'drupal/core-')) { + // Extract module name (remove drupal/ prefix). + $module_name = substr((string) $package, 7); + $modules[] = $module_name; + } + } + + return $modules; + } + +} diff --git a/.vortex/installer/src/Prompts/PromptManager.php b/.vortex/installer/src/Prompts/PromptManager.php index 8ab5a5a2d..e171dd66a 100644 --- a/.vortex/installer/src/Prompts/PromptManager.php +++ b/.vortex/installer/src/Prompts/PromptManager.php @@ -22,6 +22,7 @@ use DrevOps\VortexInstaller\Prompts\Handlers\LabelMergeConflictsPr; use DrevOps\VortexInstaller\Prompts\Handlers\MachineName; use DrevOps\VortexInstaller\Prompts\Handlers\ModulePrefix; +use DrevOps\VortexInstaller\Prompts\Handlers\Modules; use DrevOps\VortexInstaller\Prompts\Handlers\Name; use DrevOps\VortexInstaller\Prompts\Handlers\NotificationChannels; use DrevOps\VortexInstaller\Prompts\Handlers\Org; @@ -64,7 +65,7 @@ class PromptManager { * * Used to display the progress of the prompts. */ - const TOTAL_RESPONSES = 27; + const TOTAL_RESPONSES = 28; /** * Array of responses. @@ -135,6 +136,7 @@ public function runPrompts(): void { fn($r, $pr, $n): string => text(...$this->args(ProfileCustom::class)), ProfileCustom::id() ) + ->add(fn(array $r, $pr, $n): array => multiselect(...$this->args(Modules::class, NULL, $r)), Modules::id()) ->add(fn(array $r, $pr, $n): string => text(...$this->args(ModulePrefix::class, NULL, $r)), ModulePrefix::id()) ->add( fn(array $r, $pr, $n): string => $this->resolveOrPrompt(Theme::id(), $r, fn(): int|string => select(...$this->args(Theme::class))), @@ -277,6 +279,7 @@ public function runProcessors(): void { Services::id(), Timezone::id(), CodeProvider::id(), + Modules::id(), Starter::id(), ProfileCustom::id(), Profile::id(), @@ -368,6 +371,7 @@ public function getResponsesSummary(): array { $values['Drupal'] = Tui::LIST_SECTION_TITLE; $values['Starter'] = $responses[Starter::id()]; + $values['Modules'] = Converter::toList($responses[Modules::id()], ', '); $values['Webroot'] = $responses[Webroot::id()]; $values['Profile'] = $responses[Profile::id()]; $values['Module prefix'] = $responses[ModulePrefix::id()]; @@ -543,7 +547,7 @@ private function args(string $handler_class, mixed $default_override = NULL, arr } $options = $handler->options($responses); - if (is_array($options) && $options !== []) { + if (is_array($options)) { $args['options'] = $options; $args['scroll'] = 10; } diff --git a/.vortex/installer/src/Utils/JsonManipulator.php b/.vortex/installer/src/Utils/JsonManipulator.php index 8f8fe942c..1f15b0933 100644 --- a/.vortex/installer/src/Utils/JsonManipulator.php +++ b/.vortex/installer/src/Utils/JsonManipulator.php @@ -29,7 +29,15 @@ public static function fromFile(string $composer_json): ?self { // @codeCoverageIgnoreEnd } - return new self($contents); + try { + $instance = new self($contents); + } + catch (\Exception) { + // Invalid JSON. + return NULL; + } + + return $instance; } /** diff --git a/.vortex/installer/tests/Fixtures/install/_baseline/scripts/custom/provision-10-example.sh b/.vortex/installer/tests/Fixtures/install/_baseline/scripts/custom/provision-10-example.sh index a467670b7..904f92b78 100644 --- a/.vortex/installer/tests/Fixtures/install/_baseline/scripts/custom/provision-10-example.sh +++ b/.vortex/installer/tests/Fixtures/install/_baseline/scripts/custom/provision-10-example.sh @@ -34,11 +34,9 @@ note "Environment: ${environment}" if echo "${environment}" | grep -q -e dev -e stage -e ci -e local; then note "Running example operations in non-production environment." - # Set site name. task "Setting site name." drush php:eval "\Drupal::service('config.factory')->getEditable('system.site')->set('name', 'star wars')->save();" - # Enable contrib modules. task "Installing contrib modules." drush pm:install admin_toolbar coffee config_split config_update media environment_indicator pathauto redirect robotstxt shield stage_file_proxy diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_admin_toolbar/composer.json b/.vortex/installer/tests/Fixtures/install/modules_no_admin_toolbar/composer.json new file mode 100644 index 000000000..801c9e5c8 --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/modules_no_admin_toolbar/composer.json @@ -0,0 +1,8 @@ +@@ -7,7 +7,6 @@ + "php": "__VERSION__", + "composer/installers": "__VERSION__", + "cweagans/composer-patches": "__VERSION__", +- "drupal/admin_toolbar": "__VERSION__", + "drupal/clamav": "__VERSION__", + "drupal/coffee": "__VERSION__", + "drupal/config_split": "__VERSION__", diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_admin_toolbar/scripts/custom/provision-10-example.sh b/.vortex/installer/tests/Fixtures/install/modules_no_admin_toolbar/scripts/custom/provision-10-example.sh new file mode 100644 index 000000000..1d3045b5c --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/modules_no_admin_toolbar/scripts/custom/provision-10-example.sh @@ -0,0 +1,9 @@ +@@ -38,7 +38,7 @@ + drush php:eval "\Drupal::service('config.factory')->getEditable('system.site')->set('name', 'star wars')->save();" + + task "Installing contrib modules." +- drush pm:install admin_toolbar coffee config_split config_update media environment_indicator pathauto redirect robotstxt shield stage_file_proxy ++ drush pm:install coffee config_split config_update media environment_indicator pathauto redirect robotstxt shield stage_file_proxy + + task "Installing Redis module." + drush pm:install redis || true diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_coffee/composer.json b/.vortex/installer/tests/Fixtures/install/modules_no_coffee/composer.json new file mode 100644 index 000000000..a7036ebab --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/modules_no_coffee/composer.json @@ -0,0 +1,8 @@ +@@ -9,7 +9,6 @@ + "cweagans/composer-patches": "__VERSION__", + "drupal/admin_toolbar": "__VERSION__", + "drupal/clamav": "__VERSION__", +- "drupal/coffee": "__VERSION__", + "drupal/config_split": "__VERSION__", + "drupal/config_update": "__VERSION__", + "drupal/core-composer-scaffold": "__VERSION__", diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_coffee/scripts/custom/provision-10-example.sh b/.vortex/installer/tests/Fixtures/install/modules_no_coffee/scripts/custom/provision-10-example.sh new file mode 100644 index 000000000..0ed61b8be --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/modules_no_coffee/scripts/custom/provision-10-example.sh @@ -0,0 +1,9 @@ +@@ -38,7 +38,7 @@ + drush php:eval "\Drupal::service('config.factory')->getEditable('system.site')->set('name', 'star wars')->save();" + + task "Installing contrib modules." +- drush pm:install admin_toolbar coffee config_split config_update media environment_indicator pathauto redirect robotstxt shield stage_file_proxy ++ drush pm:install admin_toolbar config_split config_update media environment_indicator pathauto redirect robotstxt shield stage_file_proxy + + task "Installing Redis module." + drush pm:install redis || true diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_config_split/composer.json b/.vortex/installer/tests/Fixtures/install/modules_no_config_split/composer.json new file mode 100644 index 000000000..5797e6aff --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/modules_no_config_split/composer.json @@ -0,0 +1,8 @@ +@@ -10,7 +10,6 @@ + "drupal/admin_toolbar": "__VERSION__", + "drupal/clamav": "__VERSION__", + "drupal/coffee": "__VERSION__", +- "drupal/config_split": "__VERSION__", + "drupal/config_update": "__VERSION__", + "drupal/core-composer-scaffold": "__VERSION__", + "drupal/core-recommended": "__VERSION__", diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_config_split/scripts/custom/provision-10-example.sh b/.vortex/installer/tests/Fixtures/install/modules_no_config_split/scripts/custom/provision-10-example.sh new file mode 100644 index 000000000..4eb863930 --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/modules_no_config_split/scripts/custom/provision-10-example.sh @@ -0,0 +1,9 @@ +@@ -38,7 +38,7 @@ + drush php:eval "\Drupal::service('config.factory')->getEditable('system.site')->set('name', 'star wars')->save();" + + task "Installing contrib modules." +- drush pm:install admin_toolbar coffee config_split config_update media environment_indicator pathauto redirect robotstxt shield stage_file_proxy ++ drush pm:install admin_toolbar coffee config_update media environment_indicator pathauto redirect robotstxt shield stage_file_proxy + + task "Installing Redis module." + drush pm:install redis || true diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_config_split/tests/phpunit/Drupal/EnvironmentSettingsTest.php b/.vortex/installer/tests/Fixtures/install/modules_no_config_split/tests/phpunit/Drupal/EnvironmentSettingsTest.php new file mode 100644 index 000000000..c124d3bee --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/modules_no_config_split/tests/phpunit/Drupal/EnvironmentSettingsTest.php @@ -0,0 +1,24 @@ +@@ -186,7 +186,6 @@ + $this->requireSettingsFile(); + + $config['automated_cron.settings']['interval'] = 0; +- $config['config_split.config_split.local']['status'] = TRUE; + $config['environment_indicator.indicator']['bg_color'] = '#006600'; + $config['environment_indicator.indicator']['fg_color'] = '#ffffff'; + $config['environment_indicator.indicator']['name'] = self::ENVIRONMENT_LOCAL; +@@ -232,7 +231,6 @@ + $this->requireSettingsFile(); + + $config['automated_cron.settings']['interval'] = 0; +- $config['config_split.config_split.local']['status'] = TRUE; + $config['environment_indicator.indicator']['bg_color'] = '#006600'; + $config['environment_indicator.indicator']['fg_color'] = '#ffffff'; + $config['environment_indicator.indicator']['name'] = self::ENVIRONMENT_LOCAL; +@@ -280,7 +278,6 @@ + $this->requireSettingsFile(); + + $config['automated_cron.settings']['interval'] = 0; +- $config['config_split.config_split.ci']['status'] = TRUE; + $config['environment_indicator.indicator']['bg_color'] = '#006600'; + $config['environment_indicator.indicator']['fg_color'] = '#ffffff'; + $config['environment_indicator.indicator']['name'] = self::ENVIRONMENT_CI; diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_config_split/tests/phpunit/Drupal/SwitchableSettingsTest.php b/.vortex/installer/tests/Fixtures/install/modules_no_config_split/tests/phpunit/Drupal/SwitchableSettingsTest.php new file mode 100644 index 000000000..ddf9bd795 --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/modules_no_config_split/tests/phpunit/Drupal/SwitchableSettingsTest.php @@ -0,0 +1,94 @@ +@@ -76,93 +76,6 @@ + } + + /** +- * Test Config Split config. +- */ +- #[DataProvider('dataProviderConfigSplit')] +- public function testConfigSplit(string $env, array $expected_present, array $expected_absent): void { +- $this->setEnvVars([ +- 'DRUPAL_ENVIRONMENT' => $env, +- ]); +- +- $this->requireSettingsFile(); +- +- $this->assertConfigContains($expected_present); +- $this->assertConfigNotContains($expected_absent); +- } +- +- /** +- * Data provider for testConfigSplit(). +- */ +- public static function dataProviderConfigSplit(): array { +- return [ +- [ +- self::ENVIRONMENT_LOCAL, +- [ +- 'config_split.config_split.local' => ['status' => TRUE], +- ], +- [ +- 'config_split.config_split.stage' => NULL, +- 'config_split.config_split.dev' => NULL, +- 'config_split.config_split.ci' => NULL, +- ], +- ], +- [ +- self::ENVIRONMENT_CI, +- [ +- 'config_split.config_split.ci' => ['status' => TRUE], +- ], +- [ +- 'config_split.config_split.stage' => NULL, +- 'config_split.config_split.dev' => NULL, +- 'config_split.config_split.local' => NULL, +- ], +- ], +- [ +- self::ENVIRONMENT_DEV, +- [ +- 'config_split.config_split.dev' => ['status' => TRUE], +- ], +- [ +- 'config_split.config_split.stage' => NULL, +- 'config_split.config_split.ci' => NULL, +- 'config_split.config_split.local' => NULL, +- ], +- ], +- [ +- self::ENVIRONMENT_STAGE, +- [ +- 'config_split.config_split.stage' => ['status' => TRUE], +- ], +- [ +- 'config_split.config_split.dev' => NULL, +- 'config_split.config_split.ci' => NULL, +- 'config_split.config_split.local' => NULL, +- ], +- ], +- [ +- self::ENVIRONMENT_PROD, +- [], +- [ +- 'config_split.config_split.stage' => NULL, +- 'config_split.config_split.dev' => NULL, +- 'config_split.config_split.ci' => NULL, +- 'config_split.config_split.local' => NULL, +- ], +- ], +- [ +- self::ENVIRONMENT_SUT, +- [], +- [ +- 'config_split.config_split.stage' => NULL, +- 'config_split.config_split.dev' => NULL, +- 'config_split.config_split.ci' => NULL, +- 'config_split.config_split.local' => NULL, +- ], +- ], +- ]; +- } +- +- /** + * Test Environment Indicator config. + */ + #[DataProvider('dataProviderEnvironmentIndicator')] diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_config_split/web/sites/default/includes/modules/-settings.config_split.php b/.vortex/installer/tests/Fixtures/install/modules_no_config_split/web/sites/default/includes/modules/-settings.config_split.php new file mode 100644 index 000000000..e69de29bb diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_config_update/composer.json b/.vortex/installer/tests/Fixtures/install/modules_no_config_update/composer.json new file mode 100644 index 000000000..324bae86b --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/modules_no_config_update/composer.json @@ -0,0 +1,8 @@ +@@ -11,7 +11,6 @@ + "drupal/clamav": "__VERSION__", + "drupal/coffee": "__VERSION__", + "drupal/config_split": "__VERSION__", +- "drupal/config_update": "__VERSION__", + "drupal/core-composer-scaffold": "__VERSION__", + "drupal/core-recommended": "__VERSION__", + "drupal/environment_indicator": "__VERSION__", diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_config_update/scripts/custom/provision-10-example.sh b/.vortex/installer/tests/Fixtures/install/modules_no_config_update/scripts/custom/provision-10-example.sh new file mode 100644 index 000000000..ff3a1a0a5 --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/modules_no_config_update/scripts/custom/provision-10-example.sh @@ -0,0 +1,9 @@ +@@ -38,7 +38,7 @@ + drush php:eval "\Drupal::service('config.factory')->getEditable('system.site')->set('name', 'star wars')->save();" + + task "Installing contrib modules." +- drush pm:install admin_toolbar coffee config_split config_update media environment_indicator pathauto redirect robotstxt shield stage_file_proxy ++ drush pm:install admin_toolbar coffee config_split media environment_indicator pathauto redirect robotstxt shield stage_file_proxy + + task "Installing Redis module." + drush pm:install redis || true diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_environment_indicator/composer.json b/.vortex/installer/tests/Fixtures/install/modules_no_environment_indicator/composer.json new file mode 100644 index 000000000..be02f404d --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/modules_no_environment_indicator/composer.json @@ -0,0 +1,8 @@ +@@ -14,7 +14,6 @@ + "drupal/config_update": "__VERSION__", + "drupal/core-composer-scaffold": "__VERSION__", + "drupal/core-recommended": "__VERSION__", +- "drupal/environment_indicator": "__VERSION__", + "drupal/pathauto": "__VERSION__", + "drupal/redirect": "__VERSION__", + "drupal/redis": "__VERSION__", diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_environment_indicator/scripts/custom/provision-10-example.sh b/.vortex/installer/tests/Fixtures/install/modules_no_environment_indicator/scripts/custom/provision-10-example.sh new file mode 100644 index 000000000..29714979c --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/modules_no_environment_indicator/scripts/custom/provision-10-example.sh @@ -0,0 +1,9 @@ +@@ -38,7 +38,7 @@ + drush php:eval "\Drupal::service('config.factory')->getEditable('system.site')->set('name', 'star wars')->save();" + + task "Installing contrib modules." +- drush pm:install admin_toolbar coffee config_split config_update media environment_indicator pathauto redirect robotstxt shield stage_file_proxy ++ drush pm:install admin_toolbar coffee config_split config_update media pathauto redirect robotstxt shield stage_file_proxy + + task "Installing Redis module." + drush pm:install redis || true diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_environment_indicator/tests/phpunit/Drupal/EnvironmentSettingsTest.php b/.vortex/installer/tests/Fixtures/install/modules_no_environment_indicator/tests/phpunit/Drupal/EnvironmentSettingsTest.php new file mode 100644 index 000000000..97d8fdcde --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/modules_no_environment_indicator/tests/phpunit/Drupal/EnvironmentSettingsTest.php @@ -0,0 +1,60 @@ +@@ -72,11 +72,6 @@ + + $this->requireSettingsFile(); + +- $config['environment_indicator.indicator']['bg_color'] = '#006600'; +- $config['environment_indicator.indicator']['fg_color'] = '#ffffff'; +- $config['environment_indicator.indicator']['name'] = self::ENVIRONMENT_SUT; +- $config['environment_indicator.settings']['favicon'] = TRUE; +- $config['environment_indicator.settings']['toolbar_integration'] = [TRUE]; + $config['robotstxt.settings']['content'] = "User-agent: *\nDisallow: /"; + $config['shield.settings']['shield_enable'] = TRUE; + $config['system.performance']['cache']['page']['max_age'] = 900; +@@ -143,11 +138,6 @@ + $this->assertEquals($databases, $this->databases); + + // Verify key config overrides. +- $config['environment_indicator.indicator']['bg_color'] = '#006600'; +- $config['environment_indicator.indicator']['fg_color'] = '#ffffff'; +- $config['environment_indicator.indicator']['name'] = self::ENVIRONMENT_SUT; +- $config['environment_indicator.settings']['favicon'] = TRUE; +- $config['environment_indicator.settings']['toolbar_integration'] = [TRUE]; + $config['robotstxt.settings']['content'] = "User-agent: *\nDisallow: /"; + $config['shield.settings']['shield_enable'] = TRUE; + $config['system.performance']['cache']['page']['max_age'] = 1800; +@@ -187,11 +177,6 @@ + + $config['automated_cron.settings']['interval'] = 0; + $config['config_split.config_split.local']['status'] = TRUE; +- $config['environment_indicator.indicator']['bg_color'] = '#006600'; +- $config['environment_indicator.indicator']['fg_color'] = '#ffffff'; +- $config['environment_indicator.indicator']['name'] = self::ENVIRONMENT_LOCAL; +- $config['environment_indicator.settings']['favicon'] = TRUE; +- $config['environment_indicator.settings']['toolbar_integration'] = [TRUE]; + $config['robotstxt.settings']['content'] = "User-agent: *\nDisallow: /"; + $config['shield.settings']['shield_enable'] = FALSE; + $config['system.logging']['error_level'] = 'all'; +@@ -233,11 +218,6 @@ + + $config['automated_cron.settings']['interval'] = 0; + $config['config_split.config_split.local']['status'] = TRUE; +- $config['environment_indicator.indicator']['bg_color'] = '#006600'; +- $config['environment_indicator.indicator']['fg_color'] = '#ffffff'; +- $config['environment_indicator.indicator']['name'] = self::ENVIRONMENT_LOCAL; +- $config['environment_indicator.settings']['favicon'] = TRUE; +- $config['environment_indicator.settings']['toolbar_integration'] = [TRUE]; + $config['robotstxt.settings']['content'] = "User-agent: *\nDisallow: /"; + $config['shield.settings']['shield_enable'] = FALSE; + $config['system.logging']['error_level'] = 'all'; +@@ -281,11 +261,6 @@ + + $config['automated_cron.settings']['interval'] = 0; + $config['config_split.config_split.ci']['status'] = TRUE; +- $config['environment_indicator.indicator']['bg_color'] = '#006600'; +- $config['environment_indicator.indicator']['fg_color'] = '#ffffff'; +- $config['environment_indicator.indicator']['name'] = self::ENVIRONMENT_CI; +- $config['environment_indicator.settings']['favicon'] = TRUE; +- $config['environment_indicator.settings']['toolbar_integration'] = [TRUE]; + $config['robotstxt.settings']['content'] = "User-agent: *\nDisallow: /"; + $config['shield.settings']['shield_enable'] = FALSE; + $config['system.logging']['error_level'] = 'all'; diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_environment_indicator/tests/phpunit/Drupal/SwitchableSettingsTest.php b/.vortex/installer/tests/Fixtures/install/modules_no_environment_indicator/tests/phpunit/Drupal/SwitchableSettingsTest.php new file mode 100644 index 000000000..53e03642a --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/modules_no_environment_indicator/tests/phpunit/Drupal/SwitchableSettingsTest.php @@ -0,0 +1,72 @@ +@@ -163,71 +163,6 @@ + } + + /** +- * Test Environment Indicator config. +- */ +- #[DataProvider('dataProviderEnvironmentIndicator')] +- public function testEnvironmentIndicator(string $env, array $expected_present, array $expected_absent = []): void { +- $this->setEnvVars([ +- 'DRUPAL_ENVIRONMENT' => $env, +- ]); +- +- $this->requireSettingsFile(); +- +- $this->assertConfigContains($expected_present); +- $this->assertConfigNotContains($expected_absent); +- } +- +- /** +- * Data provider for testEnvironmentIndicator(). +- */ +- public static function dataProviderEnvironmentIndicator(): array { +- return [ +- [ +- self::ENVIRONMENT_LOCAL, +- [ +- 'environment_indicator.indicator' => ['name' => self::ENVIRONMENT_LOCAL, 'bg_color' => '#006600', 'fg_color' => '#ffffff'], +- 'environment_indicator.settings' => ['toolbar_integration' => [TRUE], 'favicon' => TRUE], +- ], +- ], +- [ +- self::ENVIRONMENT_CI, +- [ +- 'environment_indicator.indicator' => ['name' => self::ENVIRONMENT_CI, 'bg_color' => '#006600', 'fg_color' => '#ffffff'], +- 'environment_indicator.settings' => ['toolbar_integration' => [TRUE], 'favicon' => TRUE], +- ], +- ], +- [ +- self::ENVIRONMENT_DEV, +- [ +- 'environment_indicator.indicator' => ['name' => self::ENVIRONMENT_DEV, 'bg_color' => '#4caf50', 'fg_color' => '#000000'], +- 'environment_indicator.settings' => ['toolbar_integration' => [TRUE], 'favicon' => TRUE], +- ], +- ], +- [ +- self::ENVIRONMENT_STAGE, +- [ +- 'environment_indicator.indicator' => ['name' => self::ENVIRONMENT_STAGE, 'bg_color' => '#fff176', 'fg_color' => '#000000'], +- 'environment_indicator.settings' => ['toolbar_integration' => [TRUE], 'favicon' => TRUE], +- ], +- ], +- [ +- self::ENVIRONMENT_PROD, +- [ +- 'environment_indicator.indicator' => ['name' => self::ENVIRONMENT_PROD, 'bg_color' => '#ef5350', 'fg_color' => '#000000'], +- 'environment_indicator.settings' => ['toolbar_integration' => [TRUE], 'favicon' => TRUE], +- ], +- ], +- [ +- self::ENVIRONMENT_SUT, +- [ +- 'environment_indicator.indicator' => ['name' => self::ENVIRONMENT_SUT, 'bg_color' => '#006600', 'fg_color' => '#ffffff'], +- 'environment_indicator.settings' => ['toolbar_integration' => [TRUE], 'favicon' => TRUE], +- ], +- ], +- ]; +- } +- +- /** + * Test Redis settings. + */ + public function testRedis(): void { diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_environment_indicator/web/sites/default/includes/modules/-settings.environment_indicator.php b/.vortex/installer/tests/Fixtures/install/modules_no_environment_indicator/web/sites/default/includes/modules/-settings.environment_indicator.php new file mode 100644 index 000000000..e69de29bb diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_pathauto/composer.json b/.vortex/installer/tests/Fixtures/install/modules_no_pathauto/composer.json new file mode 100644 index 000000000..16dec2542 --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/modules_no_pathauto/composer.json @@ -0,0 +1,8 @@ +@@ -15,7 +15,6 @@ + "drupal/core-composer-scaffold": "__VERSION__", + "drupal/core-recommended": "__VERSION__", + "drupal/environment_indicator": "__VERSION__", +- "drupal/pathauto": "__VERSION__", + "drupal/redirect": "__VERSION__", + "drupal/redis": "__VERSION__", + "drupal/robotstxt": "__VERSION__", diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_pathauto/scripts/custom/provision-10-example.sh b/.vortex/installer/tests/Fixtures/install/modules_no_pathauto/scripts/custom/provision-10-example.sh new file mode 100644 index 000000000..3b99f8f13 --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/modules_no_pathauto/scripts/custom/provision-10-example.sh @@ -0,0 +1,9 @@ +@@ -38,7 +38,7 @@ + drush php:eval "\Drupal::service('config.factory')->getEditable('system.site')->set('name', 'star wars')->save();" + + task "Installing contrib modules." +- drush pm:install admin_toolbar coffee config_split config_update media environment_indicator pathauto redirect robotstxt shield stage_file_proxy ++ drush pm:install admin_toolbar coffee config_split config_update media environment_indicator redirect robotstxt shield stage_file_proxy + + task "Installing Redis module." + drush pm:install redis || true diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_redirect/composer.json b/.vortex/installer/tests/Fixtures/install/modules_no_redirect/composer.json new file mode 100644 index 000000000..e1cbba16f --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/modules_no_redirect/composer.json @@ -0,0 +1,8 @@ +@@ -16,7 +16,6 @@ + "drupal/core-recommended": "__VERSION__", + "drupal/environment_indicator": "__VERSION__", + "drupal/pathauto": "__VERSION__", +- "drupal/redirect": "__VERSION__", + "drupal/redis": "__VERSION__", + "drupal/robotstxt": "__VERSION__", + "drupal/search_api": "__VERSION__", diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_redirect/scripts/custom/provision-10-example.sh b/.vortex/installer/tests/Fixtures/install/modules_no_redirect/scripts/custom/provision-10-example.sh new file mode 100644 index 000000000..9d8cc49ac --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/modules_no_redirect/scripts/custom/provision-10-example.sh @@ -0,0 +1,9 @@ +@@ -38,7 +38,7 @@ + drush php:eval "\Drupal::service('config.factory')->getEditable('system.site')->set('name', 'star wars')->save();" + + task "Installing contrib modules." +- drush pm:install admin_toolbar coffee config_split config_update media environment_indicator pathauto redirect robotstxt shield stage_file_proxy ++ drush pm:install admin_toolbar coffee config_split config_update media environment_indicator pathauto robotstxt shield stage_file_proxy + + task "Installing Redis module." + drush pm:install redis || true diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_robotstxt/composer.json b/.vortex/installer/tests/Fixtures/install/modules_no_robotstxt/composer.json new file mode 100644 index 000000000..a1f905b6f --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/modules_no_robotstxt/composer.json @@ -0,0 +1,8 @@ +@@ -18,7 +18,6 @@ + "drupal/pathauto": "__VERSION__", + "drupal/redirect": "__VERSION__", + "drupal/redis": "__VERSION__", +- "drupal/robotstxt": "__VERSION__", + "drupal/search_api": "__VERSION__", + "drupal/search_api_solr": "__VERSION__", + "drupal/seckit": "__VERSION__", diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_robotstxt/scripts/custom/provision-10-example.sh b/.vortex/installer/tests/Fixtures/install/modules_no_robotstxt/scripts/custom/provision-10-example.sh new file mode 100644 index 000000000..188a92931 --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/modules_no_robotstxt/scripts/custom/provision-10-example.sh @@ -0,0 +1,9 @@ +@@ -38,7 +38,7 @@ + drush php:eval "\Drupal::service('config.factory')->getEditable('system.site')->set('name', 'star wars')->save();" + + task "Installing contrib modules." +- drush pm:install admin_toolbar coffee config_split config_update media environment_indicator pathauto redirect robotstxt shield stage_file_proxy ++ drush pm:install admin_toolbar coffee config_split config_update media environment_indicator pathauto redirect shield stage_file_proxy + + task "Installing Redis module." + drush pm:install redis || true diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_robotstxt/tests/behat/features/-robotstxt.feature b/.vortex/installer/tests/Fixtures/install/modules_no_robotstxt/tests/behat/features/-robotstxt.feature new file mode 100644 index 000000000..e69de29bb diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_robotstxt/tests/phpunit/Drupal/EnvironmentSettingsTest.php b/.vortex/installer/tests/Fixtures/install/modules_no_robotstxt/tests/phpunit/Drupal/EnvironmentSettingsTest.php new file mode 100644 index 000000000..10d999837 --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/modules_no_robotstxt/tests/phpunit/Drupal/EnvironmentSettingsTest.php @@ -0,0 +1,40 @@ +@@ -77,7 +77,6 @@ + $config['environment_indicator.indicator']['name'] = self::ENVIRONMENT_SUT; + $config['environment_indicator.settings']['favicon'] = TRUE; + $config['environment_indicator.settings']['toolbar_integration'] = [TRUE]; +- $config['robotstxt.settings']['content'] = "User-agent: *\nDisallow: /"; + $config['shield.settings']['shield_enable'] = TRUE; + $config['system.performance']['cache']['page']['max_age'] = 900; + $this->assertConfig($config); +@@ -148,7 +147,6 @@ + $config['environment_indicator.indicator']['name'] = self::ENVIRONMENT_SUT; + $config['environment_indicator.settings']['favicon'] = TRUE; + $config['environment_indicator.settings']['toolbar_integration'] = [TRUE]; +- $config['robotstxt.settings']['content'] = "User-agent: *\nDisallow: /"; + $config['shield.settings']['shield_enable'] = TRUE; + $config['system.performance']['cache']['page']['max_age'] = 1800; + $this->assertConfig($config); +@@ -192,7 +190,6 @@ + $config['environment_indicator.indicator']['name'] = self::ENVIRONMENT_LOCAL; + $config['environment_indicator.settings']['favicon'] = TRUE; + $config['environment_indicator.settings']['toolbar_integration'] = [TRUE]; +- $config['robotstxt.settings']['content'] = "User-agent: *\nDisallow: /"; + $config['shield.settings']['shield_enable'] = FALSE; + $config['system.logging']['error_level'] = 'all'; + $config['system.performance']['cache']['page']['max_age'] = 900; +@@ -238,7 +235,6 @@ + $config['environment_indicator.indicator']['name'] = self::ENVIRONMENT_LOCAL; + $config['environment_indicator.settings']['favicon'] = TRUE; + $config['environment_indicator.settings']['toolbar_integration'] = [TRUE]; +- $config['robotstxt.settings']['content'] = "User-agent: *\nDisallow: /"; + $config['shield.settings']['shield_enable'] = FALSE; + $config['system.logging']['error_level'] = 'all'; + $config['system.performance']['cache']['page']['max_age'] = 900; +@@ -286,7 +282,6 @@ + $config['environment_indicator.indicator']['name'] = self::ENVIRONMENT_CI; + $config['environment_indicator.settings']['favicon'] = TRUE; + $config['environment_indicator.settings']['toolbar_integration'] = [TRUE]; +- $config['robotstxt.settings']['content'] = "User-agent: *\nDisallow: /"; + $config['shield.settings']['shield_enable'] = FALSE; + $config['system.logging']['error_level'] = 'all'; + $config['system.performance']['cache']['page']['max_age'] = 900; diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_robotstxt/web/sites/default/includes/modules/-settings.robotstxt.php b/.vortex/installer/tests/Fixtures/install/modules_no_robotstxt/web/sites/default/includes/modules/-settings.robotstxt.php new file mode 100644 index 000000000..e69de29bb diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_seckit/composer.json b/.vortex/installer/tests/Fixtures/install/modules_no_seckit/composer.json new file mode 100644 index 000000000..8b0c83381 --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/modules_no_seckit/composer.json @@ -0,0 +1,8 @@ +@@ -21,7 +21,6 @@ + "drupal/robotstxt": "__VERSION__", + "drupal/search_api": "__VERSION__", + "drupal/search_api_solr": "__VERSION__", +- "drupal/seckit": "__VERSION__", + "drupal/shield": "__VERSION__", + "drupal/stage_file_proxy": "__VERSION__", + "drush/drush": "__VERSION__", diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_seckit/tests/phpunit/Drupal/EnvironmentSettingsTest.php b/.vortex/installer/tests/Fixtures/install/modules_no_seckit/tests/phpunit/Drupal/EnvironmentSettingsTest.php new file mode 100644 index 000000000..8321dfc51 --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/modules_no_seckit/tests/phpunit/Drupal/EnvironmentSettingsTest.php @@ -0,0 +1,27 @@ +@@ -196,8 +196,6 @@ + $config['shield.settings']['shield_enable'] = FALSE; + $config['system.logging']['error_level'] = 'all'; + $config['system.performance']['cache']['page']['max_age'] = 900; +- $config['seckit.settings']['seckit_xss']['csp']['checkbox'] = FALSE; +- $config['seckit.settings']['seckit_xss']['csp']['upgrade-req'] = FALSE; + $this->assertConfig($config); + + $settings['config_exclude_modules'] = []; +@@ -242,8 +240,6 @@ + $config['shield.settings']['shield_enable'] = FALSE; + $config['system.logging']['error_level'] = 'all'; + $config['system.performance']['cache']['page']['max_age'] = 900; +- $config['seckit.settings']['seckit_xss']['csp']['checkbox'] = FALSE; +- $config['seckit.settings']['seckit_xss']['csp']['upgrade-req'] = FALSE; + $this->assertConfig($config); + + $settings['config_exclude_modules'] = []; +@@ -290,8 +286,6 @@ + $config['shield.settings']['shield_enable'] = FALSE; + $config['system.logging']['error_level'] = 'all'; + $config['system.performance']['cache']['page']['max_age'] = 900; +- $config['seckit.settings']['seckit_xss']['csp']['checkbox'] = FALSE; +- $config['seckit.settings']['seckit_xss']['csp']['upgrade-req'] = FALSE; + $this->assertConfig($config); + + $settings['config_exclude_modules'] = []; diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_seckit/web/sites/default/includes/modules/-settings.seckit.php b/.vortex/installer/tests/Fixtures/install/modules_no_seckit/web/sites/default/includes/modules/-settings.seckit.php new file mode 100644 index 000000000..e69de29bb diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_seckit_shield_stage_file_proxy/.env b/.vortex/installer/tests/Fixtures/install/modules_no_seckit_shield_stage_file_proxy/.env new file mode 100644 index 000000000..e67a53d3d --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/modules_no_seckit_shield_stage_file_proxy/.env @@ -0,0 +1,16 @@ +@@ -61,15 +61,6 @@ + # Drupal maintenance theme name. + DRUPAL_MAINTENANCE_THEME=star_wars + +-# Stage file proxy origin. +-# +-# If using Shield, the HTTP authentication credentials will be automatically +-# added to the origin URL. +-DRUPAL_STAGE_FILE_PROXY_ORIGIN=https://www.star-wars.com +- +-# Shield message. +-DRUPAL_SHIELD_PRINT="Restricted access." +- + # Enable Redis integration. + # See settings.redis.php for details. + DRUPAL_REDIS_ENABLED=1 diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_seckit_shield_stage_file_proxy/composer.json b/.vortex/installer/tests/Fixtures/install/modules_no_seckit_shield_stage_file_proxy/composer.json new file mode 100644 index 000000000..123d13975 --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/modules_no_seckit_shield_stage_file_proxy/composer.json @@ -0,0 +1,10 @@ +@@ -21,9 +21,6 @@ + "drupal/robotstxt": "__VERSION__", + "drupal/search_api": "__VERSION__", + "drupal/search_api_solr": "__VERSION__", +- "drupal/seckit": "__VERSION__", +- "drupal/shield": "__VERSION__", +- "drupal/stage_file_proxy": "__VERSION__", + "drush/drush": "__VERSION__", + "oomphinc/composer-installers-extender": "__VERSION__", + "webflo/drupal-finder": "__VERSION__" diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_seckit_shield_stage_file_proxy/docker-compose.yml b/.vortex/installer/tests/Fixtures/install/modules_no_seckit_shield_stage_file_proxy/docker-compose.yml new file mode 100644 index 000000000..193dbfcee --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/modules_no_seckit_shield_stage_file_proxy/docker-compose.yml @@ -0,0 +1,10 @@ +@@ -49,9 +49,6 @@ + DRUPAL_TEMPORARY_FILES: ${DRUPAL_TEMPORARY_FILES:-/tmp} + # Path to configuration files. + DRUPAL_CONFIG_PATH: ${DRUPAL_CONFIG_PATH:-../config/default} +- # Drupal Shield credentials. +- DRUPAL_SHIELD_USER: ${DRUPAL_SHIELD_USER:-} +- DRUPAL_SHIELD_PASS: ${DRUPAL_SHIELD_PASS:-} + # Redis integration flag. + DRUPAL_REDIS_ENABLED: ${DRUPAL_REDIS_ENABLED:-} + diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_seckit_shield_stage_file_proxy/scripts/custom/provision-10-example.sh b/.vortex/installer/tests/Fixtures/install/modules_no_seckit_shield_stage_file_proxy/scripts/custom/provision-10-example.sh new file mode 100644 index 000000000..97c14206b --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/modules_no_seckit_shield_stage_file_proxy/scripts/custom/provision-10-example.sh @@ -0,0 +1,9 @@ +@@ -38,7 +38,7 @@ + drush php:eval "\Drupal::service('config.factory')->getEditable('system.site')->set('name', 'star wars')->save();" + + task "Installing contrib modules." +- drush pm:install admin_toolbar coffee config_split config_update media environment_indicator pathauto redirect robotstxt shield stage_file_proxy ++ drush pm:install admin_toolbar coffee config_split config_update media environment_indicator pathauto redirect robotstxt + + task "Installing Redis module." + drush pm:install redis || true diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_seckit_shield_stage_file_proxy/tests/phpunit/Drupal/EnvironmentSettingsTest.php b/.vortex/installer/tests/Fixtures/install/modules_no_seckit_shield_stage_file_proxy/tests/phpunit/Drupal/EnvironmentSettingsTest.php new file mode 100644 index 000000000..b39ac6995 --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/modules_no_seckit_shield_stage_file_proxy/tests/phpunit/Drupal/EnvironmentSettingsTest.php @@ -0,0 +1,52 @@ +@@ -78,7 +78,6 @@ + $config['environment_indicator.settings']['favicon'] = TRUE; + $config['environment_indicator.settings']['toolbar_integration'] = [TRUE]; + $config['robotstxt.settings']['content'] = "User-agent: *\nDisallow: /"; +- $config['shield.settings']['shield_enable'] = TRUE; + $config['system.performance']['cache']['page']['max_age'] = 900; + $this->assertConfig($config); + +@@ -149,7 +148,6 @@ + $config['environment_indicator.settings']['favicon'] = TRUE; + $config['environment_indicator.settings']['toolbar_integration'] = [TRUE]; + $config['robotstxt.settings']['content'] = "User-agent: *\nDisallow: /"; +- $config['shield.settings']['shield_enable'] = TRUE; + $config['system.performance']['cache']['page']['max_age'] = 1800; + $this->assertConfig($config); + +@@ -193,11 +191,8 @@ + $config['environment_indicator.settings']['favicon'] = TRUE; + $config['environment_indicator.settings']['toolbar_integration'] = [TRUE]; + $config['robotstxt.settings']['content'] = "User-agent: *\nDisallow: /"; +- $config['shield.settings']['shield_enable'] = FALSE; + $config['system.logging']['error_level'] = 'all'; + $config['system.performance']['cache']['page']['max_age'] = 900; +- $config['seckit.settings']['seckit_xss']['csp']['checkbox'] = FALSE; +- $config['seckit.settings']['seckit_xss']['csp']['upgrade-req'] = FALSE; + $this->assertConfig($config); + + $settings['config_exclude_modules'] = []; +@@ -239,11 +234,8 @@ + $config['environment_indicator.settings']['favicon'] = TRUE; + $config['environment_indicator.settings']['toolbar_integration'] = [TRUE]; + $config['robotstxt.settings']['content'] = "User-agent: *\nDisallow: /"; +- $config['shield.settings']['shield_enable'] = FALSE; + $config['system.logging']['error_level'] = 'all'; + $config['system.performance']['cache']['page']['max_age'] = 900; +- $config['seckit.settings']['seckit_xss']['csp']['checkbox'] = FALSE; +- $config['seckit.settings']['seckit_xss']['csp']['upgrade-req'] = FALSE; + $this->assertConfig($config); + + $settings['config_exclude_modules'] = []; +@@ -287,11 +279,8 @@ + $config['environment_indicator.settings']['favicon'] = TRUE; + $config['environment_indicator.settings']['toolbar_integration'] = [TRUE]; + $config['robotstxt.settings']['content'] = "User-agent: *\nDisallow: /"; +- $config['shield.settings']['shield_enable'] = FALSE; + $config['system.logging']['error_level'] = 'all'; + $config['system.performance']['cache']['page']['max_age'] = 900; +- $config['seckit.settings']['seckit_xss']['csp']['checkbox'] = FALSE; +- $config['seckit.settings']['seckit_xss']['csp']['upgrade-req'] = FALSE; + $this->assertConfig($config); + + $settings['config_exclude_modules'] = []; diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_seckit_shield_stage_file_proxy/tests/phpunit/Drupal/SwitchableSettingsTest.php b/.vortex/installer/tests/Fixtures/install/modules_no_seckit_shield_stage_file_proxy/tests/phpunit/Drupal/SwitchableSettingsTest.php new file mode 100644 index 000000000..eff9bd754 --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/modules_no_seckit_shield_stage_file_proxy/tests/phpunit/Drupal/SwitchableSettingsTest.php @@ -0,0 +1,366 @@ +@@ -301,365 +301,6 @@ + } + + /** +- * Test Shield config. +- */ +- #[DataProvider('dataProviderShield')] +- public function testShield(string $env, array $vars, array $expected_present, array $expected_absent = []): void { +- $this->setEnvVars($vars + ['DRUPAL_ENVIRONMENT' => $env]); +- +- $this->requireSettingsFile(); +- +- $this->assertConfigContains($expected_present); +- $this->assertConfigNotContains($expected_absent); +- } +- +- /** +- * Data provider for testShield(). +- */ +- public static function dataProviderShield(): array { +- return [ +- [ +- self::ENVIRONMENT_LOCAL, +- [], +- [ +- 'shield.settings' => ['shield_enable' => FALSE], +- ], +- [ +- 'shield.settings' => ['credentials' => ['shield' => ['user' => 'drupal_shield_user', 'pass' => 'drupal_shield_pass']], 'print' => 'drupal_shield_print'], +- ], +- ], +- [ +- self::ENVIRONMENT_LOCAL, +- [ +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- ], +- [ +- 'shield.settings' => ['shield_enable' => FALSE], +- ], +- [ +- 'shield.settings' => ['credentials' => ['shield' => ['user' => 'drupal_shield_user', 'pass' => 'drupal_shield_pass']], 'print' => 'drupal_shield_print'], +- ], +- ], +- [ +- self::ENVIRONMENT_LOCAL, +- [ +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- 'DRUPAL_SHIELD_PRINT' => 'drupal_shield_print', +- ], +- [ +- 'shield.settings' => ['shield_enable' => FALSE, 'credentials' => ['shield' => ['user' => 'drupal_shield_user', 'pass' => 'drupal_shield_pass']], 'print' => 'drupal_shield_print'], +- ], +- ], +- +- [ +- self::ENVIRONMENT_CI, +- [ +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- 'DRUPAL_SHIELD_PRINT' => 'drupal_shield_print', +- ], +- [ +- 'shield.settings' => ['shield_enable' => FALSE, 'credentials' => ['shield' => ['user' => 'drupal_shield_user', 'pass' => 'drupal_shield_pass']], 'print' => 'drupal_shield_print'], +- ], +- ], +- +- [ +- self::ENVIRONMENT_DEV, +- [ +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- 'DRUPAL_SHIELD_PRINT' => 'drupal_shield_print', +- ], +- [ +- 'shield.settings' => ['shield_enable' => TRUE, 'credentials' => ['shield' => ['user' => 'drupal_shield_user', 'pass' => 'drupal_shield_pass']], 'print' => 'drupal_shield_print'], +- ], +- ], +- +- [ +- self::ENVIRONMENT_STAGE, +- [ +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- 'DRUPAL_SHIELD_PRINT' => 'drupal_shield_print', +- ], +- [ +- 'shield.settings' => ['shield_enable' => TRUE, 'credentials' => ['shield' => ['user' => 'drupal_shield_user', 'pass' => 'drupal_shield_pass']], 'print' => 'drupal_shield_print'], +- ], +- ], +- +- [ +- self::ENVIRONMENT_PROD, +- [ +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- 'DRUPAL_SHIELD_PRINT' => 'drupal_shield_print', +- ], +- [ +- 'shield.settings' => ['credentials' => ['shield' => ['user' => 'drupal_shield_user', 'pass' => 'drupal_shield_pass']], 'print' => 'drupal_shield_print'], +- ], +- [ +- 'shield.settings' => ['shield_enable' => FALSE], +- ], +- ], +- +- [ +- self::ENVIRONMENT_SUT, +- [ +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- 'DRUPAL_SHIELD_PRINT' => 'drupal_shield_print', +- ], +- [ +- 'shield.settings' => ['shield_enable' => TRUE, 'credentials' => ['shield' => ['user' => 'drupal_shield_user', 'pass' => 'drupal_shield_pass']], 'print' => 'drupal_shield_print'], +- ], +- ], +- +- [ +- self::ENVIRONMENT_DEV, +- [ +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- 'DRUPAL_SHIELD_PRINT' => 'drupal_shield_print', +- 'DRUPAL_SHIELD_DISABLED' => '', +- ], +- [ +- 'shield.settings' => ['shield_enable' => TRUE, 'credentials' => ['shield' => ['user' => 'drupal_shield_user', 'pass' => 'drupal_shield_pass']], 'print' => 'drupal_shield_print'], +- ], +- ], +- +- [ +- self::ENVIRONMENT_DEV, +- [ +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- 'DRUPAL_SHIELD_PRINT' => 'drupal_shield_print', +- 'DRUPAL_SHIELD_DISABLED' => 0, +- ], +- [ +- 'shield.settings' => ['shield_enable' => TRUE, 'credentials' => ['shield' => ['user' => 'drupal_shield_user', 'pass' => 'drupal_shield_pass']], 'print' => 'drupal_shield_print'], +- ], +- ], +- [ +- self::ENVIRONMENT_DEV, +- [ +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- 'DRUPAL_SHIELD_PRINT' => 'drupal_shield_print', +- 'DRUPAL_SHIELD_DISABLED' => 1, +- ], +- [ +- 'shield.settings' => ['shield_enable' => FALSE, 'credentials' => ['shield' => ['user' => 'drupal_shield_user', 'pass' => 'drupal_shield_pass']], 'print' => 'drupal_shield_print'], +- ], +- ], +- +- [ +- self::ENVIRONMENT_DEV, +- [ +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- 'DRUPAL_SHIELD_PRINT' => 'drupal_shield_print', +- 'DRUPAL_SHIELD_DISABLED' => '0', +- ], +- [ +- 'shield.settings' => ['shield_enable' => TRUE, 'credentials' => ['shield' => ['user' => 'drupal_shield_user', 'pass' => 'drupal_shield_pass']], 'print' => 'drupal_shield_print'], +- ], +- ], +- [ +- self::ENVIRONMENT_DEV, +- [ +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- 'DRUPAL_SHIELD_PRINT' => 'drupal_shield_print', +- 'DRUPAL_SHIELD_DISABLED' => '1', +- ], +- [ +- 'shield.settings' => ['shield_enable' => FALSE, 'credentials' => ['shield' => ['user' => 'drupal_shield_user', 'pass' => 'drupal_shield_pass']], 'print' => 'drupal_shield_print'], +- ], +- ], +- [ +- self::ENVIRONMENT_DEV, +- [ +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- 'DRUPAL_SHIELD_PRINT' => 'drupal_shield_print', +- 'DRUPAL_SHIELD_DISABLED' => 'false', +- ], +- [ +- 'shield.settings' => ['shield_enable' => FALSE, 'credentials' => ['shield' => ['user' => 'drupal_shield_user', 'pass' => 'drupal_shield_pass']], 'print' => 'drupal_shield_print'], +- ], +- ], +- [ +- self::ENVIRONMENT_DEV, +- [ +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- 'DRUPAL_SHIELD_PRINT' => 'drupal_shield_print', +- 'DRUPAL_SHIELD_DISABLED' => 'true', +- ], +- [ +- 'shield.settings' => ['shield_enable' => FALSE, 'credentials' => ['shield' => ['user' => 'drupal_shield_user', 'pass' => 'drupal_shield_pass']], 'print' => 'drupal_shield_print'], +- ], +- ], +- +- [ +- self::ENVIRONMENT_DEV, +- [ +- 'DRUPAL_SHIELD_DISABLED' => TRUE, +- ], +- [ +- 'shield.settings' => ['shield_enable' => FALSE], +- ], +- ], +- [ +- self::ENVIRONMENT_STAGE, +- [ +- 'DRUPAL_SHIELD_DISABLED' => TRUE, +- ], +- [ +- 'shield.settings' => ['shield_enable' => FALSE], +- ], +- ], +- [ +- self::ENVIRONMENT_PROD, +- [ +- 'DRUPAL_SHIELD_DISABLED' => TRUE, +- ], +- [ +- 'shield.settings' => ['shield_enable' => FALSE], +- ], +- ], +- ]; +- } +- +- /** +- * Test Stage File Proxy config. +- */ +- #[DataProvider('dataProviderStageFileProxy')] +- public function testStageFileProxy(string $env, array $vars, array $expected_present, array $expected_absent = []): void { +- $this->setEnvVars($vars + ['DRUPAL_ENVIRONMENT' => $env]); +- +- $this->requireSettingsFile(); +- +- $this->assertConfigContains($expected_present); +- $this->assertConfigNotContains($expected_absent); +- } +- +- /** +- * Data provider for testStageFileProxy(). +- */ +- public static function dataProviderStageFileProxy(): array { +- return [ +- [ +- self::ENVIRONMENT_LOCAL, +- [], +- [], +- [ +- 'stage_file_proxy.settings' => ['hotlink' => FALSE, 'origin' => 'https://example.com/'], +- ], +- ], +- [ +- self::ENVIRONMENT_LOCAL, +- [ +- 'DRUPAL_STAGE_FILE_PROXY_ORIGIN' => 'https://example.com/', +- ], +- [ +- 'stage_file_proxy.settings' => ['hotlink' => FALSE, 'origin' => 'https://example.com/'], +- ], +- [], +- ], +- [ +- self::ENVIRONMENT_LOCAL, +- [ +- 'DRUPAL_STAGE_FILE_PROXY_ORIGIN' => 'https://example.com/', +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- ], +- [ +- 'stage_file_proxy.settings' => ['hotlink' => FALSE, 'origin' => 'https://drupal_shield_user:drupal_shield_pass@example.com/'], +- ], +- [], +- ], +- [ +- self::ENVIRONMENT_LOCAL, +- [ +- 'DRUPAL_STAGE_FILE_PROXY_ORIGIN' => 'https://example.com/', +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- ], +- [ +- 'stage_file_proxy.settings' => ['hotlink' => FALSE, 'origin' => 'https://example.com/'], +- ], +- [], +- ], +- +- [ +- self::ENVIRONMENT_CI, +- [ +- 'DRUPAL_STAGE_FILE_PROXY_ORIGIN' => 'https://example.com/', +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- ], +- [ +- 'stage_file_proxy.settings' => ['hotlink' => FALSE, 'origin' => 'https://drupal_shield_user:drupal_shield_pass@example.com/'], +- ], +- [], +- ], +- +- [ +- self::ENVIRONMENT_DEV, +- [ +- 'DRUPAL_STAGE_FILE_PROXY_ORIGIN' => 'https://example.com/', +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- ], +- [ +- 'stage_file_proxy.settings' => ['hotlink' => FALSE, 'origin' => 'https://drupal_shield_user:drupal_shield_pass@example.com/'], +- ], +- [], +- ], +- +- [ +- self::ENVIRONMENT_STAGE, +- [ +- 'DRUPAL_STAGE_FILE_PROXY_ORIGIN' => 'https://example.com/', +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- ], +- [ +- 'stage_file_proxy.settings' => ['hotlink' => FALSE, 'origin' => 'https://drupal_shield_user:drupal_shield_pass@example.com/'], +- ], +- [], +- ], +- +- [ +- self::ENVIRONMENT_PROD, +- [ +- 'DRUPAL_STAGE_FILE_PROXY_ORIGIN' => 'https://example.com/', +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- ], +- [], +- [ +- 'stage_file_proxy.settings' => ['hotlink' => FALSE, 'origin' => 'https://drupal_shield_user:drupal_shield_pass@example.com/'], +- ], +- ], +- +- [ +- self::ENVIRONMENT_SUT, +- [ +- 'DRUPAL_STAGE_FILE_PROXY_ORIGIN' => 'https://example.com/', +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- ], +- [ +- 'stage_file_proxy.settings' => ['hotlink' => FALSE, 'origin' => 'https://drupal_shield_user:drupal_shield_pass@example.com/'], +- ], +- [], +- ], +- ]; +- } +- +- /** + * Test trusted host patterns settings. + */ + #[DataProvider('dataProviderTrustedHostPatterns')] diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_seckit_shield_stage_file_proxy/web/sites/default/includes/modules/-settings.seckit.php b/.vortex/installer/tests/Fixtures/install/modules_no_seckit_shield_stage_file_proxy/web/sites/default/includes/modules/-settings.seckit.php new file mode 100644 index 000000000..e69de29bb diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_seckit_shield_stage_file_proxy/web/sites/default/includes/modules/-settings.shield.php b/.vortex/installer/tests/Fixtures/install/modules_no_seckit_shield_stage_file_proxy/web/sites/default/includes/modules/-settings.shield.php new file mode 100644 index 000000000..e69de29bb diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_seckit_shield_stage_file_proxy/web/sites/default/includes/modules/-settings.stage_file_proxy.php b/.vortex/installer/tests/Fixtures/install/modules_no_seckit_shield_stage_file_proxy/web/sites/default/includes/modules/-settings.stage_file_proxy.php new file mode 100644 index 000000000..e69de29bb diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_shield/.env b/.vortex/installer/tests/Fixtures/install/modules_no_shield/.env new file mode 100644 index 000000000..6d16bfae9 --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/modules_no_shield/.env @@ -0,0 +1,14 @@ +@@ -62,13 +62,7 @@ + DRUPAL_MAINTENANCE_THEME=star_wars + + # Stage file proxy origin. +-# +-# If using Shield, the HTTP authentication credentials will be automatically +-# added to the origin URL. + DRUPAL_STAGE_FILE_PROXY_ORIGIN=https://www.star-wars.com +- +-# Shield message. +-DRUPAL_SHIELD_PRINT="Restricted access." + + # Enable Redis integration. + # See settings.redis.php for details. diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_shield/composer.json b/.vortex/installer/tests/Fixtures/install/modules_no_shield/composer.json new file mode 100644 index 000000000..90509afd5 --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/modules_no_shield/composer.json @@ -0,0 +1,8 @@ +@@ -22,7 +22,6 @@ + "drupal/search_api": "__VERSION__", + "drupal/search_api_solr": "__VERSION__", + "drupal/seckit": "__VERSION__", +- "drupal/shield": "__VERSION__", + "drupal/stage_file_proxy": "__VERSION__", + "drush/drush": "__VERSION__", + "oomphinc/composer-installers-extender": "__VERSION__", diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_shield/docker-compose.yml b/.vortex/installer/tests/Fixtures/install/modules_no_shield/docker-compose.yml new file mode 100644 index 000000000..193dbfcee --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/modules_no_shield/docker-compose.yml @@ -0,0 +1,10 @@ +@@ -49,9 +49,6 @@ + DRUPAL_TEMPORARY_FILES: ${DRUPAL_TEMPORARY_FILES:-/tmp} + # Path to configuration files. + DRUPAL_CONFIG_PATH: ${DRUPAL_CONFIG_PATH:-../config/default} +- # Drupal Shield credentials. +- DRUPAL_SHIELD_USER: ${DRUPAL_SHIELD_USER:-} +- DRUPAL_SHIELD_PASS: ${DRUPAL_SHIELD_PASS:-} + # Redis integration flag. + DRUPAL_REDIS_ENABLED: ${DRUPAL_REDIS_ENABLED:-} + diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_shield/scripts/custom/provision-10-example.sh b/.vortex/installer/tests/Fixtures/install/modules_no_shield/scripts/custom/provision-10-example.sh new file mode 100644 index 000000000..1978e256f --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/modules_no_shield/scripts/custom/provision-10-example.sh @@ -0,0 +1,9 @@ +@@ -38,7 +38,7 @@ + drush php:eval "\Drupal::service('config.factory')->getEditable('system.site')->set('name', 'star wars')->save();" + + task "Installing contrib modules." +- drush pm:install admin_toolbar coffee config_split config_update media environment_indicator pathauto redirect robotstxt shield stage_file_proxy ++ drush pm:install admin_toolbar coffee config_split config_update media environment_indicator pathauto redirect robotstxt stage_file_proxy + + task "Installing Redis module." + drush pm:install redis || true diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_shield/tests/phpunit/Drupal/EnvironmentSettingsTest.php b/.vortex/installer/tests/Fixtures/install/modules_no_shield/tests/phpunit/Drupal/EnvironmentSettingsTest.php new file mode 100644 index 000000000..5a2327b4e --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/modules_no_shield/tests/phpunit/Drupal/EnvironmentSettingsTest.php @@ -0,0 +1,40 @@ +@@ -78,7 +78,6 @@ + $config['environment_indicator.settings']['favicon'] = TRUE; + $config['environment_indicator.settings']['toolbar_integration'] = [TRUE]; + $config['robotstxt.settings']['content'] = "User-agent: *\nDisallow: /"; +- $config['shield.settings']['shield_enable'] = TRUE; + $config['system.performance']['cache']['page']['max_age'] = 900; + $this->assertConfig($config); + +@@ -149,7 +148,6 @@ + $config['environment_indicator.settings']['favicon'] = TRUE; + $config['environment_indicator.settings']['toolbar_integration'] = [TRUE]; + $config['robotstxt.settings']['content'] = "User-agent: *\nDisallow: /"; +- $config['shield.settings']['shield_enable'] = TRUE; + $config['system.performance']['cache']['page']['max_age'] = 1800; + $this->assertConfig($config); + +@@ -193,7 +191,6 @@ + $config['environment_indicator.settings']['favicon'] = TRUE; + $config['environment_indicator.settings']['toolbar_integration'] = [TRUE]; + $config['robotstxt.settings']['content'] = "User-agent: *\nDisallow: /"; +- $config['shield.settings']['shield_enable'] = FALSE; + $config['system.logging']['error_level'] = 'all'; + $config['system.performance']['cache']['page']['max_age'] = 900; + $config['seckit.settings']['seckit_xss']['csp']['checkbox'] = FALSE; +@@ -239,7 +236,6 @@ + $config['environment_indicator.settings']['favicon'] = TRUE; + $config['environment_indicator.settings']['toolbar_integration'] = [TRUE]; + $config['robotstxt.settings']['content'] = "User-agent: *\nDisallow: /"; +- $config['shield.settings']['shield_enable'] = FALSE; + $config['system.logging']['error_level'] = 'all'; + $config['system.performance']['cache']['page']['max_age'] = 900; + $config['seckit.settings']['seckit_xss']['csp']['checkbox'] = FALSE; +@@ -287,7 +283,6 @@ + $config['environment_indicator.settings']['favicon'] = TRUE; + $config['environment_indicator.settings']['toolbar_integration'] = [TRUE]; + $config['robotstxt.settings']['content'] = "User-agent: *\nDisallow: /"; +- $config['shield.settings']['shield_enable'] = FALSE; + $config['system.logging']['error_level'] = 'all'; + $config['system.performance']['cache']['page']['max_age'] = 900; + $config['seckit.settings']['seckit_xss']['csp']['checkbox'] = FALSE; diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_shield/tests/phpunit/Drupal/SwitchableSettingsTest.php b/.vortex/installer/tests/Fixtures/install/modules_no_shield/tests/phpunit/Drupal/SwitchableSettingsTest.php new file mode 100644 index 000000000..301f13457 --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/modules_no_shield/tests/phpunit/Drupal/SwitchableSettingsTest.php @@ -0,0 +1,239 @@ +@@ -301,238 +301,6 @@ + } + + /** +- * Test Shield config. +- */ +- #[DataProvider('dataProviderShield')] +- public function testShield(string $env, array $vars, array $expected_present, array $expected_absent = []): void { +- $this->setEnvVars($vars + ['DRUPAL_ENVIRONMENT' => $env]); +- +- $this->requireSettingsFile(); +- +- $this->assertConfigContains($expected_present); +- $this->assertConfigNotContains($expected_absent); +- } +- +- /** +- * Data provider for testShield(). +- */ +- public static function dataProviderShield(): array { +- return [ +- [ +- self::ENVIRONMENT_LOCAL, +- [], +- [ +- 'shield.settings' => ['shield_enable' => FALSE], +- ], +- [ +- 'shield.settings' => ['credentials' => ['shield' => ['user' => 'drupal_shield_user', 'pass' => 'drupal_shield_pass']], 'print' => 'drupal_shield_print'], +- ], +- ], +- [ +- self::ENVIRONMENT_LOCAL, +- [ +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- ], +- [ +- 'shield.settings' => ['shield_enable' => FALSE], +- ], +- [ +- 'shield.settings' => ['credentials' => ['shield' => ['user' => 'drupal_shield_user', 'pass' => 'drupal_shield_pass']], 'print' => 'drupal_shield_print'], +- ], +- ], +- [ +- self::ENVIRONMENT_LOCAL, +- [ +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- 'DRUPAL_SHIELD_PRINT' => 'drupal_shield_print', +- ], +- [ +- 'shield.settings' => ['shield_enable' => FALSE, 'credentials' => ['shield' => ['user' => 'drupal_shield_user', 'pass' => 'drupal_shield_pass']], 'print' => 'drupal_shield_print'], +- ], +- ], +- +- [ +- self::ENVIRONMENT_CI, +- [ +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- 'DRUPAL_SHIELD_PRINT' => 'drupal_shield_print', +- ], +- [ +- 'shield.settings' => ['shield_enable' => FALSE, 'credentials' => ['shield' => ['user' => 'drupal_shield_user', 'pass' => 'drupal_shield_pass']], 'print' => 'drupal_shield_print'], +- ], +- ], +- +- [ +- self::ENVIRONMENT_DEV, +- [ +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- 'DRUPAL_SHIELD_PRINT' => 'drupal_shield_print', +- ], +- [ +- 'shield.settings' => ['shield_enable' => TRUE, 'credentials' => ['shield' => ['user' => 'drupal_shield_user', 'pass' => 'drupal_shield_pass']], 'print' => 'drupal_shield_print'], +- ], +- ], +- +- [ +- self::ENVIRONMENT_STAGE, +- [ +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- 'DRUPAL_SHIELD_PRINT' => 'drupal_shield_print', +- ], +- [ +- 'shield.settings' => ['shield_enable' => TRUE, 'credentials' => ['shield' => ['user' => 'drupal_shield_user', 'pass' => 'drupal_shield_pass']], 'print' => 'drupal_shield_print'], +- ], +- ], +- +- [ +- self::ENVIRONMENT_PROD, +- [ +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- 'DRUPAL_SHIELD_PRINT' => 'drupal_shield_print', +- ], +- [ +- 'shield.settings' => ['credentials' => ['shield' => ['user' => 'drupal_shield_user', 'pass' => 'drupal_shield_pass']], 'print' => 'drupal_shield_print'], +- ], +- [ +- 'shield.settings' => ['shield_enable' => FALSE], +- ], +- ], +- +- [ +- self::ENVIRONMENT_SUT, +- [ +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- 'DRUPAL_SHIELD_PRINT' => 'drupal_shield_print', +- ], +- [ +- 'shield.settings' => ['shield_enable' => TRUE, 'credentials' => ['shield' => ['user' => 'drupal_shield_user', 'pass' => 'drupal_shield_pass']], 'print' => 'drupal_shield_print'], +- ], +- ], +- +- [ +- self::ENVIRONMENT_DEV, +- [ +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- 'DRUPAL_SHIELD_PRINT' => 'drupal_shield_print', +- 'DRUPAL_SHIELD_DISABLED' => '', +- ], +- [ +- 'shield.settings' => ['shield_enable' => TRUE, 'credentials' => ['shield' => ['user' => 'drupal_shield_user', 'pass' => 'drupal_shield_pass']], 'print' => 'drupal_shield_print'], +- ], +- ], +- +- [ +- self::ENVIRONMENT_DEV, +- [ +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- 'DRUPAL_SHIELD_PRINT' => 'drupal_shield_print', +- 'DRUPAL_SHIELD_DISABLED' => 0, +- ], +- [ +- 'shield.settings' => ['shield_enable' => TRUE, 'credentials' => ['shield' => ['user' => 'drupal_shield_user', 'pass' => 'drupal_shield_pass']], 'print' => 'drupal_shield_print'], +- ], +- ], +- [ +- self::ENVIRONMENT_DEV, +- [ +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- 'DRUPAL_SHIELD_PRINT' => 'drupal_shield_print', +- 'DRUPAL_SHIELD_DISABLED' => 1, +- ], +- [ +- 'shield.settings' => ['shield_enable' => FALSE, 'credentials' => ['shield' => ['user' => 'drupal_shield_user', 'pass' => 'drupal_shield_pass']], 'print' => 'drupal_shield_print'], +- ], +- ], +- +- [ +- self::ENVIRONMENT_DEV, +- [ +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- 'DRUPAL_SHIELD_PRINT' => 'drupal_shield_print', +- 'DRUPAL_SHIELD_DISABLED' => '0', +- ], +- [ +- 'shield.settings' => ['shield_enable' => TRUE, 'credentials' => ['shield' => ['user' => 'drupal_shield_user', 'pass' => 'drupal_shield_pass']], 'print' => 'drupal_shield_print'], +- ], +- ], +- [ +- self::ENVIRONMENT_DEV, +- [ +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- 'DRUPAL_SHIELD_PRINT' => 'drupal_shield_print', +- 'DRUPAL_SHIELD_DISABLED' => '1', +- ], +- [ +- 'shield.settings' => ['shield_enable' => FALSE, 'credentials' => ['shield' => ['user' => 'drupal_shield_user', 'pass' => 'drupal_shield_pass']], 'print' => 'drupal_shield_print'], +- ], +- ], +- [ +- self::ENVIRONMENT_DEV, +- [ +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- 'DRUPAL_SHIELD_PRINT' => 'drupal_shield_print', +- 'DRUPAL_SHIELD_DISABLED' => 'false', +- ], +- [ +- 'shield.settings' => ['shield_enable' => FALSE, 'credentials' => ['shield' => ['user' => 'drupal_shield_user', 'pass' => 'drupal_shield_pass']], 'print' => 'drupal_shield_print'], +- ], +- ], +- [ +- self::ENVIRONMENT_DEV, +- [ +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- 'DRUPAL_SHIELD_PRINT' => 'drupal_shield_print', +- 'DRUPAL_SHIELD_DISABLED' => 'true', +- ], +- [ +- 'shield.settings' => ['shield_enable' => FALSE, 'credentials' => ['shield' => ['user' => 'drupal_shield_user', 'pass' => 'drupal_shield_pass']], 'print' => 'drupal_shield_print'], +- ], +- ], +- +- [ +- self::ENVIRONMENT_DEV, +- [ +- 'DRUPAL_SHIELD_DISABLED' => TRUE, +- ], +- [ +- 'shield.settings' => ['shield_enable' => FALSE], +- ], +- ], +- [ +- self::ENVIRONMENT_STAGE, +- [ +- 'DRUPAL_SHIELD_DISABLED' => TRUE, +- ], +- [ +- 'shield.settings' => ['shield_enable' => FALSE], +- ], +- ], +- [ +- self::ENVIRONMENT_PROD, +- [ +- 'DRUPAL_SHIELD_DISABLED' => TRUE, +- ], +- [ +- 'shield.settings' => ['shield_enable' => FALSE], +- ], +- ], +- ]; +- } +- +- /** + * Test Stage File Proxy config. + */ + #[DataProvider('dataProviderStageFileProxy')] diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_shield/web/sites/default/includes/modules/-settings.shield.php b/.vortex/installer/tests/Fixtures/install/modules_no_shield/web/sites/default/includes/modules/-settings.shield.php new file mode 100644 index 000000000..e69de29bb diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_stage_file_proxy/.env b/.vortex/installer/tests/Fixtures/install/modules_no_stage_file_proxy/.env new file mode 100644 index 000000000..073132bb6 --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/modules_no_stage_file_proxy/.env @@ -0,0 +1,13 @@ +@@ -61,12 +61,6 @@ + # Drupal maintenance theme name. + DRUPAL_MAINTENANCE_THEME=star_wars + +-# Stage file proxy origin. +-# +-# If using Shield, the HTTP authentication credentials will be automatically +-# added to the origin URL. +-DRUPAL_STAGE_FILE_PROXY_ORIGIN=https://www.star-wars.com +- + # Shield message. + DRUPAL_SHIELD_PRINT="Restricted access." + diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_stage_file_proxy/composer.json b/.vortex/installer/tests/Fixtures/install/modules_no_stage_file_proxy/composer.json new file mode 100644 index 000000000..a8e2bddb2 --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/modules_no_stage_file_proxy/composer.json @@ -0,0 +1,8 @@ +@@ -23,7 +23,6 @@ + "drupal/search_api_solr": "__VERSION__", + "drupal/seckit": "__VERSION__", + "drupal/shield": "__VERSION__", +- "drupal/stage_file_proxy": "__VERSION__", + "drush/drush": "__VERSION__", + "oomphinc/composer-installers-extender": "__VERSION__", + "webflo/drupal-finder": "__VERSION__" diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_stage_file_proxy/scripts/custom/provision-10-example.sh b/.vortex/installer/tests/Fixtures/install/modules_no_stage_file_proxy/scripts/custom/provision-10-example.sh new file mode 100644 index 000000000..2af9653be --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/modules_no_stage_file_proxy/scripts/custom/provision-10-example.sh @@ -0,0 +1,9 @@ +@@ -38,7 +38,7 @@ + drush php:eval "\Drupal::service('config.factory')->getEditable('system.site')->set('name', 'star wars')->save();" + + task "Installing contrib modules." +- drush pm:install admin_toolbar coffee config_split config_update media environment_indicator pathauto redirect robotstxt shield stage_file_proxy ++ drush pm:install admin_toolbar coffee config_split config_update media environment_indicator pathauto redirect robotstxt shield + + task "Installing Redis module." + drush pm:install redis || true diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_stage_file_proxy/tests/phpunit/Drupal/SwitchableSettingsTest.php b/.vortex/installer/tests/Fixtures/install/modules_no_stage_file_proxy/tests/phpunit/Drupal/SwitchableSettingsTest.php new file mode 100644 index 000000000..49225b159 --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/modules_no_stage_file_proxy/tests/phpunit/Drupal/SwitchableSettingsTest.php @@ -0,0 +1,134 @@ +@@ -533,133 +533,6 @@ + } + + /** +- * Test Stage File Proxy config. +- */ +- #[DataProvider('dataProviderStageFileProxy')] +- public function testStageFileProxy(string $env, array $vars, array $expected_present, array $expected_absent = []): void { +- $this->setEnvVars($vars + ['DRUPAL_ENVIRONMENT' => $env]); +- +- $this->requireSettingsFile(); +- +- $this->assertConfigContains($expected_present); +- $this->assertConfigNotContains($expected_absent); +- } +- +- /** +- * Data provider for testStageFileProxy(). +- */ +- public static function dataProviderStageFileProxy(): array { +- return [ +- [ +- self::ENVIRONMENT_LOCAL, +- [], +- [], +- [ +- 'stage_file_proxy.settings' => ['hotlink' => FALSE, 'origin' => 'https://example.com/'], +- ], +- ], +- [ +- self::ENVIRONMENT_LOCAL, +- [ +- 'DRUPAL_STAGE_FILE_PROXY_ORIGIN' => 'https://example.com/', +- ], +- [ +- 'stage_file_proxy.settings' => ['hotlink' => FALSE, 'origin' => 'https://example.com/'], +- ], +- [], +- ], +- [ +- self::ENVIRONMENT_LOCAL, +- [ +- 'DRUPAL_STAGE_FILE_PROXY_ORIGIN' => 'https://example.com/', +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- ], +- [ +- 'stage_file_proxy.settings' => ['hotlink' => FALSE, 'origin' => 'https://drupal_shield_user:drupal_shield_pass@example.com/'], +- ], +- [], +- ], +- [ +- self::ENVIRONMENT_LOCAL, +- [ +- 'DRUPAL_STAGE_FILE_PROXY_ORIGIN' => 'https://example.com/', +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- ], +- [ +- 'stage_file_proxy.settings' => ['hotlink' => FALSE, 'origin' => 'https://example.com/'], +- ], +- [], +- ], +- +- [ +- self::ENVIRONMENT_CI, +- [ +- 'DRUPAL_STAGE_FILE_PROXY_ORIGIN' => 'https://example.com/', +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- ], +- [ +- 'stage_file_proxy.settings' => ['hotlink' => FALSE, 'origin' => 'https://drupal_shield_user:drupal_shield_pass@example.com/'], +- ], +- [], +- ], +- +- [ +- self::ENVIRONMENT_DEV, +- [ +- 'DRUPAL_STAGE_FILE_PROXY_ORIGIN' => 'https://example.com/', +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- ], +- [ +- 'stage_file_proxy.settings' => ['hotlink' => FALSE, 'origin' => 'https://drupal_shield_user:drupal_shield_pass@example.com/'], +- ], +- [], +- ], +- +- [ +- self::ENVIRONMENT_STAGE, +- [ +- 'DRUPAL_STAGE_FILE_PROXY_ORIGIN' => 'https://example.com/', +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- ], +- [ +- 'stage_file_proxy.settings' => ['hotlink' => FALSE, 'origin' => 'https://drupal_shield_user:drupal_shield_pass@example.com/'], +- ], +- [], +- ], +- +- [ +- self::ENVIRONMENT_PROD, +- [ +- 'DRUPAL_STAGE_FILE_PROXY_ORIGIN' => 'https://example.com/', +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- ], +- [], +- [ +- 'stage_file_proxy.settings' => ['hotlink' => FALSE, 'origin' => 'https://drupal_shield_user:drupal_shield_pass@example.com/'], +- ], +- ], +- +- [ +- self::ENVIRONMENT_SUT, +- [ +- 'DRUPAL_STAGE_FILE_PROXY_ORIGIN' => 'https://example.com/', +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- ], +- [ +- 'stage_file_proxy.settings' => ['hotlink' => FALSE, 'origin' => 'https://drupal_shield_user:drupal_shield_pass@example.com/'], +- ], +- [], +- ], +- ]; +- } +- +- /** + * Test trusted host patterns settings. + */ + #[DataProvider('dataProviderTrustedHostPatterns')] diff --git a/.vortex/installer/tests/Fixtures/install/modules_no_stage_file_proxy/web/sites/default/includes/modules/-settings.stage_file_proxy.php b/.vortex/installer/tests/Fixtures/install/modules_no_stage_file_proxy/web/sites/default/includes/modules/-settings.stage_file_proxy.php new file mode 100644 index 000000000..e69de29bb diff --git a/.vortex/installer/tests/Fixtures/install/modules_none/.env b/.vortex/installer/tests/Fixtures/install/modules_none/.env new file mode 100644 index 000000000..e67a53d3d --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/modules_none/.env @@ -0,0 +1,16 @@ +@@ -61,15 +61,6 @@ + # Drupal maintenance theme name. + DRUPAL_MAINTENANCE_THEME=star_wars + +-# Stage file proxy origin. +-# +-# If using Shield, the HTTP authentication credentials will be automatically +-# added to the origin URL. +-DRUPAL_STAGE_FILE_PROXY_ORIGIN=https://www.star-wars.com +- +-# Shield message. +-DRUPAL_SHIELD_PRINT="Restricted access." +- + # Enable Redis integration. + # See settings.redis.php for details. + DRUPAL_REDIS_ENABLED=1 diff --git a/.vortex/installer/tests/Fixtures/install/modules_none/composer.json b/.vortex/installer/tests/Fixtures/install/modules_none/composer.json new file mode 100644 index 000000000..b1d0dbadd --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/modules_none/composer.json @@ -0,0 +1,24 @@ +@@ -7,23 +7,12 @@ + "php": "__VERSION__", + "composer/installers": "__VERSION__", + "cweagans/composer-patches": "__VERSION__", +- "drupal/admin_toolbar": "__VERSION__", + "drupal/clamav": "__VERSION__", +- "drupal/coffee": "__VERSION__", +- "drupal/config_split": "__VERSION__", +- "drupal/config_update": "__VERSION__", + "drupal/core-composer-scaffold": "__VERSION__", + "drupal/core-recommended": "__VERSION__", +- "drupal/environment_indicator": "__VERSION__", +- "drupal/pathauto": "__VERSION__", +- "drupal/redirect": "__VERSION__", + "drupal/redis": "__VERSION__", +- "drupal/robotstxt": "__VERSION__", + "drupal/search_api": "__VERSION__", + "drupal/search_api_solr": "__VERSION__", +- "drupal/seckit": "__VERSION__", +- "drupal/shield": "__VERSION__", +- "drupal/stage_file_proxy": "__VERSION__", + "drush/drush": "__VERSION__", + "oomphinc/composer-installers-extender": "__VERSION__", + "webflo/drupal-finder": "__VERSION__" diff --git a/.vortex/installer/tests/Fixtures/install/modules_none/docker-compose.yml b/.vortex/installer/tests/Fixtures/install/modules_none/docker-compose.yml new file mode 100644 index 000000000..193dbfcee --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/modules_none/docker-compose.yml @@ -0,0 +1,10 @@ +@@ -49,9 +49,6 @@ + DRUPAL_TEMPORARY_FILES: ${DRUPAL_TEMPORARY_FILES:-/tmp} + # Path to configuration files. + DRUPAL_CONFIG_PATH: ${DRUPAL_CONFIG_PATH:-../config/default} +- # Drupal Shield credentials. +- DRUPAL_SHIELD_USER: ${DRUPAL_SHIELD_USER:-} +- DRUPAL_SHIELD_PASS: ${DRUPAL_SHIELD_PASS:-} + # Redis integration flag. + DRUPAL_REDIS_ENABLED: ${DRUPAL_REDIS_ENABLED:-} + diff --git a/.vortex/installer/tests/Fixtures/install/modules_none/scripts/custom/provision-10-example.sh b/.vortex/installer/tests/Fixtures/install/modules_none/scripts/custom/provision-10-example.sh new file mode 100644 index 000000000..5ef95db91 --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/modules_none/scripts/custom/provision-10-example.sh @@ -0,0 +1,10 @@ +@@ -37,9 +37,6 @@ + task "Setting site name." + drush php:eval "\Drupal::service('config.factory')->getEditable('system.site')->set('name', 'star wars')->save();" + +- task "Installing contrib modules." +- drush pm:install admin_toolbar coffee config_split config_update media environment_indicator pathauto redirect robotstxt shield stage_file_proxy +- + task "Installing Redis module." + drush pm:install redis || true + diff --git a/.vortex/installer/tests/Fixtures/install/modules_none/tests/behat/features/-robotstxt.feature b/.vortex/installer/tests/Fixtures/install/modules_none/tests/behat/features/-robotstxt.feature new file mode 100644 index 000000000..e69de29bb diff --git a/.vortex/installer/tests/Fixtures/install/modules_none/tests/phpunit/Drupal/EnvironmentSettingsTest.php b/.vortex/installer/tests/Fixtures/install/modules_none/tests/phpunit/Drupal/EnvironmentSettingsTest.php new file mode 100644 index 000000000..dc3c5c3c7 --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/modules_none/tests/phpunit/Drupal/EnvironmentSettingsTest.php @@ -0,0 +1,85 @@ +@@ -72,13 +72,6 @@ + + $this->requireSettingsFile(); + +- $config['environment_indicator.indicator']['bg_color'] = '#006600'; +- $config['environment_indicator.indicator']['fg_color'] = '#ffffff'; +- $config['environment_indicator.indicator']['name'] = self::ENVIRONMENT_SUT; +- $config['environment_indicator.settings']['favicon'] = TRUE; +- $config['environment_indicator.settings']['toolbar_integration'] = [TRUE]; +- $config['robotstxt.settings']['content'] = "User-agent: *\nDisallow: /"; +- $config['shield.settings']['shield_enable'] = TRUE; + $config['system.performance']['cache']['page']['max_age'] = 900; + $this->assertConfig($config); + +@@ -143,13 +136,6 @@ + $this->assertEquals($databases, $this->databases); + + // Verify key config overrides. +- $config['environment_indicator.indicator']['bg_color'] = '#006600'; +- $config['environment_indicator.indicator']['fg_color'] = '#ffffff'; +- $config['environment_indicator.indicator']['name'] = self::ENVIRONMENT_SUT; +- $config['environment_indicator.settings']['favicon'] = TRUE; +- $config['environment_indicator.settings']['toolbar_integration'] = [TRUE]; +- $config['robotstxt.settings']['content'] = "User-agent: *\nDisallow: /"; +- $config['shield.settings']['shield_enable'] = TRUE; + $config['system.performance']['cache']['page']['max_age'] = 1800; + $this->assertConfig($config); + +@@ -186,18 +172,8 @@ + $this->requireSettingsFile(); + + $config['automated_cron.settings']['interval'] = 0; +- $config['config_split.config_split.local']['status'] = TRUE; +- $config['environment_indicator.indicator']['bg_color'] = '#006600'; +- $config['environment_indicator.indicator']['fg_color'] = '#ffffff'; +- $config['environment_indicator.indicator']['name'] = self::ENVIRONMENT_LOCAL; +- $config['environment_indicator.settings']['favicon'] = TRUE; +- $config['environment_indicator.settings']['toolbar_integration'] = [TRUE]; +- $config['robotstxt.settings']['content'] = "User-agent: *\nDisallow: /"; +- $config['shield.settings']['shield_enable'] = FALSE; + $config['system.logging']['error_level'] = 'all'; + $config['system.performance']['cache']['page']['max_age'] = 900; +- $config['seckit.settings']['seckit_xss']['csp']['checkbox'] = FALSE; +- $config['seckit.settings']['seckit_xss']['csp']['upgrade-req'] = FALSE; + $this->assertConfig($config); + + $settings['config_exclude_modules'] = []; +@@ -232,18 +208,8 @@ + $this->requireSettingsFile(); + + $config['automated_cron.settings']['interval'] = 0; +- $config['config_split.config_split.local']['status'] = TRUE; +- $config['environment_indicator.indicator']['bg_color'] = '#006600'; +- $config['environment_indicator.indicator']['fg_color'] = '#ffffff'; +- $config['environment_indicator.indicator']['name'] = self::ENVIRONMENT_LOCAL; +- $config['environment_indicator.settings']['favicon'] = TRUE; +- $config['environment_indicator.settings']['toolbar_integration'] = [TRUE]; +- $config['robotstxt.settings']['content'] = "User-agent: *\nDisallow: /"; +- $config['shield.settings']['shield_enable'] = FALSE; + $config['system.logging']['error_level'] = 'all'; + $config['system.performance']['cache']['page']['max_age'] = 900; +- $config['seckit.settings']['seckit_xss']['csp']['checkbox'] = FALSE; +- $config['seckit.settings']['seckit_xss']['csp']['upgrade-req'] = FALSE; + $this->assertConfig($config); + + $settings['config_exclude_modules'] = []; +@@ -280,18 +246,8 @@ + $this->requireSettingsFile(); + + $config['automated_cron.settings']['interval'] = 0; +- $config['config_split.config_split.ci']['status'] = TRUE; +- $config['environment_indicator.indicator']['bg_color'] = '#006600'; +- $config['environment_indicator.indicator']['fg_color'] = '#ffffff'; +- $config['environment_indicator.indicator']['name'] = self::ENVIRONMENT_CI; +- $config['environment_indicator.settings']['favicon'] = TRUE; +- $config['environment_indicator.settings']['toolbar_integration'] = [TRUE]; +- $config['robotstxt.settings']['content'] = "User-agent: *\nDisallow: /"; +- $config['shield.settings']['shield_enable'] = FALSE; + $config['system.logging']['error_level'] = 'all'; + $config['system.performance']['cache']['page']['max_age'] = 900; +- $config['seckit.settings']['seckit_xss']['csp']['checkbox'] = FALSE; +- $config['seckit.settings']['seckit_xss']['csp']['upgrade-req'] = FALSE; + $this->assertConfig($config); + + $settings['config_exclude_modules'] = []; diff --git a/.vortex/installer/tests/Fixtures/install/modules_none/tests/phpunit/Drupal/SwitchableSettingsTest.php b/.vortex/installer/tests/Fixtures/install/modules_none/tests/phpunit/Drupal/SwitchableSettingsTest.php new file mode 100644 index 000000000..1a1ce257c --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/modules_none/tests/phpunit/Drupal/SwitchableSettingsTest.php @@ -0,0 +1,525 @@ +@@ -76,158 +76,6 @@ + } + + /** +- * Test Config Split config. +- */ +- #[DataProvider('dataProviderConfigSplit')] +- public function testConfigSplit(string $env, array $expected_present, array $expected_absent): void { +- $this->setEnvVars([ +- 'DRUPAL_ENVIRONMENT' => $env, +- ]); +- +- $this->requireSettingsFile(); +- +- $this->assertConfigContains($expected_present); +- $this->assertConfigNotContains($expected_absent); +- } +- +- /** +- * Data provider for testConfigSplit(). +- */ +- public static function dataProviderConfigSplit(): array { +- return [ +- [ +- self::ENVIRONMENT_LOCAL, +- [ +- 'config_split.config_split.local' => ['status' => TRUE], +- ], +- [ +- 'config_split.config_split.stage' => NULL, +- 'config_split.config_split.dev' => NULL, +- 'config_split.config_split.ci' => NULL, +- ], +- ], +- [ +- self::ENVIRONMENT_CI, +- [ +- 'config_split.config_split.ci' => ['status' => TRUE], +- ], +- [ +- 'config_split.config_split.stage' => NULL, +- 'config_split.config_split.dev' => NULL, +- 'config_split.config_split.local' => NULL, +- ], +- ], +- [ +- self::ENVIRONMENT_DEV, +- [ +- 'config_split.config_split.dev' => ['status' => TRUE], +- ], +- [ +- 'config_split.config_split.stage' => NULL, +- 'config_split.config_split.ci' => NULL, +- 'config_split.config_split.local' => NULL, +- ], +- ], +- [ +- self::ENVIRONMENT_STAGE, +- [ +- 'config_split.config_split.stage' => ['status' => TRUE], +- ], +- [ +- 'config_split.config_split.dev' => NULL, +- 'config_split.config_split.ci' => NULL, +- 'config_split.config_split.local' => NULL, +- ], +- ], +- [ +- self::ENVIRONMENT_PROD, +- [], +- [ +- 'config_split.config_split.stage' => NULL, +- 'config_split.config_split.dev' => NULL, +- 'config_split.config_split.ci' => NULL, +- 'config_split.config_split.local' => NULL, +- ], +- ], +- [ +- self::ENVIRONMENT_SUT, +- [], +- [ +- 'config_split.config_split.stage' => NULL, +- 'config_split.config_split.dev' => NULL, +- 'config_split.config_split.ci' => NULL, +- 'config_split.config_split.local' => NULL, +- ], +- ], +- ]; +- } +- +- /** +- * Test Environment Indicator config. +- */ +- #[DataProvider('dataProviderEnvironmentIndicator')] +- public function testEnvironmentIndicator(string $env, array $expected_present, array $expected_absent = []): void { +- $this->setEnvVars([ +- 'DRUPAL_ENVIRONMENT' => $env, +- ]); +- +- $this->requireSettingsFile(); +- +- $this->assertConfigContains($expected_present); +- $this->assertConfigNotContains($expected_absent); +- } +- +- /** +- * Data provider for testEnvironmentIndicator(). +- */ +- public static function dataProviderEnvironmentIndicator(): array { +- return [ +- [ +- self::ENVIRONMENT_LOCAL, +- [ +- 'environment_indicator.indicator' => ['name' => self::ENVIRONMENT_LOCAL, 'bg_color' => '#006600', 'fg_color' => '#ffffff'], +- 'environment_indicator.settings' => ['toolbar_integration' => [TRUE], 'favicon' => TRUE], +- ], +- ], +- [ +- self::ENVIRONMENT_CI, +- [ +- 'environment_indicator.indicator' => ['name' => self::ENVIRONMENT_CI, 'bg_color' => '#006600', 'fg_color' => '#ffffff'], +- 'environment_indicator.settings' => ['toolbar_integration' => [TRUE], 'favicon' => TRUE], +- ], +- ], +- [ +- self::ENVIRONMENT_DEV, +- [ +- 'environment_indicator.indicator' => ['name' => self::ENVIRONMENT_DEV, 'bg_color' => '#4caf50', 'fg_color' => '#000000'], +- 'environment_indicator.settings' => ['toolbar_integration' => [TRUE], 'favicon' => TRUE], +- ], +- ], +- [ +- self::ENVIRONMENT_STAGE, +- [ +- 'environment_indicator.indicator' => ['name' => self::ENVIRONMENT_STAGE, 'bg_color' => '#fff176', 'fg_color' => '#000000'], +- 'environment_indicator.settings' => ['toolbar_integration' => [TRUE], 'favicon' => TRUE], +- ], +- ], +- [ +- self::ENVIRONMENT_PROD, +- [ +- 'environment_indicator.indicator' => ['name' => self::ENVIRONMENT_PROD, 'bg_color' => '#ef5350', 'fg_color' => '#000000'], +- 'environment_indicator.settings' => ['toolbar_integration' => [TRUE], 'favicon' => TRUE], +- ], +- ], +- [ +- self::ENVIRONMENT_SUT, +- [ +- 'environment_indicator.indicator' => ['name' => self::ENVIRONMENT_SUT, 'bg_color' => '#006600', 'fg_color' => '#ffffff'], +- 'environment_indicator.settings' => ['toolbar_integration' => [TRUE], 'favicon' => TRUE], +- ], +- ], +- ]; +- } +- +- /** + * Test Redis settings. + */ + public function testRedis(): void { +@@ -298,365 +146,6 @@ + unset($this->settings['bootstrap_container_definition']); + + $this->assertSettingsContains($settings); +- } +- +- /** +- * Test Shield config. +- */ +- #[DataProvider('dataProviderShield')] +- public function testShield(string $env, array $vars, array $expected_present, array $expected_absent = []): void { +- $this->setEnvVars($vars + ['DRUPAL_ENVIRONMENT' => $env]); +- +- $this->requireSettingsFile(); +- +- $this->assertConfigContains($expected_present); +- $this->assertConfigNotContains($expected_absent); +- } +- +- /** +- * Data provider for testShield(). +- */ +- public static function dataProviderShield(): array { +- return [ +- [ +- self::ENVIRONMENT_LOCAL, +- [], +- [ +- 'shield.settings' => ['shield_enable' => FALSE], +- ], +- [ +- 'shield.settings' => ['credentials' => ['shield' => ['user' => 'drupal_shield_user', 'pass' => 'drupal_shield_pass']], 'print' => 'drupal_shield_print'], +- ], +- ], +- [ +- self::ENVIRONMENT_LOCAL, +- [ +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- ], +- [ +- 'shield.settings' => ['shield_enable' => FALSE], +- ], +- [ +- 'shield.settings' => ['credentials' => ['shield' => ['user' => 'drupal_shield_user', 'pass' => 'drupal_shield_pass']], 'print' => 'drupal_shield_print'], +- ], +- ], +- [ +- self::ENVIRONMENT_LOCAL, +- [ +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- 'DRUPAL_SHIELD_PRINT' => 'drupal_shield_print', +- ], +- [ +- 'shield.settings' => ['shield_enable' => FALSE, 'credentials' => ['shield' => ['user' => 'drupal_shield_user', 'pass' => 'drupal_shield_pass']], 'print' => 'drupal_shield_print'], +- ], +- ], +- +- [ +- self::ENVIRONMENT_CI, +- [ +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- 'DRUPAL_SHIELD_PRINT' => 'drupal_shield_print', +- ], +- [ +- 'shield.settings' => ['shield_enable' => FALSE, 'credentials' => ['shield' => ['user' => 'drupal_shield_user', 'pass' => 'drupal_shield_pass']], 'print' => 'drupal_shield_print'], +- ], +- ], +- +- [ +- self::ENVIRONMENT_DEV, +- [ +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- 'DRUPAL_SHIELD_PRINT' => 'drupal_shield_print', +- ], +- [ +- 'shield.settings' => ['shield_enable' => TRUE, 'credentials' => ['shield' => ['user' => 'drupal_shield_user', 'pass' => 'drupal_shield_pass']], 'print' => 'drupal_shield_print'], +- ], +- ], +- +- [ +- self::ENVIRONMENT_STAGE, +- [ +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- 'DRUPAL_SHIELD_PRINT' => 'drupal_shield_print', +- ], +- [ +- 'shield.settings' => ['shield_enable' => TRUE, 'credentials' => ['shield' => ['user' => 'drupal_shield_user', 'pass' => 'drupal_shield_pass']], 'print' => 'drupal_shield_print'], +- ], +- ], +- +- [ +- self::ENVIRONMENT_PROD, +- [ +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- 'DRUPAL_SHIELD_PRINT' => 'drupal_shield_print', +- ], +- [ +- 'shield.settings' => ['credentials' => ['shield' => ['user' => 'drupal_shield_user', 'pass' => 'drupal_shield_pass']], 'print' => 'drupal_shield_print'], +- ], +- [ +- 'shield.settings' => ['shield_enable' => FALSE], +- ], +- ], +- +- [ +- self::ENVIRONMENT_SUT, +- [ +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- 'DRUPAL_SHIELD_PRINT' => 'drupal_shield_print', +- ], +- [ +- 'shield.settings' => ['shield_enable' => TRUE, 'credentials' => ['shield' => ['user' => 'drupal_shield_user', 'pass' => 'drupal_shield_pass']], 'print' => 'drupal_shield_print'], +- ], +- ], +- +- [ +- self::ENVIRONMENT_DEV, +- [ +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- 'DRUPAL_SHIELD_PRINT' => 'drupal_shield_print', +- 'DRUPAL_SHIELD_DISABLED' => '', +- ], +- [ +- 'shield.settings' => ['shield_enable' => TRUE, 'credentials' => ['shield' => ['user' => 'drupal_shield_user', 'pass' => 'drupal_shield_pass']], 'print' => 'drupal_shield_print'], +- ], +- ], +- +- [ +- self::ENVIRONMENT_DEV, +- [ +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- 'DRUPAL_SHIELD_PRINT' => 'drupal_shield_print', +- 'DRUPAL_SHIELD_DISABLED' => 0, +- ], +- [ +- 'shield.settings' => ['shield_enable' => TRUE, 'credentials' => ['shield' => ['user' => 'drupal_shield_user', 'pass' => 'drupal_shield_pass']], 'print' => 'drupal_shield_print'], +- ], +- ], +- [ +- self::ENVIRONMENT_DEV, +- [ +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- 'DRUPAL_SHIELD_PRINT' => 'drupal_shield_print', +- 'DRUPAL_SHIELD_DISABLED' => 1, +- ], +- [ +- 'shield.settings' => ['shield_enable' => FALSE, 'credentials' => ['shield' => ['user' => 'drupal_shield_user', 'pass' => 'drupal_shield_pass']], 'print' => 'drupal_shield_print'], +- ], +- ], +- +- [ +- self::ENVIRONMENT_DEV, +- [ +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- 'DRUPAL_SHIELD_PRINT' => 'drupal_shield_print', +- 'DRUPAL_SHIELD_DISABLED' => '0', +- ], +- [ +- 'shield.settings' => ['shield_enable' => TRUE, 'credentials' => ['shield' => ['user' => 'drupal_shield_user', 'pass' => 'drupal_shield_pass']], 'print' => 'drupal_shield_print'], +- ], +- ], +- [ +- self::ENVIRONMENT_DEV, +- [ +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- 'DRUPAL_SHIELD_PRINT' => 'drupal_shield_print', +- 'DRUPAL_SHIELD_DISABLED' => '1', +- ], +- [ +- 'shield.settings' => ['shield_enable' => FALSE, 'credentials' => ['shield' => ['user' => 'drupal_shield_user', 'pass' => 'drupal_shield_pass']], 'print' => 'drupal_shield_print'], +- ], +- ], +- [ +- self::ENVIRONMENT_DEV, +- [ +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- 'DRUPAL_SHIELD_PRINT' => 'drupal_shield_print', +- 'DRUPAL_SHIELD_DISABLED' => 'false', +- ], +- [ +- 'shield.settings' => ['shield_enable' => FALSE, 'credentials' => ['shield' => ['user' => 'drupal_shield_user', 'pass' => 'drupal_shield_pass']], 'print' => 'drupal_shield_print'], +- ], +- ], +- [ +- self::ENVIRONMENT_DEV, +- [ +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- 'DRUPAL_SHIELD_PRINT' => 'drupal_shield_print', +- 'DRUPAL_SHIELD_DISABLED' => 'true', +- ], +- [ +- 'shield.settings' => ['shield_enable' => FALSE, 'credentials' => ['shield' => ['user' => 'drupal_shield_user', 'pass' => 'drupal_shield_pass']], 'print' => 'drupal_shield_print'], +- ], +- ], +- +- [ +- self::ENVIRONMENT_DEV, +- [ +- 'DRUPAL_SHIELD_DISABLED' => TRUE, +- ], +- [ +- 'shield.settings' => ['shield_enable' => FALSE], +- ], +- ], +- [ +- self::ENVIRONMENT_STAGE, +- [ +- 'DRUPAL_SHIELD_DISABLED' => TRUE, +- ], +- [ +- 'shield.settings' => ['shield_enable' => FALSE], +- ], +- ], +- [ +- self::ENVIRONMENT_PROD, +- [ +- 'DRUPAL_SHIELD_DISABLED' => TRUE, +- ], +- [ +- 'shield.settings' => ['shield_enable' => FALSE], +- ], +- ], +- ]; +- } +- +- /** +- * Test Stage File Proxy config. +- */ +- #[DataProvider('dataProviderStageFileProxy')] +- public function testStageFileProxy(string $env, array $vars, array $expected_present, array $expected_absent = []): void { +- $this->setEnvVars($vars + ['DRUPAL_ENVIRONMENT' => $env]); +- +- $this->requireSettingsFile(); +- +- $this->assertConfigContains($expected_present); +- $this->assertConfigNotContains($expected_absent); +- } +- +- /** +- * Data provider for testStageFileProxy(). +- */ +- public static function dataProviderStageFileProxy(): array { +- return [ +- [ +- self::ENVIRONMENT_LOCAL, +- [], +- [], +- [ +- 'stage_file_proxy.settings' => ['hotlink' => FALSE, 'origin' => 'https://example.com/'], +- ], +- ], +- [ +- self::ENVIRONMENT_LOCAL, +- [ +- 'DRUPAL_STAGE_FILE_PROXY_ORIGIN' => 'https://example.com/', +- ], +- [ +- 'stage_file_proxy.settings' => ['hotlink' => FALSE, 'origin' => 'https://example.com/'], +- ], +- [], +- ], +- [ +- self::ENVIRONMENT_LOCAL, +- [ +- 'DRUPAL_STAGE_FILE_PROXY_ORIGIN' => 'https://example.com/', +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- ], +- [ +- 'stage_file_proxy.settings' => ['hotlink' => FALSE, 'origin' => 'https://drupal_shield_user:drupal_shield_pass@example.com/'], +- ], +- [], +- ], +- [ +- self::ENVIRONMENT_LOCAL, +- [ +- 'DRUPAL_STAGE_FILE_PROXY_ORIGIN' => 'https://example.com/', +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- ], +- [ +- 'stage_file_proxy.settings' => ['hotlink' => FALSE, 'origin' => 'https://example.com/'], +- ], +- [], +- ], +- +- [ +- self::ENVIRONMENT_CI, +- [ +- 'DRUPAL_STAGE_FILE_PROXY_ORIGIN' => 'https://example.com/', +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- ], +- [ +- 'stage_file_proxy.settings' => ['hotlink' => FALSE, 'origin' => 'https://drupal_shield_user:drupal_shield_pass@example.com/'], +- ], +- [], +- ], +- +- [ +- self::ENVIRONMENT_DEV, +- [ +- 'DRUPAL_STAGE_FILE_PROXY_ORIGIN' => 'https://example.com/', +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- ], +- [ +- 'stage_file_proxy.settings' => ['hotlink' => FALSE, 'origin' => 'https://drupal_shield_user:drupal_shield_pass@example.com/'], +- ], +- [], +- ], +- +- [ +- self::ENVIRONMENT_STAGE, +- [ +- 'DRUPAL_STAGE_FILE_PROXY_ORIGIN' => 'https://example.com/', +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- ], +- [ +- 'stage_file_proxy.settings' => ['hotlink' => FALSE, 'origin' => 'https://drupal_shield_user:drupal_shield_pass@example.com/'], +- ], +- [], +- ], +- +- [ +- self::ENVIRONMENT_PROD, +- [ +- 'DRUPAL_STAGE_FILE_PROXY_ORIGIN' => 'https://example.com/', +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- ], +- [], +- [ +- 'stage_file_proxy.settings' => ['hotlink' => FALSE, 'origin' => 'https://drupal_shield_user:drupal_shield_pass@example.com/'], +- ], +- ], +- +- [ +- self::ENVIRONMENT_SUT, +- [ +- 'DRUPAL_STAGE_FILE_PROXY_ORIGIN' => 'https://example.com/', +- 'DRUPAL_SHIELD_USER' => 'drupal_shield_user', +- 'DRUPAL_SHIELD_PASS' => 'drupal_shield_pass', +- ], +- [ +- 'stage_file_proxy.settings' => ['hotlink' => FALSE, 'origin' => 'https://drupal_shield_user:drupal_shield_pass@example.com/'], +- ], +- [], +- ], +- ]; + } + + /** diff --git a/.vortex/installer/tests/Fixtures/install/modules_none/web/sites/default/includes/modules/-settings.config_split.php b/.vortex/installer/tests/Fixtures/install/modules_none/web/sites/default/includes/modules/-settings.config_split.php new file mode 100644 index 000000000..e69de29bb diff --git a/.vortex/installer/tests/Fixtures/install/modules_none/web/sites/default/includes/modules/-settings.environment_indicator.php b/.vortex/installer/tests/Fixtures/install/modules_none/web/sites/default/includes/modules/-settings.environment_indicator.php new file mode 100644 index 000000000..e69de29bb diff --git a/.vortex/installer/tests/Fixtures/install/modules_none/web/sites/default/includes/modules/-settings.robotstxt.php b/.vortex/installer/tests/Fixtures/install/modules_none/web/sites/default/includes/modules/-settings.robotstxt.php new file mode 100644 index 000000000..e69de29bb diff --git a/.vortex/installer/tests/Fixtures/install/modules_none/web/sites/default/includes/modules/-settings.seckit.php b/.vortex/installer/tests/Fixtures/install/modules_none/web/sites/default/includes/modules/-settings.seckit.php new file mode 100644 index 000000000..e69de29bb diff --git a/.vortex/installer/tests/Fixtures/install/modules_none/web/sites/default/includes/modules/-settings.shield.php b/.vortex/installer/tests/Fixtures/install/modules_none/web/sites/default/includes/modules/-settings.shield.php new file mode 100644 index 000000000..e69de29bb diff --git a/.vortex/installer/tests/Fixtures/install/modules_none/web/sites/default/includes/modules/-settings.stage_file_proxy.php b/.vortex/installer/tests/Fixtures/install/modules_none/web/sites/default/includes/modules/-settings.stage_file_proxy.php new file mode 100644 index 000000000..e69de29bb diff --git a/.vortex/installer/tests/Fixtures/install/names/scripts/custom/provision-10-example.sh b/.vortex/installer/tests/Fixtures/install/names/scripts/custom/provision-10-example.sh index bf1234351..90c4b5270 100644 --- a/.vortex/installer/tests/Fixtures/install/names/scripts/custom/provision-10-example.sh +++ b/.vortex/installer/tests/Fixtures/install/names/scripts/custom/provision-10-example.sh @@ -1,13 +1,13 @@ -@@ -36,7 +36,7 @@ +@@ -35,7 +35,7 @@ + note "Running example operations in non-production environment." - # Set site name. task "Setting site name." - drush php:eval "\Drupal::service('config.factory')->getEditable('system.site')->set('name', 'star wars')->save();" + drush php:eval "\Drupal::service('config.factory')->getEditable('system.site')->set('name', 'New hope')->save();" - # Enable contrib modules. task "Installing contrib modules." -@@ -57,9 +57,9 @@ + drush pm:install admin_toolbar coffee config_split config_update media environment_indicator pathauto redirect robotstxt shield stage_file_proxy +@@ -55,9 +55,9 @@ # Note that deployment hooks for already enabled modules have run in the # parent "provision.sh" script. task "Installing custom site modules." diff --git a/.vortex/installer/tests/Fixtures/install/non_interactive_config_file/scripts/custom/provision-10-example.sh b/.vortex/installer/tests/Fixtures/install/non_interactive_config_file/scripts/custom/provision-10-example.sh index b33592c40..3366a1b5a 100644 --- a/.vortex/installer/tests/Fixtures/install/non_interactive_config_file/scripts/custom/provision-10-example.sh +++ b/.vortex/installer/tests/Fixtures/install/non_interactive_config_file/scripts/custom/provision-10-example.sh @@ -1,4 +1,4 @@ -@@ -42,9 +42,6 @@ +@@ -40,9 +40,6 @@ task "Installing contrib modules." drush pm:install admin_toolbar coffee config_split config_update media environment_indicator pathauto redirect robotstxt shield stage_file_proxy diff --git a/.vortex/installer/tests/Fixtures/install/non_interactive_config_string/scripts/custom/provision-10-example.sh b/.vortex/installer/tests/Fixtures/install/non_interactive_config_string/scripts/custom/provision-10-example.sh index 84cb13a1f..9cb0ae6e4 100644 --- a/.vortex/installer/tests/Fixtures/install/non_interactive_config_string/scripts/custom/provision-10-example.sh +++ b/.vortex/installer/tests/Fixtures/install/non_interactive_config_string/scripts/custom/provision-10-example.sh @@ -1,4 +1,4 @@ -@@ -45,10 +45,6 @@ +@@ -43,10 +43,6 @@ task "Installing Redis module." drush pm:install redis || true diff --git a/.vortex/installer/tests/Fixtures/install/services_no_clamav/scripts/custom/provision-10-example.sh b/.vortex/installer/tests/Fixtures/install/services_no_clamav/scripts/custom/provision-10-example.sh index 84cb13a1f..9cb0ae6e4 100644 --- a/.vortex/installer/tests/Fixtures/install/services_no_clamav/scripts/custom/provision-10-example.sh +++ b/.vortex/installer/tests/Fixtures/install/services_no_clamav/scripts/custom/provision-10-example.sh @@ -1,4 +1,4 @@ -@@ -45,10 +45,6 @@ +@@ -43,10 +43,6 @@ task "Installing Redis module." drush pm:install redis || true diff --git a/.vortex/installer/tests/Fixtures/install/services_no_redis/scripts/custom/provision-10-example.sh b/.vortex/installer/tests/Fixtures/install/services_no_redis/scripts/custom/provision-10-example.sh index b33592c40..3366a1b5a 100644 --- a/.vortex/installer/tests/Fixtures/install/services_no_redis/scripts/custom/provision-10-example.sh +++ b/.vortex/installer/tests/Fixtures/install/services_no_redis/scripts/custom/provision-10-example.sh @@ -1,4 +1,4 @@ -@@ -42,9 +42,6 @@ +@@ -40,9 +40,6 @@ task "Installing contrib modules." drush pm:install admin_toolbar coffee config_split config_update media environment_indicator pathauto redirect robotstxt shield stage_file_proxy diff --git a/.vortex/installer/tests/Fixtures/install/services_no_solr/scripts/custom/provision-10-example.sh b/.vortex/installer/tests/Fixtures/install/services_no_solr/scripts/custom/provision-10-example.sh index 568d0cca0..c48cf5bd8 100644 --- a/.vortex/installer/tests/Fixtures/install/services_no_solr/scripts/custom/provision-10-example.sh +++ b/.vortex/installer/tests/Fixtures/install/services_no_solr/scripts/custom/provision-10-example.sh @@ -1,4 +1,4 @@ -@@ -49,9 +49,6 @@ +@@ -47,9 +47,6 @@ drush pm:install clamav drush config-set clamav.settings mode_daemon_tcpip.hostname clamav @@ -8,7 +8,7 @@ # Enable custom site module and run its deployment hooks. # # Note that deployment hooks for already enabled modules have run in the -@@ -58,8 +55,6 @@ +@@ -56,8 +53,6 @@ # parent "provision.sh" script. task "Installing custom site modules." drush pm:install sw_base diff --git a/.vortex/installer/tests/Fixtures/install/services_none/scripts/custom/provision-10-example.sh b/.vortex/installer/tests/Fixtures/install/services_none/scripts/custom/provision-10-example.sh index 6c6cb1cf5..81783b585 100644 --- a/.vortex/installer/tests/Fixtures/install/services_none/scripts/custom/provision-10-example.sh +++ b/.vortex/installer/tests/Fixtures/install/services_none/scripts/custom/provision-10-example.sh @@ -1,4 +1,4 @@ -@@ -42,16 +42,6 @@ +@@ -40,16 +40,6 @@ task "Installing contrib modules." drush pm:install admin_toolbar coffee config_split config_update media environment_indicator pathauto redirect robotstxt shield stage_file_proxy @@ -15,7 +15,7 @@ # Enable custom site module and run its deployment hooks. # # Note that deployment hooks for already enabled modules have run in the -@@ -58,8 +48,6 @@ +@@ -56,8 +46,6 @@ # parent "provision.sh" script. task "Installing custom site modules." drush pm:install sw_base diff --git a/.vortex/installer/tests/Functional/Handlers/ModulesInstallTest.php b/.vortex/installer/tests/Functional/Handlers/ModulesInstallTest.php new file mode 100644 index 000000000..ac5e8bb39 --- /dev/null +++ b/.vortex/installer/tests/Functional/Handlers/ModulesInstallTest.php @@ -0,0 +1,148 @@ + [ + static::cw(function (): void { + $selected_modules = static::getModulesExcept('admin_toolbar'); + Env::put(PromptManager::makeEnvName(Modules::id()), Converter::toList($selected_modules)); + }), + static::cw(fn(FunctionalTestCase $test) => $test->assertSutNotContains('admin_toolbar')), + ], + + 'modules, no coffee' => [ + static::cw(function (): void { + $selected_modules = static::getModulesExcept('coffee'); + Env::put(PromptManager::makeEnvName(Modules::id()), Converter::toList($selected_modules)); + }), + static::cw(fn(FunctionalTestCase $test) => $test->assertSutNotContains('coffee')), + ], + + 'modules, no config_split' => [ + static::cw(function (): void { + $selected_modules = static::getModulesExcept('config_split'); + Env::put(PromptManager::makeEnvName(Modules::id()), Converter::toList($selected_modules)); + }), + static::cw(fn(FunctionalTestCase $test) => $test->assertSutNotContains('config_split')), + ], + + 'modules, no config_update' => [ + static::cw(function (): void { + $selected_modules = static::getModulesExcept('config_update'); + Env::put(PromptManager::makeEnvName(Modules::id()), Converter::toList($selected_modules)); + }), + static::cw(fn(FunctionalTestCase $test) => $test->assertSutNotContains('config_update')), + ], + + 'modules, no environment_indicator' => [ + static::cw(function (): void { + $selected_modules = static::getModulesExcept('environment_indicator'); + Env::put(PromptManager::makeEnvName(Modules::id()), Converter::toList($selected_modules)); + }), + static::cw(fn(FunctionalTestCase $test) => $test->assertSutNotContains('environment_indicator')), + ], + + 'modules, no pathauto' => [ + static::cw(function (): void { + $selected_modules = static::getModulesExcept('pathauto'); + Env::put(PromptManager::makeEnvName(Modules::id()), Converter::toList($selected_modules)); + }), + static::cw(fn(FunctionalTestCase $test) => $test->assertSutNotContains('pathauto')), + ], + + 'modules, no redirect' => [ + static::cw(function (): void { + $selected_modules = static::getModulesExcept('redirect'); + Env::put(PromptManager::makeEnvName(Modules::id()), Converter::toList($selected_modules)); + }), + static::cw(fn(FunctionalTestCase $test) => $test->assertSutNotContains('drupal/redirect')), + ], + + 'modules, no robotstxt' => [ + static::cw(function (): void { + $selected_modules = static::getModulesExcept('robotstxt'); + Env::put(PromptManager::makeEnvName(Modules::id()), Converter::toList($selected_modules)); + }), + static::cw(fn(FunctionalTestCase $test) => $test->assertSutNotContains('robotstxt')), + ], + + 'modules, no seckit' => [ + static::cw(function (): void { + $selected_modules = static::getModulesExcept('seckit'); + Env::put(PromptManager::makeEnvName(Modules::id()), Converter::toList($selected_modules)); + }), + static::cw(fn(FunctionalTestCase $test) => $test->assertSutNotContains('seckit')), + ], + + 'modules, no shield' => [ + static::cw(function (): void { + $selected_modules = static::getModulesExcept('shield'); + Env::put(PromptManager::makeEnvName(Modules::id()), Converter::toList($selected_modules)); + }), + static::cw(fn(FunctionalTestCase $test) => $test->assertSutNotContains('shield')), + ], + + 'modules, no stage_file_proxy' => [ + static::cw(function (): void { + $selected_modules = static::getModulesExcept('stage_file_proxy'); + Env::put(PromptManager::makeEnvName(Modules::id()), Converter::toList($selected_modules)); + }), + static::cw(fn(FunctionalTestCase $test) => $test->assertSutNotContains('stage_file_proxy')), + ], + + 'modules, no seckit, shield, stage_file_proxy' => [ + static::cw(function (): void { + $selected_modules = static::getModulesExcept(['seckit', 'shield', 'stage_file_proxy']); + Env::put(PromptManager::makeEnvName(Modules::id()), Converter::toList($selected_modules)); + }), + static::cw(fn(FunctionalTestCase $test) => $test->assertSutNotContains([ + 'seckit', + 'shield', + 'stage_file_proxy', + ])), + ], + + 'modules, none' => [ + static::cw(fn() => Env::put(PromptManager::makeEnvName(Modules::id()), ',')), + static::cw(function (FunctionalTestCase $test): void { + foreach (array_keys(Modules::getAvailableModules()) as $module) { + // Cannot assert by the module name alone, as some module names + // are generic words that may appear elsewhere. + $test->assertSutNotContains('drupal/' . $module); + } + }), + ], + + ]; + } + + /** + * Get modules list with specified modules removed. + * + * @param array|string $modules_to_remove + * Module name(s) to remove from the full list. + * + * @return array + * Array of module names with specified modules removed. + */ + protected static function getModulesExcept(array|string $modules_to_remove): array { + $all_modules = array_keys(Modules::getAvailableModules()); + $remove = is_array($modules_to_remove) ? $modules_to_remove : [$modules_to_remove]; + return array_values(array_diff($all_modules, $remove)); + } + +} diff --git a/.vortex/installer/tests/Unit/Handlers/AbstractPromptManagerTestCase.php b/.vortex/installer/tests/Unit/Handlers/AbstractPromptManagerTestCase.php index c46772538..393819ae8 100644 --- a/.vortex/installer/tests/Unit/Handlers/AbstractPromptManagerTestCase.php +++ b/.vortex/installer/tests/Unit/Handlers/AbstractPromptManagerTestCase.php @@ -19,6 +19,7 @@ use DrevOps\VortexInstaller\Prompts\Handlers\HostingProjectName; use DrevOps\VortexInstaller\Prompts\Handlers\MachineName; use DrevOps\VortexInstaller\Prompts\Handlers\ModulePrefix; +use DrevOps\VortexInstaller\Prompts\Handlers\Modules; use DrevOps\VortexInstaller\Prompts\Handlers\Name; use DrevOps\VortexInstaller\Prompts\Handlers\NotificationChannels; use DrevOps\VortexInstaller\Prompts\Handlers\Org; @@ -125,6 +126,7 @@ protected static function getExpectedDefaults(): array { Domain::id() => 'myproject.com', Starter::id() => Starter::LOAD_DATABASE_DEMO, Profile::id() => Profile::STANDARD, + Modules::id() => array_keys(Modules::getAvailableModules()), ModulePrefix::id() => 'mypr', Theme::id() => 'myproject', CodeProvider::id() => CodeProvider::GITHUB, @@ -194,6 +196,7 @@ public static function defaultTuiAnswers(): array { Domain::id() => static::TUI_DEFAULT, Starter::id() => static::TUI_DEFAULT, Profile::id() => static::TUI_DEFAULT, + Modules::id() => static::TUI_DEFAULT, ModulePrefix::id() => static::TUI_DEFAULT, Theme::id() => static::TUI_DEFAULT, ThemeCustom::id() => static::TUI_DEFAULT, diff --git a/.vortex/installer/tests/Unit/Handlers/ModulesPromptManagerTest.php b/.vortex/installer/tests/Unit/Handlers/ModulesPromptManagerTest.php new file mode 100644 index 000000000..20ad0a324 --- /dev/null +++ b/.vortex/installer/tests/Unit/Handlers/ModulesPromptManagerTest.php @@ -0,0 +1,134 @@ + [ + [Modules::id() => Key::ENTER], + [Modules::id() => array_keys(Modules::getAvailableModules())] + $expected_defaults, + ], + + 'modules - discovery - some modules' => [ + [], + [Modules::id() => ['config_split', 'pathauto', 'shield']] + $expected_installed, + function (AbstractPromptManagerTestCase $test, Config $config): void { + $test->stubVortexProject($config); + $test->stubComposerJsonDependencies([ + 'drupal/config_split' => '^2.0.2', + 'drupal/pathauto' => '^1.14', + 'drupal/shield' => '^1.8', + ]); + }, + ], + + 'modules - discovery - all modules' => [ + [], + [Modules::id() => array_keys(Modules::getAvailableModules())] + $expected_installed, + function (AbstractPromptManagerTestCase $test, Config $config): void { + $test->stubVortexProject($config); + $test->stubComposerJsonDependencies([ + 'drupal/admin_toolbar' => '^3.6.2', + 'drupal/coffee' => '^2.0.1', + 'drupal/config_split' => '^2.0.2', + 'drupal/config_update' => '^2@alpha', + 'drupal/environment_indicator' => '^4.0.25', + 'drupal/pathauto' => '^1.14', + 'drupal/redirect' => '^1.12', + 'drupal/robotstxt' => '^1.6', + 'drupal/seckit' => '^2.0.3', + 'drupal/shield' => '^1.8', + 'drupal/stage_file_proxy' => '^3.1.6', + ]); + }, + ], + + 'modules - discovery - none' => [ + [], + [Modules::id() => []] + $expected_installed, + function (AbstractPromptManagerTestCase $test, Config $config): void { + $test->stubVortexProject($config); + $test->stubComposerJsonDependencies([ + 'drupal/core-recommended' => '~11.2.5', + ]); + }, + ], + + 'modules - discovery - filters out core packages' => [ + [], + [Modules::id() => ['admin_toolbar', 'pathauto']] + $expected_installed, + function (AbstractPromptManagerTestCase $test, Config $config): void { + $test->stubVortexProject($config); + $test->stubComposerJsonDependencies([ + 'drupal/core-recommended' => '~11.2.5', + 'drupal/core-composer-scaffold' => '~11.2.5', + 'drupal/core-dev' => '~11.2.5', + 'drupal/admin_toolbar' => '^3.6.2', + 'drupal/pathauto' => '^1.14', + ]); + }, + ], + + 'modules - discovery - filters out service modules' => [ + [], + [Modules::id() => ['admin_toolbar', 'pathauto']] + $expected_installed, + function (AbstractPromptManagerTestCase $test, Config $config): void { + $test->stubVortexProject($config); + $test->stubComposerJsonDependencies([ + 'drupal/admin_toolbar' => '^3.6.2', + 'drupal/clamav' => '^2.1', + 'drupal/pathauto' => '^1.14', + 'drupal/redis' => '^1.10', + 'drupal/search_api' => '^1.40', + 'drupal/search_api_solr' => '^4.3.10', + ]); + }, + ], + + 'modules - discovery - invalid composer.json' => [ + [], + $expected_installed, + function (AbstractPromptManagerTestCase $test, Config $config): void { + $test->stubVortexProject($config); + // Invalid JSON causes discovery to fail and fall back to defaults. + File::dump(static::$sut . '/composer.json', 'invalid json content'); + }, + ], + + 'modules - discovery - non-Vortex project' => [ + [], + $expected_defaults, + function (AbstractPromptManagerTestCase $test, Config $config): void { + $test->stubComposerJsonDependencies([ + 'drupal/admin_toolbar' => '^3.6.2', + 'drupal/pathauto' => '^1.14', + ]); + }, + ], + + 'modules - discovery - non-Vortex project, invalid composer.json' => [ + [], + $expected_defaults, + function (AbstractPromptManagerTestCase $test, Config $config): void { + // Invalid JSON causes discovery to fail and fall back to defaults. + File::dump(static::$sut . '/composer.json', 'invalid json content'); + }, + ], + ]; + } + +} diff --git a/docker-compose.yml b/docker-compose.yml index 8ef005c3a..b2be3d7f4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -57,9 +57,11 @@ x-environment: &default-environment DRUPAL_TEMPORARY_FILES: ${DRUPAL_TEMPORARY_FILES:-/tmp} # Path to configuration files. DRUPAL_CONFIG_PATH: ${DRUPAL_CONFIG_PATH:-../config/default} + #;< MODULE_SHIELD # Drupal Shield credentials. DRUPAL_SHIELD_USER: ${DRUPAL_SHIELD_USER:-} DRUPAL_SHIELD_PASS: ${DRUPAL_SHIELD_PASS:-} + #;> MODULE_SHIELD #;< SERVICE_REDIS # Redis integration flag. DRUPAL_REDIS_ENABLED: ${DRUPAL_REDIS_ENABLED:-} diff --git a/scripts/custom/provision-10-example.sh b/scripts/custom/provision-10-example.sh index 4c021fd9e..b45adf3c7 100755 --- a/scripts/custom/provision-10-example.sh +++ b/scripts/custom/provision-10-example.sh @@ -34,13 +34,13 @@ note "Environment: ${environment}" if echo "${environment}" | grep -q -e dev -e stage -e ci -e local; then note "Running example operations in non-production environment." - # Set site name. task "Setting site name." drush php:eval "\Drupal::service('config.factory')->getEditable('system.site')->set('name', 'YOURSITE')->save();" - # Enable contrib modules. + #;< MODULES task "Installing contrib modules." drush pm:install admin_toolbar coffee config_split config_update media environment_indicator pathauto redirect robotstxt shield stage_file_proxy + #;> MODULES #;< SERVICE_REDIS task "Installing Redis module." diff --git a/tests/phpunit/Drupal/SwitchableSettingsTest.php b/tests/phpunit/Drupal/SwitchableSettingsTest.php index 9311b732e..1c354c4a5 100644 --- a/tests/phpunit/Drupal/SwitchableSettingsTest.php +++ b/tests/phpunit/Drupal/SwitchableSettingsTest.php @@ -78,6 +78,7 @@ public function testClamavDaemonDefaults(): void { } // phpcs:ignore #;> SERVICE_CLAMAV + // phpcs:ignore #;< MODULE_CONFIG_SPLIT /** * Test Config Split config. @@ -166,6 +167,9 @@ public static function dataProviderConfigSplit(): array { ]; } + // phpcs:ignore #;> MODULE_CONFIG_SPLIT + // phpcs:ignore #;< MODULE_ENVIRONMENT_INDICATOR + /** * Test Environment Indicator config. */ @@ -231,6 +235,7 @@ public static function dataProviderEnvironmentIndicator(): array { ]; } + // phpcs:ignore #;> MODULE_ENVIRONMENT_INDICATOR // phpcs:ignore #;< SERVICE_REDIS /** @@ -307,6 +312,7 @@ public function testRedisCustomPort(): void { } // phpcs:ignore #;> SERVICE_REDIS + // phpcs:ignore #;< MODULE_SHIELD /** * Test Shield config. @@ -540,6 +546,9 @@ public static function dataProviderShield(): array { ]; } + // phpcs:ignore #;> MODULE_SHIELD + // phpcs:ignore #;< MODULE_STAGE_FILE_PROXY + /** * Test Stage File Proxy config. */ @@ -667,6 +676,8 @@ public static function dataProviderStageFileProxy(): array { ]; } + // phpcs:ignore #;> MODULE_STAGE_FILE_PROXY + /** * Test trusted host patterns settings. */