mirror of
https://github.com/thegeeklab/wp-plugin-go.git
synced 2024-06-02 18:39:40 +02:00
Compare commits
13 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
07d29586c9 | ||
|
ec3b3263f8 | ||
|
dfbeaf935f | ||
e5e67d464c | |||
119641f63a | |||
23eca50904 | |||
6be7f2b898 | |||
|
e2bc944f1f | ||
085ee0d15a | |||
5e6b213c13 | |||
|
5ca8c9ac0e | ||
df36058fa9 | |||
|
c48fbf9bd7 |
|
@ -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
|
||||
|
|
2
Makefile
2
Makefile
|
@ -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.57.2
|
||||
GOLANGCI_LINT_PACKAGE_VERSION := v1.59.0
|
||||
|
||||
GO ?= go
|
||||
PACKAGES ?= $(shell go list ./...)
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
"sort"
|
||||
"strings"
|
||||
|
||||
wp_template "github.com/thegeeklab/wp-plugin-go/v2/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
50
exec/command.go
Normal 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
103
exec/command_test.go
Normal 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())
|
||||
})
|
||||
}
|
||||
}
|
18
file/file.go
18
file/file.go
|
@ -54,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
64
file/file_test.go
Normal 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))
|
||||
})
|
||||
}
|
||||
}
|
8
go.mod
8
go.mod
|
@ -1,4 +1,4 @@
|
|||
module github.com/thegeeklab/wp-plugin-go/v2
|
||||
module github.com/thegeeklab/wp-plugin-go/v3
|
||||
|
||||
go 1.22
|
||||
|
||||
|
@ -6,10 +6,10 @@ 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.2
|
||||
golang.org/x/net v0.24.0
|
||||
golang.org/x/net v0.25.0
|
||||
golang.org/x/sys v0.20.0
|
||||
)
|
||||
|
||||
|
@ -29,6 +29,6 @@ require (
|
|||
github.com/shopspring/decimal v1.2.0 // indirect
|
||||
github.com/spf13/cast v1.3.1 // indirect
|
||||
github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 // indirect
|
||||
golang.org/x/crypto v0.22.0 // indirect
|
||||
golang.org/x/crypto v0.23.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
|
12
go.sum
12
go.sum
|
@ -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=
|
||||
|
@ -54,15 +54,15 @@ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5t
|
|||
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.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
|
||||
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
|
||||
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.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
|
||||
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
|
||||
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=
|
||||
|
|
|
@ -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]
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -24,7 +24,7 @@ import (
|
|||
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/thegeeklab/wp-plugin-go/v2/trace"
|
||||
plugin_trace "github.com/thegeeklab/wp-plugin-go/v3/trace"
|
||||
"github.com/urfave/cli/v2"
|
||||
"golang.org/x/net/proxy"
|
||||
)
|
||||
|
@ -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{
|
||||
|
|
|
@ -96,13 +96,14 @@ 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,
|
||||
After: SetupConsoleLogger,
|
||||
}
|
||||
|
||||
if opt.HideWoodpeckerFlags {
|
||||
|
|
|
@ -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, " "))
|
||||
}
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
package types
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/sys/execabs"
|
||||
)
|
||||
|
||||
type Cmd struct {
|
||||
*execabs.Cmd
|
||||
Private bool
|
||||
Trace *bool
|
||||
}
|
||||
|
||||
func (c *Cmd) Run() error {
|
||||
if c.Trace == nil {
|
||||
c.SetTrace(true)
|
||||
}
|
||||
|
||||
if c.Env == nil {
|
||||
c.Env = os.Environ()
|
||||
}
|
||||
|
||||
if c.Stdout == nil {
|
||||
c.Stdout = os.Stdout
|
||||
}
|
||||
|
||||
if c.Stderr == nil {
|
||||
c.Stderr = os.Stderr
|
||||
}
|
||||
|
||||
if c.Private {
|
||||
c.Stdout = io.Discard
|
||||
}
|
||||
|
||||
if *c.Trace {
|
||||
fmt.Fprintf(os.Stdout, "+ %s\n", strings.Join(c.Args, " "))
|
||||
}
|
||||
|
||||
if err := c.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.Wait()
|
||||
}
|
||||
|
||||
func (c *Cmd) SetTrace(trace bool) {
|
||||
c.Trace = &trace
|
||||
}
|
|
@ -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
15
util/user.go
Normal 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
|
||||
}
|
Loading…
Reference in New Issue
Block a user