Version 1.0.0
Language EN

Creating a Plugin in Go

In this section we will walk through writing a Drone plugin in Go, from start to finish. The plugin will post a message to a Slack channel. This should give you some clear ideas what you can do with plugins, and will provide code snippets that may get you started in building your own.

Design the plugin

The first step is to design your plugin and define its input parameters. The Slack plugin will require the webhook url, channel and message text:

kind: pipeline
name: default

steps:
- name: webhook
  image: janecitizen/slack
  settings:
    webhook: https://hooks.slack.com/services/...
    channel: general
    text: hello

The input parameters are passed to the plugin as environment variables, prefixed with PLUGIN_. The input parameters from the above example are passed to the plugin as follows:

PLUGIN_CHANNEL=general
PLUGIN_WEBHOOK=https://hooks.slack.com/services/...
PLUGIN_TEXT=hello

Supported Input Types

Drone supports string, integer, float, boolean and array input types. Array values are passed to the plugin as a single comma-separated string.

Example array parameter:

kind: pipeline
name: default

steps:
- name: webhook
  image: janecitizen/slack
  settings:
    webhook: https://hooks.slack.com/services/...
    channel: [ general, ops ]
    text: hello

Example array parameter as an environment variable:

PLUGIN_CHANNEL=general,ops

Complex parameters should be stored as a file in your repository and loaded by the plugin at runtime. If you find yourself needing complex input parameters it could signal your plugin is overly complex, and should be simplified or split into multiple plugins or multiple steps.

Writing the Go Code

The next step is to create a Go program that posts a message to our Slack channel. This is an example program with the values hard-coded:

package main

import (
	"bytes"
	"encoding/json"
	"log"
	"net/http"
)

func main() {
	url := "https://hooks.slack.com/services/..."
	msg := struct {
		Channel string `json:"channel"`
		Text    string `json:"text"`
	}{
		Channel: "general",
		Text:    "hello",
	}

	raw, err := json.Marshal(msg)
	if err != nil {
		log.Fatalln(err)
	}

	resp, err = http.Post(hookURL, "application/json", bytes.NewReader(raw))
	if resp != nil {
		resp.Body.Close()
	}

	if err != nil {
		log.Fatalln(err)
	}
}

You should replace the hard-coded values with the input parameters defined in the previous section:

url := os.Getenv("PLUGIN_ENDPOINT")
msg := struct {
	Channel string `json:"channel"`
	Text    string `json:"text"`
}{
	Channel: os.Getenv("PLUGIN_CHANNEL"),
	Text:    os.Getenv("PLUGIN_TEXT_"),
}

Compiling the code

Compile your binary on the host machine for the target platform. Compiling on the host machine and adding the binary to the image is considered a best practice because it reduces the overall image size.

GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o slack

Please note, it is very important to compile using the correct target platform, otherwise your plugin will fail with a cryptic Go runtime error.

Building the plugin

Plugins are packaged and distributed as Docker images. Create a Dockerfile that adds your compiled binary to the image, and configures the image to run your binary as the main entrypoint.

FROM alpine
ADD slack /bin/
RUN apk -Uuv add ca-certificates
ENTRYPOINT /bin/slack

Build your plugin image:

docker build -t janecitizen/slack .

Testing the plugin

You should test your plugin locally to verify everything is working properly. You can test the plugin using docker run and pass configuration parameters as environment variables, for example:

docker run --rm \
  -e PLUGIN_CHANNEL=general \
  -e PLUGIN_WEBHOOK=https://hooks.slack.com/services/... \
  -e PLUGIN_TEXT="hello world" \
  janecitizen/slack

Testing Filesystem Access

Plugins have filesystem access to your pipeline workspace (the root directory of the cloned Git repository) which is set to the current working directory. You can test filesystem access by mounting your working directory:

docker run --rm \
  -e PLUGIN_CHANNEL=general \
  -e PLUGIN_WEBHOOK=https://hooks.slack.com/services/... \
  -e PLUGIN_TEXT="hello world" \
  -v $(pwd):/drone/src \
  -w /drone/src \
  janecitizen/slack

Publishing the Plugin

Plugins are published to a Docker registry and are downloaded by the Docker daemon at runtime. Once published your plugin can be shared with the broader Drone community.

Publish your plugin image:

docker push janecitizen/slack

On This Page:

Getting Help

Mailing List
Search for information in the mailing list archives, or post a question.
Chat Support
Real-time chat support from maintainers and community members.