multica/server/cmd/multica/cmd_update.go
LinYushen 606930725a
feat(daemon): support direct download update for non-Homebrew installs (#334)
* feat(daemon): support direct download update for non-Homebrew installs

Previously, CLI auto-update only worked for Homebrew installations. Non-brew
binaries would fail with "not installed via Homebrew". Now the daemon and
`multica update` fall back to downloading the release binary directly from
GitHub Releases when Homebrew is not detected.

Also fixes:
- Daemon restart now uses the current executable's absolute path instead of
  searching PATH, ensuring the updated binary is used
- Brew installs preserve the symlink path so the new Cellar version is picked up
- Daemon startup logs now include the CLI version
- Update UI auto-clears "restarting" status after 5s to show the new version

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): remove dead DetectNewBinaryPath and guard against nil latest version

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 15:38:06 +08:00

60 lines
1.7 KiB
Go

package main
import (
"fmt"
"os"
"strings"
"github.com/spf13/cobra"
"github.com/multica-ai/multica/server/internal/cli"
)
var updateCmd = &cobra.Command{
Use: "update",
Short: "Update multica to the latest version",
RunE: runUpdate,
}
func runUpdate(_ *cobra.Command, _ []string) error {
fmt.Fprintf(os.Stderr, "Current version: %s (commit: %s)\n", version, commit)
// Check latest version from GitHub.
latest, err := cli.FetchLatestRelease()
if err != nil {
fmt.Fprintf(os.Stderr, "Warning: could not check latest version: %v\n", err)
} else {
latestVer := strings.TrimPrefix(latest.TagName, "v")
currentVer := strings.TrimPrefix(version, "v")
if currentVer == latestVer {
fmt.Fprintln(os.Stderr, "Already up to date.")
return nil
}
fmt.Fprintf(os.Stderr, "Latest version: %s\n\n", latest.TagName)
}
// Detect installation method and update accordingly.
if cli.IsBrewInstall() {
fmt.Fprintln(os.Stderr, "Updating via Homebrew...")
output, err := cli.UpdateViaBrew()
if err != nil {
fmt.Fprintf(os.Stderr, "%s\n", output)
return fmt.Errorf("brew upgrade failed: %w\nYou can try manually: brew upgrade multica-ai/tap/multica", err)
}
fmt.Fprintln(os.Stderr, "Update complete.")
return nil
}
// Not installed via brew — download binary directly from GitHub Releases.
if latest == nil {
return fmt.Errorf("could not determine latest version; check https://github.com/multica-ai/multica/releases/latest")
}
targetVersion := latest.TagName
fmt.Fprintf(os.Stderr, "Downloading %s from GitHub Releases...\n", targetVersion)
output, err := cli.UpdateViaDownload(targetVersion)
if err != nil {
return fmt.Errorf("update failed: %w", err)
}
fmt.Fprintf(os.Stderr, "%s\nUpdate complete.\n", output)
return nil
}