mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2024-11-26 03:41:01 +00:00
added documentation for plugin development
This commit is contained in:
parent
9fc02e360a
commit
ccfd75196b
7 changed files with 282 additions and 10 deletions
|
@ -1,3 +1,5 @@
|
|||
> **WARNING** the 0.4 branch is very unstable. We only recommend running this branch if you plan to dig into the codebase, troubleshoot issues and contribute (please do!). We will notify the broader community once this branch is more stable.
|
||||
|
||||
Drone is a Continuous Integration platform built on container technology. Every build is executed inside an ephemeral Docker container, giving developers complete control over their build environment with guaranteed isolation.
|
||||
|
||||
### Goals
|
||||
|
@ -10,6 +12,7 @@ Drone documentation is organized into several categories:
|
|||
|
||||
* [Setup Guide](http://readme.drone.io/docs/setup/)
|
||||
* [Build Guide](http://readme.drone.io/docs/build/)
|
||||
* [Plugin Guide](http://readme.drone.io/docs/plugin/)
|
||||
* [API Reference](http://readme.drone.io/docs/api/)
|
||||
|
||||
### Community
|
||||
|
|
3
doc/plugin/README.md
Normal file
3
doc/plugin/README.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
* [Overview](overview.md)
|
||||
* [Example](example.md)
|
||||
* [Publish](publish.md)
|
156
doc/plugin/example.md
Normal file
156
doc/plugin/example.md
Normal file
|
@ -0,0 +1,156 @@
|
|||
# Plugin Tutorial
|
||||
|
||||
We're going to create a plugin that allows Drone to send a webhook when a build completes. The webhook will send an http POST request to one or more URLs with the build details, encoded in JSON format.
|
||||
|
||||
## Plugin Yaml
|
||||
|
||||
Many plugins call for some options the user can set, which can be specified in the `.drone.yml` file. This is an example configuration for our `webhook` plugin:
|
||||
|
||||
```yaml
|
||||
---
|
||||
notify:
|
||||
webhook:
|
||||
image: bradrydzewski/webhook
|
||||
urls:
|
||||
- http://foo.com/post/to/this/url
|
||||
```
|
||||
|
||||
The `image` attribute refers to the name of our plugin's Docker image. The `urls` attribute is a custom option allowing the user to define the list of webhook urls.
|
||||
|
||||
## Plugin executable
|
||||
|
||||
The next step is to write the code for our plugin. Our plugin will need access to information about the running build, and it will need its configuration options. Luckily, the build and repository details are passed to the program as a JSON encoded string over `arg[1]`.
|
||||
|
||||
The Drone team created the `drone-plugin-go` library to simplify plugin development, and we'll use this library to create our webhook plugin. First, we'll need to download the library using `go get` and import into our `main.go` file:
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/drone/drone-plugin-go"
|
||||
)
|
||||
```
|
||||
|
||||
Next we'll need to read and unmarshal the repository and build detail from `arg[1]`. Our plugin package provides simple helper functions, modeled after the `flag` package, to fetch this data. We'll also need to read and unmarshal our plugin options. Plugin options are passed as the `vargs` paramter.
|
||||
|
||||
```go
|
||||
func main() {
|
||||
var repo = plugin.Repo{}
|
||||
var build = plugin.Build{}
|
||||
var vargs = struct {
|
||||
Urls []string `json:"urls"`
|
||||
}{}
|
||||
|
||||
plugin.Param("repo", &repo)
|
||||
plugin.Param("build", &build)
|
||||
plugin.Param("vargs", &vargs)
|
||||
plugin.Parse()
|
||||
|
||||
// post build and repo data to webhook urls
|
||||
}
|
||||
```
|
||||
|
||||
Once we've parsed the build and repository details, and the webhook urls, we are ready to make the http requests. First, we'll need to construct our payload and marshal to JSON:
|
||||
|
||||
```go
|
||||
data := struct{
|
||||
Repo plugin.Repo `json:"repo"`
|
||||
Build plugin.Build `json:"build"`
|
||||
}{repo, build}
|
||||
|
||||
payload, _ := json.Marshal(&data)
|
||||
```
|
||||
|
||||
And finally, for each URL in the list, we post the JSON payload:
|
||||
|
||||
```go
|
||||
for _, url := range vargs.Urls {
|
||||
resp, _ := http.Post(url, "application/json", bytes.NewBuffer(payload))
|
||||
resp.Body.Close()
|
||||
}
|
||||
```
|
||||
|
||||
## Plugin image
|
||||
|
||||
Since plugins are distributed as Docker images, we'll need to create a `Dockerfile` for our plugin:
|
||||
|
||||
```dockerfile
|
||||
FROM gliderlabs/alpine:3.1
|
||||
RUN apk-install ca-certificates
|
||||
ADD drone-webhook /bin/
|
||||
ENTRYPOINT ["/bin/drone-webhook"]
|
||||
```
|
||||
|
||||
We recommend using the `gliderlabs/alpine` base image due to its compact size. Plugins are downloaded automatically during build execution, therefore, smaller images and faster download times provide a better overall user experience.
|
||||
|
||||
## Plugin testing
|
||||
|
||||
We can quickly test our plugin from the command line, with dummy data, to make sure everything works. Note that you can send the JSON string over `stdin` instead of `arg[1]` only when testing:
|
||||
|
||||
```bash
|
||||
go run main.go <<EOF
|
||||
{
|
||||
"repo": {
|
||||
"owner": "octocat",
|
||||
"name": "hello-world",
|
||||
"full_name": "octocat/hello-world"
|
||||
},
|
||||
"build": {
|
||||
"number": 1,
|
||||
"status": "success"
|
||||
},
|
||||
"vargs": {
|
||||
"urls": [ "http://foo.com/post/to/this/url" ]
|
||||
}
|
||||
}
|
||||
EOF
|
||||
```
|
||||
|
||||
## Complete example
|
||||
|
||||
Here is the complete Go program:
|
||||
|
||||
```go
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/drone/drone-plugin-go"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var repo = plugin.Repo{}
|
||||
var build = plugin.Build{}
|
||||
var vargs = struct {
|
||||
Urls []string `json:"urls"`
|
||||
}{}
|
||||
|
||||
plugin.Param("repo", &repo)
|
||||
plugin.Param("build", &build)
|
||||
plugin.Param("vargs", &vargs)
|
||||
plugin.Parse()
|
||||
|
||||
// data structure
|
||||
data := struct{
|
||||
Repo plugin.Repo `json:"repo"`
|
||||
Build plugin.Build `json:"build"`
|
||||
}{repo, build}
|
||||
|
||||
// json payload that will be posted
|
||||
payload, _ := json.Marshal(&data)
|
||||
|
||||
// post payload to each url
|
||||
for _, url := range vargs.Urls {
|
||||
resp, _ := http.Post(url, "application/json", bytes.NewBuffer(payload))
|
||||
resp.Body.Close()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
And the Dockerfile:
|
||||
|
||||
```dockerfile
|
||||
FROM gliderlabs/alpine:3.1
|
||||
RUN apk-install ca-certificates
|
||||
ADD drone-webhook /bin/
|
||||
ENTRYPOINT ["/bin/drone-webhook"]
|
||||
```
|
66
doc/plugin/overview.md
Normal file
66
doc/plugin/overview.md
Normal file
|
@ -0,0 +1,66 @@
|
|||
# Overview
|
||||
|
||||
Drone has a robust plugin model that allows you to extend the platform to meet your unique project needs. This documentation describes the Drone plugin architecture and will help you create your own custom plugins. If you are searching for existing plugins please see the [plugin marketplace](http://addons.drone.io).
|
||||
|
||||
## How Plugins Work
|
||||
|
||||
Plugins are simply Docker containers that attach to your build at runtime and perform custom operations. These operations may include deploying code, publishing artifacts and sending notifications.
|
||||
|
||||
Plugins are declared in the `.drone.yml` file. When Drone encounters a plugin it attempts to download from the registry (if not already downloaded) and then execute. This is an example of the [slack plugin](https://github.com/drone-plugins/drone-slack) configuration:
|
||||
|
||||
```yaml
|
||||
---
|
||||
notify:
|
||||
slack:
|
||||
image: plugins/slack
|
||||
webhook_url: https://hooks.slack.com/services/...
|
||||
username: captain_freedom
|
||||
channel: ics
|
||||
```
|
||||
|
||||
Plugins receive plugin configuration data, repository and build data as an encoded JSON string. The plugin can use this data when executing its task. For example, the [slack plugin](https://github.com/drone-plugins/drone-slack) uses the build and repository details to format and send a message to a channel.
|
||||
|
||||
Plugins also have access to the `/drone` volume, which is shared across all containers, including the build container. The repository is cloned to a subdirectory of `/drone/src`, which means plugins have access to your source code as well as any generated assets (binary files, reports, etc). For example, the [heroku plugin](https://github.com/drone-plugins/drone-heroku) accesses your source directory and executes `git push heroku master` to deploy your code.
|
||||
|
||||
## Plugin Input
|
||||
|
||||
Plugins receive build details via `arg[1]` as a JSON encoded string. The payload includes the following data structures:
|
||||
|
||||
* `repo` JSON representation of the repository
|
||||
* `build` JSON representation of the build, including commit and pull request
|
||||
* `vargs` JSON representation of the plugin configuration, as defined in the `.drone.yml`
|
||||
|
||||
Drone provides a simple [plugin library](https://github.com/drone/drone-plugin-go) that helps read and unmarshal the input parameters:
|
||||
|
||||
```go
|
||||
func main() {
|
||||
var repo = plugin.Repo{}
|
||||
var build = plugin.Build{}
|
||||
var vargs = struct {
|
||||
Webhook string `json:"webhook_url"`
|
||||
Username string `json:"username"`
|
||||
Channel string `json:"channel"`
|
||||
}{}
|
||||
|
||||
plugin.Param("repo", &repo)
|
||||
plugin.Param("build", &build)
|
||||
plugin.Param("vargs", &vargs)
|
||||
plugin.Parse()
|
||||
|
||||
// send slack notification
|
||||
}
|
||||
```
|
||||
|
||||
## Plugin Output
|
||||
|
||||
Plugins cannot send structured data back to Drone. Plugins can, however, write information to stdout so that it appears in the logs. Plugins can fail a build by exiting with a non-zero status code.
|
||||
|
||||
You may be asking yourself "how do I send reports or metrics back to Drone" or "how do I generate and store artificats in Drone"? The answer is that you cannot. Instead, you should use plugins to generate reports and send to third party services (like Coveralls) or generate and upload artifacts to third party storage services (like Bintray or S3).
|
||||
|
||||
## Plugin Reference
|
||||
|
||||
These are existing plugins that you can reference when building your own:
|
||||
|
||||
* [Slack](https://github.com/drone-plugins/drone-slack) - publish messages to a Slack channel when your build finishes
|
||||
* [Heroku](https://github.com/drone-plugins/drone-heroku) - deploy your application to Heroku
|
||||
* [Docker](https://github.com/drone-plugins/drone-docker) - build and publish your Docker image to a registry
|
44
doc/plugin/publish.md
Normal file
44
doc/plugin/publish.md
Normal file
|
@ -0,0 +1,44 @@
|
|||
# Publishing Plugins
|
||||
|
||||
Plugins must be published to a Docker registry in order for Drone to download and execute at runtime. You can publish to the official registry (at [index.docker.io](https://index.docker.io)) or to a private registry.
|
||||
|
||||
## Plugin marketplace
|
||||
|
||||
Official plugins are published to [index.docker.io/u/plugins](https://index.docker.io/u/plugins/) and are listed in the [plugin marketplace](http://addons.drone.io). If you would like to submit your plugin to the marketplace, as an officially supported Drone plugin, it must meet the following criteria:
|
||||
|
||||
* Plugin is useful to the broader community
|
||||
* Plugin is documented
|
||||
* Plugin is written in Go [1]
|
||||
* Plugin has manifest file
|
||||
* Plugin uses Apache2 license
|
||||
* Plugin uses `gliderlabs/apline` base image (unless technical limitations prohibit)
|
||||
|
||||
[1] Although plugins can be written in any language, official plugins must be written in Go. The core Drone team consists of primarily Go developers and we simply lack the expertise and bandwidth to support multiple stacks. This may change in the future (remember, this is still a young project) but for now this remains a requirement.
|
||||
|
||||
|
||||
## Plugin manifest
|
||||
|
||||
The plugin manifest, a subsection of the `.drone.yml` file, contains important information about your plugin:
|
||||
|
||||
* `name` - display name of the plugin
|
||||
* `desc` - brief description of the plugin
|
||||
* `type` - type of plugin. Possible values are clone, publish, deploy, notify
|
||||
* `image` - image repository in the Docker registry
|
||||
|
||||
Here is the [example manifest](https://github.com/drone-plugins/drone-slack/blob/master/.drone.yml) for the slack plugin:
|
||||
|
||||
```yaml
|
||||
---
|
||||
plugin:
|
||||
name: Slack
|
||||
desc: Sends build status notifications to your Slack channel.
|
||||
type: notify
|
||||
image: plugins/drone-slack
|
||||
labels:
|
||||
- chat
|
||||
- messaging
|
||||
```
|
||||
|
||||
## Plugin documentation
|
||||
|
||||
The plugin documentation is stored in the `./DOCS.md` file in the root of the repository. This file is used to auto-generate the documentation displayed in the [plugin marketplace](http://addons.drone.io).
|
|
@ -4,7 +4,7 @@ Drone uses the local Docker daemon (at `unix:///var/run/docker.sock`) to execute
|
|||
|
||||
Configure a single Docker host (1x build concurrency):
|
||||
|
||||
```
|
||||
```bash
|
||||
DOCKER_HOST="unix:///var/run/docker.sock"
|
||||
```
|
||||
|
||||
|
@ -14,7 +14,7 @@ Configure Drone to run multiple, concurrent builds by increasing the number of r
|
|||
|
||||
Configure multiple Docker hosts (4x build concurrency):
|
||||
|
||||
```
|
||||
```bash
|
||||
DOCKER_HOST_1="unix:///var/run/docker.sock"
|
||||
DOCKER_HOST_2="unix:///var/run/docker.sock"
|
||||
DOCKER_HOST_3="unix:///var/run/docker.sock"
|
||||
|
@ -23,7 +23,7 @@ DOCKER_HOST_4="unix:///var/run/docker.sock"
|
|||
|
||||
Configure a single, external Docker host (1x build concurrency):
|
||||
|
||||
```
|
||||
```bash
|
||||
DOCKER_HOST="tcp://1.2.3.4:2376"
|
||||
|
||||
DOCKER_CA="/path/to/ca.pem"
|
||||
|
@ -33,7 +33,7 @@ DOCKER_KEY="/path/to/key.pem"
|
|||
|
||||
Configure multiple, external Docker hosts (4x build concurrency using 2 remote servers):
|
||||
|
||||
```
|
||||
```bash
|
||||
DOCKER_HOST_1="tcp://1.2.3.4:2376"
|
||||
DOCKER_HOST_2="tcp://1.2.3.4:2376"
|
||||
|
||||
|
@ -59,14 +59,14 @@ This will generate the following files:
|
|||
|
||||
Tell Drone where to find the `cert.pem` and `key.pem`:
|
||||
|
||||
```
|
||||
```bash
|
||||
DOCKER_CERT="/path/to/cert.pem"
|
||||
DOCKER_KEY="/path/to/key.pem"
|
||||
```
|
||||
|
||||
If you are running Drone inside Docker you will need to mount the volume containing the certificate:
|
||||
When running Drone inside Docker, you'll need to mount the volume containing the certificate:
|
||||
|
||||
```
|
||||
```bash
|
||||
docker run
|
||||
--volume /path/to/cert.pem:/path/to/cert.pem \
|
||||
--volume /path/to/key.pem:/path/to/key.pem \
|
||||
|
@ -81,11 +81,11 @@ DOCKER_OPTS="--tlsverify --tlscacert=/etc/ssl/docker/ca.pem --tlscert=/etc/ssl/d
|
|||
|
||||
Verify that everything is configured correctly by connecting to a remote Docker server from our Drone server using the following command:
|
||||
|
||||
```
|
||||
```bash
|
||||
sudo docker \
|
||||
--tls \
|
||||
--tlscacert=/path/to/ca.pem \
|
||||
--tlscert=/path/to/cert.pem \
|
||||
--tlskey=/path/to/key.pem \
|
||||
-H=1.2.3.4:2376 version
|
||||
-H="1.2.3.4:2376" version
|
||||
```
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
Drone comes with built-in support for GitHub and GitHub Enterprise. To enable and configure GitHub, you should set the following environment variables:
|
||||
|
||||
```
|
||||
```bash
|
||||
REMOTE_DRIVER="github"
|
||||
|
||||
GITHUB_CLIENT="c0aaff74c060ff4a950d"
|
||||
|
|
Loading…
Reference in a new issue