Skip to content
Draft
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: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ services:
<<: *base
environment:
LETS_CONFIG_DIR: ..
command: gotestsum --format testname -- ./... -coverprofile=coverage.out
entrypoint: gotestsum --format testname -- ./... -coverprofile=coverage.out

test-bats:
<<: *base
Expand Down
4 changes: 3 additions & 1 deletion lets.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ commands:
git push --tags

test-unit:
description: Run unit tests
description: |
Run unit tests
(-run TestCase to run one test)
depends: [build-lets-image]
cmd:
- docker-compose
Expand Down
2 changes: 1 addition & 1 deletion upgrade/registry/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ func (reg *GithubRegistry) DownloadReleaseBinary(
}

dstDir := fmt.Sprintf("%s.dir", dstPath)
// cleanup if something abd happens during download/extract/rename flow
// cleanup if something bad happens during download/extract/rename flow
defer os.RemoveAll(dstDir)

err = os.RemoveAll(dstDir)
Expand Down
26 changes: 23 additions & 3 deletions upgrade/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,11 +119,31 @@ func replaceBinaries(downloadPath string, executablePath string, backupPath stri
defer os.RemoveAll(downloadPath)
defer os.RemoveAll(backupPath)

err := os.Rename(downloadPath, executablePath)
newBinary, err := os.Open(downloadPath)
defer newBinary.Close()

if err != nil {
// restore original file from backup
err := os.Rename(backupPath, executablePath)
return fmt.Errorf("failed to open new lets binary: %w", err)
}

currentBinary, err := os.OpenFile(executablePath, os.O_WRONLY, 0755)
defer currentBinary.Close()

if err != nil {
return fmt.Errorf("failed to open current lets binary: %w", err)
}

_, err = io.Copy(currentBinary, newBinary)
if err != nil {
backupBinary, err := os.Open(backupPath)
defer backupBinary.Close()

if err != nil {
return fmt.Errorf("failed to open backup lets binary: %w", err)
}

// restore original file from backup
_, err = io.Copy(currentBinary, backupBinary)
return fmt.Errorf("failed to update lets binary: %w", err)
}

Expand Down
49 changes: 49 additions & 0 deletions upgrade/upgrade_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,28 @@ func (m MockRegistry) GetDownloadURL(repoURI string, packageName string, version
return ""
}

type BadRegistry struct {
latestVersion string
}

func (b BadRegistry) GetLatestRelease() (string, error) {
return b.latestVersion, nil

}

func (b BadRegistry) DownloadReleaseBinary(packageName string, version string, dstPath string) error {
// do not create file at all
return nil
}

func (b BadRegistry) GetPackageName(os string, arch string) (string, error) {
return "lets_test_package", nil
}

func (b BadRegistry) GetDownloadURL(repoURI string, packageName string, version string) string {
return ""
}

func createTempBinary(content string) (*os.File, error) {
binary, err := os.CreateTemp("", "lets.*.current")
if err != nil {
Expand Down Expand Up @@ -106,6 +128,33 @@ func TestSelfUpgrade(t *testing.T) {
}
})

// TODO use https://github.com/spf13/afero#using-afero-for-testing
// TODO or use https://godocs.io/testing/fstest
// TODO or https://github.com/blang/vfs
// info https://stackoverflow.com/questions/16742331/how-to-mock-abstract-filesystem-in-go
//t.Run("should restore original binary if upgrade failed", func(t *testing.T) {
// currentVersion := "v0.0.1"
// latestVersion := "v0.0.2"
//
// upgrader, err := newMockUpgrader(&BadRegistry{latestVersion: latestVersion}, currentVersion)
// if err != nil {
// t.Errorf("failed to create upgrader: %s", err)
// }
//
// if !testVersion(upgrader.binaryPath, currentVersion) {
// t.Errorf("expected version %s", currentVersion)
// }
//
// err = upgrader.Upgrade()
// if err == nil {
// t.Errorf("expected some error if upgrade failed")
// }
//
// if !testVersion(upgrader.binaryPath, currentVersion) {
// t.Errorf("expected to preserv current binary version %s", currentVersion)
// }
//})

t.Run("should not self-upgrade same version", func(t *testing.T) {
currentVersion := "v0.0.1"
latestVersion := "v0.0.1"
Expand Down