documentation
This commit is contained in:
parent
a1a9f06c86
commit
6ef3684328
12 changed files with 221 additions and 29 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -2,3 +2,4 @@
|
||||||
**/*.rs.bk
|
**/*.rs.bk
|
||||||
|
|
||||||
/testroot
|
/testroot
|
||||||
|
/book
|
||||||
|
|
|
@ -15,7 +15,7 @@ cache: cargo
|
||||||
script:
|
script:
|
||||||
- if [ -z "$TRAVIS_TAG" ]; then cargo test --all; fi
|
- if [ -z "$TRAVIS_TAG" ]; then cargo test --all; fi
|
||||||
before_deploy:
|
before_deploy:
|
||||||
- ./ci/build-release.sh dip ${TRAVIS_TAG}-${TRAVIS_OS_NAME}
|
- ./ci/build.sh dip ${TRAVIS_TAG}-${TRAVIS_OS_NAME}
|
||||||
|
|
||||||
deploy:
|
deploy:
|
||||||
- provider: releases
|
- provider: releases
|
||||||
|
@ -27,4 +27,9 @@ deploy:
|
||||||
condition: $TRAVIS_RUST_VERSION = stable
|
condition: $TRAVIS_RUST_VERSION = stable
|
||||||
tags: true
|
tags: true
|
||||||
skip_cleanup: true
|
skip_cleanup: true
|
||||||
|
- provider: script
|
||||||
|
script: ./ci/book.sh
|
||||||
|
skip_cleanup: true
|
||||||
|
on:
|
||||||
|
condition: $TRAVIS_RUST_VERSION = stable
|
||||||
|
tags: true
|
||||||
|
|
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -184,7 +184,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dip"
|
name = "dip"
|
||||||
version = "0.1.3"
|
version = "0.1.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
|
5
book.toml
Normal file
5
book.toml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
[book]
|
||||||
|
authors = ["Michael Zhang"]
|
||||||
|
multilingual = false
|
||||||
|
src = "docs"
|
||||||
|
title = "Dip"
|
38
ci/book.sh
Executable file
38
ci/book.sh
Executable file
|
@ -0,0 +1,38 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -ex
|
||||||
|
|
||||||
|
### Setup latest mdbook version ################################################
|
||||||
|
|
||||||
|
INSTALLED=$(echo $(mdbook --version 2>/dev/null || echo "mdbook none") | cut -d' ' -f1)
|
||||||
|
PINNED=0.2.1
|
||||||
|
|
||||||
|
if [ "$PINNED" != "$INSTALLED" ]; then
|
||||||
|
URL=https://github.com/rust-lang-nursery/mdBook/releases/download/v${PINNED}/mdbook-v${PINNED}-x86_64-unknown-linux-gnu.tar.gz
|
||||||
|
curl -SsL $URL | tar xvz -C $HOME/.cargo/bin
|
||||||
|
fi
|
||||||
|
|
||||||
|
### Build the guide ################################################################
|
||||||
|
# Build and then upload the guide to a specific folder on the gh-pages branch. This way we can have multiple versions
|
||||||
|
# of the guide at the same time (See #165)
|
||||||
|
|
||||||
|
# This builds the book in target/doc/guide. See https://github.com/rust-lang-nursery/mdBook/issues/698
|
||||||
|
mdbook build -d ../target/doc/guide guide
|
||||||
|
|
||||||
|
# Get the lastest tag across all branches
|
||||||
|
# https://stackoverflow.com/a/7261049/3549270
|
||||||
|
git fetch --tags
|
||||||
|
LATEST_TAG=$(git describe --tags $(git rev-list --tags --max-count=1 -l v*))
|
||||||
|
|
||||||
|
git clone -b gh-pages https://$AUTH_TOKEN@github.com/$TRAVIS_REPO_SLUG.git gh_pages
|
||||||
|
cd gh_pages
|
||||||
|
|
||||||
|
echo "<meta http-equiv=refresh content=0;url='${LATEST_TAG}/'>" > index.html
|
||||||
|
|
||||||
|
# For builds triggered by a tag, $TRAVIS_BRANCH will be set to the tag
|
||||||
|
rm -rf "$TRAVIS_BRANCH"
|
||||||
|
cp -r ../target/doc/guide "$TRAVIS_BRANCH"
|
||||||
|
git add --all
|
||||||
|
git commit -m "Upload documentation for $TRAVIS_BRANCH"
|
||||||
|
|
||||||
|
git push -f
|
6
docs/SUMMARY.md
Normal file
6
docs/SUMMARY.md
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
# Summary
|
||||||
|
|
||||||
|
- [Intro](./intro.md)
|
||||||
|
- [Deployment](./deployment.md)
|
||||||
|
- [Configuration](./config.md)
|
||||||
|
- [Built-in Handlers](./handlers.md)
|
75
docs/config.md
Normal file
75
docs/config.md
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
# Configuration
|
||||||
|
|
||||||
|
The configuration directory should contain two subdirectories: `handlers` and `hooks`. The `hooks` directory should contain configuration files for webhooks. These files are defined in [TOML](https://github.com/toml-lang/toml). For example, here is a config file for a website deployment using gutenberg:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[[handlers]]
|
||||||
|
type = "github"
|
||||||
|
secret = "**************"
|
||||||
|
|
||||||
|
[[handlers]]
|
||||||
|
type = "command"
|
||||||
|
command = "rm -rf /var/www/default/*"
|
||||||
|
|
||||||
|
[[handlers]]
|
||||||
|
type = "command"
|
||||||
|
command = "gutenberg build --output-dir /var/www/default"
|
||||||
|
```
|
||||||
|
|
||||||
|
If this config file existed at `$DIP_ROOT/hooks/website`, then it would be served from `http://localhost:5000/webhook/website`.
|
||||||
|
|
||||||
|
## Config File Format
|
||||||
|
|
||||||
|
The hook config should contain an array called `handlers`, which is a sequence of `handler` tables.
|
||||||
|
|
||||||
|
#### The `type` key
|
||||||
|
|
||||||
|
Each `handler` must contain at least one key required by dip, `type`, which determines what kind of hook will be run.
|
||||||
|
|
||||||
|
Dip comes with two built-in handlers:
|
||||||
|
|
||||||
|
- [`command`](handlers.html#bash-commands)
|
||||||
|
- [`github`](handlers.html#github-webhooks)
|
||||||
|
|
||||||
|
If you set `type` to one of these values, dip will automatically use the built-in. Otherwise, dip will look into the `handlers` subdirectory for an executable matching the `type` that you specified. For example, if you set `type = "mkdir"`, then it will look for `$DIP_ROOT/handlers/mkdir`, which must be an executable file. It will _not_ run the system `mkdir`. If you want to run the system `mkdir`, use `type = "command"`, so it will run a bash command instead.
|
||||||
|
|
||||||
|
## Handler Input and Output
|
||||||
|
|
||||||
|
Think of a handler as a function that takes two inputs: a configuration and per-instance data. The configuration is specified in the configuration file, while the per-instance data is specific to that run of the webhook.
|
||||||
|
|
||||||
|
For example, suppose we have the following setup:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[[handlers]]
|
||||||
|
type = "github"
|
||||||
|
secret = "hunter2"
|
||||||
|
```
|
||||||
|
|
||||||
|
If a new Github webhook is deployed, then the first config input will be:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"secret": "hunter2"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This input will be provided to the executable using `--config` in JSON format. For example, if `github` was not a builtin, then a call to the `github` executable might look like:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
/usr/bin/github --config '{"secret":"hunter2"}'
|
||||||
|
```
|
||||||
|
|
||||||
|
The second input that's provided to the handler is information specific to this run. For the first handler in the sequence, this will be data serialized from the HTTP request, and for subsequent handlers, it will be the output of the previous handler. This input is provided through standard input directly as is.
|
||||||
|
|
||||||
|
Think of it as a fold over the list of handlers:
|
||||||
|
|
||||||
|
```hs
|
||||||
|
foldl (\input next_handler -> next_handler input) http_data handlers
|
||||||
|
```
|
||||||
|
|
||||||
|
### Environment Variables
|
||||||
|
|
||||||
|
Every process spawned by Dip as part of a webhook will have certain variables set to give it information about its environment:
|
||||||
|
|
||||||
|
- `DIP_ROOT`: the root config directory for Dip.
|
||||||
|
- `DIP_WORKDIR`: the temporary directory created for this specific hook invocation.
|
43
docs/deployment.md
Normal file
43
docs/deployment.md
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
# Deployment
|
||||||
|
|
||||||
|
## Download Dip
|
||||||
|
|
||||||
|
The easiest way to get a copy of Dip is to download a binary from the [releases page](https://github.com/acmumn/dip/releases).
|
||||||
|
|
||||||
|
Alternatively, clone the repository and compile from source.
|
||||||
|
|
||||||
|
### HTTP Server setup
|
||||||
|
|
||||||
|
Dip runs an HTTP server. By default it serves on port 5000 on all interfaces. Use `--bind` on the executable to change this.
|
||||||
|
|
||||||
|
It's recommended to vhost your Dip through a server such as Nginx. Here's a sample Nginx config:
|
||||||
|
|
||||||
|
```
|
||||||
|
location / {
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $remote_addr;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_pass http://localhost:5000;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Root configuration directory
|
||||||
|
|
||||||
|
Delegate a directory on your server to act as a root config directory.
|
||||||
|
|
||||||
|
### Systemd
|
||||||
|
|
||||||
|
Systemd is useful for keeping Dip running as a daemon, and starting it automatically on startup. Here's a sample systemd config:
|
||||||
|
|
||||||
|
```
|
||||||
|
[Unit]
|
||||||
|
Description=Configurable Webhook Server
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
User=dip
|
||||||
|
Environment="RUST_BACKTRACE=1"
|
||||||
|
ExecStart=/usr/bin/dip --root /etc/dip --bind "127.0.0.1:5000"
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=default.target
|
||||||
|
```
|
39
docs/handlers.md
Normal file
39
docs/handlers.md
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
# Built-in Handlers
|
||||||
|
|
||||||
|
Dip comes with two built-in handlers: Bash commands and Github webhooks.
|
||||||
|
|
||||||
|
## Bash commands
|
||||||
|
|
||||||
|
Bash commands are invoked with `type = "command"`. It will run whatever is specified in the `command` field using `bash` (assuming it exists on the system).
|
||||||
|
|
||||||
|
An full config using a `command` handler follows:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[[handlers]]
|
||||||
|
type = "command"
|
||||||
|
|
||||||
|
# the command to run using bash
|
||||||
|
command = "echo hi"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Github webhooks
|
||||||
|
|
||||||
|
For Github webhooks, dip will verify the webhook (by using the provided secret) and then clone the repository that the webhook was attached to into the temporary directory created for that specific invocation.
|
||||||
|
|
||||||
|
This handler isn't very useful by itself, so it's a good idea to follow up this handler with some `command`s or other handlers to use the newly cloned repository (for example, build or deploy).
|
||||||
|
|
||||||
|
An full config using a `github` handler follows:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[[handlers]]
|
||||||
|
type = "github"
|
||||||
|
|
||||||
|
# webhook secret
|
||||||
|
secret = "**************"
|
||||||
|
|
||||||
|
# turn off secret verification (false by default)
|
||||||
|
disable_hmac_verify = false
|
||||||
|
|
||||||
|
# path to clone to
|
||||||
|
path = "."
|
||||||
|
```
|
5
docs/intro.md
Normal file
5
docs/intro.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
# Dip
|
||||||
|
|
||||||
|
Dip is a configurable webhook server.
|
||||||
|
|
||||||
|
It will listen on endpoints, and every time that endpoint is hit, it will run through a set of commands defined through configuration files.
|
27
src/lib.rs
27
src/lib.rs
|
@ -1,32 +1,7 @@
|
||||||
/*!
|
/*!
|
||||||
# Dip
|
# Dip
|
||||||
|
|
||||||
The configurable webhook server. Latest stable binary releases for Linux are available on the [releases][1] page.
|
The configurable webhook server. Latest stable binary releases for Linux are available on the releases page.
|
||||||
|
|
||||||
## Flow
|
|
||||||
|
|
||||||
In your config file, you define **hooks**: endpoints that are listening for input. Each hook comprises of a series
|
|
||||||
of handlers, which are building blocks of the hook. The hook will execute each handler in order, taking the output
|
|
||||||
of one and passing it into the input of the next.
|
|
||||||
|
|
||||||
## Getting Started
|
|
||||||
|
|
||||||
Setup is incredibly simple: first, obtain a copy of `dip` either through the binary releases page or by compiling from source.
|
|
||||||
Then, create a directory that you'll use as your `DIP_ROOT` directory. It should look like this:
|
|
||||||
|
|
||||||
```text
|
|
||||||
root
|
|
||||||
├─handlers
|
|
||||||
│ ├─executable
|
|
||||||
├─hooks
|
|
||||||
│ ├─hookname
|
|
||||||
```
|
|
||||||
|
|
||||||
Handlers exist in the form of executables that take a `--config` and an input via `stdin`. These inputs should
|
|
||||||
take the form of JSON objects. Usually config is passed through the hook config, and stdin is the output of the
|
|
||||||
previous handler.
|
|
||||||
|
|
||||||
[1]: https://github.com/acmumn/dip/releases
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#![deny(missing_docs)]
|
#![deny(missing_docs)]
|
||||||
|
|
Loading…
Reference in a new issue