Skip to content

Fixed '--config' flag ignored and multiselect crash in '--no-interaction' mode.#2435

Open
AlexSkrypnyk wants to merge 3 commits intomainfrom
feature/config-no-interaction
Open

Fixed '--config' flag ignored and multiselect crash in '--no-interaction' mode.#2435
AlexSkrypnyk wants to merge 3 commits intomainfrom
feature/config-no-interaction

Conversation

@AlexSkrypnyk
Copy link
Copy Markdown
Member

@AlexSkrypnyk AlexSkrypnyk commented Mar 28, 2026

Summary

Fixed two bugs that prevented --config flag values from being applied during --no-interaction installs. Config keys stored by handlers use a short ID (e.g. MODULES) but PromptManager was only looking them up by the full env var name (e.g. VORTEX_INSTALLER_PROMPT_MODULES), so config values were silently ignored. Additionally, multiselect prompts crashed when receiving a single string value (from an env var or config) because the prompt library expected an array.

The fix adds a normalizeValue() method to HandlerInterface and AbstractHandler that converts comma-separated strings to arrays for MultiSelect handlers, and updates PromptManager to check both the full env var name and the short handler ID when reading from config.

Changes

HandlerInterface.php

Added normalizeValue(mixed $value): mixed to the interface. Documents that the method is called on values from config, env vars, and discovery before they are used as prompt defaults.

AbstractHandler.php

Implemented normalizeValue(): when the handler type is MultiSelect and the incoming value is a string, it delegates to Converter::fromList() to split a comma-separated string into an array. All other handlers and non-string values pass through unchanged.

PromptManager.php

Fixed the config key lookup to fall back to strtoupper($handler::id()) when the full env var name returns null. Applied $handler->normalizeValue() to the resolved default before passing it to the prompt arguments.

AbstractHandlerNormalizeValueTest.php

New unit test covering normalizeValue() across MultiSelect handlers (Modules, Services, DeployTypes, NotificationChannels) and a Text handler (Name), including comma-separated strings, single strings, arrays, and empty strings.

Before / After

Bug 1: Config key mismatch

BEFORE
──────
--config='{"modules":["admin_toolbar"]}'
              │
              ▼
   ┌─────────────────────┐
   │  Config::fromString  │
   │  strtoupper(key)     │
   └──────────┬──────────┘
              │
     stores as "MODULES"
              │
              ▼
   ┌─────────────────────────┐
   │  PromptManager::args()  │
   │                         │
   │  looks up key:          │
   │  "VORTEX_INSTALLER_     │
   │   PROMPT_MODULES"       │
   └──────────┬──────────────┘
              │
        ✗ NO MATCH
              │
              ▼
   ┌──────────────────────┐
   │  Falls back to       │
   │  handler default()   │
   │  (all modules)       │◄── User's config IGNORED
   └──────────────────────┘


AFTER
─────
--config='{"modules":["admin_toolbar"]}'
              │
              ▼
   ┌─────────────────────┐
   │  Config::fromString  │
   │  strtoupper(key)     │
   └──────────┬──────────┘
              │
     stores as "MODULES"
              │
              ▼
   ┌─────────────────────────┐
   │  PromptManager::args()  │
   │                         │
   │  1. looks up:           │
   │     "VORTEX_INSTALLER_  │
   │      PROMPT_MODULES"    │
   │          ✗ miss         │
   │                         │
   │  2. falls back to:      │
   │     "MODULES"           │
   │          ✓ MATCH        │
   └──────────┬──────────────┘
              │
              ▼
   ┌──────────────────────┐
   │  Uses config value:  │
   │  ["admin_toolbar"]   │◄── User's config APPLIED
   └──────────────────────┘

Bug 2: Multiselect string crash

BEFORE
──────
VORTEX_INSTALLER_PROMPT_MODULES="admin_toolbar"
              │
              ▼
   ┌─────────────────────┐
   │  Env::toValue()     │
   │  No comma found     │
   │  Returns string     │
   └──────────┬──────────┘
              │
      "admin_toolbar" (string)
              │
              ▼
   ┌─────────────────────────┐
   │  PromptManager::args()  │
   │  $args['default'] =     │
   │    "admin_toolbar"      │
   └──────────┬──────────────┘
              │
              ▼
   ┌──────────────────────────┐
   │  multiselect(            │
   │    default: string       │◄── EXPECTS array
   │  )                       │
   │                          │
   │  ✗ TypeError: Argument   │
   │    must be array, string │
   │    given                 │
   └──────────────────────────┘


