Compare commits

...

7 Commits

Author SHA1 Message Date
Bo-Yi Wu bce2f5f991 Update DOCS.md
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-07-05 20:25:02 +08:00
appleboy 30fbdbe54d docs: update notification docs for Woodpecker 3.x status changes
- Add documentation note explaining that in Woodpecker 3.x, build.status is always "success", which affects message templates
- Recommend using the when.status condition to separate success and failure notifications, with example YAML provided
- Clarify that this issue results from upstream Woodpecker CI changes and is not fixable in the plugin

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2025-07-05 20:22:59 +08:00
appleboy 9f96bb575e build: update Go formatting and GitHub actions configuration
- Remove `DIST` variable definition
- Update the `GOFMT` definition by removing the `-s` flag
- Install `gofumpt` latest version instead of an unspecified version

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2025-04-12 09:37:03 +08:00
appleboy 1b1fb67645 build: improve release management and Discord integration
- Add name_template to release section for Drone Discord version representation

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2025-04-12 09:35:09 +08:00
appleboy b2b10008a5 refactor: refactor file handling for improved readability and performance
- Clean path and check accessibility before reading file
- Replace file reading with `os.ReadFile` for simpler code
- Remove deferred file closing as file is read into `content`
- Write file content directly to multipart form
- Add comments for clearer code sections

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2025-04-11 23:40:58 +08:00
appleboy b291372e68 refactor: refactor and streamline status color handling
- Handle custom color by trimming the prefix '#'
- Refactor predefined status colors into a map
- Simplify status color handling code

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2025-04-11 23:38:09 +08:00
appleboy 691536f46b ci: revise golangci-lint configuration and update versioning
- Update golangci-lint-action used version from `v6` to `v7`
- Set specific golangci-lint version to `v2.0` instead of latest
- Remove `run` section with timeout setting in `.golangci.yaml`
- Eliminate multiple linters (`errcheck`, `gci`, `gofmt`, `goimports`) from `.golangci.yaml`
- Change `linters-settings` to `settings` in `.golangci.yaml`
- Add `int-conversion: true` to `perfsprint` settings
- Add new exclusion settings for generated code, preset rules, and specific paths under `exclusions` in `.golangci.yaml`
- Incorporate formatter settings with enabled formatters and exclusions for certain paths in `.golangci.yaml`

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2025-04-11 23:35:39 +08:00
6 changed files with 111 additions and 52 deletions
+2 -2
View File
@@ -15,9 +15,9 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup golangci-lint
uses: golangci/golangci-lint-action@v6
uses: golangci/golangci-lint-action@v7
with:
version: latest
version: v2.0
args: --verbose
- uses: hadolint/hadolint-action@v3.1.0
+40 -27
View File
@@ -1,14 +1,9 @@
run:
timeout: 5m
version: "2"
linters:
enable:
- asciicheck
- durationcheck
- errcheck
- errorlint
- gci
- gofmt
- goimports
- gosec
- misspell
- nakedret
@@ -18,24 +13,42 @@ linters:
- 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
settings:
gosec:
includes:
- G102
- G106
- G108
- G109
- G111
- G112
- G201
- G203
perfsprint:
int-conversion: true
err-error: true
errorf: true
sprintf1: true
strconcat: true
exclusions:
generated: lax
presets:
- comments
- common-false-positives
- legacy
- std-error-handling
paths:
- third_party$
- builtin$
- examples$
formatters:
enable:
- gci
- gofmt
- goimports
exclusions:
generated: lax
paths:
- third_party$
- builtin$
- examples$
+2
View File
@@ -98,6 +98,8 @@ release:
extra_files:
- glob: ./**.xz
name_template: "Drone Discord {{.Version}}"
changelog:
use: github
groups:
+28
View File
@@ -197,3 +197,31 @@ urlencode
since
: returns a duration string between now and the given timestamp. Example `{{since build.started}}`
## Note for Woodpecker 3.x Users
Starting with Woodpecker 3.x, the `build.status` variable is always set to `success`, which means message templates cannot correctly distinguish between success and failure. It is recommended to use the `when.status` condition to split notifications for success and failure, as shown below:
```yaml
- name: discord success notification
when:
status: [ success ]
image: appleboy/drone-discord
settings:
webhook_id: xxxxxxxxxx
webhook_token: xxxxxxxxxx
message: >
build {{build.number}} succeeded. Good job.
- name: discord failure notification
when:
status: [ failure ]
image: appleboy/drone-discord
settings:
webhook_id: xxxxxxxxxx
webhook_token: xxxxxxxxxx
message: >
build {{build.number}} failed. Fix me please.
```
This is due to a change in Woodpecker CI behavior and cannot be fixed on the plugin side. Please use the above workaround for correct notifications.
+2 -3
View File
@@ -1,6 +1,5 @@
DIST := dist
EXECUTABLE := drone-discord
GOFMT ?= gofumpt -l -s -w
GOFMT ?= gofumpt -l -w
GO ?= go
GOFILES := $(shell find . -name "*.go" -type f)
HAS_GO = $(shell hash $(GO) > /dev/null 2>&1 && echo "GO" || echo "NOGO" )
@@ -43,7 +42,7 @@ all: build
fmt:
@hash gofumpt > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
$(GO) install mvdan.cc/gofumpt; \
$(GO) install mvdan.cc/gofumpt@latest; \
fi
$(GOFMT) -w $(GOFILES)
+37 -20
View File
@@ -176,35 +176,49 @@ func templateMessage(t string, plugin Plugin) (string, error) {
// Creates a new file upload http request with optional extra params
// https://matt.aimonetti.net/posts/2013/07/01/golang-multipart-file-upload-example/
func fileUploadRequest(ctx context.Context, uri string, params map[string]string, paramName, path string) (*http.Request, error) {
file, err := os.Open(path)
if err != nil {
return nil, fmt.Errorf("failed to open file: %w", err)
// Clean and check path
path = filepath.Clean(path)
if _, err := os.Stat(path); err != nil {
return nil, fmt.Errorf("file %s not accessible: %w", path, err)
}
defer file.Close()
// Read file content
content, err := os.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("failed to read file %s: %w", path, err)
}
// Create multipart form
body := &bytes.Buffer{}
writer := multipart.NewWriter(body)
// Add file
part, err := writer.CreateFormFile(paramName, filepath.Base(path))
if err != nil {
return nil, fmt.Errorf("failed to create form file: %w", err)
}
if _, err = io.Copy(part, file); err != nil {
return nil, fmt.Errorf("failed to copy file content: %w", err)
if _, err = part.Write(content); err != nil {
return nil, fmt.Errorf("failed to write file content: %w", err)
}
// Add extra params
for key, val := range params {
if err = writer.WriteField(key, val); err != nil {
return nil, fmt.Errorf("failed to write field %s: %w", key, err)
}
}
if err = writer.Close(); err != nil {
return nil, fmt.Errorf("failed to close writer: %w", err)
return nil, fmt.Errorf("failed to close multipart writer: %w", err)
}
// Create request
req, err := http.NewRequestWithContext(ctx, http.MethodPost, uri, body)
if err != nil {
return nil, fmt.Errorf("failed to create new request: %w", err)
return nil, fmt.Errorf("failed to create request: %w", err)
}
req.Header.Set("Content-Type", writer.FormDataContentType())
return req, nil
}
@@ -402,22 +416,25 @@ func (p *Plugin) Clear() {
// Color code of the embed
func (p *Plugin) Color() int {
// Handle custom color
if p.Config.Color != "" {
p.Config.Color = strings.Replace(p.Config.Color, "#", "", -1)
if s, err := strconv.ParseInt(p.Config.Color, 16, 32); err == nil {
cleanColor := strings.TrimPrefix(p.Config.Color, "#")
if s, err := strconv.ParseInt(cleanColor, 16, 32); err == nil {
return int(s)
}
}
switch p.Build.Status {
case "success":
// green
return 0x1ac600
case "failure", "error", "killed":
// red
return 0xff3232
default:
// yellow
return 0xffd930
// Predefined status colors
statusColors := map[string]int{
"success": 0x1ac600, // green
"failure": 0xff3232, // red
"error": 0xff3232, // red
"killed": 0xff3232, // red
"default": 0xffd930, // yellow
}
if color, exists := statusColors[p.Build.Status]; exists {
return color
}
return statusColors["default"]
}