mirror of
https://github.com/appleboy/drone-telegram.git
synced 2026-06-14 22:11:12 +08:00
Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0917953677 | |||
| cd7b8b4656 | |||
| 530ced4f2a | |||
| 072876987d | |||
| caaf39fc08 | |||
| d746084872 | |||
| 6379123ca3 | |||
| cff7d4e183 | |||
| 7007692d2e | |||
| 23f0958c87 | |||
| c8c37942c1 | |||
| a7daa0df80 | |||
| f3ace6f519 | |||
| 4de983b4ef | |||
| b4a51bd6b6 | |||
| 30b9c501ff | |||
| cbae1a3737 | |||
| 0bc6220388 | |||
| 8587a97ab1 | |||
| 893f3c30bf |
@@ -38,11 +38,11 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v6
|
||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
# Initializes the CodeQL tools for scanning.
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@v3
|
uses: github/codeql-action/init@v4
|
||||||
with:
|
with:
|
||||||
languages: ${{ matrix.language }}
|
languages: ${{ matrix.language }}
|
||||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||||
@@ -51,4 +51,4 @@ jobs:
|
|||||||
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@v3
|
uses: github/codeql-action/analyze@v4
|
||||||
|
|||||||
@@ -10,16 +10,22 @@ on:
|
|||||||
branches:
|
branches:
|
||||||
- "master"
|
- "master"
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
packages: write
|
||||||
|
security-events: write
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-docker:
|
build-docker:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Setup go
|
- name: Setup go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version: "^1"
|
go-version: "^1"
|
||||||
|
check-latest: true
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
@@ -29,19 +35,19 @@ jobs:
|
|||||||
make build_linux_arm64
|
make build_linux_arm64
|
||||||
|
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v3
|
uses: docker/setup-qemu-action@v4
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v4
|
||||||
|
|
||||||
- name: Login to Docker Hub
|
- name: Login to Docker Hub
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v4
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Login to GitHub Container Registry
|
- name: Login to GitHub Container Registry
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v4
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.repository_owner }}
|
username: ${{ github.repository_owner }}
|
||||||
@@ -49,7 +55,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Docker meta
|
- name: Docker meta
|
||||||
id: docker-meta
|
id: docker-meta
|
||||||
uses: docker/metadata-action@v5
|
uses: docker/metadata-action@v6
|
||||||
with:
|
with:
|
||||||
images: |
|
images: |
|
||||||
${{ github.repository }}
|
${{ github.repository }}
|
||||||
@@ -60,8 +66,33 @@ jobs:
|
|||||||
type=semver,pattern={{major}}.{{minor}}
|
type=semver,pattern={{major}}.{{minor}}
|
||||||
type=semver,pattern={{major}}
|
type=semver,pattern={{major}}
|
||||||
|
|
||||||
|
- name: Build image for scanning
|
||||||
|
uses: docker/build-push-action@v7
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: docker/Dockerfile
|
||||||
|
platforms: linux/amd64
|
||||||
|
push: false
|
||||||
|
load: true
|
||||||
|
tags: drone-telegram:scan
|
||||||
|
|
||||||
|
- name: Run Trivy vulnerability scanner
|
||||||
|
uses: aquasecurity/trivy-action@v0.36.0
|
||||||
|
with:
|
||||||
|
image-ref: "drone-telegram:scan"
|
||||||
|
format: "sarif"
|
||||||
|
output: "trivy-image-results.sarif"
|
||||||
|
severity: "CRITICAL,HIGH"
|
||||||
|
exit-code: '1'
|
||||||
|
- name: Upload Trivy scan results to GitHub Security tab
|
||||||
|
uses: github/codeql-action/upload-sarif@v4
|
||||||
|
if: always()
|
||||||
|
with:
|
||||||
|
sarif_file: "trivy-image-results.sarif"
|
||||||
|
category: "trivy-docker-image"
|
||||||
|
|
||||||
- name: Build and push
|
- name: Build and push
|
||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@v7
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
platforms: linux/amd64,linux/arm64
|
platforms: linux/amd64,linux/arm64
|
||||||
|
|||||||
@@ -13,17 +13,17 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: Setup go
|
- name: Setup go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version-file: go.mod
|
go-version-file: go.mod
|
||||||
check-latest: true
|
check-latest: true
|
||||||
|
|
||||||
- name: Run GoReleaser
|
- name: Run GoReleaser
|
||||||
uses: goreleaser/goreleaser-action@v6
|
uses: goreleaser/goreleaser-action@v7
|
||||||
with:
|
with:
|
||||||
# either 'goreleaser' (default) or 'goreleaser-pro'
|
# either 'goreleaser' (default) or 'goreleaser-pro'
|
||||||
distribution: goreleaser
|
distribution: goreleaser
|
||||||
|
|||||||
+11
-10
@@ -9,21 +9,21 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v6
|
||||||
|
|
||||||
- name: Setup go
|
- name: Setup go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version-file: go.mod
|
go-version-file: go.mod
|
||||||
check-latest: true
|
check-latest: true
|
||||||
|
|
||||||
- name: Setup golangci-lint
|
- name: Setup golangci-lint
|
||||||
uses: golangci/golangci-lint-action@v6
|
uses: golangci/golangci-lint-action@v9
|
||||||
with:
|
with:
|
||||||
version: latest
|
version: v2.12
|
||||||
args: --verbose
|
args: --verbose
|
||||||
|
|
||||||
- uses: hadolint/hadolint-action@v3.1.0
|
- uses: hadolint/hadolint-action@v3.3.0
|
||||||
name: hadolint for Dockerfile
|
name: hadolint for Dockerfile
|
||||||
with:
|
with:
|
||||||
dockerfile: docker/Dockerfile
|
dockerfile: docker/Dockerfile
|
||||||
@@ -32,7 +32,7 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-latest]
|
os: [ubuntu-latest]
|
||||||
go: [1.22, 1.23]
|
go: [1.25, 1.26]
|
||||||
include:
|
include:
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
go-build: ~/.cache/go-build
|
go-build: ~/.cache/go-build
|
||||||
@@ -43,16 +43,17 @@ jobs:
|
|||||||
GOPROXY: https://proxy.golang.org
|
GOPROXY: https://proxy.golang.org
|
||||||
steps:
|
steps:
|
||||||
- name: Set up Go ${{ matrix.go }}
|
- name: Set up Go ${{ matrix.go }}
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version: ${{ matrix.go }}
|
go-version: ${{ matrix.go }}
|
||||||
|
check-latest: true
|
||||||
|
|
||||||
- name: Checkout Code
|
- name: Checkout Code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
ref: ${{ github.ref }}
|
ref: ${{ github.ref }}
|
||||||
|
|
||||||
- uses: actions/cache@v4
|
- uses: actions/cache@v5
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
${{ matrix.go-build }}
|
${{ matrix.go-build }}
|
||||||
@@ -64,6 +65,6 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
make test
|
make test
|
||||||
- name: Upload coverage to Codecov
|
- name: Upload coverage to Codecov
|
||||||
uses: codecov/codecov-action@v4
|
uses: codecov/codecov-action@v7
|
||||||
with:
|
with:
|
||||||
flags: ${{ matrix.os }},go-${{ matrix.go }}
|
flags: ${{ matrix.os }},go-${{ matrix.go }}
|
||||||
|
|||||||
@@ -0,0 +1,85 @@
|
|||||||
|
name: Trivy Security Scan
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
schedule:
|
||||||
|
# Run daily at 00:00 UTC
|
||||||
|
- cron: "0 0 * * *"
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
security-events: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
trivy-repo-scan:
|
||||||
|
name: Trivy Repository Scan
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v6
|
||||||
|
|
||||||
|
- name: Run Trivy vulnerability scanner (repo)
|
||||||
|
uses: aquasecurity/trivy-action@v0.36.0
|
||||||
|
with:
|
||||||
|
scan-type: "fs"
|
||||||
|
scan-ref: "."
|
||||||
|
format: "sarif"
|
||||||
|
output: "trivy-repo-results.sarif"
|
||||||
|
severity: "CRITICAL,HIGH"
|
||||||
|
|
||||||
|
- name: Upload Trivy scan results to GitHub Security tab
|
||||||
|
uses: github/codeql-action/upload-sarif@v4
|
||||||
|
if: always()
|
||||||
|
with:
|
||||||
|
sarif_file: "trivy-repo-results.sarif"
|
||||||
|
|
||||||
|
trivy-image-scan:
|
||||||
|
name: Trivy Image Scan
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v6
|
||||||
|
|
||||||
|
- name: Setup go
|
||||||
|
uses: actions/setup-go@v6
|
||||||
|
with:
|
||||||
|
go-version-file: go.mod
|
||||||
|
check-latest: true
|
||||||
|
|
||||||
|
- name: Build binary
|
||||||
|
run: |
|
||||||
|
make build_linux_amd64
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v4
|
||||||
|
|
||||||
|
- name: Build Docker image for scanning
|
||||||
|
uses: docker/build-push-action@v7
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: docker/Dockerfile
|
||||||
|
platforms: linux/amd64
|
||||||
|
push: false
|
||||||
|
load: true
|
||||||
|
tags: drone-telegram:scan
|
||||||
|
|
||||||
|
- name: Run Trivy vulnerability scanner (image)
|
||||||
|
uses: aquasecurity/trivy-action@v0.36.0
|
||||||
|
with:
|
||||||
|
image-ref: "drone-telegram:scan"
|
||||||
|
format: "sarif"
|
||||||
|
output: "trivy-image-results.sarif"
|
||||||
|
severity: "CRITICAL,HIGH"
|
||||||
|
|
||||||
|
- name: Upload Trivy image scan results to GitHub Security tab
|
||||||
|
uses: github/codeql-action/upload-sarif@v4
|
||||||
|
if: always()
|
||||||
|
with:
|
||||||
|
sarif_file: "trivy-image-results.sarif"
|
||||||
|
category: "trivy-image"
|
||||||
+100
-23
@@ -1,37 +1,114 @@
|
|||||||
|
version: "2"
|
||||||
|
output:
|
||||||
|
sort-order:
|
||||||
|
- file
|
||||||
linters:
|
linters:
|
||||||
disable-all: true
|
default: none
|
||||||
enable:
|
enable:
|
||||||
|
- bidichk
|
||||||
- bodyclose
|
- bodyclose
|
||||||
- dogsled
|
- depguard
|
||||||
- errcheck
|
- errcheck
|
||||||
- exportloopref
|
- forbidigo
|
||||||
- exhaustive
|
- gocheckcompilerdirectives
|
||||||
- gochecknoinits
|
|
||||||
- goconst
|
|
||||||
- gocritic
|
- gocritic
|
||||||
- gofmt
|
|
||||||
- goimports
|
|
||||||
- goprintffuncname
|
|
||||||
- gosec
|
|
||||||
- gosimple
|
|
||||||
- govet
|
- govet
|
||||||
- ineffassign
|
- ineffassign
|
||||||
- misspell
|
- mirror
|
||||||
|
- modernize
|
||||||
- nakedret
|
- nakedret
|
||||||
- noctx
|
- nilnil
|
||||||
- nolintlint
|
- nolintlint
|
||||||
|
- perfsprint
|
||||||
|
- revive
|
||||||
- staticcheck
|
- staticcheck
|
||||||
- stylecheck
|
- testifylint
|
||||||
- typecheck
|
|
||||||
- unconvert
|
- unconvert
|
||||||
- unparam
|
- unparam
|
||||||
- unused
|
- unused
|
||||||
- whitespace
|
- usestdlibvars
|
||||||
- gofumpt
|
- usetesting
|
||||||
|
- wastedassign
|
||||||
issues:
|
settings:
|
||||||
exclude-rules:
|
depguard:
|
||||||
# Exclude `lll` issues for long lines with `go:generate`.
|
rules:
|
||||||
|
main:
|
||||||
|
deny:
|
||||||
|
- pkg: io/ioutil
|
||||||
|
desc: use os or io instead
|
||||||
|
- pkg: golang.org/x/exp
|
||||||
|
desc: it's experimental and unreliable
|
||||||
|
- pkg: github.com/pkg/errors
|
||||||
|
desc: use builtin errors package instead
|
||||||
|
nolintlint:
|
||||||
|
allow-unused: false
|
||||||
|
require-explanation: true
|
||||||
|
require-specific: true
|
||||||
|
gocritic:
|
||||||
|
enabled-checks:
|
||||||
|
- equalFold
|
||||||
|
disabled-checks: []
|
||||||
|
revive:
|
||||||
|
severity: error
|
||||||
|
rules:
|
||||||
|
- name: blank-imports
|
||||||
|
- name: constant-logical-expr
|
||||||
|
- name: context-as-argument
|
||||||
|
- name: context-keys-type
|
||||||
|
- name: dot-imports
|
||||||
|
- name: empty-lines
|
||||||
|
- name: error-return
|
||||||
|
- name: error-strings
|
||||||
|
- name: exported
|
||||||
|
- name: identical-branches
|
||||||
|
- name: if-return
|
||||||
|
- name: increment-decrement
|
||||||
|
- name: modifies-value-receiver
|
||||||
|
- name: package-comments
|
||||||
|
- name: redefines-builtin-id
|
||||||
|
- name: superfluous-else
|
||||||
|
- name: time-naming
|
||||||
|
- name: unexported-return
|
||||||
|
- name: var-declaration
|
||||||
|
- name: var-naming
|
||||||
|
disabled: true
|
||||||
|
staticcheck:
|
||||||
|
checks:
|
||||||
|
- all
|
||||||
|
testifylint: {}
|
||||||
|
usetesting:
|
||||||
|
os-temp-dir: true
|
||||||
|
perfsprint:
|
||||||
|
concat-loop: false
|
||||||
|
govet:
|
||||||
|
enable:
|
||||||
|
- nilness
|
||||||
|
- unusedwrite
|
||||||
|
exclusions:
|
||||||
|
generated: lax
|
||||||
|
presets:
|
||||||
|
- comments
|
||||||
|
- common-false-positives
|
||||||
|
- legacy
|
||||||
|
- std-error-handling
|
||||||
|
rules:
|
||||||
- linters:
|
- linters:
|
||||||
- lll
|
- errcheck
|
||||||
source: "^//go:generate "
|
- staticcheck
|
||||||
|
- unparam
|
||||||
|
path: _test\.go
|
||||||
|
issues:
|
||||||
|
max-issues-per-linter: 0
|
||||||
|
max-same-issues: 0
|
||||||
|
formatters:
|
||||||
|
enable:
|
||||||
|
- gofmt
|
||||||
|
- gofumpt
|
||||||
|
- golines
|
||||||
|
settings:
|
||||||
|
gofumpt:
|
||||||
|
extra-rules: true
|
||||||
|
exclusions:
|
||||||
|
generated: lax
|
||||||
|
run:
|
||||||
|
timeout: 10m
|
||||||
|
|||||||
@@ -1,11 +1,17 @@
|
|||||||
---
|
---
|
||||||
date: 2019-10-19T00:00:00+00:00
|
date: 2019-10-19T00:00:00+00:00
|
||||||
title: Telegram
|
|
||||||
author: appleboy
|
author: appleboy
|
||||||
tags: [ notifications, chat ]
|
containerImage: docker.io/appleboy/drone-telegram
|
||||||
repo: appleboy/drone-telegram
|
containerImageUrl: https://hub.docker.com/r/appleboy/drone-telegram
|
||||||
logo: telegram.svg
|
description: Plugin for sending Telegram notifications
|
||||||
|
icon: https://raw.githubusercontent.com/appleboy/drone-telegram/refs/heads/master/images/logo.svg
|
||||||
image: appleboy/drone-telegram
|
image: appleboy/drone-telegram
|
||||||
|
logo: telegram.svg
|
||||||
|
name: Telegram
|
||||||
|
repo: appleboy/drone-telegram
|
||||||
|
tags: [ notifications, chat ]
|
||||||
|
title: Telegram
|
||||||
|
url: https://github.com/appleboy/drone-telegram
|
||||||
---
|
---
|
||||||
|
|
||||||
The Telegram plugin posts build status messages to your account. The below pipeline configuration demonstrates simple usage:
|
The Telegram plugin posts build status messages to your account. The below pipeline configuration demonstrates simple usage:
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
DIST := dist
|
|
||||||
EXECUTABLE := drone-telegram
|
EXECUTABLE := drone-telegram
|
||||||
GOFMT ?= gofumpt -l
|
GOFMT ?= gofumpt -l
|
||||||
DIST := dist
|
DIST := dist
|
||||||
@@ -9,7 +8,7 @@ GOFILES := $(shell find . -name "*.go" -type f)
|
|||||||
HAS_GO = $(shell hash $(GO) > /dev/null 2>&1 && echo "GO" || echo "NOGO" )
|
HAS_GO = $(shell hash $(GO) > /dev/null 2>&1 && echo "GO" || echo "NOGO" )
|
||||||
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
|
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
|
||||||
XGO_VERSION := go-1.19.x
|
XGO_VERSION := go-1.19.x
|
||||||
GXZ_PAGAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.11
|
GXZ_PACKAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.11
|
||||||
|
|
||||||
LINUX_ARCHS ?= linux/amd64,linux/arm64
|
LINUX_ARCHS ?= linux/amd64,linux/arm64
|
||||||
DARWIN_ARCHS ?= darwin-10.12/amd64,darwin-10.12/arm64
|
DARWIN_ARCHS ?= darwin-10.12/amd64,darwin-10.12/arm64
|
||||||
@@ -116,7 +115,7 @@ coverage:
|
|||||||
.PHONY: deps-backend
|
.PHONY: deps-backend
|
||||||
deps-backend:
|
deps-backend:
|
||||||
$(GO) mod download
|
$(GO) mod download
|
||||||
$(GO) install $(GXZ_PAGAGE)
|
$(GO) install $(GXZ_PACKAGE)
|
||||||
$(GO) install $(XGO_PACKAGE)
|
$(GO) install $(XGO_PACKAGE)
|
||||||
|
|
||||||
.PHONY: release
|
.PHONY: release
|
||||||
@@ -156,7 +155,7 @@ release-check: | $(DIST_DIRS)
|
|||||||
|
|
||||||
.PHONY: release-compress
|
.PHONY: release-compress
|
||||||
release-compress: | $(DIST_DIRS)
|
release-compress: | $(DIST_DIRS)
|
||||||
cd $(DIST)/release/; for file in `find . -type f -name "*"`; do echo "compressing $${file}" && $(GO) run $(GXZ_PAGAGE) -k -9 $${file}; done;
|
cd $(DIST)/release/; for file in `find . -type f -name "*"`; do echo "compressing $${file}" && $(GO) run $(GXZ_PACKAGE) -k -9 $${file}; done;
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
$(GO) clean -x -i ./...
|
$(GO) clean -x -i ./...
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||