AFTER
─────
VORTEX_INSTALLER_PROMPT_MODULES="admin_toolbar"
              │
              ▼
   ┌─────────────────────┐
   │  Env::toValue()     │
   │  No comma found     │
   │  Returns string     │
   └──────────┬──────────┘
              │
      "admin_toolbar" (string)
              │
              ▼
   ┌─────────────────────────────┐
   │  PromptManager::args()      │
   │                             │
   │  $handler->normalizeValue() │
   │                             │
   │  Handler type: MultiSelect  │
   │  Value is string            │
   │  → Converter::fromList()    │
   │  → ["admin_toolbar"]        │
   └──────────┬──────────────────┘
              │
              ▼
   ┌──────────────────────────┐
   │  multiselect(            │
   │    default: array ✓      │
   │  )                       │
   │                          │
   │  ✓ Works correctly       │
   └──────────────────────────┘

normalizeValue() dispatch

   ┌──────────────────────────────────┐
   │  Value arrives from any source:  │
   │  config, env var, or discover    │
   └──────────────┬───────────────────┘
                  │
                  ▼
   ┌──────────────────────────────────┐
   │  $handler->normalizeValue()     │
   ├─────────────────────────────────┤
   │                                  │
   │  Handler type?                   │
   │  ┌────────────┐ ┌─────────────┐ │
   │  │ MultiSelect│ │ Text/Select/│ │
   │  │            │ │ Confirm/    │ │
   │  │ is_string? │ │ Suggest     │ │
   │  │ ┌───┐┌──┐ │ │             │ │
   │  │ │yes││no│ │ │ return as-is│ │
   │  │ └─┬─┘└┬─┘ │ └─────────────┘ │
   │  │   │   │   │                  │
   │  │   ▼   ▼   │                  │
   │  │ split  │   │                  │
   │  │ on ,   │   │                  │
   │  │ →array │   │                  │
   │  │   │  pass  │                  │
   │  │   │  thru  │                  │
   │  └───┴───┴────┘                  │
   └──────────────────────────────────┘

Summary by CodeRabbit

Release Notes

  • New Features

    • Added value normalization for prompt handlers, enabling comma-separated strings to be automatically converted to arrays for multi-select options.
    • Configuration and environment variable defaults are now normalized before use as prompt defaults.
  • Chores

    • Improved environment variable naming with consistent prefixing for prompt-related configuration settings.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 28, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: f6b3e450-ea32-415a-9f42-c3d26c3b4050

📥 Commits

Reviewing files that changed from the base of the PR and between 5999fd3 and 6b03d39.

📒 Files selected for processing (11)
  • .vortex/installer/src/Prompts/Handlers/AbstractHandler.php
  • .vortex/installer/src/Prompts/Handlers/CustomModules.php
  • .vortex/installer/src/Prompts/Handlers/DeployTypes.php
  • .vortex/installer/src/Prompts/Handlers/Modules.php
  • .vortex/installer/src/Prompts/Handlers/NotificationChannels.php
  • .vortex/installer/src/Prompts/Handlers/Services.php
  • .vortex/installer/src/Prompts/Handlers/Tools.php
  • .vortex/installer/src/Prompts/PromptManager.php
  • .vortex/installer/src/Utils/Config.php
  • .vortex/installer/tests/Unit/ConfigTest.php
  • .vortex/installer/tests/Unit/Handlers/AbstractHandlerNormalizeValueTest.php

Walkthrough

Added a normalizeValue(mixed $value): mixed hook to the handler API and implementations; PromptManager now applies handler normalization to config/env-derived defaults. Config key normalization/prefixing was adjusted and unit tests added for handler normalization behavior.

Changes

