mirror of
https://codeberg.org/woodpecker-plugins/go-plugin
synced 2026-06-16 14:49:10 +08:00
Compare commits
52 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 10b75b259b | |||
| d25844e305 | |||
| ac40cced18 | |||
| aa85fcbce5 | |||
| 8ef4f8f9cc | |||
| a23e4f7e42 | |||
| 5e6aff13a7 | |||
| 6ce864b6d9 | |||
| a72f843148 | |||
| 9cf9134d0e | |||
| 16d1fd423d | |||
| 34d6107edb | |||
| 3908f282af | |||
| 15556b694d | |||
| ce08e0142d | |||
| 32c3c2a6f1 | |||
| 8ddffff10c | |||
| 7668bbb9be | |||
| d73d41e148 | |||
| fb4faa61f2 | |||
| 645238beec | |||
| 612b6a34dd | |||
| dad2b481a2 | |||
| e3f4284781 | |||
| 044f72ed49 | |||
| 94ba1fe374 | |||
| 89c7be805f | |||
| c13a4deeba | |||
| 770c8d6ae2 | |||
| 9993b2b277 | |||
| 545ea71b3c | |||
| 7dffd4a970 | |||
| 4cb087c13c | |||
| 67497c7b50 | |||
| 3afdbec338 | |||
| 16e5ebfe91 | |||
| 8c15dbc919 | |||
| 33995f25c3 | |||
| ba75700cc4 | |||
| 0db17abc92 | |||
| 0c8f2b173b | |||
| edc91fba9e | |||
| dec7e76c4e | |||
| 738d85cc8e | |||
| 0bb8640938 | |||
| 9748a14bd5 | |||
| 42e963e908 | |||
| d899146040 | |||
| a5e5444f6a | |||
| 54eb1bdcdd | |||
| daf65e94bb | |||
| 7f87818bf7 |
@@ -0,0 +1,61 @@
|
||||
version: "2"
|
||||
linters:
|
||||
default: none
|
||||
enable:
|
||||
- bidichk
|
||||
- errcheck
|
||||
- errorlint
|
||||
- forbidigo
|
||||
- govet
|
||||
- ineffassign
|
||||
- misspell
|
||||
- revive
|
||||
- staticcheck
|
||||
- unused
|
||||
- whitespace
|
||||
- zerologlint
|
||||
settings:
|
||||
errorlint:
|
||||
errorf-multi: true
|
||||
forbidigo:
|
||||
forbid:
|
||||
- pattern: context\.WithCancel$
|
||||
- pattern: ^print.*$
|
||||
misspell:
|
||||
locale: US
|
||||
exclusions:
|
||||
generated: lax
|
||||
presets:
|
||||
- comments
|
||||
- common-false-positives
|
||||
- legacy
|
||||
- std-error-handling
|
||||
paths:
|
||||
- third_party$
|
||||
- builtin$
|
||||
- examples$
|
||||
formatters:
|
||||
enable:
|
||||
- gci
|
||||
- gofmt
|
||||
- gofumpt
|
||||
settings:
|
||||
gci:
|
||||
sections:
|
||||
- standard
|
||||
- default
|
||||
- prefix(go.woodpecker-ci.org/woodpecker)
|
||||
custom-order: true
|
||||
gofmt:
|
||||
simplify: true
|
||||
rewrite-rules:
|
||||
- pattern: interface{}
|
||||
replacement: any
|
||||
gofumpt:
|
||||
extra-rules: true
|
||||
exclusions:
|
||||
generated: lax
|
||||
paths:
|
||||
- third_party$
|
||||
- builtin$
|
||||
- examples$
|
||||
+5
-15
@@ -3,32 +3,22 @@ when:
|
||||
- event: push
|
||||
branch:
|
||||
- ${CI_REPO_DEFAULT_BRANCH}
|
||||
- 'renovate/*'
|
||||
- "renovate/*"
|
||||
|
||||
variables:
|
||||
- &golang "golang:1.23"
|
||||
- &golangci-lint "golangci/golangci-lint:v1.61-alpine"
|
||||
- &reviewdog-golangci-lint "woodpeckerci/plugin-reviewdog-golangci-lint:1.59"
|
||||
- &golang "golang:1.25"
|
||||
|
||||
steps:
|
||||
vendor:
|
||||
image: *golang
|
||||
commands: go mod vendor
|
||||
|
||||
review-go:
|
||||
image: *reviewdog-golangci-lint
|
||||
settings:
|
||||
token:
|
||||
from_secret: reviewdog_token
|
||||
when:
|
||||
event: pull_request
|
||||
|
||||
lint:
|
||||
image: *golangci-lint
|
||||
commands: golangci-lint run --timeout 5m
|
||||
image: *golang
|
||||
commands: make lint
|
||||
when:
|
||||
event: [push, tag, cron]
|
||||
|
||||
test:
|
||||
image: *golang
|
||||
commands: go test --cover ./...
|
||||
commands: make test
|
||||
|
||||
@@ -6,7 +6,7 @@ when:
|
||||
|
||||
steps:
|
||||
- name: release-helper
|
||||
image: docker.io/woodpeckerci/plugin-ready-release-go:2.1.1
|
||||
image: docker.io/woodpeckerci/plugin-ready-release-go:3.4.0
|
||||
settings:
|
||||
release_branch: ${CI_COMMIT_BRANCH}
|
||||
git_email: woodpecker-bot@obermui.de
|
||||
|
||||
@@ -1,5 +1,67 @@
|
||||
# Changelog
|
||||
|
||||
## [1.0.1](https://codeberg.org/woodpecker-plugins/go-plugin/releases/tag/v1.0.1) - 2025-09-13
|
||||
|
||||
### ❤️ Thanks to all contributors! ❤️
|
||||
|
||||
@woodpecker-bot
|
||||
|
||||
### 📦️ Dependency
|
||||
|
||||
- fix(deps): update module github.com/urfave/cli/v3 to v3.4.1 [[#64](https://codeberg.org/woodpecker-plugins/go-plugin/pulls/64)]
|
||||
- chore(deps): update dependency go to v1.25.1 [[#61](https://codeberg.org/woodpecker-plugins/go-plugin/pulls/61)]
|
||||
- fix(deps): update module github.com/stretchr/testify to v1.11.1 [[#63](https://codeberg.org/woodpecker-plugins/go-plugin/pulls/63)]
|
||||
- fix(deps): update module golang.org/x/net to v0.44.0 [[#65](https://codeberg.org/woodpecker-plugins/go-plugin/pulls/65)]
|
||||
- chore(deps): update golang docker tag to v1.25 [[#62](https://codeberg.org/woodpecker-plugins/go-plugin/pulls/62)]
|
||||
- chore(deps): update docker.io/woodpeckerci/plugin-ready-release-go docker tag to v3.4.0 [[#59](https://codeberg.org/woodpecker-plugins/go-plugin/pulls/59)]
|
||||
- fix(deps): update module golang.org/x/net to v0.43.0 [[#60](https://codeberg.org/woodpecker-plugins/go-plugin/pulls/60)]
|
||||
- chore(deps): update dependency go to v1.24.6 [[#58](https://codeberg.org/woodpecker-plugins/go-plugin/pulls/58)]
|
||||
- fix(deps): update module golang.org/x/net to v0.42.0 [[#57](https://codeberg.org/woodpecker-plugins/go-plugin/pulls/57)]
|
||||
- chore(deps): update dependency go to v1.24.5 [[#56](https://codeberg.org/woodpecker-plugins/go-plugin/pulls/56)]
|
||||
- chore(deps): update docker.io/woodpeckerci/plugin-ready-release-go docker tag to v3.3.0 [[#55](https://codeberg.org/woodpecker-plugins/go-plugin/pulls/55)]
|
||||
- fix(deps): update module github.com/urfave/cli/v3 to v3.3.8 [[#54](https://codeberg.org/woodpecker-plugins/go-plugin/pulls/54)]
|
||||
- fix(deps): update module golang.org/x/net to v0.41.0 [[#53](https://codeberg.org/woodpecker-plugins/go-plugin/pulls/53)]
|
||||
- chore(deps): update dependency go to v1.24.4 [[#52](https://codeberg.org/woodpecker-plugins/go-plugin/pulls/52)]
|
||||
- chore(deps): update dependency go to v1.24.3 [[#50](https://codeberg.org/woodpecker-plugins/go-plugin/pulls/50)]
|
||||
|
||||
## [1.0.0](https://codeberg.org/woodpecker-plugins/go-plugin/releases/tag/v1.0.0) - 2025-04-24
|
||||
|
||||
### ❤️ Thanks to all contributors! ❤️
|
||||
|
||||
@woodpecker-bot, @xoxys
|
||||
|
||||
### 💥 Breaking changes
|
||||
|
||||
- Bump urfave/cli to v3.2.0 [[#49](https://codeberg.org/woodpecker-plugins/go-plugin/pulls/49)]
|
||||
|
||||
### ✨ Features
|
||||
|
||||
- feat: add custom cli flags [[#48](https://codeberg.org/woodpecker-plugins/go-plugin/pulls/48)]
|
||||
|
||||
### 📦️ Dependency
|
||||
|
||||
- fix(deps): update module github.com/urfave/cli/v3 to v3.1.1 [[#47](https://codeberg.org/woodpecker-plugins/go-plugin/pulls/47)]
|
||||
- chore(deps): update dependency go to v1.24.2 [[#46](https://codeberg.org/woodpecker-plugins/go-plugin/pulls/46)]
|
||||
- chore(deps): update golangci/golangci-lint docker tag to v2 [[#44](https://codeberg.org/woodpecker-plugins/go-plugin/pulls/44)]
|
||||
|
||||
## [0.7.1](https://codeberg.org/woodpecker-plugins/go-plugin/releases/tag/v0.7.1) - 2025-02-16
|
||||
|
||||
### ❤️ Thanks to all contributors! ❤️
|
||||
|
||||
@6543, @woodpecker-bot
|
||||
|
||||
### 📦️ Dependency
|
||||
|
||||
- chore(deps): update golangci/golangci-lint docker tag to v1.64 [[#42](https://codeberg.org/woodpecker-plugins/go-plugin/pulls/42)]
|
||||
- chore(deps): update golang docker tag to v1.24 [[#41](https://codeberg.org/woodpecker-plugins/go-plugin/pulls/41)]
|
||||
- fix(deps): update module golang.org/x/net to v0.35.0 [[#43](https://codeberg.org/woodpecker-plugins/go-plugin/pulls/43)]
|
||||
- chore(deps): update docker.io/woodpeckerci/plugin-ready-release-go docker tag to v3.1.3 [[#40](https://codeberg.org/woodpecker-plugins/go-plugin/pulls/40)]
|
||||
- chore(deps): update docker.io/woodpeckerci/plugin-ready-release-go docker tag to v3 [[#37](https://codeberg.org/woodpecker-plugins/go-plugin/pulls/37)]
|
||||
|
||||
### Misc
|
||||
|
||||
- Bump min golan version to v1.20 [[#36](https://codeberg.org/woodpecker-plugins/go-plugin/pulls/36)]
|
||||
|
||||
## [0.7.0](https://codeberg.org/woodpecker-plugins/go-plugin/releases/tag/v0.7.0) - 2024-11-13
|
||||
|
||||
### ❤️ Thanks to all contributors! ❤️
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
GOFILES_NOVENDOR = $(shell find . -type f -name '*.go' -not -path "./vendor/*" -not -path "./.git/*")
|
||||
GO_PACKAGES ?= $(shell go list ./... | grep -v /vendor/)
|
||||
|
||||
.PHONY: all
|
||||
all: lint
|
||||
|
||||
vendor:
|
||||
go mod tidy
|
||||
go mod vendor
|
||||
|
||||
format: install-tools ## Format source code
|
||||
@gofumpt -extra -w ${GOFILES_NOVENDOR}
|
||||
|
||||
formatcheck:
|
||||
@([ -z "$(shell gofumpt -d $(GOFILES_NOVENDOR) | head)" ]) || (echo "Source is unformatted"; exit 1)
|
||||
|
||||
install-tools: ## Install development tools
|
||||
@hash golangci-lint > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
|
||||
go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@latest ; \
|
||||
fi ; \
|
||||
hash gofumpt > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
|
||||
go install mvdan.cc/gofumpt@latest; \
|
||||
fi ; \
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
go clean -i ./...
|
||||
|
||||
.PHONY: lint
|
||||
lint: install-tools ## Lint code
|
||||
@echo "Running golangci-lint"
|
||||
golangci-lint run
|
||||
|
||||
.PHONY: vet
|
||||
vet:
|
||||
@echo "Running go vet..."
|
||||
@go vet $(GO_PACKAGES)
|
||||
|
||||
.PHONY: test
|
||||
test:
|
||||
go test -race -cover ./...
|
||||
@@ -0,0 +1,84 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
// StringMapFlag is a flag type which supports JSON string maps.
|
||||
type (
|
||||
StringMapFlag = cli.FlagBase[map[string]string, StringMapConfig, StringMap]
|
||||
)
|
||||
|
||||
// StringMapConfig defines the configuration for string map flags.
|
||||
type StringMapConfig struct {
|
||||
// Any config options can be added here if needed
|
||||
}
|
||||
|
||||
// StringMap implements the Value and ValueCreator interfaces for string maps.
|
||||
type StringMap struct {
|
||||
destination *map[string]string
|
||||
}
|
||||
|
||||
// Create implements the ValueCreator interface.
|
||||
func (s StringMap) Create(v map[string]string, p *map[string]string, _ StringMapConfig) cli.Value {
|
||||
*p = map[string]string{}
|
||||
|
||||
if v != nil {
|
||||
*p = v
|
||||
}
|
||||
|
||||
return &StringMap{
|
||||
destination: p,
|
||||
}
|
||||
}
|
||||
|
||||
// ToString implements the ValueCreator interface.
|
||||
func (s StringMap) ToString(v map[string]string) string {
|
||||
if len(v) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
jsonBytes, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return string(jsonBytes)
|
||||
}
|
||||
|
||||
// Set implements the flag.Value interface.
|
||||
func (s *StringMap) Set(v string) error {
|
||||
*s.destination = map[string]string{}
|
||||
|
||||
if v == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
err := json.Unmarshal([]byte(v), s.destination)
|
||||
if err != nil {
|
||||
(*s.destination)["*"] = v
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get implements the flag.Value interface.
|
||||
func (s *StringMap) Get() any {
|
||||
return *s.destination
|
||||
}
|
||||
|
||||
// String implements the flag.Value interface.
|
||||
func (s *StringMap) String() string {
|
||||
if s.destination == nil || len(*s.destination) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
jsonBytes, err := json.Marshal(*s.destination)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return string(jsonBytes)
|
||||
}
|
||||
@@ -0,0 +1,221 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestStringMapSet(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
want map[string]string
|
||||
}{
|
||||
{
|
||||
name: "empty string",
|
||||
input: "",
|
||||
want: map[string]string{},
|
||||
},
|
||||
{
|
||||
name: "valid JSON",
|
||||
input: `{"key1":"value1","key2":"value2"}`,
|
||||
want: map[string]string{"key1": "value1", "key2": "value2"},
|
||||
},
|
||||
{
|
||||
name: "single key-value",
|
||||
input: `{"key":"value"}`,
|
||||
want: map[string]string{"key": "value"},
|
||||
},
|
||||
{
|
||||
name: "non-JSON string",
|
||||
input: "not-json",
|
||||
want: map[string]string{"*": "not-json"},
|
||||
},
|
||||
{
|
||||
name: "empty JSON object",
|
||||
input: "{}",
|
||||
want: map[string]string{},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
var dest map[string]string
|
||||
s := &StringMap{
|
||||
destination: &dest,
|
||||
}
|
||||
|
||||
err := s.Set(tt.input)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tt.want, dest)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestStringMapString(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input map[string]string
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "empty map",
|
||||
input: map[string]string{},
|
||||
want: "",
|
||||
},
|
||||
{
|
||||
name: "nil map",
|
||||
input: nil,
|
||||
want: "",
|
||||
},
|
||||
{
|
||||
name: "single key-value",
|
||||
input: map[string]string{"key": "value"},
|
||||
want: `{"key":"value"}`,
|
||||
},
|
||||
{
|
||||
name: "multiple key-values",
|
||||
input: map[string]string{"key1": "value1", "key2": "value2"},
|
||||
want: `{"key1":"value1","key2":"value2"}`,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
s := &StringMap{
|
||||
destination: &tt.input,
|
||||
}
|
||||
|
||||
got := s.String()
|
||||
|
||||
if len(tt.input) > 1 {
|
||||
var expected, actual map[string]string
|
||||
_ = json.Unmarshal([]byte(tt.want), &expected)
|
||||
_ = json.Unmarshal([]byte(got), &actual)
|
||||
assert.EqualValues(t, expected, actual)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
assert.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestStringMapGet(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
want map[string]string
|
||||
}{
|
||||
{
|
||||
name: "empty map",
|
||||
want: map[string]string{},
|
||||
},
|
||||
{
|
||||
name: "single key-value",
|
||||
want: map[string]string{"key": "value"},
|
||||
},
|
||||
{
|
||||
name: "multiple key-values",
|
||||
want: map[string]string{"key1": "value1", "key2": "value2"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
s := &StringMap{
|
||||
destination: &tt.want,
|
||||
}
|
||||
|
||||
result := s.Get()
|
||||
assert.Equal(t, tt.want, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestStringMapCreate(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input map[string]string
|
||||
want map[string]string
|
||||
}{
|
||||
{
|
||||
name: "empty map",
|
||||
input: nil,
|
||||
want: map[string]string{},
|
||||
},
|
||||
{
|
||||
name: "empty map",
|
||||
input: map[string]string{},
|
||||
want: map[string]string{},
|
||||
},
|
||||
{
|
||||
name: "single key-value",
|
||||
input: map[string]string{"key": "value"},
|
||||
want: map[string]string{"key": "value"},
|
||||
},
|
||||
{
|
||||
name: "multiple key-values",
|
||||
input: map[string]string{"key1": "value1", "key2": "value2"},
|
||||
want: map[string]string{"key1": "value1", "key2": "value2"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
var dest map[string]string
|
||||
|
||||
s := StringMap{}
|
||||
config := StringMapConfig{}
|
||||
|
||||
got := s.Create(tt.input, &dest, config)
|
||||
assert.Equal(t, tt.want, dest)
|
||||
assert.Equal(t, &dest, got.(*StringMap).destination)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestStringMapToString(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input map[string]string
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "empty map",
|
||||
input: map[string]string{},
|
||||
want: "",
|
||||
},
|
||||
{
|
||||
name: "single key-value",
|
||||
input: map[string]string{"key": "value"},
|
||||
want: `{"key":"value"}`,
|
||||
},
|
||||
{
|
||||
name: "multiple key-values",
|
||||
input: map[string]string{"key1": "value1", "key2": "value2"},
|
||||
want: `{"key1":"value1","key2":"value2"}`,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
s := StringMap{}
|
||||
|
||||
got := s.ToString(tt.input)
|
||||
|
||||
if len(tt.input) > 1 {
|
||||
var expected, actual map[string]string
|
||||
_ = json.Unmarshal([]byte(tt.want), &expected)
|
||||
_ = json.Unmarshal([]byte(got), &actual)
|
||||
assert.EqualValues(t, expected, actual)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
assert.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
// StringSliceFlag is a flag type which support comma separated values and escaping to not split at unwanted lines.
|
||||
type (
|
||||
StringSliceFlag = cli.FlagBase[[]string, StringSliceConfig, StringSlice]
|
||||
)
|
||||
|
||||
// StringConfig defines the configuration for string flags.
|
||||
type StringSliceConfig struct {
|
||||
Delimiter string
|
||||
EscapeString string
|
||||
}
|
||||
|
||||
// StringSlice implements the Value and ValueCreator interfaces for string slices.
|
||||
type StringSlice struct {
|
||||
destination *[]string
|
||||
delimiter string
|
||||
escapeString string
|
||||
}
|
||||
|
||||
// Create implements the ValueCreator interface.
|
||||
func (s StringSlice) Create(v []string, p *[]string, c StringSliceConfig) cli.Value {
|
||||
*p = v
|
||||
|
||||
return &StringSlice{
|
||||
destination: p,
|
||||
delimiter: c.Delimiter,
|
||||
escapeString: c.EscapeString,
|
||||
}
|
||||
}
|
||||
|
||||
// ToString implements the ValueCreator interface.
|
||||
func (s StringSlice) ToString(v []string) string {
|
||||
if len(v) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%q", strings.Join(v, s.delimiter))
|
||||
}
|
||||
|
||||
// Set implements the flag.Value interface.
|
||||
func (s *StringSlice) Set(v string) error {
|
||||
if v == "" {
|
||||
*s.destination = []string{}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
out := strings.Split(v, s.delimiter)
|
||||
|
||||
//nolint:mnd
|
||||
for i := len(out) - 2; i >= 0; i-- {
|
||||
if strings.HasSuffix(out[i], s.escapeString) {
|
||||
out[i] = out[i][:len(out[i])-len(s.escapeString)] + s.delimiter + out[i+1]
|
||||
out = append(out[:i+1], out[i+2:]...)
|
||||
}
|
||||
}
|
||||
|
||||
*s.destination = out
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get implements the flag.Value interface.
|
||||
func (s *StringSlice) Get() any {
|
||||
return *s.destination
|
||||
}
|
||||
|
||||
// String implements the flag.Value interface.
|
||||
func (s *StringSlice) String() string {
|
||||
if s.destination == nil || len(*s.destination) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
return strings.Join(*s.destination, s.delimiter)
|
||||
}
|
||||
@@ -0,0 +1,225 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestStringSliceSet(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
want []string
|
||||
}{
|
||||
{
|
||||
name: "empty string",
|
||||
input: "",
|
||||
want: []string{},
|
||||
},
|
||||
{
|
||||
name: "simple comma separated",
|
||||
input: "a,b",
|
||||
want: []string{"a", "b"},
|
||||
},
|
||||
{
|
||||
name: "multiple commas",
|
||||
input: ",,,",
|
||||
want: []string{"", "", "", ""},
|
||||
},
|
||||
{
|
||||
name: "escaped comma",
|
||||
input: ",a\\,",
|
||||
want: []string{"", "a,"},
|
||||
},
|
||||
{
|
||||
name: "escaped backslash",
|
||||
input: "a,b\\,c\\\\d,e",
|
||||
want: []string{"a", "b,c\\\\d", "e"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
var got []string
|
||||
s := &StringSlice{
|
||||
destination: &got,
|
||||
delimiter: ",",
|
||||
escapeString: "\\",
|
||||
}
|
||||
|
||||
err := s.Set(tt.input)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestStringSliceString(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input []string
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "empty slice",
|
||||
input: []string{},
|
||||
want: "",
|
||||
},
|
||||
{
|
||||
name: "nil slice",
|
||||
input: nil,
|
||||
want: "",
|
||||
},
|
||||
{
|
||||
name: "single item",
|
||||
input: []string{"a"},
|
||||
want: "a",
|
||||
},
|
||||
{
|
||||
name: "multiple items",
|
||||
input: []string{"a", "b", "c"},
|
||||
want: "a,b,c",
|
||||
},
|
||||
{
|
||||
name: "items with commas",
|
||||
input: []string{"a,b", "c"},
|
||||
want: "a,b,c",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
s := &StringSlice{
|
||||
destination: &tt.input,
|
||||
delimiter: ",",
|
||||
escapeString: "\\",
|
||||
}
|
||||
|
||||
assert.Equal(t, tt.want, s.String())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestStringSliceGet(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
want []string
|
||||
}{
|
||||
{
|
||||
name: "empty slice",
|
||||
want: []string{},
|
||||
},
|
||||
{
|
||||
name: "single item",
|
||||
want: []string{"a"},
|
||||
},
|
||||
{
|
||||
name: "multiple items",
|
||||
want: []string{"a", "b", "c"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
s := &StringSlice{
|
||||
destination: &tt.want,
|
||||
delimiter: ",",
|
||||
escapeString: "\\",
|
||||
}
|
||||
|
||||
result := s.Get()
|
||||
assert.Equal(t, tt.want, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestStringSliceCreate(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input []string
|
||||
want []string
|
||||
config StringSliceConfig
|
||||
}{
|
||||
{
|
||||
name: "empty slice",
|
||||
input: nil,
|
||||
want: []string{},
|
||||
},
|
||||
{
|
||||
name: "default config",
|
||||
input: []string{"a", "b"},
|
||||
want: []string{"a", "b"},
|
||||
config: StringSliceConfig{
|
||||
Delimiter: ",",
|
||||
EscapeString: "\\",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "custom config",
|
||||
input: []string{"a", "b"},
|
||||
want: []string{"a", "b"},
|
||||
config: StringSliceConfig{
|
||||
Delimiter: ";",
|
||||
EscapeString: "#",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
var dest []string
|
||||
|
||||
s := StringSlice{}
|
||||
got := s.Create(tt.input, &dest, tt.config)
|
||||
|
||||
assert.Equal(t, tt.input, dest)
|
||||
assert.Equal(t, &dest, got.(*StringSlice).destination)
|
||||
assert.Equal(t, tt.config.Delimiter, got.(*StringSlice).delimiter)
|
||||
assert.Equal(t, tt.config.EscapeString, got.(*StringSlice).escapeString)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestStringSliceToString(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input []string
|
||||
delimiter string
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "empty slice",
|
||||
input: []string{},
|
||||
delimiter: ",",
|
||||
want: "",
|
||||
},
|
||||
{
|
||||
name: "single item",
|
||||
input: []string{"a"},
|
||||
delimiter: ",",
|
||||
want: `"a"`,
|
||||
},
|
||||
{
|
||||
name: "multiple items",
|
||||
input: []string{"a", "b", "c"},
|
||||
delimiter: ",",
|
||||
want: `"a,b,c"`,
|
||||
},
|
||||
{
|
||||
name: "custom delimiter",
|
||||
input: []string{"a", "b", "c"},
|
||||
delimiter: ";",
|
||||
want: `"a;b;c"`,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
s := StringSlice{delimiter: tt.delimiter}
|
||||
|
||||
got := s.ToString(tt.input)
|
||||
assert.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,15 @@
|
||||
module codeberg.org/woodpecker-plugins/go-plugin
|
||||
|
||||
go 1.19
|
||||
go 1.24.0
|
||||
|
||||
toolchain go1.25.1
|
||||
|
||||
require (
|
||||
github.com/joho/godotenv v1.5.1
|
||||
github.com/rs/zerolog v1.33.0
|
||||
github.com/stretchr/testify v1.9.0
|
||||
github.com/urfave/cli/v3 v3.0.0-alpha9.1
|
||||
golang.org/x/net v0.30.0
|
||||
github.com/rs/zerolog v1.34.0
|
||||
github.com/stretchr/testify v1.11.1
|
||||
github.com/urfave/cli/v3 v3.4.1
|
||||
golang.org/x/net v0.44.0
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -15,6 +17,6 @@ require (
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.19 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
golang.org/x/sys v0.26.0 // indirect
|
||||
golang.org/x/sys v0.36.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
@@ -12,20 +12,20 @@ github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
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.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8=
|
||||
github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
|
||||
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/v3 v3.0.0-alpha9.1 h1:1fJU+bltkwN8lF4Sni/X0i1d8XwPIrS82ivZ8qsp/q4=
|
||||
github.com/urfave/cli/v3 v3.0.0-alpha9.1/go.mod h1:FnIeEMYu+ko8zP1F9Ypr3xkZMIDqW3DR92yUtY39q1Y=
|
||||
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
|
||||
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
|
||||
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
|
||||
github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY=
|
||||
github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/urfave/cli/v3 v3.4.1 h1:1M9UOCy5bLmGnuu1yn3t3CB4rG79Rtoxuv1sPhnm6qM=
|
||||
github.com/urfave/cli/v3 v3.4.1/go.mod h1:FJSKtM/9AiiTOJL4fJ6TbMUkxBXn7GO9guZqoZtpYpo=
|
||||
golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I=
|
||||
golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/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.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
|
||||
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
|
||||
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
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=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
|
||||
+3
-5
@@ -16,7 +16,6 @@ package plugin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -72,15 +71,14 @@ func testMetadata() map[string]string {
|
||||
|
||||
func TestMetadata(t *testing.T) {
|
||||
for k, v := range testMetadata() {
|
||||
os.Setenv(k, v)
|
||||
defer os.Unsetenv(k)
|
||||
t.Setenv(k, v)
|
||||
}
|
||||
plugin := New(Options{
|
||||
Execute: func(ctx context.Context) error {
|
||||
Execute: func(_ context.Context) error {
|
||||
return nil
|
||||
},
|
||||
})
|
||||
err := plugin.app.Run(plugin.ctx, []string{"test"})
|
||||
err := plugin.App.Run(plugin.ctx, []string{"test"})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Repository
|
||||
|
||||
+10
-10
@@ -51,7 +51,7 @@ type Pipeline struct {
|
||||
|
||||
func pipelineFlags() []cli.Flag {
|
||||
return []cli.Flag{
|
||||
&cli.IntFlag{
|
||||
&cli.Int64Flag{
|
||||
Name: "pipeline.number",
|
||||
Usage: "pipeline number",
|
||||
Sources: cli.EnvVars(
|
||||
@@ -93,7 +93,7 @@ func pipelineFlags() []cli.Flag {
|
||||
"DRONE_DEPLOY_TO",
|
||||
),
|
||||
},
|
||||
&cli.IntFlag{
|
||||
&cli.Int64Flag{
|
||||
Name: "pipeline.created",
|
||||
Usage: "pipeline creation time",
|
||||
Sources: cli.EnvVars(
|
||||
@@ -101,7 +101,7 @@ func pipelineFlags() []cli.Flag {
|
||||
"DRONE_BUILD_CREATED",
|
||||
),
|
||||
},
|
||||
&cli.IntFlag{
|
||||
&cli.Int64Flag{
|
||||
Name: "pipeline.started",
|
||||
Usage: "pipeline start time",
|
||||
Sources: cli.EnvVars(
|
||||
@@ -109,7 +109,7 @@ func pipelineFlags() []cli.Flag {
|
||||
"DRONE_BUILD_STARTED",
|
||||
),
|
||||
},
|
||||
&cli.IntFlag{
|
||||
&cli.Int64Flag{
|
||||
Name: "pipeline.finished",
|
||||
Usage: "pipeline finish time",
|
||||
Sources: cli.EnvVars(
|
||||
@@ -117,7 +117,7 @@ func pipelineFlags() []cli.Flag {
|
||||
"DRONE_BUILD_FINISHED",
|
||||
),
|
||||
},
|
||||
&cli.IntFlag{
|
||||
&cli.Int64Flag{
|
||||
Name: "pipeline.parent",
|
||||
Usage: "pipeline parent",
|
||||
Sources: cli.EnvVars(
|
||||
@@ -146,16 +146,16 @@ func pipelineFromContext(c *cli.Command) Pipeline {
|
||||
}
|
||||
|
||||
return Pipeline{
|
||||
Number: c.Int("pipeline.number"),
|
||||
Number: c.Int64("pipeline.number"),
|
||||
Status: c.String("pipeline.status"),
|
||||
Event: c.String("pipeline.event"),
|
||||
URL: c.String("pipeline.url"),
|
||||
Link: c.String("pipeline.url"),
|
||||
DeployTarget: c.String("pipeline.deploy-target"),
|
||||
Created: time.Unix(c.Int("pipeline.created"), 0),
|
||||
Started: time.Unix(c.Int("pipeline.started"), 0),
|
||||
Finished: time.Unix(c.Int("pipeline.finished"), 0),
|
||||
Parent: c.Int("pipeline.parent"),
|
||||
Created: time.Unix(c.Int64("pipeline.created"), 0),
|
||||
Started: time.Unix(c.Int64("pipeline.started"), 0),
|
||||
Finished: time.Unix(c.Int64("pipeline.finished"), 0),
|
||||
Parent: c.Int64("pipeline.parent"),
|
||||
ChangedFiles: changedFiles,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ type Options struct {
|
||||
|
||||
// Plugin defines the plugin instance.
|
||||
type Plugin struct {
|
||||
app *cli.Command
|
||||
App *cli.Command
|
||||
execute ExecuteFunc
|
||||
client *http.Client
|
||||
ctx context.Context
|
||||
@@ -68,11 +68,11 @@ func New(opt Options) *Plugin {
|
||||
}
|
||||
|
||||
plugin := &Plugin{
|
||||
app: app,
|
||||
App: app,
|
||||
execute: opt.Execute,
|
||||
ctx: opt.Context,
|
||||
}
|
||||
plugin.app.Action = plugin.action
|
||||
plugin.App.Action = plugin.action
|
||||
|
||||
if plugin.ctx == nil {
|
||||
plugin.ctx = context.Background()
|
||||
@@ -103,7 +103,7 @@ func (p *Plugin) HTTPClient() *http.Client {
|
||||
|
||||
// Run the plugin.
|
||||
func (p *Plugin) Run() {
|
||||
if err := p.app.Run(p.ctx, os.Args); err != nil {
|
||||
if err := p.App.Run(p.ctx, os.Args); err != nil {
|
||||
log.Error().Err(err).Msg("execution failed")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
+2
-2
@@ -25,12 +25,12 @@ func TestPlugin(t *testing.T) {
|
||||
var executed bool
|
||||
p := New(Options{
|
||||
Name: "test",
|
||||
Execute: func(ctx context.Context) error {
|
||||
Execute: func(_ context.Context) error {
|
||||
executed = true
|
||||
return nil
|
||||
},
|
||||
})
|
||||
err := p.app.Run(p.ctx, []string{"test"})
|
||||
err := p.App.Run(p.ctx, []string{"test"})
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, executed)
|
||||
}
|
||||
|
||||
@@ -37,14 +37,14 @@ func stepFlags() []cli.Flag {
|
||||
"DRONE_STEP_NUMBER",
|
||||
),
|
||||
},
|
||||
&cli.IntFlag{
|
||||
&cli.Int64Flag{
|
||||
Name: "step.started",
|
||||
Usage: "step start time",
|
||||
Sources: cli.EnvVars(
|
||||
"CI_STEP_STARTED",
|
||||
),
|
||||
},
|
||||
&cli.IntFlag{
|
||||
&cli.Int64Flag{
|
||||
Name: "step.finished",
|
||||
Usage: "step finish time",
|
||||
Sources: cli.EnvVars(
|
||||
@@ -56,8 +56,8 @@ func stepFlags() []cli.Flag {
|
||||
|
||||
func stepFromContext(c *cli.Command) Step {
|
||||
return Step{
|
||||
Number: int(c.Int("step.number")),
|
||||
Started: time.Unix(c.Int("step.started"), 0),
|
||||
Finished: time.Unix(c.Int("step.finished"), 0),
|
||||
Number: c.Int("step.number"),
|
||||
Started: time.Unix(c.Int64("step.started"), 0),
|
||||
Finished: time.Unix(c.Int64("step.finished"), 0),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user