Skip to content

Commit b5bdd62

Browse files
committed
feat(workflow-cli): add update cmd
1 parent 811e7d3 commit b5bdd62

8 files changed

Lines changed: 185 additions & 3 deletions

File tree

cmd/cmd.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,8 @@ type Commander interface {
111111
TLSAutoEnable(string) error
112112
TLSAutoDisable(string) error
113113
TLSAutoIssuer(string, string, string, string, string) error
114-
UsersList(results int) error
114+
Update(bool) error
115+
UsersList(int) error
115116
UsersEnable(string) error
116117
UsersDisable(string) error
117118
Println(...interface{}) (int, error)

cmd/update.go

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package cmd
2+
3+
import (
4+
"fmt"
5+
"io"
6+
"net/http"
7+
"runtime"
8+
"strings"
9+
10+
"github.com/drycc/workflow-cli/version"
11+
"github.com/minio/selfupdate"
12+
)
13+
14+
const WorkflowCliURL = "https://www.drycc.cc/workflow-cli.txt"
15+
16+
func (d *DryccCmd) latestVersion() (string, string, error) {
17+
d.Print("Get the latest version of workflow cli... ")
18+
quit := progress(d.WOut)
19+
resp, err := http.Get(WorkflowCliURL)
20+
quit <- true
21+
<-quit
22+
if err != nil {
23+
return "", "", err
24+
}
25+
d.Println("done")
26+
27+
defer resp.Body.Close()
28+
body, err := io.ReadAll(resp.Body)
29+
if err != nil {
30+
return "", "", err
31+
}
32+
prefix := "drycc-"
33+
suffix := fmt.Sprintf("-%s-%s", runtime.GOOS, runtime.GOARCH)
34+
for _, url := range strings.Split(string(body), "\n") {
35+
if strings.HasSuffix(url, suffix) {
36+
names := strings.Split(url, "/")
37+
name := names[len(names)-1]
38+
version := strings.ReplaceAll(strings.ReplaceAll(name, suffix, ""), prefix, "")
39+
return version, url, nil
40+
}
41+
}
42+
return "", "", fmt.Errorf("unable to obtain version: %s, %s", runtime.GOOS, runtime.GOARCH)
43+
}
44+
45+
// Update workflow-cli to latest release
46+
func (d *DryccCmd) Update(dryRun bool) error {
47+
latestVersion, downloadURL, err := d.latestVersion()
48+
if err != nil {
49+
return err
50+
}
51+
if latestVersion != version.Version {
52+
d.Printf("Update workflow cli from %s to %s... ", version.Version, latestVersion)
53+
if dryRun {
54+
d.Println("skip")
55+
} else {
56+
resp, err := http.Get(downloadURL)
57+
if err != nil {
58+
return err
59+
}
60+
defer resp.Body.Close()
61+
quit := progress(d.WOut)
62+
err = selfupdate.Apply(resp.Body, selfupdate.Options{})
63+
quit <- true
64+
<-quit
65+
if err != nil {
66+
return err
67+
}
68+
d.Println("done")
69+
}
70+
} else {
71+
d.Println("You are already running the most recent version.")
72+
}
73+
return nil
74+
}

drycc.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,9 @@ Subcommands, use 'drycc help [subcommand]' to learn more:
7373
tags manage tags for application containers
7474
timeouts manage pods termination grace period
7575
tls manage TLS settings for applications
76-
tokens manage tokens
77-
users manage users
76+
tokens manage user tokens
77+
update update workflow cli to latest release
78+
users manage registered users
7879
version display client version
7980
volumes manage volumes for your applications
8081
@@ -169,6 +170,8 @@ Use 'git push drycc main' to deploy to an application.
169170
err = parser.Tags(argv, &cmdr)
170171
case "tls":
171172
err = parser.TLS(argv, &cmdr)
173+
case "update":
174+
err = parser.Update(argv, &cmdr)
172175
case "users":
173176
err = parser.Users(argv, &cmdr)
174177
case "tokens":

go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ require (
77
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815
88
github.com/drycc/controller-sdk-go v0.0.0-20240814100555-0168972aa222
99
github.com/drycc/pkg v0.0.0-20240225112316-78fc9239f51f
10+
github.com/minio/selfupdate v0.6.0
1011
github.com/olekukonko/tablewriter v0.0.5
1112
github.com/schollz/progressbar/v3 v3.14.4
1213
github.com/stretchr/testify v1.9.0
@@ -17,11 +18,13 @@ require (
1718
)
1819

1920
require (
21+
aead.dev/minisign v0.2.0 // indirect
2022
github.com/davecgh/go-spew v1.1.1 // indirect
2123
github.com/mattn/go-runewidth v0.0.9 // indirect
2224
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
2325
github.com/pmezard/go-difflib v1.0.0 // indirect
2426
github.com/rivo/uniseg v0.4.7 // indirect
27+
golang.org/x/crypto v0.21.0 // indirect
2528
golang.org/x/sys v0.20.0 // indirect
2629
golang.org/x/term v0.20.0 // indirect
2730
)

go.sum

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
aead.dev/minisign v0.2.0 h1:kAWrq/hBRu4AARY6AlciO83xhNnW9UaC8YipS2uhLPk=
2+
aead.dev/minisign v0.2.0/go.mod h1:zdq6LdSd9TbuSxchxwhpA9zEb9YXcVGoE8JakuiGaIQ=
13
github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro=
24
github.com/containerd/console v1.0.4/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk=
35
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -15,6 +17,8 @@ github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1
1517
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
1618
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
1719
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
20+
github.com/minio/selfupdate v0.6.0 h1:i76PgT0K5xO9+hjzKcacQtO7+MjJ4JKA8Ak8XQ9DDwU=
21+
github.com/minio/selfupdate v0.6.0/go.mod h1:bO02GTIPCMQFTEvE5h4DjYB58bCoZ35XLeBf0buTDdM=
1822
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ=
1923
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw=
2024
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
@@ -29,16 +33,34 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
2933
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
3034
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
3135
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
36+
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
37+
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
38+
golang.org/x/crypto v0.0.0-20211209193657-4570a0811e8b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
39+
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
40+
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
3241
golang.org/x/exp v0.0.0-20240213143201-ec583247a57a h1:HinSgX1tJRX3KsL//Gxynpw5CTOAIPhgL4W8PNiIpVE=
3342
golang.org/x/exp v0.0.0-20240213143201-ec583247a57a/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc=
43+
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
44+
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
3445
golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
3546
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
47+
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
48+
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
49+
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
50+
golang.org/x/sys v0.0.0-20210228012217-479acdf4ea46/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
51+
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
52+
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
3653
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
3754
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
3855
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
3956
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
57+
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
58+
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
4059
golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw=
4160
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
61+
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
62+
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
63+
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
4264
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
4365
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
4466
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

parser/update.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package parser
2+
3+
import (
4+
docopt "github.com/docopt/docopt-go"
5+
"github.com/drycc/workflow-cli/cmd"
6+
)
7+
8+
// Version displays the client version
9+
func Update(argv []string, cmdr cmd.Commander) error {
10+
usage := `
11+
Update workflow cli to latest release.
12+
13+
Usage: drycc update [options]
14+
15+
Options:
16+
-p --dry-run
17+
simulate an update, only print the version info
18+
`
19+
args, err := docopt.ParseArgs(usage, argv, "")
20+
if err != nil {
21+
return err
22+
}
23+
return cmdr.Update(safeGetBool(args, "--dry-run"))
24+
}

parser/update_test.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package parser
2+
3+
import (
4+
"bytes"
5+
"errors"
6+
"testing"
7+
8+
"github.com/drycc/workflow-cli/pkg/testutil"
9+
"github.com/stretchr/testify/assert"
10+
)
11+
12+
// Create fake implementations of each method that return the argument
13+
// we expect to have called the function (as an error to satisfy the interface).
14+
15+
func (d FakeDryccCmd) Update(bool) error {
16+
return errors.New("update")
17+
}
18+
19+
func TestUpdate(t *testing.T) {
20+
t.Parallel()
21+
22+
cf, server, err := testutil.NewTestServerAndClient()
23+
if err != nil {
24+
t.Fatal(err)
25+
}
26+
defer server.Close()
27+
var b bytes.Buffer
28+
cmdr := FakeDryccCmd{WOut: &b, ConfigFile: cf}
29+
30+
// cases defines the arguments and expected return of the call.
31+
// if expected is "", it defaults to args[0].
32+
cases := []struct {
33+
args []string
34+
expected string
35+
}{
36+
{
37+
args: []string{"update"},
38+
expected: "",
39+
},
40+
}
41+
42+
// For each case, check that calling the route with the arguments
43+
// returns the expected error, which is args[0] if not provided.
44+
for _, c := range cases {
45+
var expected string
46+
if c.expected == "" {
47+
expected = c.args[0]
48+
} else {
49+
expected = c.expected
50+
}
51+
err = Update(c.args, cmdr)
52+
assert.Error(t, errors.New(expected), err)
53+
}
54+
}

scripts/build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ go-build(){
77
go build \
88
-o _dist/drycc-$1-$GOOS-$GOARCH \
99
drycc.go
10+
upx --lzma --best _dist/drycc-$1-$GOOS-$GOARCH
1011
}
1112

1213
GOOS_LIST=("linux" "windows" "darwin")

0 commit comments

Comments
 (0)