Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,21 @@ DRUPAL_THEME=your_site_theme
# Drupal maintenance theme name.
DRUPAL_MAINTENANCE_THEME=your_site_theme


Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Consider removing the extra blank line.

Static analysis detected an extra blank line at line 64. While not functionally problematic, removing it would improve consistency with the rest of the file.

Apply this diff:

 DRUPAL_MAINTENANCE_THEME=your_site_theme
-
 #;< MODULE_STAGE_FILE_PROXY
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
DRUPAL_MAINTENANCE_THEME=your_site_theme
#;< MODULE_STAGE_FILE_PROXY
🧰 Tools
🪛 dotenv-linter (4.0.0)

[warning] 64-64: [ExtraBlankLine] Extra blank line detected

(ExtraBlankLine)

🤖 Prompt for AI Agents
In .env around line 64, there is an extra blank line that breaks visual
consistency; remove the empty line so there is no blank line at line 64,
ensuring the file has contiguous entries and matches the surrounding formatting.

#;< MODULE_STAGE_FILE_PROXY
# Stage file proxy origin.
#;< MODULE_SHIELD
#
# If using Shield, the HTTP authentication credentials will be automatically
# added to the origin URL.
#;> MODULE_SHIELD
DRUPAL_STAGE_FILE_PROXY_ORIGIN=https://www.your-site-domain.example
#;> MODULE_STAGE_FILE_PROXY

#;< MODULE_SHIELD
# Shield message.
DRUPAL_SHIELD_PRINT="Restricted access."
#;> MODULE_SHIELD

