Last active
October 26, 2025 19:37
-
-
Save kellyselden/33cfb004886bfc083b07ae1db89df627 to your computer and use it in GitHub Desktop.
cup-all
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| param( | |
| [int]$MinAgeDays = 7, | |
| [switch]$WhatIf | |
| ) | |
| Write-Host "Checking installed packages..." -ForegroundColor Cyan | |
| # Get all installed packages (no --exact) | |
| $all = choco list --limit-output 2>$null | |
| # Get outdated packages | |
| $outdated = choco outdated --ignore-pinned --limit-output --exact 2>$null | |
| if (-not $all) { | |
| Write-Host "No installed packages found." -ForegroundColor Cyan | |
| exit 0 | |
| } | |
| # Convert outdated list to a hashtable for quick lookup | |
| $outdatedHash = @{} | |
| if ($outdated) { | |
| foreach ($line in $outdated -split "`n") { | |
| $parts = $line -split '\|' | |
| if ($parts.Count -ge 3) { | |
| $outdatedHash[$parts[0]] = $parts[2] # packageId => latestVersion | |
| } | |
| } | |
| } | |
| foreach ($line in $all -split "`n") { | |
| $parts = $line -split '\|' | |
| if ($parts.Count -lt 2) { continue } | |
| $packageId = $parts[0] | |
| $installedVersion = $parts[1] | |
| if (-not $outdatedHash.ContainsKey($packageId)) { | |
| Write-Host "${packageId} is already up to date (version ${installedVersion})." -ForegroundColor DarkGray | |
| continue | |
| } | |
| $latestVersion = $outdatedHash[$packageId] | |
| Write-Host "`nChecking ${packageId} ..." -ForegroundColor White | |
| Write-Host "Installed Version: ${installedVersion}" -ForegroundColor White | |
| Write-Host "Latest Available: ${latestVersion}" -ForegroundColor White | |
| $encodedId = [System.Uri]::EscapeDataString($packageId) | |
| $feedUrl = "https://community.chocolatey.org/api/v2/FindPackagesById%28%29?id='${encodedId}'" | |
| try { | |
| $xml = [xml](Invoke-WebRequest -Uri $feedUrl -UseBasicParsing).Content | |
| $nsMgr = New-Object System.Xml.XmlNamespaceManager($xml.NameTable) | |
| $nsMgr.AddNamespace("atom", "http://www.w3.org/2005/Atom") | |
| $nsMgr.AddNamespace("d", "http://schemas.microsoft.com/ado/2007/08/dataservices") | |
| $nsMgr.AddNamespace("m", "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata") | |
| $versions = @() | |
| foreach ($entry in $xml.SelectNodes("//atom:entry", $nsMgr)) { | |
| $versionNode = $entry.SelectSingleNode(".//m:properties/d:Version", $nsMgr) | |
| $approvedNode = $entry.SelectSingleNode(".//m:properties/d:PackageApprovedDate", $nsMgr) | |
| if (-not $versionNode -or -not $versionNode.'#text') { continue } | |
| $rawVersion = $versionNode.'#text'.Trim() | |
| try { | |
| $ver = [version]$rawVersion | |
| } | |
| catch { | |
| Write-Host "Skipping ${packageId} version '${rawVersion}' (invalid or prerelease format)" -ForegroundColor DarkYellow | |
| continue | |
| } | |
| if ($ver -le [version]$installedVersion) { continue } | |
| if ($approvedNode -and $approvedNode.'#text') { | |
| try { | |
| $approvalDate = [datetime]$approvedNode.'#text' | |
| } | |
| catch { | |
| Write-Warning "Invalid approval date for ${packageId} version ${ver}: '$($approvedNode.'#text')'" | |
| throw | |
| } | |
| $ageDays = (New-TimeSpan -Start $approvalDate -End (Get-Date)).Days | |
| $versions += [PSCustomObject]@{ | |
| Version = $ver | |
| ApprovalDate = $approvalDate | |
| Age = $ageDays | |
| } | |
| } | |
| else { | |
| Write-Host "Skipping ${packageId} version ${ver} (no approval date)" -ForegroundColor DarkYellow | |
| } | |
| } | |
| } | |
| catch { | |
| Write-Warning "Failed to fetch or parse versions for ${packageId} via API" | |
| throw | |
| } | |
| if (-not $versions) { | |
| Write-Host "No valid versions found for ${packageId} (currently ${installedVersion}). Skipping." -ForegroundColor DarkGray | |
| continue | |
| } | |
| $target = $versions | Where-Object { $_.Age -ge $MinAgeDays } | | |
| Sort-Object Version -Descending | Select-Object -First 1 | |
| if ($target) { | |
| Write-Host "`n${packageId} → Upgradable to $($target.Version) (approved $($target.Age) days ago)" -ForegroundColor Green | |
| if ($WhatIf) { | |
| Write-Host "[WhatIf] Would upgrade ${packageId} from ${installedVersion} to $($target.Version)" -ForegroundColor Green | |
| } | |
| else { | |
| $choice = Read-Host "Do you want to upgrade ${packageId} from ${installedVersion} to $($target.Version)? (y/n)" | |
| if ($choice -match '^(y|yes)$') { | |
| Write-Host "Upgrading ${packageId} ..." -ForegroundColor Green | |
| try { | |
| choco upgrade ${packageId} --yes --version=$($target.Version) | |
| } | |
| catch { | |
| Write-Warning "Failed to upgrade ${packageId}." | |
| throw | |
| } | |
| } | |
| else { | |
| Write-Host "Skipping ${packageId}." -ForegroundColor Yellow | |
| } | |
| } | |
| } | |
| else { | |
| Write-Host "`n${packageId} (currently ${installedVersion}) has no versions older than ${MinAgeDays} days or newer than installed version. Skipping." -ForegroundColor Yellow | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment