0
0
mirror of https://github.com/thegeeklab/wp-plugin-go.git synced 2024-06-02 18:39:40 +02:00

Compare commits

...

28 Commits
v1.7.0 ... main

Author SHA1 Message Date
renovate[bot]
07d29586c9 chore(deps): update dependency golangci/golangci-lint to v1.59.0 2024-05-27 04:17:42 +00:00
renovate[bot]
ec3b3263f8
fix(deps): update module github.com/rs/zerolog to v1.33.0 (#84)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-24 09:38:23 +02:00
renovate[bot]
dfbeaf935f chore(deps): update dependency golangci/golangci-lint to v1.58.2 2024-05-20 14:10:22 +00:00
e5e67d464c
fix: dont handle LookPath in Command wrapper 2024-05-17 11:10:39 +02:00
119641f63a
fix: dont set stdout and stderr by default 2024-05-17 10:37:15 +02:00
23eca50904
bump major 2024-05-17 10:10:57 +02:00
6be7f2b898
refactor: rework plugin cmd (#82)
BREAKING CHANGE: `types.Cmd` was moved to `exec.Cmd` and the `Private` field from the struct was removed. The filed `Trace` is now a bool field instead of a bool pointer, and the helper method `SetTrace` was also removed.

BREAKING CHANGE: The method `trace.Cmd` was removed, please use the `Trace` field of `exec.Cmd`.
2024-05-17 09:39:33 +02:00
renovate[bot]
e2bc944f1f chore(deps): update dependency golangci/golangci-lint to v1.58.1 2024-05-13 04:39:38 +00:00
085ee0d15a
ci: fix golangci-lint deprecations 2024-05-12 11:08:23 +02:00
5e6b213c13
fix: fix global logger setup (#80) 2024-05-07 10:10:59 +02:00
renovate[bot]
5ca8c9ac0e
fix(deps): update module golang.org/x/net to v0.25.0 (#79)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-06 21:29:08 +02:00
df36058fa9
feat: add GetUserHomeDir and WriteTmpFile (#78) 2024-05-06 14:27:56 +02:00
renovate[bot]
c48fbf9bd7 chore(deps): update dependency golangci/golangci-lint to v1.58.0 2024-05-06 03:07:14 +00:00
d2c3493d68
fix: fix IsDirEmpty and add tests (#76) 2024-05-05 16:53:03 +02:00
211b38e908
feat: add new helper function IsDirEmpty (#75) 2024-05-05 16:33:21 +02:00
renovate[bot]
3cb24ef473
fix(deps): update module golang.org/x/sys to v0.20.0 (#73)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-05 16:29:28 +02:00
830d37fa00
feat: overwrite Cmd.Run to set defaults (#74) 2024-05-05 16:29:17 +02:00
25469ebab3
feat: add new helper function IsDir (#72) 2024-05-05 14:56:07 +02:00
7143086616
feat: add custom type Cmd (#71) 2024-05-05 14:55:58 +02:00
8ad911886e
fix: print version with newline (#70) 2024-05-04 15:50:28 +02:00
fc2102453c
bump module major version 2024-05-04 14:13:52 +02:00
f381a5e6ba
fix: rename SkipVerify to InsecureSkipVerify (#69)
BREAKING CHANGE: The struct field `Network.SkipVerify` was renamed to `Network.InsecureSkipVerify`.
2024-05-04 13:55:56 +02:00
35072e3425
feat: add option to hide woodpecker system flags (#68) 2024-05-03 22:51:11 +02:00
renovate[bot]
86776b673a
fix(deps): update module github.com/urfave/cli/v2 to v2.27.2 (#67)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-29 10:26:04 +02:00
renovate[bot]
b0a1901a24
fix(deps): update module golang.org/x/net to v0.24.0 (#65)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-20 14:27:27 +02:00
renovate[bot]
d0c70f927c
fix(deps): update module golang.org/x/net to v0.23.0 [security] (#66)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-20 14:20:50 +02:00
renovate[bot]
298d61949a chore(deps): update dependency golangci/golangci-lint to v1.57.2 2024-04-01 03:51:00 +00:00
renovate[bot]
bed6ac8b2b chore(deps): update dependency golangci/golangci-lint to v1.57.1 2024-03-25 05:12:15 +00:00
19 changed files with 471 additions and 78 deletions

View File

@ -23,7 +23,6 @@ linters:
- errchkjson
- errname
- errorlint
- execinquery
- exhaustive
- exportloopref
- forcetypeassert
@ -37,12 +36,12 @@ linters:
- gocyclo
- godot
# - godox
- goerr113
- err113
- gofmt
- gofumpt
- goheader
- goimports
- gomnd
- mnd
- gomoddirectives
- gomodguard
- goprintffuncname

View File

@ -1,7 +1,7 @@
# renovate: datasource=github-releases depName=mvdan/gofumpt
GOFUMPT_PACKAGE_VERSION := v0.6.0
# renovate: datasource=github-releases depName=golangci/golangci-lint
GOLANGCI_LINT_PACKAGE_VERSION := v1.56.2
GOLANGCI_LINT_PACKAGE_VERSION := v1.59.0
GO ?= go
PACKAGES ?= $(shell go list ./...)

View File

@ -9,7 +9,7 @@ import (
"sort"
"strings"
wp_template "github.com/thegeeklab/wp-plugin-go/template"
plugin_template "github.com/thegeeklab/wp-plugin-go/v3/template"
"github.com/urfave/cli/v2"
)
@ -40,7 +40,7 @@ var templateFs embed.FS
func ToMarkdown(app *cli.App) (string, error) {
var w bytes.Buffer
tpls, err := template.New("cli").Funcs(wp_template.LoadFuncMap()).ParseFS(templateFs, "**/*.tmpl")
tpls, err := template.New("cli").Funcs(plugin_template.LoadFuncMap()).ParseFS(templateFs, "**/*.tmpl")
if err != nil {
return "", err
}

50
exec/command.go Normal file
View File

@ -0,0 +1,50 @@
package exec
import (
"fmt"
"io"
"os"
"os/exec"
"strings"
"golang.org/x/sys/execabs"
)
// Cmd represents a command to be executed, with options to control its behavior.
// The Cmd struct embeds the standard library's exec.Cmd, adding additional fields
// to control the command's output and tracing.
type Cmd struct {
*exec.Cmd
Trace bool // Print composed command before execution.
TraceWriter io.Writer // Where to write the trace output.
}
// Run runs the command and waits for it to complete.
// If there is an error starting the command, it is returned.
// Otherwise, the command is waited for and its exit status is returned.
func (c *Cmd) Run() error {
if c.Trace {
fmt.Fprintf(c.TraceWriter, "+ %s\n", strings.Join(c.Args, " "))
}
if err := c.Start(); err != nil {
return err
}
return c.Wait()
}
// Command creates a new Cmd with the given name and arguments. The Cmd is configured
// with Trace set to true and TraceWriter set to os.Stdout. The Cmd's Env is set
// to the current environment.
func Command(name string, arg ...string) *Cmd {
cmd := &Cmd{
Cmd: execabs.Command(name, arg...),
Trace: true,
TraceWriter: os.Stdout,
}
cmd.Env = os.Environ()
return cmd
}

103
exec/command_test.go Normal file
View File

@ -0,0 +1,103 @@
package exec
import (
"bytes"
"os/exec"
"testing"
"github.com/stretchr/testify/assert"
)
func TestCmdRun(t *testing.T) {
tests := []struct {
name string
cmd *Cmd
wantErr bool
wantStdout string
wantStderr string
wantTrace string
}{
{
name: "trace enabled",
cmd: &Cmd{
Trace: true,
Cmd: &exec.Cmd{
Path: "/usr/bin/echo",
Args: []string{"echo", "hello"},
},
},
wantTrace: "+ echo hello\n",
wantStdout: "hello\n",
},
{
name: "trace disabled",
cmd: &Cmd{
Trace: false,
Cmd: &exec.Cmd{
Path: "/usr/bin/echo",
Args: []string{"echo", "hello"},
},
},
wantStdout: "hello\n",
},
{
name: "custom env",
cmd: &Cmd{
Trace: true,
Cmd: &exec.Cmd{
Path: "/bin/sh",
Args: []string{"sh", "-c", "echo $TEST"},
Env: []string{"TEST=1"},
},
},
wantTrace: "+ sh -c echo $TEST\n",
wantStdout: "1\n",
},
{
name: "custom stderr",
cmd: &Cmd{
Trace: true,
Cmd: &exec.Cmd{
Path: "/bin/sh",
Args: []string{"sh", "-c", "echo error >&2"},
Stderr: new(bytes.Buffer),
},
},
wantTrace: "+ sh -c echo error >&2\n",
wantStderr: "error\n",
},
{
name: "error",
cmd: &Cmd{
Trace: true,
Cmd: &exec.Cmd{
Path: "/invalid/path",
},
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
traceBuf := new(bytes.Buffer)
stdoutBuf := new(bytes.Buffer)
stderrBuf := new(bytes.Buffer)
tt.cmd.TraceWriter = traceBuf
tt.cmd.Stdout = stdoutBuf
tt.cmd.Stderr = stderrBuf
err := tt.cmd.Run()
if tt.wantErr {
assert.Error(t, err)
return
}
assert.NoError(t, err)
assert.Equal(t, tt.wantTrace, traceBuf.String())
assert.Equal(t, tt.wantStdout, stdoutBuf.String())
assert.Equal(t, tt.wantStderr, stderrBuf.String())
})
}
}

54
file/dir.go Normal file
View File

@ -0,0 +1,54 @@
package file
import (
"errors"
"io"
"os"
)
// DeleteDir deletes the directory at the given path.
// It returns nil if the deletion succeeds, or the deletion error otherwise.
// If the directory does not exist, DeleteDir returns nil.
func DeleteDir(path string) error {
if _, err := os.Stat(path); os.IsNotExist(err) {
return nil
}
return os.Remove(path)
}
// IsDir returns whether the given path is a directory. If the path does not exist, it returns (false, nil).
// If there is an error checking the path, it returns (false, err).
func IsDir(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil {
return true, nil
}
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
// IsDirEmpty checks if the directory at the given path is empty.
// It returns true if the directory is empty, false if not empty, or an error if there was a problem checking it.
func IsDirEmpty(path string) (bool, error) {
f, err := os.Open(path)
if err != nil {
return false, err
}
defer f.Close()
_, err = f.Readdir(1)
if err == nil {
return false, nil
}
if errors.Is(err, io.EOF) {
return true, nil
}
return false, err
}

69
file/dir_test.go Normal file
View File

@ -0,0 +1,69 @@
package file
import (
"errors"
"io/fs"
"os"
"path/filepath"
"testing"
)
func TestIsDirEmpty(t *testing.T) {
t.Run("empty directory", func(t *testing.T) {
dir, err := os.MkdirTemp("", "test")
if err != nil {
t.Fatalf("failed to create temp dir: %v", err)
}
defer os.RemoveAll(dir)
isEmpty, err := IsDirEmpty(dir)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
if !isEmpty {
t.Error("expected directory to be empty")
}
})
t.Run("non-empty directory", func(t *testing.T) {
dir, err := os.MkdirTemp("", "test")
if err != nil {
t.Fatalf("failed to create temp dir: %v", err)
}
defer os.RemoveAll(dir)
file, err := os.CreateTemp(dir, "test")
if err != nil {
t.Fatalf("failed to create temp file: %v", err)
}
file.Close()
isEmpty, err := IsDirEmpty(dir)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
if isEmpty {
t.Error("expected directory to be non-empty")
}
})
t.Run("non-existent directory", func(t *testing.T) {
dir := filepath.Join(os.TempDir(), "non-existent")
isEmpty, err := IsDirEmpty(dir)
if err == nil {
t.Error("expected an error for non-existent directory")
}
if isEmpty {
t.Error("expected directory to be non-empty")
}
if !errors.Is(err, fs.ErrNotExist) {
t.Errorf("unexpected error: %v", err)
}
})
}

View File

@ -34,17 +34,6 @@ func ReadStringOrFile(input string) (string, bool, error) {
return string(result), true, nil
}
// DeleteDir deletes the directory at the given path.
// It returns nil if the deletion succeeds, or the deletion error otherwise.
// If the directory does not exist, DeleteDir returns nil.
func DeleteDir(path string) error {
if _, err := os.Stat(path); os.IsNotExist(err) {
return nil
}
return os.Remove(path)
}
// ExpandFileList takes a list of file globs and expands them into a list
// of matching file paths. It returns the expanded file list and any errors
// from glob matching. This allows safely passing user input globs through to
@ -65,3 +54,21 @@ func ExpandFileList(fileList []string) ([]string, error) {
return result, nil
}
// WriteTmpFile creates a temporary file with the given name and content, and returns the path to the created file.
func WriteTmpFile(name, content string) (string, error) {
tmpfile, err := os.CreateTemp("", name)
if err != nil {
return "", err
}
if _, err := tmpfile.Write([]byte(content)); err != nil {
return "", err
}
if err := tmpfile.Close(); err != nil {
return "", err
}
return tmpfile.Name(), nil
}

64
file/file_test.go Normal file
View File

@ -0,0 +1,64 @@
package file
import (
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
)
const helloWorld = "Hello, World!"
func TestWriteTmpFile(t *testing.T) {
tests := []struct {
name string
fileName string
content string
wantErr bool
}{
{
name: "write to temp file",
fileName: "test.txt",
content: helloWorld,
wantErr: false,
},
{
name: "empty file name",
fileName: "",
content: helloWorld,
wantErr: false,
},
{
name: "empty file content",
fileName: "test.txt",
content: "",
wantErr: false,
},
{
name: "create temp file error",
fileName: filepath.Join(os.TempDir(), "non-existent", "test.txt"),
content: helloWorld,
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tmpFile, err := WriteTmpFile(tt.fileName, tt.content)
if tt.wantErr {
assert.Error(t, err)
return
}
assert.NoError(t, err)
defer os.Remove(tmpFile)
data, err := os.ReadFile(tmpFile)
assert.NoError(t, err)
assert.Equal(t, tt.content, string(data))
})
}
}

16
go.mod
View File

@ -1,4 +1,4 @@
module github.com/thegeeklab/wp-plugin-go
module github.com/thegeeklab/wp-plugin-go/v3
go 1.22
@ -6,15 +6,16 @@ require (
github.com/Masterminds/semver/v3 v3.2.1
github.com/Masterminds/sprig/v3 v3.2.3
github.com/joho/godotenv v1.5.1
github.com/rs/zerolog v1.32.0
github.com/rs/zerolog v1.33.0
github.com/stretchr/testify v1.9.0
github.com/urfave/cli/v2 v2.27.1
golang.org/x/net v0.22.0
github.com/urfave/cli/v2 v2.27.2
golang.org/x/net v0.25.0
golang.org/x/sys v0.20.0
)
require (
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/google/uuid v1.1.1 // indirect
github.com/huandu/xstrings v1.3.3 // indirect
@ -27,8 +28,7 @@ require (
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/shopspring/decimal v1.2.0 // indirect
github.com/spf13/cast v1.3.1 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
golang.org/x/crypto v0.21.0 // indirect
golang.org/x/sys v0.18.0 // indirect
github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 // indirect
golang.org/x/crypto v0.23.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

28
go.sum
View File

@ -6,8 +6,8 @@ github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYr
github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA=
github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
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/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=
@ -33,8 +33,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0=
github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8=
github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
@ -46,23 +46,23 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/urfave/cli/v2 v2.27.1 h1:8xSQ6szndafKVRmfyeUMxkNUJQMjL1F2zmsZ+qHpfho=
github.com/urfave/cli/v2 v2.27.1/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
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/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 h1:+qGGcbkzsfDQNPPe9UDgpxAWQrhbbBXOYJFQDq/dtJw=
github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913/go.mod h1:4aEEwZQutDLsQv2Deui4iYQ6DWTxR14g6m8Wv88+Xqk=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc=
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -74,8 +74,8 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=

View File

@ -238,11 +238,11 @@ func prevFromContext(c *cli.Context) Commit {
// line as the title, and the rest as the description. If there is no newline,
// the entire message is returned as the title, and the description is empty.
func splitMessage(message string) (string, string) {
//nolint:gomnd
//nolint:mnd
switch parts := strings.SplitN(message, "\n", 2); len(parts) {
case 1:
return parts[0], ""
//nolint:gomnd
//nolint:mnd
case 2:
return parts[0], parts[1]
}

View File

@ -26,8 +26,8 @@ func loggingFlags(category string) []cli.Flag {
return []cli.Flag{
&cli.StringFlag{
Name: "log-level",
Usage: "log level",
EnvVars: []string{"CI_LOG_LEVEL"},
Usage: "plugin log level",
EnvVars: []string{"PLUGIN_LOG_LEVEL"},
Value: "info",
Category: category,
},
@ -36,7 +36,11 @@ func loggingFlags(category string) []cli.Flag {
// SetupConsoleLogger sets up the console logger.
func SetupConsoleLogger(c *cli.Context) error {
level := c.String("log-level")
level := "info"
if c != nil {
level = c.String("log-level")
}
lvl, err := zerolog.ParseLevel(level)
if err != nil {
@ -51,7 +55,7 @@ func SetupConsoleLogger(c *cli.Context) error {
if zerolog.GlobalLevel() <= zerolog.DebugLevel {
log.Logger = log.With().Caller().Logger()
log.Log().Msgf("LogLevel = %s", zerolog.GlobalLevel().String())
log.Info().Msgf("LogLevel = %s", zerolog.GlobalLevel().String())
}
return nil

View File

@ -24,7 +24,7 @@ import (
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"github.com/thegeeklab/wp-plugin-go/trace"
plugin_trace "github.com/thegeeklab/wp-plugin-go/v3/trace"
"github.com/urfave/cli/v2"
"golang.org/x/net/proxy"
)
@ -45,8 +45,8 @@ type Network struct {
//nolint:containedctx
Context context.Context
/// Whether SSL verification is skipped
SkipVerify bool
/// Whether SSL verification is skipped or not.
InsecureSkipVerify bool
// Client for making network requests.
Client *http.Client
@ -55,9 +55,9 @@ type Network struct {
func networkFlags(category string) []cli.Flag {
return []cli.Flag{
&cli.BoolFlag{
Name: "transport.skip-verify",
Usage: "skip ssl verify",
EnvVars: []string{"CI_SKIP_VERIFY"},
Name: "transport.insecure-skip-verify",
Usage: "skip SSL verification",
EnvVars: []string{"PLUGIN_INSECURE_SKIP_VERIFY"},
Category: category,
},
&cli.StringFlag{
@ -77,7 +77,7 @@ func networkFlags(category string) []cli.Flag {
func NetworkFromContext(ctx *cli.Context) Network {
var (
skip = ctx.Bool("transport.skip-verify")
skipVerify = ctx.Bool("transport.insecure-skip-verify")
defaultContext = context.Background()
socks = ctx.String("transport.socks-proxy")
socksoff = ctx.Bool("transport.socks-proxy-off")
@ -90,7 +90,7 @@ func NetworkFromContext(ctx *cli.Context) Network {
tlsConfig := &tls.Config{
RootCAs: certs,
InsecureSkipVerify: skip, //nolint:gosec
InsecureSkipVerify: skipVerify, //nolint:gosec
}
transport := &http.Transport{
@ -126,7 +126,7 @@ func NetworkFromContext(ctx *cli.Context) Network {
}
if zerolog.GlobalLevel() == zerolog.TraceLevel {
defaultContext = trace.HTTP(defaultContext)
defaultContext = plugin_trace.HTTP(defaultContext)
}
client := &http.Client{
@ -134,8 +134,8 @@ func NetworkFromContext(ctx *cli.Context) Network {
}
return Network{
Context: defaultContext,
SkipVerify: skip,
Client: client,
Context: defaultContext,
InsecureSkipVerify: skipVerify,
Client: client,
}
}

View File

@ -27,6 +27,37 @@ import (
"github.com/urfave/cli/v2"
)
//nolint:lll
const appHelpTemplate = `NAME:
{{template "helpNameTemplate" .}}
USAGE:
{{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}{{if .Args}}[arguments...]{{end}}{{end}}{{end}}{{if .Version}}{{if not .HideVersion}}
VERSION:
{{.Version}}{{end}}{{end}}{{if .Description}}
DESCRIPTION:
{{template "descriptionTemplate" .}}{{end}}
{{- if len .Authors}}
AUTHOR{{template "authorsTemplate" .}}{{end}}{{if .VisibleCommands}}
COMMANDS:{{template "visibleCommandCategoryTemplate" .}}{{end}}{{if .VisibleFlagCategories}}
GLOBAL OPTIONS:{{range .VisibleFlagCategories}}{{if and .Name (ne .Name "Plugin Flags")}}{{continue}}{{end}}
{{if .Name}}{{.Name}}
{{end}}{{$flglen := len .Flags}}{{range $i, $e := .Flags}}{{if eq (subtract $flglen $i) 1}}{{$e}}
{{else}}{{$e}}
{{end}}{{end}}{{end}}{{else if .VisibleFlags}}
GLOBAL OPTIONS:{{template "visibleFlagTemplate" .}}{{end}}{{if .Copyright}}
COPYRIGHT:
{{template "copyrightTemplate" .}}{{end}}
`
// Options defines the options for the plugin.
type Options struct {
// Name of the plugin.
@ -41,6 +72,8 @@ type Options struct {
Flags []cli.Flag
// Execute function of the plugin.
Execute ExecuteFunc
// Hide woodpecker system flags.
HideWoodpeckerFlags bool
}
// Plugin defines the plugin instance.
@ -63,16 +96,23 @@ func New(opt Options) *Plugin {
_ = godotenv.Overload("/run/woodpecker/env")
}
_ = SetupConsoleLogger(nil)
app := &cli.App{
Name: opt.Name,
Usage: opt.Description,
Version: opt.Version,
Flags: append(opt.Flags, Flags()...),
Before: SetupConsoleLogger,
}
if opt.HideWoodpeckerFlags {
app.CustomAppHelpTemplate = appHelpTemplate
}
cli.VersionPrinter = func(c *cli.Context) {
version := fmt.Sprintf("%s version=%s %s\n", c.App.Name, c.App.Version, opt.VersionMetadata)
fmt.Print(strings.TrimSpace(version))
fmt.Println(strings.TrimSpace(version))
}
plugin := &Plugin{
@ -85,10 +125,6 @@ func New(opt Options) *Plugin {
}
func (p *Plugin) action(ctx *cli.Context) error {
if err := SetupConsoleLogger(ctx); err != nil {
return err
}
p.Metadata = MetadataFromContext(ctx)
p.Network = NetworkFromContext(ctx)
p.Context = ctx

View File

@ -22,12 +22,12 @@ import (
// format. Trailing or leading spaces or new-lines are not getting truncated. It
// is able to read templates from remote paths, local files or directly from the
// string.
func Render(ctx context.Context, client http.Client, templateString string, payload interface{}) (string, error) {
func Render(ctx context.Context, client http.Client, tmpl string, payload interface{}) (string, error) {
var outString bytes.Buffer
tpl := new(template.Template).Funcs(LoadFuncMap())
templateURL, err := url.Parse(templateString)
templateURL, err := url.Parse(tmpl)
if err == nil {
switch templateURL.Scheme {
case "http", "https":
@ -48,18 +48,18 @@ func Render(ctx context.Context, client http.Client, templateString string, payl
return "", fmt.Errorf("failed to read: %w", err)
}
templateString = string(out)
tmpl = string(out)
case "file":
out, err := os.ReadFile(templateURL.Path)
if err != nil {
return "", fmt.Errorf("failed to read: %w", err)
}
templateString = string(out)
tmpl = string(out)
}
}
tpl, err = tpl.Parse(templateString)
tpl, err = tpl.Parse(tmpl)
if err != nil {
return "", err
}
@ -72,8 +72,8 @@ func Render(ctx context.Context, client http.Client, templateString string, payl
// RenderTrim parses and executes a template, returning the results in string
// format. The result is trimmed to remove left and right padding and newlines
// that may be added unintentially in the template markup.
func RenderTrim(ctx context.Context, client http.Client, template string, playload interface{}) (string, error) {
out, err := Render(ctx, client, template, playload)
func RenderTrim(ctx context.Context, client http.Client, tmpl string, playload interface{}) (string, error) {
out, err := Render(ctx, client, tmpl, playload)
return strings.Trim(out, " \n"), err
}

View File

@ -12,9 +12,6 @@ import (
"fmt"
"net/http/httptrace"
"net/textproto"
"os"
"os/exec"
"strings"
"github.com/rs/zerolog/log"
)
@ -120,8 +117,3 @@ func HTTP(ctx context.Context) context.Context {
},
})
}
// Cmd prints the executed command to stdout.
func Cmd(cmd *exec.Cmd) {
fmt.Fprintf(os.Stdout, "+ %s\n", strings.Join(cmd.Args, " "))
}

View File

@ -28,7 +28,7 @@ func splitWithEscaping(in, separator, escapeString string) []string {
out := strings.Split(in, separator)
//nolint:gomnd
//nolint:mnd
for i := len(out) - 2; i >= 0; i-- {
if strings.HasSuffix(out[i], escapeString) {
out[i] = out[i][:len(out[i])-len(escapeString)] + separator + out[i+1]

15
util/user.go Normal file
View File

@ -0,0 +1,15 @@
package util
import "os/user"
// GetUserHomeDir returns the home directory path for the current user.
// If the current user cannot be determined, it returns the default "/root" path.
func GetUserHomeDir() string {
home := "/root"
if currentUser, err := user.Current(); err == nil {
home = currentUser.HomeDir
}
return home
}