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

Compare commits

...

65 Commits
v1.0.5 ... main

Author SHA1 Message Date
renovate[bot]
728bc0a268
chore(deps): update docker.io/library/alpine docker tag to v3.20 (#119)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-01 13:21:14 +02:00
renovate[bot]
4f9dee12c5 chore(deps): update dependency golangci/golangci-lint to v1.59.0 2024-05-27 03:37:17 +00:00
renovate[bot]
79f55e0b3e
fix(deps): update module github.com/rs/zerolog to v1.33.0 (#120)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-24 09:36:31 +02:00
renovate[bot]
7db4c14b96 chore(deps): update dependency golangci/golangci-lint to v1.58.2 2024-05-20 10:07:40 +00:00
renovate[bot]
b5980344c7 chore(docker): update docker.io/library/golang:1.22 docker digest to f43c6f0 2024-05-18 06:44:59 +00:00
76f5076b0a
chore: migrate to wp-plugin-go v3 (#116) 2024-05-17 21:50:20 +02:00
renovate[bot]
dc41f2d9ff
chore(docker): update docker.io/library/golang:1.22 docker digest to 91ad6f9 (#114)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-16 13:40:32 +02:00
renovate[bot]
9695526a8d chore(docker): update docker.io/library/golang:1.22 docker digest to ab48cd7 2024-05-15 20:52:20 +00:00
renovate[bot]
2f805d6fca chore(deps): update dependency golangci/golangci-lint to v1.58.1 2024-05-13 04:22:20 +00:00
a534efd107
ci: fix golangci-lint deprecations 2024-05-12 11:08:26 +02:00
3c3fb393b8
refactor: use dedicated matrix package (#111) 2024-05-11 10:25:15 +02:00
117f681b10
refactor: switch to plugin Cmd and add tests (#110) 2024-05-10 08:42:59 +02:00
renovate[bot]
4aa20c5f0e chore(docker): update docker.io/library/golang:1.22 docker digest to b1e05e2 2024-05-08 03:12:06 +00:00
renovate[bot]
1b9e7caee0 chore(deps): update dependency golangci/golangci-lint to v1.58.0 2024-05-06 04:14:06 +00:00
renovate[bot]
312b75d247
fix(deps): update module github.com/urfave/cli/v2 to v2.27.2 (#105)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-29 10:27:20 +02:00
renovate[bot]
350694d2e3 chore(docker): update docker.io/library/golang:1.22 docker digest to d5302d4 2024-04-25 03:01:24 +00:00
renovate[bot]
a7bb53a553
fix(deps): update module github.com/thegeeklab/wp-plugin-go to v1.7.1 (#103)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-22 12:38:46 +02:00
renovate[bot]
9fb64d43c3
fix(deps): update module maunium.net/go/mautrix to v0.18.1 (#102)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-17 08:45:27 +02:00
renovate[bot]
0ce44c0fc7 chore(docker): update docker.io/library/golang:1.22 docker digest to 450e382 2024-04-11 08:02:02 +00:00
renovate[bot]
7d9cd7b14c chore(docker): update docker.io/library/golang:1.22 docker digest to c4fb952 2024-04-04 05:02:33 +00:00
renovate[bot]
f92be16c5c chore(deps): update dependency golangci/golangci-lint to v1.57.2 2024-04-01 04:51:28 +00:00
renovate[bot]
a7f5a30e4a
chore(deps): update quay.io/thegeeklab/wp-docker-buildx docker tag to v4 (#98)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-27 08:55:46 +01:00
renovate[bot]
9f473db3f5
fix(deps): update module github.com/thegeeklab/wp-plugin-go to v1.7.0 (#94)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-26 21:33:55 +01:00
renovate[bot]
60095c2d59 chore(deps): update dependency golangci/golangci-lint to v1.57.1 2024-03-25 03:21:50 +00:00
renovate[bot]
ee37017679
fix(deps): update module maunium.net/go/mautrix to v0.18.0 (#96)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-17 12:04:35 +01:00
renovate[bot]
9be2f1fe39 chore(docker): update docker.io/library/golang:1.22 docker digest to 0b55ab8 2024-03-13 07:53:01 +00:00
4e6b959d04
cleanup docs and examples 2024-03-12 20:43:35 +01:00
renovate[bot]
3cfde357ae
fix(deps): update module github.com/thegeeklab/wp-plugin-go to v1.6.1 (#93)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-07 21:26:47 +01:00
renovate[bot]
4b7c33039e chore(docker): update docker.io/library/golang:1.22 docker digest to 34ce21a 2024-03-06 03:05:27 +00:00
renovate[bot]
96d388179b chore(deps): update dependency golangci/golangci-lint to v1.56.2 2024-02-19 03:35:22 +00:00
renovate[bot]
3066c3aa38 chore(docker): update docker.io/library/golang:1.22 docker digest to 7b297d9 2024-02-16 04:45:26 +00:00
6801e73ebe
[skip ci] revert renovate automerge config 2024-02-15 12:19:27 +01:00
renovate[bot]
b0214b66b4
chore(deps): update golang devdeps non-major (#88)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Robert Kaussow <mail@thegeeklab.de>
2024-02-09 22:39:01 +01:00
renovate[bot]
dfb94216e8
fix(deps): update module github.com/thegeeklab/wp-plugin-go to v1.6.0 (#89)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-09 21:56:30 +01:00
renovate[bot]
c8df7af45f
chore(deps): update docker.io/library/golang docker tag to v1.22 (#86)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Robert Kaussow <mail@thegeeklab.de>
2024-02-07 22:33:25 +01:00
b8d366468a
harmonize container image refs and use fqin 2024-02-07 09:40:38 +01:00
b548bc8ee0
run ci on renovate auto branches 2024-02-07 09:10:09 +01:00
28a50c9902
ci: enable ci run on renovate branches 2024-02-05 08:58:27 +01:00
renovate[bot]
c222609892
fix(deps): update module github.com/rs/zerolog to v1.32.0 (#85)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-05 08:45:31 +01:00
renovate[bot]
3056d8dabf chore(docker): update golang:1.21 docker digest to 7b575fe 2024-02-03 06:15:23 +00:00
renovate[bot]
4769b2942c chore(docker): update alpine:3.19 docker digest to c5b1261 2024-01-28 08:39:08 +00:00
renovate[bot]
7fccd218df chore(docker): update golang:1.21 docker digest to 76aadd9 2024-01-25 06:13:11 +00:00
renovate[bot]
480bf04f14
chore(deps): update quay.io/thegeeklab/wp-docker-buildx docker tag to v3 (#81)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-22 12:38:17 +01:00
renovate[bot]
78e837d537 chore(docker): update golang:1.21 docker digest to 5f5d61d 2024-01-17 10:17:16 +00:00
renovate[bot]
5561ac003c
fix(deps): update module maunium.net/go/mautrix to v0.17.0 (#79)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Robert Kaussow <mail@thegeeklab.de>
2024-01-16 20:05:45 +01:00
renovate[bot]
31cb34cbf4 chore(docker): update golang:1.21 docker digest to 6fbd2d3 2024-01-12 00:29:10 +00:00
renovate[bot]
ba5434d94d chore(docker): update golang:1.21 docker digest to 21260a4 2024-01-11 17:08:33 +00:00
renovate[bot]
36d591d1a1 chore(docker): update golang:1.21 docker digest to ffbb0b8 2024-01-11 05:02:56 +00:00
renovate[bot]
a65a585de4 chore(docker): update golang:1.21 docker digest to 7026fb7 2024-01-10 04:58:16 +00:00
e3d501acc8
docs: fix default value property in data file 2024-01-03 23:26:14 +01:00
2617de7d2b
chore: cleanup docs (#74) 2024-01-03 23:04:03 +01:00
renovate[bot]
c283b10071
fix(deps): update module github.com/thegeeklab/wp-plugin-go to v1.5.0 (#73)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-03 21:24:52 +01:00
renovate[bot]
611c52a270
fix(deps): update module github.com/urfave/cli/v2 to v2.27.1 (#72)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-01 16:21:26 +01:00
7288513035
use list style synatx and cleanup (#71) 2023-12-23 23:44:45 +01:00
renovate[bot]
6adc69670d
fix(deps): update module github.com/thegeeklab/wp-plugin-go to v1.3.0 (#70)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-21 13:41:47 +01:00
dependabot[bot]
8f017f08e3
chore(deps): bump golang.org/x/crypto from 0.16.0 to 0.17.0 (#69)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-21 11:55:27 +01:00
renovate[bot]
3684a58ee4 chore(docker): update golang:1.21 docker digest to 672a228 2023-12-21 06:17:00 +00:00
renovate[bot]
469203ab89 chore(docker): update golang:1.21 docker digest to fb02af5 2023-12-20 18:50:25 +00:00
renovate[bot]
1681bcc8c9 chore(docker): update golang:1.21 docker digest to 1a9d253 2023-12-20 07:33:56 +00:00
renovate[bot]
217fb8bc0b chore(docker): update golang:1.21 docker digest to b172263 2023-12-19 16:43:51 +00:00
021f400795
ci: add missing test group 2023-12-15 22:34:46 +01:00
renovate[bot]
e3c43040ac chore(docker): update golang:1.21 docker digest to 2ff79bc 2023-12-13 06:07:26 +00:00
renovate[bot]
be4746f288 chore(docker): update golang:1.21 docker digest to ae34fbf 2023-12-09 10:53:27 +00:00
renovate[bot]
79e4f73a74
chore(deps): update alpine docker tag to v3.19 (#62)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-08 08:37:40 +01:00
renovate[bot]
c460d0d759
chore(deps): update quay.io/thegeeklab/wp-docker-buildx docker tag to v2 (#61)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-07 08:39:44 +01:00
27 changed files with 753 additions and 340 deletions

1
.gitignore vendored
View File

@ -1,6 +1,7 @@
/dist
/release
/wp-matrix*
docs/data/data-raw.yaml
coverage.out
CHANGELOG.md

View File

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

6
.mockery.yaml Normal file
View File

@ -0,0 +1,6 @@
---
all: True
dir: "{{.PackageName}}/mocks"
outpkg: "mocks"
packages:
github.com/thegeeklab/wp-matrix/matrix:

View File

@ -6,8 +6,8 @@ when:
- ${CI_REPO_DEFAULT_BRANCH}
steps:
dryrun:
image: quay.io/thegeeklab/wp-docker-buildx:1
- name: dryrun
image: quay.io/thegeeklab/wp-docker-buildx:4
settings:
containerfile: Containerfile.multiarch
dry_run: true
@ -19,9 +19,9 @@ steps:
when:
- event: [pull_request]
publish-dockerhub:
- name: publish-dockerhub
image: quay.io/thegeeklab/wp-docker-buildx:4
group: container
image: quay.io/thegeeklab/wp-docker-buildx:1
settings:
auto_tag: true
containerfile: Containerfile.multiarch
@ -40,9 +40,9 @@ steps:
branch:
- ${CI_REPO_DEFAULT_BRANCH}
publish-quay:
- name: publish-quay
image: quay.io/thegeeklab/wp-docker-buildx:4
group: container
image: quay.io/thegeeklab/wp-docker-buildx:1
settings:
auto_tag: true
containerfile: Containerfile.multiarch

View File

@ -6,26 +6,25 @@ when:
- ${CI_REPO_DEFAULT_BRANCH}
steps:
build:
image: docker.io/techknowlogick/xgo:go-1.21.x
- name: build
image: docker.io/techknowlogick/xgo:go-1.22.x
commands:
- ln -s $(pwd) /source
- make release
executable:
- name: executable
image: quay.io/thegeeklab/alpine-tools
commands:
- $(find dist/ -executable -type f -iname ${CI_REPO_NAME}-linux-amd64) --help
changelog:
- name: changelog
image: quay.io/thegeeklab/git-sv
commands:
- git fetch --depth=2147483647
- git sv current-version
- git sv release-notes -t ${CI_COMMIT_TAG:-next} -o CHANGELOG.md
- cat CHANGELOG.md
publish-github:
- name: publish-github
image: docker.io/plugins/github-release
settings:
api_key:
@ -36,7 +35,7 @@ steps:
overwrite: true
title: ${CI_COMMIT_TAG}
when:
- event: [tag]
- event: [tag]
depends_on:
- test

View File

@ -6,26 +6,27 @@ when:
- ${CI_REPO_DEFAULT_BRANCH}
steps:
markdownlint:
- name: markdownlint
image: quay.io/thegeeklab/markdownlint-cli
group: test
commands:
- markdownlint 'README.md' 'CONTRIBUTING.md'
spellcheck:
- name: spellcheck
image: quay.io/thegeeklab/alpine-tools
group: test
commands:
- spellchecker --files '_docs/**/*.md' 'README.md' 'CONTRIBUTING.md' -d .dictionary -p spell indefinite-article syntax-urls
- spellchecker --files 'docs/**/*.md' 'README.md' 'CONTRIBUTING.md' -d .dictionary -p spell indefinite-article syntax-urls
environment:
FORCE_COLOR: "true"
NPM_CONFIG_LOGLEVEL: "error"
link-validation:
- name: link-validation
image: docker.io/lycheeverse/lychee
group: test
commands:
- lychee --no-progress --format detailed _docs/content README.md
- lychee --no-progress --format detailed docs/content README.md
publish:
- name: publish
image: quay.io/thegeeklab/wp-git-action
settings:
action:
@ -36,19 +37,20 @@ steps:
message: "[skip ci] auto-update documentation"
netrc_password:
from_secret: github_token
pages_directory: _docs/
pages_directory: docs/
when:
- event: [push, manual]
branch:
- ${CI_REPO_DEFAULT_BRANCH}
status: [success, failure]
pushrm-dockerhub:
- name: pushrm-dockerhub
image: docker.io/chko/docker-pushrm:1
secrets:
- source: docker_password
target: DOCKER_PASS
target: DOCKER_PASS
- source: docker_username
target: DOCKER_USER
target: DOCKER_USER
environment:
PUSHRM_FILE: README.md
PUSHRM_SHORT: Woodpecker CI plugin to send messages to Matrix
@ -59,7 +61,7 @@ steps:
- ${CI_REPO_DEFAULT_BRANCH}
status: [success]
pushrm-quay:
- name: pushrm-quay
image: docker.io/chko/docker-pushrm:1
secrets:
- source: quay_token

View File

@ -8,7 +8,7 @@ when:
runs_on: [success, failure]
steps:
matrix:
- name: matrix
image: quay.io/thegeeklab/wp-matrix
settings:
homeserver:

View File

@ -6,12 +6,12 @@ when:
- ${CI_REPO_DEFAULT_BRANCH}
steps:
lint:
image: docker.io/library/golang:1.21
- name: lint
image: docker.io/library/golang:1.22
commands:
- make lint
test:
image: docker.io/library/golang:1.21
- name: test
image: docker.io/library/golang:1.22
commands:
- make test

View File

@ -1,4 +1,4 @@
FROM --platform=$BUILDPLATFORM golang:1.21@sha256:58e14a93348a3515c2becc54ebd35302128225169d166b7c6802451ab336c907 as build
FROM --platform=$BUILDPLATFORM docker.io/library/golang:1.22@sha256:f43c6f049f04cbbaeb28f0aad3eea15274a7d0a7899a617d0037aec48d7ab010 as build
ARG TARGETOS
ARG TARGETARCH
@ -8,7 +8,7 @@ WORKDIR /src
RUN make build
FROM alpine:3.18@sha256:34871e7290500828b39e22294660bee86d966bc0017544e848dd9a255cdf59e0
FROM docker.io/library/alpine:3.20@sha256:77726ef6b57ddf65bb551896826ec38bc3e53f75cdde31354fbffb4f25238ebd
LABEL maintainer="Robert Kaussow <mail@thegeeklab.de>"
LABEL org.opencontainers.image.authors="Robert Kaussow <mail@thegeeklab.de>"

View File

@ -1,7 +1,7 @@
# renovate: datasource=github-releases depName=mvdan/gofumpt
GOFUMPT_PACKAGE_VERSION := v0.5.0
GOFUMPT_PACKAGE_VERSION := v0.6.0
# renovate: datasource=github-releases depName=golangci/golangci-lint
GOLANGCI_LINT_PACKAGE_VERSION := v1.55.2
GOLANGCI_LINT_PACKAGE_VERSION := v1.59.0
EXECUTABLE := wp-matrix
@ -18,9 +18,9 @@ GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@$(GOFUMPT_PACKAGE_VERSION)
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@$(GOLANGCI_LINT_PACKAGE_VERSION)
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
GOTESTSUM_PACKAGE ?= gotest.tools/gotestsum@latest
MOCKERY_PACKAGE ?= github.com/vektra/mockery/v2@latest
GENERATE ?=
XGO_VERSION := go-1.21.x
XGO_VERSION := go-1.22.x
XGO_TARGETS ?= linux/amd64,linux/arm-6,linux/arm-7,linux/arm64
TARGETOS ?= linux
@ -65,7 +65,8 @@ lint: golangci-lint
.PHONY: generate
generate:
$(GO) generate $(GENERATE)
$(GO) generate $(PACKAGES)
$(GO) run $(MOCKERY_PACKAGE)
.PHONY: test
test:

View File

@ -1,51 +0,0 @@
---
properties:
- name: username
description: Authentication username. If set, the `password` parameter is required as well.
type: string
required: false
- name: password
description: Authentication password.
type: string
required: false
- name: user_id
description: Aauthentication User ID. If set, the `access_token` parameter is required as well.
type: string
required: false
- name: access_token
description: Authentication access token.
type: string
required: false
- name: homeserver
description: The Matrix homeserver url to use.
defaultValue: https://matrix.org
type: string
required: false
- name: roomid
description: Room ID to send messages to.
type: string
required: false
- name: template
description: |
Golang template for the message. The [Metadata struct](https://pkg.go.dev/github.com/thegeeklab/wp-plugin-go/plugin#Metadata)
is exposed to the template and all fields can be referenced. To extend the functionality, [sprig functions](https://masterminds.github.io/sprig/) can also be used.
defaultValue: |
Status: **{{ .Pipeline.Status }}**
Build: [{{ .Repository.Slug }}]({{ .Pipeline.URL }}){{ if .Curr.Branch }} ({{ .Curr.Branch }}){{ end }} by {{ .Curr.Author.Name }}
Message: {{ .Curr.Message }}{{ if .Curr.URL }} ([source]({{ .Curr.URL }})){{ end }}
type: string
required: false
- name: template_unsafe
description: |
By default, raw HTML and potentially dangerous links in the template are not rendered. If you want to use inline HTML, you may need to turn this on.
In such cases, please ensure that the CI configuration files in the Git repository are protected against malicious changes.
defaultValue: false
type: bool
required: false

View File

@ -1,76 +0,0 @@
// Copyright (c) 2020, the Drone Plugins project authors.
// Copyright (c) 2021, Robert Kaussow <mail@thegeeklab.de>
// Use of this source code is governed by an Apache 2.0 license that can be
// found in the LICENSE file.
package main
import (
"github.com/thegeeklab/wp-matrix/plugin"
"github.com/urfave/cli/v2"
)
// settingsFlags has the cli.Flags for the plugin.Settings.
func settingsFlags(settings *plugin.Settings, category string) []cli.Flag {
return []cli.Flag{
&cli.StringFlag{
Name: "username",
EnvVars: []string{"PLUGIN_USERNAME", "MATRIX_USERNAME"},
Usage: "authentication username",
Destination: &settings.Username,
Category: category,
},
&cli.StringFlag{
Name: "password",
EnvVars: []string{"PLUGIN_PASSWORD", "MATRIX_PASSWORD"},
Usage: "authentication password",
Destination: &settings.Password,
Category: category,
},
&cli.StringFlag{
Name: "userid",
EnvVars: []string{"PLUGIN_USERID,PLUGIN_USER_ID", "MATRIX_USERID", "MATRIX_USER_ID"},
Usage: "authentication user id",
Destination: &settings.UserID,
Category: category,
},
&cli.StringFlag{
Name: "accesstoken",
EnvVars: []string{"PLUGIN_ACCESSTOKEN,PLUGIN_ACCESS_TOKEN", "MATRIX_ACCESSTOKEN", "MATRIX_ACCESS_TOKEN"},
Usage: "authentication access token",
Destination: &settings.AccessToken,
Category: category,
},
&cli.StringFlag{
Name: "homeserver",
EnvVars: []string{"PLUGIN_HOMESERVER", "MATRIX_HOMESERVER"},
Usage: "matrix home server url",
Value: "https://matrix.org",
Destination: &settings.Homeserver,
Category: category,
},
&cli.StringFlag{
Name: "roomid",
EnvVars: []string{"PLUGIN_ROOMID", "MATRIX_ROOMID"},
Usage: "roomid to send messages to",
Destination: &settings.RoomID,
Category: category,
},
&cli.StringFlag{
Name: "template",
EnvVars: []string{"PLUGIN_TEMPLATE", "MATRIX_TEMPLATE"},
Usage: "message template",
Value: plugin.DefaultMessageTemplate,
Destination: &settings.Template,
Category: category,
},
&cli.BoolFlag{
Name: "template-unsafe",
EnvVars: []string{"PLUGIN_TEMPLATE_UNSAFE", "MATRIX_TEMPLATE_UNSAFE"},
Usage: "render raw HTML and potentially dangerous links in template",
Destination: &settings.TemplateUnsafe,
Category: category,
},
}
}

View File

@ -7,11 +7,7 @@
package main
import (
"fmt"
"github.com/thegeeklab/wp-matrix/plugin"
wp "github.com/thegeeklab/wp-plugin-go/plugin"
)
//nolint:gochecknoglobals
@ -21,14 +17,5 @@ var (
)
func main() {
settings := &plugin.Settings{}
options := wp.Options{
Name: "wp-matrix",
Description: "Send messages to a Matrix room",
Version: BuildVersion,
VersionMetadata: fmt.Sprintf("date=%s", BuildDate),
Flags: settingsFlags(settings, wp.FlagsPluginCategory),
}
plugin.New(options, settings).Run()
plugin.New(nil, BuildVersion, BuildDate).Run()
}

View File

@ -21,17 +21,14 @@ Woodpecker CI plugin to send messages to a Matrix room.
## Usage
```YAML
kind: pipeline
name: default
steps:
- name: notify
image: thegeeklab/matrix
image: quay.io/thegeeklab/matrix
settings:
homeserver: https://matrix.org
roomid: abcdefghijklmnopqrstuvwxyz:matrix.org
roomid: randomstring:matrix.org
username: octocat
password: secret
password: random-secret
```
### Parameters
@ -60,9 +57,9 @@ docker build --file Containerfile.multiarch --tag thegeeklab/wp-matrix .
```Shell
docker run --rm \
-e PLUGIN_ROOMID=0123456789abcdef:matrix.org \
-e PLUGIN_USERNAME=yourbot \
-e PLUGIN_PASSWORD=p455w0rd \
-e PLUGIN_ROOMID=randomstring:matrix.org \
-e PLUGIN_USERNAME=octocat \
-e PLUGIN_PASSWORD=random-secret \
-v $(pwd):/build:z \
-w /build \
thegeeklab/wp-matrix

81
docs/data/data.yaml Normal file
View File

@ -0,0 +1,81 @@
---
properties:
- name: access_token
description: |
Authentication access token.
type: string
required: false
- name: homeserver
description: |
Matrix home server url.
type: string
defaultValue: "https://matrix.org"
required: false
- name: insecure_skip_verify
description: |
Skip SSL verification.
type: bool
defaultValue: false
required: false
- name: log_level
description: |
Plugin log level.
type: string
defaultValue: "info"
required: false
- name: password
description: |
Authentication password.
type: string
required: false
- name: roomid
description: |
Roomid to send messages to.
type: string
required: false
- name: template
description: |
Golang template for the message.
The [Metadata struct](https://pkg.go.dev/github.com/thegeeklab/wp-plugin-go/plugin#Metadata) is exposed
to the template and all fields can be referenced. To extend the functionality,
[sprig functions](https://masterminds.github.io/sprig/) can also be used.
type: string
defaultValue: |
Status: **{{ .Pipeline.Status }}**
Build: [{{ .Repository.Slug }}]({{ .Pipeline.URL }}){{ if .Curr.Branch }} ({{ .Curr.Branch }}){{ end }} by {{ .Curr.Author.Name }}
Message: {{ .Curr.Title }}{{ if .Curr.URL }} ([source]({{ .Curr.URL }})){{ end }}
required: false
- name: template_unsafe
description: |
Render raw HTML and potentially dangerous links in template.
By default, raw HTML and potentially dangerous links in the template are not rendered. If inline HTML is used,
it may be necessary to activate this option. In such cases, please ensure that the CI configuration files
in the git repository are protected against malicious changes.
type: bool
defaultValue: false
required: false
- name: user_id
description: |
Authentication user ID.
If set, the `access_token` parameter is required as well.
type: string
required: false
- name: username
description: |
Authentication username.
If set, the `password` parameter is required as well.
type: string
required: false

34
go.mod
View File

@ -1,13 +1,14 @@
module github.com/thegeeklab/wp-matrix
go 1.21
go 1.22
require (
github.com/microcosm-cc/bluemonday v1.0.26
github.com/rs/zerolog v1.31.0
github.com/thegeeklab/wp-plugin-go v1.2.0
github.com/urfave/cli/v2 v2.26.0
maunium.net/go/mautrix v0.16.2
github.com/rs/zerolog v1.33.0
github.com/stretchr/testify v1.9.0
github.com/thegeeklab/wp-plugin-go/v3 v3.0.2
github.com/urfave/cli/v2 v2.27.2
maunium.net/go/mautrix v0.18.1
)
require (
@ -15,7 +16,8 @@ require (
github.com/Masterminds/semver/v3 v3.2.1 // indirect
github.com/Masterminds/sprig/v3 v3.2.3 // indirect
github.com/aymerick/douceur v0.2.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gorilla/css v1.0.0 // indirect
github.com/huandu/xstrings v1.3.3 // indirect
@ -25,20 +27,22 @@ require (
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/shopspring/decimal v1.3.1 // indirect
github.com/spf13/cast v1.4.1 // indirect
github.com/tidwall/gjson v1.17.0 // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/tidwall/gjson v1.17.1 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
github.com/tidwall/sjson v1.2.5 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
github.com/yuin/goldmark v1.6.0 // indirect
go.mau.fi/util v0.2.1 // indirect
golang.org/x/crypto v0.16.0 // indirect
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect
golang.org/x/net v0.19.0 // indirect
golang.org/x/sys v0.15.0 // indirect
github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 // indirect
github.com/yuin/goldmark v1.7.1 // indirect
go.mau.fi/util v0.4.2 // indirect
golang.org/x/crypto v0.23.0 // indirect
golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8 // indirect
golang.org/x/net v0.25.0 // indirect
golang.org/x/sys v0.20.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
maunium.net/go/maulogger/v2 v2.4.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

61
go.sum
View File

@ -8,8 +8,8 @@ github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBa
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4=
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -43,8 +43,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.31.0 h1:FcTR3NnLWW+NnTwwhFWiJSZr4ECLpqCm6QsEnyvbV4A=
github.com/rs/zerolog v1.31.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8=
github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
@ -54,44 +54,46 @@ github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU
github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA=
github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/thegeeklab/wp-plugin-go v1.2.0 h1:ZvwfIIqT6UlclUhz3IYvHf+Jjam/orCaOgdTO+zbUiI=
github.com/thegeeklab/wp-plugin-go v1.2.0/go.mod h1:8DfPtNMelj6rJxBru3r8CAE4PMg6HsbxcRuE2Mu1tpw=
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/thegeeklab/wp-plugin-go/v3 v3.0.2 h1:Mv5i8S1WY+BUNjTjX6lOnB3p8S9mvM+XwfY4R98gx0g=
github.com/thegeeklab/wp-plugin-go/v3 v3.0.2/go.mod h1:ij1iJcAVgzerBTqXnmq0bu1VA+hhVVwzXKqiqfoGjjg=
github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/gjson v1.17.0 h1:/Jocvlh98kcTfpN2+JzGQWQcqrPQwDrVEMApx/M5ZwM=
github.com/tidwall/gjson v1.17.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/gjson v1.17.1 h1:wlYEnwqAHgzmhNUFfw7Xalt2JzQvsMx2Se4PcoFCT/U=
github.com/tidwall/gjson v1.17.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
github.com/urfave/cli/v2 v2.26.0 h1:3f3AMg3HpThFNT4I++TKOejZO8yU55t3JnnSr4S4QEI=
github.com/urfave/cli/v2 v2.26.0/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
github.com/urfave/cli/v2 v2.27.2 h1:6e0H+AkS+zDckwPCUrZkKX38mRaau4nL2uipkJpbkcI=
github.com/urfave/cli/v2 v2.27.2/go.mod h1:g0+79LmHHATl7DAcHO99smiR/T7uGLw84w8Y42x+4eM=
github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 h1:+qGGcbkzsfDQNPPe9UDgpxAWQrhbbBXOYJFQDq/dtJw=
github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913/go.mod h1:4aEEwZQutDLsQv2Deui4iYQ6DWTxR14g6m8Wv88+Xqk=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yuin/goldmark v1.6.0 h1:boZcn2GTjpsynOsC0iJHnBWa4Bi0qzfJjthwauItG68=
github.com/yuin/goldmark v1.6.0/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.mau.fi/util v0.2.1 h1:eazulhFE/UmjOFtPrGg6zkF5YfAyiDzQb8ihLMbsPWw=
go.mau.fi/util v0.2.1/go.mod h1:MjlzCQEMzJ+G8RsPawHzpLB8rwTo3aPIjG5FzBvQT/c=
github.com/yuin/goldmark v1.7.1 h1:3bajkSilaCbjdKVsKdZjZCLBNPL9pYzrCakKaf4U49U=
github.com/yuin/goldmark v1.7.1/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
go.mau.fi/util v0.4.2 h1:RR3TOcRHmCF9Bx/3YG4S65MYfa+nV6/rn8qBWW4Mi30=
go.mau.fi/util v0.4.2/go.mod h1:PlAVfUUcPyHPrwnvjkJM9UFcPE7qGPDJqk+Oufa1Gtw=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY=
golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ=
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE=
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8 h1:ESSUROHIBHg7USnszlcdmjBEwdMj9VUvU+OPk4yl2mc=
golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -103,8 +105,8 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
@ -116,6 +118,7 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
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.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
@ -123,7 +126,5 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
maunium.net/go/maulogger/v2 v2.4.1 h1:N7zSdd0mZkB2m2JtFUsiGTQQAdP0YeFWT7YMc80yAL8=
maunium.net/go/maulogger/v2 v2.4.1/go.mod h1:omPuYwYBILeVQobz8uO3XC8DIRuEb5rXYlQSuqrbCho=
maunium.net/go/mautrix v0.16.2 h1:a6GUJXNWsTEOO8VE4dROBfCIfPp50mqaqzv7KPzChvg=
maunium.net/go/mautrix v0.16.2/go.mod h1:YL4l4rZB46/vj/ifRMEjcibbvHjgxHftOF1SgmruLu4=
maunium.net/go/mautrix v0.18.1 h1:a6mUsJixegBNTXUoqC5RQ9gsumIPzKvCubKwF+zmCt4=
maunium.net/go/mautrix v0.18.1/go.mod h1:2oHaq792cSXFGvxLvYw3Gf1L4WVVP4KZcYys5HVk/h8=

42
internal/doc/main.go Normal file
View File

@ -0,0 +1,42 @@
//go:build generate
// +build generate
package main
import (
"context"
"flag"
"net/http"
"os"
"time"
"github.com/thegeeklab/wp-matrix/plugin"
plugin_docs "github.com/thegeeklab/wp-plugin-go/v3/docs"
plugin_template "github.com/thegeeklab/wp-plugin-go/v3/template"
)
func main() {
tmpl := "https://raw.githubusercontent.com/thegeeklab/woodpecker-plugins/main/templates/docs-data.yaml.tmpl"
client := http.Client{
Timeout: 30 * time.Second,
}
p := plugin.New(nil)
out, err := plugin_template.Render(context.Background(), client, tmpl, plugin_docs.GetTemplateData(p.App))
if err != nil {
panic(err)
}
outputFile := flag.String("output", "", "Output file path")
flag.Parse()
if *outputFile == "" {
panic("no output file specified")
}
err = os.WriteFile(*outputFile, []byte(out), 0o644)
if err != nil {
panic(err)
}
}

14
matrix/api.go Normal file
View File

@ -0,0 +1,14 @@
package matrix
import (
"context"
"maunium.net/go/mautrix"
"maunium.net/go/mautrix/event"
"maunium.net/go/mautrix/id"
)
//nolint:lll
type APIClient interface {
SendMessageEvent(ctx context.Context, roomID id.RoomID, eventType event.Type, contentJSON interface{}, extra ...mautrix.ReqSendEvent) (resp *mautrix.RespSendEvent, err error)
}

89
matrix/matrix.go Normal file
View File

@ -0,0 +1,89 @@
package matrix
import (
"context"
"fmt"
"github.com/microcosm-cc/bluemonday"
"maunium.net/go/mautrix"
"maunium.net/go/mautrix/event"
"maunium.net/go/mautrix/format"
"maunium.net/go/mautrix/id"
)
type Client struct {
client APIClient
Message *Message
}
type Message struct {
client APIClient
Opt MessageOptions
}
type MessageOptions struct {
RoomID id.RoomID
Message string
TemplateUnsafe bool
}
// NewClient creates a new Matrix client with the given parameters and joins the specified room.
// It authenticates the user if the userID and token are not provided, and returns a Client struct
// that can be used to send messages to the room.
func NewClient(ctx context.Context, url, roomID, userID, token, username, password string) (*Client, error) {
muid := id.NewUserID(EnsurePrefix("@", userID), url)
c, err := mautrix.NewClient(url, muid, token)
if err != nil {
return nil, err
}
if userID == "" || token == "" {
_, err := c.Login(
ctx,
&mautrix.ReqLogin{
Type: "m.login.password",
Identifier: mautrix.UserIdentifier{Type: mautrix.IdentifierTypeUser, User: username},
Password: password,
InitialDeviceDisplayName: "Woodpecker CI",
StoreCredentials: true,
},
)
if err != nil {
return nil, fmt.Errorf("failed to authenticate user: %w", err)
}
}
joinResp, err := c.JoinRoom(ctx, EnsurePrefix("!", roomID), "", nil)
if err != nil {
return nil, fmt.Errorf("failed to join room: %w", err)
}
return &Client{
client: c,
Message: &Message{
client: c,
Opt: MessageOptions{
RoomID: joinResp.RoomID,
},
},
}, nil
}
// Send sends a message to the specified room. It sanitizes the message content
// to remove potentially unsafe HTML.
func (m *Message) Send(ctx context.Context) error {
content := format.RenderMarkdown(m.Opt.Message, true, m.Opt.TemplateUnsafe)
if content.FormattedBody != "" {
content.Body = format.HTMLToMarkdown(bluemonday.UGCPolicy().Sanitize(content.FormattedBody))
content.FormattedBody = bluemonday.UGCPolicy().Sanitize(content.FormattedBody)
}
_, err := m.client.SendMessageEvent(ctx, m.Opt.RoomID, event.EventMessage, content)
if err != nil {
return err
}
return nil
}

106
matrix/matrix_test.go Normal file
View File

@ -0,0 +1,106 @@
package matrix
import (
"context"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/thegeeklab/wp-matrix/matrix/mocks"
"maunium.net/go/mautrix"
"maunium.net/go/mautrix/event"
)
func TestMessageSend(t *testing.T) {
tests := []struct {
name string
messageOpt MessageOptions
want event.MessageEventContent
wantErr bool
}{
{
name: "plain text message",
messageOpt: MessageOptions{
RoomID: "test-room",
Message: "hello world",
},
want: event.MessageEventContent{
MsgType: "m.text",
Body: "hello world",
},
},
{
name: "markdown message",
messageOpt: MessageOptions{
RoomID: "test-room",
Message: "**hello world**",
},
want: event.MessageEventContent{
MsgType: "m.text",
Body: "**hello world**",
Format: "org.matrix.custom.html",
FormattedBody: "<strong>hello world</strong>",
},
},
{
name: "html message",
messageOpt: MessageOptions{
RoomID: "test-room",
Message: "hello<br>world",
TemplateUnsafe: true,
},
want: event.MessageEventContent{
MsgType: "m.text",
Body: "hello\nworld",
Format: "org.matrix.custom.html",
FormattedBody: "hello<br>world",
},
},
{
name: "safe html message",
messageOpt: MessageOptions{
RoomID: "test-room",
Message: "hello world<script>alert('XSS')</script>",
TemplateUnsafe: false,
},
want: event.MessageEventContent{
MsgType: "m.text",
Body: "hello world<script>alert('XSS')</script>",
Format: "org.matrix.custom.html",
FormattedBody: "hello world&lt;script&gt;alert(&#39;XSS&#39;)&lt;/script&gt;",
},
},
{
name: "unsafe html message",
messageOpt: MessageOptions{
RoomID: "test-room",
Message: "hello world<script>alert('XSS')</script>",
TemplateUnsafe: true,
},
want: event.MessageEventContent{
MsgType: "m.text",
Body: "hello world",
Format: "org.matrix.custom.html",
FormattedBody: "hello world",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := context.Background()
mockClient := mocks.NewMockAPIClient(t)
m := &Message{
Opt: tt.messageOpt,
client: mockClient,
}
mockClient.
On("SendMessageEvent", mock.Anything, tt.messageOpt.RoomID, event.EventMessage, tt.want).
Return(&mautrix.RespSendEvent{}, nil)
err := m.Send(ctx)
assert.Equal(t, tt.wantErr, err != nil)
})
}
}

View File

@ -0,0 +1,117 @@
// Code generated by mockery v2.43.0. DO NOT EDIT.
package mocks
import (
context "context"
event "maunium.net/go/mautrix/event"
id "maunium.net/go/mautrix/id"
mautrix "maunium.net/go/mautrix"
mock "github.com/stretchr/testify/mock"
)
// MockAPIClient is an autogenerated mock type for the APIClient type
type MockAPIClient struct {
mock.Mock
}
type MockAPIClient_Expecter struct {
mock *mock.Mock
}
func (_m *MockAPIClient) EXPECT() *MockAPIClient_Expecter {
return &MockAPIClient_Expecter{mock: &_m.Mock}
}
// SendMessageEvent provides a mock function with given fields: ctx, roomID, eventType, contentJSON, extra
func (_m *MockAPIClient) SendMessageEvent(ctx context.Context, roomID id.RoomID, eventType event.Type, contentJSON interface{}, extra ...mautrix.ReqSendEvent) (*mautrix.RespSendEvent, error) {
_va := make([]interface{}, len(extra))
for _i := range extra {
_va[_i] = extra[_i]
}
var _ca []interface{}
_ca = append(_ca, ctx, roomID, eventType, contentJSON)
_ca = append(_ca, _va...)
ret := _m.Called(_ca...)
if len(ret) == 0 {
panic("no return value specified for SendMessageEvent")
}
var r0 *mautrix.RespSendEvent
var r1 error
if rf, ok := ret.Get(0).(func(context.Context, id.RoomID, event.Type, interface{}, ...mautrix.ReqSendEvent) (*mautrix.RespSendEvent, error)); ok {
return rf(ctx, roomID, eventType, contentJSON, extra...)
}
if rf, ok := ret.Get(0).(func(context.Context, id.RoomID, event.Type, interface{}, ...mautrix.ReqSendEvent) *mautrix.RespSendEvent); ok {
r0 = rf(ctx, roomID, eventType, contentJSON, extra...)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*mautrix.RespSendEvent)
}
}
if rf, ok := ret.Get(1).(func(context.Context, id.RoomID, event.Type, interface{}, ...mautrix.ReqSendEvent) error); ok {
r1 = rf(ctx, roomID, eventType, contentJSON, extra...)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// MockAPIClient_SendMessageEvent_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendMessageEvent'
type MockAPIClient_SendMessageEvent_Call struct {
*mock.Call
}
// SendMessageEvent is a helper method to define mock.On call
// - ctx context.Context
// - roomID id.RoomID
// - eventType event.Type
// - contentJSON interface{}
// - extra ...mautrix.ReqSendEvent
func (_e *MockAPIClient_Expecter) SendMessageEvent(ctx interface{}, roomID interface{}, eventType interface{}, contentJSON interface{}, extra ...interface{}) *MockAPIClient_SendMessageEvent_Call {
return &MockAPIClient_SendMessageEvent_Call{Call: _e.mock.On("SendMessageEvent",
append([]interface{}{ctx, roomID, eventType, contentJSON}, extra...)...)}
}
func (_c *MockAPIClient_SendMessageEvent_Call) Run(run func(ctx context.Context, roomID id.RoomID, eventType event.Type, contentJSON interface{}, extra ...mautrix.ReqSendEvent)) *MockAPIClient_SendMessageEvent_Call {
_c.Call.Run(func(args mock.Arguments) {
variadicArgs := make([]mautrix.ReqSendEvent, len(args)-4)
for i, a := range args[4:] {
if a != nil {
variadicArgs[i] = a.(mautrix.ReqSendEvent)
}
}
run(args[0].(context.Context), args[1].(id.RoomID), args[2].(event.Type), args[3].(interface{}), variadicArgs...)
})
return _c
}
func (_c *MockAPIClient_SendMessageEvent_Call) Return(resp *mautrix.RespSendEvent, err error) *MockAPIClient_SendMessageEvent_Call {
_c.Call.Return(resp, err)
return _c
}
func (_c *MockAPIClient_SendMessageEvent_Call) RunAndReturn(run func(context.Context, id.RoomID, event.Type, interface{}, ...mautrix.ReqSendEvent) (*mautrix.RespSendEvent, error)) *MockAPIClient_SendMessageEvent_Call {
_c.Call.Return(run)
return _c
}
// NewMockAPIClient creates a new instance of MockAPIClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewMockAPIClient(t interface {
mock.TestingT
Cleanup(func())
}) *MockAPIClient {
mock := &MockAPIClient{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}

16
matrix/util.go Normal file
View File

@ -0,0 +1,16 @@
package matrix
import "strings"
// EnsurePrefix ensures that the given input string starts with the provided prefix.
func EnsurePrefix(prefix, input string) string {
if strings.TrimSpace(input) == "" {
return input
}
if strings.HasPrefix(input, prefix) {
return input
}
return prefix + input
}

46
matrix/util_test.go Normal file
View File

@ -0,0 +1,46 @@
package matrix
import "testing"
func TestEnsurePrefix(t *testing.T) {
tests := []struct {
name string
prefix string
input string
want string
}{
{
name: "empty input",
prefix: "pre_",
input: "",
want: "",
},
{
name: "input already has prefix",
prefix: "pre_",
input: "pre_value",
want: "pre_value",
},
{
name: "input needs prefix",
prefix: "pre_",
input: "value",
want: "pre_value",
},
{
name: "input with leading/trailing spaces",
prefix: "pre_",
input: " value ",
want: "pre_ value ",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := EnsurePrefix(tt.prefix, tt.input)
if got != tt.want {
t.Errorf("EnsurePrefix(%q, %q) = %q, want %q", tt.prefix, tt.input, got, tt.want)
}
})
}
}

View File

@ -10,16 +10,10 @@ import (
"context"
"errors"
"fmt"
"net/http"
"strings"
"github.com/microcosm-cc/bluemonday"
"github.com/rs/zerolog/log"
"github.com/thegeeklab/wp-plugin-go/template"
"maunium.net/go/mautrix"
"maunium.net/go/mautrix/event"
"maunium.net/go/mautrix/format"
"maunium.net/go/mautrix/id"
"github.com/thegeeklab/wp-matrix/matrix"
plugin_template "github.com/thegeeklab/wp-plugin-go/v3/template"
)
var ErrAuthSourceNotSet = errors.New("either username and password or userid and accesstoken are required")
@ -49,40 +43,32 @@ func (p *Plugin) Validate() error {
// Execute provides the implementation of the plugin.
func (p *Plugin) Execute() error {
muid := id.NewUserID(prepend("@", p.Settings.UserID), p.Settings.Homeserver)
msg, err := p.CreateMessage()
if err != nil {
return fmt.Errorf("failed to create message: %w", err)
}
client, err := mautrix.NewClient(p.Settings.Homeserver, muid, p.Settings.AccessToken)
client, err := matrix.NewClient(
p.Network.Context,
p.Settings.Homeserver,
p.Settings.RoomID,
p.Settings.UserID,
p.Settings.AccessToken,
p.Settings.Username,
p.Settings.Password,
)
if err != nil {
return fmt.Errorf("failed to initialize client: %w", err)
}
if p.Settings.UserID == "" || p.Settings.AccessToken == "" {
_, err := client.Login(&mautrix.ReqLogin{
Type: "m.login.password",
Identifier: mautrix.UserIdentifier{Type: mautrix.IdentifierTypeUser, User: p.Settings.Username},
Password: p.Settings.Password,
InitialDeviceDisplayName: "Woodpecker CI",
StoreCredentials: true,
})
if err != nil {
return fmt.Errorf("failed to authenticate user: %w", err)
}
client.Message.Opt = matrix.MessageOptions{
RoomID: client.Message.Opt.RoomID,
Message: msg,
TemplateUnsafe: p.Settings.TemplateUnsafe,
}
log.Info().Msg("logged in successfully")
joined, err := client.JoinRoom(prepend("!", p.Settings.RoomID), "", nil)
if err != nil {
return fmt.Errorf("failed to join room: %w", err)
}
content, err := p.messageContent(p.Network.Context, *p.Network.Client)
if err != nil {
return fmt.Errorf("failed to render template: %w", err)
}
if _, err := client.SendMessageEvent(joined.RoomID, event.EventMessage, content); err != nil {
return fmt.Errorf("failed to submit message: %w", err)
if err := client.Message.Send(p.Network.Context); err != nil {
return fmt.Errorf("failed to send message: %w", err)
}
log.Info().Msg("message sent successfully")
@ -90,34 +76,7 @@ func (p *Plugin) Execute() error {
return nil
}
func (p *Plugin) messageContent(ctx context.Context, client http.Client) (event.MessageEventContent, error) {
message, err := template.RenderTrim(ctx, client, p.Settings.Template, p.Metadata)
if err != nil {
return event.MessageEventContent{}, err
}
content := format.RenderMarkdown(message, true, p.Settings.TemplateUnsafe)
safeBody := format.HTMLToMarkdown(bluemonday.UGCPolicy().Sanitize(content.FormattedBody))
if content.Body != safeBody {
content.Body = safeBody
}
if content.FormattedBody != "" {
content.FormattedBody = bluemonday.UGCPolicy().Sanitize(content.FormattedBody)
}
return content, nil
}
func prepend(prefix, input string) string {
if strings.TrimSpace(input) == "" {
return input
}
if strings.HasPrefix(input, prefix) {
return input
}
return prefix + input
// CreateMessage generates a message string based on the plugin's template and metadata.
func (p *Plugin) CreateMessage() (string, error) {
return plugin_template.RenderTrim(p.Network.Context, *p.Network.Client, p.Settings.Template, p.Metadata)
}

View File

@ -5,7 +5,8 @@ import (
"net/http"
"testing"
wp "github.com/thegeeklab/wp-plugin-go/plugin"
"github.com/stretchr/testify/assert"
plugin_base "github.com/thegeeklab/wp-plugin-go/v3/plugin"
)
func Test_messageContent(t *testing.T) {
@ -13,9 +14,7 @@ func Test_messageContent(t *testing.T) {
tests := []struct {
name string
want string
unsafe bool
template string
meta wp.Metadata
}{
{
name: "render default template",
@ -25,54 +24,40 @@ func Test_messageContent(t *testing.T) {
{
name: "render unsafe html template",
want: "Status: **success**\nBuild: octocat/demo",
unsafe: true,
template: "Status: **{{ .Pipeline.Status }}**<br>Build: {{ .Repository.Slug }}",
},
{
name: "render html xss template",
want: "Status: **success**\nBuild: octocat/demo",
unsafe: true,
template: "Status: **{{ .Pipeline.Status }}**<br>Build: <a href=\"javascript:alert('XSS1')\" onmouseover=\"alert('XSS2')\">{{ .Repository.Slug }}<a>",
},
{
name: "render markdown xss template",
want: "Status: **success**\nBuild: octocat/demo",
unsafe: true,
template: "Status: **{{ .Pipeline.Status }}**<br>Build: [{{ .Repository.Slug }}](javascript:alert(XSS1'))",
template: "Status: **{{ .Pipeline.Status }}**\nBuild: {{ .Repository.Slug }}",
},
}
options := wp.Options{
Name: "wp-matrix",
Execute: func(ctx context.Context) error { return nil },
p := New(func(_ context.Context) error { return nil })
p.Network = plugin_base.Network{
Context: context.Background(),
Client: &http.Client{},
}
p := New(options, &Settings{})
p.Metadata = wp.Metadata{
Curr: wp.Commit{
p.Metadata = plugin_base.Metadata{
Curr: plugin_base.Commit{
Branch: "main",
Title: "feat: demo commit title",
URL: "https://git.example.com",
Author: wp.Author{
Author: plugin_base.Author{
Name: "octobot",
},
},
Pipeline: wp.Pipeline{
Pipeline: plugin_base.Pipeline{
Status: "success",
URL: "https://ci.example.com",
},
Repository: wp.Repository{
Repository: plugin_base.Repository{
Slug: "octocat/demo",
},
}
for _, tt := range tests {
p.Settings.Template = tt.template
p.Settings.TemplateUnsafe = tt.unsafe
content, _ := p.messageContent(context.Background(), http.Client{})
t.Run(tt.name, func(t *testing.T) {
p.Settings.Template = tt.template
if content.Body != tt.want {
t.Errorf("messageContent: %q got: %q, want: %q", tt.name, content.Body, tt.want)
}
content, err := p.CreateMessage()
assert.NoError(t, err)
assert.Equal(t, tt.want, content)
})
}
}

View File

@ -7,9 +7,14 @@
package plugin
import (
wp "github.com/thegeeklab/wp-plugin-go/plugin"
"fmt"
plugin_base "github.com/thegeeklab/wp-plugin-go/v3/plugin"
"github.com/urfave/cli/v2"
)
//go:generate go run ../internal/doc/main.go -output=../docs/data/data-raw.yaml
//nolint:lll
const DefaultMessageTemplate = `
Status: **{{ .Pipeline.Status }}**
@ -19,7 +24,7 @@ Message: {{ .Curr.Title }}{{ if .Curr.URL }} ([source]({{ .Curr.URL }})){{ end }
// Plugin implements provide the plugin.
type Plugin struct {
*wp.Plugin
*plugin_base.Plugin
Settings *Settings
}
@ -35,13 +40,96 @@ type Settings struct {
TemplateUnsafe bool
}
func New(options wp.Options, settings *Settings) *Plugin {
p := &Plugin{}
func New(e plugin_base.ExecuteFunc, build ...string) *Plugin {
p := &Plugin{
Settings: &Settings{},
}
options.Execute = p.run
options := plugin_base.Options{
Name: "wp-matrix",
Description: "Send messages to a Matrix room",
Flags: Flags(p.Settings, plugin_base.FlagsPluginCategory),
Execute: p.run,
HideWoodpeckerFlags: true,
}
p.Plugin = wp.New(options)
p.Settings = settings
if len(build) > 0 {
options.Version = build[0]
}
if len(build) > 1 {
options.VersionMetadata = fmt.Sprintf("date=%s", build[1])
}
if e != nil {
options.Execute = e
}
p.Plugin = plugin_base.New(options)
return p
}
// Flags returns a slice of CLI flags for the plugin.
func Flags(settings *Settings, category string) []cli.Flag {
return []cli.Flag{
&cli.StringFlag{
Name: "username",
EnvVars: []string{"PLUGIN_USERNAME", "MATRIX_USERNAME"},
Usage: "authentication username",
Destination: &settings.Username,
Category: category,
},
&cli.StringFlag{
Name: "password",
EnvVars: []string{"PLUGIN_PASSWORD", "MATRIX_PASSWORD"},
Usage: "authentication password",
Destination: &settings.Password,
Category: category,
},
&cli.StringFlag{
Name: "userid",
EnvVars: []string{"PLUGIN_USER_ID", "PLUGIN_USERID", "MATRIX_USER_ID", "MATRIX_USERID"},
Usage: "authentication user ID",
Destination: &settings.UserID,
Category: category,
},
&cli.StringFlag{
Name: "accesstoken",
EnvVars: []string{"PLUGIN_ACCESS_TOKEN", "PLUGIN_ACCESSTOKEN", "MATRIX_ACCESS_TOKEN", "MATRIX_ACCESSTOKEN"},
Usage: "authentication access token",
Destination: &settings.AccessToken,
Category: category,
},
&cli.StringFlag{
Name: "homeserver",
EnvVars: []string{"PLUGIN_HOMESERVER", "MATRIX_HOMESERVER"},
Usage: "matrix home server url",
Value: "https://matrix.org",
Destination: &settings.Homeserver,
Category: category,
},
&cli.StringFlag{
Name: "roomid",
EnvVars: []string{"PLUGIN_ROOMID", "MATRIX_ROOMID"},
Usage: "roomid to send messages to",
Destination: &settings.RoomID,
Category: category,
},
&cli.StringFlag{
Name: "template",
EnvVars: []string{"PLUGIN_TEMPLATE", "MATRIX_TEMPLATE"},
Usage: "golang template for the message",
Value: DefaultMessageTemplate,
Destination: &settings.Template,
Category: category,
},
&cli.BoolFlag{
Name: "template-unsafe",
EnvVars: []string{"PLUGIN_TEMPLATE_UNSAFE", "MATRIX_TEMPLATE_UNSAFE"},
Usage: "render raw HTML and potentially dangerous links in template",
Destination: &settings.TemplateUnsafe,
Category: category,
},
}
}