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.
This commit is contained in:
Jerome Revillard 2026-04-27 12:17:38 +02:00
parent 2395b0e2ed
commit defab55922
1 changed files with 10 additions and 4 deletions

View File

@ -86,12 +86,15 @@ class UI {
actionType = options.action; actionType = options.action;
await prompts.log.info(`Using action from command-line: ${actionType}`); await prompts.log.info(`Using action from command-line: ${actionType}`);
} else if (options.yes) { } 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) { if (choices.length === 0) {
throw new Error('No valid actions available for this installation'); throw new Error('No valid actions available for this installation');
} }
const hasQuickUpdate = choices.some((c) => c.value === 'quick-update'); 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}`); await prompts.log.info(`Non-interactive mode (--yes): defaulting to ${actionType}`);
} else { } else {
actionType = await prompts.select({ actionType = await prompts.select({
@ -127,8 +130,11 @@ class UI {
.map((m) => m.trim()) .map((m) => m.trim())
.filter(Boolean); .filter(Boolean);
await prompts.log.info(`Using modules from command-line: ${selectedModules.join(', ')}`); await prompts.log.info(`Using modules from command-line: ${selectedModules.join(', ')}`);
} else if (options.customSource) { } else if (options.customSource && !options.yes) {
// Custom source without --modules: start with empty list (core added below) // Custom source without --modules or --yes: start with empty list
// (user will be prompted to select modules interactively; core added below).
// When --yes is also set, fall through to the --yes branch so all
// installed modules are included alongside the custom source modules.
selectedModules = []; selectedModules = [];
} else if (options.yes) { } else if (options.yes) {
selectedModules = await this.getDefaultModules(installedModuleIds); selectedModules = await this.getDefaultModules(installedModuleIds);