Cohort / File(s) Summary
Handler Interface & Base
.vortex/installer/src/Prompts/Handlers/HandlerInterface.php, .vortex/installer/src/Prompts/Handlers/AbstractHandler.php
Added public function normalizeValue(mixed $value): mixed to the interface and a default implementation in AbstractHandler.
Multi-value Handlers
.vortex/installer/src/Prompts/Handlers/Modules.php, .vortex/installer/src/Prompts/Handlers/Services.php, .vortex/installer/src/Prompts/Handlers/Tools.php, .vortex/installer/src/Prompts/Handlers/CustomModules.php, .vortex/installer/src/Prompts/Handlers/DeployTypes.php, .vortex/installer/src/Prompts/Handlers/NotificationChannels.php
Each handler now overrides normalizeValue(...), converting string inputs via Converter::fromList($value) and returning non-strings unchanged (normalization hook for multi-select/list-style prompts).
Prompt Default Resolution
.vortex/installer/src/Prompts/PromptManager.php
PromptManager::args() now calls $handler->normalizeValue(...) for config/env-derived defaults before using them; preserves existing precedence and empty-string suppression behavior.
Config key normalization
.vortex/installer/src/Utils/Config.php
Config::fromString() now uppercases/normalizes keys and ensures prompt-related keys are prefixed with VORTEX_INSTALLER_PROMPT_ when not already fully qualified.
Tests
.vortex/installer/tests/Unit/Handlers/AbstractHandlerNormalizeValueTest.php, .vortex/installer/tests/Unit/ConfigTest.php
Added unit tests verifying handler normalization scenarios (comma-separated strings → arrays, empty string → empty array, passthrough for text handlers) and updated config parsing tests to expect prefixed environment-variable style keys.

Sequence Diagram

sequenceDiagram
    participant User
    participant PromptManager as "PromptManager"
    participant Handler as "Handler (Abstract/Concrete)"
    participant Converter as "Converter"
    participant Config as "Config/Env"

    User->>PromptManager: call args()
    PromptManager->>Config: resolve config/env for handler var
    alt env/config null
        PromptManager->>Config: try strtoupper(handler::id()) fallback
    end
    PromptManager->>Handler: supply raw default
    PromptManager->>Handler: call normalizeValue(raw_default)
    alt string list input
        Handler->>Converter: fromList(string_value)
        Converter-->>Handler: array
        Handler-->>PromptManager: normalized array
    else non-string or passthrough
        Handler-->>PromptManager: return value unchanged
    end
    PromptManager->>PromptManager: apply normalized default to prompt args
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

AUTOMERGE

Poem

🐰 I nibble commas into tidy rows and stacks,
turn tangled lists to neat little packs,
Text stays cozy, arrays hop through the door,
prompts get sorted — tidier than before,
A rabbit’s small touch, bouncing defaults galore.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the two main bugs fixed: '--config' flag being ignored and multiselect crashes in '--no-interaction' mode, which directly match the core changes in the changeset.
Docstring Coverage ✅ Passed Docstring coverage is 85.71% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/config-no-interaction

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.vortex/installer/src/Prompts/PromptManager.php:
- Around line 676-679: The current check prevents normalizeValue() from running
for empty-string defaults, so multiselect `''` never becomes `[]`; in
PromptManager.php call `$handler->normalizeValue($default)` before filtering out
`''` (i.e., if `$default` is not null, normalize it first, then only set
`$args['default']` when the normalized value is not an empty string) so
multiselect empty defaults are converted to an empty array and propagated.

In @.vortex/installer/tests/Unit/Handlers/AbstractHandlerNormalizeValueTest.php:
- Around line 25-57: Add a regression test that exercises the full PromptManager
resolution flow — specifically call PromptManager::args(...) to trigger the
fallback-to-short-key logic and ensure PromptManager calls
handler->normalizeValue(...) before assigning prompt defaults (covering the
behavior fixed at the args() fallback + normalization steps). In practice,
create a new test method that constructs Config::fromString('{}') and
PromptManager, invokes $prompt_manager->args(...) with an input that only
matches the handler via its short key (and with values needing normalization,
e.g., comma-separated string for Modules::id() or Services::id()), and assert
the returned args contain the normalized array values (not raw strings) and
correct defaults; reference PromptManager::args, handler->normalizeValue, and a
handler id like Modules::id() or Services::id() to locate the code to exercise.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 82c9d16e-5875-468f-8659-6cc2c42072d8

📥 Commits

Reviewing files that changed from the base of the PR and between 39ef060 and 788520c.

📒 Files selected for processing (4)
  • .vortex/installer/src/Prompts/Handlers/AbstractHandler.php
  • .vortex/installer/src/Prompts/Handlers/HandlerInterface.php
  • .vortex/installer/src/Prompts/PromptManager.php
  • .vortex/installer/tests/Unit/Handlers/AbstractHandlerNormalizeValueTest.php

