From 3e89b30b3cdd3b2b30a8e6e5d2a2309a9d95eaed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Revillard?= Date: Tue, 28 Apr 2026 03:49:21 +0200 Subject: [PATCH] fix: use full update path when --custom-source is passed with --yes (#2336) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: use full update path when --custom-source is passed with --yes When --yes is used on an existing install, the installer auto-selects quick-update. However, quick-update never re-clones custom module repos — it only reads whatever is already in the cache. This means --custom-source with a new version tag (e.g. @1.1.0) is silently ignored and the previously cached version (e.g. 1.0.1) is reported as "already up to date". Default to the full update path when --custom-source is present, so the custom repo gets re-cloned at the requested version. Also ensure all installed modules are included in the selection when --yes is combined with --custom-source, preventing previously installed modules from being removed. * fix: address review feedback on choices.find() and comment clarity * style: prettier fix for empty-body methods in custom-module-manager --------- Co-authored-by: Brian --- tools/installer/modules/custom-module-manager.js | 2 +- tools/installer/ui.js | 14 ++++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/tools/installer/modules/custom-module-manager.js b/tools/installer/modules/custom-module-manager.js index 92644a934..ca3e52325 100644 --- a/tools/installer/modules/custom-module-manager.js +++ b/tools/installer/modules/custom-module-manager.js @@ -336,7 +336,7 @@ class CustomModuleManager { const createSpinner = async () => { if (silent) { - return { start() { }, stop() { }, error() { } }; + return { start() {}, stop() {}, error() {} }; } return await prompts.spinner(); }; diff --git a/tools/installer/ui.js b/tools/installer/ui.js index 4ec0ef118..7b720743b 100644 --- a/tools/installer/ui.js +++ b/tools/installer/ui.js @@ -200,12 +200,15 @@ class UI { actionType = options.action; await prompts.log.info(`Using action from command-line: ${actionType}`); } else if (options.yes) { - // Default to quick-update if available, otherwise first available choice + // Default to quick-update if available, unless flags that require the + // full update path are present (e.g. --custom-source which re-clones + // modules at a new version — quick-update skips that entirely). if (choices.length === 0) { throw new Error('No valid actions available for this installation'); } const hasQuickUpdate = choices.some((c) => c.value === 'quick-update'); - actionType = hasQuickUpdate ? 'quick-update' : choices[0].value; + const needsFullUpdate = !!options.customSource; + actionType = hasQuickUpdate && !needsFullUpdate ? 'quick-update' : (choices.find((c) => c.value === 'update') || choices[0]).value; await prompts.log.info(`Non-interactive mode (--yes): defaulting to ${actionType}`); } else { actionType = await prompts.select({ @@ -241,8 +244,11 @@ class UI { .map((m) => m.trim()) .filter(Boolean); await prompts.log.info(`Using modules from command-line: ${selectedModules.join(', ')}`); - } else if (options.customSource) { - // Custom source without --modules: start with empty list (core added below) + } else if (options.customSource && !options.yes) { + // Custom source without --modules or --yes: start with empty list + // (only custom source modules + core will be installed). + // When --yes is also set, fall through to the --yes branch so all + // installed modules are included alongside the custom source modules. selectedModules = []; } else if (options.yes) { selectedModules = await this.getDefaultModules(installedModuleIds);