mirror of
https://github.com/lukaszraczylo/harness-sync.git
synced 2026-10-12 00:45:22 +00:00
feat(cli): add update subcommand for in-place self-update
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
const installURL = "https://raw.githubusercontent.com/lukaszraczylo/harness-sync/main/install.sh"
|
||||
|
||||
// NewUpdate returns the `update` subcommand. It downloads and installs the
|
||||
// latest harness-sync release into the same directory the running binary
|
||||
// lives in.
|
||||
func NewUpdate() *cobra.Command {
|
||||
var (
|
||||
dryRun bool
|
||||
dir string
|
||||
)
|
||||
cmd := &cobra.Command{
|
||||
Use: "update",
|
||||
Short: "Download and install the latest harness-sync release in place",
|
||||
RunE: func(cmd *cobra.Command, _ []string) error {
|
||||
if dir == "" {
|
||||
exe, err := os.Executable()
|
||||
if err != nil {
|
||||
return fmt.Errorf("resolve current binary path: %w", err)
|
||||
}
|
||||
resolved, err := filepath.EvalSymlinks(exe)
|
||||
if err == nil {
|
||||
exe = resolved
|
||||
}
|
||||
dir = filepath.Dir(exe)
|
||||
}
|
||||
pipeline := fmt.Sprintf("curl -fsSL %q | INSTALL_DIR=%q bash", installURL, dir)
|
||||
if _, err := fmt.Fprintf(cmd.OutOrStdout(), "Installing latest harness-sync into %s\n", dir); err != nil {
|
||||
return err
|
||||
}
|
||||
if dryRun {
|
||||
_, err := fmt.Fprintln(cmd.OutOrStdout(), pipeline)
|
||||
return err
|
||||
}
|
||||
sh := exec.Command("/bin/bash", "-c", pipeline)
|
||||
sh.Stdout = cmd.OutOrStdout()
|
||||
sh.Stderr = cmd.ErrOrStderr()
|
||||
return sh.Run()
|
||||
},
|
||||
}
|
||||
cmd.Flags().BoolVar(&dryRun, "dry-run", false, "print the install command without executing it")
|
||||
cmd.Flags().StringVar(&dir, "install-dir", "", "override install directory (default: dir of running binary)")
|
||||
return cmd
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestUpdateDryRunPrintsCommand(t *testing.T) {
|
||||
cmd := NewUpdate()
|
||||
var buf bytes.Buffer
|
||||
cmd.SetOut(&buf)
|
||||
cmd.SetErr(&buf)
|
||||
cmd.SetArgs([]string{"--dry-run", "--install-dir", "/tmp/test-dir"})
|
||||
require.NoError(t, cmd.Execute())
|
||||
|
||||
out := buf.String()
|
||||
assert.Contains(t, out, "Installing latest harness-sync into /tmp/test-dir")
|
||||
assert.Contains(t, out, "curl -fsSL")
|
||||
assert.Contains(t, out, "install.sh")
|
||||
assert.Contains(t, out, "INSTALL_DIR=")
|
||||
// Should NOT have run anything
|
||||
assert.False(t, strings.Contains(out, "[INFO]"), "dry run must not invoke install.sh")
|
||||
}
|
||||
|
||||
func TestUpdateResolvesCurrentBinaryDirByDefault(t *testing.T) {
|
||||
cmd := NewUpdate()
|
||||
var buf bytes.Buffer
|
||||
cmd.SetOut(&buf)
|
||||
cmd.SetArgs([]string{"--dry-run"})
|
||||
require.NoError(t, cmd.Execute())
|
||||
|
||||
// Should mention SOME absolute path (the test binary's directory)
|
||||
out := buf.String()
|
||||
assert.Contains(t, out, "Installing latest harness-sync into /")
|
||||
}
|
||||
Reference in New Issue
Block a user