From 0f82b0cb0608300c0ed9c2cc74fbea7f2673c433 Mon Sep 17 00:00:00 2001 From: "Kai (Tam Nhu) Tran" <61256810+kaitranntt@users.noreply.github.com> Date: Sat, 22 Nov 2025 20:57:54 -0500 Subject: [PATCH] fix: clear package manager cache during update to ensure fresh downloads (v4.3.10) (#19) * fix: clear package manager cache during update to ensure fresh downloads (v4.3.10) Resolves issue where 'ccs update' would report success but serve cached package versions, requiring manual 'npm cache clean --force'. Changes: - Node.js (bin/ccs.js): Added cache clearing for npm, yarn, pnpm before update - Bash (lib/ccs): Added 'npm cache clean --force' before npm update - PowerShell (lib/ccs.ps1): Added 'npm cache clean --force' before npm update - Updated manual fallback commands to include cache clearing - Non-blocking: continues with update even if cache clearing fails Version bumped to 4.3.10 * docs: update CHANGELOG for v4.3.10 --- CHANGELOG.md | 23 +++++++++++ VERSION | 2 +- bin/ccs.js | 91 +++++++++++++++++++++++++++++------------- installers/install.ps1 | 2 +- installers/install.sh | 2 +- lib/ccs | 11 ++++- lib/ccs.ps1 | 16 +++++++- package.json | 2 +- 8 files changed, 114 insertions(+), 35 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c76a80b2..8165dbd5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,29 @@ Format: [Keep a Changelog](https://keepachangelog.com/) +## [4.3.10] - 2025-11-23 + +### Fixed +- **Update Cache Issue**: Fixed `ccs update` serving cached package versions instead of fresh downloads +- Package manager cache is now automatically cleared before updating +- Update now ensures users always receive the latest version from registry + +### Technical Details +- **Node.js (bin/ccs.js)**: Added cache clearing for npm, yarn, pnpm before update + - npm: `npm cache clean --force` + - yarn: `yarn cache clean` + - pnpm: `pnpm store prune` + - bun: No explicit cache clearing needed +- **Bash (lib/ccs)**: Added `npm cache clean --force` before npm update +- **PowerShell (lib/ccs.ps1)**: Added `npm cache clean --force` before npm update +- **Non-blocking**: Update continues even if cache clearing fails (with warning) +- **Manual fallback commands**: Updated to include cache clearing step + +### Impact +- Users no longer need to manually run `npm cache clean --force` before `ccs update` +- Resolves issue where update reported success but installed cached/outdated version +- Ensures fresh package downloads from npm registry on every update + ## [4.3.8] - 2025-11-23 ### Fixed diff --git a/VERSION b/VERSION index 7de8a1d7..5d72fe47 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -4.3.9 +4.3.10 diff --git a/bin/ccs.js b/bin/ccs.js index d560f26d..0b1bf855 100755 --- a/bin/ccs.js +++ b/bin/ccs.js @@ -533,65 +533,102 @@ async function handleUpdateCommand() { if (isNpmInstall) { // npm installation - detect package manager and update const packageManager = detectPackageManager(); - let updateCommand, updateArgs; + let updateCommand, updateArgs, cacheCommand, cacheArgs; switch (packageManager) { case 'npm': updateCommand = 'npm'; updateArgs = ['install', '-g', '@kaitranntt/ccs@latest']; + cacheCommand = 'npm'; + cacheArgs = ['cache', 'clean', '--force']; break; case 'yarn': updateCommand = 'yarn'; updateArgs = ['global', 'add', '@kaitranntt/ccs@latest']; + cacheCommand = 'yarn'; + cacheArgs = ['cache', 'clean']; break; case 'pnpm': updateCommand = 'pnpm'; updateArgs = ['add', '-g', '@kaitranntt/ccs@latest']; + cacheCommand = 'pnpm'; + cacheArgs = ['store', 'prune']; break; case 'bun': updateCommand = 'bun'; updateArgs = ['add', '-g', '@kaitranntt/ccs@latest']; + cacheCommand = null; // bun doesn't need explicit cache clearing + cacheArgs = null; break; default: updateCommand = 'npm'; updateArgs = ['install', '-g', '@kaitranntt/ccs@latest']; + cacheCommand = 'npm'; + cacheArgs = ['cache', 'clean', '--force']; } console.log(colored(`Updating via ${packageManager}...`, 'cyan')); console.log(''); - const child = spawn(updateCommand, updateArgs, { - stdio: 'inherit' - // No shell needed for direct commands - }); + // Clear package manager cache first to ensure fresh download + if (cacheCommand) { + console.log(colored('Clearing package cache...', 'cyan')); + const cacheChild = spawn(cacheCommand, cacheArgs, { + stdio: 'inherit' + }); - child.on('exit', (code) => { - if (code === 0) { + cacheChild.on('exit', (code) => { + if (code !== 0) { + console.log(colored('[!] Cache clearing failed, proceeding anyway...', 'yellow')); + } + // Continue with update regardless of cache clearing result + performUpdate(); + }); + + cacheChild.on('error', (err) => { + console.log(colored('[!] Cache clearing failed, proceeding anyway...', 'yellow')); + // Continue with update regardless of cache clearing result + performUpdate(); + }); + } else { + // No cache clearing needed, proceed directly + performUpdate(); + } + + function performUpdate() { + const child = spawn(updateCommand, updateArgs, { + stdio: 'inherit' + // No shell needed for direct commands + }); + + child.on('exit', (code) => { + if (code === 0) { + console.log(''); + console.log(colored('[OK] Update successful!', 'green')); + console.log(''); + console.log(`Run ${colored('ccs --version', 'yellow')} to verify`); + console.log(''); + } else { + console.log(''); + console.log(colored('[X] Update failed', 'red')); + console.log(''); + console.log('Try manually:'); + console.log(colored(` ${updateCommand} ${updateArgs.join(' ')}`, 'yellow')); + console.log(''); + } + process.exit(code || 0); + }); + + child.on('error', (err) => { console.log(''); - console.log(colored('[OK] Update successful!', 'green')); - console.log(''); - console.log(`Run ${colored('ccs --version', 'yellow')} to verify`); - console.log(''); - } else { - console.log(''); - console.log(colored('[X] Update failed', 'red')); + console.log(colored(`[X] Failed to run ${packageManager} update`, 'red')); console.log(''); console.log('Try manually:'); console.log(colored(` ${updateCommand} ${updateArgs.join(' ')}`, 'yellow')); console.log(''); - } - process.exit(code || 0); - }); - - child.on('error', (err) => { - console.log(''); - console.log(colored(`[X] Failed to run ${packageManager} update`, 'red')); - console.log(''); - console.log('Try manually:'); - console.log(colored(` ${updateCommand} ${updateArgs.join(' ')}`, 'yellow')); - console.log(''); - process.exit(1); - }); + process.exit(1); + }); + } } else { // Direct installation - re-run installer console.log(colored('Updating via installer...', 'cyan')); diff --git a/installers/install.ps1 b/installers/install.ps1 index 882f673e..53754de4 100644 --- a/installers/install.ps1 +++ b/installers/install.ps1 @@ -31,7 +31,7 @@ $InstallMethod = if ($ScriptDir -and ((Test-Path "$ScriptDir\lib\ccs.ps1") -or ( # IMPORTANT: Update this version when releasing new versions! # This hardcoded version is used for standalone installations (irm | iex) # For git installations, VERSION file is read if available -$CcsVersion = "4.3.9" +$CcsVersion = "4.3.10" # Try to read VERSION file for git installations if ($ScriptDir) { diff --git a/installers/install.sh b/installers/install.sh index dbe2b07a..49154b5f 100755 --- a/installers/install.sh +++ b/installers/install.sh @@ -32,7 +32,7 @@ fi # IMPORTANT: Update this version when releasing new versions! # This hardcoded version is used for standalone installations (curl | bash) # For git installations, VERSION file is read if available -CCS_VERSION="4.3.9" +CCS_VERSION="4.3.10" # Try to read VERSION file for git installations if [[ -f "$SCRIPT_DIR/VERSION" ]]; then diff --git a/lib/ccs b/lib/ccs index 70affa76..89688c87 100755 --- a/lib/ccs +++ b/lib/ccs @@ -2,7 +2,7 @@ set -euo pipefail # Version (updated by scripts/bump-version.sh) -CCS_VERSION="4.3.9" +CCS_VERSION="4.3.10" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" readonly CONFIG_FILE="${CCS_CONFIG:-$HOME/.ccs/config.json}" readonly PROFILES_JSON="$HOME/.ccs/profiles.json" @@ -674,6 +674,13 @@ update_run() { echo -e "${CYAN}Updating via npm...${RESET}" echo "" + # Clear npm cache to ensure fresh download + echo -e "${CYAN}Clearing package cache...${RESET}" + if ! npm cache clean --force 2>/dev/null; then + echo -e "${YELLOW}[!] Cache clearing failed, proceeding anyway...${RESET}" + fi + echo "" + if npm install -g @kaitranntt/ccs@latest; then echo "" echo -e "${GREEN}[OK] Update successful!${RESET}" @@ -686,7 +693,7 @@ update_run() { echo -e "${RED}[X] Update failed${RESET}" echo "" echo "Try manually:" - echo -e " ${YELLOW}npm install -g @kaitranntt/ccs@latest${RESET}" + echo -e " ${YELLOW}npm cache clean --force && npm install -g @kaitranntt/ccs@latest${RESET}" echo "" exit 1 fi diff --git a/lib/ccs.ps1 b/lib/ccs.ps1 index 3edeb238..1bcbc19b 100644 --- a/lib/ccs.ps1 +++ b/lib/ccs.ps1 @@ -12,7 +12,7 @@ param( $ErrorActionPreference = "Stop" # Version (updated by scripts/bump-version.sh) -$CcsVersion = "4.3.9" +$CcsVersion = "4.3.10" $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path $ConfigFile = if ($env:CCS_CONFIG) { $env:CCS_CONFIG } else { "$env:USERPROFILE\.ccs\config.json" } $ProfilesJson = "$env:USERPROFILE\.ccs\profiles.json" @@ -1122,6 +1122,18 @@ function Update-Run { Write-Host "Updating via npm..." -ForegroundColor Cyan Write-Host "" + # Clear npm cache to ensure fresh download + Write-Host "Clearing package cache..." -ForegroundColor Cyan + try { + npm cache clean --force 2>$null + if ($LASTEXITCODE -ne 0) { + Write-Host "[!] Cache clearing failed, proceeding anyway..." -ForegroundColor Yellow + } + } catch { + Write-Host "[!] Cache clearing failed, proceeding anyway..." -ForegroundColor Yellow + } + Write-Host "" + try { npm install -g @kaitranntt/ccs@latest if ($LASTEXITCODE -eq 0) { @@ -1139,7 +1151,7 @@ function Update-Run { Write-Host "[X] Update failed" -ForegroundColor Red Write-Host "" Write-Host "Try manually:" - Write-Host " npm install -g @kaitranntt/ccs@latest" -ForegroundColor Yellow + Write-Host " npm cache clean --force; npm install -g @kaitranntt/ccs@latest" -ForegroundColor Yellow Write-Host "" exit 1 } diff --git a/package.json b/package.json index 5cc05889..e363f88f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@kaitranntt/ccs", - "version": "4.3.9", + "version": "4.3.10", "description": "Claude Code Switch - Instant profile switching between Claude Sonnet 4.5 and GLM 4.6", "keywords": [ "cli",