diff --git a/.vortex/docs/.utils/update-videos.php b/.vortex/docs/.utils/update-videos.php index 323bde87c5..e15caede34 100755 --- a/.vortex/docs/.utils/update-videos.php +++ b/.vortex/docs/.utils/update-videos.php @@ -201,6 +201,9 @@ function build_installer_expect_script(int|float $prompt_delay, string $uri): st } set env(VORTEX_INSTALLER_PROMPT_BUILD_NOW) 0 +# The prompts below match Unicode symbols, so the installer output is decoded +# as UTF-8 whatever the locale. +encoding system utf-8 spawn php installer.php --destination=star_wars --uri=$installer_uri expect { @@ -240,22 +243,19 @@ function build_installer_expect_script(int|float $prompt_delay, string $uri): st } } -# A multiselect that scrolls prints its selection count in the bottom border, -# so the corner follows the count instead of a line. +# A prompt waiting for input starts with the active symbol, U+25C7, and an +# answered one with the completed symbol, so only a waiting prompt matches. +# A top-level prompt is numbered "(5/36)" and a nested one "(5.1)". while {1} { expect { - "Proceed with installing Vortex?" { - after 2000 - safe_send "\r" - } - "Vortex will be installed into your project" { + -re {◇[^\r\n]*Proceed with installing Vortex} { after 2000 safe_send "\r" } "Finished installing Vortex" { break } - -re {─┘| selected ┘} { + -re {◇[^\r\n]*\([0-9]+(\.[0-9]+)*(/[0-9]+)?\)} { wait_and_enter } timeout { diff --git a/.vortex/docs/.vale/config/vocabularies/Vortex/accept.txt b/.vortex/docs/.vale/config/vocabularies/Vortex/accept.txt index cca854d87c..b277af614c 100644 --- a/.vortex/docs/.vale/config/vocabularies/Vortex/accept.txt +++ b/.vortex/docs/.vale/config/vocabularies/Vortex/accept.txt @@ -26,6 +26,7 @@ PHPCS PHPStan PHPUnit PhpStorm +Prompty Pygmy Rector Renovate diff --git a/.vortex/docs/content/contributing/maintenance/installer.mdx b/.vortex/docs/content/contributing/maintenance/installer.mdx index 8a065f2e52..aed67ba717 100644 --- a/.vortex/docs/content/contributing/maintenance/installer.mdx +++ b/.vortex/docs/content/contributing/maintenance/installer.mdx @@ -33,7 +33,7 @@ together with the installer logic that handles it, so the 2 stay in step. The installer is written in PHP because it touches many parts of the template and has to manage every permutation of the template's variants. PHP also gives it a terminal UI through -[Laravel Prompts](https://github.com/laravel/prompts), which asks the +[Prompty](https://github.com/AlexSkrypnyk/prompty), which asks the questions 1 at a time. With `--no-interaction`, it asks nothing at all: it installs and updates projects unattended, which suits automated pipelines and CI environments. @@ -52,10 +52,18 @@ value: `composer.json`, `.env`, hosting-specific files like `.lagoon.yml`). 3. **Handler defaults** - fallback values defined by each handler. +An environment variable named `VORTEX_INSTALLER_PROMPT_` followed by the +prompt ID in capitals answers that prompt, so the installer doesn't ask it. +For example, `VORTEX_INSTALLER_PROMPT_HOSTING_PROVIDER=lagoon` answers the +hosting prompt. The variable wins over the 3 preceding sources. A prompt +with several choices reads a comma-separated list. A yes or no prompt reads +`1`, `true` and `yes` as yes, and `0`, `false` and `no` as no. An invalid +value stops the installer at that prompt. + The profile, theme and web root prompts go a step further. When discovery finds a value, or an earlier answer settles it, the installer uses that value without asking. For these 3 prompts, that value wins over -`--prompts`. Choosing Acquia +`--prompts` and the environment variable. Choosing Acquia hosting, for example, settles the web root. `--prompts` with `--no-interaction` runs a whole installation without a @@ -77,8 +85,8 @@ keyed by their `VORTEX_INSTALLER_*` names, such as `VORTEX_INSTALLER_TEMPLATE_REPO`. An environment variable with the same name wins over the value in the JSON. -The final **Run the site build now?** question is the only question with -an environment variable of its own: +The final **Run the site build now?** question comes after the summary, and +its environment variable sets the question's default: - `VORTEX_INSTALLER_PROMPT_BUILD_NOW` sets its default. `0` or an empty value defaults to no. Any other value, or an unset variable, defaults to diff --git a/.vortex/docs/cspell.json b/.vortex/docs/cspell.json index 8a3db57a56..db7e21a182 100644 --- a/.vortex/docs/cspell.json +++ b/.vortex/docs/cspell.json @@ -88,6 +88,7 @@ "phpstorm", "postbuild", "preboot", + "prompty", "pyrech", "redis", "renovatebot", diff --git a/.vortex/docs/static/img/installer.json b/.vortex/docs/static/img/installer.json index 6228397fea..8e45399c11 100644 --- a/.vortex/docs/static/img/installer.json +++ b/.vortex/docs/static/img/installer.json @@ -1,219 +1,193 @@ -{"version":2,"width":80,"height":27,"timestamp":1792537540,"command":"/home/user/demo/installer.exp","title":"Vortex Installer Demo","env":{"SHELL":"/opt/homebrew/opt/bash/bin/bash"}} -[0.510641, "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 ╚██╗ ██╔╝ ██║ ██║ ██╔══██╗ ██║ ██╔══╝ ██╔██╗\u001b[39m\r\r\n \u001b[36m ╚████╔╝ ╚██████╔╝ ██║ ██║ "] -[0.510655, "o", " ██"] -[0.51074, "o", "║ ███████╗ ██╔╝ ██╗\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──────────────────────────────────────────────────────────────────────────────\u001b[39m\r\r\n \u001b[2m Installer version: development\u001b[22m\r\r\n\r\r\n"] -[0.514866, "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[4mdevelopment\u001b[0m\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m version of Vortex into your project.\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[39m "] -[0.514876, "o", " "] -[0.514951, "o", " \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\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m 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.514963, "o", "───"] -[0.515028, "o", "────────────────────────┘\u001b[39m\r\r\n\r\r\n"] -[0.515267, "o", "\u001b[?25l"] -[0.518093, "o", "\r\r\n \u001b[36m⠂\u001b[39m \u001b[33mValidating repository and reference\u001b[39m\r\r\n"] -[0.524412, "o", "\u001b[999D\u001b[2A\u001b[J\u001b[?25h"] -[0.524471, "o", "\r\r\n \u001b[34m✦ Validating repository and reference\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[2mChecking repository \"/home/user/vortex\" and reference\u001b[22m\r\r\n \u001b[2m\"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✓ Repository and reference validated successfully\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 \r\r\n"] -[0.524573, "o", " \u001b[2mPress any key to continue...\u001b[22m\r\r\n"] -[3.533773, "o", "\r\r\n \u001b[46m\u001b[30m General information \u001b[39m\u001b[49m\r\r\n\r\r\n"] -[3.548138, "o", "\u001b[?25l"] -[3.551838, "o", "\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mSite name \u001b[2m(1/41)\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.705249, "o", "\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mSite name \u001b[2m(1/41)\u001b[22m\u001b[39m \u001b[90m────────────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m star \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/41)\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.705417, "o", "──"] -[4.296743, "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/41)\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/41)\u001b[22m\u001b[39m \u001b[90m────────────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m St\u001b[7m \u001b[27m "] -[4.296757, "o", " "] -[4.296825, "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.300314, "o", "\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mSite name \u001b[2m(1/41)\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.304032, "o", "\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mSite name \u001b[2m(1/41)\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.304168, "o", "\u001b[?25h"] -[5.323358, "o", "\u001b[?25l"] -[5.327832, "o", "\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mSite machine name \u001b[2m(2/41)\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.35401, "o", "\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mSite machine name \u001b[2m(2/41)\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"] -[6.387119, "o", "\u001b[?25l"] -[6.39355, "o", "\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mOrganization name \u001b[2m(3/41)\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.54757, "o", "\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mOrganization name \u001b[2m(3/41)\u001b[22m\u001b[39m \u001b[90m────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m Star Wa\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/41)\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.547584, "o", "───"] -[7.393206, "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/41)\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/41)\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.393223, "o", "────"] -[7.39332, "o", "─────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m We will use this name in the project and documentation.\u001b[39m\r\r\n"] -[8.39752, "o", "\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mOrganization name \u001b[2m(3/41)\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.400838, "o", "\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mOrganization name \u001b[2m(3/41)\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/41)\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.40107, "o", "de.\u001b[39m\r"] -[9.401418, "o", "\r\r\n"] -[10.405608, "o", "\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mOrganization machine name \u001b[2m(4/41)\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/41)\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.405614, "o", "tocol and"] -[10.40572, "o", " trailing slash.\u001b[39m\r\r\n"] -[11.407281, "o", "\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mPublic domain \u001b[2m(5/41)\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/41)\u001b[…\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.407736, "o", " "] -[11.407907, "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.40821, "o", "g an exist"] -[12.412947, "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.413221, "o", "──"] -[12.413546, "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.422656, "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/41)\u001b[…\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.422668, "o", " "] -[13.422753, "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.422766, "o", " "] -[13.422894, "o", " \u001b[90m│\u001b[39m\r\r\n\u001b[90m └─────────────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h"] -[14.424576, "o", "\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mProfile \u001b[2m(7/41)\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.425169, "o", "\u001b[1G\u001b[8A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mProfile \u001b[2m(7/41)\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/41)\u001b[22m\u001b[39m \u001b[90m──────────────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m› ◼\u001b[39m Coffee \u001b[36m┃\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m◼\u001b[39m \u001b[2mConfig split\u001b[22m \u001b[90m│\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m◼\u001b[39m \u001b[2mConfig upda"] -[15.42525, "o", "te\u001b[22m "] -[15.425306, "o", " \u001b[90m│\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m◼\u001b[39m \u001b[2mDevel\u001b[22m \u001b[90m│\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m◼\u001b[39m \u001b[2mDrupal helpers\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[2mFast 404\u001b[22m \u001b[90m│\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m◼\u001b[39m \u001b[2mGenerated content\u001b[22m \u001b[90m│\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m◼\u001b[39m \u001b[2mNavigation extra tools\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 └───────────────────────"] -[15.42536, "o", "───"] -[16.429262, "o", "─────────────────────── 19 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/41)\u001b[22m\u001b[22m \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 Devel \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Drupal helpers \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Environment indicator \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Fast 404 \u001b[90m│\u001b[39m\r"] -[16.429269, "o", "\r\n\u001b[90m │"] -[16.429402, "o", "\u001b[39m Generated content \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Navigation extra tools \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\r\n\u001b[90m │\u001b[39m Reroute email \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Robots.txt \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m SDC Devel \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 Testmode \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m XML Si"] -[16.429411, "o", "temap "] -[17.430871, "o", " \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 modules prefix \u001b[2m(9/41)\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/41)\u001b[22m\u001b[22m \u001b[90m────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m s"] -[17.430882, "o", "w "] -[17.431024, "o", " \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h"] -[18.435647, "o", "\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mCustom modules \u001b[2m(10/41)\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 Select which custom modules to include in your project: \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m ○ \u001b[1mBase\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Starter module with common site utilities (mail handling, \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m deploy hooks) and test scaffolding for Unit, Kernel, \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Functional, and FunctionalJavascript tests. \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90"] -[18.435672, "o", "m │\u001b[39m"] -[18.435925, "o", " ○ \u001b[1mSearch\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Custom Solr search integration module. Requires the Solr \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m service to be selected. \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m ○ \u001b[1mDemo\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Demonstrates how Vortex tooling works: includes a counter \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m block with CSS/JS, PHPUnit example tests across all test \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m types, and a Behat feature. Safe to remove on real projects. \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m ├──────────────────────────────────────"] -[18.43613, "o", "───"] -[18.436245, "o", "────────────────────────────┤\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m› ◼\u001b[39m Base - starter module with utilities and test scaffolding \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m◼\u001b[39m \u001b[2mSearch - custom Solr search integration\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m◼\u001b[39m \u001b[2mDemo - counter block and example tests to demonstrate tooling\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 modules.\u001b[39m\r\r\n"] -[19.448017, "o", "\u001b[1G\u001b[25A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mCustom modules \u001b[2m(10/41)\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 Select which custom modules to include in your project: \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m ○ \u001b[1mBase\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Starter module with common site utilities (mail handling, \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m deploy hooks) and test scaffolding for Unit, Kernel, \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Functional, and FunctionalJavascript tests. \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b"] -[19.448026, "o", "[39m "] -[19.448113, "o", "○ \u001b[1mSearch\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Custom Solr search integration module. Requires the Solr \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m service to be selected. \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m ○ \u001b[1mDemo\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Demonstrates how Vortex tooling works: includes a counter \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m block with CSS/JS, PHPUnit example tests across all test \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m types, and a Behat feature. Safe to remove on real projects. \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m ├───────────────────────────────────────────"] -[19.448122, "o", "───"] -[19.448228, "o", "──────────────────────┤\u001b[39m\r\r\n\u001b[90m │\u001b[39m Base - starter module with utilities and test scaffolding \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Search - custom Solr search integration \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Demo - counter block and example tests to demonstrate tooling \u001b[90m│\u001b[39m\r\r\n\u001b[90m └────────────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h"] -[20.451353, "o", "\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mTheme \u001b[2m(11/41)\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"] -[21.452224, "o", "\u001b[1G\u001b[8A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mTheme \u001b[2m(11/41)\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(12/41)\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"] -[21.452613, "o", " this nam"] -[21.452876, "o", "e as a custom theme name\u001b[39m\r\r\n"] -[22.455729, "o", "\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mCustom theme machine name \u001b[2m(12/41)\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\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mBuild front-end assets in the container? \u001b[2m(13/41)\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 Disable to build theme assets on the host or as part of deployment."] -[22.455741, "o", "\u001b[39m\r\r\n"] -[23.457703, "o", "\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mBuild front-end assets in the container? \u001b[2m(13/41)\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[36mStorybook component library? \u001b[2m(14/41)\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 Component library for the custom theme, rendered by Drupal \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m itself. \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Stories are author"] -[23.458075, "o", "ed in Twig "] -[23.458245, "o", "next to each component, so the \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m library shows the same markup the site renders. \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m A development server runs on demand with `ahoy storybook`. A \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m static build is produced during provisioning and served at \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m `/storybook` in local, CI and development environments. \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○ Yes /\u001b[22m \u001b[32m●\u001b[39m No \u001b[90m│\u001b[39m\r\r\n\u001b[90m └───────────────────────────────"] -[23.458439, "o", "───"] -[24.463215, "o", "────────────────────────────┘\u001b[39m\r\r\n\u001b[90m Adds Storybook packages to the theme and a step to provisioning.\u001b[39m\r\r\n\u001b[1G\u001b[17A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mStorybook component library? \u001b[2m(14/41)\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 Component library for the custom theme, rendered by Drupal \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m itself. \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Stories are authored in Twig next to each component, so the \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m library shows the same markup the site renders. \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m A development serv"] -[24.463594, "o", "er runs on d"] -[24.463888, "o", "emand with `ahoy storybook`. A \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m static build is produced during provisioning and served at \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m `/storybook` in local, CI and development environments. \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 No \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h"] -[25.466692, "o", "\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(15/41)\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"] -[25.466866, "o", "│\u001b[39m\r\r\n\u001b"] -[25.467018, "o", "[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m Use ⬆ and ⬇ to select your code repository provider.\u001b[39m\r\r\n"] -[26.479044, "o", "\u001b[1G\u001b[11A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mRepository provider \u001b[2m(15/41)\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 └────────────────────────────────────────────────────"] -[26.479058, "o", "───"] -[26.479164, "o", "───────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h"] -[27.483075, "o", "\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mRelease versioning scheme \u001b[2m(16/41)\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 your versioning scheme: \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m ○ \u001b[1mCalendar Versioning (CalVer)\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[4myear.month.patch\u001b[0m (E.g., \u001b[4m24.1.0\u001b[0m) \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m https://calver.org \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m ○ \u001b[1mSemantic Versioning (SemVer)\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[4mmajor.minor.patch\u001b[0m (E.g., \u001b[4m1.0.0\u001b[0m) "] -[27.483098, "o", " "] -[27.483359, "o", " \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m https://semver.org \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m ○ \u001b[1mOther\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Custom versioning scheme of your choice. \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 Calendar Versioning (CalVer) \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mSemantic Versioning (SemVer)\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mOther\u001b[22m \u001b"] -[27.483542, "o", "[90m│\u001b["] -[27.483648, "o", "39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m Use ⬆ and ⬇ to select your version scheme.\u001b[39m\r\r\n"] -[28.487696, "o", "\u001b[1G\u001b[22A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mRelease versioning scheme \u001b[2m(16/41)\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 your versioning scheme: \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m ○ \u001b[1mCalendar Versioning (CalVer)\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[4myear.month.patch\u001b[0m (E.g., \u001b[4m24.1.0\u001b[0m) \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m https://calver.org \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m ○ \u001b[1mSemantic Versioning (SemVer)\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[4mmajor.minor.patch\u001b[0m (E.g., \u001b[4m1.0.0\u001b[0m) "] -[28.487707, "o", " "] -[28.487869, "o", " \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m https://semver.org \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m ○ \u001b[1mOther\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Custom versioning scheme of your choice. \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 Calendar Versioning (CalVer) \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h"] -[29.492595, "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(17/41)\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(17/41)\u001b[22m\u001b[22m \u001b[90m"] -[29.492815, "o", "────"] -[29.492945, "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"] -[30.493198, "o", "\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mServices \u001b[2m(18/41)\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(18/41)\u001b[22m\u001b[22m \u001b[90m────────────────────────────────────────────┐\u001b"] -[30.493258, "o", "[39m\r\r\n\u001b["] -[30.493326, "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"] -[31.498728, "o", "\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mDevelopment tools \u001b[2m(19/41)\u001b[22m\u001b[39m \u001b[90m───────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m› ◼\u001b[39m PHP CodeSniffer \u001b[36m┃\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m◼\u001b[39m \u001b[2mPHPStan\u001b[22m \u001b[90m│\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m◼\u001b[39m \u001b[2mRector\u001b[22m \u001b[90m│\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m◼\u001b[39m \u001b[2mESLint\u001b[22m \u001b[90m│\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m◼\u001b[39m \u001b[2mStylelint\u001b[22m \u001b[90m│\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m◼\u001b[39m \u001b[2mJest\u001b[22m \u001b[90m│\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m◼\u001b[39m \u001b[2mPHPUnit\u001b[22m "] -[31.499037, "o", " \u001b[90"] -[31.49935, "o", "m│\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m◼\u001b[39m \u001b[2mBehat\u001b[22m \u001b[90m│\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m◼\u001b[39m \u001b[2mTwig CS Fixer\u001b[22m \u001b[90m│\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m◼\u001b[39m \u001b[2mDCLint\u001b[22m \u001b[90m│\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m └───────────────────────────────────────────────── 11 selected ┘\u001b[39m\r\r\n\u001b[90m Use ⬆, ⬇ and Space bar to select one or more tools.\u001b[39m\r\r\n"] -[32.504923, "o", "\u001b[1G\u001b[14A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mDevelopment tools \u001b[2m(19/41)\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 ESLint \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Stylelint \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Jest \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 Twig CS Fixer \u001b[90m│\u001b[39m\r\r\n\u001b"] -[32.504931, "o", "[90m │\u001b[3"] -[32.505037, "o", "9m DCLint \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Hadolint \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h"] -[33.507601, "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(20/41)\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"] -[34.5123, "o", "\u001b[1G\u001b[8A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mHosting provider \u001b[2m(20/41)\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(21/41)\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"] -[34.512624, "o", "rver serv"] -[34.512708, "o", "es the site.\u001b[39m\r\r\n"] -[35.517247, "o", "\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mCustom web root directory \u001b[2m(21/41)\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(22/41)\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[36m◼\u001b[39m \u001b[2mCustom webhook\u001b[22m "] -[35.517446, "o", " \u001b["] -[35.518003, "o", "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"] -[36.522716, "o", "\u001b[1G\u001b[7A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mDeployment types \u001b[2m(22/41)\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(23/41)\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 │"] -[36.522736, "o", "\u001b[39m "] -[36.522958, "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 ├─"] -[36.523089, "o", "───"] -[37.5286, "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(23/41)\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"] -[37.528625, "o", "nvironment"] -[37.528954, "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. "] -[37.529273, "o", " "] -[38.530575, "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(24/41)\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 "] -[38.530889, "o", " "] -[38.530984, "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[2mS3 bucket\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 fetch source.\u001b[39m\r\r\n"] -[39.553542, "o", "\u001b[1G\u001b[11A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mDatabase source \u001b[2m(24/41)\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"] -[40.557815, "o", "\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mUse a second database for migrations? \u001b[2m(25/41)\u001b[22m\u001b[39m \u001b[90m───────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○ Yes /\u001b[22m \u001b[32m●\u001b[39m No \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m Adds a second database service for Drupal migrations.\u001b[39m\r\r\n"] -[41.562975, "o", "\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mUse a second database for migrations? \u001b[2m(25/41)\u001b[22m\u001b[22m \u001b[90m───────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m No \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 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(26/41)\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 "] -[41.563276, "o", "│\u001b[39m \u001b["] -[41.563674, "o", "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 └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m Use ⬆, ⬇ and Space bar to select one or more notification channels.\u001b[39m\r\r\n"] -[42.567115, "o", "\u001b[1G\u001b[10A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mNotification channels \u001b[2m(26/41)\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(27/41)\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 "] -[42.567339, "o", " \u001b["] -[42.567501, "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"] -[43.571947, "o", "\u001b[1G\u001b[7A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mContinuous Integration provider \u001b[2m(27/41)\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\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mVisual regression testing with Diffy? \u001b[2m(28/41)\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 Diffy-powered visual regression workflow to compare deployed \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 Automatically trig"] -[43.571961, "o", "gers compar"] -[43.572067, "o", "isons for dependency-update \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m pull requests matching the configured branch pattern \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m (`deps/*` by default). \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Runs comparisons for pull requests tagged with the `VR` \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m label and posts a sticky comment. \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Also supports manual runs against any URL. \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○ Yes /\u001b[22m "] -[43.57208, "o", "\u001b[32m●\u001b["] -[44.578802, "o", "39m No \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m Requires a Diffy account.\u001b[39m\r\r\n\u001b[1G\u001b[19A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mVisual regression testing with Diffy? \u001b[2m(28/41)\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 Diffy-powered visual regression workflow to compare deployed \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 Automatically triggers comparisons for dependency-update \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m pull requests matching the configured branch pattern \u001b[90m│\u001b[39m\r\r\n"] -[44.578813, "o", "\u001b[90m │\u001b["] -[44.579093, "o", "39m (`deps/*` by default). \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Runs comparisons for pull requests tagged with the `VR` \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m label and posts a sticky comment. \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Also supports manual runs against any URL. \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 No \u001b[90m│\u001b[39m\r\r\n\u001b[90m └────────────────────────────"] -[44.579283, "o", "───"] -[45.583027, "o", "───────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mScan for committed secrets with Gitleaks? \u001b[2m(29/41)\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 Runs in CI to detect hardcoded passwords, API keys and tokens.\u001b[39m\r\r\n\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mScan for committed secrets with Gitleaks? \u001b[2m(29/41)\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 └─────────────────────────────────────────"] -[45.583329, "o", "───"] -[45.583565, "o", "──────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h"] -[46.587489, "o", "\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(30/41)\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\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m Use ⬆ and ⬇ to select the dependency updates provider.\u001b[39m\r\r\n\u001b[1G\u001b[7A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mDependency updates provider \u001b[2m(30/41)\u001b[22m\u001b[22m \u001b[90m─────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m Ren"] -[46.587812, "o", "ovate GitHub"] -[46.58808, "o", " app \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h"] -[47.592483, "o", "\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mAuto-merge dependency updates \u001b[2m(31/41)\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 Pull requests in the selected groups are merged as soon as \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m they meet the branch protection rules. Pull requests in \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m other groups need a manual merge. \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Requires \"Allow auto-merge\" in the repository settings and \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m at least one required status check on the base branch. \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m ├─────────────────────────────────────"] -[47.592496, "o", "────"] -[47.592601, "o", "─────────────────────┤\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m› ◼\u001b[39m PHP packages, except Drupal core (minor and patch) \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m◼\u001b[39m \u001b[2mDrupal core (minor and patch)\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m◼\u001b[39m \u001b[2mJavaScript packages (minor and patch)\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m◼\u001b[39m \u001b[2mContainer images (major, minor and patch)\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m◼\u001b[39m \u001b[2mCI tools (major, minor and patch)\u001b[22m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[36m◼\u001b[39m \u001b[2mGitHub Actions (major, minor and patch)\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 groups.\u001b[39m\r\r\n"] -[48.603783, "o", "\u001b[1G\u001b[19A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mAuto-merge dependency updates \u001b[2m(31/41)\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 Pull requests in the selected groups are merged as soon as \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m they meet the branch protection rules. Pull requests in \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m other groups need a manual merge. \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Requires \"Allow auto-merge\" in the repository settings and \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m at least one required status check on the base branch. \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[90m│\u001b[39m\r\r\n\u001b[90m ├────────────────────────────────────"] -[48.603799, "o", "───"] -[48.604011, "o", "───────────────────────┤\u001b[39m\r\r\n\u001b[90m │\u001b[39m PHP packages, except Drupal core (minor and patch) \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Drupal core (minor and patch) \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m JavaScript packages (minor and patch) \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m Container images (major, minor and patch) \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m CI tools (major, minor and patch) \u001b[90m│\u001b[39m\r\r\n\u001b[90m │\u001b[39m GitHub Actions (major, minor and patch) \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h"] -[49.608335, "o", "\u001b[?25l\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mCode coverage provider \u001b[2m(32/41)\u001b[22m\u001b[39m \u001b[90m──────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○\u001b[22m \u001b[2mCodecov\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 ⬇ to select the code coverage provider.\u001b[39m\r\r\n"] -[50.613136, "o", "\u001b[1G\u001b[6A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mCode coverage provider \u001b[2m(32/41)\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[36mAuto-assign the author to their PR? \u001b[2m(33/41)\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"] -[51.613864, "o", "\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mAuto-assign the author to their PR? \u001b[2m(33/41)\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(34/41)\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"] -[52.617614, "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(34/41)\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(35/41)\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"] -[52.618108, "o", " within the "] -[52.618304, "o", "repository.\u001b[39m\r\r\n"] -[53.621005, "o", "\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mPreserve project documentation? \u001b[2m(35/41)\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[36mProvide AI agent instructions? \u001b[2m(36/41)\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 Provides AI coding agents"] -[53.621012, "o", " with better"] -[53.621171, "o", " context about the project.\u001b[39m\r\r\n"] -[54.625137, "o", "\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mProvide AI agent instructions? \u001b[2m(36/41)\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 \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│\u001b[39m\r\r\n \u001b[90m│"] -[54.625169, "o", "\u001b[39m\u001b[39m "] -[54.625423, "o", "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 Modules \u001b[39m\u001b[90m│\u001b[39m\u001b[39m cof"] -[54.625548, "o", "fee, co"] -[55.629481, "o", "nfig_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, devel,\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 drupal_helpers,\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 environment_indicator, fast_404,\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 generated_content,\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 navigation_extra_tools, pathauto,\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 redirect, reroute_email,\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 robotstxt, sdc_deve"] -[55.629855, "o", "l, seck"] -[55.630124, "o", "it,\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[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\u001b[39m testmode, xmlsitemap \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 Custom modules \u001b[39m\u001b[90m│\u001b[39m\u001b[39m base, search, demo \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 Build f"] -[55.630487, "o", "ront-end"] -[55.630756, "o", " in container \u001b[39m\u001b[90m│\u001b[39m\u001b[39m Yes \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Storybook component library \u001b[39m\u001b[90m│\u001b[39m\u001b[39m No \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 Version scheme \u001b[39m\u001b[90m│\u001b[39m\u001b[39m calver \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"] -[55.631039, "o", " clamav"] -[55.631159, "o", ", 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 behat, dclint, eslint, hadolint,\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 jest, phpcs, phpstan, 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 rector, stylelint, twig_cs_fixer \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 "] -[55.631436, "o", " "] -[55.631602, "o", " \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 Migration database \u001b[39m\u001b[90m│\u001b[39m\u001b[39m No \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"] -[55.631614, "o", " \u001b[90m"] -[55.631915, "o", "│\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 Visual regression testing \u001b[39m\u001b[90m│\u001b[39m\u001b[39m No \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Secret scanning with Gitleaks \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[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-merge dependency updates \u001b[39m\u001b[90m│\u001b[39m\u001b[39m php, drupal_core, js,\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 container_images, ci_tools,\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m "] -[55.631926, "o", " "] -[55.63218, "o", "\u001b[39m\u001b[90m│\u001b[39m\u001b[39m github_actions \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Code coverage 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 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 \u001b[39m\u001b[90m│\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m AI agent instructions \u001b[39m\u001b[90m│\u001b[39m\u001b[39m Yes "] -[55.632191, "o", " "] -[55.632436, "o", " \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/vortex/.ar\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 tifacts/tmp/videos-workspace \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/vortex/.ar\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 tifacts/tmp/videos-workspace/star_\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 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 /home/user/vortex \u001b[39m\u001b[90m│\u001b[39m\r"] -[55.632733, "o", "\r\n \u001b[90m"] -[55.632889, "o", "│\u001b[39m\u001b[39m Vortex reference \u001b[39m\u001b[90m│\u001b[39m\u001b[39m HEAD \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/demo/star_wars\"\r\r\n"] -[57.63594, "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"] -[59.641371, "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[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 \"/home/user/vortex\" repository at ref\u001b[22m\r\r\n \u001b[2m\"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 (develop)\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"] -[59.642154, "o", "[2A\u001b[J\r\r\n \u001b[36m⠒\u001b[39m \u001b[33mCusto"] -[60.646035, "o", "mizing Vortex for your project\u001b[39m\r\r\n\u001b[999D\u001b[2A\u001b[J\u001b[?25h\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\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\u001b[?25l\r\r\n \u001b[36m⠂\u001b[39m \u001b[33mPreparing destination directory\u001b[39m\r\r\n\u001b[999D\u001b[2A\u001b[J\u001b[?25h\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\r\r\n \u001b[2mCreated directory \"/home/user/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[2mInitializing a new Git repository in directory \"/home/user/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\u001b[?25l\r\r\n \u001b[36m⠂\u001b[39m \u001b[33mCopying files to the destination directory\u001b[39m\r\r\n\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠒\u001b[39m \u001b[33mCopying files to the destination directory\u001b[39m\r\r\n\u001b[999D\u001b[2A\u001b[J\u001b[?25h\r\r\n \u001b[34m✦ Copying files to the destination directory\u001b[39m\r\r\n\r\r\n\r"] -[60.64605, "o", "\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 "] -[60.646147, "o", "to destination directory\u001b[39m\r\r\n\r\r\n"] -[60.646196, "o", "\r\r\n \u001b[A\u001b[A\u001b[A\u001b[A\r\r\n\r\r\n"] -[60.646372, "o", "\u001b[?25l"] -[60.650228, "o", "\r\r\n \u001b[36m⠂\u001b[39m \u001b[33mPreparing demo content\u001b[39m\r\r\n"] -[60.733243, "o", "\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠒\u001b[39m \u001b[33mPreparing demo content\u001b[39m\r\r\n"] -[60.818869, "o", "\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠐\u001b[39m \u001b[33mPreparing demo content\u001b[39m\r\r\n"] -[60.900329, "o", "\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠰\u001b[39m \u001b[33mPreparing demo content\u001b[39m\r\r\n"] -[60.984926, "o", "\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠠\u001b[39m \u001b[33mPreparing demo content\u001b[39m\r\r\n"] -[61.065473, "o", "\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠤\u001b[39m \u001b[33mPreparing demo content\u001b[39m\r\r\n"] -[61.147791, "o", "\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠄\u001b[39m \u001b[33mPreparing demo content\u001b[39m\r\r\n"] -[61.230432, "o", "\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠆\u001b[39m \u001b[33mPreparing demo content\u001b[39m\r\r\n"] -[61.30935, "o", "\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠂\u001b[39m \u001b[33mPreparing demo content\u001b[39m\r\r\n"] -[61.388788, "o", "\u001b[1G\u001b[2A\u001b[J\r\r\n \u001b[36m⠒\u001b[39m \u001b[33mPreparing demo content\u001b[39m\r\r\n"] -[61.400264, "o", "\u001b[999D\u001b[2A\u001b[J\u001b[?25h"] -[61.400443, "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/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/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[2mFetched demo database from https://github.com/drevops/vortex/releases/download/1.40.0/db.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\r\r\n \u001b[A\u001b[A\u001b[A\u001b[A\r\r\n\r\r\n"] -[61.402975, "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 Add and commit all files:\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[90m│\u001b[39m\r\r\n \u001b[90m└───────────────────────────────────┘\u001b[39m\r\r\n\r\r\n"] -[61.419715, "o", "\u001b[?25l"] -[61.422415, "o", "\r\r\n\u001b[90m ┌\u001b[39m \u001b[36mRun the site build now?\u001b[39m \u001b[90m─────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m \u001b[2m○ Yes /\u001b[22m \u001b[32m●\u001b[39m No \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\u001b[90m Takes ~5-10 min; output will be streamed. You can skip and run later with…\u001b[39m\r\r\n"] -[63.435549, "o", "\u001b[1G\u001b[5A\u001b[J\r\r\n\u001b[90m ┌\u001b[39m \u001b[2mRun the site build now?\u001b[22m \u001b[90m─────────────────────────────────────┐\u001b[39m\r\r\n\u001b[90m │\u001b[39m No \u001b[90m│\u001b[39m\r\r\n\u001b[90m └──────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n\u001b[?25h"] -[63.444408, "o", "\r\r\n \u001b[90m┌────────────────────────────────────────────────────────────────────────────┐\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m \u001b[32mReady to build\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 Build the site:\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"] -[63.444424, "o", "│\u001b[39"] -[63.444533, "o", "m\r\r\n \u001b[90m│\u001b[39m\u001b[39m Setup GitHub Actions:\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 https://www.vortextemplate.com/docs/continuous-integration/github-actions#\u001b[39m\u001b[39m \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m│\u001b[39m\u001b[39m onboarding\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 \u001b[39m\u001b[90m│\u001b[39m\r\r\n \u001b[90m└────────────────────────────────────────────────────────────────────────────┘\u001b[39m\r\r\n\r\r\n"] -[63.455073, "x", "0"] +{"version":2,"width":80,"height":27,"timestamp":1794377261,"command":"/home/user/demo/installer.exp","title":"Vortex Installer Demo","env":{"SHELL":"/opt/homebrew/opt/bash/bin/bash"}} +[0.513183, "o", "\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 ╚██╗ ██╔╝ ██║ ██║ ██╔══██╗ ██║ ██╔══╝ ██╔██╗\u001b[39m\r\r\n\u001b[36m ╚████╔╝ ╚██████╔╝ ██║ ██║ ██║ "] +[0.513224, "o", " █"] +[0.513294, "o", "██████╗ ██╔╝ ██╗\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──────────────────────────────────────────────────────────────────────────────\u001b[39m\r\r\n\u001b[2m Installer version: development\u001b[22m\r\r\n"] +[0.514513, "o", "\u001b[90m│\u001b[0m \u001b[90m┌───────────────────────────────────────────────────────────────────────────┐\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[1mWelcome to the Vortex interactive installer\u001b[0m \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[90m───────────────────────────────────────────\u001b[0m \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m This tool will guide you through installing the latest \u001b[4mdevelopment\u001b[0m \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m version of Vortex into your project. \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m You will be asked a few questions to tailor the c"] +[0.514517, "o", "onfigu"] +[0.51459, "o", "ration to your \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m site. \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m No changes will be made until you confirm everything at the end. \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m Press \u001b[33mCtrl+C\u001b[39m at any time to exit the installer.\u001b[0m \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m Press \u001b[33mCtrl+U\u001b[39m at any time to go back to the previous step.\u001b[0m \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m└───────────────────────────────────────────────────────────────────────────┘\u001b[0m\r\r\n\u001b[90m│\u001b"] +[0.514594, "o", "[0m\r\r\n"] +[0.515221, "o", "\u001b[36m◇\u001b[0m Validating repository and reference\r\r\n"] +[0.521313, "o", "\u001b[90m│\u001b[0m \u001b[2mChecking repository \"/home/user/vortex\" and reference \"HEAD\"\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[32m✓ Repository and reference validated successfully\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[0.5346, "o", "\u001b[?25l\u001b[36m◇\u001b[0m Press any key to continue...\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[3.539737, "o", "\u001b[2A\r\u001b[J"] +[3.550914, "o", "\u001b[?25h"] +[3.567294, "o", "\u001b[?25l"] +[3.567362, "o", "\r\r\n\u001b[90m┌\u001b[0m \u001b[1mGeneral information\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[3.567628, "o", "\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mstar wars\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[3.72272, "o", "\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[37mstar war\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[37mstar wa\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[37mstar w\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[37mstar \u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[37mstar\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use"] +[3.722727, "o", " this name in the project an"] +[4.49924, "o", "d documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[37msta\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[37mst\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[37ms\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Site\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Site\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m"] +[4.499259, "o", "│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe "] +[4.499363, "o", "will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[5.502853, "o", "\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Site\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Site\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Site\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Site\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Site\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r"] +[5.503115, "o", "\r\n\u001b[90m│\u001b[0m \u001b[2mWe will u"] +[5.504792, "o", "se this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[5.505193, "o", "\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Site\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Site\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Site\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Site\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Site\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r"] +[5.506029, "o", "\r\n\u001b[90m│\u001b[0m \u001b[2mWe will u"] +[5.506121, "o", "se this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Site\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Site\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Site\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[5.506194, "o", "\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Site\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[5.506325, "o", "\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Site\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[5.506437, "o", "\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Site\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[5.506558, "o", "\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Site\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[5.506625, "o", "\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Site\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[5.506744, "o", "\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Site\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[5.506848, "o", "\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Site\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[5.506935, "o", "\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Site\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[5.507049, "o", "\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Site\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[5.507189, "o", "\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Site\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[5.507237, "o", "\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Site\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[5.50735, "o", "\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Site\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[5.50742, "o", "\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Site\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[5.507516, "o", "\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Site\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[5.507629, "o", "\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Site\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[5.507752, "o", "\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Site\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[5.50782, "o", "\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Site\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[5.507921, "o", "\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Site\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[5.508032, "o", "\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Site\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[5.508108, "o", "\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Site\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[5.508221, "o", "\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Site\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[5.508322, "o", "\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Site\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[5.508452, "o", "\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Site\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[5.50851, "o", "\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Site\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[5.508663, "o", "\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Site\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[5.508699, "o", "\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Site\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[5.508824, "o", "\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Site\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[5.508915, "o", "\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[37mS\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[5.509017, "o", "\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[37mSt\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[5.509122, "o", "\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[37mSta\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[5.509217, "o", "\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[37mStar\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[5.509291, "o", "\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[37mStar \u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[5.509393, "o", "\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[37mStar W\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[5.509513, "o", "\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[37mStar Wa\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[5.509587, "o", "\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[37mStar War\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[5.509695, "o", "\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Site name \u001b[2m(1/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[37mStar Wars\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[5.509784, "o", "\u001b[6A\r\u001b[J\u001b[36m◆\u001b[0m Site name (1/32)\r\r\n\u001b[90m│\u001b[0m \u001b[2mStar Wars\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[5.510167, "o", "\u001b[36m◇\u001b[0m Site machine name \u001b[2m(2/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mstar_wars\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name for the project directory and in the code.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[6.515201, "o", "\u001b[6A\r\u001b[J\u001b[36m◆\u001b[0m Site machine name (2/32)\r\r\n\u001b[90m│\u001b[0m \u001b[2mstar_wars\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[6.51592, "o", "\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mStar Wars Org\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[6.668715, "o", "\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[37mStar Wars Or\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[37mStar Wars O\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[37mStar Wars \u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[37mStar Wars\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[37mStar War\u001b[0"] +[6.668944, "o", "m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0"] +[7.81266, "o", "m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[37mStar Wa\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[37mStar W\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[37mStar \u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[37mStar\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m O"] +[7.813011, "o", "rganization name \u001b[2m(3/32)"] +[7.814077, "o", "\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[37mSta\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[37mSt\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[37mS\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Org\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Org\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name i"] +[7.814157, "o", "n the project and documentat"] +[8.821805, "o", "ion.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Org\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Org\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Org\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Org\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b["] +[8.823027, "o", "90m│\u001b[0m \u001b[90mE.g. My Org"] +[8.823117, "o", "\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Org\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[9.827727, "o", "\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Org\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Org\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Org\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Org\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My O"] +[9.827739, "o", "rg\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m"] +[9.827985, "o", "│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[10.833155, "o", "\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Org\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Org\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Org\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Org\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My O"] +[10.833494, "o", "rg\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m"] +[10.833604, "o", "│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Org\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Org\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Org\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Org\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b["] +[10.833794, "o", "0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m O"] +[11.835524, "o", "rganization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Org\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Org\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Org\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Org\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Org\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b["] +[11.835536, "o", "90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b"] +[11.835665, "o", "[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[12.840987, "o", "\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Org\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Org\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Org\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Org\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My O"] +[12.841462, "o", "rg\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m"] +[12.84161, "o", "│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Org\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[13.845364, "o", "\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Org\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Org\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Org\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My Org\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90mE.g. My O"] +[13.845372, "o", "rg\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m"] +[13.845491, "o", "│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[14.847879, "o", "\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[37mR\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[37mRe\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[37mReb\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[37mRebe\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[37mRebel\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90"] +[14.8482, "o", "m│\u001b[0m \u001b[2mWe will use th"] +[14.848343, "o", "is name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[37mRebell\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[15.852422, "o", "\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[37mRebelli\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[37mRebellio\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◇\u001b[0m Organization name \u001b[2m(3/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[37mRebellion\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the project and documentation.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◆\u001b[0m Organization name (3/32)\r\r\n\u001b[90m│\u001b[0m \u001b[2mRebellion\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[36m◇\u001b[0m Organization machine name \u001b[2m(4/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mrebellion\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in the code.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◆\u001b[0m Organization "] +[15.856824, "o", "machine name (4/32)\r\r\n\u001b[90m"] +[15.857769, "o", "│\u001b[0m \u001b[2mrebellion\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[36m◇\u001b[0m Public domain \u001b[2m(5/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mstar-wars.com\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mDomain name without protocol and trailing slash.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[16.860407, "o", "\u001b[6A\r\u001b[J\u001b[36m◆\u001b[0m Public domain (5/32)\r\r\n\u001b[90m│\u001b[0m \u001b[2mstar-wars.com\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m├\u001b[0m \u001b[1mDrupal\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[36m◇\u001b[0m How would you like your site to be created on the first run? \u001b[2m(6/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3mChoose how your site will be created the first time after this installer\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3mfinishes:\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m ○ \u001b[1mDrupal, installed from profile\u001b[22m\u001b[2;3m\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m Creates a new site by \u001b[4mpopulating a fresh database\u001b[0m\u001b[2;3m\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m from one of the standard Drupal installation profiles.\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m ○ \u001b[1mDrupal CMS, installed from profile\u001b[22m\u001b[2;3m\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m Creates a new site by \u001b[4mpopulating a fresh database\u001b[0m\u001b[2;3m\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m from the Drupal CMS recipe.\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m ○ \u001b[1mDrupal, loaded from the demo database"] +[16.860422, "o", "\u001b[22m\u001b[2;3m\u001b[0m\r\r\n"] +[16.86057, "o", "\u001b[90m│\u001b[0m \u001b[2;3m Creates a site by \u001b[4mloading an existing demo database\u001b[0m\u001b[2;3m\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m provided with the installer.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2m○\u001b[0m \u001b[2mDrupal, installed from profile\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2m○\u001b[0m \u001b[2mDrupal CMS, installed from profile\u001b[0m\r\r\n\u001b[90m│\u001b[0m\u001b[36m❯\u001b[0m \u001b[32m●\u001b[0m Drupal, loaded from the demo database\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mUse ⬆ and ⬇. Applies only on the first run of the installer.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[17.864365, "o", "\u001b[22A\r\u001b[J\u001b[36m◆\u001b[0m How would you like your site to be created on the first run? (6/32)\r\r\n\u001b[90m│\u001b[0m \u001b[2mDrupal, loaded from the demo database\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[36m◇\u001b[0m Profile \u001b[2m(7/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m\u001b[36m❯\u001b[0m \u001b[32m●\u001b[0m Standard\r\r\n\u001b[90m│\u001b[0m \u001b[2m○\u001b[0m \u001b[2mMinimal\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2m○\u001b[0m \u001b[2mDemo Umami\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2m○\u001b[0m \u001b[2mCustom (next prompt)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mUse ⬆ and ⬇ to select which Drupal profile to use.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[9A\r\u001b[J\u001b[36m◆\u001b[0m Profile (7/32)\r\r\n\u001b[90m│\u001b[0m \u001b[2mStandard\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[36m◇\u001b[0m Modules \u001b[2m(8/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m\u001b[36m❯\u001b[0m \u001b[32m◼\u001b[0m Coffee\r\r\n\u001b[90m│\u001b[0m \u001b[32m◼\u001b[0m Config split\r\r\n\u001b[90m│\u001b[0m \u001b[32m◼\u001b[0m Config update\r\r\n\u001b[90m│\u001b[0m \u001b[32m◼\u001b[0m Devel\r\r\n\u001b[90m│\u001b[0m \u001b[32m◼\u001b[0m Diff\r\r\n\u001b[90m│\u001b[0m \u001b[32m◼\u001b[0m Drupal helpers\r\r\n\u001b[90m│\u001b[0m \u001b[32m◼\u001b[0m Entity usage\r\r\n\u001b[90m│\u001b[0m \u001b[32m◼\u001b[0m Environment indicator\r\r\n"] +[17.864376, "o", "\u001b[90m│\u001b[0m \u001b[32m◼\u001b[0m"] +[17.864478, "o", " Fast 404\r\r\n\u001b[90m│\u001b[0m \u001b[32m◼\u001b[0m Field group\r\r\n\u001b[90m│\u001b[0m \u001b[2m↓ 19 more\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mUse ⬆, ⬇ and Space bar to select one or more modules.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[18.868827, "o", "\u001b[17A\r\u001b[J\u001b[36m◆\u001b[0m Modules (8/32)\r\r\n\u001b[90m│\u001b[0m \u001b[2mCoffee, Config split, Config update, Devel, Diff, Drupal helpers, Entity\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2musage, Environment indicator, Fast 404, Field group, Generated content, Gin\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2madmin theme, Linkit, Menu trail by path, Metatag, Navigation extra tools,\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mPathauto, Redirect, Reroute email, Robots.txt, Scheduled transitions,\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mSchema.org Metatag, SDC Devel, Seckit, Shield, Stage file proxy, Testmode,\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mViews bulk operations, XML Sitemap\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[36m◇\u001b[0m Custom modules prefix \u001b[2m(9/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2msw\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mWe will use this name in custom modules\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[6A\r\u001b[J\u001b[36m◆\u001b[0m Custom modules prefix (9/32)\r\r\n\u001b[90m│\u001b[0m \u001b[2msw\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[36m◇\u001b[0m Custom modules \u001b[2m(10/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3mSelect which custom modules to include in your project:\u001b[0m"] +[18.868864, "o", "\r\r\n\u001b[90m│\u001b[0m \u001b["] +[18.868944, "o", "2;3m\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m ○ \u001b[1mBase\u001b[22m\u001b[2;3m\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m Starter module with deploy hooks and test scaffolding for\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m Unit, Kernel, Functional, and FunctionalJavascript tests.\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m ○ \u001b[1mSearch\u001b[22m\u001b[2;3m\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m Custom Solr search integration module. Requires the Solr\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m service to be selected.\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m ○ \u001b[1mDemo\u001b[22m\u001b[2;3m\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m Demonstrates how Vortex tooling works: includes a counter\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m block with CSS/JS, PHPUnit example tests across all test\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m types, and a Behat feature. Safe to remove on real projects.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m\u001b[36m❯\u001b[0m \u001b[32m◼\u001b[0m Base - starter module with utilities and test scaffolding\r\r\n\u001b[90m│\u001b[0m \u001b[32m◼\u001b[0m Search - custom Solr search integration\r\r\n\u001b[90m│\u001b[0m \u001b["] +[18.868947, "o", "32m◼\u001b[0m Demo "] +[19.872962, "o", "- counter block and example tests to demonstrate tooling\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mUse ⬆, ⬇ and Space bar to select one or more modules.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[22A\r\u001b[J\u001b[36m◆\u001b[0m Custom modules (10/32)\r\r\n\u001b[90m│\u001b[0m \u001b[2mBase - starter module with utilities and test scaffolding, Search - custom\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mSolr search integration, Demo - counter block and example tests to\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mdemonstrate tooling\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[36m◇\u001b[0m Theme \u001b[2m(11/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2m○\u001b[0m \u001b[2mOlivero\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2m○\u001b[0m \u001b[2mClaro\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2m○\u001b[0m \u001b[2mStark\u001b[0m\r\r\n\u001b[90m│\u001b[0m\u001b[36m❯\u001b[0m \u001b[32m●\u001b[0m Custom (next prompt)\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mUse ⬆ and ⬇ to select which Drupal theme to use.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[9A\r\u001b[J\u001b[36m◆\u001b[0m Theme (11/32)\r\r\n\u001b[90m│\u001b[0m \u001b[2mCustom (next prompt)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[36m◇\u001b[0m Custom theme machine name \u001b[2m(11.1)\u001b[0m\r\r\n\u001b[90m│\u001b"] +[19.873008, "o", "[0m \u001b[90m│\u001b[0m \r\r\n\u001b["] +[19.87308, "o", "90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[2mstar_wars\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[2mWe will use this name as a custom theme name\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \r\r\n"] +[20.876865, "o", "\u001b[6A\r\u001b[J\u001b[90m│\u001b[0m \u001b[36m◆\u001b[0m Custom theme machine name (11.1)\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[2mstar_wars\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \r\r\n\u001b[90m│\u001b[0m \u001b[36m◇\u001b[0m Build front-end assets in the container? \u001b[2m(11.2)\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[32m●\u001b[0m Yes \u001b[2m/\u001b[0m \u001b[2m○\u001b[0m \u001b[2mNo\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[2mDisable to build theme assets on the host or as part of deployment.\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \r\r\n\u001b[6A\r\u001b[J\u001b[90m│\u001b[0m \u001b[36m◆\u001b[0m Build front-end assets in the container? (11.2)\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[2mYes\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \r\r\n\u001b[90m│\u001b[0m \u001b[36m◇\u001b[0m Storybook component library? \u001b[2m(11.3)\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3mComponent library for the custom theme, rendered by Drupal itself.\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3mStories are authored in Twig next to each component, so the library shows\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3mthe same markup the site"] +[20.87691, "o", " renders.\u001b[0m\r\r\n\u001b"] +[20.876975, "o", "[90m│\u001b[0m \u001b[2;3m\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3mA development server runs on demand with `ahoy storybook`. A static build\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3mis produced during provisioning and served at `/storybook` in local, CI\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3mand development environments.\u001b[0m\r\r\n\u001b[90m│\u001b[0m \r\r\n\u001b[90m│\u001b[0m \u001b[2m○\u001b[0m \u001b[2mYes\u001b[0m \u001b[2m/\u001b[0m \u001b[32m●\u001b[0m No\r\r\n\u001b[90m│\u001b[0m \r\r\n\u001b[90m│\u001b[0m \u001b[2mAdds Storybook packages to the theme and a step to provisioning.\u001b[0m\r\r\n\u001b[90m│\u001b[0m \r\r\n"] +[21.881079, "o", "\u001b[14A\r\u001b[J\u001b[90m│\u001b[0m \u001b[36m◆\u001b[0m Storybook component library? (11.3)\r\r\n\u001b[90m│\u001b[0m \u001b[2mNo\u001b[0m\r\r\n\u001b[90m│\u001b[0m \r\r\n\u001b[90m├\u001b[0m \u001b[1mCode repository\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[36m◇\u001b[0m Repository provider \u001b[2m(12/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3mVortex offers full automation with GitHub, while support for other providers\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3mis limited.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m\u001b[36m❯\u001b[0m \u001b[32m●\u001b[0m GitHub\r\r\n\u001b[90m│\u001b[0m \u001b[2m○\u001b[0m \u001b[2mOther\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mUse ⬆ and ⬇ to select your code repository provider.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[9A\r\u001b[J\u001b[36m◆\u001b[0m Repository provider (12/32)\r\r\n\u001b[90m│\u001b[0m \u001b[2mGitHub\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[36m◇\u001b[0m Release versioning scheme \u001b[2m(13/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3mChoose your versioning scheme:\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m ○ \u001b[1mCalendar Versioning (CalVer)\u001b[22m\u001b[2;3m\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m \u001b[4myear.month.patch\u001b[0m\u001b[2;3m (E.g., \u001b[4m24.1.0\u001b[0m\u001b[2;3m)\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m "] +[21.881092, "o", "https://calver.org\u001b[0m"] +[21.881192, "o", "\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m ○ \u001b[1mSemantic Versioning (SemVer)\u001b[22m\u001b[2;3m\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m \u001b[4mmajor.minor.patch\u001b[0m\u001b[2;3m (E.g., \u001b[4m1.0.0\u001b[0m\u001b[2;3m)\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m https://semver.org\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m ○ \u001b[1mOther\u001b[22m\u001b[2;3m\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m Custom versioning scheme of your choice.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m\u001b[36m❯\u001b[0m \u001b[32m●\u001b[0m Calendar Versioning (CalVer)\r\r\n\u001b[90m│\u001b[0m \u001b[2m○\u001b[0m \u001b[2mSemantic Versioning (SemVer)\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2m○\u001b[0m \u001b[2mOther\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mUse ⬆ and ⬇ to select your version scheme.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[22.885316, "o", "\u001b[20A\r\u001b[J\u001b[36m◆\u001b[0m Release versioning scheme (13/32)\r\r\n\u001b[90m│\u001b[0m \u001b[2mCalendar Versioning (CalVer)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m├\u001b[0m \u001b[1mEnvironment\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[36m◇\u001b[0m Timezone \u001b[2m(14/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mUTC\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mEtc/UTC\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mUTC\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mUse ⬆ and ⬇, or start typing to select the timezone for your project.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[22.885435, "o", "\u001b[8A\r\u001b[J\u001b[36m◆\u001b[0m Timezone (14/32)\r\r\n\u001b[90m│\u001b[0m \u001b[2mUTC\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[23.890858, "o", "\u001b[36m◇\u001b[0m Services \u001b[2m(15/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m\u001b[36m❯\u001b[0m \u001b[32m◼\u001b[0m ClamAV\r\r\n\u001b[90m│\u001b[0m \u001b[32m◼\u001b[0m Solr\r\r\n\u001b[90m│\u001b[0m \u001b[32m◼\u001b[0m Redis\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mUse ⬆, ⬇ and Space bar to select one or more services.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[24.8944, "o", "\u001b[8A\r\u001b[J\u001b[36m◆\u001b[0m Services (15/32)\r\r\n\u001b[90m│\u001b[0m \u001b[2mClamAV, Redis, Solr\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[36m◇\u001b[0m Development tools \u001b[2m(16/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m\u001b[36m❯\u001b[0m \u001b[32m◼\u001b[0m PHP CodeSniffer\r\r\n\u001b[90m│\u001b[0m \u001b[32m◼\u001b[0m PHPStan\r\r\n\u001b[90m│\u001b[0m \u001b[32m◼\u001b[0m Rector\r\r\n\u001b[90m│\u001b[0m \u001b[32m◼\u001b[0m ESLint\r\r\n\u001b[90m│\u001b[0m \u001b[32m◼\u001b[0m Stylelint\r\r\n\u001b[90m│\u001b[0m \u001b[32m◼\u001b[0m Jest\r\r\n\u001b[90m│\u001b[0m \u001b[32m◼\u001b[0m PHPUnit\r\r\n\u001b[90m│\u001b[0m \u001b[32m◼\u001b[0m Behat\r\r\n\u001b[90m│\u001b[0m \u001b[32m◼\u001b[0m Twig CS Fixer\r\r\n\u001b[90m│\u001b[0m \u001b[32m◼\u001b[0m DCLint\r\r\n\u001b[90m│\u001b[0m \u001b[2m↓ 1 more\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mUse ⬆, ⬇ and Space bar to select one or more tools.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[25.898851, "o", "\u001b[17A\r\u001b[J\u001b[36m◆\u001b[0m Development tools (16/32)\r\r\n\u001b[90m│\u001b[0m \u001b[2mBehat, DCLint, ESLint, Hadolint, Jest, PHP CodeSniffer, PHPStan, PHPUnit,\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mRector, Stylelint, Twig CS Fixer\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m├\u001b[0m \u001b[1mHosting\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[36m◇\u001b[0m Hosting provider \u001b[2m(17/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2m○\u001b[0m \u001b[2mAcquia Cloud\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2m○\u001b[0m \u001b[2mLagoon\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2m○\u001b[0m \u001b[2mOther\u001b[0m\r\r\n\u001b[90m│\u001b[0m\u001b[36m❯\u001b[0m \u001b[32m●\u001b[0m None\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mUse ⬆, ⬇ and Space bar to select your hosting provider.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[26.902311, "o", "\u001b[9A\r\u001b[J\u001b[36m◆\u001b[0m Hosting provider (17/32)\r\r\n\u001b[90m│\u001b[0m \u001b[2mNone\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[36m◇\u001b[0m Custom web root directory \u001b[2m(18/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mweb\u001b[0m\u001b[36m█\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mCustom directory where the web server serves the site.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[27.906089, "o", "\u001b[6A\r\u001b[J\u001b[36m◆\u001b[0m Custom web root directory (18/32)\r\r\n\u001b[90m│\u001b[0m \u001b[2mweb\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m├\u001b[0m \u001b[1mDeployment\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[36m◇\u001b[0m Deployment types \u001b[2m(19/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m\u001b[36m❯\u001b[0m \u001b[32m◻\u001b[0m Code artifact\r\r\n\u001b[90m│\u001b[0m \u001b[2m◻\u001b[0m \u001b[2mLagoon webhook\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[32m◼\u001b[0m Custom webhook\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mUse ⬆, ⬇ and Space bar to select one or more deployment types.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[28.910773, "o", "\u001b[8A\r\u001b[J\u001b[36m◆\u001b[0m Deployment types (19/32)\r\r\n\u001b[90m│\u001b[0m \u001b[2mCustom webhook\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m├\u001b[0m \u001b[1mWorkflow\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[36m◇\u001b[0m Provision type \u001b[2m(20/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3mProvisioning sets up the site in an environment using an already assembled\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3mcodebase.\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m ○ \u001b[1mImport from database dump\u001b[22m\u001b[2;3m\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m Provisions the site by importing a database dump\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m typically copied from production into lower\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m environments.\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m ○ \u001b[1mInstall from profile\u001b[22m\u001b[2;3m\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m Provisions the site by installing a fresh Drupal\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m site from a profile every time an environment is\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m created.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m\u001b[36m❯\u001b[0m \u001b[32m●\u001b[0m Import from database dump\r\r\n\u001b[9"] +[28.910802, "o", "0m│\u001b[0m \u001b[2m○\u001b["] +[28.910931, "o", "0m \u001b[2mInstall from profile\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mUse ⬆ and ⬇ to select the provision type.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[29.914567, "o", "\u001b[19A\r\u001b[J\u001b[36m◆\u001b[0m Provision type (20/32)\r\r\n\u001b[90m│\u001b[0m \u001b[2mImport from database dump\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[36m◇\u001b[0m Database source \u001b[2m(20.1)\u001b[0m\r\r\n\u001b[90m│\u001b[0m \r\r\n\u001b[90m│\u001b[0m \u001b[36m❯\u001b[0m \u001b[32m●\u001b[0m URL download\r\r\n\u001b[90m│\u001b[0m \u001b[2m○\u001b[0m \u001b[2mFTP download\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2m○\u001b[0m \u001b[2mAcquia backup\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2m○\u001b[0m \u001b[2mLagoon environment\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2m○\u001b[0m \u001b[2mContainer registry\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2m○\u001b[0m \u001b[2mS3 bucket\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2m○\u001b[0m \u001b[2mNone\u001b[0m\r\r\n\u001b[90m│\u001b[0m \r\r\n\u001b[90m│\u001b[0m \u001b[2mUse ⬆ and ⬇ to select the database fetch source.\u001b[0m\r\r\n\u001b[90m│\u001b[0m \r\r\n"] +[30.918629, "o", "\u001b[12A\r\u001b[J\u001b[90m│\u001b[0m \u001b[36m◆\u001b[0m Database source (20.1)\r\r\n\u001b[90m│\u001b[0m \u001b[2mURL download\u001b[0m\r\r\n\u001b[90m│\u001b[0m \r\r\n\u001b[36m◇\u001b[0m Use a second database for migrations? \u001b[2m(21/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2m○\u001b[0m \u001b[2mYes\u001b[0m \u001b[2m/\u001b[0m \u001b[32m●\u001b[0m No\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mAdds a second database service for Drupal migrations.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[31.923539, "o", "\u001b[6A\r\u001b[J\u001b[36m◆\u001b[0m Use a second database for migrations? (21/32)\r\r\n\u001b[90m│\u001b[0m \u001b[2mNo\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m├\u001b[0m \u001b[1mNotifications\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[36m◇\u001b[0m Notification channels \u001b[2m(22/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m\u001b[36m❯\u001b[0m \u001b[32m◼\u001b[0m Email\r\r\n\u001b[90m│\u001b[0m \u001b[2m◻\u001b[0m \u001b[2mGitHub\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2m◻\u001b[0m \u001b[2mJIRA\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2m◻\u001b[0m \u001b[2mNew Relic\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2m◻\u001b[0m \u001b[2mSlack\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2m◻\u001b[0m \u001b[2mWebhook\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mUse ⬆, ⬇ and Space bar to select one or more notification channels.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[32.926586, "o", "\u001b[11A\r\u001b[J\u001b[36m◆\u001b[0m Notification channels (22/32)\r\r\n\u001b[90m│\u001b[0m \u001b[2mEmail\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m├\u001b[0m \u001b[1mContinuous Integration\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[36m◇\u001b[0m Continuous Integration provider \u001b[2m(23/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m\u001b[36m❯\u001b[0m \u001b[32m●\u001b[0m GitHub Actions\r\r\n\u001b[90m│\u001b[0m \u001b[2m○\u001b[0m \u001b[2mCircleCI\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2m○\u001b[0m \u001b[2mNone\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mUse ⬆ and ⬇ to select the CI provider.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[33.933241, "o", "\u001b[8A\r\u001b[J\u001b[36m◆\u001b[0m Continuous Integration provider (23/32)\r\r\n\u001b[90m│\u001b[0m \u001b[2mGitHub Actions\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[36m◇\u001b[0m Visual regression testing with Diffy? \u001b[2m(24/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3mDiffy-powered visual regression workflow to compare deployed environments.\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3mAutomatically triggers comparisons for dependency-update pull requests\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3mmatching the configured branch pattern (`deps/*` by default).\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3mRuns comparisons for pull requests tagged with the `VR` label and posts a\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3msticky comment.\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3mAlso supports manual runs against any URL.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2m○\u001b[0m \u001b[2mYes\u001b[0m \u001b[2m/\u001b[0m \u001b[32m●\u001b[0m No\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mRequires a Diffy account.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[33.933343, "o", "\u001b[15A\r\u001b[J\u001b[36m◆\u001b[0m Visual regression testing with Diffy? (24/32)\r\r\n\u001b[90m│\u001b[0m \u001b[2mNo\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[34.937999, "o", "\u001b[36m◇\u001b[0m Scan for committed secrets with Gitleaks? \u001b[2m(25/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[32m●\u001b[0m Yes \u001b[2m/\u001b[0m \u001b[2m○\u001b[0m \u001b[2mNo\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mRuns in CI to detect hardcoded passwords, API keys and tokens.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[35.940716, "o", "\u001b[6A\r\u001b[J\u001b[36m◆\u001b[0m Scan for committed secrets with Gitleaks? (25/32)\r\r\n\u001b[90m│\u001b[0m \u001b[2mYes\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m├\u001b[0m \u001b[1mAutomations\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[36m◇\u001b[0m Dependency updates provider \u001b[2m(26/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m\u001b[36m❯\u001b[0m \u001b[32m●\u001b[0m Renovate GitHub app\r\r\n\u001b[90m│\u001b[0m \u001b[2m○\u001b[0m \u001b[2mRenovate self-hosted in CI\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2m○\u001b[0m \u001b[2mNone\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mUse ⬆ and ⬇ to select the dependency updates provider.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[36.944127, "o", "\u001b[8A\r\u001b[J\u001b[36m◆\u001b[0m Dependency updates provider (26/32)\r\r\n\u001b[90m│\u001b[0m \u001b[2mRenovate GitHub app\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[36m◇\u001b[0m Auto-merge dependency updates \u001b[2m(26.1)\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3mPull requests in the selected groups are merged as soon as they meet the\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3mbranch protection rules. Pull requests in other groups need a manual\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3mmerge.\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3m\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3mRequires \"Allow auto-merge\" in the repository settings and at least one\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2;3mrequired status check on the base branch.\u001b[0m\r\r\n\u001b[90m│\u001b[0m \r\r\n\u001b[90m│\u001b[0m \u001b[36m❯\u001b[0m \u001b[32m◼\u001b[0m PHP packages, except Drupal core (minor and patch)\r\r\n\u001b[90m│\u001b[0m \u001b[32m◼\u001b[0m Drupal core (minor and patch)\r\r\n\u001b[90m│\u001b[0m \u001b[32m◼\u001b[0m JavaScript packages (minor and patch)\r\r\n\u001b[90m│\u001b[0m \u001b[32m◼\u001b[0m Container images (major, minor and patch)\r\r\n\u001b[90m│\u001b[0m \u001b[32m◼\u001b[0m CI "] +[36.944173, "o", "tools (major, mi"] +[36.94423, "o", "nor and patch)\r\r\n\u001b[90m│\u001b[0m \u001b[32m◼\u001b[0m GitHub Actions (major, minor and patch)\r\r\n\u001b[90m│\u001b[0m \r\r\n\u001b[90m│\u001b[0m \u001b[2mUse ⬆, ⬇ and Space bar to select one or more groups.\u001b[0m\r\r\n\u001b[90m│\u001b[0m \r\r\n"] +[37.948256, "o", "\u001b[17A\r\u001b[J\u001b[90m│\u001b[0m \u001b[36m◆\u001b[0m Auto-merge dependency updates (26.1)\r\r\n\u001b[90m│\u001b[0m \u001b[2mPHP packages, except Drupal core (minor and patch), Drupal core (minor and\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mpatch), JavaScript packages (minor and patch), Container images (major,\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mminor and patch), CI tools (major, minor and patch), GitHub Actions\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2m(major, minor and patch)\u001b[0m\r\r\n\u001b[90m│\u001b[0m \r\r\n\u001b[36m◇\u001b[0m Code coverage provider \u001b[2m(27/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2m○\u001b[0m \u001b[2mCodecov\u001b[0m\r\r\n\u001b[90m│\u001b[0m\u001b[36m❯\u001b[0m \u001b[32m●\u001b[0m None\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mUse ⬆ and ⬇ to select the code coverage provider.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[38.952398, "o", "\u001b[7A\r\u001b[J\u001b[36m◆\u001b[0m Code coverage provider (27/32)\r\r\n\u001b[90m│\u001b[0m \u001b[2mNone\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[36m◇\u001b[0m Auto-assign the author to their PR? \u001b[2m(28/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[32m●\u001b[0m Yes \u001b[2m/\u001b[0m \u001b[2m○\u001b[0m \u001b[2mNo\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mHelps to keep the PRs organized.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[39.956459, "o", "\u001b[6A\r\u001b[J\u001b[36m◆\u001b[0m Auto-assign the author to their PR? (28/32)\r\r\n\u001b[90m│\u001b[0m \u001b[2mYes\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[36m◇\u001b[0m Auto-add a CONFLICT label to a PR when conflicts occur? \u001b[2m(29/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[32m●\u001b[0m Yes \u001b[2m/\u001b[0m \u001b[2m○\u001b[0m \u001b[2mNo\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mHelps to keep quickly identify PRs that need attention.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[40.960517, "o", "\u001b[6A\r\u001b[J\u001b[36m◆\u001b[0m Auto-add a CONFLICT label to a PR when conflicts occur? (29/32)\r\r\n\u001b[90m│\u001b[0m \u001b[2mYes\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m├\u001b[0m \u001b[1mDocumentation\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[36m◇\u001b[0m Preserve project documentation? \u001b[2m(30/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[32m●\u001b[0m Yes \u001b[2m/\u001b[0m \u001b[2m○\u001b[0m \u001b[2mNo\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mHelps to maintain the project documentation within the repository.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[40.960739, "o", "\u001b[6A\r\u001b[J\u001b[36m◆\u001b[0m Preserve project documentation? (30/32)\r\r\n\u001b[90m│\u001b[0m \u001b[2mYes\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[41.964993, "o", "\u001b[90m├\u001b[0m \u001b[1mAI\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[36m◇\u001b[0m Provide AI agent instructions? \u001b[2m(31/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[32m●\u001b[0m Yes \u001b[2m/\u001b[0m \u001b[2m○\u001b[0m \u001b[2mNo\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mProvides AI coding agents with better context about the project.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[41.96519, "o", "\u001b[6A\r\u001b[J\u001b[36m◆\u001b[0m Provide AI agent instructions? (31/32)\r\r\n\u001b[90m│\u001b[0m \u001b[2mYes\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[42.969564, "o", "\u001b[36m◇\u001b[0m Configure AI code review with CodeRabbit? \u001b[2m(32/32)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2m○\u001b[0m \u001b[2mYes\u001b[0m \u001b[2m/\u001b[0m \u001b[32m●\u001b[0m No\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mRequires the CodeRabbit app on the repository.\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[43.973082, "o", "\u001b[6A\r\u001b[J\u001b[36m◆\u001b[0m Configure AI code review with CodeRabbit? (32/32)\r\r\n\u001b[90m│\u001b[0m \u001b[2mNo\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[?25h\u001b[34m●\u001b[0m \u001b[34mInstallation summary\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m┌───────────────────────────────────────────────────────────────────────────┐\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[1mGeneral information\u001b[0m \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m├──────────────────────────────────┬────────────────────────────────────────┤\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m Site name \u001b[90m│\u001b[0m Star Wars \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m Site machine name \u001b[90m│\u001b[0m sta"] +[43.973341, "o", "r_wars "] +[43.973619, "o", " \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m Organization name \u001b[90m│\u001b[0m Rebellion \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m Organization machine name \u001b[90m│\u001b[0m rebellion \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m Public domain \u001b[90m│\u001b[0m star-wars.com \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m├──────────────────────────────────┴────────────────────────────────────────┤\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[1mDrupal\u001b[0m \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m├──────────────────────────────────┬───────────────────────────────"] +[43.973829, "o", "──"] +[43.974057, "o", "───────┤\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m Starter \u001b[90m│\u001b[0m load_demodb \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m Modules \u001b[90m│\u001b[0m coffee, config_split, config_update, \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[90m│\u001b[0m devel, diff, drupal_helpers, \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[90m│\u001b[0m entity_usage, environment_indicator, \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[90m│\u001b[0m fast_404, field_group, \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[90m│\u001b[0m generated_content, gin, linkit, \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[90m│\u001b[0m menu_trail_by_path, metatag, \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[90m│\u001b[0m navigation_extra_tools, pathaut"] +[43.974317, "o", "o, "] +[43.974476, "o", "\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[90m│\u001b[0m redirect, reroute_email, robotstxt, \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[90m│\u001b[0m scheduled_transitions, schema_metatag, \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[90m│\u001b[0m sdc_devel, seckit, shield, \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[90m│\u001b[0m stage_file_proxy, testmode, \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[90m│\u001b[0m views_bulk_operations, xmlsitemap \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m Webroot \u001b[90m│\u001b[0m web \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m Profile \u001b[90m│\u001b[0m standard \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m Module prefix \u001b[90m│\u001b[0m sw \u001b[90m│"] +[43.974996, "o", "\u001b[0m\r\r\n\u001b["] +[43.975988, "o", "90m│\u001b[0m \u001b[90m│\u001b[0m Custom modules \u001b[90m│\u001b[0m base, search, demo \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m Theme machine name \u001b[90m│\u001b[0m star_wars \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m Build front-end in container \u001b[90m│\u001b[0m Yes \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m Storybook component library \u001b[90m│\u001b[0m No \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m├──────────────────────────────────┴────────────────────────────────────────┤\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[1mCode repository\u001b[0m \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m├──────────────────────────────────┬───"] +[43.976249, "o", "──"] +[43.976415, "o", "───────────────────────────────────┤\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m Code provider \u001b[90m│\u001b[0m github \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m Version scheme \u001b[90m│\u001b[0m calver \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m├──────────────────────────────────┴────────────────────────────────────────┤\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[1mEnvironment\u001b[0m \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m├──────────────────────────────────┬────────────────────────────────────────┤\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[9"] +[43.976728, "o", "0m│\u001b["] +[43.976893, "o", "0m Timezone \u001b[90m│\u001b[0m UTC \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m Services \u001b[90m│\u001b[0m clamav, redis, solr \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m Tools \u001b[90m│\u001b[0m behat, dclint, eslint, hadolint, jest, \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[90m│\u001b[0m phpcs, phpstan, phpunit, rector, \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[90m│\u001b[0m stylelint, twig_cs_fixer \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m├──────────────────────────────────┴────────────────────────────────────────┤\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[1mHosting\u001b[0m \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m├───"] +[43.977123, "o", "──"] +[43.977417, "o", "─────────────────────────────┬────────────────────────────────────────┤\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m Hosting provider \u001b[90m│\u001b[0m none \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m├──────────────────────────────────┴────────────────────────────────────────┤\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[1mDeployment\u001b[0m \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m├──────────────────────────────────┬────────────────────────────────────────┤\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m Deployment t"] +[43.977423, "o", "ypes "] +[43.977558, "o", " \u001b[90m│\u001b[0m webhook \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m├──────────────────────────────────┴────────────────────────────────────────┤\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[1mWorkflow\u001b[0m \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m├──────────────────────────────────┬────────────────────────────────────────┤\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m Provision type \u001b[90m│\u001b[0m database \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m Database source \u001b[90m│\u001b[0m url \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m Migration database "] +[43.977564, "o", " "] +[43.977684, "o", " \u001b[90m│\u001b[0m No \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m├──────────────────────────────────┴────────────────────────────────────────┤\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[1mNotifications\u001b[0m \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m├──────────────────────────────────┬────────────────────────────────────────┤\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m Channels \u001b[90m│\u001b[0m email \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m├──────────────────────────────────┴────────────────────"] +[43.977718, "o", "──"] +[43.977844, "o", "──────────────────┤\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[1mContinuous Integration\u001b[0m \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m├──────────────────────────────────┬────────────────────────────────────────┤\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m CI provider \u001b[90m│\u001b[0m gha \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m Visual regression testing \u001b[90m│\u001b[0m No \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m Secret scanning with Gitleaks \u001b[90m│\u001b[0m Yes \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m├──────────────────────────────────┴───────────────────────"] +[43.97787, "o", "───"] +[43.977972, "o", "──────────────┤\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[1mAutomations\u001b[0m \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m├──────────────────────────────────┬────────────────────────────────────────┤\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m Dependency updates provider \u001b[90m│\u001b[0m renovatebot_app \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m Auto-merge dependency updates \u001b[90m│\u001b[0m php, drupal_core, js, \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[90m│\u001b[0m container_images, ci_tools, \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[90m│\u001b[0m github_actions \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m Code coverage provider \u001b[90m│\u001b[0m none "] +[43.977984, "o", " "] +[43.978096, "o", " \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m Auto-assign PR author \u001b[90m│\u001b[0m Yes \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m Auto-add a CONFLICT label to PRs \u001b[90m│\u001b[0m Yes \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m├──────────────────────────────────┴────────────────────────────────────────┤\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[1mDocumentation\u001b[0m \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m├──────────────────────────────────┬────────────────────────────────────────┤\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m Preserve project documentation \u001b[90m│\u001b[0m Yes "] +[43.978112, "o", " "] +[43.978211, "o", " \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m├──────────────────────────────────┴────────────────────────────────────────┤\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[1mAI\u001b[0m \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m├──────────────────────────────────┬────────────────────────────────────────┤\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m AI agent instructions \u001b[90m│\u001b[0m Yes \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m AI code review \u001b[90m│\u001b[0m No \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m├────────────────────────────"] +[43.978218, "o", "──"] +[43.978322, "o", "────┴────────────────────────────────────────┤\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[1mLocations\u001b[0m \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m├──────────────────────────────────┬────────────────────────────────────────┤\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m Current directory \u001b[90m│\u001b[0m /home/user/vortex/.artifa \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[90m│\u001b[0m cts/tmp/videos-workspace \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m Destination directory \u001b[90m│\u001b[0m /home/user/vortex/.artifa \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[90m│\u001b[0m cts/tmp/videos-workspace/star_wars \u001b[90m"] +[43.978351, "o", "│\u001b[0"] +[43.978416, "o", "m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m Vortex repository \u001b[90m│\u001b[0m /home/user/vortex \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m Vortex reference \u001b[90m│\u001b[0m HEAD \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m└──────────────────────────────────┴────────────────────────────────────────┘\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[43.981795, "o", " Vortex will be installed into your project's directory \"/home/user/demo/star_wars\"\r\r\n"] +[43.996492, "o", "\u001b[?25l"] +[43.996573, "o", "\u001b[36m◇\u001b[0m Proceed with installing Vortex?\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[32m●\u001b[0m Yes \u001b[2m/\u001b[0m \u001b[2m○\u001b[0m \u001b[2mNo\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[45.997971, "o", "\u001b[4A\r\u001b[J\u001b[36m◆\u001b[0m Proceed with installing Vortex?\r\r\n\u001b[90m│\u001b[0m \u001b[2mYes\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[?25h\u001b[34m●\u001b[0m \u001b[34mStarting project installation\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[36m◇\u001b[0m Downloading Vortex\r\r\n\u001b[90m│\u001b[0m \u001b[2mDownloading from \"/home/user/vortex\" repository at ref \"HEAD\"\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[32m✓ Vortex downloaded (develop)\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[36m◇\u001b[0m Customizing Vortex for your project\r\r\n\u001b[90m│\u001b[0m \u001b[32m✓ Vortex was customized for your project\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[36m◇\u001b[0m Preparing destination directory\r\r\n\u001b[90m│\u001b[0m \u001b[2mCreated directory\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2m\"/home/user/demo/star_wars\".\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mInitializing a new Git repository in directory\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2m\"/home/user/demo/star_wars\".\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[32m✓ Destination directory is ready\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[36m◇\u001b[0m Copying files to the destination directory\r\r\n\u001b[90m"] +[45.99798, "o", "│\u001b[0m \u001b[32m✓ Fi"] +[45.998097, "o", "les copied to destination directory\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[36m◇\u001b[0m Preparing demo content\r\r\n"] +[46.699309, "o", "\u001b[90m│\u001b[0m \u001b[2mCreated data directory\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2m\"/home/user/demo/star_wars/.\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mdata\".\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mNo database dump file was found in\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2m\"/home/user/demo/star_wars/.\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mdata\" directory.\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mFetched demo database from\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mhttps://github.com/drevops/vortex/releases/download/1.40.0/db.demo.sql.\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[32m✓ Demo content prepared\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[46.699997, "o", "\u001b[90m│\u001b[0m \u001b[90m┌────────────────────────────────────────────────┐\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[1mFinished installing Vortex\u001b[0m \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[90m──────────────────────────\u001b[0m \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m Add and commit all files: \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m git add -A \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m git commit -m \"Initial commit.\" \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m Files: 402 added \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m Status and diff of every file are recorded in: \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m .logs/vortex-install-2026-11-11-060826"] +[46.700043, "o", ".md \u001b["] +[46.700134, "o", "90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m└────────────────────────────────────────────────┘\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[46.716138, "o", "\u001b[?25l"] +[46.716285, "o", "\u001b[36m◇\u001b[0m Run the site build now?\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2m○\u001b[0m \u001b[2mYes\u001b[0m \u001b[2m/\u001b[0m \u001b[32m●\u001b[0m No\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mTakes ~5-10 min; output will be streamed. You can skip and run later with:\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[2mahoy build\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[48.720564, "o", "\u001b[7A\r\u001b[J\u001b[36m◆\u001b[0m Run the site build now?\r\r\n\u001b[90m│\u001b[0m \u001b[2mNo\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n\u001b[?25h\u001b[90m│\u001b[0m \u001b[90m┌───────────────────────────────────────────────────────────────────────────┐\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[1mReady to build\u001b[0m \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[90m──────────────\u001b[0m \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m Build the site: \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m ahoy build \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m Setup GitHub Action"] +[48.720571, "o", "s: "] +[48.720667, "o", " \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m https://www.vortextemplate.com/docs/continuous-integration/github-actio \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m ns#onboarding \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m│\u001b[0m \u001b[90m│\u001b[0m\r\r\n\u001b[90m│\u001b[0m \u001b[90m└───────────────────────────────────────────────────────────────────────────┘\u001b[0m\r\r\n\u001b[90m│\u001b[0m\r\r\n"] +[48.730226, "x", "0"] diff --git a/.vortex/docs/static/img/installer.png b/.vortex/docs/static/img/installer.png index 4655073e4c..5941af63c5 100644 Binary files a/.vortex/docs/static/img/installer.png and b/.vortex/docs/static/img/installer.png differ diff --git a/.vortex/docs/static/img/installer.svg b/.vortex/docs/static/img/installer.svg index d3b74eada5..f7f1b9ff69 100644 --- a/.vortex/docs/static/img/installer.svg +++ b/.vortex/docs/static/img/installer.svg @@ -1 +1 @@ -──────────────────────────────────────────────────────────────────────────────██╗██╗██████╗██████╗████████╗███████╗██╗██╗██║██║██╔═══██╗██╔══██╗╚══██╔══╝██╔════╝╚██╗██╔╝██║██║██║██║██████╔╝██║█████╗╚███╔╝╚██╗██╔╝██║██║██╔══██╗██║██╔══╝██╔██╗╚████╔╝╚██████╔╝██║██║██║███████╗██╔╝██╗╚═══╝╚═════╝╚═╝╚═╝╚═╝╚══════╝╚═╝╚═╝DrupalprojecttemplatebyDrevOpsInstallerversion:development┌───────────────────────────────────────────────────────────────────────┐│WelcometotheVortexinteractiveinstaller││───────────────────────────────────────────││││Thistoolwillguideyouthroughinstallingthelatestdevelopment││versionofVortexintoyourproject.│││Youwillbeaskedafewquestionstotailortheconfigurationtoyour││site.││Nochangeswillbemadeuntilyouconfirmeverythingattheend.││PressCtrl+Catanytimetoexittheinstaller.││PressCtrl+Uatanytimetogobacktothepreviousstep.│└────────────────────────────────────────────└───────────────────────────────────────────────└───────────────────────────────────────────────────────────────────────┘✦ValidatingrepositoryandreferenceCheckingrepository"/home/user/vortex"andreference"HEAD"✓RepositoryandreferencevalidatedsuccessfullyPressanykeytocontinue... General information ┌Sitename(1/41)────────────────────────────────────────────┐└──────────────────────────────────────────────────────────────┘Wewillusethisnameintheprojectanddocumentation.│E.g.MySite│└──────────────────────────────────│St ┌Sitename(1/41)────────────────────────────────────────────┐│StarWars││star_wars │┌Sitemachinename(2/41)────────────────────────────────────┐│star_wars│┌Organizationname(3/41)────────────────────────────────────┐│E.g.MyOrg││Re │┌Organizationname(3/41)────────────────────────────────────┐│Rebellion│┌Organizationmachinename(4/41)────────────────────────────┐│rebellion │Wewillusethisnameinthecode.┌Organizationmachinename(4/41)────────────────────────────┐│rebellion│┌Publicdomain(5/41)────────────────────────────────────────┐│star-wars.com │┌Publicdomain(5/41)────────────────────────────────────────┐│star-wars.com│ Drupal ┌Howwouldyoulikeyoursitetobecreatedonthefirstrun?(6/41)┐│││Choosehowyoursitewillbecreatedthefirsttimeafterthis││installerfinishes:││○Drupal,installedfromprofile││Createsanewsitebypopulatingafreshdatabase││fromoneofthestandardDrupalinstallationprofiles.││○DrupalCMS,installedfromprofile││fromtheDrupalCMSrecipe.││○Drupal,loadedfromthedemodatabase││Createsasitebyloadinganexistingdemodatabase││providedwiththeinstaller.│├─────────────────────────────────────────────────────────────────────┤│○Drupal,installedfromprofile││○DrupalCMS,installedfromprofile││›●Drupal,loadedfromthedemodatabase│└─────────────────────────────────────────────────────────────────────┘┌Howwouldyoulikeyoursitetobecreatedonthefirstrun?(6/41)┐│○DrupalCMS,installedfromprofile│Drupal,loadedfromthedemodatabase│Drupal,loadedfromthedemodatabase│┌Profile(7/41)──────────────────────────────────────────────┐│Standard│┌Modules(8/41)──────────────────────────────────────────────┐│›◼Coffee┃││◼Configsplit│││◼Configupdate│││◼Devel│││◼Drupalhelpers│││◼Environmentindicator│││◼Fast404│││◼Generatedcontent│││◼Navigationextratools│││◼Pathauto││┌Modules(8/41)──────────────────────────────────────────────┐│Coffee││Configsplit││Configupdate││Devel││Drupalhelpers││Environmentindicator││Fast404││Generatedcontent││Navigationextratools││Pathauto││Redirect││Rerouteemail││Robots.txt││SDCDevel││Seckit││Shield││Stagefileproxy││Testmode││XMLSitemap│┌Custommodulesprefix(9/41)────────────────────────────────┐│sw│┌Custommodules(10/41)─────────────────────────────────────────────┐│Selectwhichcustommodulestoincludeinyourproject:││○Base││Startermodulewithcommonsiteutilities(mailhandling,││deployhooks)andtestscaffoldingforUnit,Kernel,││Functional,andFunctionalJavascripttests.││○Search││CustomSolrsearchintegrationmodule.RequirestheSolr││servicetobeselected.││○Demo││DemonstrateshowVortextoolingworks:includesacounter││blockwithCSS/JS,PHPUnitexampletestsacrossalltest││types,andaBehatfeature.Safetoremoveonrealprojects.│├─────────────────────────────────────────┌Custommodules(10/41)────────────────────────────────────────────┐│││Selectwhichcustommodulestoincludeinyourproject:││○Base││Startermodulewithcommonsiteutilities(mailhandling,││deployhooks)andtestscaffoldingforUnit,Kernel,││Functional,andFunctionalJavascripttests.││○Search││CustomSolrsearchintegrationmodule.RequirestheSolr││servicetobeselected.││○Demo││DemonstrateshowVortextoolingworks:includesacounter││blockwithCSS/JS,PHPUnitexampletestsacrossalltest││types,andaBehatfeature.Safetoremoveonrealprojects.│├────────────────────────────────────────────────────────────────────┤│Base-startermodulewithutilitiesandtestscaffolding││Search-customSolrsearchintegration││Demo-counterblockandexampleteststodemonstratetooling│└────────────────────────────────────────────────────────────────────┘┌Theme(11/41)───────────────────────────────────────────────┐│Custom(nextprompt)│┌Customthememachinename(12/41)───────────────────────────┐┌Customthememachinename(12/41)───────────────────────────┐┌Buildfront-endassetsinthecontainer?(13/41)────────────┐│●Yes/○No│Disabletobuildthemeassetsonthehostoraspartofdeployment.┌Buildfront-endassetsinthecontainer?(13/41)────────────┐│Yes│┌Storybookcomponentlibrary?(14/41)────────────────────────┐│││Componentlibraryforthecustomtheme,renderedbyDrupal││itself.││StoriesareauthoredinTwignexttoeachcomponent,sothe││libraryshowsthesamemarkupthesiterenders.││Adevelopmentserverrunsondemandwith`ahoystorybook`.A││staticbuildisproducedduringprovisioningandservedat││`/storybook`inlocal,CIanddevelopmentenvironments.│├──────────────────────────────────────────────────────────────┤│○Yes/●No│└───────────────────────────────┌Storybookcomponentlibrary?(14/41)────────────────────────┐│No│ Code repository ┌Repositoryprovider(15/41)─────────────────────────────────┐│VortexoffersfullautomationwithGitHub,whilesupportfor││otherprovidersislimited.││›●GitHub││○Other│○Other│┌Repositoryprovider(15/41)─────────────────────────────────┐│GitHub│┌Releaseversioningscheme(16/41)───────────────────────────┐│Chooseyourversioningscheme:││○CalendarVersioning(CalVer)││year.month.patch(E.g.,24.1.0)││https://calver.org││○SemanticVersioning(SemVer)││major.minor.patch(E.g.,1.0.0)│major.minor.patch(E.g.,1.0.0)││https://semver.org││○Other││Customversioningschemeofyourchoice.││›●CalendarVersioning(CalVer)││○SemanticVersioning(SemVer)│┌Releaseversioningscheme(16/41)───────────────────────────┐│CalendarVersioning(CalVer)│ Environment ┌Timezone(17/41)────────────────────────────────────────────┐│UTC│┌Services(18/41)────────────────────────────────────────────┐│ClamAV││Solr││Redis│┌Developmenttools(19/41)───────────────────────────────────┐│›◼PHPCodeSniffer┃││◼PHPStan│││◼Rector│││◼ESLint│││◼Stylelint│││◼Jest│││◼PHPUnit┌Developmenttools(19/41)───────────────────────────────────┐│PHPCodeSniffer││PHPStan││Rector││ESLint││Stylelint││Jest││PHPUnit││Behat││TwigCSFixer││DCLint││Hadolint│ Hosting │›●None│┌Hostingprovider(20/41)────────────────────────────────────┐│None│┌Customwebrootdirectory(21/41)───────────────────────────┐│web │┌Customwebrootdirectory(21/41)───────────────────────────┐│web│ Deployment ┌Deploymenttypes(22/41)────────────────────────────────────┐│›◻Codeartifact││◻Lagoonwebhook││◼Customwebhook┌Deploymenttypes(22/41)────────────────────────────────────┐│Customwebhook│ Workflow ┌Provisiontype(23/41)──────────────────────────────────────┐│Provisioningsetsupthesiteinanenvironmentusingan││alreadyassembledcodebase.││○Importfromdatabasedump││Provisionsthesitebyimportingadatabasedump││typicallycopiedfromproductionintolower││environments.││○Installfromprofile││ProvisionsthesitebyinstallingafreshDrupal││sitefromaprofileeverytimeanenvironmentis││created.│┌Provisiontype(23/41)──────────────────────────────────────┐│created.│Importfromdatabasedump│┌Databasesource(24/41)─────────────────────────────────────┐│›●URLdownload││○FTPdownload│○None│┌Databasesource(24/41)─────────────────────────────────────┐│URLdownload│┌Useaseconddatabaseformigrations?(25/41)───────────────┐ Notifications ┌Notificationchannels(26/41)───────────────────────────────┐│›◼Email││◻GitHub││◻JIRA│┌Notificationchannels(26/41)───────────────────────────────┐│Email│ Continuous Integration ┌ContinuousIntegrationprovider(27/41)─────────────────────┐│›●GitHubActions││○CircleCI││○None┌ContinuousIntegrationprovider(27/41)─────────────────────┐│GitHubActions│┌VisualregressiontestingwithDiffy?(28/41)───────────────┐│Diffy-poweredvisualregressionworkflowtocomparedeployed││environments.││Automaticallytriggerscomparisonsfordependency-update││pullrequestsmatchingtheconfiguredbranchpattern││(`deps/*`bydefault).││Runscomparisonsforpullrequeststaggedwiththe`VR`││labelandpostsastickycomment.││AlsosupportsmanualrunsagainstanyURL.│┌VisualregressiontestingwithDiffy?(28/41)───────────────┐┌ScanforcommittedsecretswithGitleaks?(29/41)───────────┐ Automations ┌Dependencyupdatesprovider(30/41)─────────────────────────┐│RenovateGitHubapp│┌Auto-mergedependencyupdates(31/41)───────────────────────┐│Pullrequestsintheselectedgroupsaremergedassoonas││theymeetthebranchprotectionrules.Pullrequestsin││othergroupsneedamanualmerge.││Requires"Allowauto-merge"intherepositorysettingsand││atleastonerequiredstatuscheckonthebasebranch.│┌Auto-mergedependencyupdates(31/41)───────────────────────┐│PHPpackages,exceptDrupalcore(minorandpatch)││Drupalcore(minorandpatch)││JavaScriptpackages(minorandpatch)││Containerimages(major,minorandpatch)││CItools(major,minorandpatch)││GitHubActions(major,minorandpatch)│┌Codecoverageprovider(32/41)──────────────────────────────┐┌Auto-assigntheauthortotheirPR?(33/41)─────────────────┐└─────────────────────────────────────────────────────────────────┘┌Auto-addaCONFLICTlabeltoaPRwhenconflictsoccur?(34/41)┐│Yes│ Documentation ┌Preserveprojectdocumentation?(35/41)─────────────────────┐┌Preserveprojectdocumentation?(35/41)─────────────────────┐ AI ┌ProvideAIagentinstructions?(36/41)──────────────────────┐┌ProvideAIagentinstructions?(36/41)──────────────────────┐ Installation summary ┌────────────────────────────────────┬────────────────────────────────────┐│Generalinformation│││Sitename│StarWars││Sitemachinename│star_wars││Organizationname│Rebellion││Organizationmachinename│rebellion││Publicdomain│star-wars.com││Drupal│││Starter│load_demodb││Modules│coffee,config_split,│││config_update,devel,│││drupal_helpers,│││environment_indicator,fast_404,│││generated_content,│││navigation_extra_tools,pathauto,│││redirect,reroute_email,│││robotstxt,sdc_devel,seckit,│││shield,stage_file_proxy,│││testmode,xmlsitemap││Webroot│web││Profile│standard││Moduleprefix│sw││Custommodules│base,search,demo││Thememachinename│star_wars││Buildfront-endincontainer│Yes││Storybookcomponentlibrary│No││Coderepository│││Codeprovider│github││Versionscheme│calver││Environment│││Timezone│UTC││Services│clamav,redis,solr││Tools│behat,dclint,eslint,hadolint,│││jest,phpcs,phpstan,phpunit,│││rector,stylelint,twig_cs_fixer││Hosting│││Hostingprovider│none││Deployment│││Deploymenttypes│webhook│Deploymenttypes│webhook││Workflow│││Provisiontype│database││Databasesource│url││Migrationdatabase│No││Notifications│││Channels│email││ContinuousIntegration│││CIprovider│gha││Visualregressiontesting│No││SecretscanningwithGitleaks│Yes││Automations│││Dependencyupdatesprovider│renovatebot_app││Auto-mergedependencyupdates│php,drupal_core,js,│││container_images,ci_tools,│││github_actions││Codecoverageprovider│none││Auto-assignPRauthor│Yes││Auto-addaCONFLICTlabeltoPRs│Yes││Documentation│││Preserveprojectdocumentation│Yes││AI│││AIagentinstructions│Yes│AIagentinstructions│Yes││Locations│││Currentdirectory│/home/user/vortex/.ar│││tifacts/tmp/videos-workspace││Destinationdirectory│/home/user/vortex/.ar│││tifacts/tmp/videos-workspace/star_│││wars││Vortexrepository│/home/user/vortex││Vortexreference│HEAD│└────────────────────────────────────┴────────────────────────────────────┘Vortexwillbeinstalledintoyourproject'sdirectory"/home/user/demo/star_wars"┌ProceedwithinstallingVortex?─────────────────────────────┐ Starting project installation ✦DownloadingVortexDownloadingfrom"/home/user/vortex"repositoryatref✓Vortexdownloaded(develop)✦CustomizingVortexforyourproject✓Vortexwascustomizedforyourproject✦PreparingdestinationdirectoryCreateddirectory"/home/user/demo/star_wars".InitializinganewGitrepositoryindirectory"/home/user/demo/star_wars".✓Destinationdirectoryisready✦Copyingfilestothedestinationdirectory✓Filescopiedtodestinationdirectory⠂Preparingdemocontent⠒Preparingdemocontent✦PreparingdemocontentCreateddatadirectory"/home/user/demo/star_wars/.data".Nodatabasedumpfilewasfoundin"/home/user/demo/star_wars/.data"directory.Fetcheddemodatabasefromhttps://github.com/drevops/vortex/releases/download/1.40.0/db.demo.sql.✓Democontentprepared┌───────────────────────────────────┐│FinishedinstallingVortex││──────────────────────────││││Addandcommitallfiles:││gitadd-A││gitcommit-m"Initialcommit."│└───────────────────────────────────┘┌Runthesitebuildnow?─────────────────────────────────────┐┌────────────────────────────────────────────────────────────────────────────┐│Readytobuild││──────────────││││Buildthesite:││ahoybuild│╚████╔╝╚██████╔╝██║██║╚████╔╝╚██████╔╝██║██║██⠂Validatingrepositoryandreference│starwars │└────────────────────────────────────│St ││StarWars │┌Sitemachinename(2/41)────────────────────────────────────┐Wewillusethisnamefortheprojectdirectoryandinthecode.│StarWarsOrg │└─────└─────────│Rebellion │WewillusethisnameinthecoDomainnamewithoutproDomainnamewithoutprotocolandDomainnamewithoutprotocolandtrailingslash.│Createsasitebyloadin│Createsasitebyloadinganexist└────────────────────────────────────────────────────────────└──────────────────────────────────────────────────────────────Use⬆and⬇.Appliesonlyonthefirstrunoftheinstaller.┌Profile(7/41)──────────────────────────────────────────────┐│›●Standard││○Minimal││○DemoUmami││○Custom(nextprompt)│Use⬆and⬇toselectwhichDrupalprofiletouse.│◼Configupda│◼Configupdate└───────────────────────└──────────────────────────│XMLSi│XMLSitemap│s│sw├──────────────────────────────────────│›◼Base-startermodulewithutilitiesandtestscaffolding││◼Search-customSolrsearchintegration││◼Demo-counterblockandexampleteststodemonstratetooling│Use⬆,⬇andSpacebartoselectoneormoremodules.├───────────────────────────────────────────├──────────────────────────────────────────────┌Theme(11/41)───────────────────────────────────────────────┐│○Olivero││○Claro││○Stark││›●Custom(nextprompt)│Use⬆and⬇toselectwhichDrupalthemetouse.WewilluseWewillusethisnamWewillusethisnameasacustomthemename│Storiesareauthor│StoriesareauthoredinTwig│Adevelopmentserv│AdevelopmentserverrunsondUse⬆and⬇toselectyourcoderepositoryprovider.└────────────────────────────────────────────────────└───────────────────────────────────────────────────────Use⬆and⬇toselectyourversionscheme.┌Timezone(17/41)┌Timezone(17/41)────│◼PHPUnit│││◼Behat│││◼TwigCSFixer│││◼DCLint││└─────────────────────────────────────────────────11selected┘Use⬆,⬇andSpacebartoselectoneormoretools.┌Hostingprovider(20/41)────────────────────────────────────┐│○AcquiaCloud││○Lagoon│Use⬆,⬇andSpacebartoselectyourhostingprovider.CustomdirectorywherethewebseCustomdirectorywherethewebserverservCustomdirectorywherethewebserverservesthesite.│◼Customwebhook│Use⬆,⬇andSpacebartoselectoneormoredeploymenttypes.├─├────│Provisioningsetsupthesiteinane│Provisioningsetsupthesiteinanenvironment│○FTPdownload││○Acquiabackup││○Lagoonenvironment││○Containerregistry││○S3bucket│Use⬆and⬇toselectthedatabasefetchsource.┌Useaseconddatabaseformigrations?(25/41)───────────────┐AddsaseconddatabaseserviceforDrupalmigrations.│◻NewRelic││◻Slack││◻Webhook│Use⬆,⬇andSpacebartoselectoneormorenotificationchannels.Use⬆and⬇toselecttheCIprovider.│Automaticallytrig│Automaticallytriggerscompar│○Yes/│○Yes/●└────────────────────────────└─────────────────────────────────────────│Ren│RenovateGitHub├─────────────────────────────────────│›◼PHPpackages,exceptDrupalcore(minorandpatch)││◼Drupalcore(minorandpatch)││◼JavaScriptpackages(minorandpatch)││◼Containerimages(major,minorandpatch)││◼CItools(major,minorandpatch)││◼GitHubActions(major,minorandpatch)│Use⬆,⬇andSpacebartoselectoneormoregroups.├────────────────────────────────────├───────────────────────────────────────┌Codecoverageprovider(32/41)──────────────────────────────┐│○Codecov│Use⬆and⬇toselectthecodecoverageprovider.┌Auto-assigntheauthortotheirPR?(33/41)─────────────────┐HelpstokeepthePRsorganized.┌Auto-addaCONFLICTlabeltoaPRwhenconflictsoccur?(34/41)┐│●Yes/○No│HelpstokeepquicklyidentifyPRsthatneedattention.HelpstomaintaintheprojectdocumentationHelpstomaintaintheprojectdocumentationwithintheHelpstomaintaintheprojectdocumentationwithintherepository.ProvidesAIcodingagentsProvidesAIcodingagentswithbetterProvidesAIcodingagentswithbettercontextabouttheproject.│Modules│cof│Modules│coffee,co││robotstxt,sdc_deve││robotstxt,sdc_devel,seck│Buildf│Buildfront-end│Services││Services│clamav┌ProceedwithinstallingVortex?─────────────────────────────┐⠂CustomizingVortexforyourproject⠒Custo✓Filescopied⠐Preparingdemocontent⠰Preparingdemocontent⠠Preparingdemocontent⠤Preparingdemocontent⠄Preparingdemocontent⠆Preparingdemocontent┌Runthesitebuildnow?─────────────────────────────────────┐Takes~5-10min;outputwillbestreamed.Youcanskipandrunlaterwith…│SetupGitHubActions:││https://www.vortextemplate.com/docs/continuous-integration/github-actions#││onboarding│└────────────────────────────────────────────────────────────────────────────┘ \ No newline at end of file +──────────────────────────────────────────────────────────────────────────────██╗██╗██████╗██████╗████████╗███████╗██╗██╗██║██║██╔═══██╗██╔══██╗╚══██╔══╝██╔════╝╚██╗██╔╝██║██║██║██║██████╔╝██║█████╗╚███╔╝╚██╗██╔╝██║██║██╔══██╗██║██╔══╝██╔██╗╚████╔╝╚██████╔╝██║██║██║███████╗██╔╝██╗╚═══╝╚═════╝╚═╝╚═╝╚═╝╚══════╝╚═╝╚═╝DrupalprojecttemplatebyDrevOpsInstallerversion:development│┌───────────────────────────────────────────────────────────────────────────┐││WelcometotheVortexinteractiveinstaller│││───────────────────────────────────────────│││Thistoolwillguideyouthroughinstallingthelatestdevelopment│││versionofVortexintoyourproject.││││││Youwillbeaskedafewquestionstotailortheconfigurationtoyour│││site.│││Nochangeswillbemadeuntilyouconfirmeverythingattheend.│││PressCtrl+Catanytimetoexittheinstaller.│││PressCtrl+Uatanytimetogobacktothepreviousstep.││└───────────────────────────────────────────────────────────────────────────┘│◇Validatingrepositoryandreference│Checkingrepository"/home/user/vortex"andreference"HEAD"│✓Repositoryandreferencevalidatedsuccessfully┌Generalinformation◇Sitename(1/32)│Wewillusethisnameintheprojectanddocumentation.│star█│E.g.MySite█│Wewillu│StarWar█◆Sitename(1/32)│StarWars◆Sitemachinename(2/32)│star_wars◇Organizationname(3/32)◇O│E.g.MyOrg█│E.g.MyO│Rebel█◆Organizationname(3/32)│Rebellion◆Organizationmachinename(4/32)│rebellion◆Publicdomain(5/32)│star-wars.com├Drupal◇Howwouldyoulikeyoursitetobecreatedonthefirstrun?(6/32)│Choosehowyoursitewillbecreatedthefirsttimeafterthisinstaller│finishes:│○Drupal,installedfromprofile│Createsanewsitebypopulatingafreshdatabase│fromoneofthestandardDrupalinstallationprofiles.│○DrupalCMS,installedfromprofile│fromtheDrupalCMSrecipe.│○Drupal,loadedfromthedemodatabase◆Howwouldyoulikeyoursitetobecreatedonthefirstrun?(6/32)│Drupal,loadedfromthedemodatabase◆Profile(7/32)│Standard◇Modules(8/32)│❯◼Coffee│◼Configsplit│◼Configupdate│◼Devel│◼Diff│◼Drupalhelpers│◼Entityusage│◼Environmentindicator◆Modules(8/32)│Coffee,Configsplit,Configupdate,Devel,Diff,Drupalhelpers,Entity│usage,Environmentindicator,Fast404,Fieldgroup,Generatedcontent,Gin│admintheme,Linkit,Menutrailbypath,Metatag,Navigationextratools,│Pathauto,Redirect,Rerouteemail,Robots.txt,Scheduledtransitions,│Schema.orgMetatag,SDCDevel,Seckit,Shield,Stagefileproxy,Testmode,│Viewsbulkoperations,XMLSitemap◆Custommodulesprefix(9/32)│sw◇Custommodules(10/32)│Selectwhichcustommodulestoincludeinyourproject:│○Base│Startermodulewithdeployhooksandtestscaffoldingfor│Unit,Kernel,Functional,andFunctionalJavascripttests.│○Search│CustomSolrsearchintegrationmodule.RequirestheSolr│servicetobeselected.│○Demo│DemonstrateshowVortextoolingworks:includesacounter│blockwithCSS/JS,PHPUnitexampletestsacrossalltest│types,andaBehatfeature.Safetoremoveonrealprojects.│❯◼Base-startermodulewithutilitiesandtestscaffolding│◼Search-customSolrsearchintegration◆Custommodules(10/32)│Base-startermodulewithutilitiesandtestscaffolding,Search-custom│Solrsearchintegration,Demo-counterblockandexampleteststo│demonstratetooling◆Theme(11/32)│Custom(nextprompt)│││◇Customthememachinename(11.1)│◆Customthememachinename(11.1)││star_wars│◆Buildfront-endassetsinthecontainer?(11.2)││Yes│◇Storybookcomponentlibrary?(11.3)│Componentlibraryforthecustomtheme,renderedbyDrupalitself.│StoriesareauthoredinTwignexttoeachcomponent,sothelibraryshows│thesamemarkupthesiterenders.│◆Storybookcomponentlibrary?(11.3)│No├Coderepository◆Repositoryprovider(12/32)│GitHub◇Releaseversioningscheme(13/32)│Chooseyourversioningscheme:│○CalendarVersioning(CalVer)│year.month.patch(E.g.,24.1.0)│https://calver.org│○Other◆Releaseversioningscheme(13/32)│CalendarVersioning(CalVer)├Environment│UTC◆Timezone(14/32)◆Services(15/32)│ClamAV,Redis,Solr◆Developmenttools(16/32)│Behat,DCLint,ESLint,Hadolint,Jest,PHPCodeSniffer,PHPStan,PHPUnit,│Rector,Stylelint,TwigCSFixer├Hosting│❯●None◆Hostingprovider(17/32)│None◆Customwebrootdirectory(18/32)│web├Deployment◆Deploymenttypes(19/32)│Customwebhook├Workflow◇Provisiontype(20/32)│Provisioningsetsupthesiteinanenvironmentusinganalreadyassembled│codebase.│○Importfromdatabasedump│Provisionsthesitebyimportingadatabasedump│typicallycopiedfromproductionintolower│environments.│○Installfromprofile│ProvisionsthesitebyinstallingafreshDrupal│sitefromaprofileeverytimeanenvironmentis│created.│❯●Importfromdatabasedump◆Provisiontype(20/32)│Importfromdatabasedump│◆Databasesource(20.1)│URLdownload│○Yes/●No◆Useaseconddatabaseformigrations?(21/32)│No├Notifications◆Notificationchannels(22/32)│Email├ContinuousIntegration│○None◆ContinuousIntegrationprovider(23/32)│GitHubActions◆VisualregressiontestingwithDiffy?(24/32)│●Yes/○No◆ScanforcommittedsecretswithGitleaks?(25/32)│Yes├Automations◆Dependencyupdatesprovider(26/32)│RenovateGitHubapp│◇Auto-mergedependencyupdates(26.1)│Pullrequestsintheselectedgroupsaremergedassoonastheymeetthe│branchprotectionrules.Pullrequestsinothergroupsneedamanual│merge.│Requires"Allowauto-merge"intherepositorysettingsandatleastone│requiredstatuscheckonthebasebranch.│❯◼PHPpackages,exceptDrupalcore(minorandpatch)│◼Drupalcore(minorandpatch)│◼JavaScriptpackages(minorandpatch)│◼Containerimages(major,minorandpatch)│◆Auto-mergedependencyupdates(26.1)│PHPpackages,exceptDrupalcore(minorandpatch),Drupalcore(minorand│patch),JavaScriptpackages(minorandpatch),Containerimages(major,│minorandpatch),CItools(major,minorandpatch),GitHubActions│(major,minorandpatch)◆Codecoverageprovider(27/32)◆Auto-assigntheauthortotheirPR?(28/32)◆Auto-addaCONFLICTlabeltoaPRwhenconflictsoccur?(29/32)├Documentation◆Preserveprojectdocumentation?(30/32)├AI◆ProvideAIagentinstructions?(31/32)◆ConfigureAIcodereviewwithCodeRabbit?(32/32)●Installationsummary││Generalinformation││├──────────────────────────────────┬────────────────────────────────────────┤││Sitename│StarWars│││Sitemachinename│star_wars│││Organizationname│Rebellion│││Organizationmachinename│rebellion│││Publicdomain│star-wars.com││├──────────────────────────────────┴────────────────────────────────────────┤││Drupal│││Starter│load_demodb│││Modules│coffee,config_split,config_update,││││devel,diff,drupal_helpers,││││entity_usage,environment_indicator,││││fast_404,field_group,││││generated_content,gin,linkit,││││menu_trail_by_path,metatag,││││navigation_extra_tools,pathauto,││││redirect,reroute_email,robotstxt,││││scheduled_transitions,schema_metatag,││││sdc_devel,seckit,shield,││││stage_file_proxy,testmode,││││views_bulk_operations,xmlsitemap│││Webroot│web│││Profile│standard│││Moduleprefix│sw│││Custommodules│base,search,demo│││Thememachinename│star_wars│││Buildfront-endincontainer│Yes│││Storybookcomponentlibrary│No│││Coderepository│││Codeprovider│github│││Versionscheme│calver│││Environment│││Timezone│UTC│││Services│clamav,redis,solr│││Tools│behat,dclint,eslint,hadolint,jest,││││phpcs,phpstan,phpunit,rector,││││stylelint,twig_cs_fixer│││Hosting│││Hostingprovider│none│││Deployment│││Deploymenttypes│webhook│││Workflow│││Provisiontype│database│││Databasesource│url│││Migrationdatabase││Migrationdatabase│No│││Notifications│││Channels│email│││ContinuousIntegration│││CIprovider│gha│││Visualregressiontesting│No│││SecretscanningwithGitleaks│Yes│││Automations│││Dependencyupdatesprovider│renovatebot_app│││Auto-mergedependencyupdates│php,drupal_core,js,││││container_images,ci_tools,││││github_actions│││Codecoverageprovider│none││Codecoverageprovider│none│││Auto-assignPRauthor│Yes│││Auto-addaCONFLICTlabeltoPRs│Yes│││Documentation│││Preserveprojectdocumentation│Yes││Preserveprojectdocumentation│Yes│││AI│││AIagentinstructions│Yes│││AIcodereview│No│││Locations│││Currentdirectory│/home/user/vortex/.artifa││││cts/tmp/videos-workspace│││Destinationdirectory│/home/user/vortex/.artifa││││cts/tmp/videos-workspace/star_wars│││Vortexrepository│/home/user/vortex│││Vortexreference│HEAD││└──────────────────────────────────┴────────────────────────────────────────┘Vortexwillbeinstalledintoyourproject'sdirectory"/home/user/demo/star_wars"◆ProceedwithinstallingVortex?●Startingprojectinstallation◇DownloadingVortex│Downloadingfrom"/home/user/vortex"repositoryatref"HEAD"│✓Vortexdownloaded(develop)◇CustomizingVortexforyourproject│✓Vortexwascustomizedforyourproject◇Preparingdestinationdirectory│Createddirectory│"/home/user/demo/star_wars".│InitializinganewGitrepositoryindirectory│✓Destinationdirectoryisready◇Copyingfilestothedestinationdirectory│✓Filescopiedtodestinationdirectory◇Preparingdemocontent│Createddatadirectory│"/home/user/demo/star_wars/.│data".│Nodatabasedumpfilewasfoundin│data"directory.│Fetcheddemodatabasefrom│https://github.com/drevops/vortex/releases/download/1.40.0/db.demo.sql.│✓Democontentprepared│┌────────────────────────────────────────────────┐││FinishedinstallingVortex│││──────────────────────────│││Addandcommitallfiles:│││gitadd-A│││gitcommit-m"Initialcommit."││││││Files:402added│││Statusanddiffofeveryfilearerecordedin:│││.logs/vortex-install-2026-11-11-060826.md││└────────────────────────────────────────────────┘◆Runthesitebuildnow?││Readytobuild│││──────────────│││Buildthesite:│││ahoybuild│╚████╔╝╚██████╔╝██║██║██║╚████╔╝╚██████╔╝██║██║██║█││Youwillbeaskedafewquestionstotailorthec││Youwillbeaskedafewquestionstotailortheconfigu◇Pressanykeytocontinue...│starwars█│Wewilluse│Wewillusethisnameintheprojectan│We│S█│St█│Sta█│Star█│Star█│StarW█│StarWa█│StarWars█◇Sitemachinename(2/32)│star_wars█│Wewillusethisnamefortheprojectdirectoryandinthecode.│StarWarsOrg█│StarWar│Wewillusethisnamei│Wewillusethisnameintheprojectanddocumentat│E.g.MyOrg│Wewilluseth│Rebell█◆Organization◇Publicdomain(5/32)│star-wars.com█│Domainnamewithoutprotocolandtrailingslash.│Createsasitebyloadinganexistingdemodatabase│providedwiththeinstaller.│○Drupal,installedfromprofile│○DrupalCMS,installedfromprofile│❯●Drupal,loadedfromthedemodatabase│Use⬆and⬇.Appliesonlyonthefirstrunoftheinstaller.│◼│◼Fast404│◼Fieldgroup│↓19more│Use⬆,⬇andSpacebartoselectoneormoremodules.│◼Demo││star_wars█││Wewillusethisnameasacustomthemename│thesamemarkupthesite│Adevelopmentserverrunsondemandwith`ahoystorybook`.Astaticbuild│isproducedduringprovisioningandservedat`/storybook`inlocal,CI│anddevelopmentenvironments.│○Yes/●No│AddsStorybookpackagestothethemeandasteptoprovisioning.│○SemanticVersioning(SemVer)│major.minor.patch(E.g.,1.0.0)│https://semver.org│○Other│Customversioningschemeofyourchoice.│❯●CalendarVersioning(CalVer)│○SemanticVersioning(SemVer)│Use⬆and⬇toselectyourversionscheme.◇Timezone(14/32)│UTC█│Etc/UTC│Use⬆and⬇,orstarttypingtoselectthetimezoneforyourproject.◇Services(15/32)│❯◼ClamAV│◼Solr│◼Redis│Use⬆,⬇andSpacebartoselectoneormoreservices.◇Developmenttools(16/32)│❯◼PHPCodeSniffer│◼PHPStan│◼Rector│◼ESLint│◼Stylelint│◼Jest│◼PHPUnit│◼Behat│◼TwigCSFixer│◼DCLint│↓1more│Use⬆,⬇andSpacebartoselectoneormoretools.◇Hostingprovider(17/32)│○AcquiaCloud│○Lagoon│Use⬆,⬇andSpacebartoselectyourhostingprovider.◇Customwebrootdirectory(18/32)│web█│Customdirectorywherethewebserverservesthesite.◇Deploymenttypes(19/32)│❯◻Codeartifact│◻Lagoonwebhook│◼Customwebhook│Use⬆,⬇andSpacebartoselectoneormoredeploymenttypes.│○│○Installfromprofile│Use⬆and⬇toselecttheprovisiontype.│◇Databasesource(20.1)│❯●URLdownload│○FTPdownload│○Acquiabackup│○Lagoonenvironment│○Containerregistry│○S3bucket│○None│Use⬆and⬇toselectthedatabasefetchsource.◇Useaseconddatabaseformigrations?(21/32)│AddsaseconddatabaseserviceforDrupalmigrations.◇Notificationchannels(22/32)│❯◼Email│◻GitHub│◻JIRA│◻NewRelic│◻Slack│◻Webhook│Use⬆,⬇andSpacebartoselectoneormorenotificationchannels.◇ContinuousIntegrationprovider(23/32)│❯●GitHubActions│○CircleCI│Use⬆and⬇toselecttheCIprovider.◇VisualregressiontestingwithDiffy?(24/32)│Diffy-poweredvisualregressionworkflowtocomparedeployedenvironments.│Automaticallytriggerscomparisonsfordependency-updatepullrequests│matchingtheconfiguredbranchpattern(`deps/*`bydefault).│Runscomparisonsforpullrequeststaggedwiththe`VR`labelandpostsa│stickycomment.│AlsosupportsmanualrunsagainstanyURL.│RequiresaDiffyaccount.◇ScanforcommittedsecretswithGitleaks?(25/32)│RunsinCItodetecthardcodedpasswords,APIkeysandtokens.◇Dependencyupdatesprovider(26/32)│❯●RenovateGitHubapp│○Renovateself-hostedinCI│Use⬆and⬇toselectthedependencyupdatesprovider.│◼CI│◼CItools(major,mi│◼CItools(major,minorandpatch)│◼GitHubActions(major,minorandpatch)│Use⬆,⬇andSpacebartoselectoneormoregroups.◇Codecoverageprovider(27/32)│○Codecov│Use⬆and⬇toselectthecodecoverageprovider.◇Auto-assigntheauthortotheirPR?(28/32)│HelpstokeepthePRsorganized.◇Auto-addaCONFLICTlabeltoaPRwhenconflictsoccur?(29/32)│HelpstokeepquicklyidentifyPRsthatneedattention.◇Preserveprojectdocumentation?(30/32)│Helpstomaintaintheprojectdocumentationwithintherepository.◇ProvideAIagentinstructions?(31/32)│ProvidesAIcodingagentswithbettercontextabouttheproject.◇ConfigureAIcodereviewwithCodeRabbit?(32/32)│RequirestheCodeRabbitappontherepository.││Sitemachinename│sta││Sitemachinename│star_wars│├──────────────────────────────────┬───────────────────────────────│├──────────────────────────────────┬─────────────────────────────────│││navigation_extra_tools,pathaut│││navigation_extra_tools,pathauto,│├──────────────────────────────────┬───│├──────────────────────────────────┬─────│├───│├─────││Deploymentt││Deploymenttypes│├──────────────────────────────────┴────────────────────│├──────────────────────────────────┴──────────────────────│├──────────────────────────────────┴───────────────────────│├──────────────────────────────────┴──────────────────────────│├────────────────────────────│├──────────────────────────────│││cts/tmp/videos-workspace/star_wars◇ProceedwithinstallingVortex?│✓Fi││.logs/vortex-install-2026-11-11-060826││.logs/vortex-install-2026-11-11-060826.md◇Runthesitebuildnow?│Takes~5-10min;outputwillbestreamed.Youcanskipandrunlaterwith:│ahoybuild││SetupGitHubAction││SetupGitHubActions:││SetupGitHubActions:│││https://www.vortextemplate.com/docs/continuous-integration/github-actio│││ns#onboarding│ \ No newline at end of file diff --git a/.vortex/installer/CLAUDE.md b/.vortex/installer/CLAUDE.md index 28c992921c..e639f43d58 100644 --- a/.vortex/installer/CLAUDE.md +++ b/.vortex/installer/CLAUDE.md @@ -65,8 +65,8 @@ permission before running. Triggers that require re-recording: - New `Handlers/*.php` class or handler removal. - Wording change to `label()` or `hint()` of any existing handler. -- Adding, removing or reordering prompts inside - `PromptManager::runPrompts()`, which also moves the progress denominator. +- Adding, removing or reordering prompts in the `PromptManager::runPrompts()` + chain, which also changes the step count in each label. ## Conditional Token System @@ -133,9 +133,14 @@ Content removed if feature not selected ### Ordering -`PromptManager::runPrompts()` is the catalogue of prompts: the `form()` -chain lists every prompt, in order, under its section heading. Add a new -prompt there, and the progress denominator follows automatically. +`PromptManager::runPrompts()` declares the whole prompt flow as 1 +`Prompty::flow()` chain: each `->section()` heading, then its handlers in +order with `->add()`. A prompt whose `shouldRun()` reads another prompt's +answer goes between `->children()` and `->end()` under that prompt, so it is +asked as a nested step. The chain holds structure only: each handler is a +Prompty step, so its `shouldRun()` decides whether it is asked and its +label, options and default decide what it shows. Add a new prompt to the +chain, and the step count follows automatically. Processing runs in a different order, so each handler declares its own `processWeight()` - lowest first, broadly the reverse of the prompt order so @@ -174,97 +179,3 @@ Each handler has dedicated test class extending Structure: each `dataProvider*` sits immediately after the test it feeds; helper methods go last. - -## Patches - -The installer applies a single patch to `laravel/prompts` via -`cweagans/composer-patches` v2 to add three behaviors it depends on. - -### Patch location - -- File: `patches/laravel-prompts.patch` -- Registered in: `composer.json` under `extra.patches` -- Lockfile: `patches.lock.json` (regenerated by composer-patches; do not - hand-edit) - -### What the patch adds - -1. **`description` field on every Prompt class and renderer**. A new - `RendersDescription` trait under - `vendor/laravel/prompts/src/Themes/Default/Concerns/` renders a - description block inside the prompt frame. `PromptManager::runPrompts()` - threads `$handler->description($responses)` into `$args['description']` - for every handler that returns a non-null description. -2. **`Prompt::validateUsing(?Closure $callback)` accepts null**, so - `tests/Traits/TuiTrait.php::tuiTeardown()` can clear the validator - between tests. -3. **The static `validateUsing` callback runs before the instance - `validate` closure and receives `$value`**. `TuiTrait::tuiSetUp()` uses - this to intercept every prompt's validation and throw `RuntimeException` - on failure, so non-interactive tests fail fast instead of hanging - waiting for user input. - -The patch also includes a small `Concerns/TypedValue.php` tweak -(`strlen($default) > 0` → truthy check); not exercised directly by the -installer. - -### Re-roll procedure - -Whenever the `laravel/prompts` version in `composer.json` is bumped -(Renovate PR or manual update), the patch must be re-rolled because the -description trait touches renderers that frequently change between -releases. - -```bash -# 1. After bumping the version in .vortex/installer/composer.json, try the -# existing patch first. -composer --working-dir .vortex/installer update laravel/prompts --with-dependencies -rm -f ~/Library/Caches/composer/patches/*.patch # macOS cache path -rm -f ~/.cache/composer/patches/*.patch # Linux cache path -composer --working-dir .vortex/installer patches-relock -composer --working-dir .vortex/installer patches-repatch -``` - -If `patches-repatch` succeeds, jump to the verify step. - -If it fails (`No available patcher was able to apply patch`), the patch -conflicts with the new upstream and needs editing: - -```bash -# 2. Extract the new upstream source for editing. -git clone https://github.com/laravel/prompts.git /tmp/prompts-upstream -git -C /tmp/prompts-upstream checkout v -cp -R /tmp/prompts-upstream/src /tmp/upstream-pristine-src - -# 3. Apply the three changes to /tmp/prompts-upstream/src using -# .vortex/installer/patches/laravel-prompts.patch as reference: -# a) Re-introduce the RendersDescription trait and thread `description` -# through every Prompt constructor + matching renderer. -# b) Update Prompt::validateUsing() signature to `?Closure $callback`. -# c) Swap the match arms in Prompt::validate() so the static validator -# runs first and receives $value as the second argument. - -# 4. Regenerate the unified diff against the pristine upstream copy. -diff -ruN /tmp/upstream-pristine-src /tmp/prompts-upstream/src > /tmp/raw.patch - -# 5. Re-root paths to `a/src/...` / `b/src/...` and strip timestamps using -# the committed helper. -php .vortex/installer/patches/reroot-patch.php \ - /tmp/raw.patch \ - .vortex/installer/patches/laravel-prompts.patch \ - /tmp/upstream-pristine-src/ \ - /tmp/prompts-upstream/src/ - -# 6. Refresh the lockfile and re-apply. -rm -f ~/Library/Caches/composer/patches/*.patch -rm -f ~/.cache/composer/patches/*.patch -composer --working-dir .vortex/installer patches-relock -composer --working-dir .vortex/installer patches-repatch -``` - -Verify: - -```bash -composer --working-dir .vortex/installer test -composer --working-dir .vortex/installer lint -``` diff --git a/.vortex/installer/composer.json b/.vortex/installer/composer.json index d7fc8521af..e2dd2995ce 100644 --- a/.vortex/installer/composer.json +++ b/.vortex/installer/composer.json @@ -19,12 +19,11 @@ "require": { "php": ">=8.3", "alexskrypnyk/file": "^1.3.0", + "alexskrypnyk/prompty": "dev-main", "alexskrypnyk/str2name": "^1.7.0", "composer/composer": "^2.11.1", - "cweagans/composer-patches": "^2", "czproject/git-php": "^4.6", "guzzlehttp/guzzle": "^8.3.1", - "laravel/prompts": "^0.3.27", "nelexa/zip": "^4.1.0", "nikic/iter": "^2.4.1", "sebastian/diff": "^7.0.1", @@ -41,12 +40,18 @@ "drupal/coder": "^9.0.1@alpha", "ergebnis/composer-normalize": "^2.56.0", "laravel/serializable-closure": "^2.1.0", - "mockery/mockery": "^1.6.15", "phpstan/phpstan": "^2.3.5", "phpunit/phpunit": "^12.5.43", "rector/rector": "^2.8.4", "symfony/finder": "^7.4.23" }, + "repositories": [ + { + "name": "prompty", + "type": "vcs", + "url": "https://github.com/AlexSkrypnyk/prompty" + } + ], "autoload": { "psr-4": { "DrevOps\\VortexInstaller\\": "src/" @@ -66,7 +71,6 @@ "config": { "allow-plugins": { "bamarni/composer-bin-plugin": true, - "cweagans/composer-patches": true, "dealerdirect/phpcodesniffer-composer-installer": true, "ergebnis/composer-normalize": true }, @@ -74,13 +78,6 @@ "process-timeout": 0, "sort-packages": true }, - "extra": { - "patches": { - "laravel/prompts": { - "Description support, nullable validateUsing, validator precedence, TypedValue truthy check": "patches/laravel-prompts.patch" - } - } - }, "scripts": { "build": [ "@composer bin box require --dev humbug/box", diff --git a/.vortex/installer/composer.lock b/.vortex/installer/composer.lock index 7b82b2787b..8b4f4ae3b9 100644 --- a/.vortex/installer/composer.lock +++ b/.vortex/installer/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "aabc2b6c653b67116031b3b78a5e505a", + "content-hash": "9c147eb0b284e96b6ec7a822122c3170", "packages": [ { "name": "alexskrypnyk/file", @@ -76,6 +76,98 @@ "time": "2026-10-21T12:43:31+00:00", "published-time": "2026-10-21T12:44:51+00:00" }, + { + "name": "alexskrypnyk/prompty", + "version": "dev-main", + "source": { + "type": "git", + "url": "https://github.com/AlexSkrypnyk/prompty.git", + "reference": "2d752ef89f6264b8ad60d900f69fdf8113d59807" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/AlexSkrypnyk/prompty/zipball/2d752ef89f6264b8ad60d900f69fdf8113d59807", + "reference": "2d752ef89f6264b8ad60d900f69fdf8113d59807", + "shasum": "" + }, + "require": { + "php": ">=8.3" + }, + "require-dev": { + "alexskrypnyk/phpunit-helpers": "^1.2.0", + "bamarni/composer-bin-plugin": "^1.9.1", + "dealerdirect/phpcodesniffer-composer-installer": "^1.2.1", + "drevops/phpcs-standard": "^1.1.0", + "drupal/coder": "^9.0.1", + "ergebnis/composer-normalize": "^2.52.0", + "opis/closure": "^4.5.0", + "phpstan/phpstan": "^2.2.8", + "phpunit/phpunit": "^12.5.43", + "rector/rector": "^2.6.2" + }, + "default-branch": true, + "type": "library", + "autoload": { + "classmap": [ + "Prompty.php", + "PromptyTestTrait.php" + ] + }, + "autoload-dev": { + "classmap": [ + "tests/phpunit" + ] + }, + "scripts": { + "lint": [ + "phpcs", + "phpstan", + "rector --dry-run", + "php .util/check-embed.php" + ], + "lint-fix": [ + "rector", + "phpcbf" + ], + "reset": [ + "rm -Rf vendor vendor-bin composer.lock" + ], + "test": [ + "phpunit --no-coverage" + ], + "test-coverage": [ + "phpunit" + ] + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Alex Skrypnyk", + "email": "prompty@alexskrypnyk.com", + "homepage": "https://alexskrypnyk.com", + "role": "Maintainer" + } + ], + "description": "Zero-dependency interactive CLI prompt library", + "homepage": "https://github.com/alexskrypnyk/prompty", + "support": { + "issues": "https://github.com/alexskrypnyk/prompty/issues", + "source": "https://github.com/alexskrypnyk/prompty" + }, + "funding": [ + { + "type": "github", + "url": "https://github.com/alexskrypnyk" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/alexskrypnyk" + } + ], + "time": "2026-11-11T05:49:04+00:00" + }, { "name": "alexskrypnyk/str2name", "version": "1.7.0", @@ -767,131 +859,6 @@ "time": "2024-05-06T16:37:16+00:00", "published-time": "2024-05-06T17:01:42+00:00" }, - { - "name": "cweagans/composer-configurable-plugin", - "version": "2.0.0", - "source": { - "type": "git", - "url": "https://github.com/cweagans/composer-configurable-plugin.git", - "reference": "15433906511a108a1806710e988629fd24b89974" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/cweagans/composer-configurable-plugin/zipball/15433906511a108a1806710e988629fd24b89974", - "reference": "15433906511a108a1806710e988629fd24b89974", - "shasum": "" - }, - "require": { - "php": ">=8.0.0" - }, - "require-dev": { - "codeception/codeception": "~4.0", - "codeception/module-asserts": "^2.0", - "composer/composer": "~2.0", - "php-coveralls/php-coveralls": "~2.0", - "php-parallel-lint/php-parallel-lint": "^1.0.0", - "phpro/grumphp": "^1.8.0", - "sebastian/phpcpd": "^6.0", - "squizlabs/php_codesniffer": "^3.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "cweagans\\Composer\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Cameron Eagans", - "email": "me@cweagans.net" - } - ], - "description": "Provides a lightweight configuration system for Composer plugins.", - "support": { - "issues": "https://github.com/cweagans/composer-configurable-plugin/issues", - "source": "https://github.com/cweagans/composer-configurable-plugin/tree/2.0.0" - }, - "funding": [ - { - "url": "https://github.com/cweagans", - "type": "github" - } - ], - "time": "2023-02-12T04:58:58+00:00", - "published-time": "2023-02-12T05:06:43+00:00" - }, - { - "name": "cweagans/composer-patches", - "version": "2.0.0", - "source": { - "type": "git", - "url": "https://github.com/cweagans/composer-patches.git", - "reference": "bfa6018a5f864653d9ed899b902ea72f858a2cf7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/cweagans/composer-patches/zipball/bfa6018a5f864653d9ed899b902ea72f858a2cf7", - "reference": "bfa6018a5f864653d9ed899b902ea72f858a2cf7", - "shasum": "" - }, - "require": { - "composer-plugin-api": "^2.0", - "cweagans/composer-configurable-plugin": "^2.0", - "ext-json": "*", - "php": ">=8.0.0" - }, - "require-dev": { - "codeception/codeception": "~4.0", - "codeception/module-asserts": "^2.0", - "codeception/module-cli": "^2.0", - "codeception/module-filesystem": "^2.0", - "composer/composer": "~2.0", - "php-coveralls/php-coveralls": "~2.0", - "php-parallel-lint/php-parallel-lint": "^1.0.0", - "phpro/grumphp": "^1.8.0", - "sebastian/phpcpd": "^6.0", - "squizlabs/php_codesniffer": "^4.0" - }, - "type": "composer-plugin", - "extra": { - "_": "The following two lines ensure that composer-patches is loaded as early as possible.", - "class": "cweagans\\Composer\\Plugin\\Patches", - "plugin-modifies-downloads": true, - "plugin-modifies-install-path": true - }, - "autoload": { - "psr-4": { - "cweagans\\Composer\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Cameron Eagans", - "email": "me@cweagans.net" - } - ], - "description": "Provides a way to patch Composer packages.", - "support": { - "issues": "https://github.com/cweagans/composer-patches/issues", - "source": "https://github.com/cweagans/composer-patches/tree/2.0.0" - }, - "funding": [ - { - "url": "https://github.com/cweagans", - "type": "github" - } - ], - "time": "2025-10-30T23:44:22+00:00", - "published-time": "2025-10-31T01:21:00+00:00" - }, { "name": "czproject/git-php", "version": "v4.6.0", @@ -1355,65 +1322,6 @@ "time": "2026-10-24T08:53:34+00:00", "published-time": "2026-10-24T08:53:38+00:00" }, - { - "name": "laravel/prompts", - "version": "v0.3.27", - "source": { - "type": "git", - "url": "https://github.com/laravel/prompts.git", - "reference": "abdfc75a1ae6c6f21522daed50da7124cbff09d2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laravel/prompts/zipball/abdfc75a1ae6c6f21522daed50da7124cbff09d2", - "reference": "abdfc75a1ae6c6f21522daed50da7124cbff09d2", - "shasum": "" - }, - "require": { - "composer-runtime-api": "^2.2", - "ext-mbstring": "*", - "php": "^8.1", - "symfony/console": "^6.2|^7.0|^8.0" - }, - "conflict": { - "illuminate/console": ">=10.17.0 <10.25.0", - "laravel/framework": ">=10.17.0 <10.25.0" - }, - "require-dev": { - "illuminate/collections": "^10.0|^11.0|^12.0|^13.0", - "mockery/mockery": "^1.5", - "pestphp/pest": "^2.3|^3.4|^4.0", - "phpstan/phpstan": "^1.12.28", - "phpstan/phpstan-mockery": "^1.1.3" - }, - "suggest": { - "ext-pcntl": "Required for the spinner to be animated." - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "0.3.x-dev" - } - }, - "autoload": { - "files": [ - "src/helpers.php" - ], - "psr-4": { - "Laravel\\Prompts\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Add beautiful and user-friendly forms to your command-line applications.", - "support": { - "source": "https://github.com/laravel/prompts/tree/v0.3.27" - }, - "time": "2026-11-09T16:07:10+00:00", - "published-time": "2026-11-09T16:09:07+00:00" - }, { "name": "marc-mabe/php-enum", "version": "v4.7.2", @@ -4498,62 +4406,6 @@ "time": "2026-09-24T19:42:52+00:00", "published-time": "2026-09-24T19:43:04+00:00" }, - { - "name": "hamcrest/hamcrest-php", - "version": "v3.0.0", - "source": { - "type": "git", - "url": "https://github.com/hamcrest/hamcrest-php.git", - "reference": "b61cd040da1a4925bc90a51c074f5297e7c0fa52" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/b61cd040da1a4925bc90a51c074f5297e7c0fa52", - "reference": "b61cd040da1a4925bc90a51c074f5297e7c0fa52", - "shasum": "" - }, - "require": { - "ext-ctype": "*", - "ext-dom": "*", - "php": "^7.4|^8.0" - }, - "replace": { - "cordoval/hamcrest-php": "*", - "davedevelopment/hamcrest-php": "*", - "kodova/hamcrest-php": "*" - }, - "require-dev": { - "phpstan/phpstan": "^2.1", - "phpstan/phpstan-phpunit": "^2.0", - "phpunit/php-file-iterator": "^1.4 || ^2.0 || ^3.0", - "phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5 || ^7.0 || ^8.0 || ^9.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "hamcrest" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "This is the PHP port of Hamcrest Matchers", - "keywords": [ - "test" - ], - "support": { - "issues": "https://github.com/hamcrest/hamcrest-php/issues", - "source": "https://github.com/hamcrest/hamcrest-php/tree/v3.0.0" - }, - "time": "2026-03-17T11:56:53+00:00", - "published-time": "2026-06-16T10:52:40+00:00" - }, { "name": "laravel/serializable-closure", "version": "v2.1.0", @@ -4672,89 +4524,6 @@ "time": "2025-08-30T09:44:18+00:00", "published-time": "2025-08-30T09:45:38+00:00" }, - { - "name": "mockery/mockery", - "version": "1.6.15", - "source": { - "type": "git", - "url": "https://github.com/mockery/mockery.git", - "reference": "967a801bd188989a5669bd280f252d51c0fdc9ee" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/mockery/mockery/zipball/967a801bd188989a5669bd280f252d51c0fdc9ee", - "reference": "967a801bd188989a5669bd280f252d51c0fdc9ee", - "shasum": "" - }, - "require": { - "hamcrest/hamcrest-php": "^2.0 || ^3.0", - "php": ">=7.3" - }, - "conflict": { - "phpunit/phpunit": "<8.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.6.36", - "symplify/easy-coding-standard": "^13.2.17" - }, - "type": "library", - "autoload": { - "files": [ - "library/helpers.php", - "library/Mockery.php" - ], - "psr-4": { - "Mockery\\": "library/Mockery" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Pádraic Brady", - "email": "padraic.brady@gmail.com", - "homepage": "https://github.com/padraic", - "role": "Author" - }, - { - "name": "Dave Marshall", - "email": "dave.marshall@atstsolutions.co.uk", - "homepage": "https://davedevelopment.co.uk", - "role": "Developer" - }, - { - "name": "Nathanael Esayeas", - "email": "nathanael.esayeas@protonmail.com", - "homepage": "https://github.com/ghostwriter", - "role": "Lead Developer" - } - ], - "description": "Mockery is a simple yet flexible PHP mock object framework", - "homepage": "https://github.com/mockery/mockery", - "keywords": [ - "BDD", - "TDD", - "library", - "mock", - "mock objects", - "mockery", - "stub", - "test", - "test double", - "testing" - ], - "support": { - "docs": "https://docs.mockery.io/", - "issues": "https://github.com/mockery/mockery/issues", - "rss": "https://github.com/mockery/mockery/releases.atom", - "security": "https://github.com/mockery/mockery/security/advisories", - "source": "https://github.com/mockery/mockery" - }, - "time": "2026-08-19T19:37:52+00:00", - "published-time": "2026-08-19T19:38:57+00:00" - }, { "name": "myclabs/deep-copy", "version": "1.14.0", @@ -6800,6 +6569,7 @@ "aliases": [], "minimum-stability": "stable", "stability-flags": { + "alexskrypnyk/prompty": 20, "drupal/coder": 15 }, "prefer-stable": false, diff --git a/.vortex/installer/patches.lock.json b/.vortex/installer/patches.lock.json deleted file mode 100644 index 1615cfa225..0000000000 --- a/.vortex/installer/patches.lock.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "_hash": "dc0fda737136aaf6161a15cbcdec116815593858abcbd6fa74deff274bcbec07", - "patches": { - "laravel/prompts": [ - { - "package": "laravel/prompts", - "description": "Description support, nullable validateUsing, validator precedence, TypedValue truthy check", - "url": "patches/laravel-prompts.patch", - "sha256": "6be6cb4d721c726074dbeb3e9b44ab03b2affaa6369d7e7115f6f5a6411c2046", - "depth": 1, - "extra": { - "provenance": "root" - } - } - ] - } -} diff --git a/.vortex/installer/patches/laravel-prompts.patch b/.vortex/installer/patches/laravel-prompts.patch deleted file mode 100644 index c05cf56417..0000000000 --- a/.vortex/installer/patches/laravel-prompts.patch +++ /dev/null @@ -1,1317 +0,0 @@ -diff -ruN a/src/AutoCompletePrompt.php b/src/AutoCompletePrompt.php ---- a/src/AutoCompletePrompt.php -+++ b/src/AutoCompletePrompt.php -@@ -39,6 +39,7 @@ - public mixed $validate = null, - public string $hint = '', - public ?Closure $transform = null, -+ public ?string $description = null, - ) { - $this->options = $options instanceof Collection ? $options->all() : $options; - -diff -ruN a/src/ConfirmPrompt.php b/src/ConfirmPrompt.php ---- a/src/ConfirmPrompt.php -+++ b/src/ConfirmPrompt.php -@@ -23,6 +23,7 @@ - public mixed $validate = null, - public string $hint = '', - public ?Closure $transform = null, -+ public ?string $description = null, - ) { - $this->confirmed = $default; - -diff -ruN a/src/FormBuilder.php b/src/FormBuilder.php ---- a/src/FormBuilder.php -+++ b/src/FormBuilder.php -@@ -88,7 +88,7 @@ - /** - * Prompt the user for text input. - */ -- public function text(string $label, string $placeholder = '', string $default = '', bool|string $required = false, mixed $validate = null, string $hint = '', ?string $name = null, ?Closure $transform = null): self -+ public function text(string $label, string $placeholder = '', string $default = '', bool|string $required = false, mixed $validate = null, string $hint = '', ?string $name = null, ?Closure $transform = null, ?string $description = null): self - { - return $this->runPrompt(text(...), get_defined_vars()); - } -@@ -96,7 +96,7 @@ - /** - * Prompt the user for multiline text input. - */ -- public function textarea(string $label, string $placeholder = '', string $default = '', bool|string $required = false, ?Closure $validate = null, string $hint = '', int $rows = 5, ?string $name = null, ?Closure $transform = null): self -+ public function textarea(string $label, string $placeholder = '', string $default = '', bool|string $required = false, ?Closure $validate = null, string $hint = '', int $rows = 5, ?string $name = null, ?Closure $transform = null, ?string $description = null): self - { - return $this->runPrompt(textarea(...), get_defined_vars()); - } -@@ -104,7 +104,7 @@ - /** - * Prompt the user for input, hiding the value. - */ -- public function password(string $label, string $placeholder = '', bool|string $required = false, mixed $validate = null, string $hint = '', ?string $name = null, ?Closure $transform = null): self -+ public function password(string $label, string $placeholder = '', bool|string $required = false, mixed $validate = null, string $hint = '', ?string $name = null, ?Closure $transform = null, ?string $description = null): self - { - return $this->runPrompt(password(...), get_defined_vars()); - } -@@ -115,7 +115,7 @@ - * @param array|Collection $options - * @param true|string $required - */ -- public function select(string $label, array|Collection $options, int|string|null $default = null, int $scroll = 5, mixed $validate = null, string $hint = '', bool|string $required = true, ?string $name = null, ?Closure $transform = null): self -+ public function select(string $label, array|Collection $options, int|string|null $default = null, int $scroll = 5, mixed $validate = null, string $hint = '', bool|string $required = true, ?string $name = null, ?Closure $transform = null, ?string $description = null): self - { - return $this->runPrompt(select(...), get_defined_vars()); - } -@@ -126,7 +126,7 @@ - * @param array|Collection $options - * @param array|Collection $default - */ -- public function multiselect(string $label, array|Collection $options, array|Collection $default = [], int $scroll = 5, bool|string $required = false, mixed $validate = null, string $hint = 'Use the space bar to select options.', ?string $name = null, ?Closure $transform = null): self -+ public function multiselect(string $label, array|Collection $options, array|Collection $default = [], int $scroll = 5, bool|string $required = false, mixed $validate = null, string $hint = 'Use the space bar to select options.', ?string $name = null, ?Closure $transform = null, ?string $description = null): self - { - return $this->runPrompt(multiselect(...), get_defined_vars()); - } -@@ -134,7 +134,7 @@ - /** - * Prompt the user to confirm an action. - */ -- public function confirm(string $label, bool $default = true, string $yes = 'Yes', string $no = 'No', bool|string $required = false, mixed $validate = null, string $hint = '', ?string $name = null, ?Closure $transform = null): self -+ public function confirm(string $label, bool $default = true, string $yes = 'Yes', string $no = 'No', bool|string $required = false, mixed $validate = null, string $hint = '', ?string $name = null, ?Closure $transform = null, ?string $description = null): self - { - return $this->runPrompt(confirm(...), get_defined_vars()); - } -@@ -152,7 +152,7 @@ - * - * @param array|Collection|Closure(string): array $options - */ -- public function suggest(string $label, array|Collection|Closure $options, string $placeholder = '', string $default = '', int $scroll = 5, bool|string $required = false, mixed $validate = null, string $hint = '', ?string $name = null, ?Closure $transform = null): self -+ public function suggest(string $label, array|Collection|Closure $options, string $placeholder = '', string $default = '', int $scroll = 5, bool|string $required = false, mixed $validate = null, string $hint = '', ?string $name = null, ?Closure $transform = null, ?string $description = null): self - { - return $this->runPrompt(suggest(...), get_defined_vars()); - } -@@ -163,7 +163,7 @@ - * @param Closure(string): array $options - * @param true|string $required - */ -- public function search(string $label, Closure $options, string $placeholder = '', int $scroll = 5, mixed $validate = null, string $hint = '', bool|string $required = true, ?string $name = null, ?Closure $transform = null): self -+ public function search(string $label, Closure $options, string $placeholder = '', int $scroll = 5, mixed $validate = null, string $hint = '', bool|string $required = true, ?string $name = null, ?Closure $transform = null, ?string $description = null): self - { - return $this->runPrompt(search(...), get_defined_vars()); - } -@@ -173,7 +173,7 @@ - * - * @param Closure(string): array $options - */ -- public function multisearch(string $label, Closure $options, string $placeholder = '', int $scroll = 5, bool|string $required = false, mixed $validate = null, string $hint = 'Use the space bar to select options.', ?string $name = null, ?Closure $transform = null): self -+ public function multisearch(string $label, Closure $options, string $placeholder = '', int $scroll = 5, bool|string $required = false, mixed $validate = null, string $hint = 'Use the space bar to select options.', ?string $name = null, ?Closure $transform = null, ?string $description = null): self - { - return $this->runPrompt(multisearch(...), get_defined_vars()); - } -diff -ruN a/src/MultiSearchPrompt.php b/src/MultiSearchPrompt.php ---- a/src/MultiSearchPrompt.php -+++ b/src/MultiSearchPrompt.php -@@ -46,6 +46,7 @@ - public string $hint = '', - public ?Closure $transform = null, - public string|Closure $info = '', -+ public ?string $description = null, - ) { - $this->trackTypedValue(submit: false, ignore: fn ($key) => Key::oneOf([Key::SPACE, Key::HOME, Key::END, Key::CTRL_A, Key::CTRL_E], $key) && $this->highlighted !== null); - -diff -ruN a/src/MultiSelectPrompt.php b/src/MultiSelectPrompt.php ---- a/src/MultiSelectPrompt.php -+++ b/src/MultiSelectPrompt.php -@@ -47,6 +47,7 @@ - public string $hint = '', - public ?Closure $transform = null, - public string|Closure $info = '', -+ public ?string $description = null, - ) { - $this->options = $options instanceof Collection ? $options->all() : $options; - $this->default = $default instanceof Collection ? $default->all() : $default; -diff -ruN a/src/NumberPrompt.php b/src/NumberPrompt.php ---- a/src/NumberPrompt.php -+++ b/src/NumberPrompt.php -@@ -23,6 +23,7 @@ - public ?int $min = null, - public ?int $max = null, - public ?int $step = null, -+ public ?string $description = null, - ) { - $this->trackTypedValue($default); - -diff -ruN a/src/PasswordPrompt.php b/src/PasswordPrompt.php ---- a/src/PasswordPrompt.php -+++ b/src/PasswordPrompt.php -@@ -18,6 +18,7 @@ - public mixed $validate = null, - public string $hint = '', - public ?Closure $transform = null, -+ public ?string $description = null, - ) { - $this->trackTypedValue(); - } -diff -ruN a/src/Prompt.php b/src/Prompt.php ---- a/src/Prompt.php -+++ b/src/Prompt.php -@@ -249,7 +249,7 @@ - /** - * Set the custom validation callback. - */ -- public static function validateUsing(Closure $callback): void -+ public static function validateUsing(?Closure $callback): void - { - static::$validateUsing = $callback; - } -@@ -403,8 +403,8 @@ - } - - $error = match (true) { -+ isset(static::$validateUsing) => (static::$validateUsing)($this, $value), - is_callable($this->validate) => ($this->validate)($value), -- isset(static::$validateUsing) => (static::$validateUsing)($this), - default => throw new RuntimeException('The validation logic is missing.'), - }; - -diff -ruN a/src/SearchPrompt.php b/src/SearchPrompt.php ---- a/src/SearchPrompt.php -+++ b/src/SearchPrompt.php -@@ -34,6 +34,7 @@ - public bool|string $required = true, - public ?Closure $transform = null, - public string|Closure $info = '', -+ public ?string $description = null, - ) { - if ($this->required === false) { - throw new InvalidArgumentException('Argument [required] must be true or a string.'); -diff -ruN a/src/SelectPrompt.php b/src/SelectPrompt.php ---- a/src/SelectPrompt.php -+++ b/src/SelectPrompt.php -@@ -33,6 +33,7 @@ - public bool|string $required = true, - public ?Closure $transform = null, - public string|Closure $info = '', -+ public ?string $description = null, - ) { - if ($this->required === false) { - throw new InvalidArgumentException('Argument [required] must be true or a string.'); -diff -ruN a/src/SuggestPrompt.php b/src/SuggestPrompt.php ---- a/src/SuggestPrompt.php -+++ b/src/SuggestPrompt.php -@@ -42,6 +42,7 @@ - public string $hint = '', - public ?Closure $transform = null, - public string|Closure $info = '', -+ public ?string $description = null, - ) { - $this->options = $options instanceof Collection ? $options->all() : $options; - -diff -ruN a/src/TextPrompt.php b/src/TextPrompt.php ---- a/src/TextPrompt.php -+++ b/src/TextPrompt.php -@@ -19,6 +19,7 @@ - public mixed $validate = null, - public string $hint = '', - public ?Closure $transform = null, -+ public ?string $description = null, - ) { - $this->trackTypedValue($default); - } -diff -ruN a/src/TextareaPrompt.php b/src/TextareaPrompt.php ---- a/src/TextareaPrompt.php -+++ b/src/TextareaPrompt.php -@@ -31,6 +31,7 @@ - public string $hint = '', - int $rows = 5, - public ?Closure $transform = null, -+ public ?string $description = null, - ) { - $this->scroll = $rows; - -diff -ruN a/src/Themes/Default/AutoCompletePromptRenderer.php b/src/Themes/Default/AutoCompletePromptRenderer.php ---- a/src/Themes/Default/AutoCompletePromptRenderer.php -+++ b/src/Themes/Default/AutoCompletePromptRenderer.php -@@ -3,10 +3,12 @@ - namespace Laravel\Prompts\Themes\Default; - - use Laravel\Prompts\AutoCompletePrompt; -+use Laravel\Prompts\Prompt; - - class AutoCompletePromptRenderer extends Renderer - { - use Concerns\DrawsBoxes; -+ use Concerns\RendersDescription; - - /** - * Render the text prompt. -@@ -14,18 +16,21 @@ - public function __invoke(AutoCompletePrompt $prompt): string - { - $maxWidth = $prompt->terminal()->cols() - 6; -+ $hasDescription = $prompt->description && trim($prompt->description) !== ''; - - return match ($prompt->state) { - 'submit' => $this - ->box( - $this->dim($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)), -- $this->truncate($prompt->value(), $maxWidth), -+ $hasDescription ? $this->renderDescription($prompt, $maxWidth, fn () => $this->calculateDescriptionWidth($prompt, $maxWidth)) : $this->truncate($prompt->value(), $maxWidth), -+ $hasDescription ? $this->truncate($prompt->value(), $maxWidth) : '', - ), - - 'cancel' => $this - ->box( - $this->truncate($prompt->label, $prompt->terminal()->cols() - 6), -- $this->strikethrough($this->dim($this->truncate($prompt->value() ?: $prompt->placeholder, $maxWidth))), -+ $hasDescription ? $this->renderDescription($prompt, $maxWidth, fn () => $this->calculateDescriptionWidth($prompt, $maxWidth)) : $this->strikethrough($this->dim($this->truncate($prompt->value() ?: $prompt->placeholder, $maxWidth))), -+ $hasDescription ? $this->strikethrough($this->dim($this->truncate($prompt->value() ?: $prompt->placeholder, $maxWidth))) : '', - color: 'red', - ) - ->error($prompt->cancelMessage), -@@ -33,7 +38,8 @@ - 'error' => $this - ->box( - $this->truncate($prompt->label, $prompt->terminal()->cols() - 6), -- $prompt->valueWithCursor($maxWidth), -+ $hasDescription ? $this->renderDescription($prompt, $maxWidth, fn () => $this->calculateDescriptionWidth($prompt, $maxWidth)) : $prompt->valueWithCursor($maxWidth), -+ $hasDescription ? $prompt->valueWithCursor($maxWidth) : '', - color: 'yellow', - ) - ->warning($this->truncate($prompt->error, $prompt->terminal()->cols() - 5)), -@@ -41,7 +47,8 @@ - default => $this - ->box( - $this->cyan($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)), -- $prompt->valueWithCursor($maxWidth), -+ $hasDescription ? $this->renderDescription($prompt, $maxWidth, fn () => $this->calculateDescriptionWidth($prompt, $maxWidth)) : $prompt->valueWithCursor($maxWidth), -+ $hasDescription ? $prompt->valueWithCursor($maxWidth) : '', - ) - ->when( - $prompt->hint, -@@ -49,5 +56,23 @@ - fn () => $this->newLine() // Space for errors - ) - }; -+ } -+ -+ /** -+ * Calculate the description width based on input content. -+ */ -+ protected function calculateDescriptionWidth(Prompt $prompt, int $maxWidth): int -+ { -+ if (! $prompt instanceof AutoCompletePrompt) { -+ return $this->minWidth; -+ } -+ -+ $titleWidth = mb_strwidth($this->stripEscapeSequences($prompt->label)); -+ $inputWidth = max( -+ mb_strwidth($this->stripEscapeSequences($prompt->value() ?: $prompt->placeholder)), -+ 40 // minimum reasonable input width -+ ); -+ -+ return max($this->minWidth, max($titleWidth, min($inputWidth, $maxWidth))); - } - } -diff -ruN a/src/Themes/Default/Concerns/RendersDescription.php b/src/Themes/Default/Concerns/RendersDescription.php ---- a/src/Themes/Default/Concerns/RendersDescription.php -+++ b/src/Themes/Default/Concerns/RendersDescription.php -@@ -0,0 +1,33 @@ -+description || trim($prompt->description) === '') { -+ return ''; -+ } -+ -+ $targetWidth = $calculateContentWidth ? $calculateContentWidth() : $this->calculateDescriptionWidth($prompt, $maxWidth); -+ -+ return $this->mbWordwrap($prompt->description, $targetWidth, PHP_EOL); -+ } -+ -+ /** -+ * Calculate the default description width based on title and minWidth. -+ */ -+ protected function calculateDescriptionWidth(Prompt $prompt, int $maxWidth): int -+ { -+ $titleWidth = mb_strwidth($this->stripEscapeSequences($prompt->label)); -+ -+ return max($this->minWidth, min($titleWidth, $maxWidth)); -+ } -+} -diff -ruN a/src/Themes/Default/ConfirmPromptRenderer.php b/src/Themes/Default/ConfirmPromptRenderer.php ---- a/src/Themes/Default/ConfirmPromptRenderer.php -+++ b/src/Themes/Default/ConfirmPromptRenderer.php -@@ -3,27 +3,34 @@ - namespace Laravel\Prompts\Themes\Default; - - use Laravel\Prompts\ConfirmPrompt; -+use Laravel\Prompts\Prompt; - - class ConfirmPromptRenderer extends Renderer - { - use Concerns\DrawsBoxes; -+ use Concerns\RendersDescription; - - /** - * Render the confirm prompt. - */ - public function __invoke(ConfirmPrompt $prompt): string - { -+ $maxWidth = $prompt->terminal()->cols() - 6; -+ $hasDescription = $prompt->description && trim($prompt->description) !== ''; -+ - return match ($prompt->state) { - 'submit' => $this - ->box( - $this->dim($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)), -- $this->truncate($prompt->label(), $prompt->terminal()->cols() - 6) -+ $hasDescription ? $this->renderDescription($prompt, $maxWidth, fn () => $this->calculateDescriptionWidth($prompt, $maxWidth)) : $this->truncate($prompt->label(), $prompt->terminal()->cols() - 6), -+ $hasDescription ? $this->truncate($prompt->label(), $prompt->terminal()->cols() - 6) : '', - ), - - 'cancel' => $this - ->box( - $this->truncate($prompt->label, $prompt->terminal()->cols() - 6), -- $this->renderOptions($prompt), -+ $hasDescription ? $this->renderDescription($prompt, $maxWidth, fn () => $this->calculateDescriptionWidth($prompt, $maxWidth)) : $this->renderOptions($prompt), -+ $hasDescription ? $this->renderOptions($prompt) : '', - color: 'red' - ) - ->error($prompt->cancelMessage), -@@ -31,7 +38,8 @@ - 'error' => $this - ->box( - $this->truncate($prompt->label, $prompt->terminal()->cols() - 6), -- $this->renderOptions($prompt), -+ $hasDescription ? $this->renderDescription($prompt, $maxWidth, fn () => $this->calculateDescriptionWidth($prompt, $maxWidth)) : $this->renderOptions($prompt), -+ $hasDescription ? $this->renderOptions($prompt) : '', - color: 'yellow', - ) - ->warning($this->truncate($prompt->error, $prompt->terminal()->cols() - 5)), -@@ -39,7 +47,8 @@ - default => $this - ->box( - $this->cyan($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)), -- $this->renderOptions($prompt), -+ $hasDescription ? $this->renderDescription($prompt, $maxWidth, fn () => $this->calculateDescriptionWidth($prompt, $maxWidth)) : $this->renderOptions($prompt), -+ $hasDescription ? $this->renderOptions($prompt) : '', - ) - ->when( - $prompt->hint, -@@ -47,6 +56,21 @@ - fn () => $this->newLine() // Space for errors - ), - }; -+ } -+ -+ /** -+ * Calculate the description width based on buttons. -+ */ -+ protected function calculateDescriptionWidth(Prompt $prompt, int $maxWidth): int -+ { -+ if (! $prompt instanceof ConfirmPrompt) { -+ return $this->minWidth; -+ } -+ -+ $titleWidth = mb_strwidth($this->stripEscapeSequences($prompt->label)); -+ $buttonsWidth = mb_strwidth($prompt->yes.' / '.$prompt->no) + 10; // padding for buttons -+ -+ return max($this->minWidth, max($titleWidth, min($buttonsWidth, $maxWidth))); - } - - /** -diff -ruN a/src/Themes/Default/MultiSearchPromptRenderer.php b/src/Themes/Default/MultiSearchPromptRenderer.php ---- a/src/Themes/Default/MultiSearchPromptRenderer.php -+++ b/src/Themes/Default/MultiSearchPromptRenderer.php -@@ -3,12 +3,14 @@ - namespace Laravel\Prompts\Themes\Default; - - use Laravel\Prompts\MultiSearchPrompt; -+use Laravel\Prompts\Prompt; - use Laravel\Prompts\Themes\Contracts\Scrolling; - - class MultiSearchPromptRenderer extends Renderer implements Scrolling - { - use Concerns\DrawsBoxes; - use Concerns\DrawsScrollbars; -+ use Concerns\RendersDescription; - - /** - * Render the suggest prompt. -@@ -16,18 +18,21 @@ - public function __invoke(MultiSearchPrompt $prompt): string - { - $maxWidth = $prompt->terminal()->cols() - 6; -+ $hasDescription = $prompt->description && trim($prompt->description) !== ''; - - return match ($prompt->state) { - 'submit' => $this - ->box( - $this->dim($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)), -- $this->renderSelectedOptions($prompt), -+ $hasDescription ? $this->renderDescription($prompt, $maxWidth, fn () => $this->calculateDescriptionWidth($prompt, $maxWidth)) : $this->renderSelectedOptions($prompt), -+ $hasDescription ? $this->renderSelectedOptions($prompt) : '', - ), - - 'cancel' => $this - ->box( - $this->dim($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)), -- $this->strikethrough($this->dim($this->truncate($prompt->searchValue() ?: $prompt->placeholder, $maxWidth))), -+ $hasDescription ? $this->renderDescription($prompt, $maxWidth, fn () => $this->calculateDescriptionWidth($prompt, $maxWidth)) : $this->strikethrough($this->dim($this->truncate($prompt->searchValue() ?: $prompt->placeholder, $maxWidth))), -+ $hasDescription ? $this->strikethrough($this->dim($this->truncate($prompt->searchValue() ?: $prompt->placeholder, $maxWidth))) : '', - color: 'red', - ) - ->error($prompt->cancelMessage), -@@ -35,8 +40,8 @@ - 'error' => $this - ->box( - $this->truncate($prompt->label, $prompt->terminal()->cols() - 6), -- $prompt->valueWithCursor($maxWidth), -- $this->renderOptions($prompt), -+ $hasDescription ? $this->renderDescription($prompt, $maxWidth, fn () => $this->calculateDescriptionWidth($prompt, $maxWidth)) : $prompt->valueWithCursor($maxWidth), -+ $hasDescription ? $prompt->valueWithCursor($maxWidth).PHP_EOL.$this->renderOptions($prompt) : $this->renderOptions($prompt), - color: 'yellow', - info: $this->getInfoText($prompt), - ) -@@ -45,8 +50,8 @@ - 'searching' => $this - ->box( - $this->cyan($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)), -- $this->valueWithCursorAndSearchIcon($prompt, $maxWidth), -- $this->renderOptions($prompt), -+ $hasDescription ? $this->renderDescription($prompt, $maxWidth, fn () => $this->calculateDescriptionWidth($prompt, $maxWidth)) : $this->valueWithCursorAndSearchIcon($prompt, $maxWidth), -+ $hasDescription ? $this->valueWithCursorAndSearchIcon($prompt, $maxWidth).PHP_EOL.$this->renderOptions($prompt) : $this->renderOptions($prompt), - info: $this->getInfoText($prompt), - ) - ->hint($prompt->hint), -@@ -54,8 +59,8 @@ - default => $this - ->box( - $this->cyan($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)), -- $prompt->valueWithCursor($maxWidth), -- $this->renderOptions($prompt), -+ $hasDescription ? $this->renderDescription($prompt, $maxWidth, fn () => $this->calculateDescriptionWidth($prompt, $maxWidth)) : $prompt->valueWithCursor($maxWidth), -+ $hasDescription ? $prompt->valueWithCursor($maxWidth).PHP_EOL.$this->renderOptions($prompt) : $this->renderOptions($prompt), - info: $this->getInfoText($prompt), - ) - ->when( -@@ -168,6 +173,21 @@ - $parts = array_filter([$prompt->infoText(), $selected]); - - return implode(' · ', $parts); -+ } -+ -+ /** -+ * Calculate the width for description text. -+ */ -+ protected function calculateDescriptionWidth(Prompt $prompt, int $maxWidth): int -+ { -+ if (! $prompt instanceof MultiSearchPrompt) { -+ return $maxWidth; -+ } -+ -+ $titleWidth = mb_strwidth($this->stripEscapeSequences($prompt->label)); -+ $optionsWidth = $this->longest($prompt->matches()); -+ -+ return max($this->minWidth, max($titleWidth, $optionsWidth)); - } - - /** -diff -ruN a/src/Themes/Default/MultiSelectPromptRenderer.php b/src/Themes/Default/MultiSelectPromptRenderer.php ---- a/src/Themes/Default/MultiSelectPromptRenderer.php -+++ b/src/Themes/Default/MultiSelectPromptRenderer.php -@@ -3,29 +3,36 @@ - namespace Laravel\Prompts\Themes\Default; - - use Laravel\Prompts\MultiSelectPrompt; -+use Laravel\Prompts\Prompt; - use Laravel\Prompts\Themes\Contracts\Scrolling; - - class MultiSelectPromptRenderer extends Renderer implements Scrolling - { - use Concerns\DrawsBoxes; - use Concerns\DrawsScrollbars; -+ use Concerns\RendersDescription; - - /** - * Render the multiselect prompt. - */ - public function __invoke(MultiSelectPrompt $prompt): string - { -+ $maxWidth = $prompt->terminal()->cols() - 6; -+ $hasDescription = $prompt->description && trim($prompt->description) !== ''; -+ - return match ($prompt->state) { - 'submit' => $this - ->box( - $this->dim($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)), -- $this->renderSelectedOptions($prompt) -+ $hasDescription ? $this->renderDescription($prompt, $maxWidth, fn () => $this->calculateDescriptionWidth($prompt, $maxWidth)) : $this->renderSelectedOptions($prompt), -+ $hasDescription ? $this->renderSelectedOptions($prompt) : '', - ), - - 'cancel' => $this - ->box( - $this->truncate($prompt->label, $prompt->terminal()->cols() - 6), -- $this->renderOptions($prompt), -+ $hasDescription ? $this->renderDescription($prompt, $maxWidth, fn () => $this->calculateDescriptionWidth($prompt, $maxWidth)) : $this->renderOptions($prompt), -+ $hasDescription ? $this->renderOptions($prompt) : '', - color: 'red', - ) - ->error($prompt->cancelMessage), -@@ -33,7 +40,8 @@ - 'error' => $this - ->box( - $this->truncate($prompt->label, $prompt->terminal()->cols() - 6), -- $this->renderOptions($prompt), -+ $hasDescription ? $this->renderDescription($prompt, $maxWidth, fn () => $this->calculateDescriptionWidth($prompt, $maxWidth)) : $this->renderOptions($prompt), -+ $hasDescription ? $this->renderOptions($prompt) : '', - color: 'yellow', - info: count($prompt->options) > $prompt->scroll ? (count($prompt->value()).' selected') : '', - ) -@@ -42,7 +50,8 @@ - default => $this - ->box( - $this->cyan($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)), -- $this->renderOptions($prompt), -+ $hasDescription ? $this->renderDescription($prompt, $maxWidth, fn () => $this->calculateDescriptionWidth($prompt, $maxWidth)) : $this->renderOptions($prompt), -+ $hasDescription ? $this->renderOptions($prompt) : '', - info: $this->getInfoText($prompt), - ) - ->when( -@@ -51,6 +60,21 @@ - fn () => $this->newLine() // Space for errors - ), - }; -+ } -+ -+ /** -+ * Calculate the description width based on options. -+ */ -+ protected function calculateDescriptionWidth(Prompt $prompt, int $maxWidth): int -+ { -+ if (! $prompt instanceof MultiSelectPrompt) { -+ return $this->minWidth; -+ } -+ -+ $optionsWidth = min($this->longest($prompt->options, padding: 6), $prompt->terminal()->cols() - 6); -+ $titleWidth = mb_strwidth($this->stripEscapeSequences($prompt->label)); -+ -+ return max($this->minWidth, max($titleWidth, $optionsWidth)); - } - - /** -diff -ruN a/src/Themes/Default/NumberPromptRenderer.php b/src/Themes/Default/NumberPromptRenderer.php ---- a/src/Themes/Default/NumberPromptRenderer.php -+++ b/src/Themes/Default/NumberPromptRenderer.php -@@ -3,10 +3,12 @@ - namespace Laravel\Prompts\Themes\Default; - - use Laravel\Prompts\NumberPrompt; -+use Laravel\Prompts\Prompt; - - class NumberPromptRenderer extends Renderer - { - use Concerns\DrawsBoxes; -+ use Concerns\RendersDescription; - - protected string $upArrow = '▲'; - -@@ -18,18 +20,21 @@ - public function __invoke(NumberPrompt $prompt): string - { - $maxWidth = $prompt->terminal()->cols() - 6; -+ $hasDescription = $prompt->description && trim($prompt->description) !== ''; - - return match ($prompt->state) { - 'submit' => $this - ->box( - $this->dim($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)), -- $this->truncate((string) $prompt->value(), $maxWidth), -+ $hasDescription ? $this->renderDescription($prompt, $maxWidth, fn () => $this->calculateDescriptionWidth($prompt, $maxWidth)) : $this->truncate((string) $prompt->value(), $maxWidth), -+ $hasDescription ? $this->truncate((string) $prompt->value(), $maxWidth) : '', - ), - - 'cancel' => $this - ->box( - $this->truncate($prompt->label, $prompt->terminal()->cols() - 6), -- $this->strikethrough($this->dim($this->truncate((string) $prompt->value() ?: $prompt->placeholder, $maxWidth))), -+ $hasDescription ? $this->renderDescription($prompt, $maxWidth, fn () => $this->calculateDescriptionWidth($prompt, $maxWidth)) : $this->strikethrough($this->dim($this->truncate((string) $prompt->value() ?: $prompt->placeholder, $maxWidth))), -+ $hasDescription ? $this->strikethrough($this->dim($this->truncate((string) $prompt->value() ?: $prompt->placeholder, $maxWidth))) : '', - color: 'red', - ) - ->error('Cancelled.'), -@@ -37,7 +42,8 @@ - 'error' => $this - ->box( - $this->truncate($prompt->label, $prompt->terminal()->cols() - 6), -- $this->withArrows($prompt, $prompt->valueWithCursor($maxWidth), 'yellow'), -+ $hasDescription ? $this->renderDescription($prompt, $maxWidth, fn () => $this->calculateDescriptionWidth($prompt, $maxWidth)) : $this->withArrows($prompt, $prompt->valueWithCursor($maxWidth), 'yellow'), -+ $hasDescription ? $this->withArrows($prompt, $prompt->valueWithCursor($maxWidth), 'yellow') : '', - color: 'yellow', - ) - ->warning($this->truncate($prompt->error, $prompt->terminal()->cols() - 5)), -@@ -45,7 +51,8 @@ - default => $this - ->box( - $this->cyan($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)), -- $this->withArrows($prompt, $prompt->valueWithCursor($maxWidth)), -+ $hasDescription ? $this->renderDescription($prompt, $maxWidth, fn () => $this->calculateDescriptionWidth($prompt, $maxWidth)) : $this->withArrows($prompt, $prompt->valueWithCursor($maxWidth)), -+ $hasDescription ? $this->withArrows($prompt, $prompt->valueWithCursor($maxWidth)) : '', - ) - ->when( - $prompt->hint, -@@ -53,6 +60,24 @@ - fn () => $this->newLine() // Space for errors - ) - }; -+ } -+ -+ /** -+ * Calculate the description width based on input content. -+ */ -+ protected function calculateDescriptionWidth(Prompt $prompt, int $maxWidth): int -+ { -+ if (! $prompt instanceof NumberPrompt) { -+ return $this->minWidth; -+ } -+ -+ $titleWidth = mb_strwidth($this->stripEscapeSequences($prompt->label)); -+ $inputWidth = max( -+ mb_strwidth($this->stripEscapeSequences((string) $prompt->value() ?: $prompt->placeholder)), -+ 40 // minimum reasonable input width -+ ); -+ -+ return max($this->minWidth, max($titleWidth, min($inputWidth, $maxWidth))); - } - - protected function withArrows(NumberPrompt $prompt, int|string $value, ?string $color = null): string -diff -ruN a/src/Themes/Default/PasswordPromptRenderer.php b/src/Themes/Default/PasswordPromptRenderer.php ---- a/src/Themes/Default/PasswordPromptRenderer.php -+++ b/src/Themes/Default/PasswordPromptRenderer.php -@@ -3,10 +3,12 @@ - namespace Laravel\Prompts\Themes\Default; - - use Laravel\Prompts\PasswordPrompt; -+use Laravel\Prompts\Prompt; - - class PasswordPromptRenderer extends Renderer - { - use Concerns\DrawsBoxes; -+ use Concerns\RendersDescription; - - /** - * Render the password prompt. -@@ -14,18 +16,21 @@ - public function __invoke(PasswordPrompt $prompt): string - { - $maxWidth = $prompt->terminal()->cols() - 6; -+ $hasDescription = $prompt->description && trim($prompt->description) !== ''; - - return match ($prompt->state) { - 'submit' => $this - ->box( - $this->dim($prompt->label), -- $this->truncate($prompt->masked(), $maxWidth), -+ $hasDescription ? $this->renderDescription($prompt, $maxWidth, fn () => $this->calculateDescriptionWidth($prompt, $maxWidth)) : $this->truncate($prompt->masked(), $maxWidth), -+ $hasDescription ? $this->truncate($prompt->masked(), $maxWidth) : '', - ), - - 'cancel' => $this - ->box( - $this->truncate($prompt->label, $prompt->terminal()->cols() - 6), -- $this->strikethrough($this->dim($this->truncate($prompt->masked() ?: $prompt->placeholder, $maxWidth))), -+ $hasDescription ? $this->renderDescription($prompt, $maxWidth, fn () => $this->calculateDescriptionWidth($prompt, $maxWidth)) : $this->strikethrough($this->dim($this->truncate($prompt->masked() ?: $prompt->placeholder, $maxWidth))), -+ $hasDescription ? $this->strikethrough($this->dim($this->truncate($prompt->masked() ?: $prompt->placeholder, $maxWidth))) : '', - color: 'red', - ) - ->error($prompt->cancelMessage), -@@ -33,7 +38,8 @@ - 'error' => $this - ->box( - $this->dim($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)), -- $prompt->maskedWithCursor($maxWidth), -+ $hasDescription ? $this->renderDescription($prompt, $maxWidth, fn () => $this->calculateDescriptionWidth($prompt, $maxWidth)) : $prompt->maskedWithCursor($maxWidth), -+ $hasDescription ? $prompt->maskedWithCursor($maxWidth) : '', - color: 'yellow', - ) - ->warning($this->truncate($prompt->error, $prompt->terminal()->cols() - 5)), -@@ -41,7 +47,8 @@ - default => $this - ->box( - $this->cyan($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)), -- $prompt->maskedWithCursor($maxWidth), -+ $hasDescription ? $this->renderDescription($prompt, $maxWidth, fn () => $this->calculateDescriptionWidth($prompt, $maxWidth)) : $prompt->maskedWithCursor($maxWidth), -+ $hasDescription ? $prompt->maskedWithCursor($maxWidth) : '', - ) - ->when( - $prompt->hint, -@@ -49,5 +56,23 @@ - fn () => $this->newLine() // Space for errors - ), - }; -+ } -+ -+ /** -+ * Calculate the description width based on password input content. -+ */ -+ protected function calculateDescriptionWidth(Prompt $prompt, int $maxWidth): int -+ { -+ if (! $prompt instanceof PasswordPrompt) { -+ return $this->minWidth; -+ } -+ -+ $titleWidth = mb_strwidth($this->stripEscapeSequences($prompt->label)); -+ $inputWidth = max( -+ mb_strwidth($this->stripEscapeSequences($prompt->masked() ?: $prompt->placeholder)), -+ 40 // minimum reasonable input width -+ ); -+ -+ return max($this->minWidth, max($titleWidth, min($inputWidth, $maxWidth))); - } - } -diff -ruN a/src/Themes/Default/SearchPromptRenderer.php b/src/Themes/Default/SearchPromptRenderer.php ---- a/src/Themes/Default/SearchPromptRenderer.php -+++ b/src/Themes/Default/SearchPromptRenderer.php -@@ -2,6 +2,7 @@ - - namespace Laravel\Prompts\Themes\Default; - -+use Laravel\Prompts\Prompt; - use Laravel\Prompts\SearchPrompt; - use Laravel\Prompts\Themes\Contracts\Scrolling; - -@@ -9,6 +10,7 @@ - { - use Concerns\DrawsBoxes; - use Concerns\DrawsScrollbars; -+ use Concerns\RendersDescription; - - /** - * Render the suggest prompt. -@@ -16,18 +18,21 @@ - public function __invoke(SearchPrompt $prompt): string - { - $maxWidth = $prompt->terminal()->cols() - 6; -+ $hasDescription = $prompt->description && trim($prompt->description) !== ''; - - return match ($prompt->state) { - 'submit' => $this - ->box( - $this->dim($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)), -- $this->truncate($prompt->label(), $maxWidth), -+ $hasDescription ? $this->renderDescription($prompt, $maxWidth, fn () => $this->calculateDescriptionWidth($prompt, $maxWidth)) : $this->truncate($prompt->label(), $maxWidth), -+ $hasDescription ? $this->truncate($prompt->label(), $maxWidth) : '', - ), - - 'cancel' => $this - ->box( - $this->dim($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)), -- $this->strikethrough($this->dim($this->truncate($prompt->searchValue() ?: $prompt->placeholder, $maxWidth))), -+ $hasDescription ? $this->renderDescription($prompt, $maxWidth, fn () => $this->calculateDescriptionWidth($prompt, $maxWidth)) : $this->strikethrough($this->dim($this->truncate($prompt->searchValue() ?: $prompt->placeholder, $maxWidth))), -+ $hasDescription ? $this->strikethrough($this->dim($this->truncate($prompt->searchValue() ?: $prompt->placeholder, $maxWidth))) : '', - color: 'red', - ) - ->error($prompt->cancelMessage), -@@ -35,8 +40,8 @@ - 'error' => $this - ->box( - $this->truncate($prompt->label, $prompt->terminal()->cols() - 6), -- $prompt->valueWithCursor($maxWidth), -- $this->renderOptions($prompt), -+ $hasDescription ? $this->renderDescription($prompt, $maxWidth, fn () => $this->calculateDescriptionWidth($prompt, $maxWidth)) : $prompt->valueWithCursor($maxWidth), -+ $hasDescription ? $prompt->valueWithCursor($maxWidth).PHP_EOL.$this->renderOptions($prompt) : $this->renderOptions($prompt), - color: 'yellow', - ) - ->warning($this->truncate($prompt->error, $prompt->terminal()->cols() - 5)), -@@ -44,8 +49,8 @@ - 'searching' => $this - ->box( - $this->cyan($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)), -- $this->valueWithCursorAndSearchIcon($prompt, $maxWidth), -- $this->renderOptions($prompt), -+ $hasDescription ? $this->renderDescription($prompt, $maxWidth, fn () => $this->calculateDescriptionWidth($prompt, $maxWidth)) : $this->valueWithCursorAndSearchIcon($prompt, $maxWidth), -+ $hasDescription ? $this->valueWithCursorAndSearchIcon($prompt, $maxWidth).PHP_EOL.$this->renderOptions($prompt) : $this->renderOptions($prompt), - info: $prompt->infoText(), - ) - ->hint($prompt->hint), -@@ -53,8 +58,8 @@ - default => $this - ->box( - $this->cyan($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)), -- $prompt->valueWithCursor($maxWidth), -- $this->renderOptions($prompt), -+ $hasDescription ? $this->renderDescription($prompt, $maxWidth, fn () => $this->calculateDescriptionWidth($prompt, $maxWidth)) : $prompt->valueWithCursor($maxWidth), -+ $hasDescription ? $prompt->valueWithCursor($maxWidth).PHP_EOL.$this->renderOptions($prompt) : $this->renderOptions($prompt), - info: $prompt->infoText(), - ) - ->when( -@@ -123,6 +128,21 @@ - count($prompt->matches()), - min($this->longest($prompt->matches(), padding: 4), $prompt->terminal()->cols() - 6) - )); -+ } -+ -+ /** -+ * Calculate the width for description text. -+ */ -+ protected function calculateDescriptionWidth(Prompt $prompt, int $maxWidth): int -+ { -+ if (! $prompt instanceof SearchPrompt) { -+ return $this->minWidth; -+ } -+ -+ $titleWidth = mb_strwidth($this->stripEscapeSequences($prompt->label)); -+ $optionsWidth = $this->longest($prompt->matches()); -+ -+ return max($this->minWidth, max($titleWidth, $optionsWidth)); - } - - /** -diff -ruN a/src/Themes/Default/SelectPromptRenderer.php b/src/Themes/Default/SelectPromptRenderer.php ---- a/src/Themes/Default/SelectPromptRenderer.php -+++ b/src/Themes/Default/SelectPromptRenderer.php -@@ -2,6 +2,7 @@ - - namespace Laravel\Prompts\Themes\Default; - -+use Laravel\Prompts\Prompt; - use Laravel\Prompts\SelectPrompt; - use Laravel\Prompts\Themes\Contracts\Scrolling; - -@@ -9,6 +10,7 @@ - { - use Concerns\DrawsBoxes; - use Concerns\DrawsScrollbars; -+ use Concerns\RendersDescription; - - /** - * Render the select prompt. -@@ -17,17 +19,21 @@ - { - $maxWidth = $prompt->terminal()->cols() - 6; - -+ $hasDescription = $prompt->description && trim($prompt->description) !== ''; -+ - return match ($prompt->state) { - 'submit' => $this - ->box( - $this->dim($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)), -- $this->truncate($prompt->label(), $maxWidth), -+ $hasDescription ? $this->renderDescription($prompt, $maxWidth, fn () => $this->calculateDescriptionWidth($prompt, $maxWidth)) : $this->truncate($prompt->label(), $maxWidth), -+ $hasDescription ? $this->truncate($prompt->label(), $maxWidth) : '', - ), - - 'cancel' => $this - ->box( - $this->truncate($prompt->label, $prompt->terminal()->cols() - 6), -- $this->renderOptions($prompt), -+ $hasDescription ? $this->renderDescription($prompt, $maxWidth, fn () => $this->calculateDescriptionWidth($prompt, $maxWidth)) : $this->renderOptions($prompt), -+ $hasDescription ? $this->renderOptions($prompt) : '', - color: 'red', - ) - ->error($prompt->cancelMessage), -@@ -35,7 +41,8 @@ - 'error' => $this - ->box( - $this->truncate($prompt->label, $prompt->terminal()->cols() - 6), -- $this->renderOptions($prompt), -+ $hasDescription ? $this->renderDescription($prompt, $maxWidth, fn () => $this->calculateDescriptionWidth($prompt, $maxWidth)) : $this->renderOptions($prompt), -+ $hasDescription ? $this->renderOptions($prompt) : '', - color: 'yellow', - ) - ->warning($this->truncate($prompt->error, $prompt->terminal()->cols() - 5)), -@@ -43,7 +50,8 @@ - default => $this - ->box( - $this->cyan($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)), -- $this->renderOptions($prompt), -+ $hasDescription ? $this->renderDescription($prompt, $maxWidth, fn () => $this->calculateDescriptionWidth($prompt, $maxWidth)) : $this->renderOptions($prompt), -+ $hasDescription ? $this->renderOptions($prompt) : '', - info: $prompt->infoText(), - ) - ->when( -@@ -52,6 +60,21 @@ - fn () => $this->newLine() // Space for errors - ), - }; -+ } -+ -+ /** -+ * Calculate the description width based on options. -+ */ -+ protected function calculateDescriptionWidth(Prompt $prompt, int $maxWidth): int -+ { -+ if (! $prompt instanceof SelectPrompt) { -+ return $maxWidth; -+ } -+ -+ $optionsWidth = min($this->longest($prompt->options, padding: 6), $prompt->terminal()->cols() - 6); -+ $titleWidth = mb_strwidth($this->stripEscapeSequences($prompt->label)); -+ -+ return max($this->minWidth, max($titleWidth, $optionsWidth)); - } - - /** -diff -ruN a/src/Themes/Default/SuggestPromptRenderer.php b/src/Themes/Default/SuggestPromptRenderer.php ---- a/src/Themes/Default/SuggestPromptRenderer.php -+++ b/src/Themes/Default/SuggestPromptRenderer.php -@@ -2,6 +2,7 @@ - - namespace Laravel\Prompts\Themes\Default; - -+use Laravel\Prompts\Prompt; - use Laravel\Prompts\SuggestPrompt; - use Laravel\Prompts\Themes\Contracts\Scrolling; - -@@ -9,6 +10,7 @@ - { - use Concerns\DrawsBoxes; - use Concerns\DrawsScrollbars; -+ use Concerns\RendersDescription; - - /** - * Render the suggest prompt. -@@ -16,18 +18,21 @@ - public function __invoke(SuggestPrompt $prompt): string - { - $maxWidth = $prompt->terminal()->cols() - 6; -+ $hasDescription = $prompt->description && trim($prompt->description) !== ''; - - return match ($prompt->state) { - 'submit' => $this - ->box( - $this->dim($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)), -- $this->truncate($prompt->value(), $maxWidth), -+ $hasDescription ? $this->renderDescription($prompt, $maxWidth, fn () => $this->calculateDescriptionWidth($prompt, $maxWidth)) : $this->truncate($prompt->value(), $maxWidth), -+ $hasDescription ? $this->truncate($prompt->value(), $maxWidth) : '', - ), - - 'cancel' => $this - ->box( - $this->dim($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)), -- $this->strikethrough($this->dim($this->truncate($prompt->value() ?: $prompt->placeholder, $maxWidth))), -+ $hasDescription ? $this->renderDescription($prompt, $maxWidth, fn () => $this->calculateDescriptionWidth($prompt, $maxWidth)) : $this->strikethrough($this->dim($this->truncate($prompt->value() ?: $prompt->placeholder, $maxWidth))), -+ $hasDescription ? $this->strikethrough($this->dim($this->truncate($prompt->value() ?: $prompt->placeholder, $maxWidth))) : '', - color: 'red', - ) - ->error($prompt->cancelMessage), -@@ -35,8 +40,8 @@ - 'error' => $this - ->box( - $this->truncate($prompt->label, $prompt->terminal()->cols() - 6), -- $this->valueWithCursorAndArrow($prompt, $maxWidth), -- $this->renderOptions($prompt), -+ $hasDescription ? $this->renderDescription($prompt, $maxWidth, fn () => $this->calculateDescriptionWidth($prompt, $maxWidth)) : $this->valueWithCursorAndArrow($prompt, $maxWidth), -+ $hasDescription ? $this->valueWithCursorAndArrow($prompt, $maxWidth).PHP_EOL.$this->renderOptions($prompt) : $this->renderOptions($prompt), - color: 'yellow', - ) - ->warning($this->truncate($prompt->error, $prompt->terminal()->cols() - 5)), -@@ -44,8 +49,8 @@ - default => $this - ->box( - $this->cyan($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)), -- $this->valueWithCursorAndArrow($prompt, $maxWidth), -- $this->renderOptions($prompt), -+ $hasDescription ? $this->renderDescription($prompt, $maxWidth, fn () => $this->calculateDescriptionWidth($prompt, $maxWidth)) : $this->valueWithCursorAndArrow($prompt, $maxWidth), -+ $hasDescription ? $this->valueWithCursorAndArrow($prompt, $maxWidth).PHP_EOL.$this->renderOptions($prompt) : $this->renderOptions($prompt), - info: $prompt->infoText(), - ) - ->when( -@@ -112,6 +117,25 @@ - min($this->longest($prompt->matches(), padding: 4), $prompt->terminal()->cols() - 6), - $prompt->state === 'cancel' ? 'dim' : 'cyan' - )); -+ } -+ -+ /** -+ * Calculate the width for description text. -+ */ -+ protected function calculateDescriptionWidth(Prompt $prompt, int $maxWidth): int -+ { -+ if (! $prompt instanceof SuggestPrompt) { -+ return $this->minWidth; -+ } -+ -+ $titleWidth = mb_strwidth($this->stripEscapeSequences($prompt->label)); -+ $inputWidth = max( -+ mb_strwidth($prompt->placeholder), -+ mb_strwidth($prompt->default), -+ $this->longest($prompt->matches()) -+ ); -+ -+ return max($this->minWidth, max($titleWidth, min($inputWidth + 4, $maxWidth))); - } - - /** -diff -ruN a/src/Themes/Default/TextPromptRenderer.php b/src/Themes/Default/TextPromptRenderer.php ---- a/src/Themes/Default/TextPromptRenderer.php -+++ b/src/Themes/Default/TextPromptRenderer.php -@@ -2,11 +2,13 @@ - - namespace Laravel\Prompts\Themes\Default; - -+use Laravel\Prompts\Prompt; - use Laravel\Prompts\TextPrompt; - - class TextPromptRenderer extends Renderer - { - use Concerns\DrawsBoxes; -+ use Concerns\RendersDescription; - - /** - * Render the text prompt. -@@ -14,18 +16,21 @@ - public function __invoke(TextPrompt $prompt): string - { - $maxWidth = $prompt->terminal()->cols() - 6; -+ $hasDescription = $prompt->description && trim($prompt->description) !== ''; - - return match ($prompt->state) { - 'submit' => $this - ->box( - $this->dim($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)), -- $this->truncate($prompt->value(), $maxWidth), -+ $hasDescription ? $this->renderDescription($prompt, $maxWidth, fn () => $this->calculateDescriptionWidth($prompt, $maxWidth)) : $this->truncate($prompt->value(), $maxWidth), -+ $hasDescription ? $this->truncate($prompt->value(), $maxWidth) : '', - ), - - 'cancel' => $this - ->box( - $this->truncate($prompt->label, $prompt->terminal()->cols() - 6), -- $this->strikethrough($this->dim($this->truncate($prompt->value() ?: $prompt->placeholder, $maxWidth))), -+ $hasDescription ? $this->renderDescription($prompt, $maxWidth, fn () => $this->calculateDescriptionWidth($prompt, $maxWidth)) : $this->strikethrough($this->dim($this->truncate($prompt->value() ?: $prompt->placeholder, $maxWidth))), -+ $hasDescription ? $this->strikethrough($this->dim($this->truncate($prompt->value() ?: $prompt->placeholder, $maxWidth))) : '', - color: 'red', - ) - ->error($prompt->cancelMessage), -@@ -33,7 +38,8 @@ - 'error' => $this - ->box( - $this->truncate($prompt->label, $prompt->terminal()->cols() - 6), -- $prompt->valueWithCursor($maxWidth), -+ $hasDescription ? $this->renderDescription($prompt, $maxWidth, fn () => $this->calculateDescriptionWidth($prompt, $maxWidth)) : $prompt->valueWithCursor($maxWidth), -+ $hasDescription ? $prompt->valueWithCursor($maxWidth) : '', - color: 'yellow', - ) - ->warning($this->truncate($prompt->error, $prompt->terminal()->cols() - 5)), -@@ -41,7 +47,8 @@ - default => $this - ->box( - $this->cyan($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)), -- $prompt->valueWithCursor($maxWidth), -+ $hasDescription ? $this->renderDescription($prompt, $maxWidth, fn () => $this->calculateDescriptionWidth($prompt, $maxWidth)) : $prompt->valueWithCursor($maxWidth), -+ $hasDescription ? $prompt->valueWithCursor($maxWidth) : '', - ) - ->when( - $prompt->hint, -@@ -49,5 +56,23 @@ - fn () => $this->newLine() // Space for errors - ) - }; -+ } -+ -+ /** -+ * Calculate the description width based on input content. -+ */ -+ protected function calculateDescriptionWidth(Prompt $prompt, int $maxWidth): int -+ { -+ if (! $prompt instanceof TextPrompt) { -+ return $this->minWidth; -+ } -+ -+ $titleWidth = mb_strwidth($this->stripEscapeSequences($prompt->label)); -+ $inputWidth = max( -+ mb_strwidth($this->stripEscapeSequences($prompt->value() ?: $prompt->placeholder)), -+ 40 // minimum reasonable input width -+ ); -+ -+ return max($this->minWidth, max($titleWidth, min($inputWidth, $maxWidth))); - } - } -diff -ruN a/src/Themes/Default/TextareaPromptRenderer.php b/src/Themes/Default/TextareaPromptRenderer.php ---- a/src/Themes/Default/TextareaPromptRenderer.php -+++ b/src/Themes/Default/TextareaPromptRenderer.php -@@ -2,6 +2,7 @@ - - namespace Laravel\Prompts\Themes\Default; - -+use Laravel\Prompts\Prompt; - use Laravel\Prompts\TextareaPrompt; - use Laravel\Prompts\Themes\Contracts\Scrolling; - -@@ -9,6 +10,7 @@ - { - use Concerns\DrawsBoxes; - use Concerns\DrawsScrollbars; -+ use Concerns\RendersDescription; - - /** - * Render the textarea prompt. -@@ -16,18 +18,22 @@ - public function __invoke(TextareaPrompt $prompt): string - { - $prompt->width = $prompt->terminal()->cols() - 8; -+ $maxWidth = $prompt->terminal()->cols() - 6; -+ $hasDescription = $prompt->description && trim($prompt->description) !== ''; - - return match ($prompt->state) { - 'submit' => $this - ->box( - $this->dim($this->truncate($prompt->label, $prompt->width)), -- implode(PHP_EOL, $prompt->lines()), -+ $hasDescription ? $this->renderDescription($prompt, $maxWidth, fn () => $this->calculateDescriptionWidth($prompt, $maxWidth)) : implode(PHP_EOL, $prompt->lines()), -+ $hasDescription ? implode(PHP_EOL, $prompt->lines()) : '', - ), - - 'cancel' => $this - ->box( - $this->truncate($prompt->label, $prompt->width), -- implode(PHP_EOL, array_map(fn ($line) => $this->strikethrough($this->dim($line)), $prompt->lines())), -+ $hasDescription ? $this->renderDescription($prompt, $maxWidth, fn () => $this->calculateDescriptionWidth($prompt, $maxWidth)) : implode(PHP_EOL, array_map(fn ($line) => $this->strikethrough($this->dim($line)), $prompt->lines())), -+ $hasDescription ? implode(PHP_EOL, array_map(fn ($line) => $this->strikethrough($this->dim($line)), $prompt->lines())) : '', - color: 'red', - ) - ->error($prompt->cancelMessage), -@@ -35,7 +41,8 @@ - 'error' => $this - ->box( - $this->truncate($prompt->label, $prompt->width), -- $this->renderText($prompt), -+ $hasDescription ? $this->renderDescription($prompt, $maxWidth, fn () => $this->calculateDescriptionWidth($prompt, $maxWidth)) : $this->renderText($prompt), -+ $hasDescription ? $this->renderText($prompt) : '', - color: 'yellow', - info: 'Ctrl+D to submit' - ) -@@ -44,7 +51,8 @@ - default => $this - ->box( - $this->cyan($this->truncate($prompt->label, $prompt->width)), -- $this->renderText($prompt), -+ $hasDescription ? $this->renderDescription($prompt, $maxWidth, fn () => $this->calculateDescriptionWidth($prompt, $maxWidth)) : $this->renderText($prompt), -+ $hasDescription ? $this->renderText($prompt) : '', - info: 'Ctrl+D to submit' - ) - ->when( -@@ -53,6 +61,21 @@ - fn () => $this->newLine() // Space for errors - ) - }; -+ } -+ -+ /** -+ * Calculate the description width based on textarea content. -+ */ -+ protected function calculateDescriptionWidth(Prompt $prompt, int $maxWidth): int -+ { -+ if (! $prompt instanceof TextareaPrompt) { -+ return $this->minWidth; -+ } -+ -+ $titleWidth = mb_strwidth($this->stripEscapeSequences($prompt->label)); -+ $textareaWidth = min($prompt->width, $maxWidth); -+ -+ return max($this->minWidth, max($titleWidth, $textareaWidth)); - } - - /** -diff -ruN a/src/helpers.php b/src/helpers.php ---- a/src/helpers.php -+++ b/src/helpers.php -@@ -17,6 +17,7 @@ - mixed $validate = null, - string $hint = '', - ?Closure $transform = null, -+ ?string $description = null, - ): string { - return (new TextPrompt(...get_defined_vars()))->prompt(); - } -@@ -37,6 +38,7 @@ - mixed $validate = null, - string $hint = '', - ?Closure $transform = null, -+ ?string $description = null, - ): string { - return (new AutoCompletePrompt(...get_defined_vars()))->prompt(); - } -@@ -46,7 +48,7 @@ - /** - * Prompt the user for number input. - */ -- function number(string $label, string $placeholder = '', string $default = '', bool|string $required = false, mixed $validate = null, string $hint = '', ?int $min = null, ?int $max = null, ?int $step = null): int|string -+ function number(string $label, string $placeholder = '', string $default = '', bool|string $required = false, mixed $validate = null, string $hint = '', ?int $min = null, ?int $max = null, ?int $step = null, ?string $description = null): int|string - { - return (new NumberPrompt(...get_defined_vars()))->prompt(); - } -@@ -65,6 +67,7 @@ - string $hint = '', - int $rows = 5, - ?Closure $transform = null, -+ ?string $description = null, - ): string { - return (new TextareaPrompt(...get_defined_vars()))->prompt(); - } -@@ -81,6 +84,7 @@ - mixed $validate = null, - string $hint = '', - ?Closure $transform = null, -+ ?string $description = null, - ): string { - return (new PasswordPrompt(...get_defined_vars()))->prompt(); - } -@@ -103,6 +107,7 @@ - bool|string $required = true, - ?Closure $transform = null, - string|Closure $info = '', -+ ?string $description = null, - ): int|string { - return (new SelectPrompt(...get_defined_vars()))->prompt(); - } -@@ -126,6 +131,7 @@ - string $hint = 'Use the space bar to select options.', - ?Closure $transform = null, - string|Closure $info = '', -+ ?string $description = null, - ): array { - return (new MultiSelectPrompt(...get_defined_vars()))->prompt(); - } -@@ -144,6 +150,7 @@ - mixed $validate = null, - string $hint = '', - ?Closure $transform = null, -+ ?string $description = null, - ): bool { - return (new ConfirmPrompt(...get_defined_vars()))->prompt(); - } -@@ -186,6 +193,7 @@ - string $hint = '', - ?Closure $transform = null, - string|Closure $info = '', -+ ?string $description = null, - ): string { - return (new SuggestPrompt(...get_defined_vars()))->prompt(); - } -@@ -208,6 +216,7 @@ - bool|string $required = true, - ?Closure $transform = null, - string|Closure $info = '', -+ ?string $description = null, - ): int|string { - return (new SearchPrompt(...get_defined_vars()))->prompt(); - } -@@ -230,6 +239,7 @@ - string $hint = 'Use the space bar to select options.', - ?Closure $transform = null, - string|Closure $info = '', -+ ?string $description = null, - ): array { - return (new MultiSearchPrompt(...get_defined_vars()))->prompt(); - } diff --git a/.vortex/installer/patches/reroot-patch.php b/.vortex/installer/patches/reroot-patch.php deleted file mode 100644 index 0ad577c071..0000000000 --- a/.vortex/installer/patches/reroot-patch.php +++ /dev/null @@ -1,86 +0,0 @@ - - * - * Example: - * php .vortex/installer/patches/reroot-patch.php \ - * /tmp/raw.patch \ - * .vortex/installer/patches/laravel-prompts-fork-parity.patch \ - * /tmp/prompts-upstream/ \ - * /tmp/prompts-fork/ - * - * The prefixes must end with a slash and correspond to the two directories - * passed to `diff -ruN` when generating the source patch. - */ - -if ($argc !== 5) { - fwrite(STDERR, "Usage: php reroot-patch.php \n"); - exit(2); -} - -[$_, $source, $target, $upstream_prefix, $fork_prefix] = $argv; - -if (!str_ends_with($upstream_prefix, '/') || !str_ends_with($fork_prefix, '/')) { - fwrite(STDERR, "Prefix arguments must end with a slash.\n"); - exit(2); -} - -$lines = file($source, FILE_IGNORE_NEW_LINES); -if ($lines === FALSE) { - fwrite(STDERR, sprintf("Failed to read source patch: %s\n", $source)); - exit(1); -} - -$out = []; - -foreach ($lines as $line) { - if (str_starts_with($line, 'diff -ruN ')) { - $line = str_replace($upstream_prefix, 'a/', $line); - $line = str_replace($fork_prefix, 'b/', $line); - $out[] = $line; - - continue; - } - - if (str_starts_with($line, '--- ')) { - $path = substr($line, 4); - $tab_pos = strpos($path, "\t"); - if ($tab_pos !== FALSE) { - $path = substr($path, 0, $tab_pos); - } - $path = str_replace($upstream_prefix, 'a/', $path); - $out[] = '--- ' . $path; - - continue; - } - - if (str_starts_with($line, '+++ ')) { - $path = substr($line, 4); - $tab_pos = strpos($path, "\t"); - if ($tab_pos !== FALSE) { - $path = substr($path, 0, $tab_pos); - } - $path = str_replace($fork_prefix, 'b/', $path); - $out[] = '+++ ' . $path; - - continue; - } - - $out[] = $line; -} - -$result = implode("\n", $out) . "\n"; - -if (file_put_contents($target, $result) === FALSE) { - fwrite(STDERR, sprintf("Failed to write target patch: %s\n", $target)); - exit(1); -} - -fwrite(STDOUT, sprintf("Wrote %d lines to %s\n", count($out), $target)); diff --git a/.vortex/installer/playground/task-streaming.php b/.vortex/installer/playground/task-streaming.php index 3370fd29ab..c56aa47932 100644 --- a/.vortex/installer/playground/task-streaming.php +++ b/.vortex/installer/playground/task-streaming.php @@ -129,23 +129,25 @@ Task::action( label: 'Streaming task with nested spinner', action: function () { - // The nested command uses spin() which outputs cursor control sequences. - \Laravel\Prompts\spin( - function () { + // The nested non-streaming task outputs cursor control sequences. + Task::action( + label: 'Nested spinner task...', + action: function () { usleep(300000); usleep(300000); usleep(300000); + return true; }, - 'Nested spinner task...' ); echo "AFTER SPINNER 1\n"; - \Laravel\Prompts\spin( - function () { + Task::action( + label: 'Another nested spinner task...', + action: function () { usleep(1000000); usleep(1000000); + return true; }, - 'Another nested spinner task...' ); echo "AFTER SPINNER 2\n"; diff --git a/.vortex/installer/playground/tui.php b/.vortex/installer/playground/tui.php index 54bca3b7e2..d036f08dfa 100755 --- a/.vortex/installer/playground/tui.php +++ b/.vortex/installer/playground/tui.php @@ -108,7 +108,7 @@ Tui::box("This is content inside a box.\nIt can have multiple lines.", "Box Title"); echo PHP_EOL; -// Info/Note/Error (Laravel Prompts styles). +// Info/Note/Error. echo "--- Messages ---" . PHP_EOL; Tui::info("This is an info message"); Tui::note("This is a note message"); diff --git a/.vortex/installer/src/Command/InstallCommand.php b/.vortex/installer/src/Command/InstallCommand.php index ba1082b0a3..02a4890cf2 100644 --- a/.vortex/installer/src/Command/InstallCommand.php +++ b/.vortex/installer/src/Command/InstallCommand.php @@ -193,13 +193,15 @@ protected function execute(InputInterface $input, OutputInterface $output): int hint: fn(): string => sprintf('Checking repository "%s" and reference "%s"', $this->artifact->getRepo(), $this->artifact->getRef()), success: fn(string $return): string => $return ); - Tui::line(''); } - Tui::line(Tui::dim('Press any key to continue...')); - Tui::getChar(); + Tui::pause('Press any key to continue...'); - $this->promptManager->runPrompts(); + if (!$this->promptManager->runPrompts()) { + Tui::info('Aborting project installation. No files were changed.'); + + return Command::FAILURE; + } Tui::list($this->promptManager->getResponsesSummary(), 'Installation summary'); @@ -286,7 +288,7 @@ function (string $dir, string $ref): void { if ($should_build) { $build_ok = Task::action( label: 'Building site', - action: fn(): bool => $this->runBuildCommand($output), + action: fn(): bool => $this->runBuildCommand(Tui::output()), streaming: TRUE, ); diff --git a/.vortex/installer/src/Prompts/Handlers/AbstractHandler.php b/.vortex/installer/src/Prompts/Handlers/AbstractHandler.php index a5493c3a2b..e329d596b4 100644 --- a/.vortex/installer/src/Prompts/Handlers/AbstractHandler.php +++ b/.vortex/installer/src/Prompts/Handlers/AbstractHandler.php @@ -7,6 +7,7 @@ use DrevOps\VortexInstaller\Prompts\PromptType; use DrevOps\VortexInstaller\Utils\Config; use DrevOps\VortexInstaller\Utils\Converter; +use DrevOps\VortexInstaller\Utils\Tui; abstract class AbstractHandler implements HandlerInterface { @@ -37,6 +38,11 @@ abstract class AbstractHandler implements HandlerInterface { */ protected array $responses; + /** + * The answer supplied with the --prompts option. + */ + protected null|string|bool|array $override = NULL; + /** * Constructor. */ @@ -182,6 +188,97 @@ public function resolvedMessage(array $responses, mixed $resolved): ?string { return NULL; } + /** + * {@inheritdoc} + */ + public function setOverride(null|string|bool|array $override): static { + $this->override = $override; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function key(): string { + return static::id(); + } + + /** + * {@inheritdoc} + */ + public function widget(): string { + return $this->type()->value; + } + + /** + * {@inheritdoc} + */ + public function condition(array $results): bool { + return $this->shouldRun($results); + } + + /** + * {@inheritdoc} + */ + public function arguments(array $results): array { + $type = $this->type(); + $options = $this->options($results); + + $arguments = [ + 'label' => $this->label(), + 'help' => $this->hint($results), + 'placeholder' => $this->placeholder($results), + 'transform' => $this->transform(), + 'validate' => $this->validate(), + 'description' => static::description($results), + 'required' => $this->isRequired() ?: NULL, + 'options' => $options, + 'scroll' => is_array($options) ? 10 : NULL, + // A discovered list keeps the order the project already has it in. + 'order' => $type === PromptType::MultiSelect ? 'default' : NULL, + ]; + + // A value read from the destination answers the step without asking, and + // may name a profile or theme outside the options. + $resolved = $this->resolvedValue($results); + + if (is_string($resolved)) { + $message = $this->resolvedMessage($results, $resolved); + + if ($message) { + Tui::success($message); + } + + if (is_array($options) && !array_key_exists($resolved, $options)) { + $arguments['options'] = $options + [$resolved => $resolved]; + } + + $arguments['discovered'] = $resolved; + + return array_filter($arguments, fn(mixed $value): bool => $value !== NULL); + } + + $default = $this->override ?? $this->discover() ?? $this->default($results); + + // The widgets reject a default outside the options, so a default that no + // longer matches one is dropped and the widget starts from its first + // option. + if (is_array($options) && $type === PromptType::Select && (!is_string($default) || !array_key_exists($default, $options))) { + $default = NULL; + } + + if (is_array($options) && $type === PromptType::MultiSelect && is_array($default)) { + $default = array_values(array_filter($default, fn($value): bool => array_key_exists($value, $options))); + } + + if ($default !== NULL && $default !== '') { + $arguments['default'] = $default; + } + + return array_filter($arguments, fn(mixed $value): bool => $value !== NULL); + } + /** * {@inheritdoc} */ diff --git a/.vortex/installer/src/Prompts/Handlers/HandlerInterface.php b/.vortex/installer/src/Prompts/Handlers/HandlerInterface.php index 1c25b4651c..b50dccd964 100644 --- a/.vortex/installer/src/Prompts/Handlers/HandlerInterface.php +++ b/.vortex/installer/src/Prompts/Handlers/HandlerInterface.php @@ -4,12 +4,16 @@ namespace DrevOps\VortexInstaller\Prompts\Handlers; +use AlexSkrypnyk\Prompty\PromptyStepInterface; use DrevOps\VortexInstaller\Prompts\PromptType; /** * The interface for the prompt handlers. + * + * Each handler is a Prompty flow step: it decides whether it is asked and what + * its widget shows. */ -interface HandlerInterface { +interface HandlerInterface extends PromptyStepInterface { /** * Reserved dependency key for system-state conditions. @@ -201,6 +205,15 @@ public function resolvedValue(array $responses): null|string|bool|array; */ public function resolvedMessage(array $responses, mixed $resolved): ?string; + /** + * Set the answer supplied with the --prompts option. + * + * @param string|bool|array|null $override + * The supplied answer, which pre-fills the prompt ahead of discovery and + * the handler default. + */ + public function setOverride(null|string|bool|array $override): static; + /** * Set the responses. * diff --git a/.vortex/installer/src/Prompts/PromptManager.php b/.vortex/installer/src/Prompts/PromptManager.php index b1986f3730..a0d60e1939 100644 --- a/.vortex/installer/src/Prompts/PromptManager.php +++ b/.vortex/installer/src/Prompts/PromptManager.php @@ -4,6 +4,7 @@ namespace DrevOps\VortexInstaller\Prompts; +use AlexSkrypnyk\Prompty\Prompty; use DrevOps\VortexInstaller\Prompts\Handlers\AbstractHandler; use DrevOps\VortexInstaller\Prompts\Handlers\AiCodeInstructions; use DrevOps\VortexInstaller\Prompts\Handlers\AiCodeReview; @@ -53,24 +54,13 @@ use DrevOps\VortexInstaller\Utils\Converter; use DrevOps\VortexInstaller\Utils\File; use DrevOps\VortexInstaller\Utils\Tui; -use Laravel\Prompts\FormBuilder; -use Laravel\Prompts\FormStep; use Symfony\Component\Console\Output\OutputInterface; -use function Laravel\Prompts\form; /** * Centralized place for providing prompts and their processing. */ class PromptManager { - /** - * Total number of top-level responses. - * - * Counted from the form in runPrompts() and used to display the progress of - * the prompts. - */ - protected int $totalResponses = 0; - /** * Array of responses. */ @@ -78,19 +68,9 @@ class PromptManager { /** * Responses describing the destination as the handlers found it. - * - * Collected while the prompts run, so each value is the one discovery - * produced with the same preceding responses in context. */ protected array $discoveredResponses = []; - /** - * Current response index. - * - * Used to display the progress of the prompts. - */ - protected int $currentResponseIndex = 0; - /** * Array of handlers. * @@ -98,15 +78,6 @@ class PromptManager { */ protected array $handlers = []; - /** - * Prompt overrides from --prompts CLI option. - * - * Keyed by handler ID with validated values. - * - * @var array - */ - protected array $promptOverrides = []; - /** * PromptManager constructor. * @@ -125,175 +96,122 @@ public function __construct( * * In non-interactive mode, each prompt returns its default, which includes * values discovered from the existing codebase. + * + * @return bool + * TRUE when every prompt was answered, FALSE when the user cancelled one. */ - public function runPrompts(): void { + public function runPrompts(): bool { // Quiet the TUI output in non-interactive mode; the original verbosity is - // restored after the form completes. + // restored after the prompts complete. $original_verbosity = Tui::output()->getVerbosity(); if ($this->config->getNoInteraction()) { Tui::output()->setVerbosity(OutputInterface::VERBOSITY_QUIET); } - // @formatter:off - // phpcs:disable Generic.Functions.FunctionCallArgumentSpacing.TooMuchSpaceAfterComma - // phpcs:disable Drupal.WhiteSpace.Comma.TooManySpaces - // phpcs:disable Drupal.WhiteSpace.ObjectOperatorIndent.Indent - // phpcs:disable Drupal.WhiteSpace.ScopeIndent.IncorrectExact - $form = form() - ->intro('General information') - ->add(fn($r, $pr, $n): mixed => $this->prompt(Name::class), Name::id()) - ->add(fn(array $r, $pr, $n): mixed => $this->prompt(MachineName::class, $r), MachineName::id()) - ->add(fn(array $r, $pr, $n): mixed => $this->prompt(Org::class, $r), Org::id()) - ->add(fn(array $r, $pr, $n): mixed => $this->prompt(OrgMachineName::class, $r), OrgMachineName::id()) - ->add(fn(array $r, $pr, $n): mixed => $this->prompt(Domain::class, $r), Domain::id()) - - ->intro('Drupal') - ->addIf( - fn(array $r): bool => $this->handler(Starter::id())->shouldRun($r), - fn(array $r, $pr, $n): mixed => $this->prompt(Starter::class, $r), - Starter::id() - ) - ->add( - fn(array $r, $pr, $n): string => $this->resolveOrPrompt(Profile::id(), $r, fn(): mixed => $this->prompt(Profile::class)), - Profile::id() - ) - ->addIf( - fn(array $r): bool => $this->handler(ProfileCustom::id())->shouldRun($r), - fn($r, $pr, $n): mixed => $this->prompt(ProfileCustom::class), - ProfileCustom::id() - ) - ->add(fn(array $r, $pr, $n): mixed => $this->prompt(Modules::class, $r), Modules::id()) - ->add(fn(array $r, $pr, $n): mixed => $this->prompt(ModulePrefix::class, $r), ModulePrefix::id()) - ->add(fn(array $r, $pr, $n): mixed => $this->prompt(CustomModules::class, $r), CustomModules::id()) - ->add( - fn(array $r, $pr, $n): string => $this->resolveOrPrompt(Theme::id(), $r, fn(): mixed => $this->prompt(Theme::class)), - Theme::id() - ) - ->addIf( - fn(array $r): bool => $this->handler(ThemeCustom::id())->shouldRun($r), - fn(array $r, $pr, $n): mixed => $this->prompt(ThemeCustom::class, $r), - ThemeCustom::id() - ) - ->addIf( - fn(array $r): bool => $this->handler(FrontendBuild::id())->shouldRun($r), - fn(array $r, $pr, $n): mixed => $this->prompt(FrontendBuild::class, $r), - FrontendBuild::id() - ) - ->addIf( - fn(array $r): bool => $this->handler(Storybook::id())->shouldRun($r), - fn(array $r, $pr, $n): mixed => $this->prompt(Storybook::class, $r), - Storybook::id() - ) - - ->intro('Code repository') - ->add(fn($r, $pr, $n): mixed => $this->prompt(CodeProvider::class), CodeProvider::id()) - ->add(fn($r, $pr, $n): mixed => $this->prompt(VersionScheme::class), VersionScheme::id()) - - ->intro('Environment') - ->add(fn($r, $pr, $n): mixed => $this->prompt(Timezone::class), Timezone::id()) - ->add(fn($r, $pr, $n): mixed => $this->prompt(Services::class), Services::id()) - ->add(fn($r, $pr, $n): mixed => $this->prompt(Tools::class), Tools::id()) - - ->intro('Hosting') - ->add(fn($r, $pr, $n): mixed => $this->prompt(HostingProvider::class), HostingProvider::id()) - ->addIf( - fn(array $r): bool => $this->handler(HostingProjectName::id())->shouldRun($r), - fn(array $r, $pr, $n): mixed => $this->prompt(HostingProjectName::class, $r), - HostingProjectName::id() - ) - ->add( - fn(array $r, $pr, $n): string => $this->resolveOrPrompt(Webroot::id(), $r, fn(): mixed => $this->prompt(Webroot::class, $r)), - Webroot::id() - ) - - ->intro('Deployment') - ->add(fn(array $r, $pr, $n): mixed => $this->prompt(DeployTypes::class, $r), DeployTypes::id()) - - ->intro('Workflow') - ->add(fn($r, $pr, $n): mixed => $this->prompt(ProvisionType::class), ProvisionType::id()) - ->addIf( - fn(array $r): bool => $this->handler(DatabaseFetchSource::id())->shouldRun($r), - fn(array $r, $pr, $n): mixed => $this->prompt(DatabaseFetchSource::class, $r), - DatabaseFetchSource::id() - ) - ->addIf( - fn(array $r): bool => $this->handler(DatabaseImage::id())->shouldRun($r), - fn(array $r, $pr, $n): mixed => $this->prompt(DatabaseImage::class, $r), - DatabaseImage::id() - ) - ->add(fn($r, $pr, $n): mixed => $this->prompt(Migration::class), Migration::id()) - ->addIf( - fn(array $r): bool => $this->handler(MigrationFetchSource::id())->shouldRun($r), - fn(array $r, $pr, $n): mixed => $this->prompt(MigrationFetchSource::class, $r), - MigrationFetchSource::id() - ) - ->addIf( - fn(array $r): bool => $this->handler(MigrationImage::id())->shouldRun($r), - fn(array $r, $pr, $n): mixed => $this->prompt(MigrationImage::class, $r), - MigrationImage::id() - ) - - ->intro('Notifications') - ->add(fn($r, $pr, $n): mixed => $this->prompt(NotificationChannels::class), NotificationChannels::id()) - - ->intro('Continuous Integration') - ->add(fn(array $r, $pr, $n): mixed => $this->prompt(CiProvider::class, $r), CiProvider::id()) - ->add(fn($r, $pr, $n): mixed => $this->prompt(VisualRegression::class), VisualRegression::id()) - ->add(fn($r, $pr, $n): mixed => $this->prompt(Gitleaks::class), Gitleaks::id()) - - ->intro('Automations') - ->add(fn($r, $pr, $n): mixed => $this->prompt(DependencyUpdatesProvider::class), DependencyUpdatesProvider::id()) - ->addIf( - fn(array $r): bool => $this->handler(DependencyUpdatesAutomerge::id())->shouldRun($r), - fn(array $r, $pr, $n): mixed => $this->prompt(DependencyUpdatesAutomerge::class, $r), - DependencyUpdatesAutomerge::id() - ) - ->add(fn($r, $pr, $n): mixed => $this->prompt(CodeCoverageProvider::class), CodeCoverageProvider::id()) - ->add(fn($r, $pr, $n): mixed => $this->prompt(AssignAuthorPr::class), AssignAuthorPr::id()) - ->add(fn($r, $pr, $n): mixed => $this->prompt(LabelMergeConflictsPr::class), LabelMergeConflictsPr::id()) - - ->intro('Documentation') - ->add(fn($r, $pr, $n): mixed => $this->prompt(PreserveDocsProject::class), PreserveDocsProject::id()) - - ->intro('AI') - ->add(fn($r, $pr, $n): mixed => $this->prompt(AiCodeInstructions::class), AiCodeInstructions::id()) - ->add(fn($r, $pr, $n): mixed => $this->prompt(AiCodeReview::class), AiCodeReview::id()); - - // @formatter:on - // phpcs:enable Generic.Functions.FunctionCallArgumentSpacing.TooMuchSpaceAfterComma - // phpcs:enable Drupal.WhiteSpace.Comma.TooManySpaces - // phpcs:enable Drupal.WhiteSpace.ObjectOperatorIndent.Indent - // phpcs:enable Drupal.WhiteSpace.ScopeIndent.IncorrectExact - - $this->totalResponses = $this->countPrompts($form); - - $responses = $form->submit(); - - // Filter out elements with numeric keys returned by intro() calls. - $responses = array_filter($responses, fn($key): bool => !is_numeric($key), ARRAY_FILTER_USE_KEY); - - if ($this->config->getNoInteraction()) { - Tui::output()->setVerbosity($original_verbosity); + // Each handler decides whether its step is asked and what it shows, so + // the chain declares only the order, the sections and the nesting. + $h = $this->handlers; + + // phpcs:disable Drupal.WhiteSpace.ObjectOperatorIndent -- Indentation follows the nesting of the steps. + $responses = Prompty::flow() + ->section('General information') + ->add($h[Name::id()]) + ->add($h[MachineName::id()]) + ->add($h[Org::id()]) + ->add($h[OrgMachineName::id()]) + ->add($h[Domain::id()]) + ->section('Drupal') + ->add($h[Starter::id()]) + ->add($h[Profile::id()]) + ->children() + ->add($h[ProfileCustom::id()]) + ->end() + ->add($h[Modules::id()]) + ->add($h[ModulePrefix::id()]) + ->add($h[CustomModules::id()]) + ->add($h[Theme::id()]) + ->children() + ->add($h[ThemeCustom::id()]) + ->add($h[FrontendBuild::id()]) + ->add($h[Storybook::id()]) + ->end() + ->section('Code repository') + ->add($h[CodeProvider::id()]) + ->add($h[VersionScheme::id()]) + ->section('Environment') + ->add($h[Timezone::id()]) + ->add($h[Services::id()]) + ->add($h[Tools::id()]) + ->section('Hosting') + ->add($h[HostingProvider::id()]) + ->children() + ->add($h[HostingProjectName::id()]) + ->end() + ->add($h[Webroot::id()]) + ->section('Deployment') + ->add($h[DeployTypes::id()]) + ->section('Workflow') + ->add($h[ProvisionType::id()]) + ->children() + ->add($h[DatabaseFetchSource::id()]) + ->children() + ->add($h[DatabaseImage::id()]) + ->end() + ->end() + ->add($h[Migration::id()]) + ->children() + ->add($h[MigrationFetchSource::id()]) + ->children() + ->add($h[MigrationImage::id()]) + ->end() + ->end() + ->section('Notifications') + ->add($h[NotificationChannels::id()]) + ->section('Continuous Integration') + ->add($h[CiProvider::id()]) + ->add($h[VisualRegression::id()]) + ->add($h[Gitleaks::id()]) + ->section('Automations') + ->add($h[DependencyUpdatesProvider::id()]) + ->children() + ->add($h[DependencyUpdatesAutomerge::id()]) + ->end() + ->add($h[CodeCoverageProvider::id()]) + ->add($h[AssignAuthorPr::id()]) + ->add($h[LabelMergeConflictsPr::id()]) + ->section('Documentation') + ->add($h[PreserveDocsProject::id()]) + ->section('AI') + ->add($h[AiCodeInstructions::id()]) + ->add($h[AiCodeReview::id()]) + ->run(numbering: 'total', env_prefix: 'VORTEX_INSTALLER_PROMPT_'); + // phpcs:enable Drupal.WhiteSpace.ObjectOperatorIndent + + Tui::output()->setVerbosity($original_verbosity); + + // The flow answers NULL only when the user cancels a step. + if ($responses === NULL) { + return FALSE; } $this->responses = $this->normalizeResponses($responses); - // A conditional prompt this run skips never reaches args(), so its handler - // is asked directly. Otherwise the answer describing the destination would - // be replaced by the one describing this run. + // A value read from the destination describes the project as installed, + // so it replaces the answer this run collected. + $discovered = []; + foreach ($this->handlers as $id => $handler) { - if (!isset($this->discoveredResponses[$id])) { - $discovered = $handler->discover(); + $resolved = $handler->resolvedValue($responses); + $value = is_string($resolved) ? $resolved : $handler->discover(); - if ($discovered !== NULL) { - $this->discoveredResponses[$id] = $discovered; - } + if ($value !== NULL) { + $discovered[$id] = $value; } } - // Discovery covers only the handlers that read the destination, so the - // collected answers fill the rest. - $this->discoveredResponses = $this->normalizeResponses(array_replace($responses, $this->discoveredResponses)); + $this->discoveredResponses = $this->normalizeResponses(array_replace($responses, $discovered)); + + return TRUE; } /** @@ -551,48 +469,6 @@ public function getProcessHandlers(): array { return $handlers; } - /** - * Generate a label for a prompt. - * - * @param string $text - * The text to display in the label. - * @param string|null $suffix - * An optional suffix to display in the label. - * - * @return string - * The formatted label text. - */ - protected function label(string $text, ?string $suffix = NULL): string { - if ($suffix === NULL) { - $this->currentResponseIndex++; - } - - $suffix = $suffix !== NULL ? $this->currentResponseIndex . '.' . $suffix : $this->currentResponseIndex; - - return $text . ' ' . Tui::dim('(' . $suffix . '/' . $this->totalResponses . ')'); - } - - /** - * Count the prompts a form defines. - * - * Steps added by intro() carry no name, so the named steps are the prompts. - * Conditional steps are counted as well, because whether they run depends on - * answers the run has not collected yet, so the result is the most prompts a - * run can ask. - * - * @param \Laravel\Prompts\FormBuilder $form - * The form built in runPrompts(). - * - * @return int - * The number of prompts. - */ - protected function countPrompts(FormBuilder $form): int { - /** @var array $steps */ - $steps = (new \ReflectionProperty($form, 'steps'))->getValue($form); - - return count(array_filter($steps, fn(FormStep $step): bool => $step->name !== NULL)); - } - /** * Collect and initialize handlers. */ @@ -659,150 +535,9 @@ protected function resolvePromptOverrides(): void { foreach ($raw as $key => $value) { if (isset($this->handlers[$key])) { - $this->promptOverrides[$key] = $value; + $this->handlers[$key]->setOverride($value); } } } - /** - * Dispatch a prompt using the handler's type enum. - * - * @param string $handler_class - * The handler class name. - * @param array $responses - * Current form responses for context-aware methods. - * - * @return mixed - * The prompt result. - */ - protected function prompt(string $handler_class, array $responses = []): mixed { - $fn = $this->handler($handler_class::id())->type()->promptFunction(); - - return $fn(...$this->args($handler_class, NULL, $responses)); - } - - /** - * Convert handler properties to Laravel prompts. - * - * Kept deliberately unoptimized to ease debugging and future changes. - * - * @param string $handler_class - * The handler class name. - * @param mixed $default_override - * Optional override for the default value (for response dependencies). - * @param array $responses - * Current form responses for context-aware methods. - * - * @return array - * Array of prompt arguments suitable for Laravel prompts. - */ - protected function args(string $handler_class, mixed $default_override = NULL, array $responses = []): array { - $id = $handler_class::id(); - $handler = $this->handler($id); - - $args = [ - 'label' => $this->label($handler->label()), - 'hint' => $handler->hint($responses), - 'placeholder' => $handler->placeholder($responses), - 'transform' => $handler->transform(), - 'validate' => $handler->validate(), - ]; - - $description = $handler::description($responses); - if ($description !== NULL) { - $args['description'] = PHP_EOL . $description . PHP_EOL; - } - - if ($handler->isRequired()) { - $args['required'] = TRUE; - } - - $options = $handler->options($responses); - if (is_array($options)) { - $args['options'] = $options; - $args['scroll'] = 10; - } - - $default_from_handler = $handler->default($responses); - $default_from_prompts = $this->promptOverrides[$id] ?? NULL; - $default_from_discovery = $handler->discover(); - - if ($default_from_discovery !== NULL) { - $this->discoveredResponses[$id] = $default_from_discovery; - } - - if ($default_from_prompts !== NULL) { - $default = $default_from_prompts; - } - elseif ($default_from_discovery !== NULL) { - $default = $default_from_discovery; - } - elseif ($default_override !== NULL) { - $default = $default_override; - } - else { - $default = $default_from_handler; - } - - if ($default !== NULL && $default !== '') { - $args['default'] = $default; - } - - return array_filter($args, fn($value): bool => $value !== NULL); - } - - /** - * Resolve a value via handler or prompt the user. - * - * @param string $handler_id - * The handler ID. - * @param array $r - * Current form responses for context-aware methods. - * @param callable $prompt - * The prompt callable to use if the value is not resolved. - * - * @return string - * The resolved value. - */ - protected function resolveOrPrompt(string $handler_id, array $r, callable $prompt): string { - $handler = $this->handler($handler_id); - $resolved = $handler->resolvedValue($r); - - if (is_string($resolved)) { - $message = $handler->resolvedMessage($r, $resolved); - - if ($message) { - Tui::success($message); - } - - // A resolved value is read from the destination, so it stands in for - // discovery for handlers that never reach a prompt. - $this->discoveredResponses[$handler_id] = $resolved; - - return $resolved; - } - - return (string) $prompt(); - } - - /** - * Get a registered handler. - * - * @param string $id - * The handler ID. - * - * @return \DrevOps\VortexInstaller\Prompts\Handlers\HandlerInterface - * The handler instance. - * - * @throws \RuntimeException - * If no handler is registered for the ID. - */ - protected function handler(string $id): HandlerInterface { - if (!array_key_exists($id, $this->handlers)) { - throw new \RuntimeException(sprintf('Handler for "%s" not found.', $id)); - } - - return $this->handlers[$id]; - } - } diff --git a/.vortex/installer/src/Prompts/PromptType.php b/.vortex/installer/src/Prompts/PromptType.php index db8a0a799d..47a27b06dc 100644 --- a/.vortex/installer/src/Prompts/PromptType.php +++ b/.vortex/installer/src/Prompts/PromptType.php @@ -4,20 +4,8 @@ namespace DrevOps\VortexInstaller\Prompts; -use function Laravel\Prompts\confirm; -use function Laravel\Prompts\multisearch; -use function Laravel\Prompts\multiselect; -use function Laravel\Prompts\number; -use function Laravel\Prompts\password; -use function Laravel\Prompts\pause; -use function Laravel\Prompts\search; -use function Laravel\Prompts\select; -use function Laravel\Prompts\suggest; -use function Laravel\Prompts\text; -use function Laravel\Prompts\textarea; - /** - * Prompt input types covering all Laravel Prompts input types. + * Prompt input types, valued as the Prompty widget names. */ enum PromptType: string { @@ -31,35 +19,4 @@ enum PromptType: string { case Suggest = 'suggest'; - case Number = 'number'; - - case Textarea = 'textarea'; - - case Password = 'password'; - - case Search = 'search'; - - case MultiSearch = 'multisearch'; - - case Pause = 'pause'; - - /** - * Get the Laravel Prompts function for this type. - */ - public function promptFunction(): \Closure { - return match ($this) { - self::Text => text(...), - self::Select => select(...), - self::MultiSelect => multiselect(...), - self::Confirm => confirm(...), - self::Suggest => suggest(...), - self::Number => number(...), - self::Textarea => textarea(...), - self::Password => password(...), - self::Search => search(...), - self::MultiSearch => multisearch(...), - self::Pause => pause(...), - }; - } - } diff --git a/.vortex/installer/src/Task/Task.php b/.vortex/installer/src/Task/Task.php index a6560b361f..09a5902ba8 100644 --- a/.vortex/installer/src/Task/Task.php +++ b/.vortex/installer/src/Task/Task.php @@ -4,16 +4,12 @@ namespace DrevOps\VortexInstaller\Task; -use DrevOps\VortexInstaller\Utils\Strings; +use AlexSkrypnyk\Prompty\Prompty; use DrevOps\VortexInstaller\Utils\Tui; -use function Laravel\Prompts\spin; +use Symfony\Component\Console\Output\StreamOutput; class Task { - protected static string $message; - - protected static ?string $hint; - public static function action( \Closure|string $label, ?\Closure $action = NULL, @@ -28,80 +24,92 @@ public static function action( throw new \InvalidArgumentException('Action must be callable.'); } - $label = Tui::normalizeText($label); - - if ($streaming) { - $original_output = Tui::output(); + // Prompty draws 1 task at a time, so a task inside a streamed task is + // part of that task's output. + if (Tui::isCaptured()) { + return self::plain($label, $action, $hint, $success, $failure); + } - $task_output = new TaskOutput($original_output); + $output = Tui::output(); + $is_interactive = Tui::isInteractive(); - self::start($label); + $run = function () use ($action, $output, $is_interactive, $streaming): mixed { + if ($streaming) { + Tui::capture(TRUE); + } - Tui::setOutput($task_output); + try { + return $action(); + } + finally { + if ($streaming) { + Tui::capture(FALSE); + } + + // A command run by the action initializes the TUI with its own output, + // so the result line needs this command's output back. + Tui::init($output, $is_interactive); + } + }; - ob_start(function (string|iterable $buffer) use ($task_output): string { - $task_output->write($buffer); - return ''; - }, 1); + // Lines written to php://output go through the output buffer that a + // streamed task captures. + if ($streaming) { + $stream = fopen('php://output', 'w'); - $return = $action(); + if ($stream === FALSE) { + throw new \RuntimeException('Could not open php://output for a streamed task.'); + } - ob_end_clean(); - Tui::setOutput($original_output); - } - else { - // @phpstan-ignore-next-line - $return = spin($action, Tui::yellow($label)); - self::label($label, $hint && is_callable($hint) ? $hint() : $hint, is_array($return) ? $return : NULL, Strings::isAsciiStart($label) ? 2 : 3); + Tui::setOutput(new StreamOutput($stream, $output->getVerbosity(), $output->isDecorated())); } - if ($return === FALSE) { - $failure = $failure && is_callable($failure) ? $failure() : $failure; - Tui::error($failure ? Tui::normalizeText($failure) : 'FAILED'); + try { + return Prompty::task($label, action: $run, hint: $hint ?? '', success: $success ?? '', failure: $failure ?? '', stream: $streaming); } - else { - $success = $success && is_callable($success) ? $success($return) : $success; - self::ok($success ? Tui::normalizeText($success) : 'OK'); + finally { + Tui::setOutput($output); } - - return $return; } - protected static function label(string $message, ?string $hint = NULL, ?array $sublist = NULL, int $sublist_indent = 3): void { - $width = Tui::terminalWidth(); - $right_offset = 10; - - $message = '✦ ' . $message; - $message = Tui::normalizeText($message); - - self::$message = Tui::blue(wordwrap($message, $width - $right_offset, PHP_EOL)); - self::$hint = $hint ? wordwrap(Tui::normalizeText($hint), $width - $right_offset, PHP_EOL) : NULL; - - Tui::note(self::$message); - Tui::note(str_repeat(Tui::caretUp(), 5)); - - if (self::$hint) { - Tui::note(str_repeat(' ', $sublist_indent) . Tui::dim(self::$hint)); - Tui::note(str_repeat(Tui::caretUp(), 5)); + /** + * Run an action and report it as plain lines. + * + * @param string $label + * The task label. + * @param \Closure $action + * The action to run. + * @param \Closure|string|null $hint + * The hint, or a callable that receives the action's return value. + * @param \Closure|string|null $success + * The success message, or a callable that receives the return value. + * @param \Closure|string|null $failure + * The failure message, or a callable that receives the return value. + * + * @return mixed + * The value the action returns. + */ + protected static function plain(string $label, \Closure $action, \Closure|string|null $hint, \Closure|string|null $success, \Closure|string|null $failure): mixed { + Tui::line($label, 0); + + $return = $action(); + + $hint = is_callable($hint) ? $hint($return) : $hint; + if ($hint) { + Tui::line($hint, 2); } - if (is_array($sublist)) { - foreach ($sublist as $value) { - Tui::note(str_repeat(' ', $sublist_indent) . Tui::dim($value)); - Tui::note(str_repeat(Tui::caretUp(), 5)); - } + foreach (is_array($return) ? $return : [] as $detail) { + Tui::line((string) $detail, 2); } - } - protected static function ok(string $text = 'OK'): void { - $ok = Tui::green(Tui::normalizeText('✓ ' . $text)); - Tui::note($ok); - Tui::note(str_repeat(Tui::caretUp(), 4)); - } + $is_ok = $return !== FALSE; + $message = $is_ok ? $success : $failure; + $message = is_callable($message) ? $message($return) : $message; - protected static function start(string $label): void { - $message = '✦ ' . $label; - Tui::line(Tui::blue(Tui::normalizeText($message))); + Tui::line(($is_ok ? '✓ ' : '✕ ') . ($message ?: ($is_ok ? 'OK' : 'FAILED')), 0); + + return $return; } } diff --git a/.vortex/installer/src/Task/TaskOutput.php b/.vortex/installer/src/Task/TaskOutput.php deleted file mode 100644 index 932cc671ba..0000000000 --- a/.vortex/installer/src/Task/TaskOutput.php +++ /dev/null @@ -1,128 +0,0 @@ - $messages - * The message or messages to write. - * @param bool $newline - * Whether to add a newline after the message. - * @param int $options - * Write options. - */ - public function write(string|iterable $messages, bool $newline = FALSE, int $options = 0): void { - $this->wrapped->write($this->dim($messages), $newline, $options); - } - - /** - * Writes a message to the output and adds a newline at the end. - * - * @param string|iterable $messages - * The message or messages to write. - * @param int $options - * Write options. - */ - public function writeln(string|iterable $messages, int $options = 0): void { - $this->wrapped->writeln($this->dim($messages), $options); - } - - /** - * Dim a message or every message in a list. - * - * @param string|iterable $messages - * The message or messages to dim. - * - * @return string|array - * The dimmed message or messages. - */ - protected function dim(string|iterable $messages): string|array { - return is_iterable($messages) ? array_map(Tui::dim(...), (array) $messages) : Tui::dim($messages); - } - - /** - * {@inheritdoc} - */ - public function setVerbosity(int $level): void { - $this->wrapped->setVerbosity($level); - } - - /** - * {@inheritdoc} - */ - public function getVerbosity(): int { - return $this->wrapped->getVerbosity(); - } - - /** - * {@inheritdoc} - */ - public function isQuiet(): bool { - return $this->wrapped->isQuiet(); - } - - /** - * {@inheritdoc} - */ - public function isVerbose(): bool { - return $this->wrapped->isVerbose(); - } - - /** - * {@inheritdoc} - */ - public function isVeryVerbose(): bool { - return $this->wrapped->isVeryVerbose(); - } - - /** - * {@inheritdoc} - */ - public function isDebug(): bool { - return $this->wrapped->isDebug(); - } - - /** - * {@inheritdoc} - */ - public function setDecorated(bool $decorated): void { - $this->wrapped->setDecorated($decorated); - } - - /** - * {@inheritdoc} - */ - public function isDecorated(): bool { - return $this->wrapped->isDecorated(); - } - - /** - * {@inheritdoc} - */ - public function setFormatter(OutputFormatterInterface $formatter): void { - $this->wrapped->setFormatter($formatter); - } - - /** - * {@inheritdoc} - */ - public function getFormatter(): OutputFormatterInterface { - return $this->wrapped->getFormatter(); - } - -} diff --git a/.vortex/installer/src/Utils/Tui.php b/.vortex/installer/src/Utils/Tui.php index 76fc5adf42..e3fa6caf57 100644 --- a/.vortex/installer/src/Utils/Tui.php +++ b/.vortex/installer/src/Utils/Tui.php @@ -4,15 +4,8 @@ namespace DrevOps\VortexInstaller\Utils; -use Laravel\Prompts\Prompt; -use Laravel\Prompts\Terminal; +use AlexSkrypnyk\Prompty\Prompty; use Symfony\Component\Console\Output\OutputInterface; -use function Laravel\Prompts\confirm; -use function Laravel\Prompts\error; -use function Laravel\Prompts\info; -use function Laravel\Prompts\intro; -use function Laravel\Prompts\note; -use function Laravel\Prompts\table; class Tui { @@ -20,21 +13,44 @@ class Tui { protected static OutputInterface $output; + /** + * The output Prompty draws to. + * + * Only init() sets it, so setOutput() redirects lines but not Prompty's + * frames. + */ + protected static OutputInterface $promptyOutput; + protected static bool $isInteractive = TRUE; + /** + * The number of streamed tasks whose action is running. + * + * While it is above 0, output is the content of the outer task, so it is + * written as plain lines to $output instead of being drawn by Prompty. + */ + protected static int $captureDepth = 0; + public static function init(OutputInterface $output, bool $is_interactive = TRUE): void { self::$output = $output; self::$isInteractive = $is_interactive; - // Symfony console styles are not used here because Laravel Prompts does - // not correctly calculate the length of strings with style tags, which - // breaks the layout. Instead, helpers in this class apply ANSI escape - // codes directly. - Prompt::setOutput($output); - - if (!$is_interactive) { - Prompt::interactive(FALSE); + // A command run inside a streamed task keeps Prompty drawing the task. + if (self::isCaptured()) { + return; } + + self::$promptyOutput = $output; + + // Raw output keeps the prompt frames away from the console formatter. + Prompty::configure( + labels: ['done' => 'OK', 'failed' => 'FAILED'], + unicode: TRUE, + ansi: $output->isDecorated(), + output: fn(string $chunk) => self::$promptyOutput->write($chunk, FALSE, OutputInterface::OUTPUT_RAW), + interactive: $is_interactive, + placeholder_fallback: FALSE, + ); } public static function output(): OutputInterface { @@ -46,23 +62,40 @@ public static function output(): OutputInterface { public static function setOutput(OutputInterface $output): void { self::$output = $output; - Prompt::setOutput($output); + } + + public static function isInteractive(): bool { + return self::$isInteractive; + } + + /** + * Start or end capturing output as the content of a streamed task. + * + * @param bool $is_captured + * TRUE when a streamed task's action starts, FALSE when it ends. + */ + public static function capture(bool $is_captured): void { + self::$captureDepth = max(0, self::$captureDepth + ($is_captured ? 1 : -1)); + } + + public static function isCaptured(): bool { + return self::$captureDepth > 0; } public static function info(string $message): void { - intro($message); + self::isCaptured() ? self::line($message, 0) : Prompty::note($message); } public static function note(string $message): void { - note($message); + self::isCaptured() ? self::line($message, 0) : Prompty::output(explode(PHP_EOL, $message)); } public static function success(string $message): void { - info($message); + self::isCaptured() ? self::line('✓ ' . $message, 0) : Prompty::note($message, type: 'success'); } public static function error(string $message): void { - error('✕ ' . $message); + self::isCaptured() ? self::line('✕ ' . $message, 0) : Prompty::note($message, type: 'error'); } public static function confirm(string $label, bool $default = TRUE, ?string $hint = NULL): bool { @@ -70,11 +103,12 @@ public static function confirm(string $label, bool $default = TRUE, ?string $hin return $default; } - return confirm( - label: $label, - default: $default, - hint: $hint ?? '', - ); + // A cancelled prompt answers NULL, which declines. + return (bool) Prompty::confirm($label, default: $default, help: $hint ?? ''); + } + + public static function pause(string $message): void { + Prompty::pause($message, erase: TRUE); } public static function line(string $message, int $padding = 1): void { @@ -119,100 +153,68 @@ public static function undim(string $text): string { return self::escapeMultiline($text, 22, 22); } - public static function getChar(): string { - if (!self::$isInteractive) { - return ''; - } - - // Disable input buffering. - system('stty cbreak -echo'); - - $res = fopen('php://stdin', 'r'); - if ($res === FALSE) { - return ''; - } - - $char = (string) fgetc($res); - - // Restore terminal settings. - system('stty -cbreak echo'); - - return $char; - } - protected static function escapeMultiline(string $text, int $color_code, int $end_code = 39): string { $lines = explode("\n", $text); $colored_lines = array_map(fn(string $line): string => sprintf("\033[%sm%s\033[%sm", $color_code, $line, $end_code), $lines); return implode("\n", $colored_lines); } - public static function caretDown(): string { - return "\033[B"; - } - - public static function caretUp(): string { - return "\033[A"; - } - - public static function caretEol(string $text): string { - $lines = explode(PHP_EOL, $text); - $longest = max(array_map(Strings::strlenPlain(...), $lines)); - - return "\033[" . $longest . "C"; - } - + /** + * Print a titled key-value list. + * + * @param array> $values + * Values keyed by their label. A value of LIST_SECTION_TITLE makes its key + * a section row, and a list value is joined with commas. + * @param string|null $title + * The title printed above the list. + */ public static function list(array $values, ?string $title): void { - foreach ($values as $key => $value) { - if (is_array($value)) { - $values[$key] = implode(', ', $value); - } - } - - $terminal_width = self::terminalWidth(); - - // (margin + 2 x border + 2 x padding) x 2 - 1 collapse divider width. - $column_width = max(1, (int) floor(($terminal_width - (1 + (1 + 1) * 2) * 2 - 1) / 2)); - - $header = []; $rows = []; + foreach ($values as $key => $value) { if ($value === self::LIST_SECTION_TITLE) { - $rows[] = [Tui::cyan(Tui::bold(self::normalizeText($key)))]; + $rows[] = (string) $key; continue; } - $key = self::normalizeText($key); - $value = self::normalizeText($value); - - $key = ' ' . wordwrap(self::normalizeText($key), $column_width + 2, PHP_EOL . ' ', TRUE); - $value = wordwrap(self::normalizeText($value), $column_width, PHP_EOL, TRUE); + $rows[] = [(string) $key, is_array($value) ? implode(', ', $value) : $value]; + } - $rows[] = [$key, $value]; + if ($title) { + self::info($title); } - intro(PHP_EOL . self::normalizeText($title) . PHP_EOL); - table($header, $rows); + self::table([], $rows); } - public static function box(string $content, ?string $title = NULL, ?int $width = NULL): void { - $rows = []; - - $width ??= self::terminalWidth(); + public static function box(string $content, ?string $title = NULL): void { + if (self::isCaptured()) { + self::line(trim(($title ? $title . PHP_EOL : '') . $content), 0); - // 1 margin + 1 border + 1 padding + 1 padding + 1 border + 1 margin. - $offset = 6; + return; + } - $content = wordwrap($content, $width - $offset, PHP_EOL, TRUE); + Prompty::box($content, title: $title ?? ''); + } + + /** + * Print rows as a table. + * + * @param array $header + * Header cells. An empty header draws no header row. + * @param array> $rows + * Table rows. A string row spans every column. + */ + public static function table(array $header, array $rows): void { + if (self::isCaptured()) { + foreach (array_merge($header === [] ? [] : [$header], $rows) as $row) { + self::line(is_array($row) ? implode(': ', $row) : $row, 0); + } - if ($title) { - $title = wordwrap($title, $width - $offset, PHP_EOL, FALSE); - $rows[] = [self::green($title)]; - $rows[] = [self::green(str_repeat('─', Strings::strlenPlain(explode(PHP_EOL, self::normalizeText($title))[0]))) . PHP_EOL]; + return; } - $rows[] = [$content]; - - table([], $rows); + Prompty::table($rows, headers: $header); } public static function center(string $text, int $width = 80, ?string $border = NULL): string { @@ -244,40 +246,7 @@ public static function center(string $text, int $width = 80, ?string $border = N } public static function terminalWidth(int $max = 100): int { - return min($max, max(20, (new Terminal())->cols())); - } - - public static function normalizeText(string $text): string { - if (!Strings::isAsciiStart($text)) { - return $text; - } - - $text = preg_replace('/\s{2,}/', ' ', $text); - - preg_match_all('/\X/u', (string) $text, $matches); - - $utf8_chars = $matches[0]; - $utf8_chars = array_map(fn(string $char): string => Strings::isAsciiStart($char) ? $char : $char . self::utfPadding($char), $utf8_chars); - - return implode('', $utf8_chars); - } - - protected static function utfPadding(string $char): string { - $padding = ''; - - $len = strlen($char); - $mblen = mb_strlen($char); - - // @see https://youtrack.jetbrains.com/issue/IJPL-101568/Terminal-display-Python-icon-in-wrong-width - if (str_contains((string) getenv('TERMINAL_EMULATOR'), 'JetBrains') && ($mblen === 1 && $len < 4)) { - $padding = ' '; - } - - if (str_contains((string) getenv('TERM_PROGRAM'), 'Apple_Terminal') && ($mblen > 1 && $len < 8)) { - return ' '; - } - - return $padding; + return min($max, max(20, Prompty::terminalWidth())); } } diff --git a/.vortex/installer/tests/Fixtures/handler_process/code_provider_other/.circleci/config.yml b/.vortex/installer/tests/Fixtures/handler_process/code_provider_other/.circleci/config.yml new file mode 100644 index 0000000000..f56bdf626c --- /dev/null +++ b/.vortex/installer/tests/Fixtures/handler_process/code_provider_other/.circleci/config.yml @@ -0,0 +1,653 @@ +# CircleCI configuration file for building, testing, and deploying. +# +# This configuration file uses the "docker" executor to run the Docker stack. +# +# A "runner" container, created from a specified container image, is used to +# checkout source code and run commands defined in this file. Application Docker +# containers defined in `docker-compose.yml` run on a *remote* Docker server +# controlled by CircleCI. +# The "runner" container uses Docker client to control the remote Docker server. +version: '2.1' + +aliases: + # SSH key fingerprint to fetch the database. + # Replace this key fingerprint with your own and remove this comment. + - &db_ssh_fingerprint "SHA256:6d+U5QubT0eAWz+4N2wt+WM2qx6o4cvyvQ6xILETJ84" + + # SSH key fingerprint to deploy code. + # Replace this key fingerprint with your own and remove this comment. + - &deploy_ssh_fingerprint "SHA256:6d+U5QubT0eAWz+4N2wt+WM2qx6o4cvyvQ6xILETJ84" + + # Schedule to run nightly database build (to cache the database for the next day). + - &nightly_db_schedule "0 18 * * *" + + # Shared runner container configuration applied to each job. + - &runner_config + working_directory: &working_directory ~/project + environment: + VORTEX_FETCH_DB_SSH_FINGERPRINT: *db_ssh_fingerprint + VORTEX_DEPLOY_SSH_FINGERPRINT: *deploy_ssh_fingerprint + docker: + # Using the 'runner' container where each job will be executed. + # This container has all the necessary tools to run a dockerized environment. + # https://github.com/drevops/ci-runner + # https://hub.docker.com/repository/docker/drevops/ci-runner/tags + - image: drevops/ci-runner:__VERSION__ + auth: + username: ${VORTEX_CONTAINER_REGISTRY_USER} + password: ${VORTEX_CONTAINER_REGISTRY_PASS} + environment: + # Set runner timezone via UI to ensure that executed operations use correct timestamps. + # https://en.wikipedia.org/wiki/List_of_tz_database_time_zones + TZ: UTC + # Set runner terminal capabilities. + TERM: xterm-256color + # Disable strict host key checking for SSH connections. + VORTEX_SSH_DISABLE_STRICT_HOST_KEY_CHECKING: "1" + # Remove all SSH keys from the runner container. + VORTEX_SSH_REMOVE_ALL_KEYS: "1" + # How often to refresh the cache of the DB dump. Refer to `date` command. + VORTEX_CI_DB_CACHE_TIMESTAMP: +%Y%m%d + # Use previous database caches on this branch as a fallback if the above cache + # does not match (for example, the cache is available only from the previous + # day). If "no" is set, the cache will be rebuilt from scratch. + VORTEX_CI_DB_CACHE_FALLBACK: "yes" + # Which branch to use as a source of DB caches. + VORTEX_CI_DB_CACHE_BRANCH: "develop" + # Directory to store test results. + VORTEX_CI_TEST_RESULTS: &test_results /tmp/tests + # Directory to store test artifacts. + VORTEX_CI_ARTIFACTS: &artifacts /tmp/artifacts + # Directory to use for artifact deployments. + VORTEX_DEPLOY_ARTIFACT_SRC: /tmp/workspace/code + # Source code location for artifact deployments. + VORTEX_DEPLOY_ARTIFACT_ROOT: *working_directory + # Report file location for artifact deployments. + VORTEX_DEPLOY_ARTIFACT_LOG: /tmp/artifacts/deployment_log.txt + # Check only minimal stack requirements. + VORTEX_DOCTOR_CHECK_MINIMAL: 1 + # CI runner resource class. + # https://circleci.com/docs/2.0/configuration-reference/#resource_class + # Change to 'large' for faster builds. + resource_class: medium + + - &step_setup_remote_docker + setup_remote_docker: + # Docker Layer Caching allows to significantly speed up builds by caching + # images built during previous runs. + # https://circleci.com/docs/2.0/docker-layer-caching/ + docker_layer_caching: false + version: default + + - &step_process_codebase_for_ci + run: + name: Process codebase to run in CI + command: | + find . -name "docker-compose.yml" -print0 | xargs -0 -I {} sh -c "sed -i -e '/###/d' {} && sed -i -e 's/##//' {}" + mkdir -p /tmp/workspace/code + + - &load_variables_from_dotenv + run: + name: Load environment variables from .env file + # Load variables from .env file, respecting existing values, and make them available for the next steps. + command: t=$(mktemp) && export -p >"${t}" && set -a && . ./.env && set +a && . "${t}" && export -p >> "$BASH_ENV" + +################################################################################ +# JOBS +################################################################################ + +jobs: + + # Lint job runs in parallel with database and build jobs. + lint: + <<: *runner_config + steps: + - checkout + - *step_process_codebase_for_ci + - *load_variables_from_dotenv + + - run: + name: Validate Composer configuration + command: composer validate --strict || [ "${VORTEX_CI_COMPOSER_VALIDATE_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Install Vortex tooling + command: ./scripts/vortex-tooling.sh + + - *step_setup_remote_docker + + - run: + name: Login to container registry + command: ./vendor/bin/vortex-login-container-registry + + - run: + name: Lint Dockerfiles with Hadolint + command: | + for file in $(find .docker \( -name 'Dockerfile' -o -name '*.dockerfile' \)); do + echo "Linting ${file}" && cat "${file}" | docker run --rm -i hadolint/hadolint:__VERSION__ || [ "${VORTEX_CI_HADOLINT_IGNORE_FAILURE:-0}" -eq 1 ] + done + + # The remote Docker engine has no access to the checkout, so the files + # are copied into the container. + - run: + name: Lint Docker Compose files with DCLint + command: | + container="$(docker create --rm zavoloklom/dclint:__VERSION__ .)" + docker cp ./. "${container}:/app" + docker start --attach "${container}" || [ "${VORTEX_CI_DCLINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Build stack + command: docker compose up --no-deps --detach cli + + - run: + name: Install development dependencies + command: | + docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ + if [ -n \"\${PACKAGE_TOKEN:-}\" ]; then composer config --global --auth github-oauth.github.com \"\${PACKAGE_TOKEN}\"; fi && \ + COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" + docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "npm ci" + + - run: + name: Validate Composer configuration is normalized + command: docker compose exec -T cli composer normalize --dry-run || [ "${VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPCS + command: docker compose exec -T cli vendor/bin/phpcs || [ "${VORTEX_CI_PHPCS_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPStan + command: docker compose exec -T cli vendor/bin/phpstan || [ "${VORTEX_CI_PHPSTAN_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Rector + command: docker compose exec -T cli vendor/bin/rector --dry-run || [ "${VORTEX_CI_RECTOR_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Twig CS Fixer + command: docker compose exec -T cli vendor/bin/twig-cs-fixer || [ "${VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Gherkin Lint + command: docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features || [ "${VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint module code with NodeJS linters + command: docker compose exec -T cli bash -c "npm run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint theme code with NodeJS linters + command: | + [ "${VORTEX_FRONTEND_BUILD_SKIP:-0}" -eq 1 ] && exit 0 + docker compose exec -T cli bash -c "npm --prefix=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + + # Audit job runs in its own workflow, independently of the commit workflow. + audit: + <<: *runner_config + steps: + - checkout + - *load_variables_from_dotenv + + - *step_setup_remote_docker + + - run: + name: Audit Composer packages + when: always + command: composer audit --locked || [ "${VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE:-0}" -eq 1 ] + + # The threshold is passed here rather than in 'package-audit.jsonc', because + # audit-ci passes every advisory when no threshold is set. + - run: + name: Audit npm packages + when: always + command: | + config=() + [ -f package-audit.jsonc ] && config=(--config package-audit.jsonc) + npx --yes audit-ci@__VERSION__ --high --extra-args=--package-lock-only "${config[@]}" || [ "${VORTEX_CI_NPM_AUDIT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Audit npm packages of the theme + when: always + command: | + dir="${WEBROOT}/themes/custom/${DRUPAL_THEME}" + config=() + [ -f "${dir}/package-audit.jsonc" ] && config=(--config "${dir}/package-audit.jsonc") + npx --yes audit-ci@__VERSION__ --high --extra-args=--package-lock-only --directory "${dir}" "${config[@]}" || [ "${VORTEX_CI_NPM_AUDIT_IGNORE_FAILURE:-0}" -eq 1 ] + + # The remote Docker engine has no access to the checkout, so the files + # are copied into the container. + - run: + name: Scan for committed secrets with Gitleaks + when: always + command: | + container="$(docker create --rm -w /repo ghcr.io/gitleaks/gitleaks:__VERSION__ dir . --no-banner)" + docker cp ./. "${container}:/repo" + docker start --attach "${container}" || [ "${VORTEX_CI_GITLEAKS_IGNORE_FAILURE:-0}" -eq 1 ] + + # Database handling is a first step of the build. + # - $VORTEX_CI_DB_CACHE_TIMESTAMP is used to determine if a fresh DB dump + # should be fetched for the current build. Usually, a daily database dump + # is sufficient for development activities. + # - $VORTEX_CI_DB_CACHE_FALLBACK is used if the cache did not match $VORTEX_CI_DB_CACHE_TIMESTAMP. + # This allows to rely on the cache from the previous days within the same branch. + database: &job-database + <<: *runner_config + steps: + - attach_workspace: + at: /tmp/workspace + + - add_ssh_keys: + fingerprints: + - *db_ssh_fingerprint + + - checkout + - *step_process_codebase_for_ci + - *load_variables_from_dotenv + + - run: + name: Install Vortex tooling + command: ./scripts/vortex-tooling.sh + + - *step_setup_remote_docker + + - run: + name: Create cache keys for database caching as files + command: | + echo "${VORTEX_CI_DB_CACHE_BRANCH}" | tee /tmp/db_cache_branch + echo "${VORTEX_CI_DB_CACHE_FALLBACK/no/${CIRCLE_BUILD_NUM}}" | tee /tmp/db_cache_fallback + date "${VORTEX_CI_DB_CACHE_TIMESTAMP}" | tee /tmp/db_cache_timestamp + echo "yes" | tee /tmp/db_cache_fallback_yes + + - restore_cache: + keys: + # Restore DB cache based on the cache strategy set by the cache keys below. + # https://circleci.com/docs/2.0/caching/#restoring-cache + # Bump the last segment of the version prefix below to force a cache reset. + # Lookup cache based on the default branch and a timestamp. Allows + # to use cache from the very first build on the day (sanitized database dump, for example). + - __VERSION__-{{ checksum "/tmp/db_cache_branch" }}-{{ checksum "/tmp/db_cache_fallback" }}-{{ checksum "/tmp/db_cache_timestamp" }} + # Fallback to caching by default branch name only. Allows to use + # cache from the branch build on the previous day. + - __VERSION__-{{ checksum "/tmp/db_cache_branch" }}-{{ checksum "/tmp/db_cache_fallback" }}- + + - run: + name: Fetch DB + command: VORTEX_FETCH_DB_SEMAPHORE=/tmp/fetch-db-fresh ./vendor/bin/vortex-fetch-db + no_output_timeout: 30m + + # Execute commands after database fetch script finished: if the + # DB dump was fetched - build the site (to ensure that the DB dump + # is valid) and export the DB using selected method (to support + # "file-to-image" or "image-to-file" conversions). + # Note that configuration changes and the DB updates are not applied, so + # the database will be cached in the same state as fetched. + - run: + name: Export DB + command: | + [ ! -f /tmp/fetch-db-fresh ] && echo "==> Database fetch semaphore file is missing. DB export will not proceed." && exit 0 + ./vendor/bin/vortex-refresh-db + no_output_timeout: 30m + + - save_cache: + # Save cache per default branch and the timestamp. + # The cache will not be saved if it already exists. + # Note that the cache fallback flag is enabled for this case in order + # to save cache even if the fallback is not used when restoring it. + key: __VERSION__-{{ checksum "/tmp/db_cache_branch" }}-{{ checksum "/tmp/db_cache_fallback_yes" }}-{{ checksum "/tmp/db_cache_timestamp" }} + paths: + - /root/project/.data + + # Nightly database job. Same as above, but with additional variables set. + # Triggered by the "nightly-db" schedule configured in CircleCI UI. + database-nightly: + <<: *job-database + environment: + VORTEX_FETCH_DB_SSH_FINGERPRINT: *db_ssh_fingerprint + VORTEX_DEPLOY_SSH_FINGERPRINT: *deploy_ssh_fingerprint + # Enforce fresh DB build (do not rely on fallback caches). + VORTEX_CI_DB_CACHE_FALLBACK: 'no' + # Do not build the Drupal front-end. + VORTEX_FRONTEND_BUILD_SKIP: 1 + + # Build and test is a second step of the build. The testing is performed + # within the same job to save time on provisioning during the job. + build: &job_build + <<: *runner_config + parallelism: 2 + steps: + - attach_workspace: + at: /tmp/workspace + + - checkout + - *step_process_codebase_for_ci + - *load_variables_from_dotenv + + - run: + name: Set test runner roles + command: | + # Which tools run on this node. Tools that only need to run once are + # pinned to the first node. Add a line for every additional tool and + # reference it in that tool's step. + # https://www.vortextemplate.com/docs/continuous-integration#test-parallelism + { + echo "export VORTEX_CI_RUNNER_INDEX=${CIRCLE_NODE_INDEX:-0}" + echo "export VORTEX_CI_RUNNER_TOTAL=${CIRCLE_NODE_TOTAL:-1}" + echo "export VORTEX_CI_IS_JEST_RUNNER=$([ "${CIRCLE_NODE_INDEX:-0}" -eq 0 ] && echo 1 || echo 0)" + echo "export VORTEX_CI_IS_PHPUNIT_RUNNER=$([ "${CIRCLE_NODE_INDEX:-0}" -eq 0 ] && echo 1 || echo 0)" + echo "export VORTEX_CI_IS_SDC_DEVEL_RUNNER=$([ "${CIRCLE_NODE_INDEX:-0}" -eq 0 ] && echo 1 || echo 0)" + # Runs on every node, using the `p` profile. + echo "export VORTEX_CI_IS_BEHAT_RUNNER=1" + # Subtracted from the node index to derive the profile number. + # Raise it by one for every leading node that does not run + # Behat, so the first Behat node still selects the `p0` + # catch-all profile. + echo "export VORTEX_CI_BEHAT_PROFILE_OFFSET=0" + } >> "${BASH_ENV}" + + - run: + name: Validate Composer configuration + command: composer validate --strict || [ "${VORTEX_CI_COMPOSER_VALIDATE_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Install Vortex tooling + command: ./scripts/vortex-tooling.sh + + - run: + name: Set cache keys for database caching + command: | + echo "${VORTEX_CI_DB_CACHE_BRANCH}" | tee /tmp/db_cache_branch + echo "yes" | tee /tmp/db_cache_fallback_yes + echo "$(date ${VORTEX_CI_DB_CACHE_TIMESTAMP})" | tee /tmp/db_cache_timestamp + + - restore_cache: + keys: + # Use cached artifacts from previous builds of this branch. + # https://circleci.com/docs/2.0/caching/#restoring-cache + - __VERSION__-{{ checksum "/tmp/db_cache_branch" }}-{{ checksum "/tmp/db_cache_fallback_yes" }}-{{ checksum "/tmp/db_cache_timestamp" }} + - __VERSION__-{{ checksum "/tmp/db_cache_branch" }}-{{ checksum "/tmp/db_cache_fallback_yes" }}- + + - *step_setup_remote_docker + + - run: + name: Login to container registry + command: ./vendor/bin/vortex-login-container-registry + + - run: + name: Build stack + command: docker compose up --detach && docker builder prune --all --force && docker image prune --force + + - run: + name: Export built codebase + command: | + echo "${VORTEX_DEPLOY_TYPES:-}" | grep -vq "artifact" && exit 0 || true + mkdir -p "/tmp/workspace/code" + docker compose --progress quiet cp -L cli:"/app/." "/tmp/workspace/code" + du -sh "/tmp/workspace/code" + + - run: + name: Install development dependencies + command: | + docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ + if [ -n \"\${PACKAGE_TOKEN:-}\" ]; then composer config --global --auth github-oauth.github.com \"\${PACKAGE_TOKEN}\"; fi && \ + COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" + docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "npm ci" + + - run: + name: Provision site + command: | + # Database dumps are removed from the runner once they are inside the + # container to avoid holding two copies for the rest of the job. + if [ -f .data/db.sql ]; then + docker compose exec cli mkdir -p .data + docker compose --progress quiet cp -L .data/db.sql cli:/app/.data/db.sql + rm -f .data/db.sql + fi + docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli ./vendor/bin/vortex-provision + no_output_timeout: 30m + + - run: + name: Test with Jest + command: | + [ "${VORTEX_CI_IS_JEST_RUNNER:-1}" = "1" ] || exit 0 + docker compose exec -T cli bash -c "npm test" || [ "${VORTEX_CI_JEST_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Test with PHPUnit + command: | + [ "${VORTEX_CI_IS_PHPUNIT_RUNNER:-1}" = "1" ] || exit 0 + docker compose exec -T cli vendor/bin/phpunit || [ "${VORTEX_CI_PHPUNIT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Process PHPUnit logs and coverage + command: | + [ "${VORTEX_CI_IS_PHPUNIT_RUNNER:-1}" = "1" ] || exit 0 + mkdir -p "${VORTEX_CI_ARTIFACTS}" + if docker compose ps --services --filter "status=running" | grep -q cli && docker compose exec cli test -d /app/.logs; then + docker compose --progress quiet cp cli:/app/.logs/. "${VORTEX_CI_ARTIFACTS}/" + fi + + - run: + name: Extract code coverage + command: | + [ "${VORTEX_CI_IS_PHPUNIT_RUNNER:-1}" = "1" ] || exit 0 + RATE=$(grep -om1 'line-rate="[0-9.]*"' /tmp/artifacts/coverage/phpunit/cobertura.xml | tr -cd '0-9.') + PERCENT=$(awk "BEGIN {printf \"%.2f\", $RATE*100}") + echo "Coverage: $PERCENT% (threshold: ${VORTEX_CI_CODE_COVERAGE_THRESHOLD:-90}%)" + echo "export COVERAGE_PERCENT=${PERCENT}" >> "${BASH_ENV}" + + - run: + name: Post coverage summary as PR comment + command: | + [ "${VORTEX_CI_IS_PHPUNIT_RUNNER:-1}" = "1" ] || exit 0 + [ "${VORTEX_CI_CODE_COVERAGE_PR_COMMENT_SKIP:-0}" = "1" ] && exit 0 + .circleci/post-coverage-comment.sh /tmp/artifacts/coverage/phpunit/coverage.txt + + - run: + name: Check code coverage threshold + command: | + [ "${VORTEX_CI_IS_PHPUNIT_RUNNER:-1}" = "1" ] || exit 0 + if [ "${COVERAGE_PERCENT//.}" -lt "$((${VORTEX_CI_CODE_COVERAGE_THRESHOLD:-90}*100))" ]; then + echo "FAIL: coverage ${COVERAGE_PERCENT}% is below threshold ${VORTEX_CI_CODE_COVERAGE_THRESHOLD:-90}%" + exit 1 + fi + + - run: + name: Validate Single Directory Components + command: | + [ "${VORTEX_CI_IS_SDC_DEVEL_RUNNER:-1}" = "1" ] || exit 0 + [ "${VORTEX_FRONTEND_BUILD_SKIP:-0}" -eq 1 ] && exit 0 + output=$(docker compose exec -T cli vendor/bin/drush sdc-devel:validate "${DRUPAL_THEME}" 2>&1) + echo "${output}" + if echo "${output}" | grep -qE 'Critical|Errors?|Warnings?'; then + echo "SDC validation reported problems." + [ "${VORTEX_CI_SDC_DEVEL_IGNORE_FAILURE:-0}" -eq 1 ] || exit 1 + fi + + - run: + name: Test with Behat + command: | + [ "${VORTEX_CI_IS_BEHAT_RUNNER:-1}" = "1" ] || exit 0 + if [ "${VORTEX_CI_RUNNER_TOTAL:-1}" -gt 1 ]; then export VORTEX_CI_BEHAT_PROFILE="${VORTEX_CI_BEHAT_PROFILE:-p$((VORTEX_CI_RUNNER_INDEX - VORTEX_CI_BEHAT_PROFILE_OFFSET))}"; fi + echo "Running with ${VORTEX_CI_BEHAT_PROFILE:-default} profile" + docker compose exec -T -e BEHAT_SCREENSHOT_ANIMATION_SKIP=1 cli php -d memory_limit=-1 vendor/bin/behat --colors --strict --profile="${VORTEX_CI_BEHAT_PROFILE:-default}" || \ + docker compose exec -T -e BEHAT_SCREENSHOT_ANIMATION_SKIP=1 cli php -d memory_limit=-1 vendor/bin/behat --colors --strict --rerun --profile="${VORTEX_CI_BEHAT_PROFILE:-default}" || \ + [ "${VORTEX_CI_BEHAT_IGNORE_FAILURE:-0}" -eq 1 ] + no_output_timeout: 30m + + - run: + name: Process test logs and artifacts + command: | + mkdir -p "${VORTEX_CI_TEST_RESULTS}" "${VORTEX_CI_ARTIFACTS}" + if docker compose ps --services --filter "status=running" | grep -q cli && docker compose exec cli test -d /app/.logs; then + docker compose --progress quiet cp cli:/app/.logs/. "${VORTEX_CI_ARTIFACTS}/" + if docker compose exec -T cli sh -c '[ -d /app/.logs/test_results/ ]'; then + docker compose --progress quiet cp cli:/app/.logs/test_results/. "${VORTEX_CI_TEST_RESULTS}/" + fi + fi + when: always + + - store_test_results: + path: *test_results + + - store_artifacts: + path: *artifacts + + - persist_to_workspace: + root: /tmp/workspace + paths: + - code + + # Placed after the test steps so a dirty tree never suppresses them. + - run: + name: Check that the build left a clean working tree + command: ./vendor/bin/vortex-check-worktree-changes || [ "${VORTEX_CI_WORKTREE_CHANGES_IGNORE_FAILURE:-0}" -eq 1 ] + + # Deploy primary branches. + deploy: &job_deploy + <<: *runner_config + steps: + - attach_workspace: + at: /tmp/workspace + + - add_ssh_keys: + fingerprints: + - *deploy_ssh_fingerprint + + - checkout + - *step_process_codebase_for_ci + - *load_variables_from_dotenv + + - run: + name: Check if deployment should be skipped + command: | + if [ "${CIRCLE_PULL_REQUEST}" != "" ] && echo "${CIRCLE_BRANCH}" | grep -q "^project/"; then + echo "Skipping deployment - PR from project/* branch" + circleci-agent step halt + fi + + - run: + name: Install Vortex tooling + command: ./scripts/vortex-tooling.sh + + - run: + name: Deploy + command: | + VORTEX_DEPLOY_BRANCH="${CIRCLE_BRANCH}" \ + VORTEX_DEPLOY_PR="$(echo ${CIRCLE_PULL_REQUEST} | cut -d'/' -f 7)" \ + VORTEX_DEPLOY_PR_HEAD=${CIRCLE_SHA1} \ + ./vendor/bin/vortex-deploy + no_output_timeout: 30m + + - store_artifacts: + path: *artifacts + + # Deploy tags. + deploy-tags: &job-deploy-tags + <<: *runner_config + steps: + - attach_workspace: + at: /tmp/workspace + + - add_ssh_keys: + fingerprints: + - *deploy_ssh_fingerprint + + - checkout + - *step_process_codebase_for_ci + - *load_variables_from_dotenv + + - run: + name: Install Vortex tooling + command: ./scripts/vortex-tooling.sh + + - run: + name: Deploy + command: VORTEX_DEPLOY_MODE="tag" ./vendor/bin/vortex-deploy + no_output_timeout: 30m + + - store_artifacts: + path: *artifacts + +################################################################################ +# WORKFLOWS +################################################################################ + +workflows: + # Commit workflow. Runs for every commit push to the remote repository. + commit: + jobs: + - database: + filters: + tags: + only: /.*/ + - lint: + filters: + tags: + only: /.*/ + - build: + requires: + - database + filters: + tags: + only: /.*/ + - deploy: + requires: + - build + - lint + filters: + branches: + # A branch is deployed when it matches any of the patterns below. + only: + # production, main, master, develop + - /^(production|main|master|develop)$/ + # project/description + - /^project\/[a-zA-Z0-9\-\.]+/ + # feature/description, feature/123-description + # bugfix/description, bugfix/123-description + - /^(feature|bugfix)\/[a-zA-Z0-9\-\.\,_]+$/ + # ci, cisomething + - /^ci.*/ + # release/__VERSION__, release/__VERSION__ (per https://semver.org/) + # hotfix/__VERSION__, hotfix/__VERSION__ (per https://semver.org/) + - /^(release|hotfix)\/[0-9]+(\.[0-9]+){2}(-rc\.[0-9]+)?$/ + # release/2023-04-17, release/2023-04-17.123 (date-based) + # hotfix/2023-04-17, hotfix/2023-04-17.123 (date-based) + - /^(release|hotfix)\/[0-9]{4}-[0-9]{2}-[0-9]{2}(\.[0-9]+)?$/ + # Major version branches. + - /^[0-9]+\.x$/ + tags: + ignore: /.*/ + - deploy-tags: + requires: + - build + - lint + filters: + branches: + ignore: /.*/ + tags: + # Allowed tags: + # - __VERSION__, __VERSION__ (per https://semver.org/) + # - 2023-04-17, 2023-04-17.123 (date-based) + only: /^[0-9]+(\.[0-9]+){2}(-rc\.[0-9]+)?$|^[0-9]{4}-[0-9]{2}-[0-9]{2}(\.[0-9]+)?$/ + + # Security audit workflow. Runs for every commit push to the remote repository, + # independently of the commit workflow. + audit: + jobs: + - audit: + filters: + tags: + only: /.*/ + + # Nightly database workflow runs overnight to capture fresh database and cache it. + nightly-db: + triggers: + - schedule: + cron: *nightly_db_schedule + filters: + branches: + only: + - develop + jobs: + - database-nightly diff --git a/.vortex/installer/tests/Fixtures/handler_process/code_provider_other/.circleci/post-coverage-comment.sh b/.vortex/installer/tests/Fixtures/handler_process/code_provider_other/.circleci/post-coverage-comment.sh new file mode 100755 index 0000000000..d9e7374090 --- /dev/null +++ b/.vortex/installer/tests/Fixtures/handler_process/code_provider_other/.circleci/post-coverage-comment.sh @@ -0,0 +1,79 @@ +#!/usr/bin/env bash +## +## Post code coverage summary as a PR comment on GitHub. +## +## Minimizes previous coverage comments before posting a new one. +## +## Environment variables: +## CIRCLE_PULL_REQUEST - CircleCI PR URL. +## GITHUB_TOKEN - GitHub token for API access. +## CIRCLE_PROJECT_USERNAME - GitHub org/user. +## CIRCLE_PROJECT_REPONAME - GitHub repo name. +## VORTEX_CI_CODE_COVERAGE_THRESHOLD - Coverage threshold percentage (default: 90). +## +## Usage: +## .circleci/post-coverage-comment.sh /path/to/coverage.txt + +set -euo pipefail + +COVERAGE_FILE="${1:-}" + +if [ -z "${COVERAGE_FILE}" ] || [ ! -f "${COVERAGE_FILE}" ]; then + echo "ERROR: Coverage file not found: ${COVERAGE_FILE}" >&2 + exit 1 +fi + +if [ -z "${CIRCLE_PULL_REQUEST:-}" ]; then + echo "Not a pull request. Skipping." + exit 0 +fi + +if [ -z "${GITHUB_TOKEN:-}" ]; then + echo "GITHUB_TOKEN is not set. Skipping." + exit 0 +fi + +COVERAGE_SUMMARY=$(awk '/^ *Summary:/{f=1;next} f && /^$/{exit} f' "${COVERAGE_FILE}") +COVERAGE_DETAILS=$(awk 'BEGIN{s=0} /^ *Summary:/{s=1} s==1 && /^$/{s=2;next} s==2' "${COVERAGE_FILE}") +PR_NUMBER=$(echo "${CIRCLE_PULL_REQUEST}" | cut -d'/' -f 7) +REPO_SLUG="${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}" +THRESHOLD="${VORTEX_CI_CODE_COVERAGE_THRESHOLD:-90}" + +MARKER="" + +BODY=$(jq -n --arg body "**Code coverage** (threshold: ${THRESHOLD}%) +\`\`\` +${COVERAGE_SUMMARY} +\`\`\` +
+Per-class coverage + +\`\`\` +${COVERAGE_DETAILS} +\`\`\` +
+${MARKER}" '{body: $body}') + +# Minimize previous coverage comments. +COMMENTS_JSON=$(curl -s \ + -H "Authorization: token ${GITHUB_TOKEN}" \ + -H "Accept: application/vnd.github.v3+json" \ + "https://api.github.com/repos/${REPO_SLUG}/issues/${PR_NUMBER}/comments?per_page=100") + +EXISTING_IDS=$(echo "${COMMENTS_JSON}" | jq -r '.[] | select(.body | contains("")) | .node_id') + +for NODE_ID in ${EXISTING_IDS}; do + GRAPHQL_BODY=$(jq -n --arg id "${NODE_ID}" '{query: "mutation($id:ID!){minimizeComment(input:{subjectId:$id,classifier:OUTDATED}){minimizedComment{isMinimized}}}", variables: {id: $id}}') + curl -s -X POST \ + -H "Authorization: bearer ${GITHUB_TOKEN}" \ + -H "Content-Type: application/json" \ + "https://api.github.com/graphql" \ + -d "${GRAPHQL_BODY}" +done + +# Post new coverage comment. +curl -s -X POST \ + -H "Authorization: token ${GITHUB_TOKEN}" \ + -H "Accept: application/vnd.github.v3+json" \ + "https://api.github.com/repos/${REPO_SLUG}/issues/${PR_NUMBER}/comments" \ + -d "${BODY}" diff --git a/.vortex/installer/tests/Fixtures/handler_process/code_provider_other/.dockerignore b/.vortex/installer/tests/Fixtures/handler_process/code_provider_other/.dockerignore new file mode 100644 index 0000000000..56497d2e80 --- /dev/null +++ b/.vortex/installer/tests/Fixtures/handler_process/code_provider_other/.dockerignore @@ -0,0 +1,10 @@ +@@ -45,9 +45,6 @@ + **/.phpunit.cache + **/.twig-cs-fixer.cache + +-# Database cache key files written into the workspace by the CI workflow. +-db_cache_* +- + # Local override files. + docker-compose.override.yml + .env.local diff --git a/.vortex/installer/tests/Fixtures/handler_process/code_provider_other/README.md b/.vortex/installer/tests/Fixtures/handler_process/code_provider_other/README.md new file mode 100644 index 0000000000..7dd841ca83 --- /dev/null +++ b/.vortex/installer/tests/Fixtures/handler_process/code_provider_other/README.md @@ -0,0 +1,10 @@ +@@ -11,8 +11,7 @@ + + Drupal 11 implementation of star wars for star wars Org + +-[![Database, Build, Test and +-Deploy](https://github.com/star_wars_org/star_wars/actions/workflows/build-test-deploy.yml/badge.svg)](https://github.com/star_wars_org/star_wars/actions/workflows/build-test-deploy.yml) ++[![CircleCI](https://circleci.com/gh/star_wars_org/star_wars.svg?style=shield)](https://circleci.com/gh/star_wars_org/star_wars) + + ![Drupal + 11](https://img.shields.io/badge/Drupal-11-0678BE?logo=drupal&logoColor=white) diff --git a/.vortex/installer/tests/Fixtures/handler_process/code_provider_other/docs/ci.md b/.vortex/installer/tests/Fixtures/handler_process/code_provider_other/docs/ci.md new file mode 100644 index 0000000000..769dba577b --- /dev/null +++ b/.vortex/installer/tests/Fixtures/handler_process/code_provider_other/docs/ci.md @@ -0,0 +1,14 @@ +@@ -5,10 +5,10 @@ + + ## CI provider + +-This project uses [GitHub Actions](https://github.com/features/actions). ++This project uses [CircleCI](https://circleci.com/). + +-See [GitHub Actions +-documentation](https://www.vortextemplate.com/docs/continuous-integration/github-actions) ++See [CircleCI ++documentation](https://www.vortextemplate.com/docs/continuous-integration/circleci) + for setup and configuration details. + + ## Project-specific configuration diff --git a/.vortex/installer/tests/Fixtures/handler_process/code_provider_other/tests/phpunit/CircleCiConfigTest.php b/.vortex/installer/tests/Fixtures/handler_process/code_provider_other/tests/phpunit/CircleCiConfigTest.php new file mode 100644 index 0000000000..e592478b2e --- /dev/null +++ b/.vortex/installer/tests/Fixtures/handler_process/code_provider_other/tests/phpunit/CircleCiConfigTest.php @@ -0,0 +1,330 @@ +config = static::loadConfig(); + } + + /** + * Loads the CircleCI config. + * + * @return array + * Decoded config. + */ + protected static function loadConfig(): array { + $file = file_get_contents(__DIR__ . '/../../.circleci/config.yml'); + if (!$file) { + throw new \RuntimeException('Unable to read CircleCI config file.'); + } + + return Yaml::decode($file); + } + + /** + * Tests for deploy branch regex. + * + * @see https://semver.org/ + */ + #[DataProvider('dataProviderDeployBranchRegex')] + public function testDeployBranchRegex(string $branch, bool $expected = TRUE): void { + $patterns = $this->config['workflows']['commit']['jobs'][3]['deploy']['filters']['branches']['only']; + + $result = FALSE; + foreach ($patterns as $pattern) { + if (preg_match($pattern, $branch)) { + $result = TRUE; + break; + } + } + + $this->assertSame($expected, $result); + } + + /** + * Data provider for testDeployBranchRegex(). + */ + public static function dataProviderDeployBranchRegex(): \Iterator { + // Positive branches. + yield ['production']; + yield ['main']; + yield ['master']; + yield ['develop']; + + yield ['ci']; + yield ['cisomething']; + + yield ['release/__VERSION__']; + yield ['release/__VERSION__']; + yield ['hotfix/__VERSION__']; + yield ['hotfix/__VERSION__']; + + yield ['release/2023-04-17']; + yield ['release/2023-04-17.1']; + yield ['hotfix/2023-04-17']; + yield ['hotfix/2023-04-17.1']; + + yield ['feature/description']; + yield ['feature/Description']; + yield ['feature/Description-With-Hyphens']; + yield ['feature/Description-With_Underscores']; + yield ['feature/123-description']; + yield ['feature/123-Description']; + yield ['feature/UNDERSCORES_UNDERSCORES']; + yield ['feature/123-Description-With_UNDERSCORES']; + yield ['feature/1.x']; + yield ['feature/0.x']; + yield ['feature/0.1.x']; + yield ['feature/__VERSION__.x']; + yield ['feature/1.x-description']; + yield ['feature/0.x-description']; + yield ['feature/0.1.x-description']; + yield ['feature/__VERSION__.x-description']; + + yield ['bugfix/description']; + yield ['bugfix/Description']; + yield ['bugfix/Description-With-Hyphens']; + yield ['bugfix/Description-With_Underscores']; + yield ['bugfix/123-description']; + yield ['bugfix/123-Description']; + yield ['bugfix/UNDERSCORES_UNDERSCORES']; + yield ['bugfix/123-Description-With_UNDERSCORES']; + yield ['bugfix/1.x']; + yield ['bugfix/0.x']; + yield ['bugfix/0.1.x']; + yield ['bugfix/__VERSION__.x']; + yield ['bugfix/1.x-description']; + yield ['bugfix/0.x-description']; + yield ['bugfix/0.1.x-description']; + yield ['bugfix/__VERSION__.x-description']; + + yield ['project/description']; + yield ['project/Description']; + yield ['project/Description-With-Hyphens']; + yield ['project/123-description']; + yield ['project/123-Description']; + yield ['project/1.x']; + yield ['project/0.x']; + yield ['project/0.1.x']; + yield ['project/__VERSION__.x']; + yield ['project/1.x-description']; + yield ['project/0.x-description']; + yield ['project/0.1.x-description']; + yield ['project/__VERSION__.x-description']; + + // Negative branches. + yield ['something', FALSE]; + yield ['premain', FALSE]; + yield ['premaster', FALSE]; + yield ['predevelop', FALSE]; + yield ['mainpost', FALSE]; + yield ['masterpost', FALSE]; + yield ['developpost', FALSE]; + yield ['premainpost', FALSE]; + yield ['premasterpost', FALSE]; + yield ['predeveloppost', FALSE]; + + yield ['preci', FALSE]; + yield ['precipost', FALSE]; + + yield ['deps/something', FALSE]; + yield ['deps', FALSE]; + yield ['predeps', FALSE]; + yield ['depspost', FALSE]; + yield ['predepspost', FALSE]; + + yield ['feature', FALSE]; + yield ['release', FALSE]; + yield ['hotfix', FALSE]; + yield ['prefeature', FALSE]; + yield ['prerelease', FALSE]; + yield ['prehotfix', FALSE]; + yield ['featurepost', FALSE]; + yield ['releasepost', FALSE]; + yield ['hotfixpost', FALSE]; + yield ['prefeaturepost', FALSE]; + yield ['prereleasepost', FALSE]; + yield ['prehotfixpost', FALSE]; + + yield ['release/123', FALSE]; + yield ['release/123.456', FALSE]; + yield ['hotfix/123', FALSE]; + yield ['hotfix/123.456', FALSE]; + + yield ['release/202-04-17', FALSE]; + yield ['release/2023-4-17', FALSE]; + yield ['release/2023-04-1', FALSE]; + yield ['release/pre2023-04-17', FALSE]; + yield ['release/2023-04-17post', FALSE]; + yield ['release/pre2023-04-17post', FALSE]; + + yield ['hotfix/202-04-17', FALSE]; + yield ['hotfix/2023-4-17', FALSE]; + yield ['hotfix/2023-04-1', FALSE]; + yield ['hotfix/pre2023-04-17', FALSE]; + yield ['hotfix/2023-04-17post', FALSE]; + yield ['hotfix/pre2023-04-17post', FALSE]; + + yield ['release/__VERSION__', FALSE]; + yield ['release/__VERSION__', FALSE]; + yield ['release/__VERSION__', FALSE]; + yield ['release/__VERSION__', FALSE]; + yield ['release/__VERSION__', FALSE]; + yield ['release/__VERSION__', FALSE]; + yield ['release/__VERSION__', FALSE]; + yield ['release/__VERSION__', FALSE]; + yield ['release/__VERSION__', FALSE]; + yield ['release/__VERSION__', FALSE]; + + yield ['hotfix/__VERSION__', FALSE]; + yield ['hotfix/__VERSION__', FALSE]; + yield ['hotfix/__VERSION__', FALSE]; + yield ['hotfix/__VERSION__', FALSE]; + yield ['hotfix/__VERSION__', FALSE]; + yield ['hotfix/__VERSION__', FALSE]; + yield ['hotfix/__VERSION__', FALSE]; + yield ['hotfix/__VERSION__', FALSE]; + yield ['hotfix/__VERSION__', FALSE]; + yield ['hotfix/__VERSION__', FALSE]; + + yield ['prefeature/something', FALSE]; + yield ['prefbugfix/something', FALSE]; + yield ['prerelease/something', FALSE]; + yield ['prehotfix/something', FALSE]; + yield ['featurepost/something', FALSE]; + yield ['bugfixpost/something', FALSE]; + yield ['releasepost/something', FALSE]; + yield ['hotfixpost/something', FALSE]; + yield ['prefeaturepost/something', FALSE]; + yield ['prebugfixpost/something', FALSE]; + yield ['prereleasepost/something', FALSE]; + yield ['prehotfixpost/something', FALSE]; + yield ['preproject/something', FALSE]; + yield ['projectpost/something', FALSE]; + } + + /** + * Tests for deploy tag regex. + * + * @see https://semver.org/ + */ + #[DataProvider('dataProviderDeployTagRegex')] + public function testDeployTagRegex(string $branch, bool $expected = TRUE): void { + $pattern = $this->config['workflows']['commit']['jobs'][4]['deploy-tags']['filters']['tags']['only']; + $result = preg_match($pattern, $branch); + $this->assertEquals($expected, $result); + } + + /** + * Data provider for testDeployTagRegex(). + */ + public static function dataProviderDeployTagRegex(): \Iterator { + // Positive tags. + yield ['__VERSION__']; + yield ['__VERSION__']; + yield ['2023-04-17']; + yield ['2023-04-17.123']; + + // Negative tags. + yield ['123', FALSE]; + yield ['123.456', FALSE]; + yield ['__VERSION__', FALSE]; + yield ['__VERSION__', FALSE]; + yield ['__VERSION__', FALSE]; + yield ['__VERSION__', FALSE]; + yield ['__VERSION__', FALSE]; + + yield ['202-04-17', FALSE]; + yield ['2023-0-17', FALSE]; + yield ['2023-04-1', FALSE]; + yield ['pre2023-04-17', FALSE]; + yield ['2023-04-17post', FALSE]; + yield ['pre2023-04-17post', FALSE]; + yield ['2023-04-17.123.', FALSE]; + yield ['2023-04-17.pre123', FALSE]; + yield ['2023-04-17.pre123post', FALSE]; + yield ['2023-04-17.123post', FALSE]; + } + + /** + * Tests that filter patterns are within the supported length. + */ + #[DataProvider('dataProviderFilterPatternLength')] + public function testFilterPatternLength(string $pattern): void { + $regex = preg_match('#^/(.*)/$#', $pattern, $matches) === 1 ? $matches[1] : $pattern; + + $this->assertLessThanOrEqual(static::FILTER_PATTERN_MAX_LENGTH, strlen($regex)); + } + + /** + * Data provider for testFilterPatternLength(). + */ + public static function dataProviderFilterPatternLength(): \Iterator { + foreach (static::collectFilterPatterns(static::loadConfig()) as $path => $pattern) { + yield $path => [$pattern]; + } + } + + /** + * Collects the patterns of every workflow filter in the config. + * + * @param mixed $config + * Config structure to traverse. + * @param string $path + * Path of the structure within the config, used to label the patterns. + * @param bool $is_filter + * Whether the structure is within a filter. + * + * @return array + * Patterns keyed by their path within the config. + */ + protected static function collectFilterPatterns(mixed $config, string $path = '', bool $is_filter = FALSE): array { + if (!is_array($config)) { + return $is_filter ? [$path . ': ' . $config => (string) $config] : []; + } + + $patterns = []; + + foreach ($config as $key => $value) { + $child = $path === '' ? (string) $key : $path . '.' . $key; + $patterns += static::collectFilterPatterns($value, $child, $is_filter || $key === 'filters'); + } + + return $patterns; + } + +} diff --git a/.vortex/installer/tests/Fixtures/handler_process/code_provider_other/tests/phpunit/Drupal/EnvironmentSettingsTest.php b/.vortex/installer/tests/Fixtures/handler_process/code_provider_other/tests/phpunit/Drupal/EnvironmentSettingsTest.php new file mode 100644 index 0000000000..d65f3bd498 --- /dev/null +++ b/.vortex/installer/tests/Fixtures/handler_process/code_provider_other/tests/phpunit/Drupal/EnvironmentSettingsTest.php @@ -0,0 +1,12 @@ +@@ -407,9 +407,9 @@ + } + + /** +- * Test per-environment settings for GitHub Actions. ++ * Test per-environment settings for CircleCI. + */ +- public function testEnvironmentGha(): void { ++ public function testEnvironmentCircleCi(): void { + $this->setEnvVars([ + 'CI' => TRUE, + ]); diff --git a/.vortex/installer/tests/Fixtures/handler_process/code_provider_other/web/sites/default/includes/providers/-settings.gha.php b/.vortex/installer/tests/Fixtures/handler_process/code_provider_other/web/sites/default/includes/providers/-settings.gha.php new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/code_provider_other/web/sites/default/includes/providers/settings.circleci.php b/.vortex/installer/tests/Fixtures/handler_process/code_provider_other/web/sites/default/includes/providers/settings.circleci.php new file mode 100644 index 0000000000..7cad35cf80 --- /dev/null +++ b/.vortex/installer/tests/Fixtures/handler_process/code_provider_other/web/sites/default/includes/providers/settings.circleci.php @@ -0,0 +1,17 @@ +/dev/null | cut -d : -f 2) +- export VORTEX_HOST_SOLR_PORT=$(docker compose port solr 8983 2>/dev/null | cut -d : -f 2) + export VORTEX_HOST_SELENIUM_VNC_PORT=$(docker compose port chrome 7900 2>/dev/null | cut -d : -f 2) + export VORTEX_HOST_HAS_SEQUELACE=$(uname -a | grep -i -q darwin && mdfind -name 'Sequel Ace' 2>/dev/null | grep -q "Ace" && echo 1 || true) + ahoy cli ./vendor/bin/vortex-info "$@" diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/-solr.dockerfile b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/-solr.dockerfile new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_ar.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_ar.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_bg.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_bg.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_ca.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_ca.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_cs.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_cs.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_cy.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_cy.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_da.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_da.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_de.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_de.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_el.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_el.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_en.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_en.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_es.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_es.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_et.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_et.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_fa.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_fa.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_fi.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_fi.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_fr.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_fr.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_ga.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_ga.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_hi.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_hi.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_hr.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_hr.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_hu.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_hu.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_id.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_id.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_it.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_it.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_lv.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_lv.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_nb.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_nb.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_nl.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_nl.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_nn.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_nn.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_pl.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_pl.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_pt_br.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_pt_br.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_pt_pt.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_pt_pt.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_ro.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_ro.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_ru.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_ru.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_sk.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_sk.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_sr.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_sr.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_sv.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_sv.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_th.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_th.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_tr.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_tr.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_uk.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_uk.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_und.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-accents_und.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-elevate.xml b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-elevate.xml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_ar.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_ar.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_bg.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_bg.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_ca.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_ca.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_cy.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_cy.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_da.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_da.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_de.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_de.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_el.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_el.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_es.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_es.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_et.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_et.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_fa.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_fa.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_fi.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_fi.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_fr.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_fr.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_hi.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_hi.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_it.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_it.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_nb.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_nb.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_nl.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_nl.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_nn.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_nn.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_pl.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_pl.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_pt_br.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_pt_br.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_pt_pt.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_pt_pt.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_ro.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_ro.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_ru.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_ru.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_sv.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_sv.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_th.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_th.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_tr.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_tr.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_uk.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-nouns_uk.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_ar.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_ar.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_bg.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_bg.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_ca.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_ca.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_cs.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_cs.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_cy.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_cy.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_da.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_da.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_de.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_de.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_el.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_el.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_en.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_en.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_es.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_es.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_et.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_et.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_fa.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_fa.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_fi.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_fi.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_fr.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_fr.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_ga.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_ga.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_hi.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_hi.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_hr.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_hr.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_hu.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_hu.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_id.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_id.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_it.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_it.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_lv.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_lv.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_nb.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_nb.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_nl.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_nl.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_nn.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_nn.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_pl.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_pl.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_pt_br.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_pt_br.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_pt_pt.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_pt_pt.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_ro.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_ro.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_ru.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_ru.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_sk.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_sk.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_sr.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_sr.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_sv.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_sv.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_th.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_th.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_tr.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_tr.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_uk.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_uk.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_und.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-protwords_und.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-schema.xml b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-schema.xml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-schema_extra_fields.xml b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-schema_extra_fields.xml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-schema_extra_types.xml b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-schema_extra_types.xml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-solrconfig.xml b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-solrconfig.xml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-solrconfig_extra.xml b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-solrconfig_extra.xml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-solrconfig_index.xml b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-solrconfig_index.xml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-solrconfig_query.xml b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-solrconfig_query.xml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-solrconfig_requestdispatcher.xml b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-solrconfig_requestdispatcher.xml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-solrcore.properties b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-solrcore.properties new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stoptags_ja.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stoptags_ja.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_ar.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_ar.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_bg.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_bg.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_ca.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_ca.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_cs.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_cs.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_cy.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_cy.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_da.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_da.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_de.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_de.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_el.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_el.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_en.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_en.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_es.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_es.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_et.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_et.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_fa.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_fa.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_fi.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_fi.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_fr.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_fr.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_ga.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_ga.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_hi.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_hi.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_hr.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_hr.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_hu.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_hu.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_id.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_id.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_it.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_it.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_ja.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_ja.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_ko.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_ko.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_lv.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_lv.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_nb.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_nb.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_nl.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_nl.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_nn.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_nn.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_pl.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_pl.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_pt_br.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_pt_br.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_pt_pt.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_pt_pt.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_ro.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_ro.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_ru.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_ru.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_sk.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_sk.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_sr.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_sr.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_sv.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_sv.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_th.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_th.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_tr.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_tr.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_uk.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_uk.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_und.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-stopwords_und.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_ar.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_ar.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_bg.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_bg.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_ca.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_ca.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_cs.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_cs.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_cy.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_cy.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_da.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_da.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_de.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_de.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_el.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_el.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_en.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_en.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_es.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_es.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_et.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_et.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_fa.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_fa.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_fi.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_fi.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_fr.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_fr.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_ga.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_ga.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_hi.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_hi.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_hr.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_hr.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_hu.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_hu.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_id.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_id.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_it.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_it.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_lv.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_lv.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_nb.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_nb.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_nl.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_nl.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_nn.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_nn.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_pl.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_pl.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_pt_br.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_pt_br.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_pt_pt.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_pt_pt.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_ro.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_ro.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_ru.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_ru.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_sk.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_sk.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_sr.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_sr.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_sv.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_sv.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_th.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_th.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_tr.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_tr.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_uk.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_uk.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_und.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/.docker/config/solr/config-set/-synonyms_und.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/composer.json b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/composer.json new file mode 100644 index 0000000000..0e1663ac53 --- /dev/null +++ b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/composer.json @@ -0,0 +1,8 @@ +@@ -36,7 +36,6 @@ + "drupal/schema_metatag": "__VERSION__", + "drupal/sdc_devel": "__VERSION__", + "drupal/search_api": "__VERSION__", +- "drupal/search_api_solr": "__VERSION__", + "drupal/seckit": "__VERSION__", + "drupal/shield": "__VERSION__", + "drupal/stage_file_proxy": "__VERSION__", diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/docker-compose.yml b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/docker-compose.yml new file mode 100644 index 0000000000..b3bc3a1726 --- /dev/null +++ b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/docker-compose.yml @@ -0,0 +1,40 @@ +@@ -158,17 +158,6 @@ + redis: + image: uselagoon/valkey-8:__VERSION__ + +- solr: +- build: +- context: . +- dockerfile: .docker/solr.dockerfile +- environment: +- <<: *default-environment +- volumes: +- - solr:/var/solr +- ports: +- - '8983' # Solr port in a container. Find port on host with `ahoy info` or `docker compose port solr 8983`. +- + clamav: + build: + context: . +@@ -199,13 +188,10 @@ + - clamav + - database + - redis +- - solr + command: + - clamav:3310 + - database:3306 + - redis:6379 +- - solr:8983 +- - curl -s "http://solr:8983/solr/drupal/select?q=*:*&rows=0&wt=json" | grep response + + networks: ### Use external networks locally. Automatically removed in CI. + amazeeio-network: ### Automatically removed in CI. +@@ -214,7 +200,6 @@ + volumes: + app: {} + files: {} +- solr: {} + + secrets: + package_token: diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/scripts/-provision-30-search-index.sh b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/scripts/-provision-30-search-index.sh new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/scripts/provision-00-enable-demo-modules.sh b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/scripts/provision-00-enable-demo-modules.sh index a24af01174..0eda6f28f1 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/scripts/provision-00-enable-demo-modules.sh +++ b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_search/scripts/provision-00-enable-demo-modules.sh @@ -1,9 +1,20 @@ -@@ -91,8 +91,6 @@ +@@ -80,10 +80,6 @@ + drush config:set clamav.settings mode_daemon_tcpip.hostname clamav + pass "Installed and configured ClamAV." + +-task "Installing Solr search modules." +-drush pm:install search_api search_api_solr +-pass "Installed Solr search modules." +- + # Enable custom site module and run its deployment hooks. + # + # Note that deployment hooks for already enabled modules have run in the +@@ -90,8 +86,6 @@ + # parent "vortex-provision" script. task "Installing custom site modules." drush pm:install sw_base - --drush pm:install sw_search - +-drush pm:install sw_search + drush pm:install sw_demo pass "Installed custom site modules." - diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.ahoy.yml b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.ahoy.yml new file mode 100644 index 0000000000..f13bb20aef --- /dev/null +++ b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.ahoy.yml @@ -0,0 +1,8 @@ +@@ -32,7 +32,6 @@ + cmd: | + export COMPOSE_PROJECT_NAME=${COMPOSE_PROJECT_NAME:-${PWD##*/}} + export VORTEX_HOST_DB_PORT=$(docker compose port database 3306 2>/dev/null | cut -d : -f 2) +- export VORTEX_HOST_SOLR_PORT=$(docker compose port solr 8983 2>/dev/null | cut -d : -f 2) + export VORTEX_HOST_SELENIUM_VNC_PORT=$(docker compose port chrome 7900 2>/dev/null | cut -d : -f 2) + export VORTEX_HOST_HAS_SEQUELACE=$(uname -a | grep -i -q darwin && mdfind -name 'Sequel Ace' 2>/dev/null | grep -q "Ace" && echo 1 || true) + ahoy cli ./vendor/bin/vortex-info "$@" diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/-solr.dockerfile b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/-solr.dockerfile new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_ar.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_ar.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_bg.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_bg.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_ca.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_ca.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_cs.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_cs.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_cy.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_cy.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_da.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_da.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_de.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_de.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_el.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_el.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_en.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_en.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_es.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_es.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_et.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_et.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_fa.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_fa.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_fi.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_fi.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_fr.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_fr.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_ga.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_ga.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_hi.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_hi.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_hr.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_hr.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_hu.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_hu.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_id.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_id.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_it.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_it.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_lv.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_lv.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_nb.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_nb.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_nl.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_nl.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_nn.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_nn.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_pl.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_pl.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_pt_br.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_pt_br.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_pt_pt.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_pt_pt.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_ro.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_ro.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_ru.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_ru.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_sk.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_sk.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_sr.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_sr.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_sv.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_sv.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_th.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_th.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_tr.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_tr.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_uk.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_uk.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_und.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-accents_und.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-elevate.xml b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-elevate.xml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_ar.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_ar.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_bg.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_bg.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_ca.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_ca.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_cy.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_cy.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_da.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_da.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_de.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_de.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_el.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_el.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_es.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_es.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_et.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_et.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_fa.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_fa.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_fi.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_fi.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_fr.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_fr.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_hi.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_hi.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_it.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_it.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_nb.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_nb.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_nl.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_nl.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_nn.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_nn.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_pl.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_pl.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_pt_br.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_pt_br.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_pt_pt.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_pt_pt.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_ro.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_ro.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_ru.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_ru.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_sv.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_sv.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_th.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_th.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_tr.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_tr.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_uk.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-nouns_uk.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_ar.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_ar.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_bg.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_bg.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_ca.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_ca.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_cs.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_cs.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_cy.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_cy.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_da.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_da.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_de.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_de.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_el.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_el.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_en.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_en.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_es.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_es.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_et.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_et.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_fa.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_fa.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_fi.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_fi.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_fr.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_fr.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_ga.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_ga.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_hi.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_hi.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_hr.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_hr.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_hu.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_hu.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_id.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_id.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_it.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_it.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_lv.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_lv.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_nb.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_nb.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_nl.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_nl.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_nn.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_nn.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_pl.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_pl.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_pt_br.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_pt_br.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_pt_pt.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_pt_pt.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_ro.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_ro.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_ru.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_ru.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_sk.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_sk.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_sr.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_sr.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_sv.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_sv.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_th.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_th.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_tr.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_tr.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_uk.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_uk.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_und.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-protwords_und.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-schema.xml b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-schema.xml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-schema_extra_fields.xml b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-schema_extra_fields.xml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-schema_extra_types.xml b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-schema_extra_types.xml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-solrconfig.xml b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-solrconfig.xml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-solrconfig_extra.xml b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-solrconfig_extra.xml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-solrconfig_index.xml b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-solrconfig_index.xml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-solrconfig_query.xml b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-solrconfig_query.xml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-solrconfig_requestdispatcher.xml b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-solrconfig_requestdispatcher.xml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-solrcore.properties b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-solrcore.properties new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stoptags_ja.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stoptags_ja.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_ar.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_ar.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_bg.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_bg.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_ca.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_ca.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_cs.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_cs.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_cy.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_cy.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_da.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_da.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_de.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_de.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_el.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_el.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_en.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_en.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_es.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_es.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_et.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_et.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_fa.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_fa.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_fi.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_fi.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_fr.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_fr.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_ga.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_ga.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_hi.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_hi.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_hr.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_hr.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_hu.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_hu.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_id.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_id.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_it.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_it.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_ja.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_ja.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_ko.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_ko.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_lv.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_lv.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_nb.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_nb.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_nl.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_nl.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_nn.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_nn.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_pl.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_pl.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_pt_br.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_pt_br.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_pt_pt.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_pt_pt.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_ro.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_ro.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_ru.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_ru.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_sk.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_sk.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_sr.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_sr.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_sv.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_sv.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_th.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_th.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_tr.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_tr.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_uk.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_uk.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_und.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-stopwords_und.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_ar.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_ar.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_bg.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_bg.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_ca.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_ca.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_cs.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_cs.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_cy.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_cy.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_da.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_da.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_de.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_de.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_el.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_el.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_en.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_en.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_es.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_es.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_et.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_et.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_fa.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_fa.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_fi.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_fi.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_fr.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_fr.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_ga.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_ga.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_hi.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_hi.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_hr.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_hr.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_hu.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_hu.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_id.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_id.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_it.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_it.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_lv.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_lv.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_nb.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_nb.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_nl.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_nl.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_nn.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_nn.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_pl.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_pl.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_pt_br.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_pt_br.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_pt_pt.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_pt_pt.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_ro.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_ro.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_ru.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_ru.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_sk.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_sk.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_sr.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_sr.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_sv.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_sv.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_th.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_th.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_tr.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_tr.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_uk.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_uk.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_und.txt b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/.docker/config/solr/config-set/-synonyms_und.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/composer.json b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/composer.json new file mode 100644 index 0000000000..0e1663ac53 --- /dev/null +++ b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/composer.json @@ -0,0 +1,8 @@ +@@ -36,7 +36,6 @@ + "drupal/schema_metatag": "__VERSION__", + "drupal/sdc_devel": "__VERSION__", + "drupal/search_api": "__VERSION__", +- "drupal/search_api_solr": "__VERSION__", + "drupal/seckit": "__VERSION__", + "drupal/shield": "__VERSION__", + "drupal/stage_file_proxy": "__VERSION__", diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/docker-compose.yml b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/docker-compose.yml new file mode 100644 index 0000000000..b3bc3a1726 --- /dev/null +++ b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/docker-compose.yml @@ -0,0 +1,40 @@ +@@ -158,17 +158,6 @@ + redis: + image: uselagoon/valkey-8:__VERSION__ + +- solr: +- build: +- context: . +- dockerfile: .docker/solr.dockerfile +- environment: +- <<: *default-environment +- volumes: +- - solr:/var/solr +- ports: +- - '8983' # Solr port in a container. Find port on host with `ahoy info` or `docker compose port solr 8983`. +- + clamav: + build: + context: . +@@ -199,13 +188,10 @@ + - clamav + - database + - redis +- - solr + command: + - clamav:3310 + - database:3306 + - redis:6379 +- - solr:8983 +- - curl -s "http://solr:8983/solr/drupal/select?q=*:*&rows=0&wt=json" | grep response + + networks: ### Use external networks locally. Automatically removed in CI. + amazeeio-network: ### Automatically removed in CI. +@@ -214,7 +200,6 @@ + volumes: + app: {} + files: {} +- solr: {} + + secrets: + package_token: diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/scripts/-provision-30-search-index.sh b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/scripts/-provision-30-search-index.sh new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/scripts/provision-00-enable-demo-modules.sh b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/scripts/provision-00-enable-demo-modules.sh index 907c132c57..55f5270368 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/scripts/provision-00-enable-demo-modules.sh +++ b/.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/scripts/provision-00-enable-demo-modules.sh @@ -16,7 +16,16 @@ task "Setting site name." drush php:eval "\Drupal::service('config.factory')->getEditable('system.site')->set('name', 'star wars')->save();" pass "Set site name." -@@ -89,11 +78,7 @@ +@@ -80,20 +69,12 @@ + drush config:set clamav.settings mode_daemon_tcpip.hostname clamav + pass "Installed and configured ClamAV." + +-task "Installing Solr search modules." +-drush pm:install search_api search_api_solr +-pass "Installed Solr search modules." +- + # Enable custom site module and run its deployment hooks. + # # Note that deployment hooks for already enabled modules have run in the # parent "vortex-provision" script. task "Installing custom site modules." diff --git a/.vortex/installer/tests/Functional/FunctionalTestCase.php b/.vortex/installer/tests/Functional/FunctionalTestCase.php index dd086cd3aa..4204199187 100644 --- a/.vortex/installer/tests/Functional/FunctionalTestCase.php +++ b/.vortex/installer/tests/Functional/FunctionalTestCase.php @@ -37,7 +37,7 @@ public static function setUpBeforeClass(): void { * {@inheritdoc} */ protected function tearDown(): void { - static::tuiTeardown(); + $this->tuiTeardown(); if (empty(static::$fixtures)) { throw new \RuntimeException('Fixtures directory is not set.'); diff --git a/.vortex/installer/tests/Functional/PharTest.php b/.vortex/installer/tests/Functional/PharTest.php index 2b0ce6a919..7e9dac432b 100644 --- a/.vortex/installer/tests/Functional/PharTest.php +++ b/.vortex/installer/tests/Functional/PharTest.php @@ -111,11 +111,8 @@ protected function runInstallationWithPhar(string $phar_path, array $options = [ ]; $options += $defaults; - // The interactive mode is not supported in the tests as installer - // uses Laravel\Prompts which require a real TTY or a series of fallback - // callbacks to be defined. These callbacks are not implemented yet, so - // we enforce the non-interactive mode for the tests. - // @see https://github.com/drush-ops/drush/blob/13.x/src/Commands/ConfiguresPrompts.php + // Interactive prompts need a real TTY, which the PHAR process does not + // have. $options['no-interaction'] = TRUE; foreach ($options as $option => $value) { diff --git a/.vortex/installer/tests/Traits/TuiTrait.php b/.vortex/installer/tests/Traits/TuiTrait.php index ef0bb11c9d..87fe98e9dd 100644 --- a/.vortex/installer/tests/Traits/TuiTrait.php +++ b/.vortex/installer/tests/Traits/TuiTrait.php @@ -4,32 +4,36 @@ namespace DrevOps\VortexInstaller\Tests\Traits; +use AlexSkrypnyk\Prompty\PromptyTestTrait; use DrevOps\VortexInstaller\Utils\Tui; -use Laravel\Prompts\Output\BufferedConsoleOutput; -use Laravel\Prompts\Prompt; +use Symfony\Component\Console\Output\BufferedOutput; trait TuiTrait { - protected static function tuiSetUp(): void { - Tui::init((new BufferedConsoleOutput()), FALSE); - - // Override how validation is handled (it expects a user input on incorrect - // validation) to throw an exception instead so that we can assert on it - // in the tests. - Prompt::validateUsing(function (Prompt $prompt, mixed $value): null { - if (is_callable($prompt->validate)) { - $error = ($prompt->validate)($value); - if ($error) { - throw new \RuntimeException(sprintf('Validation failed with error "%s".', $error)); - } - } - - return NULL; - }); + use PromptyTestTrait; + + protected static function tuiSetUp(bool $is_interactive = FALSE): void { + Tui::init(new BufferedOutput(), $is_interactive); + } + + protected function tuiTeardown(): void { + // Tui::init() configures a new Prompty instance in the next test. + $this->promptyTearDown(); } - protected static function tuiTeardown(): void { - Prompt::validateUsing(NULL); + /** + * Feed keystrokes to the prompts. + * + * A rejected answer throws instead of re-prompting, so a test can assert on + * the validation message rather than on a prompt cancelled at the end of the + * input. + * + * @param array $keystrokes + * Keystrokes in the order the prompts read them. + */ + protected function tuiInput(array $keystrokes): void { + $this->promptyInput(implode('', $keystrokes)); + $this->promptyThrowOnInvalid(); } /** diff --git a/.vortex/installer/tests/Unit/Prompts/Handlers/AbstractHandlerDiscoveryTestCase.php b/.vortex/installer/tests/Unit/Prompts/Handlers/AbstractHandlerDiscoveryTestCase.php index d45f95bb26..7f4049e7eb 100644 --- a/.vortex/installer/tests/Unit/Prompts/Handlers/AbstractHandlerDiscoveryTestCase.php +++ b/.vortex/installer/tests/Unit/Prompts/Handlers/AbstractHandlerDiscoveryTestCase.php @@ -52,7 +52,6 @@ use DrevOps\VortexInstaller\Tests\Unit\UnitTestCase; use DrevOps\VortexInstaller\Utils\Config; use DrevOps\VortexInstaller\Utils\File; -use Laravel\Prompts\Prompt; use PHPUnit\Framework\Attributes\DataProvider; /** @@ -73,7 +72,7 @@ protected function setUp(): void { static::envUnsetProjectVars(); - static::tuiSetUp(); + static::tuiSetUp(TRUE); static::$sut = File::mkdir(static::$sut . DIRECTORY_SEPARATOR . 'myproject'); } @@ -82,7 +81,7 @@ protected function setUp(): void { * {@inheritdoc} */ protected function tearDown(): void { - static::tuiTeardown(); + $this->tuiTeardown(); parent::tearDown(); } @@ -109,7 +108,7 @@ public function testRunPrompts( $answers = array_replace(static::defaultTuiAnswers(), $answers); $keystrokes = static::tuiKeystrokes($answers, 40); - Prompt::fake($keystrokes); + $this->tuiInput($keystrokes); $pm = new PromptManager($config); $pm->runPrompts(); diff --git a/.vortex/installer/tests/Unit/Prompts/Handlers/AiCodeInstructionsHandlerDiscoveryTest.php b/.vortex/installer/tests/Unit/Prompts/Handlers/AiCodeInstructionsHandlerDiscoveryTest.php index cfc073e4c5..af9db7711c 100644 --- a/.vortex/installer/tests/Unit/Prompts/Handlers/AiCodeInstructionsHandlerDiscoveryTest.php +++ b/.vortex/installer/tests/Unit/Prompts/Handlers/AiCodeInstructionsHandlerDiscoveryTest.php @@ -7,7 +7,6 @@ use DrevOps\VortexInstaller\Prompts\Handlers\AiCodeInstructions; use DrevOps\VortexInstaller\Utils\Config; use DrevOps\VortexInstaller\Utils\File; -use Laravel\Prompts\Key; use PHPUnit\Framework\Attributes\CoversClass; #[CoversClass(AiCodeInstructions::class)] @@ -17,7 +16,7 @@ public static function dataProviderRunPrompts(): \Iterator { $expected_defaults = static::getExpectedDefaults(); $expected_installed = static::getExpectedInstalled(); yield 'ai instructions - prompt' => [ - [AiCodeInstructions::id() => Key::ENTER], + [AiCodeInstructions::id() => self::KEY_ENTER], [AiCodeInstructions::id() => TRUE] + $expected_defaults, ]; yield 'ai instructions - discovery' => [ diff --git a/.vortex/installer/tests/Unit/Prompts/Handlers/AiCodeReviewHandlerDiscoveryTest.php b/.vortex/installer/tests/Unit/Prompts/Handlers/AiCodeReviewHandlerDiscoveryTest.php index ff7670ba4a..8f6469c2e8 100644 --- a/.vortex/installer/tests/Unit/Prompts/Handlers/AiCodeReviewHandlerDiscoveryTest.php +++ b/.vortex/installer/tests/Unit/Prompts/Handlers/AiCodeReviewHandlerDiscoveryTest.php @@ -7,7 +7,6 @@ use DrevOps\VortexInstaller\Prompts\Handlers\AiCodeReview; use DrevOps\VortexInstaller\Utils\Config; use DrevOps\VortexInstaller\Utils\File; -use Laravel\Prompts\Key; use PHPUnit\Framework\Attributes\CoversClass; #[CoversClass(AiCodeReview::class)] @@ -17,11 +16,11 @@ public static function dataProviderRunPrompts(): \Iterator { $expected_defaults = static::getExpectedDefaults(); $expected_installed = static::getExpectedInstalled(); yield 'ai code review - prompt' => [ - [AiCodeReview::id() => Key::ENTER], + [AiCodeReview::id() => self::KEY_ENTER], [AiCodeReview::id() => FALSE] + $expected_defaults, ]; yield 'ai code review - prompt - enabled' => [ - [AiCodeReview::id() => Key::LEFT . Key::ENTER], + [AiCodeReview::id() => self::KEY_LEFT . self::KEY_ENTER], [AiCodeReview::id() => TRUE] + $expected_defaults, ]; yield 'ai code review - discovery' => [ diff --git a/.vortex/installer/tests/Unit/Prompts/Handlers/CiProviderHandlerDiscoveryTest.php b/.vortex/installer/tests/Unit/Prompts/Handlers/CiProviderHandlerDiscoveryTest.php index d84e2bb122..dffd2829f2 100644 --- a/.vortex/installer/tests/Unit/Prompts/Handlers/CiProviderHandlerDiscoveryTest.php +++ b/.vortex/installer/tests/Unit/Prompts/Handlers/CiProviderHandlerDiscoveryTest.php @@ -7,7 +7,6 @@ use DrevOps\VortexInstaller\Prompts\Handlers\CiProvider; use DrevOps\VortexInstaller\Utils\Config; use DrevOps\VortexInstaller\Utils\File; -use Laravel\Prompts\Key; use PHPUnit\Framework\Attributes\CoversClass; #[CoversClass(CiProvider::class)] @@ -17,7 +16,7 @@ public static function dataProviderRunPrompts(): \Iterator { $expected_defaults = static::getExpectedDefaults(); $expected_installed = static::getExpectedInstalled(); yield 'ci provider - prompt' => [ - [CiProvider::id() => Key::ENTER], + [CiProvider::id() => self::KEY_ENTER], [CiProvider::id() => CiProvider::GITHUB_ACTIONS] + $expected_defaults, ]; yield 'ci provider - discovery - gha' => [ diff --git a/.vortex/installer/tests/Unit/Prompts/Handlers/CodeCoverageProviderHandlerDiscoveryTest.php b/.vortex/installer/tests/Unit/Prompts/Handlers/CodeCoverageProviderHandlerDiscoveryTest.php index 23ebc1cab6..a40a0384c1 100644 --- a/.vortex/installer/tests/Unit/Prompts/Handlers/CodeCoverageProviderHandlerDiscoveryTest.php +++ b/.vortex/installer/tests/Unit/Prompts/Handlers/CodeCoverageProviderHandlerDiscoveryTest.php @@ -8,7 +8,6 @@ use DrevOps\VortexInstaller\Prompts\Handlers\CodeCoverageProvider; use DrevOps\VortexInstaller\Utils\Config; use DrevOps\VortexInstaller\Utils\File; -use Laravel\Prompts\Key; use PHPUnit\Framework\Attributes\CoversClass; #[CoversClass(CodeCoverageProvider::class)] @@ -18,7 +17,7 @@ public static function dataProviderRunPrompts(): \Iterator { $expected_defaults = static::getExpectedDefaults(); $expected_installed = static::getExpectedInstalled(); yield 'code coverage provider - prompt' => [ - [CodeCoverageProvider::id() => Key::ENTER], + [CodeCoverageProvider::id() => self::KEY_ENTER], [CodeCoverageProvider::id() => CodeCoverageProvider::NONE] + $expected_defaults, ]; yield 'code coverage provider - discovery - codecov - gha' => [ diff --git a/.vortex/installer/tests/Unit/Prompts/Handlers/CodeProviderHandlerDiscoveryTest.php b/.vortex/installer/tests/Unit/Prompts/Handlers/CodeProviderHandlerDiscoveryTest.php index 9a5044e2b8..6f9ca15161 100644 --- a/.vortex/installer/tests/Unit/Prompts/Handlers/CodeProviderHandlerDiscoveryTest.php +++ b/.vortex/installer/tests/Unit/Prompts/Handlers/CodeProviderHandlerDiscoveryTest.php @@ -9,7 +9,6 @@ use DrevOps\VortexInstaller\Utils\Config; use DrevOps\VortexInstaller\Utils\File; use DrevOps\VortexInstaller\Utils\Git; -use Laravel\Prompts\Key; use PHPUnit\Framework\Attributes\CoversClass; #[CoversClass(CodeProvider::class)] @@ -19,11 +18,11 @@ public static function dataProviderRunPrompts(): \Iterator { $expected_defaults = static::getExpectedDefaults(); $expected_installed = static::getExpectedInstalled(); yield 'code repo - prompt' => [ - [CodeProvider::id() => Key::ENTER], + [CodeProvider::id() => self::KEY_ENTER], [CodeProvider::id() => CodeProvider::GITHUB] + $expected_defaults, ]; yield 'code repo - prompt - other' => [ - [CodeProvider::id() => Key::DOWN . Key::ENTER], + [CodeProvider::id() => self::KEY_DOWN . self::KEY_ENTER], [ CodeProvider::id() => CodeProvider::OTHER, CiProvider::id() => CiProvider::CIRCLECI, diff --git a/.vortex/installer/tests/Unit/Prompts/Handlers/CustomModulesHandlerDiscoveryTest.php b/.vortex/installer/tests/Unit/Prompts/Handlers/CustomModulesHandlerDiscoveryTest.php index 0aac3256c5..c828efb5a7 100644 --- a/.vortex/installer/tests/Unit/Prompts/Handlers/CustomModulesHandlerDiscoveryTest.php +++ b/.vortex/installer/tests/Unit/Prompts/Handlers/CustomModulesHandlerDiscoveryTest.php @@ -5,9 +5,9 @@ namespace DrevOps\VortexInstaller\Tests\Unit\Prompts\Handlers; use DrevOps\VortexInstaller\Prompts\Handlers\CustomModules; +use DrevOps\VortexInstaller\Prompts\Handlers\Services; use DrevOps\VortexInstaller\Utils\Config; use DrevOps\VortexInstaller\Utils\File; -use Laravel\Prompts\Key; use PHPUnit\Framework\Attributes\CoversClass; #[CoversClass(CustomModules::class)] @@ -17,7 +17,7 @@ public static function dataProviderRunPrompts(): \Iterator { $expected_defaults = static::getExpectedDefaults(); $expected_installed = static::getExpectedInstalled(); yield 'custom_modules - prompt' => [ - [CustomModules::id() => Key::ENTER], + [CustomModules::id() => self::KEY_ENTER], [CustomModules::id() => [CustomModules::BASE, CustomModules::SEARCH, CustomModules::DEMO]] + $expected_defaults, ]; yield 'custom_modules - discovery - all' => [ @@ -32,7 +32,7 @@ function (AbstractHandlerDiscoveryTestCase $test, Config $config): void { ]; yield 'custom_modules - discovery - base only' => [ [], - [CustomModules::id() => [CustomModules::BASE]] + $expected_installed, + [CustomModules::id() => [CustomModules::BASE], Services::id() => [Services::CLAMAV, Services::REDIS]] + $expected_installed, function (AbstractHandlerDiscoveryTestCase $test, Config $config): void { $test->stubVortexProject($config); File::mkdir(static::$sut . '/web/modules/custom/mypr_base'); @@ -40,7 +40,7 @@ function (AbstractHandlerDiscoveryTestCase $test, Config $config): void { ]; yield 'custom_modules - discovery - base and demo' => [ [], - [CustomModules::id() => [CustomModules::BASE, CustomModules::DEMO]] + $expected_installed, + [CustomModules::id() => [CustomModules::BASE, CustomModules::DEMO], Services::id() => [Services::CLAMAV, Services::REDIS]] + $expected_installed, function (AbstractHandlerDiscoveryTestCase $test, Config $config): void { $test->stubVortexProject($config); File::mkdir(static::$sut . '/web/modules/custom/mypr_base'); diff --git a/.vortex/installer/tests/Unit/Prompts/Handlers/DatabaseFetchSourceHandlerDiscoveryTest.php b/.vortex/installer/tests/Unit/Prompts/Handlers/DatabaseFetchSourceHandlerDiscoveryTest.php index bcc78955b3..444a5470be 100644 --- a/.vortex/installer/tests/Unit/Prompts/Handlers/DatabaseFetchSourceHandlerDiscoveryTest.php +++ b/.vortex/installer/tests/Unit/Prompts/Handlers/DatabaseFetchSourceHandlerDiscoveryTest.php @@ -5,7 +5,6 @@ namespace DrevOps\VortexInstaller\Tests\Unit\Prompts\Handlers; use DrevOps\VortexInstaller\Prompts\Handlers\DatabaseFetchSource; -use Laravel\Prompts\Key; use PHPUnit\Framework\Attributes\CoversClass; #[CoversClass(DatabaseFetchSource::class)] @@ -14,7 +13,7 @@ class DatabaseFetchSourceHandlerDiscoveryTest extends AbstractHandlerDiscoveryTe public static function dataProviderRunPrompts(): \Iterator { $expected_defaults = static::getExpectedDefaults(); yield 'database fetch source - prompt' => [ - [DatabaseFetchSource::id() => Key::ENTER], + [DatabaseFetchSource::id() => self::KEY_ENTER], [DatabaseFetchSource::id() => DatabaseFetchSource::URL] + $expected_defaults, ]; yield 'database fetch source - discovery' => [ diff --git a/.vortex/installer/tests/Unit/Prompts/Handlers/DatabaseImageHandlerDiscoveryTest.php b/.vortex/installer/tests/Unit/Prompts/Handlers/DatabaseImageHandlerDiscoveryTest.php index 06a772b02f..2eaf11b04d 100644 --- a/.vortex/installer/tests/Unit/Prompts/Handlers/DatabaseImageHandlerDiscoveryTest.php +++ b/.vortex/installer/tests/Unit/Prompts/Handlers/DatabaseImageHandlerDiscoveryTest.php @@ -7,7 +7,6 @@ use DrevOps\VortexInstaller\Prompts\Handlers\DatabaseFetchSource; use DrevOps\VortexInstaller\Prompts\Handlers\DatabaseImage; use DrevOps\VortexInstaller\Utils\Config; -use Laravel\Prompts\Key; use PHPUnit\Framework\Attributes\CoversClass; #[CoversClass(DatabaseImage::class)] @@ -17,28 +16,29 @@ public static function dataProviderRunPrompts(): \Iterator { $expected_defaults = static::getExpectedDefaults(); yield 'database image - prompt' => [ [ - DatabaseFetchSource::id() => Key::DOWN . Key::DOWN . Key::DOWN . Key::DOWN . Key::ENTER, + DatabaseFetchSource::id() => self::KEY_DOWN . self::KEY_DOWN . self::KEY_DOWN . self::KEY_DOWN . self::KEY_ENTER, DatabaseImage::id() => 'myregistry/myimage:mytag', ], [DatabaseFetchSource::id() => DatabaseFetchSource::CONTAINER_REGISTRY, DatabaseImage::id() => 'myregistry/myimage:mytag'] + $expected_defaults, ]; yield 'database image - invalid' => [ [ - DatabaseFetchSource::id() => Key::DOWN . Key::DOWN . Key::DOWN . Key::DOWN . Key::ENTER, + DatabaseFetchSource::id() => self::KEY_DOWN . self::KEY_DOWN . self::KEY_DOWN . self::KEY_DOWN . self::KEY_ENTER, DatabaseImage::id() => 'myregistry:myimage:mytag', ], 'Please enter a valid container image name with an optional tag.', ]; yield 'database image - invalid - capitalization' => [ [ - DatabaseFetchSource::id() => Key::DOWN . Key::DOWN . Key::DOWN . Key::DOWN . Key::ENTER, + DatabaseFetchSource::id() => self::KEY_DOWN . self::KEY_DOWN . self::KEY_DOWN . self::KEY_DOWN . self::KEY_ENTER, DatabaseImage::id() => 'MyRegistry/MyImage:mytag', ], 'Please enter a valid container image name with an optional tag.', ]; yield 'database image - discovery' => [ [ - DatabaseFetchSource::id() => Key::DOWN . Key::DOWN . Key::DOWN . Key::DOWN . Key::ENTER, + DatabaseFetchSource::id() => self::KEY_DOWN . self::KEY_DOWN . self::KEY_DOWN . self::KEY_DOWN . self::KEY_ENTER, + DatabaseImage::id() => static::TUI_DEFAULT, ], [ DatabaseFetchSource::id() => DatabaseFetchSource::CONTAINER_REGISTRY, diff --git a/.vortex/installer/tests/Unit/Prompts/Handlers/DependencyUpdatesProviderHandlerDiscoveryTest.php b/.vortex/installer/tests/Unit/Prompts/Handlers/DependencyUpdatesProviderHandlerDiscoveryTest.php index 8d87c1a285..0e50cc3436 100644 --- a/.vortex/installer/tests/Unit/Prompts/Handlers/DependencyUpdatesProviderHandlerDiscoveryTest.php +++ b/.vortex/installer/tests/Unit/Prompts/Handlers/DependencyUpdatesProviderHandlerDiscoveryTest.php @@ -9,7 +9,6 @@ use DrevOps\VortexInstaller\Prompts\Handlers\DependencyUpdatesProvider; use DrevOps\VortexInstaller\Utils\Config; use DrevOps\VortexInstaller\Utils\File; -use Laravel\Prompts\Key; use PHPUnit\Framework\Attributes\CoversClass; #[CoversClass(DependencyUpdatesProvider::class)] @@ -21,7 +20,7 @@ public static function dataProviderRunPrompts(): \Iterator { $expected_installed = static::getExpectedInstalled(); $all_groups = array_keys(DependencyUpdatesAutomerge::GROUPS); yield 'dependency updates provider - prompt' => [ - [DependencyUpdatesProvider::id() => Key::ENTER], + [DependencyUpdatesProvider::id() => self::KEY_ENTER], [DependencyUpdatesProvider::id() => DependencyUpdatesProvider::RENOVATEBOT_APP] + $expected_defaults, ]; yield 'dependency updates provider - discovery - renovate self-hosted - gha' => [ @@ -75,11 +74,11 @@ function (AbstractHandlerDiscoveryTestCase $test): void { }, ]; yield 'dependency updates automerge - prompt - deselect first group' => [ - [DependencyUpdatesAutomerge::id() => Key::SPACE . Key::ENTER], + [DependencyUpdatesAutomerge::id() => self::KEY_SPACE . self::KEY_ENTER], [DependencyUpdatesAutomerge::id() => array_values(array_diff($all_groups, [DependencyUpdatesAutomerge::PHP]))] + $expected_defaults, ]; yield 'dependency updates automerge - prompt - skipped without renovate' => [ - [DependencyUpdatesProvider::id() => Key::DOWN . Key::DOWN . Key::ENTER], + [DependencyUpdatesProvider::id() => self::KEY_DOWN . self::KEY_DOWN . self::KEY_ENTER], [ DependencyUpdatesProvider::id() => DependencyUpdatesProvider::NONE, DependencyUpdatesAutomerge::id() => NULL, diff --git a/.vortex/installer/tests/Unit/Prompts/Handlers/DeployTypesHandlerDiscoveryTest.php b/.vortex/installer/tests/Unit/Prompts/Handlers/DeployTypesHandlerDiscoveryTest.php index 347e824e59..e33239c583 100644 --- a/.vortex/installer/tests/Unit/Prompts/Handlers/DeployTypesHandlerDiscoveryTest.php +++ b/.vortex/installer/tests/Unit/Prompts/Handlers/DeployTypesHandlerDiscoveryTest.php @@ -7,7 +7,6 @@ use DrevOps\VortexInstaller\Prompts\Handlers\DeployTypes; use DrevOps\VortexInstaller\Utils\Config; use DrevOps\VortexInstaller\Utils\Converter; -use Laravel\Prompts\Key; use PHPUnit\Framework\Attributes\CoversClass; #[CoversClass(DeployTypes::class)] @@ -16,7 +15,7 @@ class DeployTypesHandlerDiscoveryTest extends AbstractHandlerDiscoveryTestCase { public static function dataProviderRunPrompts(): \Iterator { $expected_defaults = static::getExpectedDefaults(); yield 'deploy types - prompt' => [ - [DeployTypes::id() => Key::ENTER], + [DeployTypes::id() => self::KEY_ENTER], [DeployTypes::id() => [DeployTypes::WEBHOOK]] + $expected_defaults, ]; yield 'deploy types - discovery' => [ diff --git a/.vortex/installer/tests/Unit/Prompts/Handlers/DocsHandlerDiscoveryTest.php b/.vortex/installer/tests/Unit/Prompts/Handlers/DocsHandlerDiscoveryTest.php index 86e77a6608..c1caacf3f3 100644 --- a/.vortex/installer/tests/Unit/Prompts/Handlers/DocsHandlerDiscoveryTest.php +++ b/.vortex/installer/tests/Unit/Prompts/Handlers/DocsHandlerDiscoveryTest.php @@ -7,7 +7,6 @@ use DrevOps\VortexInstaller\Prompts\Handlers\PreserveDocsProject; use DrevOps\VortexInstaller\Utils\Config; use DrevOps\VortexInstaller\Utils\File; -use Laravel\Prompts\Key; use PHPUnit\Framework\Attributes\CoversClass; #[CoversClass(PreserveDocsProject::class)] @@ -17,7 +16,7 @@ public static function dataProviderRunPrompts(): \Iterator { $expected_defaults = static::getExpectedDefaults(); $expected_installed = static::getExpectedInstalled(); yield 'preserve project documentation - prompt' => [ - [PreserveDocsProject::id() => Key::ENTER], + [PreserveDocsProject::id() => self::KEY_ENTER], [PreserveDocsProject::id() => TRUE] + $expected_defaults, ]; yield 'preserve project documentation - discovery' => [ diff --git a/.vortex/installer/tests/Unit/Prompts/Handlers/FrontendBuildHandlerDiscoveryTest.php b/.vortex/installer/tests/Unit/Prompts/Handlers/FrontendBuildHandlerDiscoveryTest.php index d2b18f432e..43490fcb73 100644 --- a/.vortex/installer/tests/Unit/Prompts/Handlers/FrontendBuildHandlerDiscoveryTest.php +++ b/.vortex/installer/tests/Unit/Prompts/Handlers/FrontendBuildHandlerDiscoveryTest.php @@ -8,7 +8,6 @@ use DrevOps\VortexInstaller\Prompts\Handlers\Storybook; use DrevOps\VortexInstaller\Prompts\Handlers\Theme; use DrevOps\VortexInstaller\Utils\Config; -use Laravel\Prompts\Key; use PHPUnit\Framework\Attributes\CoversClass; #[CoversClass(FrontendBuild::class)] @@ -25,11 +24,11 @@ public static function dataProviderRunPrompts(): \Iterator { $expected_defaults_core[Storybook::id()] = NULL; yield 'frontend build - prompt' => [ - [FrontendBuild::id() => Key::ENTER], + [FrontendBuild::id() => self::KEY_ENTER], [FrontendBuild::id() => TRUE] + $expected_defaults, ]; yield 'frontend build - not shown for core theme' => [ - [Theme::id() => Key::DOWN . Key::ENTER], + [Theme::id() => self::KEY_DOWN . self::KEY_ENTER], [Theme::id() => Theme::OLIVERO] + $expected_defaults_core, ]; yield 'frontend build - discovery - build in container' => [ diff --git a/.vortex/installer/tests/Unit/Prompts/Handlers/HostingProjectNameHandlerDiscoveryTest.php b/.vortex/installer/tests/Unit/Prompts/Handlers/HostingProjectNameHandlerDiscoveryTest.php index 59a9fbe6d5..cc9dd7d1dd 100644 --- a/.vortex/installer/tests/Unit/Prompts/Handlers/HostingProjectNameHandlerDiscoveryTest.php +++ b/.vortex/installer/tests/Unit/Prompts/Handlers/HostingProjectNameHandlerDiscoveryTest.php @@ -11,7 +11,6 @@ use DrevOps\VortexInstaller\Prompts\Handlers\Webroot; use DrevOps\VortexInstaller\Utils\Config; use DrevOps\VortexInstaller\Utils\File; -use Laravel\Prompts\Key; use PHPUnit\Framework\Attributes\CoversClass; #[CoversClass(HostingProjectName::class)] @@ -20,10 +19,10 @@ class HostingProjectNameHandlerDiscoveryTest extends AbstractHandlerDiscoveryTes public static function dataProviderRunPrompts(): \Iterator { $expected_defaults = static::getExpectedDefaults(); - $clear_keys = implode('', array_fill(0, 20, Key::BACKSPACE)); + $clear_keys = implode('', array_fill(0, 20, self::KEY_BACKSPACE)); yield 'hosting project name - acquia - prompt' => [ [ - HostingProvider::id() => Key::DOWN . Key::ENTER . $clear_keys . 'my_acquia-project', + HostingProvider::id() => self::KEY_DOWN . self::KEY_ENTER . $clear_keys . 'my_acquia-project', ], [ HostingProvider::id() => HostingProvider::ACQUIA, @@ -34,12 +33,12 @@ public static function dataProviderRunPrompts(): \Iterator { ] + $expected_defaults, ]; yield 'hosting project name - acquia - prompt - invalid' => [ - [HostingProvider::id() => Key::DOWN . Key::ENTER . $clear_keys . 'my_acquia project'], + [HostingProvider::id() => self::KEY_DOWN . self::KEY_ENTER . $clear_keys . 'my_acquia project'], 'Please enter a valid machine name: only lowercase letters, numbers, hyphens and underscores are allowed.', ]; yield 'hosting project name - acquia - discovery from .env' => [ [ - HostingProvider::id() => Key::DOWN . Key::ENTER, + HostingProvider::id() => self::KEY_DOWN . self::KEY_ENTER, ], [ HostingProvider::id() => HostingProvider::ACQUIA, @@ -54,7 +53,7 @@ function (AbstractHandlerDiscoveryTestCase $test, Config $config): void { ]; yield 'hosting project name - acquia - discovery from settings.acquia.php' => [ [ - HostingProvider::id() => Key::DOWN . Key::ENTER, + HostingProvider::id() => self::KEY_DOWN . self::KEY_ENTER, ], [ HostingProvider::id() => HostingProvider::ACQUIA, @@ -74,7 +73,7 @@ function (AbstractHandlerDiscoveryTestCase $test, Config $config): void { ]; yield 'hosting project name - lagoon - prompt' => [ [ - HostingProvider::id() => Key::DOWN . Key::DOWN . Key::ENTER . $clear_keys . 'my_lagoon-project', + HostingProvider::id() => self::KEY_DOWN . self::KEY_DOWN . self::KEY_ENTER . $clear_keys . 'my_lagoon-project' . self::KEY_ENTER, ], [ HostingProvider::id() => HostingProvider::LAGOON, @@ -84,12 +83,12 @@ function (AbstractHandlerDiscoveryTestCase $test, Config $config): void { ] + $expected_defaults, ]; yield 'hosting project name - lagoon - prompt - invalid' => [ - [HostingProvider::id() => Key::DOWN . Key::DOWN . Key::ENTER . $clear_keys . 'my_lagoon project'], + [HostingProvider::id() => self::KEY_DOWN . self::KEY_DOWN . self::KEY_ENTER . $clear_keys . 'my_lagoon project'], 'Please enter a valid machine name: only lowercase letters, numbers, hyphens and underscores are allowed.', ]; yield 'hosting project name - lagoon - discovery from .env' => [ [ - HostingProvider::id() => Key::DOWN . Key::DOWN . Key::ENTER, + HostingProvider::id() => self::KEY_DOWN . self::KEY_DOWN . self::KEY_ENTER . self::KEY_ENTER, ], [ HostingProvider::id() => HostingProvider::LAGOON, @@ -103,7 +102,7 @@ function (AbstractHandlerDiscoveryTestCase $test, Config $config): void { ]; yield 'hosting project name - lagoon - discovery from drush lagoon.site.yml' => [ [ - HostingProvider::id() => Key::DOWN . Key::DOWN . Key::ENTER, + HostingProvider::id() => self::KEY_DOWN . self::KEY_DOWN . self::KEY_ENTER . self::KEY_ENTER, ], [ HostingProvider::id() => HostingProvider::LAGOON, diff --git a/.vortex/installer/tests/Unit/Prompts/Handlers/HostingProviderHandlerDiscoveryTest.php b/.vortex/installer/tests/Unit/Prompts/Handlers/HostingProviderHandlerDiscoveryTest.php index fc8558a38a..4d9fd20946 100644 --- a/.vortex/installer/tests/Unit/Prompts/Handlers/HostingProviderHandlerDiscoveryTest.php +++ b/.vortex/installer/tests/Unit/Prompts/Handlers/HostingProviderHandlerDiscoveryTest.php @@ -11,7 +11,6 @@ use DrevOps\VortexInstaller\Prompts\Handlers\Webroot; use DrevOps\VortexInstaller\Utils\Config; use DrevOps\VortexInstaller\Utils\File; -use Laravel\Prompts\Key; use PHPUnit\Framework\Attributes\CoversClass; #[CoversClass(HostingProvider::class)] @@ -20,7 +19,7 @@ class HostingProviderHandlerDiscoveryTest extends AbstractHandlerDiscoveryTestCa public static function dataProviderRunPrompts(): \Iterator { $expected_defaults = static::getExpectedDefaults(); yield 'hosting provider - prompt' => [ - [HostingProvider::id() => Key::ENTER], + [HostingProvider::id() => self::KEY_ENTER], [HostingProvider::id() => HostingProvider::NONE] + $expected_defaults, ]; yield 'hosting provider - discovery - Acquia' => [ @@ -50,7 +49,7 @@ function (AbstractHandlerDiscoveryTestCase $test, Config $config): void { }, ]; yield 'hosting provider - discovery - Lagoon' => [ - [], + [HostingProvider::id() => self::KEY_ENTER . self::KEY_ENTER], [ HostingProvider::id() => HostingProvider::LAGOON, HostingProjectName::id() => 'myproject', diff --git a/.vortex/installer/tests/Unit/Prompts/Handlers/MigrationFetchSourceHandlerDiscoveryTest.php b/.vortex/installer/tests/Unit/Prompts/Handlers/MigrationFetchSourceHandlerDiscoveryTest.php index fa6800840e..2e800ecf29 100644 --- a/.vortex/installer/tests/Unit/Prompts/Handlers/MigrationFetchSourceHandlerDiscoveryTest.php +++ b/.vortex/installer/tests/Unit/Prompts/Handlers/MigrationFetchSourceHandlerDiscoveryTest.php @@ -6,7 +6,6 @@ use DrevOps\VortexInstaller\Prompts\Handlers\Migration; use DrevOps\VortexInstaller\Prompts\Handlers\MigrationFetchSource; -use Laravel\Prompts\Key; use PHPUnit\Framework\Attributes\CoversClass; #[CoversClass(MigrationFetchSource::class)] @@ -16,21 +15,22 @@ public static function dataProviderRunPrompts(): \Iterator { $expected_defaults = static::getExpectedDefaults(); yield 'migration download source - prompt' => [ [ - Migration::id() => Key::LEFT . Key::ENTER, - MigrationFetchSource::id() => Key::ENTER, + Migration::id() => self::KEY_LEFT . self::KEY_ENTER, + MigrationFetchSource::id() => self::KEY_ENTER, ], [Migration::id() => TRUE, MigrationFetchSource::id() => MigrationFetchSource::URL] + $expected_defaults, ]; yield 'migration download source - prompt - ftp' => [ [ - Migration::id() => Key::LEFT . Key::ENTER, - MigrationFetchSource::id() => Key::DOWN . Key::ENTER, + Migration::id() => self::KEY_LEFT . self::KEY_ENTER, + MigrationFetchSource::id() => self::KEY_DOWN . self::KEY_ENTER, ], [Migration::id() => TRUE, MigrationFetchSource::id() => MigrationFetchSource::FTP] + $expected_defaults, ]; yield 'migration download source - discovery' => [ [ - Migration::id() => Key::LEFT . Key::ENTER, + Migration::id() => self::KEY_LEFT . self::KEY_ENTER, + MigrationFetchSource::id() => self::KEY_ENTER, ], [Migration::id() => TRUE, MigrationFetchSource::id() => MigrationFetchSource::FTP] + $expected_defaults, function (AbstractHandlerDiscoveryTestCase $test): void { @@ -39,7 +39,8 @@ function (AbstractHandlerDiscoveryTestCase $test): void { ]; yield 'migration download source - discovery - s3' => [ [ - Migration::id() => Key::LEFT . Key::ENTER, + Migration::id() => self::KEY_LEFT . self::KEY_ENTER, + MigrationFetchSource::id() => self::KEY_ENTER, ], [Migration::id() => TRUE, MigrationFetchSource::id() => MigrationFetchSource::S3] + $expected_defaults, function (AbstractHandlerDiscoveryTestCase $test): void { @@ -48,8 +49,8 @@ function (AbstractHandlerDiscoveryTestCase $test): void { ]; yield 'migration download source - discovery - invalid' => [ [ - Migration::id() => Key::LEFT . Key::ENTER, - MigrationFetchSource::id() => Key::ENTER, + Migration::id() => self::KEY_LEFT . self::KEY_ENTER, + MigrationFetchSource::id() => self::KEY_ENTER, ], [Migration::id() => TRUE, MigrationFetchSource::id() => MigrationFetchSource::URL] + $expected_defaults, function (AbstractHandlerDiscoveryTestCase $test): void { diff --git a/.vortex/installer/tests/Unit/Prompts/Handlers/MigrationHandlerDiscoveryTest.php b/.vortex/installer/tests/Unit/Prompts/Handlers/MigrationHandlerDiscoveryTest.php index 5eebc65d8c..ca38df3687 100644 --- a/.vortex/installer/tests/Unit/Prompts/Handlers/MigrationHandlerDiscoveryTest.php +++ b/.vortex/installer/tests/Unit/Prompts/Handlers/MigrationHandlerDiscoveryTest.php @@ -10,7 +10,6 @@ use DrevOps\VortexInstaller\Utils\Config; use DrevOps\VortexInstaller\Utils\File; use DrevOps\VortexInstaller\Utils\Yaml; -use Laravel\Prompts\Key; use PHPUnit\Framework\Attributes\CoversClass; #[CoversClass(Migration::class)] @@ -20,19 +19,19 @@ public static function dataProviderRunPrompts(): \Iterator { $expected_defaults = static::getExpectedDefaults(); $expected_installed = static::getExpectedInstalled(); yield 'migration - prompt - disabled' => [ - [Migration::id() => Key::ENTER], + [Migration::id() => self::KEY_ENTER], [Migration::id() => FALSE] + $expected_defaults, ]; yield 'migration - prompt - enabled' => [ [ - Migration::id() => Key::LEFT . Key::ENTER, - MigrationFetchSource::id() => Key::ENTER, + Migration::id() => self::KEY_LEFT . self::KEY_ENTER, + MigrationFetchSource::id() => self::KEY_ENTER, ], [Migration::id() => TRUE, MigrationFetchSource::id() => MigrationFetchSource::URL] + $expected_defaults, ]; yield 'migration - discovery - database2 exists' => [ [ - MigrationFetchSource::id() => Key::ENTER, + MigrationFetchSource::id() => self::KEY_ENTER, ], [Migration::id() => TRUE, MigrationFetchSource::id() => MigrationFetchSource::URL] + $expected_installed, function (AbstractHandlerDiscoveryTestCase $test, Config $config): void { diff --git a/.vortex/installer/tests/Unit/Prompts/Handlers/MigrationImageHandlerDiscoveryTest.php b/.vortex/installer/tests/Unit/Prompts/Handlers/MigrationImageHandlerDiscoveryTest.php index 34769268f0..20ff21d460 100644 --- a/.vortex/installer/tests/Unit/Prompts/Handlers/MigrationImageHandlerDiscoveryTest.php +++ b/.vortex/installer/tests/Unit/Prompts/Handlers/MigrationImageHandlerDiscoveryTest.php @@ -8,7 +8,6 @@ use DrevOps\VortexInstaller\Prompts\Handlers\MigrationFetchSource; use DrevOps\VortexInstaller\Prompts\Handlers\MigrationImage; use DrevOps\VortexInstaller\Utils\Config; -use Laravel\Prompts\Key; use PHPUnit\Framework\Attributes\CoversClass; #[CoversClass(MigrationImage::class)] @@ -18,24 +17,25 @@ public static function dataProviderRunPrompts(): \Iterator { $expected_defaults = static::getExpectedDefaults(); yield 'migration image - default' => [ [ - Migration::id() => Key::LEFT . Key::ENTER, - MigrationFetchSource::id() => Key::DOWN . Key::DOWN . Key::DOWN . Key::DOWN . Key::ENTER, + Migration::id() => self::KEY_LEFT . self::KEY_ENTER, + MigrationFetchSource::id() => self::KEY_DOWN . self::KEY_DOWN . self::KEY_DOWN . self::KEY_DOWN . self::KEY_ENTER, MigrationImage::id() => static::TUI_DEFAULT, ], [Migration::id() => TRUE, MigrationFetchSource::id() => MigrationFetchSource::CONTAINER_REGISTRY, MigrationImage::id() => 'myprojectorg/myproject-data-migration:latest'] + $expected_defaults, ]; yield 'migration image - invalid' => [ [ - Migration::id() => Key::LEFT . Key::ENTER, - MigrationFetchSource::id() => Key::DOWN . Key::DOWN . Key::DOWN . Key::DOWN . Key::ENTER, + Migration::id() => self::KEY_LEFT . self::KEY_ENTER, + MigrationFetchSource::id() => self::KEY_DOWN . self::KEY_DOWN . self::KEY_DOWN . self::KEY_DOWN . self::KEY_ENTER, MigrationImage::id() => 'myregistry:myimage:mytag', ], 'Please enter a valid container image name with an optional tag.', ]; yield 'migration image - discovery' => [ [ - Migration::id() => Key::LEFT . Key::ENTER, - MigrationFetchSource::id() => Key::DOWN . Key::DOWN . Key::DOWN . Key::DOWN . Key::ENTER, + Migration::id() => self::KEY_LEFT . self::KEY_ENTER, + MigrationFetchSource::id() => self::KEY_DOWN . self::KEY_DOWN . self::KEY_DOWN . self::KEY_DOWN . self::KEY_ENTER, + MigrationImage::id() => static::TUI_DEFAULT, ], [ Migration::id() => TRUE, diff --git a/.vortex/installer/tests/Unit/Prompts/Handlers/ModulesHandlerDiscoveryTest.php b/.vortex/installer/tests/Unit/Prompts/Handlers/ModulesHandlerDiscoveryTest.php index 45b37aa477..cf1f8546c9 100644 --- a/.vortex/installer/tests/Unit/Prompts/Handlers/ModulesHandlerDiscoveryTest.php +++ b/.vortex/installer/tests/Unit/Prompts/Handlers/ModulesHandlerDiscoveryTest.php @@ -7,7 +7,6 @@ use DrevOps\VortexInstaller\Prompts\Handlers\Modules; use DrevOps\VortexInstaller\Utils\Config; use DrevOps\VortexInstaller\Utils\File; -use Laravel\Prompts\Key; use PHPUnit\Framework\Attributes\CoversClass; #[CoversClass(Modules::class)] @@ -17,7 +16,7 @@ public static function dataProviderRunPrompts(): \Iterator { $expected_defaults = static::getExpectedDefaults(); $expected_installed = static::getExpectedInstalled(); yield 'modules - prompt' => [ - [Modules::id() => Key::ENTER], + [Modules::id() => self::KEY_ENTER], [Modules::id() => array_keys(Modules::getAvailableModules())] + $expected_defaults, ]; yield 'modules - discovery - some modules' => [ diff --git a/.vortex/installer/tests/Unit/Prompts/Handlers/NotificationChannelsHandlerDiscoveryTest.php b/.vortex/installer/tests/Unit/Prompts/Handlers/NotificationChannelsHandlerDiscoveryTest.php index 17a8493b60..bf827d2f8d 100644 --- a/.vortex/installer/tests/Unit/Prompts/Handlers/NotificationChannelsHandlerDiscoveryTest.php +++ b/.vortex/installer/tests/Unit/Prompts/Handlers/NotificationChannelsHandlerDiscoveryTest.php @@ -7,7 +7,6 @@ use DrevOps\VortexInstaller\Prompts\Handlers\NotificationChannels; use DrevOps\VortexInstaller\Utils\Config; use DrevOps\VortexInstaller\Utils\Converter; -use Laravel\Prompts\Key; use PHPUnit\Framework\Attributes\CoversClass; #[CoversClass(NotificationChannels::class)] @@ -17,7 +16,7 @@ public static function dataProviderRunPrompts(): \Iterator { $expected_defaults = static::getExpectedDefaults(); $expected_installed = static::getExpectedInstalled(); yield 'notification channels - prompt' => [ - [NotificationChannels::id() => Key::ENTER], + [NotificationChannels::id() => self::KEY_ENTER], $expected_defaults, ]; yield 'notification channels - discovery - email only' => [ diff --git a/.vortex/installer/tests/Unit/Prompts/Handlers/ProfileHandlerDiscoveryTest.php b/.vortex/installer/tests/Unit/Prompts/Handlers/ProfileHandlerDiscoveryTest.php index fc302fc98e..325dd11280 100644 --- a/.vortex/installer/tests/Unit/Prompts/Handlers/ProfileHandlerDiscoveryTest.php +++ b/.vortex/installer/tests/Unit/Prompts/Handlers/ProfileHandlerDiscoveryTest.php @@ -7,7 +7,6 @@ use DrevOps\VortexInstaller\Prompts\Handlers\Profile; use DrevOps\VortexInstaller\Utils\Config; use DrevOps\VortexInstaller\Utils\File; -use Laravel\Prompts\Key; use PHPUnit\Framework\Attributes\CoversClass; #[CoversClass(Profile::class)] @@ -17,15 +16,15 @@ public static function dataProviderRunPrompts(): \Iterator { $expected_defaults = static::getExpectedDefaults(); $expected_installed = static::getExpectedInstalled(); yield 'profile - prompt' => [ - [Profile::id() => Key::DOWN . Key::ENTER], + [Profile::id() => self::KEY_DOWN . self::KEY_ENTER], [Profile::id() => 'minimal'] + $expected_defaults, ]; yield 'profile - prompt - custom' => [ - [Profile::id() => Key::DOWN . Key::DOWN . Key::DOWN . Key::ENTER . 'myprofile'], + [Profile::id() => self::KEY_DOWN . self::KEY_DOWN . self::KEY_DOWN . self::KEY_ENTER . 'myprofile' . self::KEY_ENTER], [Profile::id() => 'myprofile'] + $expected_defaults, ]; yield 'profile - prompt - invalid' => [ - [Profile::id() => Key::DOWN . Key::DOWN . Key::DOWN . Key::ENTER . 'my profile'], + [Profile::id() => self::KEY_DOWN . self::KEY_DOWN . self::KEY_DOWN . self::KEY_ENTER . 'my profile'], 'Please enter a valid profile name: only lowercase letters, numbers, and underscores are allowed.', ]; yield 'profile - discovery' => [ diff --git a/.vortex/installer/tests/Unit/Prompts/Handlers/ProvisionTypeHandlerDiscoveryTest.php b/.vortex/installer/tests/Unit/Prompts/Handlers/ProvisionTypeHandlerDiscoveryTest.php index 586614f9e4..699d1c462e 100644 --- a/.vortex/installer/tests/Unit/Prompts/Handlers/ProvisionTypeHandlerDiscoveryTest.php +++ b/.vortex/installer/tests/Unit/Prompts/Handlers/ProvisionTypeHandlerDiscoveryTest.php @@ -7,7 +7,6 @@ use DrevOps\VortexInstaller\Prompts\Handlers\DatabaseFetchSource; use DrevOps\VortexInstaller\Prompts\Handlers\ProvisionType; use DrevOps\VortexInstaller\Utils\Config; -use Laravel\Prompts\Key; use PHPUnit\Framework\Attributes\CoversClass; #[CoversClass(ProvisionType::class)] @@ -16,7 +15,7 @@ class ProvisionTypeHandlerDiscoveryTest extends AbstractHandlerDiscoveryTestCase public static function dataProviderRunPrompts(): \Iterator { $expected_defaults = static::getExpectedDefaults(); yield 'provision type - prompt' => [ - [ProvisionType::id() => Key::ENTER], + [ProvisionType::id() => self::KEY_ENTER], [ProvisionType::id() => ProvisionType::DATABASE] + $expected_defaults, ]; yield 'provision type - discovery - database' => [ diff --git a/.vortex/installer/tests/Unit/Prompts/Handlers/PullRequestHandlerDiscoveryTest.php b/.vortex/installer/tests/Unit/Prompts/Handlers/PullRequestHandlerDiscoveryTest.php index cfa0cb8069..7f06c10860 100644 --- a/.vortex/installer/tests/Unit/Prompts/Handlers/PullRequestHandlerDiscoveryTest.php +++ b/.vortex/installer/tests/Unit/Prompts/Handlers/PullRequestHandlerDiscoveryTest.php @@ -8,7 +8,6 @@ use DrevOps\VortexInstaller\Prompts\Handlers\LabelMergeConflictsPr; use DrevOps\VortexInstaller\Utils\Config; use DrevOps\VortexInstaller\Utils\File; -use Laravel\Prompts\Key; use PHPUnit\Framework\Attributes\CoversClass; #[CoversClass(AssignAuthorPr::class)] @@ -19,7 +18,7 @@ public static function dataProviderRunPrompts(): \Iterator { $expected_defaults = static::getExpectedDefaults(); $expected_installed = static::getExpectedInstalled(); yield 'auto assign pr - prompt' => [ - [AssignAuthorPr::id() => Key::ENTER], + [AssignAuthorPr::id() => self::KEY_ENTER], [AssignAuthorPr::id() => TRUE] + $expected_defaults, ]; yield 'auto assign pr - discovery' => [ @@ -52,7 +51,7 @@ function (AbstractHandlerDiscoveryTestCase $test): void { }, ]; yield 'label merge conflicts - prompt' => [ - [LabelMergeConflictsPr::id() => Key::ENTER], + [LabelMergeConflictsPr::id() => self::KEY_ENTER], [LabelMergeConflictsPr::id() => TRUE] + $expected_defaults, ]; yield 'label merge conflicts - discovery' => [ diff --git a/.vortex/installer/tests/Unit/Prompts/Handlers/ServicesHandlerDiscoveryTest.php b/.vortex/installer/tests/Unit/Prompts/Handlers/ServicesHandlerDiscoveryTest.php index 9daed2c03a..02f2fd16a8 100644 --- a/.vortex/installer/tests/Unit/Prompts/Handlers/ServicesHandlerDiscoveryTest.php +++ b/.vortex/installer/tests/Unit/Prompts/Handlers/ServicesHandlerDiscoveryTest.php @@ -8,7 +8,6 @@ use DrevOps\VortexInstaller\Utils\Config; use DrevOps\VortexInstaller\Utils\File; use DrevOps\VortexInstaller\Utils\Yaml; -use Laravel\Prompts\Key; use PHPUnit\Framework\Attributes\CoversClass; #[CoversClass(Services::class)] @@ -18,7 +17,7 @@ public static function dataProviderRunPrompts(): \Iterator { $expected_defaults = static::getExpectedDefaults(); $expected_installed = static::getExpectedInstalled(); yield 'services - prompt' => [ - [Services::id() => Key::ENTER], + [Services::id() => self::KEY_ENTER], [Services::id() => [Services::CLAMAV, Services::REDIS, Services::SOLR]] + $expected_defaults, ]; yield 'services - discovery - solr' => [ diff --git a/.vortex/installer/tests/Unit/Prompts/Handlers/StarterHandlerDiscoveryTest.php b/.vortex/installer/tests/Unit/Prompts/Handlers/StarterHandlerDiscoveryTest.php index 3c5f9704d2..d0ef6b9fbc 100644 --- a/.vortex/installer/tests/Unit/Prompts/Handlers/StarterHandlerDiscoveryTest.php +++ b/.vortex/installer/tests/Unit/Prompts/Handlers/StarterHandlerDiscoveryTest.php @@ -7,7 +7,6 @@ use DrevOps\VortexInstaller\Prompts\Handlers\Profile; use DrevOps\VortexInstaller\Prompts\Handlers\Starter; use DrevOps\VortexInstaller\Utils\Config; -use Laravel\Prompts\Key; use PHPUnit\Framework\Attributes\CoversClass; #[CoversClass(Starter::class)] @@ -16,15 +15,15 @@ class StarterHandlerDiscoveryTest extends AbstractHandlerDiscoveryTestCase { public static function dataProviderRunPrompts(): \Iterator { $expected_defaults = static::getExpectedDefaults(); yield 'starter - prompt' => [ - [Starter::id() => Key::ENTER], + [Starter::id() => self::KEY_ENTER], [Starter::id() => Starter::LOAD_DATABASE_DEMO] + $expected_defaults, ]; yield 'starter - prompt - Drupal profile' => [ - [Starter::id() => Key::DOWN . Key::ENTER], + [Starter::id() => self::KEY_DOWN . self::KEY_ENTER], [Starter::id() => Starter::INSTALL_PROFILE_CORE] + $expected_defaults, ]; yield 'starter - prompt - Drupal CMS profile' => [ - [Starter::id() => Key::DOWN . Key::DOWN . Key::ENTER], + [Starter::id() => self::KEY_DOWN . self::KEY_DOWN . self::KEY_ENTER], [ Starter::id() => Starter::INSTALL_PROFILE_DRUPALCMS, Profile::id() => Starter::INSTALL_PROFILE_DRUPALCMS_PATH, diff --git a/.vortex/installer/tests/Unit/Prompts/Handlers/StorybookHandlerDiscoveryTest.php b/.vortex/installer/tests/Unit/Prompts/Handlers/StorybookHandlerDiscoveryTest.php index b4b017634b..d35023823d 100644 --- a/.vortex/installer/tests/Unit/Prompts/Handlers/StorybookHandlerDiscoveryTest.php +++ b/.vortex/installer/tests/Unit/Prompts/Handlers/StorybookHandlerDiscoveryTest.php @@ -9,7 +9,6 @@ use DrevOps\VortexInstaller\Prompts\Handlers\Theme; use DrevOps\VortexInstaller\Utils\Config; use DrevOps\VortexInstaller\Utils\File; -use Laravel\Prompts\Key; use PHPUnit\Framework\Attributes\CoversClass; #[CoversClass(Storybook::class)] @@ -26,15 +25,15 @@ public static function dataProviderRunPrompts(): \Iterator { $expected_defaults_core[Storybook::id()] = NULL; yield 'storybook - prompt - disabled' => [ - [Storybook::id() => Key::ENTER], + [Storybook::id() => self::KEY_ENTER], [Storybook::id() => FALSE] + $expected_defaults, ]; yield 'storybook - prompt - enabled' => [ - [Storybook::id() => Key::LEFT . Key::ENTER], + [Storybook::id() => self::KEY_LEFT . self::KEY_ENTER], [Storybook::id() => TRUE] + $expected_defaults, ]; yield 'storybook - not shown for core theme' => [ - [Theme::id() => Key::DOWN . Key::ENTER], + [Theme::id() => self::KEY_DOWN . self::KEY_ENTER], [Theme::id() => Theme::OLIVERO] + $expected_defaults_core, ]; yield 'storybook - discovery - provision script present' => [ diff --git a/.vortex/installer/tests/Unit/Prompts/Handlers/ThemeHandlerDiscoveryTest.php b/.vortex/installer/tests/Unit/Prompts/Handlers/ThemeHandlerDiscoveryTest.php index 51ef0cd63a..a3cd8bf698 100644 --- a/.vortex/installer/tests/Unit/Prompts/Handlers/ThemeHandlerDiscoveryTest.php +++ b/.vortex/installer/tests/Unit/Prompts/Handlers/ThemeHandlerDiscoveryTest.php @@ -9,7 +9,6 @@ use DrevOps\VortexInstaller\Prompts\Handlers\Theme; use DrevOps\VortexInstaller\Utils\Config; use DrevOps\VortexInstaller\Utils\File; -use Laravel\Prompts\Key; use PHPUnit\Framework\Attributes\CoversClass; #[CoversClass(Theme::class)] @@ -28,29 +27,29 @@ public static function dataProviderRunPrompts(): \Iterator { $expected_installed_core[FrontendBuild::id()] = NULL; $expected_installed_core[Storybook::id()] = NULL; - $clear_keys = implode('', array_fill(0, 20, Key::BACKSPACE)); + $clear_keys = implode('', array_fill(0, 20, self::KEY_BACKSPACE)); yield 'theme - prompt - olivero' => [ - [Theme::id() => Key::DOWN . Key::ENTER], + [Theme::id() => self::KEY_DOWN . self::KEY_ENTER], [Theme::id() => Theme::OLIVERO] + $expected_defaults_core, ]; yield 'theme - prompt - claro' => [ - [Theme::id() => Key::DOWN . Key::DOWN . Key::ENTER], + [Theme::id() => self::KEY_DOWN . self::KEY_DOWN . self::KEY_ENTER], [Theme::id() => Theme::CLARO] + $expected_defaults_core, ]; yield 'theme - prompt - stark' => [ - [Theme::id() => Key::DOWN . Key::DOWN . Key::DOWN . Key::ENTER], + [Theme::id() => self::KEY_DOWN . self::KEY_DOWN . self::KEY_DOWN . self::KEY_ENTER], [Theme::id() => Theme::STARK] + $expected_defaults_core, ]; yield 'theme - prompt - custom' => [ - [Theme::id() => Key::ENTER . $clear_keys . 'mytheme'], + [Theme::id() => self::KEY_ENTER . $clear_keys . 'mytheme'], [Theme::id() => 'mytheme'] + $expected_defaults, ]; yield 'theme - prompt - custom - invalid' => [ - [Theme::id() => Key::ENTER . $clear_keys . 'my theme'], + [Theme::id() => self::KEY_ENTER . $clear_keys . 'my theme'], 'Please enter a valid theme machine name: only lowercase letters, numbers, and underscores are allowed.', ]; yield 'theme - prompt - custom - invalid - capitalization' => [ - [Theme::id() => Key::ENTER . $clear_keys . 'MyTheme'], + [Theme::id() => self::KEY_ENTER . $clear_keys . 'MyTheme'], 'Please enter a valid theme machine name: only lowercase letters, numbers, and underscores are allowed.', ]; yield 'theme - discovery - olivero' => [ diff --git a/.vortex/installer/tests/Unit/Prompts/Handlers/ToolsHandlerDiscoveryTest.php b/.vortex/installer/tests/Unit/Prompts/Handlers/ToolsHandlerDiscoveryTest.php index 68ef729a35..56fb29f6ab 100644 --- a/.vortex/installer/tests/Unit/Prompts/Handlers/ToolsHandlerDiscoveryTest.php +++ b/.vortex/installer/tests/Unit/Prompts/Handlers/ToolsHandlerDiscoveryTest.php @@ -8,7 +8,6 @@ use DrevOps\VortexInstaller\Prompts\Handlers\Tools; use DrevOps\VortexInstaller\Utils\Config; use DrevOps\VortexInstaller\Utils\File; -use Laravel\Prompts\Key; use PHPUnit\Framework\Attributes\CoversClass; #[CoversClass(Tools::class)] @@ -18,7 +17,7 @@ public static function dataProviderRunPrompts(): \Iterator { $expected_defaults = static::getExpectedDefaults(); $expected_installed = static::getExpectedInstalled(); yield 'tools - prompt - defaults' => [ - [Tools::id() => Key::ENTER], + [Tools::id() => self::KEY_ENTER], [Tools::id() => [Tools::BEHAT, Tools::DCLINT, Tools::ESLINT, Tools::HADOLINT, Tools::JEST, Tools::PHPCS, Tools::PHPSTAN, Tools::PHPUNIT, Tools::RECTOR, Tools::STYLELINT, Tools::TWIG_CS_FIXER]] + $expected_defaults, ]; yield 'tools - discovery - all tools' => [ diff --git a/.vortex/installer/tests/Unit/Prompts/Handlers/VersionSchemeHandlerDiscoveryTest.php b/.vortex/installer/tests/Unit/Prompts/Handlers/VersionSchemeHandlerDiscoveryTest.php index c6c15617ba..6633ba9945 100644 --- a/.vortex/installer/tests/Unit/Prompts/Handlers/VersionSchemeHandlerDiscoveryTest.php +++ b/.vortex/installer/tests/Unit/Prompts/Handlers/VersionSchemeHandlerDiscoveryTest.php @@ -6,7 +6,6 @@ use DrevOps\VortexInstaller\Prompts\Handlers\VersionScheme; use DrevOps\VortexInstaller\Utils\Config; -use Laravel\Prompts\Key; use PHPUnit\Framework\Attributes\CoversClass; #[CoversClass(VersionScheme::class)] @@ -16,7 +15,7 @@ public static function dataProviderRunPrompts(): \Iterator { $expected_defaults = static::getExpectedDefaults(); $expected_installed = static::getExpectedInstalled(); yield 'version scheme - prompt' => [ - [VersionScheme::id() => Key::ENTER], + [VersionScheme::id() => self::KEY_ENTER], $expected_defaults, ]; yield 'version scheme - discovery - calver' => [ diff --git a/.vortex/installer/tests/Unit/Prompts/Handlers/WebrootHandlerDiscoveryTest.php b/.vortex/installer/tests/Unit/Prompts/Handlers/WebrootHandlerDiscoveryTest.php index eed0026ca8..73e24f4f5f 100644 --- a/.vortex/installer/tests/Unit/Prompts/Handlers/WebrootHandlerDiscoveryTest.php +++ b/.vortex/installer/tests/Unit/Prompts/Handlers/WebrootHandlerDiscoveryTest.php @@ -7,7 +7,6 @@ use DrevOps\VortexInstaller\Prompts\Handlers\HostingProvider; use DrevOps\VortexInstaller\Prompts\Handlers\Webroot; use DrevOps\VortexInstaller\Utils\Config; -use Laravel\Prompts\Key; use PHPUnit\Framework\Attributes\CoversClass; #[CoversClass(Webroot::class)] @@ -17,7 +16,7 @@ public static function dataProviderRunPrompts(): \Iterator { $expected_defaults = static::getExpectedDefaults(); yield 'webroot - prompt' => [ [ - HostingProvider::id() => Key::DOWN . Key::DOWN . Key::DOWN . Key::ENTER, + HostingProvider::id() => self::KEY_DOWN . self::KEY_DOWN . self::KEY_DOWN . self::KEY_ENTER, Webroot::id() => 'my_webroot', ], [ @@ -27,7 +26,7 @@ public static function dataProviderRunPrompts(): \Iterator { ]; yield 'webroot - prompt - capitalization' => [ [ - HostingProvider::id() => Key::DOWN . Key::DOWN . Key::DOWN . Key::ENTER, + HostingProvider::id() => self::KEY_DOWN . self::KEY_DOWN . self::KEY_DOWN . self::KEY_ENTER, Webroot::id() => 'MyWebroot', ], [ @@ -37,7 +36,7 @@ public static function dataProviderRunPrompts(): \Iterator { ]; yield 'webroot - prompt - invalid' => [ [ - HostingProvider::id() => Key::DOWN . Key::DOWN . Key::DOWN . Key::ENTER, + HostingProvider::id() => self::KEY_DOWN . self::KEY_DOWN . self::KEY_DOWN . self::KEY_ENTER, Webroot::id() => 'my webroot', ], 'Please enter a valid webroot name: only lowercase letters, numbers, and underscores are allowed.', diff --git a/.vortex/installer/tests/Unit/Prompts/PromptTypeTest.php b/.vortex/installer/tests/Unit/Prompts/PromptTypeTest.php index 02c2f1c034..9bd24ae5e0 100644 --- a/.vortex/installer/tests/Unit/Prompts/PromptTypeTest.php +++ b/.vortex/installer/tests/Unit/Prompts/PromptTypeTest.php @@ -15,22 +15,6 @@ #[CoversClass(PromptType::class)] class PromptTypeTest extends UnitTestCase { - #[DataProvider('dataProviderPromptFunctionResolvesToNamedHelper')] - public function testPromptFunctionResolvesToNamedHelper(PromptType $case): void { - $reflection = new \ReflectionFunction($case->promptFunction()); - - $this->assertSame('Laravel\Prompts\\' . $case->value, $reflection->getName()); - } - - /** - * Data provider for testPromptFunctionResolvesToNamedHelper. - */ - public static function dataProviderPromptFunctionResolvesToNamedHelper(): \Iterator { - foreach (PromptType::cases() as $case) { - yield $case->name => [$case]; - } - } - #[DataProvider('dataProviderFromValidString')] public function testFromValidString(string $value, PromptType $expected): void { $this->assertSame($expected, PromptType::from($value)); @@ -45,12 +29,6 @@ public static function dataProviderFromValidString(): \Iterator { yield 'multiselect' => ['multiselect', PromptType::MultiSelect]; yield 'confirm' => ['confirm', PromptType::Confirm]; yield 'suggest' => ['suggest', PromptType::Suggest]; - yield 'number' => ['number', PromptType::Number]; - yield 'textarea' => ['textarea', PromptType::Textarea]; - yield 'password' => ['password', PromptType::Password]; - yield 'search' => ['search', PromptType::Search]; - yield 'multisearch' => ['multisearch', PromptType::MultiSearch]; - yield 'pause' => ['pause', PromptType::Pause]; } public function testFromInvalidString(): void { diff --git a/.vortex/installer/tests/Unit/Task/TaskOutputTest.php b/.vortex/installer/tests/Unit/Task/TaskOutputTest.php deleted file mode 100644 index 04b70386dd..0000000000 --- a/.vortex/installer/tests/Unit/Task/TaskOutputTest.php +++ /dev/null @@ -1,128 +0,0 @@ -assertInstanceOf(TaskOutput::class, $output); - } - - /** - * Test write method dims single message. - */ - public function testWriteSingleMessage(): void { - $wrapped = new BufferedOutput(); - $output = new TaskOutput($wrapped); - - $output->write('Test message'); - - $content = $wrapped->fetch(); - // The message should be dimmed (wrapped with ANSI codes). - $this->assertStringContainsString('Test message', $content); - } - - /** - * Test write method dims iterable messages. - */ - public function testWriteIterableMessages(): void { - $wrapped = new BufferedOutput(); - $output = new TaskOutput($wrapped); - - $output->write(['Line 1', 'Line 2']); - - $content = $wrapped->fetch(); - $this->assertStringContainsString('Line 1', $content); - $this->assertStringContainsString('Line 2', $content); - } - - /** - * Test writeln method dims single message. - */ - public function testWritelnSingleMessage(): void { - $wrapped = new BufferedOutput(); - $output = new TaskOutput($wrapped); - - $output->writeln('Test message'); - - $content = $wrapped->fetch(); - $this->assertStringContainsString('Test message', $content); - } - - /** - * Test writeln method dims iterable messages. - */ - public function testWritelnIterableMessages(): void { - $wrapped = new BufferedOutput(); - $output = new TaskOutput($wrapped); - - $output->writeln(['Line 1', 'Line 2']); - - $content = $wrapped->fetch(); - $this->assertStringContainsString('Line 1', $content); - $this->assertStringContainsString('Line 2', $content); - } - - /** - * Test verbosity delegation. - */ - public function testVerbosityDelegation(): void { - $wrapped = new BufferedOutput(); - $output = new TaskOutput($wrapped); - - $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG); - $this->assertEquals(OutputInterface::VERBOSITY_DEBUG, $output->getVerbosity()); - - $this->assertFalse($output->isQuiet()); - $this->assertTrue($output->isVerbose()); - $this->assertTrue($output->isVeryVerbose()); - $this->assertTrue($output->isDebug()); - } - - /** - * Test decoration delegation. - */ - public function testDecorationDelegation(): void { - $wrapped = new BufferedOutput(); - $output = new TaskOutput($wrapped); - - $output->setDecorated(TRUE); - $this->assertTrue($output->isDecorated()); - - $output->setDecorated(FALSE); - $this->assertFalse($output->isDecorated()); - } - - /** - * Test formatter delegation. - */ - public function testFormatterDelegation(): void { - $wrapped = new BufferedOutput(); - $output = new TaskOutput($wrapped); - - $formatter = new OutputFormatter(); - $output->setFormatter($formatter); - - $this->assertSame($formatter, $output->getFormatter()); - } - -} diff --git a/.vortex/installer/tests/Unit/Task/TaskTest.php b/.vortex/installer/tests/Unit/Task/TaskTest.php index 93eb490bdd..06c12ca732 100644 --- a/.vortex/installer/tests/Unit/Task/TaskTest.php +++ b/.vortex/installer/tests/Unit/Task/TaskTest.php @@ -35,7 +35,7 @@ public function testAction( $expected_output = is_array($expected_output) ? $expected_output : [$expected_output]; foreach ($expected_output as $expected) { - $this->assertStringContainsString(Tui::normalizeText($expected), $actual); + $this->assertStringContainsString($expected, $actual); } } @@ -111,6 +111,43 @@ public static function dataProviderAction(): \Iterator { ]; } + public function testActionNestedInStreamingTask(): void { + $output = new BufferedOutput(); + Tui::init($output); + + $result = Task::action( + label: 'Outer task', + action: function (): bool { + Task::action( + label: 'Inner task', + action: fn(): array => ['detail 1'], + hint: 'Inner hint', + success: 'Inner done', + ); + Task::action( + label: 'Inner failing task', + action: fn(): bool => FALSE, + ); + + return TRUE; + }, + success: 'Outer done', + streaming: TRUE, + ); + + $actual = $output->fetch(); + + $this->assertTrue($result); + $this->assertFalse(Tui::isCaptured()); + $this->assertStringContainsString('Outer task', $actual); + $this->assertStringContainsString('Inner task', $actual); + $this->assertStringContainsString('Inner hint', $actual); + $this->assertStringContainsString('detail 1', $actual); + $this->assertStringContainsString('✓ Inner done', $actual); + $this->assertStringContainsString('✕ FAILED', $actual); + $this->assertStringContainsString('✓ Outer done', $actual); + } + public function testActionInvalidArgument(): void { $output = new BufferedOutput(); Tui::init($output); diff --git a/.vortex/installer/tests/Unit/Utils/TuiTest.php b/.vortex/installer/tests/Unit/Utils/TuiTest.php index ca9981a59b..c15181d99d 100644 --- a/.vortex/installer/tests/Unit/Utils/TuiTest.php +++ b/.vortex/installer/tests/Unit/Utils/TuiTest.php @@ -4,6 +4,7 @@ namespace DrevOps\VortexInstaller\Tests\Unit\Utils; +use AlexSkrypnyk\Prompty\Prompty; use DrevOps\VortexInstaller\Tests\Unit\UnitTestCase; use DrevOps\VortexInstaller\Utils\Strings; use DrevOps\VortexInstaller\Utils\Tui; @@ -19,9 +20,11 @@ public function testInit(): void { Tui::init($output); $this->assertSame($output, Tui::output()); + $this->assertTrue(Tui::isInteractive()); Tui::init($output, FALSE); $this->assertSame($output, Tui::output()); + $this->assertFalse(Tui::isInteractive()); } public function testOutputNotInitialized(): void { @@ -32,34 +35,24 @@ public function testOutputNotInitialized(): void { $this->assertSame($output, Tui::output()); } - public function testInfo(): void { + #[DataProvider('dataProviderMessages')] + public function testMessages(string $method, string $message, array $expected): void { $output = new BufferedOutput(); Tui::init($output); - Tui::info('Test info message'); + Tui::$method($message); $actual = $output->fetch(); - $this->assertStringContainsString('Test info message', $actual); + foreach ($expected as $expected_string) { + $this->assertStringContainsString($expected_string, $actual); + } } - public function testNote(): void { - $output = new BufferedOutput(); - Tui::init($output); - - Tui::note('Test note message'); - - $actual = $output->fetch(); - $this->assertStringContainsString('Test note message', $actual); - } - - public function testError(): void { - $output = new BufferedOutput(); - Tui::init($output); - - Tui::error('Test error message'); - - $actual = $output->fetch(); - $this->assertStringContainsString('✕ Test error message', $actual); + public static function dataProviderMessages(): \Iterator { + yield 'info' => ['info', 'Test info message', ['Test info message']]; + yield 'note' => ['note', "Line 1\nLine 2", ['Line 1', 'Line 2']]; + yield 'success' => ['success', 'Operation succeeded', ['✓', 'Operation succeeded']]; + yield 'error' => ['error', 'Test error message', ['✕', 'Test error message']]; } #[DataProvider('dataProviderColorMethods')] @@ -106,355 +99,30 @@ public static function dataProviderColorMethodsMultiline(): \Iterator { ]; } - public function testEscapeMultilineViaPublicMethod(): void { - // escapeMultiline() is protected, so green() exercises it. - $text = <<<'TEXT' -Line 1 -Line 2 -TEXT; - - $result = Tui::green($text); - // The escape sequence appears without the leading backslash in the - // actual output. - $this->assertStringContainsString('[32m', $result); - $this->assertStringContainsString('Line 1', $result); - $this->assertStringContainsString('Line 2', $result); - } - - public function testCaretMethods(): void { - $this->assertSame("\033[B", Tui::caretDown()); - $this->assertSame("\033[A", Tui::caretUp()); - } - - public function testCaretEol(): void { - $result = Tui::caretEol('Short'); - $this->assertSame("\033[5C", $result); - - $multiline = <<<'TEXT' -Short -Longer line -TEXT; - $result = Tui::caretEol($multiline); - $this->assertSame("\033[11C", $result); - } - public function testTerminalWidth(): void { - $width = Tui::terminalWidth(); - $this->assertGreaterThanOrEqual(20, $width); + Tui::init(new BufferedOutput()); + + $this->assertSame(min(100, max(20, Prompty::terminalWidth())), Tui::terminalWidth()); + $this->assertSame(min(10, max(20, Prompty::terminalWidth())), Tui::terminalWidth(10)); } #[DataProvider('dataProviderBox')] - public function testBox( - string $content, - ?string $title, - ?int $width, - ?int $terminal_width, - string $expected_output, - ): void { + public function testBox(string $content, ?string $title, array $expected): void { $output = new BufferedOutput(); Tui::init($output); - if ($terminal_width !== NULL) { - static::envSet('COLUMNS', (string) $terminal_width); - } + Tui::box($content, $title); - if ($width !== NULL) { - Tui::box($content, $title, $width); - } - else { - Tui::box($content, $title); + $actual = Strings::stripAnsiColors($output->fetch()); + foreach ($expected as $expected_string) { + $this->assertStringContainsString($expected_string, $actual); } - - $actual = $output->fetch(); - - $actual_clean = Strings::stripAnsiColors($actual); - $expected_clean = Strings::stripAnsiColors($expected_output); - - $this->assertSame($expected_clean, $actual_clean); } public static function dataProviderBox(): \Iterator { - yield 'simple content without title' => [ - 'content' => 'Simple content', - 'title' => NULL, - 'width' => 50, - 'terminal_width' => 100, - 'expected_output' => << [ - 'content' => 'Content with title', - 'title' => 'Box Title', - 'width' => 50, - 'terminal_width' => 100, - 'expected_output' => << [ - 'content' => '', - 'title' => 'Empty Content', - 'width' => 40, - 'terminal_width' => 100, - 'expected_output' => << [ - 'content' => 'Content with empty title', - 'title' => '', - 'width' => 40, - 'terminal_width' => 100, - 'expected_output' => << [ - 'content' => 'X', - 'title' => 'A', - 'width' => 25, - 'terminal_width' => 100, - 'expected_output' => << [ - 'content' => ' ', - 'title' => NULL, - 'width' => 30, - 'terminal_width' => 100, - 'expected_output' => << [ - 'content' => 'Terminal width test', - 'title' => 'Narrow Terminal', - 'width' => 100, - 'terminal_width' => 30, - 'expected_output' => << [ - 'content' => 'Default width content', - 'title' => 'Default Width', - 'width' => NULL, - 'terminal_width' => 50, - 'expected_output' => << [ - 'content' => 'This is a very long line of content that should definitely be wrapped when the box width is narrow', - 'title' => 'Long Content Test', - 'width' => 40, - 'terminal_width' => 100, - 'expected_output' => << [ - 'content' => 'Short line', - 'title' => 'This is a very long title that should be wrapped across multiple lines when the box width is constrained', - 'width' => 35, - 'terminal_width' => 100, - 'expected_output' => << [ - 'content' => "Multi\nLine\nContent\nHere", - 'title' => 'Multi-Line Test', - 'width' => 30, - 'terminal_width' => 100, - 'expected_output' => << [ - 'content' => 'This line has some words and should wrap nicely', - 'title' => NULL, - 'width' => 25, - 'terminal_width' => 100, - 'expected_output' => << [ - 'content' => 'OneVeryLongWordThatCannotBeWrappedNormally', - 'title' => 'Unbreakable', - 'width' => 20, - 'terminal_width' => 100, - 'expected_output' => << [ - 'content' => "Paragraph one with some text.\n\nParagraph two with more text after empty line.", - 'title' => 'Multi-Paragraph', - 'width' => 45, - 'terminal_width' => 100, - 'expected_output' => << [ - 'content' => 'Content with émojis 🌟 and special chars ñáéíóú that affect wrapping calculations', - 'title' => 'Special Chars', - 'width' => 35, - 'terminal_width' => 100, - 'expected_output' => << [ - 'content' => 'Short', - 'title' => 'Normal Title', - 'width' => 10, - 'terminal_width' => 100, - 'expected_output' => << ['Simple content', NULL, ['┌', '│ Simple content │', '┘']]; + yield 'content with title' => ['Content with title', 'Box Title', ['Box Title', 'Content with title']]; + yield 'multiline content' => ["Multi\nLine", 'Multi-Line Test', ['Multi-Line Test', '│ Multi ', '│ Line ']]; } #[DataProvider('dataProviderList')] @@ -491,108 +159,16 @@ public static function dataProviderList(): \Iterator { ]; } - #[DataProvider('dataProviderUtfPadding')] - public function testUtfPadding( - string $char, - ?string $terminal_emulator, - ?string $term_program, - string $expected_padding, - ): void { - if ($terminal_emulator !== NULL) { - static::envSet('TERMINAL_EMULATOR', $terminal_emulator); - } - else { - static::envUnset('TERMINAL_EMULATOR'); - } - - if ($term_program !== NULL) { - static::envSet('TERM_PROGRAM', $term_program); - } - else { - static::envUnset('TERM_PROGRAM'); - } - - $reflection = new \ReflectionClass(Tui::class); - $method = $reflection->getMethod('utfPadding'); + public function testTable(): void { + $output = new BufferedOutput(); + Tui::init($output); - $result = $method->invoke(NULL, $char); - $this->assertSame($expected_padding, $result); - } + Tui::table(['Name', 'Value'], [['key1', 'value1'], 'Section']); - public static function dataProviderUtfPadding(): \Iterator { - yield 'JetBrains with 1-byte UTF-8 char' => [ - // 2 bytes, 1 mb_strlen - 'char' => 'é', - 'terminal_emulator' => 'JetBrains-something', - 'term_program' => NULL, - 'expected_padding' => ' ', - ]; - yield 'JetBrains with 3-byte UTF-8 char' => [ - // 3 bytes, 1 mb_strlen - 'char' => 'あ', - 'terminal_emulator' => 'JetBrains-IDE', - 'term_program' => NULL, - 'expected_padding' => ' ', - ]; - yield 'JetBrains with 4-byte UTF-8 char' => [ - // 4 bytes, 1 mb_strlen - should NOT get padding (len >= 4) - 'char' => '🌟', - 'terminal_emulator' => 'JetBrains-IDE', - 'term_program' => NULL, - 'expected_padding' => '', - ]; - yield 'Non-JetBrains terminal' => [ - 'char' => 'é', - 'terminal_emulator' => 'other-terminal', - 'term_program' => NULL, - 'expected_padding' => '', - ]; - yield 'Apple Terminal with multi-byte char under 8 bytes' => [ - // 2 chars × 3 bytes = 6 bytes total, mblen=2, len=6 < 8 - 'char' => 'あい', - 'terminal_emulator' => NULL, - 'term_program' => 'Apple_Terminal', - 'expected_padding' => ' ', - ]; - yield 'Apple Terminal with long multi-byte string' => [ - // 5 chars × 3 bytes = 15 bytes, mblen=5, len=15 >= 8 - 'char' => 'あいうえお', - 'terminal_emulator' => NULL, - 'term_program' => 'Apple_Terminal', - 'expected_padding' => '', - ]; - yield 'Apple Terminal with single-byte char' => [ - // Single byte, single mb_strlen. - 'char' => 'A', - 'terminal_emulator' => NULL, - 'term_program' => 'Apple_Terminal', - 'expected_padding' => '', - ]; - yield 'No special terminal with UTF-8' => [ - 'char' => '🌟', - 'terminal_emulator' => NULL, - 'term_program' => NULL, - 'expected_padding' => '', - ]; - yield 'Regular ASCII character' => [ - 'char' => 'A', - 'terminal_emulator' => NULL, - 'term_program' => NULL, - 'expected_padding' => '', - ]; - yield 'Both JetBrains and Apple set' => [ - 'char' => 'é', - 'terminal_emulator' => 'JetBrains-IDE', - 'term_program' => 'Apple_Terminal', - // JetBrains condition should trigger first. - 'expected_padding' => ' ', - ]; - yield 'Empty environment values' => [ - 'char' => 'é', - 'terminal_emulator' => '', - 'term_program' => '', - 'expected_padding' => '', - ]; + $actual = $output->fetch(); + $this->assertStringContainsString('Name', $actual); + $this->assertStringContainsString('key1', $actual); + $this->assertStringContainsString('Section', $actual); } #[DataProvider('dataProviderCenter')] @@ -743,52 +319,6 @@ public static function dataProviderCenter(): \Iterator { ]; } - #[DataProvider('dataProviderNormalizeText')] - public function testNormalizeText(string $input, string $expected): void { - $result = Tui::normalizeText($input); - $this->assertEquals($expected, $result); - } - - public static function dataProviderNormalizeText(): \Iterator { - yield 'multiple spaces' => [ - 'input' => 'Hello world', - 'expected' => 'Hello world', - ]; - yield 'multiple types of whitespace' => [ - 'input' => "Hello\t\t \n world", - 'expected' => 'Hello world', - ]; - yield 'leading and trailing spaces with multiple interior spaces' => [ - 'input' => ' Hello world ', - 'expected' => ' Hello world ', - ]; - // Test non-ASCII text gets whitespace normalized + UTF padding. - yield 'text starting with non-ASCII character' => [ - 'input' => 'éHello world', - 'expected' => 'éHello world', - ]; - yield 'simple ASCII text' => [ - 'input' => 'Hello world', - 'expected' => 'Hello world', - ]; - yield 'ASCII text with UTF-8 characters' => [ - 'input' => 'Hello 🌟 world', - 'expected' => 'Hello 🌟 world', - ]; - yield 'empty string' => [ - 'input' => '', - 'expected' => '', - ]; - yield 'single space' => [ - 'input' => ' ', - 'expected' => ' ', - ]; - yield 'only multiple spaces' => [ - 'input' => ' ', - 'expected' => ' ', - ]; - } - public function testSetOutput(): void { $output1 = new BufferedOutput(); $output2 = new BufferedOutput(); @@ -798,16 +328,11 @@ public function testSetOutput(): void { Tui::setOutput($output2); $this->assertSame($output2, Tui::output()); - } - - public function testSuccess(): void { - $output = new BufferedOutput(); - Tui::init($output); - - Tui::success('Operation succeeded'); - $actual = $output->fetch(); - $this->assertStringContainsString('Operation succeeded', $actual); + // Prompty keeps drawing to the output passed to init(). + Tui::info('Drawn by Prompty'); + $this->assertStringContainsString('Drawn by Prompty', $output1->fetch()); + $this->assertSame('', $output2->fetch()); } public function testLine(): void { @@ -841,12 +366,48 @@ public function testConfirmNonInteractive(): void { $this->assertFalse($result); } - public function testGetCharNonInteractive(): void { + public function testCapturedWritesPlainLines(): void { + $output = new BufferedOutput(); + Tui::init($output); + + Tui::capture(TRUE); + $this->assertTrue(Tui::isCaptured()); + + // A command run while captured keeps Prompty drawing to the first output. + $nested = new BufferedOutput(); + Tui::init($nested); + + Tui::info('Info line'); + Tui::success('Success line'); + Tui::error('Error line'); + Tui::note('Note line'); + Tui::box('Box content', 'Box title'); + Tui::table(['Name', 'Value'], [['key1', 'value1'], 'Section']); + + Tui::capture(FALSE); + $this->assertFalse(Tui::isCaptured()); + + $this->assertSame(implode(PHP_EOL, [ + 'Info line', + '✓ Success line', + '✕ Error line', + 'Note line', + 'Box title', + 'Box content', + 'Name: Value', + 'key1: value1', + 'Section', + ]) . PHP_EOL, $nested->fetch()); + $this->assertSame('', $output->fetch()); + } + + public function testPauseNonInteractive(): void { $output = new BufferedOutput(); Tui::init($output, FALSE); - $result = Tui::getChar(); - $this->assertEquals('', $result); + Tui::pause('Press any key to continue...'); + + $this->assertStringNotContainsString('Press any key to continue...', $output->fetch()); } }