feat(cli): add update command to install latest release#96
Conversation
📝 WalkthroughWalkthroughAdds a CLI self-update command that fetches the latest GitHub release, selects and downloads the OS-specific asset, replaces the running binary with a backup, and verifies installation. Also adds version comparison utilities with tests to compare semantic versions and pre-release suffixes. Changes
Sequence Diagram(s)sequenceDiagram
participant User as User/CLI
participant Update as Update Command
participant GitHub as GitHub API
participant FS as OS/Filesystem
participant Version as Version Module
User->>Update: run `update` (maybe --force)
Update->>GitHub: fetch latest release metadata
GitHub-->>Update: release info + assets
Update->>Version: compare current vs release TagName
Version-->>Update: comparison result
alt proceed with update
Update->>Update: select OS-specific asset URL
Update->>GitHub: download asset
GitHub-->>Update: binary stream
Update->>FS: write temp file & verify executability
alt verification passes
Update->>FS: backup current binary
Update->>FS: replace binary file (handle permissions)
Update->>FS: run new binary --version
FS-->>Update: version output
Update-->>User: report success
else verification fails
Update-->>User: report error & guidance
end
else up-to-date and not forced
Update-->>User: already latest
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In `@cmd/update.go`:
- Around line 257-264: The backup step currently ignores errors from
copyFile(targetPath, backupPath); change this so that if copyFile returns an
error you abort the update unless the error indicates the target binary does not
exist: after calling copyFile, check if err != nil and if os.IsNotExist(err)
then continue, otherwise return a wrapped error (e.g., fmt.Errorf("failed to
backup existing binary: %w", err)); keep the existing cleanup of backupPath on
failure but do not swallow copy errors for other cases.
- Around line 105-108: The code currently proceeds after printing "Verifying
downloaded binary..." but lacks a robust cryptographic integrity check before
executing/replacing the binary; implement and call a strong verification step in
the verifyBinary(tempFile) logic that performs either: 1) checksum validation
against a trusted checksum (e.g., SHA-256) retrieved from a signed/HTTPS-backed
source, or 2) signature verification using a known public key to verify a
detached or embedded signature; ensure verifyBinary returns a clear error on
mismatch and that the caller (the block around fmt.Println("Verifying downloaded
binary...") and the if err := verifyBinary(tempFile) ... ) aborts
replacement/execution on any verification failure and logs the verification
failure details (without exposing secrets) so the update is blocked when
integrity cannot be proven.
In `@internal/version/version.go`:
- Around line 29-37: The base-version comparison that currently uses string
comparison on v1Base and v2Base must be changed to numeric-segment comparison:
split v1Base and v2Base on '.' into slices, parse each segment to integers
(handle parse errors as 0 or return appropriate error), iterate corresponding
segments comparing ints, return -1/1 on first numeric difference, and if all
compared segments equal, treat the longer non-zero tail as greater (or equal if
all zeros). Update the comparison logic where v1Base/v2Base are used (the
version comparison function in internal/version/version.go) to perform this
numeric-segment compare instead of simple string < / > checks.
🧹 Nitpick comments (1)
internal/version/version_test.go (1)
12-24: Add tests for multi-digit base segments (e.g., 0.10.0 vs 0.2.0).These cases would prevent regressions on numeric base comparison.
✅ Suggested additions
{ {"same version", "v0.0.1-rc8", "v0.0.1-rc8", 0}, + {"0.10.0 > 0.2.0", "v0.10.0", "v0.2.0", 1}, + {"0.2.0 < 0.10.0", "v0.2.0", "v0.10.0", -1}, {"rc8 < rc9", "v0.0.1-rc8", "v0.0.1-rc9", -1},
Summary by CodeRabbit
New Features
Tests
✏️ Tip: You can customize this high-level summary in your review settings.