Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: qwerty287 <qwerty287@posteo.de> Co-authored-by: qwerty287 <80460567+qwerty287@users.noreply.github.com>
4.6 KiB
Creating plugins
Creating a new plugin is simple: Build a Docker container which uses your plugin logic as the ENTRYPOINT.
Settings
To allow users to configure the behavior of your plugin, you should use settings:
.
These are passed to your plugin as uppercase env vars with a PLUGIN_
prefix.
Using a setting like url
results in an env var named PLUGIN_URL
.
Characters like -
are converted to an underscore (_
). some_String
gets PLUGIN_SOME_STRING
.
CamelCase is not respected, anInt
get PLUGIN_ANINT
.
Basic settings
Using any basic YAML type (scalar) will be converted into a string:
Setting | Environment value |
---|---|
some-bool: false |
PLUGIN_SOME_BOOL="false" |
some_String: hello |
PLUGIN_SOME_STRING="hello" |
anInt: 3 |
PLUGIN_ANINT="3" |
Complex settings
It's also possible to use complex settings like this:
steps:
- name: plugin
image: foo/plugin
settings:
complex:
abc: 2
list:
- 2
- 3
Values like this are converted to JSON and then passed to your plugin. In the example above, the environment variable PLUGIN_COMPLEX
would contain {"abc": "2", "list": [ "2", "3" ]}
.
Secrets
Secrets should be passed as settings too. Therefore, users should use from_secret
.
Plugin library
For Go, we provide a plugin library you can use to get easy access to internal env vars and your settings. See https://codeberg.org/woodpecker-plugins/go-plugin.
Metadata
In your documentation, you can use a Markdown header to define metadata for your plugin. This data is used by our plugin index.
Supported metadata:
name
: The plugin's full nameicon
: URL to your plugin's icondescription
: A short description of what it's doingauthor
: Your nametags
: List of keywords (e.g.[git, clone]
for the clone plugin)containerImage
: name of the container imagecontainerImageUrl
: link to the container imageurl
: homepage or repository of your plugin
If you want your plugin to be listed in the index, you should add as many fields as possible, but only name
is required.
Example plugin
This provides a brief tutorial for creating a Woodpecker webhook plugin, using simple shell scripting, to make HTTP requests during the build pipeline.
What end users will see
The below example demonstrates how we might configure a webhook plugin in the YAML file:
steps:
- name: webhook
image: foo/webhook
settings:
url: https://example.com
method: post
body: |
hello world
Write the logic
Create a simple shell script that invokes curl using the YAML configuration parameters, which are passed to the script as environment variables in uppercase and prefixed with PLUGIN_
.
#!/bin/sh
curl \
-X ${PLUGIN_METHOD} \
-d ${PLUGIN_BODY} \
${PLUGIN_URL}
Package it
Create a Dockerfile that adds your shell script to the image, and configures the image to execute your shell script as the main entrypoint.
# please pin the version, e.g. alpine:3.19
FROM alpine
ADD script.sh /bin/
RUN chmod +x /bin/script.sh
RUN apk -Uuv add curl ca-certificates
ENTRYPOINT /bin/script.sh
Build and publish your plugin to the Docker registry. Once published, your plugin can be shared with the broader Woodpecker community.
docker build -t foo/webhook .
docker push foo/webhook
Execute your plugin locally from the command line to verify it is working:
docker run --rm \
-e PLUGIN_METHOD=post \
-e PLUGIN_URL=https://example.com \
-e PLUGIN_BODY="hello world" \
foo/webhook
Best practices
- Build your plugin for different architectures to allow many users to use them.
At least, you should support
amd64
andarm64
. - Provide binaries for users using the
local
backend. These should also be built for different OS/architectures. - Use built-in env vars where possible.
- Do not use any configuration except settings (and internal env vars). This means: Don't require using
environment
and don't require specific secret names. - Add a
docs.md
file, listing all your settings and plugin metadata (example). - Add your plugin to the plugin index using your
docs.md
(the example above in the index).