#;< SERVICE_REDIS
# Enable Redis integration.
Expand Down
342 changes: 166 additions & 176 deletions .vortex/docs/static/img/installer.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion .vortex/docs/static/img/installer.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions .vortex/installer/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
},
"require": {
"php": ">=8.3",
"alexskrypnyk/file": "^0.13.1",
"alexskrypnyk/file": "^0.14",
"alexskrypnyk/str2name": "^1.4",
"composer/composer": "^2.9.1",
"cweagans/composer-patches": "^2",
Expand Down Expand Up @@ -88,10 +88,10 @@
"lint": [
"phpcs",
"phpstan",
"rector --clear-cache --dry-run"
"rector --dry-run"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

Verify removal of --clear-cache flags from Rector commands.

The --clear-cache flag has been removed from both the lint and lint-fix scripts for Rector. Ensure this change is intentional and that Rector's caching behavior in the current version (^2.2.8) doesn't require explicit cache clearing for consistent results.

Run the following to verify Rector behavior without the flag:

Also applies to: 94-94


🏁 Script executed:

#!/bin/bash
# Description: Test Rector lint commands to ensure they work correctly without --clear-cache

# Check if rector runs successfully without --clear-cache
cd .vortex/installer
composer install --quiet

echo "=== Testing rector --dry-run (lint) ==="
./vendor/bin/rector --dry-run || echo "Rector dry-run failed"

echo ""
echo "=== Check Rector documentation for caching behavior ==="
./vendor/bin/rector --help | grep -i cache

Length of output: 341


🏁 Script executed:

#!/bin/bash
# Examine the composer.json file to see the rector version and changes

echo "=== Checking rector version in composer.json ==="
cat .vortex/installer/composer.json | grep -A 2 -B 2 '"rector'

echo ""
echo "=== Viewing lines 85-100 to see the lint scripts ==="
sed -n '85,100p' .vortex/installer/composer.json

echo ""
echo "=== Full composer.json for context ==="
cat .vortex/installer/composer.json

Length of output: 4320


🌐 Web query:

Rector 2.2.8 caching behavior --clear-cache flag required

💡 Result:

Short answer: Yes — Rector caches processed files, so to force a full re-run (e.g., after changing rules/config or when files were previously skipped) you must clear the cache (use --clear-cache). Many docs and reports recommend always running with --clear-cache when changing rules or running on a full codebase; Rector’s behaviour also includes kaizen/cache rules that enforce clearing when files or rules change. [1][2][3]

Sources:

  • Rector release notes / changelog (mentions kaizen / cache behaviour). [1]
  • Neos/rector docs (explicit recommendation: run with --clear-cache after adjusting rules). [2]
  • Community answers / examples showing vendor/bin/rector process --clear-cache usage (StackOverflow / blog posts). [3]

Restore --clear-cache flags to Rector commands for consistent linting results.

Rector caches processed files and recommends using --clear-cache to force a full re-run, especially when changing rules or running on a full codebase. Removing this flag from both lint scripts (lines 91 and 94) risks inconsistent or stale cache-based results.

Restore --clear-cache to:

  • Line 91: "rector --clear-cache --dry-run"
  • Line 94: "rector --clear-cache"

Also applies to: 94-94

🤖 Prompt for AI Agents
.vortex/installer/composer.json around lines 91 and 94: the Rector commands
removed the --clear-cache flag causing potential stale cache results; restore
the flag by changing the entry at line 91 to include --clear-cache --dry-run and
the entry at line 94 to include --clear-cache so Rector always clears its cache
before running.

],
"lint-fix": [
"rector --clear-cache",
"rector",
"phpcbf"
],
"reset": "rm -Rf vendor vendor-bin",
Expand Down
14 changes: 8 additions & 6 deletions .vortex/installer/composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .vortex/installer/src/Prompts/Handlers/ModulePrefix.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class ModulePrefix extends AbstractHandler {
* {@inheritdoc}
*/
public function label(): string {
return 'Module prefix';
return 'Custom modules prefix';
}

/**
Expand Down
178 changes: 178 additions & 0 deletions .vortex/installer/src/Prompts/Handlers/Modules.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
<?php

declare(strict_types=1);

namespace DrevOps\VortexInstaller\Prompts\Handlers;

use DrevOps\VortexInstaller\Utils\File;
use DrevOps\VortexInstaller\Utils\JsonManipulator;

class Modules extends AbstractHandler {

/**
* {@inheritdoc}
*/
public function label(): string {
return 'Modules';
}

/**
* {@inheritdoc}
*/
public function hint(array $responses): ?string {
return 'Use ⬆, ⬇ and Space bar to select one or more modules.';
}

/**
* {@inheritdoc}
*/
public function options(array $responses): ?array {
return static::getAvailableModules();
}

/**
* {@inheritdoc}
*/
public function default(array $responses): null|string|bool|array {
// Default to all modules selected (meaning none will be removed).
return array_keys(static::getAvailableModules());
}

/**
* {@inheritdoc}
*/
public function discover(): null|string|bool|array {
if (!$this->isInstalled()) {
return NULL;
}

$composer_file = $this->dstDir . '/composer.json';
$discovered_modules = $this->getModulesFromComposerFile($composer_file);

if ($discovered_modules === NULL) {
return NULL;
}

// Filter discovered modules to only include those in our available list.
$available_modules = array_keys(static::getAvailableModules());
$modules = array_intersect($discovered_modules, $available_modules);

sort($modules);

return $modules;
}

/**
* {@inheritdoc}
*/
public function process(): void {
$selected_modules = $this->getResponseAsArray();
$all_modules = static::getAvailableModules();

$t = $this->tmpDir;
$w = $this->webroot;

// Process each module that was NOT selected (remove them).
foreach (array_keys($all_modules) as $module_name) {
if (!in_array($module_name, $selected_modules)) {
// Remove from composer.json.
$pattern = '/\s*"drupal\/' . preg_quote($module_name, '/') . '":\s*"[^\"]+",?\n/';
File::replaceContentInFile($t . '/composer.json', $pattern, "\n");

Comment on lines +75 to +81

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Make composer.json removal regex resilient to CRLF line endings (optional)

The pattern:

$pattern = '/\s*"drupal\/' . preg_quote($module_name, '/') . '":\s*"[^\"]+",?\n/';

assumes \n line endings and may fail to match lines ending with \r\n. To make this more robust across platforms without changing behavior on LF files, consider allowing an optional \r:

-        $pattern = '/\s*"drupal\/' . preg_quote($module_name, '/') . '":\s*"[^\"]+",?\n/';
+        $pattern = '/\s*"drupal\/' . preg_quote($module_name, '/') . '":\s*"[^\"]+",?(\r?\n)/';

and keep the replacement consistent (e.g., "\n" or "$1" depending on how you want to normalize line endings).

🤖 Prompt for AI Agents
.vortex/installer/src/Prompts/Handlers/Modules.php around lines 75 to 81: the
regex used to remove module lines from composer.json assumes LF-only line
endings and will miss CRLF lines; update the pattern to accept an optional
carriage return (use \r?\n) so it matches both "\n" and "\r\n", and ensure the
replacement uses the desired normalized newline (e.g., "\n") so file line
endings remain consistent after removal.

// Remove module from settings file.
File::remove($t . '/' . $w . '/sites/default/includes/modules/settings.' . $module_name . '.php');

// Remove module from the provision example file.
File::replaceContentCallbackInFile($t . '/scripts/custom/provision-10-example.sh', function (string $content) use ($module_name): string {
$pattern = '/^(\s*)(drush\s+pm:install.*\b' . preg_quote($module_name, '/') . '\b.*)$/m';
$content = preg_replace_callback($pattern, function (array $matches) use ($module_name): string {
$indent = $matches[1];
$line = $matches[2];
$line = preg_replace('/\s+\b' . preg_quote($module_name, '/') . '\b/', '', $line);
$line = preg_replace('/\s{2,}/', ' ', $line) ?? $line;
return $indent . $line;
}, $content);
return $content ?? '';
});

// Remove module from the Behat tests.
File::remove($t . '/tests/behat/features/' . $module_name . '.feature');

// Remove module from the config tests.
$pattern = '/\s*\$config\[\'' . preg_quote($module_name, '/') . '\..*;(\r?\n)?/';
File::removeLine($t . '/tests/phpunit/Drupal/EnvironmentSettingsTest.php', $pattern);

// Remove module tokens.
File::removeTokenAsync('MODULE_' . strtoupper($module_name));
}
}

if (count($selected_modules) === 0) {
File::removeTokenAsync('MODULE');
}
}

/**
* Get the full list of available Drupal contributed modules.
*
* This list excludes Drupal core modules and service modules.
*
* @return array<string, string>
* Array of module machine names as keys and labels as values.
*/
public static function getAvailableModules(): array {
return [
'admin_toolbar' => 'Admin toolbar',
'coffee' => 'Coffee',
'config_split' => 'Config split',
'config_update' => 'Config update',
'environment_indicator' => 'Environment indicator',
'pathauto' => 'Pathauto',
'redirect' => 'Redirect',
'robotstxt' => 'Robots.txt',
'seckit' => 'Seckit',
'shield' => 'Shield',
'stage_file_proxy' => 'Stage file proxy',
];
}

/**
* Extract Drupal contributed module names from a composer.json file.
*
* @param string $composer_file
* Path to the composer.json file.
*
* @return array|null
* Array of module machine names (without drupal/ prefix), or NULL on error.
*/
protected function getModulesFromComposerFile(string $composer_file): ?array {
if (!file_exists($composer_file)) {
return NULL;
}

$cj = JsonManipulator::fromFile($composer_file);

if (!$cj instanceof JsonManipulator) {
return NULL;
}

$require = $cj->getProperty('require');

if (!is_array($require)) {
return NULL;
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

$modules = [];
foreach (array_keys($require) as $package) {
// Only include drupal/* packages, excluding core packages.
if (str_starts_with((string) $package, 'drupal/') && !str_starts_with((string) $package, 'drupal/core-')) {
// Extract module name (remove drupal/ prefix).
$module_name = substr((string) $package, 7);
$modules[] = $module_name;
}
}

return $modules;
}

}
8 changes: 6 additions & 2 deletions .vortex/installer/src/Prompts/PromptManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
use DrevOps\VortexInstaller\Prompts\Handlers\LabelMergeConflictsPr;
use DrevOps\VortexInstaller\Prompts\Handlers\MachineName;
use DrevOps\VortexInstaller\Prompts\Handlers\ModulePrefix;
use DrevOps\VortexInstaller\Prompts\Handlers\Modules;
use DrevOps\VortexInstaller\Prompts\Handlers\Name;
use DrevOps\VortexInstaller\Prompts\Handlers\NotificationChannels;
use DrevOps\VortexInstaller\Prompts\Handlers\Org;
Expand Down Expand Up @@ -64,7 +65,7 @@ class PromptManager {
*
* Used to display the progress of the prompts.
*/
const TOTAL_RESPONSES = 27;
const TOTAL_RESPONSES = 28;

/**
* Array of responses.
Expand Down Expand Up @@ -135,6 +136,7 @@ public function runPrompts(): void {
fn($r, $pr, $n): string => text(...$this->args(ProfileCustom::class)),
ProfileCustom::id()
)
->add(fn(array $r, $pr, $n): array => multiselect(...$this->args(Modules::class, NULL, $r)), Modules::id())
->add(fn(array $r, $pr, $n): string => text(...$this->args(ModulePrefix::class, NULL, $r)), ModulePrefix::id())
->add(
fn(array $r, $pr, $n): string => $this->resolveOrPrompt(Theme::id(), $r, fn(): int|string => select(...$this->args(Theme::class))),
Expand Down Expand Up @@ -277,6 +279,7 @@ public function runProcessors(): void {
Services::id(),
Timezone::id(),
CodeProvider::id(),
Modules::id(),
Starter::id(),
ProfileCustom::id(),
Profile::id(),
Expand Down Expand Up @@ -368,6 +371,7 @@ public function getResponsesSummary(): array {

$values['Drupal'] = Tui::LIST_SECTION_TITLE;
$values['Starter'] = $responses[Starter::id()];
$values['Modules'] = Converter::toList($responses[Modules::id()], ', ');
$values['Webroot'] = $responses[Webroot::id()];
$values['Profile'] = $responses[Profile::id()];
$values['Module prefix'] = $responses[ModulePrefix::id()];
Expand Down Expand Up @@ -543,7 +547,7 @@ private function args(string $handler_class, mixed $default_override = NULL, arr
}

$options = $handler->options($responses);
if (is_array($options) && $options !== []) {
if (is_array($options)) {
$args['options'] = $options;
$args['scroll'] = 10;
}
Expand Down
10 changes: 9 additions & 1 deletion .vortex/installer/src/Utils/JsonManipulator.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,15 @@ public static function fromFile(string $composer_json): ?self {
// @codeCoverageIgnoreEnd
}

return new self($contents);
try {
$instance = new self($contents);
}
catch (\Exception) {
// Invalid JSON.
return NULL;
}
Comment thread
AlexSkrypnyk marked this conversation as resolved.

return $instance;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,9 @@ note "Environment: ${environment}"
if echo "${environment}" | grep -q -e dev -e stage -e ci -e local; then
note "Running example operations in non-production environment."

# Set site name.
task "Setting site name."
drush php:eval "\Drupal::service('config.factory')->getEditable('system.site')->set('name', 'star wars')->save();"

# Enable contrib modules.
task "Installing contrib modules."
drush pm:install admin_toolbar coffee config_split config_update media environment_indicator pathauto redirect robotstxt shield stage_file_proxy

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
@@ -7,7 +7,6 @@
"php": "__VERSION__",
"composer/installers": "__VERSION__",
"cweagans/composer-patches": "__VERSION__",
- "drupal/admin_toolbar": "__VERSION__",
"drupal/clamav": "__VERSION__",
"drupal/coffee": "__VERSION__",
"drupal/config_split": "__VERSION__",
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
@@ -38,7 +38,7 @@
drush php:eval "\Drupal::service('config.factory')->getEditable('system.site')->set('name', 'star wars')->save();"

task "Installing contrib modules."
- drush pm:install admin_toolbar coffee config_split config_update media environment_indicator pathauto redirect robotstxt shield stage_file_proxy
+ drush pm:install coffee config_split config_update media environment_indicator pathauto redirect robotstxt shield stage_file_proxy

task "Installing Redis module."
drush pm:install redis || true
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
@@ -9,7 +9,6 @@
"cweagans/composer-patches": "__VERSION__",
"drupal/admin_toolbar": "__VERSION__",
"drupal/clamav": "__VERSION__",
- "drupal/coffee": "__VERSION__",
"drupal/config_split": "__VERSION__",
"drupal/config_update": "__VERSION__",
"drupal/core-composer-scaffold": "__VERSION__",
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
@@ -38,7 +38,7 @@
drush php:eval "\Drupal::service('config.factory')->getEditable('system.site')->set('name', 'star wars')->save();"

task "Installing contrib modules."
- drush pm:install admin_toolbar coffee config_split config_update media environment_indicator pathauto redirect robotstxt shield stage_file_proxy
+ drush pm:install admin_toolbar config_split config_update media environment_indicator pathauto redirect robotstxt shield stage_file_proxy

task "Installing Redis module."
drush pm:install redis || true
Loading