Skip to content

Commit 4ab7038

Browse files
authored
fix(cli): make uipro update upgrade CLI via npm
Approved by github-maintain cron-safe review. Supersedes #326.
1 parent 3a12b63 commit 4ab7038

2 files changed

Lines changed: 39 additions & 7 deletions

File tree

cli/README.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ uipro init --force # Overwrite existing files
3333

3434
# Other commands
3535
uipro versions # List available versions
36-
uipro update # Refresh skill files from installed CLI package
36+
uipro update # Update the global CLI to the latest release
3737
```
3838

3939
## GitHub Authentication
@@ -63,13 +63,15 @@ uipro init
6363
6464
## How It Works
6565

66-
`uipro init` generates assistant-specific files from the templates bundled with the installed CLI package. To get newer templates and data, update the package first:
66+
`uipro init` generates assistant-specific files from the templates bundled with the installed CLI package. To get newer templates and data, update the package, then regenerate:
6767

6868
```bash
69-
npm install -g uipro-cli@latest
70-
uipro init --ai codex
69+
uipro update # updates the global CLI to the latest release
70+
uipro init --ai codex --force # regenerate skill files from the new package
7171
```
7272

73+
`uipro update` runs `npm install -g uipro-cli@latest` for you (it shells out to `npm` only on Windows, where `npm` is a `.cmd`). You can still run that command manually if you prefer. When the CLI is already current, `uipro update` just refreshes the installed skill files.
74+
7375
## Development
7476

7577
```bash

cli/src/commands/update.ts

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { execFileSync } from 'node:child_process';
12
import { readFile } from 'node:fs/promises';
23
import { dirname, join } from 'node:path';
34
import { fileURLToPath } from 'node:url';
@@ -38,9 +39,38 @@ export async function updateCommand(options: UpdateOptions): Promise<void> {
3839

3940
if (currentVersion !== latestVersion) {
4041
console.log();
41-
logger.warn(`Installed CLI package is ${chalk.cyan(currentVersion)}, but latest release is ${chalk.cyan(release.tag_name)}.`);
42-
logger.info(`Update the CLI package first: ${chalk.cyan(`npm install -g uipro-cli@${latestVersion}`)}`);
43-
logger.info('Then rerun: uipro init --ai <platform>');
42+
43+
// Only auto-run with a well-formed semver, so nothing unexpected can
44+
// reach the shell that npm.cmd requires on Windows.
45+
if (!/^\d+\.\d+\.\d+([.-][0-9A-Za-z.-]+)?$/.test(latestVersion)) {
46+
logger.warn(`Installed CLI is ${chalk.cyan(currentVersion)}; latest release is ${chalk.cyan(release.tag_name)}.`);
47+
logger.info(`Update the CLI package: ${chalk.cyan(`npm install -g uipro-cli@${latestVersion}`)}`);
48+
logger.info('Then rerun: uipro init --ai <platform> --force');
49+
return;
50+
}
51+
52+
logger.info(`Updating CLI from ${chalk.cyan(currentVersion)} to ${chalk.cyan(latestVersion)}...`);
53+
console.log();
54+
55+
const isWindows = process.platform === 'win32';
56+
try {
57+
// execFileSync with an explicit args array — no shell string to expand.
58+
// On Windows npm is npm.cmd, which Node only spawns via a shell.
59+
execFileSync(
60+
isWindows ? 'npm.cmd' : 'npm',
61+
['install', '-g', `uipro-cli@${latestVersion}`],
62+
{ stdio: 'inherit', shell: isWindows }
63+
);
64+
} catch {
65+
console.log();
66+
logger.error('Automatic update failed (you may need elevated/admin permissions).');
67+
logger.info(`Update manually: ${chalk.cyan(`npm install -g uipro-cli@${latestVersion}`)}`);
68+
process.exit(1);
69+
}
70+
71+
console.log();
72+
logger.success(`Updated to ${chalk.cyan(latestVersion)}.`);
73+
logger.info(`Now rerun ${chalk.cyan('uipro init --ai <platform> --force')} to refresh your skill files.`);
4474
return;
4575
}
4676

0 commit comments

Comments
 (0)