mirror of
https://github.com/appleboy/drone-ssh.git
synced 2026-06-16 14:49:25 +08:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 37b95a017d | |||
| 1fabfc4f97 | |||
| 883f947b4f | |||
| 2c52afb7fd | |||
| d56db7a5b3 | |||
| 67cd964f13 | |||
| 2519a9a894 | |||
| 1edb4744ca | |||
| 43270d582c | |||
| dc927a6123 | |||
| ceb4e12d92 |
@@ -14,6 +14,8 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup go
|
||||
uses: actions/setup-go@v5
|
||||
|
||||
@@ -31,7 +31,7 @@ jobs:
|
||||
testing:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: golang:1.22-alpine
|
||||
image: golang:1.23-alpine
|
||||
options: --sysctl net.ipv6.conf.all.disable_ipv6=0
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
run:
|
||||
timeout: 5m
|
||||
linters:
|
||||
enable:
|
||||
- asciicheck
|
||||
- durationcheck
|
||||
- errcheck
|
||||
- errorlint
|
||||
- exportloopref
|
||||
- gci
|
||||
- gofmt
|
||||
- goimports
|
||||
- gosec
|
||||
- misspell
|
||||
- nakedret
|
||||
- nilerr
|
||||
- nolintlint
|
||||
- perfsprint
|
||||
- revive
|
||||
- usestdlibvars
|
||||
- wastedassign
|
||||
|
||||
linters-settings:
|
||||
gosec:
|
||||
# To select a subset of rules to run.
|
||||
# Available rules: https://github.com/securego/gosec#available-rules
|
||||
# Default: [] - means include all rules
|
||||
includes:
|
||||
- G102
|
||||
- G106
|
||||
- G108
|
||||
- G109
|
||||
- G111
|
||||
- G112
|
||||
- G201
|
||||
- G203
|
||||
perfsprint:
|
||||
err-error: true
|
||||
errorf: true
|
||||
int-conversion: true
|
||||
sprintf1: true
|
||||
strconcat: true
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
FROM alpine:3.17
|
||||
FROM alpine:3.20
|
||||
|
||||
ARG TARGETOS
|
||||
ARG TARGETARCH
|
||||
|
||||
@@ -1,23 +1,24 @@
|
||||
module github.com/appleboy/drone-ssh
|
||||
|
||||
go 1.22
|
||||
go 1.23.0
|
||||
|
||||
require (
|
||||
github.com/appleboy/easyssh-proxy v1.5.0
|
||||
github.com/joho/godotenv v1.5.1
|
||||
github.com/stretchr/testify v1.8.4
|
||||
github.com/urfave/cli/v2 v2.27.2
|
||||
golang.org/x/crypto v0.25.0
|
||||
github.com/urfave/cli/v2 v2.27.5
|
||||
github.com/yassinebenaid/godump v0.11.1
|
||||
golang.org/x/crypto v0.36.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/ScaleFT/sshkeys v1.2.0 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/dchest/bcrypt_pbkdf v0.0.0-20150205184540-83f37f9c154a // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
|
||||
golang.org/x/sys v0.22.0 // indirect
|
||||
golang.org/x/sys v0.31.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
@@ -2,8 +2,8 @@ github.com/ScaleFT/sshkeys v1.2.0 h1:5BRp6rTVIhJzXT3VcUQrKgXR8zWA3sOsNeuyW15WUA8
|
||||
github.com/ScaleFT/sshkeys v1.2.0/go.mod h1:gxOHeajFfvGQh/fxlC8oOKBe23xnnJTif00IFFbiT+o=
|
||||
github.com/appleboy/easyssh-proxy v1.5.0 h1:OYdSPvYQN3mhnsMH5I2OF1TgwSEcSq33kvjQfTwvZww=
|
||||
github.com/appleboy/easyssh-proxy v1.5.0/go.mod h1:zcEMrStH91/tcUn3gUGP0KpQwUYLm8tX/Ook1AH98uc=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@@ -19,22 +19,24 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/urfave/cli/v2 v2.27.2 h1:6e0H+AkS+zDckwPCUrZkKX38mRaau4nL2uipkJpbkcI=
|
||||
github.com/urfave/cli/v2 v2.27.2/go.mod h1:g0+79LmHHATl7DAcHO99smiR/T7uGLw84w8Y42x+4eM=
|
||||
github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w=
|
||||
github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ=
|
||||
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4=
|
||||
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
|
||||
github.com/yassinebenaid/godump v0.11.1 h1:SPujx/XaYqGDfmNh7JI3dOyCUVrG0bG2duhO3Eh2EhI=
|
||||
github.com/yassinebenaid/godump v0.11.1/go.mod h1:dc/0w8wmg6kVIvNGAzbKH1Oa54dXQx8SNKh4dPRyW44=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
|
||||
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
|
||||
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
|
||||
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200219091948-cb0a6d8edb6c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
|
||||
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk=
|
||||
golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4=
|
||||
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
||||
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y=
|
||||
golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
easyssh "github.com/appleboy/easyssh-proxy"
|
||||
"github.com/joho/godotenv"
|
||||
"github.com/urfave/cli/v2"
|
||||
"github.com/yassinebenaid/godump"
|
||||
)
|
||||
|
||||
// Version set at compile-time
|
||||
@@ -131,6 +132,11 @@ func main() {
|
||||
Usage: "execute single commands for github action",
|
||||
EnvVars: []string{"INPUT_SCRIPT"},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "script.file",
|
||||
Usage: "execute commands from a file for github action",
|
||||
EnvVars: []string{"PLUGIN_SCRIPT_FILE", "INPUT_SCRIPT_FILE"},
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "script.stop",
|
||||
Usage: "stop script after first failure",
|
||||
@@ -207,7 +213,7 @@ func main() {
|
||||
&cli.BoolFlag{
|
||||
Name: "debug",
|
||||
Usage: "debug mode",
|
||||
EnvVars: []string{"PLUGIN_DEBUG", "INPUT_DEBUG"},
|
||||
EnvVars: []string{"PLUGIN_DEBUG", "INPUT_DEBUG", "DEBUG"},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "envs.format",
|
||||
@@ -271,6 +277,18 @@ func run(c *cli.Context) error {
|
||||
scripts = append(scripts, s)
|
||||
}
|
||||
|
||||
if f := c.String("script.file"); f != "" {
|
||||
// check file exists
|
||||
if _, err := os.Stat(f); err != nil {
|
||||
return err
|
||||
}
|
||||
s, err := os.ReadFile(f)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
scripts = append(scripts, string(s))
|
||||
}
|
||||
|
||||
plugin := Plugin{
|
||||
Config: Config{
|
||||
Key: c.String("ssh-key"),
|
||||
@@ -312,5 +330,9 @@ func run(c *cli.Context) error {
|
||||
Writer: os.Stdout,
|
||||
}
|
||||
|
||||
if plugin.Config.Debug {
|
||||
_ = godump.Dump(plugin)
|
||||
}
|
||||
|
||||
return plugin.Exec()
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ func (p Plugin) exec(host string, wg *sync.WaitGroup, errChannel chan error) {
|
||||
return
|
||||
}
|
||||
// read from the output channel until the done signal is passed
|
||||
isTimeout := true
|
||||
var isTimeout bool
|
||||
loop:
|
||||
for {
|
||||
select {
|
||||
@@ -145,11 +145,11 @@ loop:
|
||||
break loop
|
||||
case outline := <-stdoutChan:
|
||||
if outline != "" {
|
||||
p.log(host, "out:", outline)
|
||||
p.log(host, outline)
|
||||
}
|
||||
case errline := <-stderrChan:
|
||||
if errline != "" {
|
||||
p.log(host, "err:", errline)
|
||||
p.log(host, errline)
|
||||
}
|
||||
case err = <-errChan:
|
||||
}
|
||||
@@ -230,9 +230,9 @@ func (p Plugin) Exec() error {
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("==============================================")
|
||||
fmt.Println("✅ Successfully executed commands to all host.")
|
||||
fmt.Println("==============================================")
|
||||
fmt.Println("===============================================")
|
||||
fmt.Println("✅ Successfully executed commands to all hosts.")
|
||||
fmt.Println("===============================================")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
+25
-25
@@ -365,17 +365,17 @@ func TestCommandOutput(t *testing.T) {
|
||||
whoami
|
||||
uname
|
||||
localhost: ======END======
|
||||
localhost: out: /home/drone-scp
|
||||
localhost: out: drone-scp
|
||||
localhost: out: Linux
|
||||
localhost: /home/drone-scp
|
||||
localhost: drone-scp
|
||||
localhost: Linux
|
||||
127.0.0.1: ======CMD======
|
||||
127.0.0.1: pwd
|
||||
whoami
|
||||
uname
|
||||
127.0.0.1: ======END======
|
||||
127.0.0.1: out: /home/drone-scp
|
||||
127.0.0.1: out: drone-scp
|
||||
127.0.0.1: out: Linux
|
||||
127.0.0.1: /home/drone-scp
|
||||
127.0.0.1: drone-scp
|
||||
127.0.0.1: Linux
|
||||
`
|
||||
)
|
||||
|
||||
@@ -444,7 +444,7 @@ func TestFingerprint(t *testing.T) {
|
||||
var (
|
||||
buffer bytes.Buffer
|
||||
expected = `
|
||||
out: drone-scp
|
||||
drone-scp
|
||||
`
|
||||
)
|
||||
|
||||
@@ -475,7 +475,7 @@ func TestScriptStopWithMultipleHostAndSyncMode(t *testing.T) {
|
||||
var (
|
||||
buffer bytes.Buffer
|
||||
expected = `
|
||||
err: mkdir: can't create directory 'a/b/c': No such file or directory
|
||||
mkdir: can't create directory 'a/b/c': No such file or directory
|
||||
`
|
||||
)
|
||||
|
||||
@@ -506,7 +506,7 @@ func TestScriptStop(t *testing.T) {
|
||||
var (
|
||||
buffer bytes.Buffer
|
||||
expected = `
|
||||
err: mkdir: can't create directory 'a/b/c': No such file or directory
|
||||
mkdir: can't create directory 'a/b/c': No such file or directory
|
||||
`
|
||||
)
|
||||
|
||||
@@ -536,8 +536,8 @@ func TestNoneScriptStop(t *testing.T) {
|
||||
var (
|
||||
buffer bytes.Buffer
|
||||
expected = `
|
||||
err: mkdir: can't create directory 'a/b/c': No such file or directory
|
||||
err: mkdir: can't create directory 'd/e/f': No such file or directory
|
||||
mkdir: can't create directory 'a/b/c': No such file or directory
|
||||
mkdir: can't create directory 'd/e/f': No such file or directory
|
||||
`
|
||||
)
|
||||
|
||||
@@ -584,13 +584,13 @@ func TestEnvOutput(t *testing.T) {
|
||||
export ENV_6='test"'
|
||||
export ENV_7='test,!#;?.@$~'\''"'
|
||||
======END======
|
||||
out: [test]
|
||||
out: [test test]
|
||||
out: [test ]
|
||||
out: [ test test ]
|
||||
out: [test']
|
||||
out: [test"]
|
||||
out: [test,!#;?.@$~'"]
|
||||
[test]
|
||||
[test test]
|
||||
[test ]
|
||||
[ test test ]
|
||||
[test']
|
||||
[test"]
|
||||
[test,!#;?.@$~'"]
|
||||
`
|
||||
)
|
||||
|
||||
@@ -719,8 +719,8 @@ func TestUseInsecureCipher(t *testing.T) {
|
||||
var (
|
||||
buffer bytes.Buffer
|
||||
expected = `
|
||||
err: mkdir: can't create directory 'a/b/c': No such file or directory
|
||||
err: mkdir: can't create directory 'd/e/f': No such file or directory
|
||||
mkdir: can't create directory 'a/b/c': No such file or directory
|
||||
mkdir: can't create directory 'd/e/f': No such file or directory
|
||||
`
|
||||
)
|
||||
|
||||
@@ -871,9 +871,9 @@ func TestAllEnvs(t *testing.T) {
|
||||
var (
|
||||
buffer bytes.Buffer
|
||||
expected = `
|
||||
out: [foobar]
|
||||
out: [foobar]
|
||||
out: [foobar]
|
||||
[foobar]
|
||||
[foobar]
|
||||
[foobar]
|
||||
`
|
||||
)
|
||||
|
||||
@@ -915,7 +915,7 @@ func TestSudoCommand(t *testing.T) {
|
||||
var (
|
||||
buffer bytes.Buffer
|
||||
expected = `
|
||||
out: root
|
||||
root
|
||||
`
|
||||
)
|
||||
|
||||
@@ -942,7 +942,7 @@ func TestCommandWithIPv6(t *testing.T) {
|
||||
var (
|
||||
buffer bytes.Buffer
|
||||
expected = `
|
||||
out: drone-scp
|
||||
drone-scp
|
||||
`
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user