/
upgrade.go
104 lines (89 loc) · 2.3 KB
/
upgrade.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
package upgrade
import (
"context"
"errors"
"fmt"
"io"
"net/http"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"github.com/apex/log"
"github.com/google/go-github/github"
kingpin "gopkg.in/alecthomas/kingpin.v2"
)
// New build command
func New(ctx context.Context, root *kingpin.Application, version string) {
cmd := root.Command("upgrade", "upgrade joy to the latest version")
cmd.Action(func(_ *kingpin.ParseContext) (err error) {
return upgrade(ctx, version)
})
}
// https://github.com/apex/apex/blob/master/upgrade/upgrade.go
// Thanks TJ
func upgrade(ctx context.Context, version string) (err error) {
log.Infof("current release is %s", version)
// fetch releases
gh := github.NewClient(nil)
releases, _, err := gh.Repositories.ListReleases(ctx, "matthewmueller", "joy", nil)
if err != nil {
return err
}
// see if it's new
latest := releases[0]
log.Infof("latest release is %s", *latest.TagName)
latestVersion := (*latest.TagName)[1:]
// TODO: ignore if semver
if latestVersion == version {
log.Infof("you're up to date :)")
return nil
}
asset := findAsset(latest)
if asset == nil {
return errors.New("cannot find binary for your system")
}
// get the executable's path
cmdPath, err := exec.LookPath("joy")
if err != nil {
return err
}
cmdDir := filepath.Dir(cmdPath)
// create tmp file
tmpPath := filepath.Join(cmdDir, "joy-upgrade")
f, err := os.OpenFile(tmpPath, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0755)
if err != nil {
return err
}
// download binary
log.Infof("downloading %s", *asset.BrowserDownloadURL)
res, err := http.Get(*asset.BrowserDownloadURL)
if err != nil {
return err
}
defer res.Body.Close()
// copy it down
_, err = io.Copy(f, res.Body)
if err != nil {
return err
}
// replace it
log.Infof("replacing %s", cmdPath)
err = os.Rename(tmpPath, cmdPath)
if err != nil {
return err
}
log.Infof("visit https://github.com/matthewmueller/joy/releases for the changelog")
return nil
}
// findAsset returns the binary for this platform.
func findAsset(release *github.RepositoryRelease) *github.ReleaseAsset {
for _, asset := range release.Assets {
version := strings.TrimPrefix(*release.TagName, "v")
if *asset.Name == fmt.Sprintf("joy_%s_%s_%s.tar.gz", version, runtime.GOOS, runtime.GOARCH) {
return &asset
}
}
return nil
}