Comment on lines +25 to +57
#[DataProvider('dataProviderNormalizeValue')]
public function testNormalizeValue(string $handler_id, mixed $input, mixed $expected): void {
$config = Config::fromString('{}');
$prompt_manager = new PromptManager($config);
$handlers = $prompt_manager->getHandlers();

$this->assertArrayHasKey($handler_id, $handlers);

$handler = $handlers[$handler_id];
$this->assertSame($expected, $handler->normalizeValue($input));
}

public static function dataProviderNormalizeValue(): \Iterator {
// MultiSelect: comma-separated string converted to array.
yield 'modules - comma string' => [Modules::id(), 'admin_toolbar,coffee', ['admin_toolbar', 'coffee']];
// MultiSelect: single string converted to single-element array.
yield 'modules - single string' => [Modules::id(), 'admin_toolbar', ['admin_toolbar']];
// MultiSelect: array passed through unchanged.
yield 'modules - array' => [Modules::id(), ['admin_toolbar', 'coffee'], ['admin_toolbar', 'coffee']];
// MultiSelect: empty string converted to empty array.
yield 'modules - empty string' => [Modules::id(), '', []];

// Other multiselect handlers.
yield 'services - single string' => [Services::id(), 'redis', ['redis']];
yield 'services - comma string' => [Services::id(), 'redis,solr', ['redis', 'solr']];
yield 'deploy_types - single string' => [DeployTypes::id(), 'lagoon', ['lagoon']];
yield 'notification_channels - single string' => [NotificationChannels::id(), 'email', ['email']];

// Text handler: string passed through unchanged.
yield 'name - string passthrough' => [Name::id(), 'My Project', 'My Project'];
// Text handler: array passed through unchanged (not its concern).
yield 'name - array passthrough' => [Name::id(), ['a'], ['a']];
}
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

Add a PromptManager-level regression test for the fixed path.

This suite validates handler normalization well, but it does not cover the actual resolution flow in PromptManager::args() (Line 651 fallback to short key + Line 677 normalization before prompt default assignment). A focused regression test there would lock in the bugfix behavior end-to-end.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.vortex/installer/tests/Unit/Handlers/AbstractHandlerNormalizeValueTest.php
around lines 25 - 57, Add a regression test that exercises the full
PromptManager resolution flow — specifically call PromptManager::args(...) to
trigger the fallback-to-short-key logic and ensure PromptManager calls
handler->normalizeValue(...) before assigning prompt defaults (covering the
behavior fixed at the args() fallback + normalization steps). In practice,
create a new test method that constructs Config::fromString('{}') and
PromptManager, invokes $prompt_manager->args(...) with an input that only
matches the handler via its short key (and with values needing normalization,
e.g., comma-separated string for Modules::id() or Services::id()), and assert
the returned args contain the normalized array values (not raw strings) and
correct defaults; reference PromptManager::args, handler->normalizeValue, and a
handler id like Modules::id() or Services::id() to locate the code to exercise.

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 28, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 79.27%. Comparing base (39ef060) to head (6b03d39).
⚠️ Report is 5 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2435      +/-   ##
==========================================
- Coverage   79.71%   79.27%   -0.44%     
==========================================
  Files         127      120       -7     
  Lines        6831     6684     -147     
  Branches       44        0      -44     
==========================================
- Hits         5445     5299     -146     
+ Misses       1386     1385       -1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions

This comment has been minimized.

@AlexSkrypnyk

This comment has been minimized.

2 similar comments
@AlexSkrypnyk

This comment has been minimized.

@AlexSkrypnyk

This comment has been minimized.

@github-actions
Copy link
Copy Markdown

Code coverage (threshold: 90%)

  Classes: 100.00% (1/1)
  Methods: 100.00% (2/2)
  Lines:   100.00% (196/196)
Per-class coverage
Drupal\ys_demo\Plugin\Block\CounterBlock
  Methods: 100.00% ( 2/ 2)   Lines: 100.00% ( 10/ 10)

@AlexSkrypnyk

This comment has been minimized.

2 similar comments
@AlexSkrypnyk

This comment has been minimized.

@AlexSkrypnyk
Copy link
Copy Markdown
Member Author

Code coverage (threshold: 90%)

  Classes: 100.00% (1/1)
  Methods: 100.00% (2/2)
  Lines:   100.00% (189/189)
Per-class coverage
Drupal\ys_demo\Plugin\Block\CounterBlock
  Methods: 100.00% ( 2/ 2)   Lines: 100.00% ( 10/ 10)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: BACKLOG

Development

Successfully merging this pull request may close these issues.

1 participant