A lightweight webhook action engine — execute custom commands and scripts based on YAML rules when webhook requests arrive.
Single binary, cross-platform (Linux / Windows / macOS).
$ hookrun validate
Validating config: config.yaml
PASS: All configurations are valid
Server port: 9000
Webhook route: /webhook
Allow all: true
First match only: true
Log path: ./logs
Log retention: 30 days
Config dir: ./hooks
Rule files loaded: 1
- github-auto-deploy (2 rules: push-to-main, tag-release) [auth: token]
$ hookrun start
HookRun started in background (PID: 8421)
$ hookrun status
Status: running
PID: 8421
Port: 9000
Rules: 2 config(s)
Uptime: 12m30s
# Incoming webhook
$ curl -X POST http://localhost:9000/webhook/github-auto-deploy \
-H "X-Webhook-Token: your-secret-token" \
-H "X-GitHub-Event: push" \
-d '{"ref":"refs/heads/main"}'
→ {"code":200,"message":"ok","config":"github-auto-deploy","rule":"push-to-main","actions":3}
- YAML Driven — All rules defined in YAML files, zero coding required
- Targeted Routing —
/webhook/{filename}directly routes to specific config for efficient matching - Flexible Auth — Token (Header/Query) + HMAC Signature (GitHub/GitLab) + IP whitelist with AND relationship
- Multi-Condition Filters — Match against Header / Query / Body with operators:
eqnecontainsregex - Execution Policies — Three modes:
block(prevent concurrency),always(always execute),cooldown(rate limiting) - Policy Inheritance — File-level → Rule-level override
- Matching Control —
first_match_onlytoggle for first-match-stops vs execute-all - Parameter Passing — Template variables (
{{.body.ref}}) andpass_argsto inject request data into commands - Hot Reload — Reload configs at runtime without restarting
- Log Management — Daily rotation with automatic cleanup
| Document | Description |
|---|---|
| Configuration Reference | Complete parameter reference for all config fields |
| Usage Guide | CLI commands, routing, response formats, and common scenarios |
| Deployment Guide | Build, systemd, Docker, Windows, and reverse proxy setup |
| 文档 | 说明 |
|---|---|
| 配置参数说明 | 所有配置字段的完整参数参考 |
| 使用指南 | CLI 命令、路由、响应格式和常见场景 |
| 部署说明 | 构建、systemd、Docker、Windows 及反向代理部署 |
# Build from source
git clone https://github.com/bluvenr/hookrun.git
cd HookRun
go build -o hookrun ./cmd/hookrun/- Edit global config
config.yaml:
server:
port: 9000
route: "/webhook"
allow_all: true # allow base route to iterate all configs
first_match_only: true # stop at first matching rule
log:
path: "./logs"
retention_days: 30
config_dir: "./hooks" # rule YAML files directory- Create a rule file
hooks/my-app.yaml:
name: "my-app-deploy"
auth:
token:
source: "header"
key: "X-Webhook-Token"
value: "your-secret"
execution:
policy: "block"
rules:
- name: "deploy-main"
filters:
- type: "header"
key: "X-GitHub-Event"
operator: "eq"
value: "push"
- type: "body"
key: "ref"
operator: "eq"
value: "refs/heads/main"
actions:
- type: "command"
cmd: "cd /var/www/my-app && git pull origin main"
timeout: 30
- type: "command"
cmd: "cd /var/www/my-app && npm install --production && npm run build"
timeout: 120
- type: "script"
path: "./scripts/deploy.sh"
args: ["production"]
timeout: 300# Validate configuration
hookrun validate
# Start server (daemon mode)
hookrun start
# Foreground mode (for debugging)
hookrun start -f| URL Pattern | Behavior |
|---|---|
/webhook/my-app |
Directly route to hooks/my-app.yaml, execute first matching rule |
/webhook |
Iterate all configs (controlled by allow_all and first_match_only) |
| Command | Description |
|---|---|
hookrun start |
Start server (daemon by default, -f for foreground) |
hookrun stop |
Stop the running server |
hookrun restart |
Restart the server |
hookrun status |
Show status (PID, port, rules count, uptime) |
hookrun reload |
Hot-reload all YAML configurations |
hookrun validate |
Validate all YAML files |
hookrun version |
Show version information |
Token, HMAC signature, and IP whitelist use AND relationship — all configured checks must pass:
auth:
token:
source: "header" # "header" or "query"
key: "X-Webhook-Token"
value: "secret123"
hmac:
header: "X-Hub-Signature-256" # GitHub signature header
secret: "your-webhook-secret" # HMAC secret from GitHub webhook settings
algorithm: "sha256" # "sha256" (default) | "sha1" | "sha512"
ip_whitelist:
- "192.168.1.100"
- "10.0.0.0/24" # CIDR supportedMultiple filters within a rule use AND relationship (all must match):
filters:
- type: "header" # "header" | "query" | "body"
key: "X-GitHub-Event"
operator: "eq" # "eq" | "ne" | "contains" | "regex"
value: "push"
- type: "body"
key: "commits[0].message" # JSON path supported
operator: "contains"
value: "release"Supports file-level and rule-level inheritance. Rule-level takes priority:
# File-level (default for all rules)
execution:
policy: "block" # "block" | "always" | "cooldown"
cooldown_seconds: 300 # only for cooldown mode
rules:
- name: "light-task"
execution:
policy: "always" # overrides file-level
...| Policy | Behavior | Use Case |
|---|---|---|
block |
Reject if still running (409) | Deploy, build |
always |
Always spawn new execution | Stateless notifications |
cooldown |
Reject within cooldown period (429) | Rate-limited scenarios |
actions:
- type: "command" # "command" | "script"
cmd: "echo hello"
timeout: 60 # timeout in seconds
isolate: false # run in isolated subprocess
continue_on_error: false # continue to next action on failure
- type: "command"
# Template variables: embed request data directly into commands
cmd: "git checkout {{.body.ref}}"
- type: "command"
# pass_args: extract and append as trailing arguments
cmd: "echo 'Deploying:'"
pass_args:
- source: "body"
key: "ref"
- source: "header"
key: "X-GitHub-Event"
- type: "script"
path: "./scripts/deploy.sh"
args: ["production"]
timeout: 300
isolate: trueAll responses are JSON with English messages:
{"code": 200, "message": "ok", "config": "my-app", "rule": "deploy-main", "actions": 3}
{"code": 401, "message": "Authentication failed"}
{"code": 409, "message": "Task 'my-app/deploy-main' is running, please try again later"}
{"code": 429, "message": "Task 'my-app/deploy-main' is in cooldown, retry in 120 seconds"}
{"code": 404, "message": "Config 'not-exist' not found"}HookRun/
├── cmd/hookrun/ # CLI entry point
├── internal/
│ ├── config/ # Config parsing & validation
│ ├── server/ # HTTP server & routing
│ ├── engine/ # Matching engine (Auth + Filter + Policy)
│ ├── executor/ # Command/script executor
│ ├── logger/ # Logging module
│ └── daemon/ # Daemon process management
├── config.yaml # Global configuration
├── hooks/ # Rule YAML directory
│ └── example.yaml
└── docs/ # Design documentation
MIT