Compare commits

...

11 Commits

Author SHA1 Message Date
appleboy 37b95a017d chore: upgrade Go and dependencies to improve compatibility
- Update Go version from 1.22 to 1.23
- Upgrade golang.org/x/crypto from version 0.29.0 to 0.36.0
- Upgrade golang.org/x/sys from version 0.27.0 to 0.31.0
- Change Docker image in GitHub Actions from golang:1.22-alpine to golang:1.23-alpine

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2025-03-09 21:43:05 +08:00
appleboy 1fabfc4f97 chore: implement debug functionality with godump integration
- Add a new dependency on `github.com/yassinebenaid/godump`
- Include `godump` in the import statements
- Add a new environment variable `DEBUG` to the existing list
- Implement a debug dump of the plugin if debugging is enabled

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2025-03-09 21:42:02 +08:00
Bo-Yi Wu 883f947b4f chore(log): remove prefix out: and err: prefix (#287)
- Simplify log output by removing "out:" and "err:" prefixes in `plugin.go`
- Update test expectations to match the new log output format

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2024-11-17 14:48:14 +08:00
appleboy 2c52afb7fd fix: improve script file handling and testing robustness
- Add a check to verify if the script file exists before reading it

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2024-11-17 14:32:06 +08:00
appleboy d56db7a5b3 chore(deps): update dependencies to latest versions
- Update `github.com/urfave/cli/v2` to version `2.27.5`
- Update `golang.org/x/crypto` to version `0.29.0`
- Update `github.com/cpuguy83/go-md2man/v2` to version `2.0.5`
- Update `golang.org/x/sys` to version `0.27.0`

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2024-11-17 14:18:47 +08:00
appleboy 67cd964f13 ci(github): improve CI workflows and API integration
- Add `fetch-depth: 0` to the `actions/checkout` step in the `goreleaser` GitHub workflow

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2024-11-16 10:05:31 +08:00
appleboy 2519a9a894 ci(golangci): enable comprehensive linting and update variable initialization
- Add a `.golangci.yaml` configuration file with various linters enabled and specific settings for `gosec` and `perfsprint`.
- Change `isTimeout` from being initialized to `true` to being declared as a `bool` variable without an initial value in `plugin.go`.

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2024-11-16 09:58:21 +08:00
appleboy 1edb4744ca feat(envs): support drone plugin
- Add `PLUGIN_SCRIPT_FILE` to the environment variables list in the main function

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2024-10-27 22:22:23 +08:00
Kyle Leonhard 43270d582c chore: add support for passing commands via a file (#285) 2024-10-24 09:56:07 +08:00
Lukáš Tesař dc927a6123 fix: typo in success message (#283)
My OCD just kicks in :)) This has bothered me for a long time. Will also update README in https://github.com/appleboy/ssh-action to reflect this change.
2024-10-13 09:00:20 +08:00
Bo-Yi Wu ceb4e12d92 chore: update base image to Alpine 3.20
- Update base image from alpine version 3.17 to 3.20

Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2024-09-07 15:15:40 +08:00
9 changed files with 118 additions and 49 deletions
+2
View File
@@ -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
+1 -1
View File
@@ -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
+42
View File
@@ -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
View File
@@ -1,4 +1,4 @@
FROM alpine:3.17
FROM alpine:3.20
ARG TARGETOS
ARG TARGETARCH
+6 -5
View File
@@ -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
)
+12 -10
View File
@@ -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=
+23 -1
View File
@@ -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()
}
+6 -6
View File
@@ -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
View File
@@ -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
`
)