fix: improve auto-update to happen before you execute a command (#1371)

This commit is contained in:
Ralph Khreish
2025-11-01 14:46:07 +01:00
parent a72c8cfb49
commit 64785eaa28
4 changed files with 55 additions and 20 deletions

View File

@@ -0,0 +1,8 @@
---
"task-master-ai": patch
---
Improved auto-update experience:
- updates now happen before your CLI command runs and automatically restart to execute your command with the new version.
- No more manual restarts needed!

View File

@@ -32,7 +32,8 @@ export {
checkForUpdate,
performAutoUpdate,
displayUpgradeNotification,
compareVersions
compareVersions,
restartWithNewVersion
} from './utils/auto-update.js';
export { runInteractiveSetup } from './commands/models/index.js';

View File

@@ -7,6 +7,7 @@ import https from 'https';
import chalk from 'chalk';
import ora from 'ora';
import boxen from 'boxen';
import process from 'process';
export interface UpdateInfo {
currentVersion: string;
@@ -345,9 +346,6 @@ export async function performAutoUpdate(
`Successfully updated to version ${chalk.bold(latestVersion)}`
)
);
console.log(
chalk.dim('Please restart your command to use the new version.')
);
resolve(true);
} else {
spinner.fail(chalk.red('Auto-update failed'));
@@ -375,3 +373,33 @@ export async function performAutoUpdate(
});
});
}
/**
* Restart the CLI with the newly installed version
* @param argv - Original command-line arguments (process.argv)
*/
export function restartWithNewVersion(argv: string[]): void {
const args = argv.slice(2); // Remove 'node' and script path
console.log(chalk.dim('Restarting with updated version...\n'));
// Spawn the updated task-master command
const child = spawn('task-master', args, {
stdio: 'inherit', // Inherit stdin/stdout/stderr so it looks seamless
detached: false,
shell: process.platform === 'win32' // Windows compatibility
});
child.on('exit', (code) => {
process.exit(code || 0);
});
child.on('error', (error) => {
console.error(
chalk.red('Failed to restart with new version:'),
error.message
);
console.log(chalk.yellow('Please run your command again manually.'));
process.exit(1);
});
}

View File

@@ -8,10 +8,7 @@ import path from 'path';
import chalk from 'chalk';
import boxen from 'boxen';
import fs from 'fs';
import https from 'https';
import http from 'http';
import inquirer from 'inquirer';
import search from '@inquirer/search';
import { log, readJSON } from './utils.js';
// Import command registry and utilities from @tm/cli
@@ -20,6 +17,7 @@ import {
checkForUpdate,
performAutoUpdate,
displayUpgradeNotification,
restartWithNewVersion,
displayError,
runInteractiveSetup
} from '@tm/cli';
@@ -4447,18 +4445,10 @@ async function runCLI(argv = process.argv) {
process.exit(0);
}
// Start the update check in the background - don't await yet
// Check for updates BEFORE executing the command
const currentVersion = getTaskMasterVersion();
const updateCheckPromise = checkForUpdate(currentVersion);
const updateInfo = await checkForUpdate(currentVersion);
// Setup and parse
// NOTE: getConfig() might be called during setupCLI->registerCommands if commands need config
// This means the ConfigurationError might be thrown here if configuration file is missing.
const programInstance = setupCLI();
await programInstance.parseAsync(argv);
// After command execution, check if an update is available
const updateInfo = await updateCheckPromise;
if (updateInfo.needsUpdate) {
// Display the upgrade notification first
displayUpgradeNotification(
@@ -4467,14 +4457,22 @@ async function runCLI(argv = process.argv) {
updateInfo.highlights
);
// Then automatically perform the update
// Automatically perform the update
const updateSuccess = await performAutoUpdate(updateInfo.latestVersion);
if (updateSuccess) {
// Exit gracefully after successful update
process.exit(0);
// Restart with the new version - this will execute the user's command
restartWithNewVersion(argv);
return; // Never reached, but for clarity
}
// If update fails, continue with current version
}
// Setup and parse
// NOTE: getConfig() might be called during setupCLI->registerCommands if commands need config
// This means the ConfigurationError might be thrown here if configuration file is missing.
const programInstance = setupCLI();
await programInstance.parseAsync(argv);
// Check if migration has occurred and show FYI notice once
try {
// Use initTaskMaster with no required fields - will only fail if no project root