Skip to content

Commit

Permalink
feat: add self-update command (#778)
Browse files Browse the repository at this point in the history
* feat: add auto updater

* fix: query latest release

* feat: implement the upgrader

* fix: move upgrader to a specific folder

* ci: adjust CI to not include upgrader in npm and rubygems packages

* chore: add package description

* chore: add colors

* chore: simplify the look and feel of commands

* chore: small cosmetic changes

* chore: add backup recover on issues with file system

* test: add tests

* fix: special fix for windows
  • Loading branch information
mrexox authored Jul 23, 2024
1 parent d7ae5f7 commit 1f055b2
Show file tree
Hide file tree
Showing 17 changed files with 680 additions and 71 deletions.
78 changes: 57 additions & 21 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,59 @@ before:
hooks:
- go generate ./...
builds:
- env:
- CGO_ENABLED=0
goos:
- linux
- darwin
- windows
- freebsd
goarch:
- amd64
- arm64
- 386
ignore:
- goos: darwin
goarch: 386
- goos: linux
goarch: 386
- goos: freebsd
goarch: 386
ldflags:
- -s -w -X github.com/evilmartians/lefthook/internal/version.commit={{.Commit}}
# Builds the binaries without `lefthook upgrade`
- id: no_self_update
tags:
- no_self_update
env:
- GCO_ENABLED=0
goos:
- linux
- darwin
- windows
- freebsd
goarch:
- amd64
- arm64
- 386
ignore:
- goos: darwin
goarch: 386
- goos: linux
goarch: 386
- goos: freebsd
goarch: 386
ldflags:
- -s -w -X github.com/evilmartians/lefthook/internal/version.commit={{.Commit}}

# Full lefthook binary
- id: lefthook
env:
- CGO_ENABLED=0
goos:
- linux
- darwin
- windows
- freebsd
goarch:
- amd64
- arm64
- 386
ignore:
- goos: darwin
goarch: 386
- goos: linux
goarch: 386
- goos: freebsd
goarch: 386
ldflags:
- -s -w -X github.com/evilmartians/lefthook/internal/version.commit={{.Commit}}

archives:
- id: lefthook
format: binary
builds:
- lefthook
files:
- none*
name_template: >-
Expand All @@ -36,8 +66,11 @@ archives:
{{- if eq .Arch "amd64" }}x86_64
{{- else if eq .Arch "386" }}i386
{{- else }}{{ .Arch }}{{ end }}
- id: lefthook-gz
format: gz
builds:
- lefthook
files:
- none*
name_template: >-
Expand All @@ -48,10 +81,13 @@ archives:
{{- if eq .Arch "amd64" }}x86_64
{{- else if eq .Arch "386" }}i386
{{- else }}{{ .Arch }}{{ end }}
checksum:
name_template: '{{ .ProjectName }}_checksums.txt'

snapshot:
name_template: "{{ .Tag }}"

changelog:
sort: asc
filters:
Expand All @@ -78,7 +114,7 @@ nfpms:
file_name_template: '{{ .ProjectName }}_{{ .Version }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}'
homepage: https://github.com/evilmartians/lefthook
description: Lefthook a single dependency-free binary to manage all your git hooks that works with any language in any environment, and in all common team workflows
maintainer: Alexander Abroskin <arkweid@evilmartians.com>
maintainer: Evil Martians <lefthook@evilmartians.com>
license: MIT
vendor: Evil Martians
formats:
Expand Down
4 changes: 3 additions & 1 deletion cmd/add.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ import (
//go:embed add-doc.txt
var addDoc string

func newAddCmd(opts *lefthook.Options) *cobra.Command {
type add struct{}

func (add) New(opts *lefthook.Options) *cobra.Command {
args := lefthook.AddArgs{}

addHookCompletions := func(cmd *cobra.Command, args []string, toComplete string) (ret []string, compDir cobra.ShellCompDirective) {
Expand Down
23 changes: 23 additions & 0 deletions cmd/commands.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//go:build !no_self_update

package cmd

import (
"github.com/spf13/cobra"

"github.com/evilmartians/lefthook/internal/lefthook"
)

type command interface {
New(*lefthook.Options) *cobra.Command
}

var commands = [...]command{
version{},
add{},
install{},
uninstall{},
run{},
dump{},
selfUpdate{},
}
22 changes: 22 additions & 0 deletions cmd/commands_no_self_update.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//go:build no_self_update

package cmd

import (
"github.com/spf13/cobra"

"github.com/evilmartians/lefthook/internal/lefthook"
)

type command interface {
New(*lefthook.Options) *cobra.Command
}

var commands = [...]command{
version{},
add{},
install{},
uninstall{},
run{},
dump{},
}
4 changes: 3 additions & 1 deletion cmd/dump.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import (
"github.com/evilmartians/lefthook/internal/lefthook"
)

func newDumpCmd(opts *lefthook.Options) *cobra.Command {
type dump struct{}

func (dump) New(opts *lefthook.Options) *cobra.Command {
dumpArgs := lefthook.DumpArgs{}
dumpCmd := cobra.Command{
Use: "dump",
Expand Down
4 changes: 3 additions & 1 deletion cmd/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import (
"github.com/evilmartians/lefthook/internal/log"
)

func newInstallCmd(opts *lefthook.Options) *cobra.Command {
type install struct{}

func (install) New(opts *lefthook.Options) *cobra.Command {
var a, force bool

installCmd := cobra.Command{
Expand Down
11 changes: 1 addition & 10 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,6 @@ import (
"github.com/evilmartians/lefthook/internal/log"
)

var commands = [...]func(*lefthook.Options) *cobra.Command{
newVersionCmd,
newAddCmd,
newInstallCmd,
newUninstallCmd,
newRunCmd,
newDumpCmd,
}

func newRootCmd() *cobra.Command {
options := lefthook.Options{
Fs: afero.NewOsFs(),
Expand Down Expand Up @@ -61,7 +52,7 @@ func newRootCmd() *cobra.Command {
}

for _, subcommand := range commands {
rootCmd.AddCommand(subcommand(&options))
rootCmd.AddCommand(subcommand.New(&options))
}

return rootCmd
Expand Down
4 changes: 3 additions & 1 deletion cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import (
"github.com/evilmartians/lefthook/internal/log"
)

func newRunCmd(opts *lefthook.Options) *cobra.Command {
type run struct{}

func (run) New(opts *lefthook.Options) *cobra.Command {
runArgs := lefthook.RunArgs{}

runHookCompletions := func(cmd *cobra.Command, args []string, toComplete string) (ret []string, compDir cobra.ShellCompDirective) {
Expand Down
73 changes: 73 additions & 0 deletions cmd/self_update.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package cmd

import (
"context"
"fmt"
"os"
"os/signal"
"syscall"

"github.com/spf13/cobra"

"github.com/evilmartians/lefthook/internal/lefthook"
"github.com/evilmartians/lefthook/internal/log"
"github.com/evilmartians/lefthook/internal/updater"
)

type selfUpdate struct{}

func (selfUpdate) New(opts *lefthook.Options) *cobra.Command {
var yes bool
upgradeCmd := cobra.Command{
Use: "self-update",
Short: "Update lefthook executable",
Example: "lefthook self-update",
ValidArgsFunction: cobra.NoFileCompletions,
Args: cobra.NoArgs,
RunE: func(_cmd *cobra.Command, _args []string) error {
return update(opts, yes)
},
}

upgradeCmd.Flags().BoolVarP(&yes, "yes", "y", false, "no prompt")
upgradeCmd.Flags().BoolVarP(&opts.Force, "force", "f", false, "force upgrade")
upgradeCmd.Flags().BoolVarP(&opts.Verbose, "verbose", "v", false, "show verbose logs")

return &upgradeCmd
}

func update(opts *lefthook.Options, yes bool) error {
if os.Getenv(lefthook.EnvVerbose) == "1" || os.Getenv(lefthook.EnvVerbose) == "true" {
opts.Verbose = true
}
if opts.Verbose {
log.SetLevel(log.DebugLevel)
log.Debug("Verbose mode enabled")
}

ctx, cancel := context.WithCancel(context.Background())
defer cancel()

// Handle interrupts
signalChan := make(chan os.Signal, 1)
signal.Notify(
signalChan,
syscall.SIGINT,
syscall.SIGTERM,
)
go func() {
<-signalChan
cancel()
}()

exePath, err := os.Executable()
if err != nil {
return fmt.Errorf("failed to determine the binary path: %w", err)
}

return updater.New().SelfUpdate(ctx, updater.Options{
Yes: yes,
Force: opts.Force,
ExePath: exePath,
})
}
4 changes: 3 additions & 1 deletion cmd/uninstall.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import (
"github.com/evilmartians/lefthook/internal/lefthook"
)

func newUninstallCmd(opts *lefthook.Options) *cobra.Command {
type uninstall struct{}

func (uninstall) New(opts *lefthook.Options) *cobra.Command {
args := lefthook.UninstallArgs{}

uninstallCmd := cobra.Command{
Expand Down
8 changes: 5 additions & 3 deletions cmd/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ import (

"github.com/evilmartians/lefthook/internal/lefthook"
"github.com/evilmartians/lefthook/internal/log"
"github.com/evilmartians/lefthook/internal/version"
ver "github.com/evilmartians/lefthook/internal/version"
)

func newVersionCmd(_opts *lefthook.Options) *cobra.Command {
type version struct{}

func (version) New(_opts *lefthook.Options) *cobra.Command {
var verbose bool

versionCmd := cobra.Command{
Expand All @@ -17,7 +19,7 @@ func newVersionCmd(_opts *lefthook.Options) *cobra.Command {
ValidArgsFunction: cobra.NoFileCompletions,
Args: cobra.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
log.Println(version.Version(verbose))
log.Println(ver.Version(verbose))
},
}

Expand Down
9 changes: 7 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,20 @@ require (
github.com/mattn/go-tty v0.0.5
github.com/mitchellh/mapstructure v1.5.0
github.com/rogpeppe/go-internal v1.12.0
github.com/schollz/progressbar/v3 v3.14.4
github.com/spf13/afero v1.11.0
github.com/spf13/cobra v1.8.0
github.com/spf13/viper v1.19.0
github.com/stretchr/testify v1.9.0
gopkg.in/alessio/shellescape.v1 v1.0.0-20170105083845-52074bc9df61
)

require (
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/charmbracelet/x/ansi v0.1.1 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
Expand All @@ -49,8 +54,8 @@ require (
github.com/spf13/cast v1.6.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
golang.org/x/sys v0.19.0 // indirect
golang.org/x/term v0.15.0 // indirect
golang.org/x/sys v0.22.0 // indirect
golang.org/x/term v0.22.0 // indirect
golang.org/x/text v0.14.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v3 v3.0.1
Expand Down
Loading

0 comments on commit 1f055b2

Please sign in to comment.