|

|
||||||
|
|
||||||
[](https://godoc.org/github.com/appleboy/drone-telegram)
|
[](https://godoc.org/github.com/appleboy/drone-telegram)
|
||||||
|
[](https://github.com/appleboy/drone-telegram/actions/workflows/trivy.yml)
|
||||||
[](https://codecov.io/gh/appleboy/drone-telegram)
|
[](https://codecov.io/gh/appleboy/drone-telegram)
|
||||||
[](https://goreportcard.com/report/github.com/appleboy/drone-telegram)
|
[](https://goreportcard.com/report/github.com/appleboy/drone-telegram)
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
FROM alpine:3.17
|
FROM alpine:3.23
|
||||||
|
|
||||||
ARG TARGETOS
|
ARG TARGETOS
|
||||||
ARG TARGETARCH
|
ARG TARGETARCH
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
module github.com/appleboy/drone-telegram
|
module github.com/appleboy/drone-telegram
|
||||||
|
|
||||||
go 1.22
|
go 1.25.10
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/appleboy/drone-template-lib v1.3.0
|
github.com/appleboy/drone-template-lib v1.3.0
|
||||||
@@ -28,7 +28,7 @@ require (
|
|||||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||||
github.com/spf13/cast v1.7.0 // indirect
|
github.com/spf13/cast v1.7.0 // indirect
|
||||||
github.com/technoweenie/multipartstreamer v1.0.1 // indirect
|
github.com/technoweenie/multipartstreamer v1.0.1 // indirect
|
||||||
golang.org/x/crypto v0.27.0 // indirect
|
golang.org/x/crypto v0.45.0 // indirect
|
||||||
golang.org/x/sys v0.25.0 // indirect
|
golang.org/x/sys v0.38.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -64,12 +64,12 @@ github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQ
|
|||||||
github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog=
|
github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog=
|
||||||
github.com/urfave/cli v1.22.15 h1:nuqt+pdC/KqswQKhETJjo7pvn/k4xMUxgW6liI7XpnM=
|
github.com/urfave/cli v1.22.15 h1:nuqt+pdC/KqswQKhETJjo7pvn/k4xMUxgW6liI7XpnM=
|
||||||
github.com/urfave/cli v1.22.15/go.mod h1:wSan1hmo5zeyLGBjRJbzRTNk8gwoYa2B9n4q9dmRIc0=
|
github.com/urfave/cli v1.22.15/go.mod h1:wSan1hmo5zeyLGBjRJbzRTNk8gwoYa2B9n4q9dmRIc0=
|
||||||
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
|
golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q=
|
||||||
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
|
golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4=
|
||||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
|
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
|
||||||
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.38.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 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"html"
|
"html"
|
||||||
"io"
|
|
||||||
"log"
|
"log"
|
||||||
|
"maps"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
@@ -118,10 +117,10 @@ var icons = map[string]string{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func trimElement(keys []string) []string {
|
func trimElement(keys []string) []string {
|
||||||
var newKeys []string
|
newKeys := make([]string, 0, len(keys))
|
||||||
|
|
||||||
for _, value := range keys {
|
for _, value := range keys {
|
||||||
value = strings.Trim(value, " ")
|
value = strings.TrimSpace(value)
|
||||||
if len(value) == 0 {
|
if len(value) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -132,7 +131,7 @@ func trimElement(keys []string) []string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func escapeMarkdown(keys []string) []string {
|
func escapeMarkdown(keys []string) []string {
|
||||||
var newKeys []string
|
newKeys := make([]string, 0, len(keys))
|
||||||
|
|
||||||
for _, value := range keys {
|
for _, value := range keys {
|
||||||
value = escapeMarkdownOne(value)
|
value = escapeMarkdownOne(value)
|
||||||
@@ -152,14 +151,20 @@ func escapeMarkdownOne(str string) string {
|
|||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func escapeMarkdownFields(fields ...*string) {
|
||||||
|
for _, f := range fields {
|
||||||
|
*f = escapeMarkdownOne(*f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func globList(keys []string) []string {
|
func globList(keys []string) []string {
|
||||||
var newKeys []string
|
newKeys := make([]string, 0, len(keys))
|
||||||
|
|
||||||
for _, pattern := range keys {
|
for _, pattern := range keys {
|
||||||
pattern = strings.Trim(pattern, " ")
|
pattern = strings.TrimSpace(pattern)
|
||||||
matches, err := filepath.Glob(pattern)
|
matches, err := filepath.Glob(pattern)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Glob error for %q: %s\n", pattern, err)
|
log.Printf("Glob error for %q: %s", pattern, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
newKeys = append(newKeys, matches...)
|
newKeys = append(newKeys, matches...)
|
||||||
@@ -183,7 +188,6 @@ func convertLocation(value string) (Location, bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(values) > 3 {
|
if len(values) > 3 {
|
||||||
title = values[2]
|
|
||||||
address = values[3]
|
address = values[3]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,13 +212,7 @@ func convertLocation(value string) (Location, bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func loadTextFromFile(filename string) ([]string, error) {
|
func loadTextFromFile(filename string) ([]string, error) {
|
||||||
f, err := os.Open(filename)
|
content, err := os.ReadFile(filename)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
r := bufio.NewReader(f)
|
|
||||||
content, err := io.ReadAll(r)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -258,12 +256,8 @@ func parseTo(to []string, authorEmail string, matchEmail bool) []int64 {
|
|||||||
return ids
|
return ids
|
||||||
}
|
}
|
||||||
|
|
||||||
func templateMessage(t string, plugin Plugin) (string, error) {
|
|
||||||
return template.RenderTrim(t, plugin)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Exec executes the plugin.
|
// Exec executes the plugin.
|
||||||
func (p Plugin) Exec() (err error) {
|
func (p *Plugin) Exec() (err error) {
|
||||||
if len(p.Config.Token) == 0 || len(p.Config.To) == 0 {
|
if len(p.Config.Token) == 0 || len(p.Config.To) == 0 {
|
||||||
return errors.New("missing telegram token or user list")
|
return errors.New("missing telegram token or user list")
|
||||||
}
|
}
|
||||||
@@ -273,7 +267,7 @@ func (p Plugin) Exec() (err error) {
|
|||||||
case len(p.Config.MessageFile) > 0:
|
case len(p.Config.MessageFile) > 0:
|
||||||
message, err = loadTextFromFile(p.Config.MessageFile)
|
message, err = loadTextFromFile(p.Config.MessageFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error loading message file '%s': %v", p.Config.MessageFile, err)
|
return fmt.Errorf("error loading message file '%s': %w", p.Config.MessageFile, err)
|
||||||
}
|
}
|
||||||
case len(p.Config.Message) > 0:
|
case len(p.Config.Message) > 0:
|
||||||
message = []string{p.Config.Message}
|
message = []string{p.Config.Message}
|
||||||
@@ -285,36 +279,46 @@ func (p Plugin) Exec() (err error) {
|
|||||||
if p.Config.TemplateVars != "" {
|
if p.Config.TemplateVars != "" {
|
||||||
p.Tpl = make(map[string]string)
|
p.Tpl = make(map[string]string)
|
||||||
if err = json.Unmarshal([]byte(p.Config.TemplateVars), &p.Tpl); err != nil {
|
if err = json.Unmarshal([]byte(p.Config.TemplateVars), &p.Tpl); err != nil {
|
||||||
return fmt.Errorf("unable to unmarshall template vars from JSON string '%s': %v", p.Config.TemplateVars, err)
|
return fmt.Errorf(
|
||||||
|
"unable to unmarshal template vars from JSON string '%s': %w",
|
||||||
|
p.Config.TemplateVars,
|
||||||
|
err,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.Config.TemplateVarsFile != "" {
|
if p.Config.TemplateVarsFile != "" {
|
||||||
content, err := os.ReadFile(p.Config.TemplateVarsFile)
|
content, err := os.ReadFile(p.Config.TemplateVarsFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to read file with template vars '%s': %v", p.Config.TemplateVarsFile, err)
|
return fmt.Errorf(
|
||||||
|
"unable to read file with template vars '%s': %w",
|
||||||
|
p.Config.TemplateVarsFile,
|
||||||
|
err,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
vars := make(map[string]string)
|
vars := make(map[string]string)
|
||||||
if err = json.Unmarshal(content, &vars); err != nil {
|
if err = json.Unmarshal(content, &vars); err != nil {
|
||||||
return fmt.Errorf("unable to unmarshall template vars from JSON file '%s': %v", p.Config.TemplateVarsFile, err)
|
return fmt.Errorf(
|
||||||
|
"unable to unmarshal template vars from JSON file '%s': %w",
|
||||||
|
p.Config.TemplateVarsFile,
|
||||||
|
err,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
// Merging templates variables from file to the variables form plugin settings (variables from file takes precedence)
|
// File variables take precedence over inline variables
|
||||||
if p.Tpl == nil {
|
if p.Tpl == nil {
|
||||||
p.Tpl = vars
|
p.Tpl = vars
|
||||||
} else {
|
} else {
|
||||||
for k, v := range vars {
|
maps.Copy(p.Tpl, vars)
|
||||||
p.Tpl[k] = v
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
var proxyURL *url.URL
|
|
||||||
if proxyURL, err = url.Parse(p.Config.Socks5); err != nil {
|
|
||||||
return fmt.Errorf("unable to unmarshall socks5 proxy url from string '%s': %v", p.Config.Socks5, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var bot *tgbotapi.BotAPI
|
var bot *tgbotapi.BotAPI
|
||||||
if len(p.Config.Socks5) > 0 {
|
if len(p.Config.Socks5) > 0 {
|
||||||
|
var proxyURL *url.URL
|
||||||
|
proxyURL, err = url.Parse(p.Config.Socks5)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to parse socks5 proxy URL '%s': %w", p.Config.Socks5, err)
|
||||||
|
}
|
||||||
proxyClient := &http.Client{Transport: &http.Transport{Proxy: http.ProxyURL(proxyURL)}}
|
proxyClient := &http.Client{Transport: &http.Transport{Proxy: http.ProxyURL(proxyURL)}}
|
||||||
bot, err = tgbotapi.NewBotAPIWithClient(p.Config.Token, proxyClient)
|
bot, err = tgbotapi.NewBotAPIWithClient(p.Config.Token, proxyClient)
|
||||||
} else {
|
} else {
|
||||||
@@ -328,12 +332,12 @@ func (p Plugin) Exec() (err error) {
|
|||||||
bot.Debug = p.Config.Debug
|
bot.Debug = p.Config.Debug
|
||||||
|
|
||||||
ids := parseTo(p.Config.To, p.Commit.Email, p.Config.MatchEmail)
|
ids := parseTo(p.Config.To, p.Commit.Email, p.Config.MatchEmail)
|
||||||
photos := globList(trimElement(p.Config.Photo))
|
photos := globList(p.Config.Photo)
|
||||||
documents := globList(trimElement(p.Config.Document))
|
documents := globList(p.Config.Document)
|
||||||
stickers := globList(trimElement(p.Config.Sticker))
|
stickers := globList(p.Config.Sticker)
|
||||||
audios := globList(trimElement(p.Config.Audio))
|
audios := globList(p.Config.Audio)
|
||||||
voices := globList(trimElement(p.Config.Voice))
|
voices := globList(p.Config.Voice)
|
||||||
videos := globList(trimElement(p.Config.Video))
|
videos := globList(p.Config.Video)
|
||||||
locations := trimElement(p.Config.Location)
|
locations := trimElement(p.Config.Location)
|
||||||
venues := trimElement(p.Config.Venue)
|
venues := trimElement(p.Config.Venue)
|
||||||
|
|
||||||
@@ -342,30 +346,43 @@ func (p Plugin) Exec() (err error) {
|
|||||||
if p.Config.Format == formatMarkdown {
|
if p.Config.Format == formatMarkdown {
|
||||||
message = escapeMarkdown(message)
|
message = escapeMarkdown(message)
|
||||||
|
|
||||||
p.Commit.Message = escapeMarkdownOne(p.Commit.Message)
|
escapeMarkdownFields(
|
||||||
p.Commit.Branch = escapeMarkdownOne(p.Commit.Branch)
|
&p.Commit.Message, &p.Commit.Branch, &p.Commit.Link,
|
||||||
p.Commit.Link = escapeMarkdownOne(p.Commit.Link)
|
&p.Commit.Author, &p.Commit.Email,
|
||||||
p.Commit.Author = escapeMarkdownOne(p.Commit.Author)
|
&p.Build.Tag, &p.Build.Link, &p.Build.PR,
|
||||||
p.Commit.Email = escapeMarkdownOne(p.Commit.Email)
|
&p.Repo.Namespace, &p.Repo.Name,
|
||||||
|
)
|
||||||
p.Build.Tag = escapeMarkdownOne(p.Build.Tag)
|
|
||||||
p.Build.Link = escapeMarkdownOne(p.Build.Link)
|
|
||||||
p.Build.PR = escapeMarkdownOne(p.Build.PR)
|
|
||||||
|
|
||||||
p.Repo.Namespace = escapeMarkdownOne(p.Repo.Namespace)
|
|
||||||
p.Repo.Name = escapeMarkdownOne(p.Repo.Name)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// send message.
|
// pre-render message templates (identical for all users)
|
||||||
for _, user := range ids {
|
var renderedMessages []string
|
||||||
for _, value := range message {
|
for _, value := range message {
|
||||||
txt, err := templateMessage(value, p)
|
txt, err := template.RenderTrim(value, p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
renderedMessages = append(renderedMessages, html.UnescapeString(txt))
|
||||||
|
}
|
||||||
|
|
||||||
txt = html.UnescapeString(txt)
|
// pre-parse locations and venues (identical for all users)
|
||||||
|
var parsedLocations []Location
|
||||||
|
for _, value := range locations {
|
||||||
|
loc, empty := convertLocation(value)
|
||||||
|
if !empty {
|
||||||
|
parsedLocations = append(parsedLocations, loc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var parsedVenues []Location
|
||||||
|
for _, value := range venues {
|
||||||
|
loc, empty := convertLocation(value)
|
||||||
|
if !empty {
|
||||||
|
parsedVenues = append(parsedVenues, loc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, user := range ids {
|
||||||
|
for _, txt := range renderedMessages {
|
||||||
msg := tgbotapi.NewMessage(user, txt)
|
msg := tgbotapi.NewMessage(user, txt)
|
||||||
msg.ParseMode = p.Config.Format
|
msg.ParseMode = p.Config.Format
|
||||||
msg.DisableWebPagePreview = p.Config.DisableWebPagePreview
|
msg.DisableWebPagePreview = p.Config.DisableWebPagePreview
|
||||||
@@ -398,7 +415,7 @@ func (p Plugin) Exec() (err error) {
|
|||||||
|
|
||||||
for _, value := range audios {
|
for _, value := range audios {
|
||||||
msg := tgbotapi.NewAudioUpload(user, value)
|
msg := tgbotapi.NewAudioUpload(user, value)
|
||||||
msg.Title = "Audio Message."
|
msg.Title = "Audio Message"
|
||||||
if err := p.Send(bot, msg); err != nil {
|
if err := p.Send(bot, msg); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -419,27 +436,21 @@ func (p Plugin) Exec() (err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, value := range locations {
|
for _, loc := range parsedLocations {
|
||||||
location, empty := convertLocation(value)
|
msg := tgbotapi.NewLocation(user, loc.Latitude, loc.Longitude)
|
||||||
|
|
||||||
if empty {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
msg := tgbotapi.NewLocation(user, location.Latitude, location.Longitude)
|
|
||||||
if err := p.Send(bot, msg); err != nil {
|
if err := p.Send(bot, msg); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, value := range venues {
|
for _, loc := range parsedVenues {
|
||||||
location, empty := convertLocation(value)
|
msg := tgbotapi.NewVenue(
|
||||||
|
user,
|
||||||
if empty {
|
loc.Title,
|
||||||
continue
|
loc.Address,
|
||||||
}
|
loc.Latitude,
|
||||||
|
loc.Longitude,
|
||||||
msg := tgbotapi.NewVenue(user, location.Title, location.Address, location.Latitude, location.Longitude)
|
)
|
||||||
if err := p.Send(bot, msg); err != nil {
|
if err := p.Send(bot, msg); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -450,7 +461,7 @@ func (p Plugin) Exec() (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Send bot message.
|
// Send bot message.
|
||||||
func (p Plugin) Send(bot *tgbotapi.BotAPI, msg tgbotapi.Chattable) error {
|
func (p *Plugin) Send(bot *tgbotapi.BotAPI, msg tgbotapi.Chattable) error {
|
||||||
message, err := bot.Send(msg)
|
message, err := bot.Send(msg)
|
||||||
|
|
||||||
if p.Config.Debug {
|
if p.Config.Debug {
|
||||||
@@ -467,7 +478,7 @@ func (p Plugin) Send(bot *tgbotapi.BotAPI, msg tgbotapi.Chattable) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Message is plugin default message.
|
// Message is plugin default message.
|
||||||
func (p Plugin) Message() []string {
|
func (p *Plugin) Message() []string {
|
||||||
icon := icons[strings.ToLower(p.Build.Status)]
|
icon := icons[strings.ToLower(p.Build.Status)]
|
||||||
|
|
||||||
if p.Config.GitHub {
|
if p.Config.GitHub {
|
||||||
@@ -485,7 +496,8 @@ func (p Plugin) Message() []string {
|
|||||||
// chore: update default template
|
// chore: update default template
|
||||||
//
|
//
|
||||||
// 🌐 https://cloud.drone.io/appleboy/drone-telegram/106
|
// 🌐 https://cloud.drone.io/appleboy/drone-telegram/106
|
||||||
return []string{fmt.Sprintf("%s Build #%d of `%s` %s.\n\n📝 Commit by %s on `%s`:\n``` %s ```\n\n🌐 %s",
|
return []string{
|
||||||
|
fmt.Sprintf("%s Build #%d of `%s` %s.\n\n📝 Commit by %s on `%s`:\n``` %s ```\n\n🌐 %s",
|
||||||
icon,
|
icon,
|
||||||
p.Build.Number,
|
p.Build.Number,
|
||||||
p.Repo.FullName,
|
p.Repo.FullName,
|
||||||
@@ -494,5 +506,6 @@ func (p Plugin) Message() []string {
|
|||||||
p.Commit.Branch,
|
p.Commit.Branch,
|
||||||
p.Commit.Message,
|
p.Commit.Message,
|
||||||
p.Build.Link,
|
p.Build.Link,
|
||||||
)}
|
),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+63
-28
@@ -7,14 +7,22 @@ import (
|
|||||||
|
|
||||||
"github.com/appleboy/drone-template-lib/template"
|
"github.com/appleboy/drone-template-lib/template"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func skipIfNoTelegramSecrets(t *testing.T) {
|
||||||
|
t.Helper()
|
||||||
|
if os.Getenv("TELEGRAM_TOKEN") == "" || os.Getenv("TELEGRAM_TO") == "" {
|
||||||
|
t.Skip("TELEGRAM_TOKEN/TELEGRAM_TO not set; skipping integration test")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestMissingDefaultConfig(t *testing.T) {
|
func TestMissingDefaultConfig(t *testing.T) {
|
||||||
var plugin Plugin
|
var plugin Plugin
|
||||||
|
|
||||||
err := plugin.Exec()
|
err := plugin.Exec()
|
||||||
|
|
||||||
assert.NotNil(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMissingUserConfig(t *testing.T) {
|
func TestMissingUserConfig(t *testing.T) {
|
||||||
@@ -26,7 +34,7 @@ func TestMissingUserConfig(t *testing.T) {
|
|||||||
|
|
||||||
err := plugin.Exec()
|
err := plugin.Exec()
|
||||||
|
|
||||||
assert.NotNil(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDefaultMessageFormat(t *testing.T) {
|
func TestDefaultMessageFormat(t *testing.T) {
|
||||||
@@ -51,7 +59,13 @@ func TestDefaultMessageFormat(t *testing.T) {
|
|||||||
|
|
||||||
message := plugin.Message()
|
message := plugin.Message()
|
||||||
|
|
||||||
assert.Equal(t, []string{"✅ Build #101 of `appleboy/go-hello` success.\n\n📝 Commit by Bo-Yi Wu on `master`:\n``` update travis ```\n\n🌐 https://github.com/appleboy/go-hello"}, message)
|
assert.Equal(
|
||||||
|
t,
|
||||||
|
[]string{
|
||||||
|
"✅ Build #101 of `appleboy/go-hello` success.\n\n📝 Commit by Bo-Yi Wu on `master`:\n``` update travis ```\n\n🌐 https://github.com/appleboy/go-hello",
|
||||||
|
},
|
||||||
|
message,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDefaultMessageFormatFromGitHub(t *testing.T) {
|
func TestDefaultMessageFormatFromGitHub(t *testing.T) {
|
||||||
@@ -73,7 +87,11 @@ func TestDefaultMessageFormatFromGitHub(t *testing.T) {
|
|||||||
|
|
||||||
message := plugin.Message()
|
message := plugin.Message()
|
||||||
|
|
||||||
assert.Equal(t, []string{"appleboy/go-hello/test-workflow triggered by appleboy (push)"}, message)
|
assert.Equal(
|
||||||
|
t,
|
||||||
|
[]string{"appleboy/go-hello/test-workflow triggered by appleboy (push)"},
|
||||||
|
message,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSendMessage(t *testing.T) {
|
func TestSendMessage(t *testing.T) {
|
||||||
@@ -98,7 +116,12 @@ func TestSendMessage(t *testing.T) {
|
|||||||
|
|
||||||
Config: Config{
|
Config: Config{
|
||||||
Token: os.Getenv("TELEGRAM_TOKEN"),
|
Token: os.Getenv("TELEGRAM_TOKEN"),
|
||||||
To: []string{os.Getenv("TELEGRAM_TO"), os.Getenv("TELEGRAM_TO") + ":appleboy@gmail.com", "中文ID", "1234567890"},
|
To: []string{
|
||||||
|
os.Getenv("TELEGRAM_TO"),
|
||||||
|
os.Getenv("TELEGRAM_TO") + ":appleboy@gmail.com",
|
||||||
|
"中文ID",
|
||||||
|
"1234567890",
|
||||||
|
},
|
||||||
Message: "Test Telegram Chat Bot From Travis or Local, commit message: 『{{ build.message }}』",
|
Message: "Test Telegram Chat Bot From Travis or Local, commit message: 『{{ build.message }}』",
|
||||||
Photo: []string{"tests/github.png", "1234", " "},
|
Photo: []string{"tests/github.png", "1234", " "},
|
||||||
Document: []string{"tests/gophercolor.png", "1234", " "},
|
Document: []string{"tests/gophercolor.png", "1234", " "},
|
||||||
@@ -106,27 +129,33 @@ func TestSendMessage(t *testing.T) {
|
|||||||
Audio: []string{"tests/audio.mp3", "1234", " "},
|
Audio: []string{"tests/audio.mp3", "1234", " "},
|
||||||
Voice: []string{"tests/voice.ogg", "1234", " "},
|
Voice: []string{"tests/voice.ogg", "1234", " "},
|
||||||
Location: []string{"24.9163213 121.1424972", "1", " "},
|
Location: []string{"24.9163213 121.1424972", "1", " "},
|
||||||
Venue: []string{"35.661777 139.704051 竹北體育館 新竹縣竹北市", "24.9163213 121.1424972", "1", " "},
|
Venue: []string{
|
||||||
|
"35.661777 139.704051 竹北體育館 新竹縣竹北市",
|
||||||
|
"24.9163213 121.1424972",
|
||||||
|
"1",
|
||||||
|
" ",
|
||||||
|
},
|
||||||
Video: []string{"tests/video.mp4", "1234", " "},
|
Video: []string{"tests/video.mp4", "1234", " "},
|
||||||
Debug: false,
|
Debug: false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
err := plugin.Exec()
|
err := plugin.Exec()
|
||||||
assert.NotNil(t, err)
|
require.Error(t, err)
|
||||||
|
|
||||||
plugin.Config.Format = formatMarkdown
|
plugin.Config.Format = formatMarkdown
|
||||||
plugin.Config.Message = "Test escape under_score"
|
plugin.Config.Message = "Test escape under_score"
|
||||||
err = plugin.Exec()
|
err = plugin.Exec()
|
||||||
assert.NotNil(t, err)
|
require.Error(t, err)
|
||||||
|
|
||||||
// disable message
|
// disable message
|
||||||
plugin.Config.Message = ""
|
plugin.Config.Message = ""
|
||||||
err = plugin.Exec()
|
err = plugin.Exec()
|
||||||
assert.NotNil(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDisableWebPagePreviewMessage(t *testing.T) {
|
func TestDisableWebPagePreviewMessage(t *testing.T) {
|
||||||
|
skipIfNoTelegramSecrets(t)
|
||||||
plugin := Plugin{
|
plugin := Plugin{
|
||||||
Config: Config{
|
Config: Config{
|
||||||
Token: os.Getenv("TELEGRAM_TOKEN"),
|
Token: os.Getenv("TELEGRAM_TOKEN"),
|
||||||
@@ -138,16 +167,17 @@ func TestDisableWebPagePreviewMessage(t *testing.T) {
|
|||||||
|
|
||||||
plugin.Config.Message = "DisableWebPagePreview https://www.google.com.tw"
|
plugin.Config.Message = "DisableWebPagePreview https://www.google.com.tw"
|
||||||
err := plugin.Exec()
|
err := plugin.Exec()
|
||||||
assert.Nil(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// disable message
|
// disable message
|
||||||
plugin.Config.DisableWebPagePreview = false
|
plugin.Config.DisableWebPagePreview = false
|
||||||
plugin.Config.Message = "EnableWebPagePreview https://www.google.com.tw"
|
plugin.Config.Message = "EnableWebPagePreview https://www.google.com.tw"
|
||||||
err = plugin.Exec()
|
err = plugin.Exec()
|
||||||
assert.Nil(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDisableNotificationMessage(t *testing.T) {
|
func TestDisableNotificationMessage(t *testing.T) {
|
||||||
|
skipIfNoTelegramSecrets(t)
|
||||||
plugin := Plugin{
|
plugin := Plugin{
|
||||||
Config: Config{
|
Config: Config{
|
||||||
Token: os.Getenv("TELEGRAM_TOKEN"),
|
Token: os.Getenv("TELEGRAM_TOKEN"),
|
||||||
@@ -159,13 +189,13 @@ func TestDisableNotificationMessage(t *testing.T) {
|
|||||||
|
|
||||||
plugin.Config.Message = "DisableNotification https://www.google.com.tw"
|
plugin.Config.Message = "DisableNotification https://www.google.com.tw"
|
||||||
err := plugin.Exec()
|
err := plugin.Exec()
|
||||||
assert.Nil(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// disable message
|
// disable message
|
||||||
plugin.Config.DisableNotification = false
|
plugin.Config.DisableNotification = false
|
||||||
plugin.Config.Message = "EnableNotification https://www.google.com.tw"
|
plugin.Config.Message = "EnableNotification https://www.google.com.tw"
|
||||||
err = plugin.Exec()
|
err = plugin.Exec()
|
||||||
assert.Nil(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBotError(t *testing.T) {
|
func TestBotError(t *testing.T) {
|
||||||
@@ -194,7 +224,7 @@ func TestBotError(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
err := plugin.Exec()
|
err := plugin.Exec()
|
||||||
assert.NotNil(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTrimElement(t *testing.T) {
|
func TestTrimElement(t *testing.T) {
|
||||||
@@ -270,7 +300,7 @@ func TestParseTo(t *testing.T) {
|
|||||||
|
|
||||||
// test empty ids
|
// test empty ids
|
||||||
ids = parseTo([]string{"", " ", " "}, "a@gmail.com", true)
|
ids = parseTo([]string{"", " ", " "}, "a@gmail.com", true)
|
||||||
assert.Equal(t, 0, len(ids))
|
assert.Empty(t, ids)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGlobList(t *testing.T) {
|
func TestGlobList(t *testing.T) {
|
||||||
@@ -294,27 +324,27 @@ func TestConvertLocation(t *testing.T) {
|
|||||||
input = "1"
|
input = "1"
|
||||||
result, empty = convertLocation(input)
|
result, empty = convertLocation(input)
|
||||||
|
|
||||||
assert.Equal(t, true, empty)
|
assert.True(t, empty)
|
||||||
assert.Equal(t, Location{}, result)
|
assert.Equal(t, Location{}, result)
|
||||||
|
|
||||||
// strconv.ParseInt: parsing "測試": invalid syntax
|
// strconv.ParseInt: parsing "測試": invalid syntax
|
||||||
input = "測試 139.704051"
|
input = "測試 139.704051"
|
||||||
result, empty = convertLocation(input)
|
result, empty = convertLocation(input)
|
||||||
|
|
||||||
assert.Equal(t, true, empty)
|
assert.True(t, empty)
|
||||||
assert.Equal(t, Location{}, result)
|
assert.Equal(t, Location{}, result)
|
||||||
|
|
||||||
// strconv.ParseInt: parsing "測試": invalid syntax
|
// strconv.ParseInt: parsing "測試": invalid syntax
|
||||||
input = "35.661777 測試"
|
input = "35.661777 測試"
|
||||||
result, empty = convertLocation(input)
|
result, empty = convertLocation(input)
|
||||||
|
|
||||||
assert.Equal(t, true, empty)
|
assert.True(t, empty)
|
||||||
assert.Equal(t, Location{}, result)
|
assert.Equal(t, Location{}, result)
|
||||||
|
|
||||||
input = "35.661777 139.704051"
|
input = "35.661777 139.704051"
|
||||||
result, empty = convertLocation(input)
|
result, empty = convertLocation(input)
|
||||||
|
|
||||||
assert.Equal(t, false, empty)
|
assert.False(t, empty)
|
||||||
assert.Equal(t, Location{
|
assert.Equal(t, Location{
|
||||||
Latitude: float64(35.661777),
|
Latitude: float64(35.661777),
|
||||||
Longitude: float64(139.704051),
|
Longitude: float64(139.704051),
|
||||||
@@ -323,7 +353,7 @@ func TestConvertLocation(t *testing.T) {
|
|||||||
input = "35.661777 139.704051 title"
|
input = "35.661777 139.704051 title"
|
||||||
result, empty = convertLocation(input)
|
result, empty = convertLocation(input)
|
||||||
|
|
||||||
assert.Equal(t, false, empty)
|
assert.False(t, empty)
|
||||||
assert.Equal(t, Location{
|
assert.Equal(t, Location{
|
||||||
Title: "title",
|
Title: "title",
|
||||||
Address: "",
|
Address: "",
|
||||||
@@ -334,7 +364,7 @@ func TestConvertLocation(t *testing.T) {
|
|||||||
input = "35.661777 139.704051 title address"
|
input = "35.661777 139.704051 title address"
|
||||||
result, empty = convertLocation(input)
|
result, empty = convertLocation(input)
|
||||||
|
|
||||||
assert.Equal(t, false, empty)
|
assert.False(t, empty)
|
||||||
assert.Equal(t, Location{
|
assert.Equal(t, Location{
|
||||||
Title: "title",
|
Title: "title",
|
||||||
Address: "address",
|
Address: "address",
|
||||||
@@ -344,6 +374,7 @@ func TestConvertLocation(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestHTMLMessage(t *testing.T) {
|
func TestHTMLMessage(t *testing.T) {
|
||||||
|
skipIfNoTelegramSecrets(t)
|
||||||
plugin := Plugin{
|
plugin := Plugin{
|
||||||
Repo: Repo{
|
Repo: Repo{
|
||||||
Name: "go-hello",
|
Name: "go-hello",
|
||||||
@@ -374,13 +405,14 @@ Test HTML Format
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.Nil(t, plugin.Exec())
|
assert.NoError(t, plugin.Exec())
|
||||||
|
|
||||||
plugin.Config.MessageFile = "tests/message_html.txt"
|
plugin.Config.MessageFile = "tests/message_html.txt"
|
||||||
assert.Nil(t, plugin.Exec())
|
assert.NoError(t, plugin.Exec())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMessageFile(t *testing.T) {
|
func TestMessageFile(t *testing.T) {
|
||||||
|
skipIfNoTelegramSecrets(t)
|
||||||
plugin := Plugin{
|
plugin := Plugin{
|
||||||
Repo: Repo{
|
Repo: Repo{
|
||||||
Name: "go-hello",
|
Name: "go-hello",
|
||||||
@@ -408,10 +440,11 @@ func TestMessageFile(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
err := plugin.Exec()
|
err := plugin.Exec()
|
||||||
assert.Nil(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTemplateVars(t *testing.T) {
|
func TestTemplateVars(t *testing.T) {
|
||||||
|
skipIfNoTelegramSecrets(t)
|
||||||
plugin := Plugin{
|
plugin := Plugin{
|
||||||
Repo: Repo{
|
Repo: Repo{
|
||||||
Name: "go-hello",
|
Name: "go-hello",
|
||||||
@@ -441,10 +474,11 @@ func TestTemplateVars(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
err := plugin.Exec()
|
err := plugin.Exec()
|
||||||
assert.Nil(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTemplateVarsFile(t *testing.T) {
|
func TestTemplateVarsFile(t *testing.T) {
|
||||||
|
skipIfNoTelegramSecrets(t)
|
||||||
plugin := Plugin{
|
plugin := Plugin{
|
||||||
Repo: Repo{
|
Repo: Repo{
|
||||||
Name: "go-hello",
|
Name: "go-hello",
|
||||||
@@ -472,10 +506,11 @@ func TestTemplateVarsFile(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
err := plugin.Exec()
|
err := plugin.Exec()
|
||||||
assert.Nil(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestProxySendMessage(t *testing.T) {
|
func TestProxySendMessage(t *testing.T) {
|
||||||
|
skipIfNoTelegramSecrets(t)
|
||||||
plugin := Plugin{
|
plugin := Plugin{
|
||||||
Repo: Repo{
|
Repo: Repo{
|
||||||
Name: "go-hello",
|
Name: "go-hello",
|
||||||
@@ -505,7 +540,7 @@ func TestProxySendMessage(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
err := plugin.Exec()
|
err := plugin.Exec()
|
||||||
assert.Nil(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBuildTemplate(t *testing.T) {
|
func TestBuildTemplate(t *testing.T) {
|
||||||
@@ -533,5 +568,5 @@ Commit msg: {{uppercasefirst commit.message}}
|
|||||||
|
|
||||||
duration: {{duration build.started build.finished}}
|
duration: {{duration build.started build.finished}}
|
||||||
`, plugin)
|
`, plugin)
|
||||||
assert.Nil(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user