Skip to main content
Version: Next

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:

SettingEnvironment value
some-bool: falsePLUGIN_SOME_BOOL="false"
some_String: helloPLUGIN_SOME_STRING="hello"
anInt: 3PLUGIN_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 name
  • icon: URL to your plugin's icon
  • description: A short description of what it's doing
  • author: Your name
  • tags: List of keywords (e.g. [git, clone] for the clone plugin)
  • containerImage: name of the container image
  • containerImageUrl: link to the container image
  • url: 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 and arm64.
  • 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).