Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ title: Changelog

## [Unreleased](https://github.com/lets-cli/lets/releases/tag/v0.0.X)

* `[Fixed]` Prevent `lets self upgrade` from overwriting Homebrew-managed installs. Issue [#338](https://github.com/lets-cli/lets/issues/338)

## [0.0.60](https://github.com/lets-cli/lets/releases/tag/v0.0.60)

* `[Dependency]` update go to `1.26`
Expand Down
4 changes: 4 additions & 0 deletions internal/upgrade/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ func NewBinaryUpgrader(reg registry.RepoRegistry, currentVersion string) (*Binar
}

func (up *BinaryUpgrader) Upgrade(ctx context.Context) error {
if isHomebrewInstall(up.binaryPath) {
return fmt.Errorf("homebrew-managed lets install must be upgraded with %q", "brew upgrade lets-cli/tap/lets")
}

latestVersion, err := up.registry.GetLatestRelease(ctx)
if err != nil {
return fmt.Errorf("failed to get latest release version: %w", err)
Expand Down
41 changes: 41 additions & 0 deletions internal/upgrade/upgrade_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"os"
"path"
"strings"
"testing"
"time"

Expand Down Expand Up @@ -144,4 +145,44 @@ func TestSelfUpgrade(t *testing.T) {
t.Errorf("binary must not been updated")
}
})

t.Run("should not self-upgrade homebrew-managed binary", func(t *testing.T) {
currentVersion := "v0.0.1"
latestVersion := "v0.0.2"

tempDir := t.TempDir()
binaryPath := path.Join(tempDir, "Cellar", "lets", currentVersion, "bin", "lets")
if err := os.MkdirAll(path.Dir(binaryPath), 0o755); err != nil {
t.Fatalf("failed to create homebrew binary dir: %s", err)
}

if err := os.WriteFile(binaryPath, []byte(currentVersion), 0o755); err != nil {
t.Fatalf("failed to write homebrew binary: %s", err)
}

upgrader := &BinaryUpgrader{
registry: &MockRegistry{latestVersion: latestVersion},
currentVersion: currentVersion,
binaryPath: binaryPath,
downloadPath: path.Join(tempDir, "lets.download"),
backupPath: path.Join(tempDir, "lets.backup"),
}

err := upgrader.Upgrade(context.Background())
if err == nil {
t.Fatal("expected homebrew upgrade error")
}

if !strings.Contains(err.Error(), "brew upgrade lets-cli/tap/lets") {
t.Fatalf("expected homebrew upgrade command in error, got %q", err.Error())
}

if !testVersion(binaryPath, currentVersion) {
t.Errorf("expected version %s", currentVersion)
}

if _, err := os.Stat(upgrader.downloadPath); !os.IsNotExist(err) {
t.Fatalf("expected no downloaded binary, got err %v", err)
}
})
}
Loading