Warn when no network configuration is selected (#4408)

* Make network configuration mandatory with explicit "No network" option

* Add network configuration recommendation hint and disable sorting

* Warn when network selection was skipped instead of making it mandatory

Replace the mandatory network_config menu requirement with a yellow
warning on the final confirmation screen, shown only when the user
skipped the network menu entirely. Explicitly picking "No network
configuration" is treated as a conscious choice and does not trigger
the warning.

- Drop mandatory=True from the network_config global menu item
- Rename NicType.NONE menu label from "No network" to
  "No network configuration" (an installed system still has an NIC;
  only the install-time configuration is absent)
- Add ConfigurationOutput.get_install_warnings() and render them in
  confirm_config when show_install_warnings=True
- guided.py and minimal.py enable the warning on the confirm screen
- Reuse the existing "No network configuration" msgid in .pot; add the
  warning string; update Ukrainian translations accordingly

* Drop NicType.NONE from this PR

The NONE option introduced earlier in this branch is being removed per
review feedback (#4408). Whether to add explicit "None" options across
multiple menus (greeter, gfx driver, network, bootloader) is now being
discussed in #4464 and should land as a separate change there.

This PR keeps only the warning-on-confirm behaviour: when the user
skipped the network menu entirely (network_config is None), a yellow
warning is shown on the final confirmation screen.
This commit is contained in:
Softer 2026-04-28 13:17:40 +03:00 committed by GitHub
parent 1b7a32a3b3
commit cb0f3a6eba
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 41 additions and 5 deletions

View File

@ -124,10 +124,13 @@ class ConfigurationOutput:
label_width = max(len(label) for label, _ in rows) + 2 label_width = max(len(label) for label, _ in rows) + 2
return '\n'.join(f'{label:<{label_width}}{value}' for label, value in rows) return '\n'.join(f'{label:<{label_width}}{value}' for label, value in rows)
async def confirm_config(self) -> bool: async def confirm_config(self, show_install_warnings: bool = False) -> bool:
header = f'{tr("The specified configuration will be applied")}. ' header = f'{tr("The specified configuration will be applied")}. '
header += tr('Would you like to continue?') + '\n' header += tr('Would you like to continue?') + '\n'
if show_install_warnings:
header += self._render_install_warnings()
group = MenuItemGroup.yes_no() group = MenuItemGroup.yes_no()
group.set_preview_for_all(lambda x: self.user_config_to_json()) group.set_preview_for_all(lambda x: self.user_config_to_json())
@ -145,6 +148,22 @@ class ConfigurationOutput:
return True return True
def get_install_warnings(self) -> list[str]:
warnings: list[str] = []
if not isinstance(self._config.network_config, NetworkConfiguration):
warnings.append(tr('Warning: no network configuration selected. Network will need to be set up manually on the installed system.'))
return warnings
def _render_install_warnings(self) -> str:
warnings = self.get_install_warnings()
if not warnings:
return ''
return '\n' + '\n'.join(f'[yellow]{w}[/]' for w in warnings) + '\n'
def _is_valid_path(self, dest_path: Path) -> bool: def _is_valid_path(self, dest_path: Path) -> bool:
dest_path_ok = dest_path.exists() and dest_path.is_dir() dest_path_ok = dest_path.exists() and dest_path.is_dir()
if not dest_path_ok: if not dest_path_ok:

View File

@ -172,14 +172,17 @@ async def select_network(preset: NetworkConfiguration | None) -> NetworkConfigur
""" """
items = [MenuItem(n.display_msg(), value=n) for n in NicType] items = [MenuItem(n.display_msg(), value=n) for n in NicType]
group = MenuItemGroup(items, sort_items=True) group = MenuItemGroup(items, sort_items=False)
if preset: if preset:
group.set_selected_by_value(preset.type) group.set_selected_by_value(preset.type)
header = tr('Choose network configuration') + '\n'
header += tr('Recommended: Network Manager for desktop, Manual for server') + '\n'
result = await Selection[NicType]( result = await Selection[NicType](
group, group,
header=tr('Choose network configuration'), header=header,
allow_reset=True, allow_reset=True,
allow_skip=True, allow_skip=True,
).show() ).show()

View File

@ -2192,6 +2192,14 @@ msgstr ""
msgid "Choose network configuration" msgid "Choose network configuration"
msgstr "" msgstr ""
msgid "Recommended: Network Manager for desktop, Manual for server"
msgstr ""
msgid ""
"Warning: no network configuration selected. Network will need to be set up "
"manually on the installed system."
msgstr ""
msgid "No packages found" msgid "No packages found"
msgstr "" msgstr ""

View File

@ -2133,6 +2133,12 @@ msgstr "Оберіть інтерфейс"
msgid "Choose network configuration" msgid "Choose network configuration"
msgstr "Оберіть конфігурацію мережі" msgstr "Оберіть конфігурацію мережі"
msgid "Recommended: Network Manager for desktop, Manual for server"
msgstr "Рекомендовано: Network Manager для робочого столу, ручне налаштування для сервера"
msgid "Warning: no network configuration selected. Network will need to be set up manually on the installed system."
msgstr "Попередження: конфігурацію мережі не обрано. Мережу доведеться налаштувати вручну на встановленій системі."
msgid "No packages found" msgid "No packages found"
msgstr "Пакети не знайдено" msgstr "Пакети не знайдено"

View File

@ -226,7 +226,7 @@ def main(arch_config_handler: ArchConfigHandler | None = None) -> None:
if not arch_config_handler.args.silent: if not arch_config_handler.args.silent:
aborted = False aborted = False
res: bool = tui.run(config.confirm_config) res: bool = tui.run(lambda: config.confirm_config(show_install_warnings=True))
if not res: if not res:
debug('Installation aborted') debug('Installation aborted')

View File

@ -77,7 +77,7 @@ async def main(arch_config_handler: ArchConfigHandler | None = None) -> None:
if not arch_config_handler.args.silent: if not arch_config_handler.args.silent:
aborted = False aborted = False
res: bool = tui.run(config.confirm_config) res: bool = tui.run(lambda: config.confirm_config(show_install_warnings=True))
if not res: if not res:
debug('Installation aborted') debug('Installation aborted')