docs: rewrite README to be less webhook centric
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: I4a46610262c629f22bc61b8581a4a0336a6a6964
This commit is contained in:
parent
2facb2a1e2
commit
d952b973a8
1 changed files with 144 additions and 87 deletions
231
README.md
231
README.md
|
|
@ -3,10 +3,34 @@
|
|||
Troutbot is the final solution to protecting the trout population. It's
|
||||
environmental protection incarnate!
|
||||
|
||||
Well in reality, it's a GitHub webhook bot that analyzes issues and pull
|
||||
requests using real signals such as CI check results, diff quality, and body
|
||||
structure and then posts trout-themed comments about the findings. Now you know
|
||||
whether your changes hurt or help the trout population.
|
||||
Well, in reality, it is a GitHub bot that analyzes issues and pull requests
|
||||
using real signals such as CI check results, diff quality, and body structure
|
||||
and then posts trout-themed comments about the findings. Now you know whether
|
||||
your changes hurt or help the trout population.
|
||||
|
||||
## Operation Modes
|
||||
|
||||
Troutbot supports two operation modes:
|
||||
|
||||
### Webhook Mode (Real-time)
|
||||
|
||||
GitHub sends webhook events to troutbot when issues/PRs are opened or updated.
|
||||
Troutbot responds immediately. Best for:
|
||||
|
||||
- Single or few repositories
|
||||
- You have admin access to configure webhooks
|
||||
- You can expose a public endpoint
|
||||
|
||||
### Polling Mode (Periodic)
|
||||
|
||||
Troutbot periodically polls configured repositories for `@troutbot` mentions in
|
||||
comments. Best for:
|
||||
|
||||
- Monitoring dozens of repositories without webhook setup
|
||||
- Running behind a firewall or on dynamic IPs
|
||||
- Simplified deployment without webhook secrets
|
||||
|
||||
Both modes use the same analysis engine and produce the same results.
|
||||
|
||||
## Quick Start
|
||||
|
||||
|
|
@ -17,18 +41,17 @@ $ npm install
|
|||
# Populate the environment config
|
||||
$ cp .env.example .env
|
||||
|
||||
# Set up application confg
|
||||
# Set up application config
|
||||
cp config.example.ts config.ts
|
||||
|
||||
# Edit .env and config.ts, then to start:
|
||||
npm run build && npm start
|
||||
# Edit .env and config.ts, then build and start.
|
||||
# If `.env` is not populated, Troutbot will start in dry-run mode.
|
||||
pnpm run build && pnpm start
|
||||
```
|
||||
|
||||
## How It Works
|
||||
|
||||
Troutbot has three analysis backends ran against each incoming webhook event.
|
||||
They are the primary decisionmaking logic behind whether your changes affect the
|
||||
trout population negatively, or positively.
|
||||
Troutbot has three analysis backends that analyze issues and PRs:
|
||||
|
||||
### `checks`
|
||||
|
||||
|
|
@ -71,6 +94,75 @@ checks 0.4, diff 0.3, quality 0.3). Backends that return zero confidence (e.g.,
|
|||
no CI checks found yet) are excluded from the average. If combined confidence
|
||||
falls below `confidenceThreshold`, the result is forced to neutral.
|
||||
|
||||
## Webhook Mode
|
||||
|
||||
In webhook mode, troutbot receives real-time events from GitHub.
|
||||
|
||||
### GitHub Webhook Setup
|
||||
|
||||
1. Go to your repository's **Settings > Webhooks > Add webhook**
|
||||
2. **Payload URL**: `https://your-host/webhook`
|
||||
3. **Content type**: `application/json`
|
||||
4. **Secret**: Generate with `openssl rand -hex 32` and set as `WEBHOOK_SECRET`
|
||||
5. **Events**: Select **Issues**, **Pull requests**, and optionally **Check
|
||||
suites** (for re-analysis when CI finishes)
|
||||
|
||||
If you enable **Check suites** and set `response.allowUpdates: true` in your
|
||||
config, troutbot will update its comment on a PR once CI results are available.
|
||||
|
||||
### Webhook Security
|
||||
|
||||
- **`WEBHOOK_SECRET` is strongly recommended.** Without it, anyone who can reach
|
||||
the `/webhook` endpoint can trigger analysis and post comments. Always set a
|
||||
secret and configure the same value in your GitHub webhook settings.
|
||||
|
||||
## Polling Mode
|
||||
|
||||
In polling mode, troutbot periodically checks configured repositories for
|
||||
`@troutbot` mentions in comments.
|
||||
|
||||
### Configuration
|
||||
|
||||
Enable polling in your `config.ts`:
|
||||
|
||||
```typescript
|
||||
polling: {
|
||||
enabled: true,
|
||||
intervalMinutes: 5, // Check every 5 minutes
|
||||
lookbackMinutes: 10, // Look back 10 minutes for new comments
|
||||
}
|
||||
```
|
||||
|
||||
### How It Works
|
||||
|
||||
1. On startup, troutbot fetches recent comments from all configured repositories
|
||||
2. It scans each comment for `@troutbot` mentions
|
||||
3. When found, it analyzes the associated issue/PR and posts a response
|
||||
4. Processed comments are tracked to avoid duplicate responses
|
||||
5. The cycle repeats every `intervalMinutes`
|
||||
|
||||
### On-Demand Analysis
|
||||
|
||||
Users can trigger analysis by mentioning `@troutbot` in any comment:
|
||||
|
||||
```plaintext
|
||||
Hey @troutbot, can you take a look at this?
|
||||
```
|
||||
|
||||
The bot will analyze the issue/PR and respond with a trout-themed assessment.
|
||||
|
||||
### Rate Limiting
|
||||
|
||||
Polling uses the GitHub REST API and respects rate limits. The default settings
|
||||
(5 min interval, 10 min lookback) are conservative and work well within GitHub's
|
||||
5000 requests/hour limit for personal access tokens.
|
||||
|
||||
### Requirements
|
||||
|
||||
- `GITHUB_TOKEN` with read access to all watched repositories
|
||||
- Repositories configured in `config.repositories`
|
||||
- Write access to post comments
|
||||
|
||||
## GitHub Account & Token Setup
|
||||
|
||||
Troutbot is designed to run as a dedicated bot account on GitHub. Create a
|
||||
|
|
@ -89,8 +181,7 @@ The bot account needs access to every repository it will comment on:
|
|||
- **For organization repos**: Invite the bot account as a collaborator with
|
||||
**Write** access, or add it to a team with write permissions.
|
||||
- **For personal repos**: Add the bot account as a collaborator under
|
||||
\*\*Settings
|
||||
> Collaborators\*\*.
|
||||
`Settings > Collaborators`.
|
||||
|
||||
The bot needs write access to post comments. Read access alone is not enough.
|
||||
|
||||
|
|
@ -98,10 +189,10 @@ The bot needs write access to post comments. Read access alone is not enough.
|
|||
|
||||
Log in as the bot account and create a fine-grained PAT:
|
||||
|
||||
1. Go to **Settings > Developer settings > Personal access tokens > Fine-grained
|
||||
tokens**
|
||||
1. Go to
|
||||
`Settings > Developer settings > Personal access tokens > Fine-grained tokens`
|
||||
2. Click **Generate new token**
|
||||
3. Set a descriptive name (e.g., `troutbot-webhook`)
|
||||
3. Set a descriptive name (e.g., `troutbot-production`)
|
||||
4. Set **Expiration** - pick a long-lived duration or no expiration, since this
|
||||
runs unattended
|
||||
5. Under **Repository access**, select the specific repositories the bot will
|
||||
|
|
@ -121,19 +212,7 @@ Set this as the `GITHUB_TOKEN` environment variable.
|
|||
> `repo` scope. Fine-grained tokens are recommended because they follow the
|
||||
> principle of least privilege.
|
||||
|
||||
### 4. Generate a webhook secret
|
||||
|
||||
Generate a random secret to verify webhook payloads:
|
||||
|
||||
```bash
|
||||
openssl rand -hex 32
|
||||
```
|
||||
|
||||
Set this as the `WEBHOOK_SECRET` environment variable, and use the same value
|
||||
when configuring the webhook in GitHub (see
|
||||
[GitHub Webhook Setup](#github-webhook-setup)).
|
||||
|
||||
## Configuration
|
||||
## Configuring Troutbot
|
||||
|
||||
### Environment Variables
|
||||
|
||||
|
|
@ -142,7 +221,7 @@ when configuring the webhook in GitHub (see
|
|||
| Variable | Description | Required |
|
||||
| ---------------- | ----------------------------------------------------- | ---------------------------- |
|
||||
| `GITHUB_TOKEN` | Fine-grained PAT from the bot account (see above) | No (dry-run without it) |
|
||||
| `WEBHOOK_SECRET` | Secret for verifying webhook signatures | No (skips verification) |
|
||||
| `WEBHOOK_SECRET` | Secret for verifying webhook signatures | No (only for webhook mode) |
|
||||
| `PORT` | Server port (overrides `server.port` in config) | No |
|
||||
| `CONFIG_PATH` | Path to config file | No (defaults to `config.ts`) |
|
||||
| `LOG_LEVEL` | Log level override (`debug`, `info`, `warn`, `error`) | No |
|
||||
|
|
@ -156,10 +235,11 @@ default-exports a `Config` object - full type checking and autocompletion in
|
|||
your editor.
|
||||
|
||||
```typescript
|
||||
import type { Config } from "./src/types";
|
||||
import type { Config } from './src/types';
|
||||
|
||||
const config: Config = {
|
||||
server: { port: 3000 },
|
||||
repositories: [{ owner: 'myorg', repo: 'myrepo' }],
|
||||
engine: {
|
||||
backends: {
|
||||
checks: { enabled: true },
|
||||
|
|
@ -169,6 +249,11 @@ const config: Config = {
|
|||
weights: { checks: 0.4, diff: 0.3, quality: 0.3 },
|
||||
confidenceThreshold: 0.1,
|
||||
},
|
||||
polling: {
|
||||
enabled: true,
|
||||
intervalMinutes: 5,
|
||||
lookbackMinutes: 10,
|
||||
},
|
||||
// ...
|
||||
};
|
||||
|
||||
|
|
@ -180,28 +265,13 @@ pre-compilation needed.
|
|||
|
||||
See `config.example.ts` for the full annotated reference.
|
||||
|
||||
## GitHub Webhook Setup
|
||||
|
||||
1. Go to your repository's **Settings > Webhooks > Add webhook**
|
||||
2. **Payload URL**: `https://your-host/webhook`
|
||||
3. **Content type**: `application/json`
|
||||
4. **Secret**: Must match your `WEBHOOK_SECRET` env var
|
||||
5. **Events**: Select **Issues**, **Pull requests**, and optionally **Check
|
||||
suites** (for re-analysis when CI finishes)
|
||||
|
||||
If you enable **Check suites** and set `response.allowUpdates: true` in your
|
||||
config, troutbot will update its comment on a PR once CI results are available.
|
||||
|
||||
## Production Configuration
|
||||
|
||||
When deploying troutbot to production, keep the following in mind:
|
||||
|
||||
- **`WEBHOOK_SECRET` is strongly recommended.** Without it, anyone who can reach
|
||||
the `/webhook` endpoint can trigger analysis and post comments. Always set a
|
||||
secret and configure the same value in your GitHub webhook settings.
|
||||
- **Use a reverse proxy with TLS.** GitHub sends webhook payloads over HTTPS.
|
||||
Put nginx, Caddy, or a cloud load balancer in front of troutbot and terminate
|
||||
TLS there.
|
||||
- **Use a reverse proxy with TLS.** If using webhook mode, GitHub sends payloads
|
||||
over HTTPS. Put nginx, Caddy, or a cloud load balancer in front of troutbot
|
||||
and terminate TLS there. Polling mode doesn't require a public endpoint.
|
||||
- **Set `NODE_ENV=production`.** This is set automatically in the Docker image.
|
||||
For standalone deployments, export it in your environment. Express uses this
|
||||
to enable performance optimizations.
|
||||
|
|
@ -218,22 +288,19 @@ When deploying troutbot to production, keep the following in mind:
|
|||
|
||||
## Deployment
|
||||
|
||||
<details>
|
||||
<summary>Standalone (Node.js)</summary>
|
||||
### Standalone (Node.js)
|
||||
|
||||
```bash
|
||||
npm ci
|
||||
npm run build
|
||||
export NODE_ENV=production
|
||||
export GITHUB_TOKEN="ghp_..."
|
||||
export WEBHOOK_SECRET="your-secret"
|
||||
# Only needed for webhook mode:
|
||||
# export WEBHOOK_SECRET="your-secret"
|
||||
npm start
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Nix</summary>
|
||||
### Nix
|
||||
|
||||
**Flake** (NixOS or flake-enabled systems):
|
||||
|
||||
|
|
@ -248,8 +315,8 @@ npm start
|
|||
{
|
||||
services.troutbot = {
|
||||
enable = true;
|
||||
environmentFile = "/path/to/.env"; # use Agenix if possible
|
||||
configPath = "/path/to/config.ts" # use Agenix if possible
|
||||
environmentFile = "/path/to/.env";
|
||||
configPath = "/path/to/config.ts";
|
||||
};
|
||||
}
|
||||
];
|
||||
|
|
@ -264,10 +331,7 @@ npm start
|
|||
nix run github:notashelf/troutbot
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Docker</summary>
|
||||
### Docker
|
||||
|
||||
```bash
|
||||
docker build -t troutbot .
|
||||
|
|
@ -275,7 +339,6 @@ docker run -d \
|
|||
--name troutbot \
|
||||
-p 127.0.0.1:3000:3000 \
|
||||
-e GITHUB_TOKEN="ghp_..." \
|
||||
-e WEBHOOK_SECRET="your-secret" \
|
||||
-v $(pwd)/config.ts:/app/config.ts:ro \
|
||||
--restart unless-stopped \
|
||||
troutbot
|
||||
|
|
@ -283,17 +346,14 @@ docker run -d \
|
|||
|
||||
Multi-stage build, non-root user, built-in health check, `STOPSIGNAL SIGTERM`.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Docker Compose</summary>
|
||||
### Docker Compose
|
||||
|
||||
```yaml
|
||||
services:
|
||||
troutbot:
|
||||
build: .
|
||||
ports:
|
||||
- "127.0.0.1:3000:3000"
|
||||
- '127.0.0.1:3000:3000'
|
||||
env_file: .env
|
||||
volumes:
|
||||
- ./config.ts:/app/config.ts:ro
|
||||
|
|
@ -305,20 +365,17 @@ services:
|
|||
logging:
|
||||
driver: json-file
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "3"
|
||||
max-size: '10m'
|
||||
max-file: '3'
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>systemd</summary>
|
||||
### Systemd
|
||||
|
||||
Create `/etc/systemd/system/troutbot.service`:
|
||||
|
||||
```ini
|
||||
[Unit]
|
||||
Description=Troutbot GitHub Webhook Bot
|
||||
Description=Troutbot GitHub Bot
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
|
|
@ -345,10 +402,9 @@ sudo systemctl daemon-reload
|
|||
sudo systemctl enable --now troutbot
|
||||
```
|
||||
|
||||
</details>
|
||||
### Reverse Proxy (nginx)
|
||||
|
||||
<details>
|
||||
<summary>Reverse Proxy (nginx)</summary>
|
||||
Only needed for webhook mode:
|
||||
|
||||
```nginx
|
||||
server {
|
||||
|
|
@ -369,7 +425,7 @@ server {
|
|||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
# Optional: nginx-level rate limiting
|
||||
# Optional: nginx-level rate limiting for webhooks
|
||||
# limit_req_zone $binary_remote_addr zone=webhook:10m rate=10r/s;
|
||||
# location /webhook {
|
||||
# limit_req zone=webhook burst=20 nodelay;
|
||||
|
|
@ -378,21 +434,23 @@ server {
|
|||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
## API Endpoints
|
||||
|
||||
<!--markdownlint-disable MD013-->
|
||||
|
||||
| Method | Path | Description |
|
||||
| -------- | ------------- | ---------------------------------------------------------------------------------------- |
|
||||
| `GET` | `/health` | Health check - returns `status`, `uptime` (seconds), `version`, `dryRun`, and `backends` |
|
||||
| `POST` | `/webhook` | GitHub webhook receiver (rate limited) |
|
||||
| `POST` | `/webhook` | GitHub webhook receiver (rate limited, webhook mode only) |
|
||||
| `GET` | `/dashboard` | Web UI dashboard with status, events, and config editor |
|
||||
| `GET` | `/api/status` | JSON status: uptime, version, dry-run, backends, repo count |
|
||||
| `GET` | `/api/events` | Recent webhook events from the in-memory ring buffer |
|
||||
| `GET` | `/api/events` | Recent events from the in-memory ring buffer |
|
||||
| `DELETE` | `/api/events` | Clear the event ring buffer |
|
||||
| `GET` | `/api/config` | Current runtime configuration as JSON |
|
||||
| `PUT` | `/api/config` | Partial config update: deep-merges, validates, and applies in-place |
|
||||
|
||||
<!--markdownlint-enable MD013-->
|
||||
|
||||
## Dashboard & Runtime API
|
||||
|
||||
Troutbot ships with a built-in web dashboard and JSON API for monitoring and
|
||||
|
|
@ -405,9 +463,8 @@ running). The dashboard provides:
|
|||
|
||||
- **Status card** - uptime, version, dry-run state, active backends, and repo
|
||||
count. Auto-refreshes every 30 seconds.
|
||||
- **Event log** - table of recent webhook events showing repo, PR/issue number,
|
||||
action, impact rating, and confidence score. Keeps the last 100 events in
|
||||
memory.
|
||||
- **Event log** - table of recent events showing repo, PR/issue number, action,
|
||||
impact rating, and confidence score. Keeps the last 100 events in memory.
|
||||
- **Config editor** - read-only JSON view of the current runtime config with an
|
||||
"Edit" toggle that lets you modify and save changes without restarting.
|
||||
|
||||
|
|
@ -441,8 +498,8 @@ original config remains unchanged if validation fails.
|
|||
|
||||
### Event Buffer API
|
||||
|
||||
The event buffer stores the last 100 processed webhook events in memory. Events
|
||||
are lost on restart.
|
||||
The event buffer stores the last 100 processed events in memory (from both
|
||||
webhooks and polling). Events are lost on restart.
|
||||
|
||||
```bash
|
||||
# List recent events
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue