Commit 03e0a23
feat(cli): Add upgrade command for CLI self-update (#348)
* feat(cli): Add upgrade command for CLI self-update
Add a new top-level `xcodebuildmcp upgrade` command that compares the
installed version against the latest GitHub release, detects the install
method (Homebrew, npm-global, npx, or unknown), shows a truncated
release-notes excerpt, and either runs the correct upgrade command with
inherited stdio or prints the manual command for unsupported channels.
Supports `--check` to report versions without prompting and `--yes`/`-y`
to skip the interactive confirmation for scripted use. Non-TTY callers
that could auto-upgrade but omit `--yes` exit with status 1 so scripts
do not hang.
Repo owner/name and package name are now emitted from the version
generator so the command reads them from package.json rather than
hardcoding. The command short-circuits in src/cli.ts to avoid the full
runtime bootstrap, mirroring `init` and `setup`.
Co-Authored-By: Claude <noreply@anthropic.com>
* feat(cli): Make upgrade command channel-aware
Each install channel now queries its own source of truth for the latest
version instead of always using GitHub Releases. This prevents misleading
results when release channels drift — e.g. GitHub may publish a version
before the Homebrew tap bumps, or npm dist-tags may lag a pre-release.
- Homebrew: `brew info --json=v2` (handles exit-0-with-empty-formulae)
- npm-global / npx: `npm view <pkg>@latest version --json`
- Unknown: falls back to GitHub Releases latest endpoint
Release notes are fetched separately by tag from GitHub and are non-fatal
if unavailable (404, timeout, network error).
New DI surface: fetchLatestVersionForChannel, fetchReleaseNotesForTag,
runChannelLookupCommand (for test isolation). The dependency factory
rebuilds derived defaults from merged overrides so tests can mock at
any level.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(cli): Allow hyphens in semver identifiers and check brew exit code
Fix parseVersion regex to accept hyphens in prerelease and build-metadata
identifiers as required by SemVer 2.0.0, so versions like 1.0.0-alpha-1
or 1.0.0-rc-1+build-hash no longer fail to parse.
Check the exit code of `brew info` before attempting to parse its stdout.
Homebrew exits 0 for missing formulas (a quirk the existing empty-formulae
path handles), but other failure modes like a broken brew install or
permission errors exit non-zero with empty stdout — those now surface a
specific exit-code error instead of a misleading "invalid JSON output".
Reported in PR review by Cursor Bugbot and Sentry.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(cli): Compare prerelease identifiers in ASCII order per SemVer 2.0.0
SemVer 2.0.0 §11 requires lexical comparison of prerelease identifiers in
ASCII sort order. The previous implementation used String.prototype.localeCompare,
which applies locale-dependent collation and can differ from ASCII ordering.
For example, "Alpha".localeCompare("alpha") returns 1 in common locales while
ASCII comparison returns -1.
Replace localeCompare with a UTF-16 code-unit comparison, which matches
ASCII ordering for the [0-9A-Za-z-] character set SemVer permits.
Reported in PR review by Cursor Bugbot.
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent c40789b commit 03e0a23
File tree
11 files changed
+2013
-3
lines changed- docs
- scripts
- src
- cli
- commands
- __tests__
- utils/version
11 files changed
+2013
-3
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
3 | 9 | | |
4 | 10 | | |
5 | 11 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
352 | 352 | | |
353 | 353 | | |
354 | 354 | | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
355 | 362 | | |
356 | 363 | | |
357 | 364 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
28 | 28 | | |
29 | 29 | | |
30 | 30 | | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
31 | 46 | | |
32 | 47 | | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
33 | 84 | | |
34 | 85 | | |
35 | 86 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
62 | 62 | | |
63 | 63 | | |
64 | 64 | | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
65 | 75 | | |
66 | 76 | | |
67 | 77 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
125 | 125 | | |
126 | 126 | | |
127 | 127 | | |
128 | | - | |
| 128 | + | |
129 | 129 | | |
130 | 130 | | |
131 | 131 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
| 5 | + | |
5 | 6 | | |
6 | 7 | | |
7 | 8 | | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
8 | 20 | | |
9 | 21 | | |
10 | 22 | | |
| |||
15 | 27 | | |
16 | 28 | | |
17 | 29 | | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
18 | 37 | | |
19 | 38 | | |
20 | 39 | | |
21 | | - | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
22 | 44 | | |
23 | 45 | | |
24 | 46 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
80 | 80 | | |
81 | 81 | | |
82 | 82 | | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
83 | 90 | | |
84 | 91 | | |
85 | 92 | | |
| |||
95 | 102 | | |
96 | 103 | | |
97 | 104 | | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
98 | 109 | | |
99 | 110 | | |
100 | 111 | | |
| |||
0 commit comments