feat(update): self-update notifications and auto-update - #45
Conversation
run/shell check GitHub for a newer opencode-sandbox release (throttled to update.interval, default 1d, minimum 1h). update.mode selects the behavior: prompt (default), notify, auto-upgrade, or auto-upgrade-exit. Add an 'upgrade' command for on-demand installs.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #45 +/- ##
==========================================
+ Coverage 88.73% 88.83% +0.10%
==========================================
Files 87 88 +1
Lines 5299 5553 +254
==========================================
+ Hits 4702 4933 +231
- Misses 414 431 +17
- Partials 183 189 +6 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
| if err != nil { | ||
| return err | ||
| } | ||
| if opencode.VersionCompare(version, latest) >= 0 { |
There was a problem hiding this comment.
Can we use semver module for comparing versions?
There was a problem hiding this comment.
Done - version comparison now uses github.com/Masterminds/semver/v3 via upgrade.isNewer, and opencode.NewerThan for the runner-image opencode upgrade path.
| Args: cobra.NoArgs, | ||
| Short: "Check for and install the latest release", | ||
| RunE: func(cmd *cobra.Command, _ []string) error { | ||
| if version == devVersion { |
There was a problem hiding this comment.
everything non-argparsing should be delegated to the update package
There was a problem hiding this comment.
Done - buildUpgradeCmd now only parses args; the non-argparsing logic lives in upgrade.Upgrade.
|
|
||
| --- | ||
|
|
||
| ### upgrade |
There was a problem hiding this comment.
update vs. upgrade naming clash. upgrade is better IMHO
There was a problem hiding this comment.
Renamed update->upgrade across the package, config keys (upgrade.mode/upgrade.interval), env vars, state file, and docs for consistent naming.
| The launcher validates: | ||
|
|
||
| - `cpus` must be between 0 and 255 | ||
| - `update.mode` must be one of `prompt`, `notify`, `auto-upgrade`, `auto-upgrade-exit` |
There was a problem hiding this comment.
auto-upgrade -> auto
autp-upgrade-exit -> auto-exit
There was a problem hiding this comment.
Done - the modes are now auto and auto-exit.
| return Result{}, nil | ||
| } | ||
| interval := opts.Interval | ||
| switch { |
There was a problem hiding this comment.
fail on misconfiguration, otherwise users might not understand why updates are not happening at their configured frequency
There was a problem hiding this comment.
Done - upgrade.Check now returns an error for an explicit sub-minimum interval instead of silently clamping it.
| // the same filesystem and therefore atomic. | ||
| func replaceExecutable(assetPath, exePath string) error { | ||
| //nolint:gosec // G302: the downloaded release binary must be executable | ||
| if err := os.Chmod(assetPath, 0o755); err != nil { |
There was a problem hiding this comment.
The user might have installed it with different permissions, we should preserve the ones from the old binary
There was a problem hiding this comment.
Done - replaceExecutable now preserves the old binary's mode instead of hardcoding 0o755.
- Rename update package/config to upgrade for consistent naming - Compare versions with Masterminds/semver instead of custom comparison - Delegate non-argparsing upgrade logic into the upgrade package - Shorten modes: auto-upgrade->auto, auto-upgrade-exit->auto-exit - Fail loudly on sub-minimum upgrade interval misconfiguration - Preserve the old binary's permissions when replacing it - Add tests covering previously-missing branches
Closes #31
Summary
Adds self-update support:
run/shellcheck GitHub for a newer opencode-sandbox release and optionally install it.Changes
internal/updatepackage:Check(queryreleases/latest, compare versions, throttle, act per mode),Update(downloadopencode-sandbox-<os>-<arch>asset + atomic replace over the running executable), and persisted state (last-check time + per-version dismissals).config.yaml+OPENCODE_SANDBOX_UPDATE_*env):update.mode(prompt|notify|auto-upgrade|auto-upgrade-exit, defaultprompt) andupdate.interval(default1d, minimum1hto guard against GitHub rate limits).upgradecommand for on-demand installs.run/shell(skipped on--dry-run);devbuilds and transient network failures are skipped silently; non-interactivepromptfalls back to a notice.docs/configuration.mdSelf-update section,docs/commands.md) andCHANGELOG.md.Testing
make checkpasses (fmt, golangci-lint 0 issues,go test ./...).updatepackage,viperconfigupdate config/validation, and CLIupgradetests.