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
|
Troutbot is the final solution to protecting the trout population. It's
|
||||||
environmental protection incarnate!
|
environmental protection incarnate!
|
||||||
|
|
||||||
Well in reality, it's a GitHub webhook bot that analyzes issues and pull
|
Well, in reality, it is a GitHub bot that analyzes issues and pull requests
|
||||||
requests using real signals such as CI check results, diff quality, and body
|
using real signals such as CI check results, diff quality, and body structure
|
||||||
structure and then posts trout-themed comments about the findings. Now you know
|
and then posts trout-themed comments about the findings. Now you know whether
|
||||||
whether your changes hurt or help the trout population.
|
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
|
## Quick Start
|
||||||
|
|
||||||
|
|
@ -17,18 +41,17 @@ $ npm install
|
||||||
# Populate the environment config
|
# Populate the environment config
|
||||||
$ cp .env.example .env
|
$ cp .env.example .env
|
||||||
|
|
||||||
# Set up application confg
|
# Set up application config
|
||||||
cp config.example.ts config.ts
|
cp config.example.ts config.ts
|
||||||
|
|
||||||
# Edit .env and config.ts, then to start:
|
# Edit .env and config.ts, then build and start.
|
||||||
npm run build && npm start
|
# If `.env` is not populated, Troutbot will start in dry-run mode.
|
||||||
|
pnpm run build && pnpm start
|
||||||
```
|
```
|
||||||
|
|
||||||
## How It Works
|
## How It Works
|
||||||
|
|
||||||
Troutbot has three analysis backends ran against each incoming webhook event.
|
Troutbot has three analysis backends that analyze issues and PRs:
|
||||||
They are the primary decisionmaking logic behind whether your changes affect the
|
|
||||||
trout population negatively, or positively.
|
|
||||||
|
|
||||||
### `checks`
|
### `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
|
no CI checks found yet) are excluded from the average. If combined confidence
|
||||||
falls below `confidenceThreshold`, the result is forced to neutral.
|
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
|
## GitHub Account & Token Setup
|
||||||
|
|
||||||
Troutbot is designed to run as a dedicated bot account on GitHub. Create a
|
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
|
- **For organization repos**: Invite the bot account as a collaborator with
|
||||||
**Write** access, or add it to a team with write permissions.
|
**Write** access, or add it to a team with write permissions.
|
||||||
- **For personal repos**: Add the bot account as a collaborator under
|
- **For personal repos**: Add the bot account as a collaborator under
|
||||||
\*\*Settings
|
`Settings > Collaborators`.
|
||||||
> Collaborators\*\*.
|
|
||||||
|
|
||||||
The bot needs write access to post comments. Read access alone is not enough.
|
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:
|
Log in as the bot account and create a fine-grained PAT:
|
||||||
|
|
||||||
1. Go to **Settings > Developer settings > Personal access tokens > Fine-grained
|
1. Go to
|
||||||
tokens**
|
`Settings > Developer settings > Personal access tokens > Fine-grained tokens`
|
||||||
2. Click **Generate new token**
|
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
|
4. Set **Expiration** - pick a long-lived duration or no expiration, since this
|
||||||
runs unattended
|
runs unattended
|
||||||
5. Under **Repository access**, select the specific repositories the bot will
|
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
|
> `repo` scope. Fine-grained tokens are recommended because they follow the
|
||||||
> principle of least privilege.
|
> principle of least privilege.
|
||||||
|
|
||||||
### 4. Generate a webhook secret
|
## Configuring Troutbot
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
### Environment Variables
|
### Environment Variables
|
||||||
|
|
||||||
|
|
@ -142,7 +221,7 @@ when configuring the webhook in GitHub (see
|
||||||
| Variable | Description | Required |
|
| Variable | Description | Required |
|
||||||
| ---------------- | ----------------------------------------------------- | ---------------------------- |
|
| ---------------- | ----------------------------------------------------- | ---------------------------- |
|
||||||
| `GITHUB_TOKEN` | Fine-grained PAT from the bot account (see above) | No (dry-run without it) |
|
| `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 |
|
| `PORT` | Server port (overrides `server.port` in config) | No |
|
||||||
| `CONFIG_PATH` | Path to config file | No (defaults to `config.ts`) |
|
| `CONFIG_PATH` | Path to config file | No (defaults to `config.ts`) |
|
||||||
| `LOG_LEVEL` | Log level override (`debug`, `info`, `warn`, `error`) | No |
|
| `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.
|
your editor.
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import type { Config } from "./src/types";
|
import type { Config } from './src/types';
|
||||||
|
|
||||||
const config: Config = {
|
const config: Config = {
|
||||||
server: { port: 3000 },
|
server: { port: 3000 },
|
||||||
|
repositories: [{ owner: 'myorg', repo: 'myrepo' }],
|
||||||
engine: {
|
engine: {
|
||||||
backends: {
|
backends: {
|
||||||
checks: { enabled: true },
|
checks: { enabled: true },
|
||||||
|
|
@ -169,6 +249,11 @@ const config: Config = {
|
||||||
weights: { checks: 0.4, diff: 0.3, quality: 0.3 },
|
weights: { checks: 0.4, diff: 0.3, quality: 0.3 },
|
||||||
confidenceThreshold: 0.1,
|
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.
|
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
|
## Production Configuration
|
||||||
|
|
||||||
When deploying troutbot to production, keep the following in mind:
|
When deploying troutbot to production, keep the following in mind:
|
||||||
|
|
||||||
- **`WEBHOOK_SECRET` is strongly recommended.** Without it, anyone who can reach
|
- **Use a reverse proxy with TLS.** If using webhook mode, GitHub sends payloads
|
||||||
the `/webhook` endpoint can trigger analysis and post comments. Always set a
|
over HTTPS. Put nginx, Caddy, or a cloud load balancer in front of troutbot
|
||||||
secret and configure the same value in your GitHub webhook settings.
|
and terminate TLS there. Polling mode doesn't require a public endpoint.
|
||||||
- **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.
|
|
||||||
- **Set `NODE_ENV=production`.** This is set automatically in the Docker image.
|
- **Set `NODE_ENV=production`.** This is set automatically in the Docker image.
|
||||||
For standalone deployments, export it in your environment. Express uses this
|
For standalone deployments, export it in your environment. Express uses this
|
||||||
to enable performance optimizations.
|
to enable performance optimizations.
|
||||||
|
|
@ -218,22 +288,19 @@ When deploying troutbot to production, keep the following in mind:
|
||||||
|
|
||||||
## Deployment
|
## Deployment
|
||||||
|
|
||||||
<details>
|
### Standalone (Node.js)
|
||||||
<summary>Standalone (Node.js)</summary>
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm ci
|
npm ci
|
||||||
npm run build
|
npm run build
|
||||||
export NODE_ENV=production
|
export NODE_ENV=production
|
||||||
export GITHUB_TOKEN="ghp_..."
|
export GITHUB_TOKEN="ghp_..."
|
||||||
export WEBHOOK_SECRET="your-secret"
|
# Only needed for webhook mode:
|
||||||
|
# export WEBHOOK_SECRET="your-secret"
|
||||||
npm start
|
npm start
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
### Nix
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Nix</summary>
|
|
||||||
|
|
||||||
**Flake** (NixOS or flake-enabled systems):
|
**Flake** (NixOS or flake-enabled systems):
|
||||||
|
|
||||||
|
|
@ -248,8 +315,8 @@ npm start
|
||||||
{
|
{
|
||||||
services.troutbot = {
|
services.troutbot = {
|
||||||
enable = true;
|
enable = true;
|
||||||
environmentFile = "/path/to/.env"; # use Agenix if possible
|
environmentFile = "/path/to/.env";
|
||||||
configPath = "/path/to/config.ts" # use Agenix if possible
|
configPath = "/path/to/config.ts";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
@ -264,10 +331,7 @@ npm start
|
||||||
nix run github:notashelf/troutbot
|
nix run github:notashelf/troutbot
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
### Docker
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Docker</summary>
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker build -t troutbot .
|
docker build -t troutbot .
|
||||||
|
|
@ -275,7 +339,6 @@ docker run -d \
|
||||||
--name troutbot \
|
--name troutbot \
|
||||||
-p 127.0.0.1:3000:3000 \
|
-p 127.0.0.1:3000:3000 \
|
||||||
-e GITHUB_TOKEN="ghp_..." \
|
-e GITHUB_TOKEN="ghp_..." \
|
||||||
-e WEBHOOK_SECRET="your-secret" \
|
|
||||||
-v $(pwd)/config.ts:/app/config.ts:ro \
|
-v $(pwd)/config.ts:/app/config.ts:ro \
|
||||||
--restart unless-stopped \
|
--restart unless-stopped \
|
||||||
troutbot
|
troutbot
|
||||||
|
|
@ -283,17 +346,14 @@ docker run -d \
|
||||||
|
|
||||||
Multi-stage build, non-root user, built-in health check, `STOPSIGNAL SIGTERM`.
|
Multi-stage build, non-root user, built-in health check, `STOPSIGNAL SIGTERM`.
|
||||||
|
|
||||||
</details>
|
### Docker Compose
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Docker Compose</summary>
|
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
services:
|
services:
|
||||||
troutbot:
|
troutbot:
|
||||||
build: .
|
build: .
|
||||||
ports:
|
ports:
|
||||||
- "127.0.0.1:3000:3000"
|
- '127.0.0.1:3000:3000'
|
||||||
env_file: .env
|
env_file: .env
|
||||||
volumes:
|
volumes:
|
||||||
- ./config.ts:/app/config.ts:ro
|
- ./config.ts:/app/config.ts:ro
|
||||||
|
|
@ -305,20 +365,17 @@ services:
|
||||||
logging:
|
logging:
|
||||||
driver: json-file
|
driver: json-file
|
||||||
options:
|
options:
|
||||||
max-size: "10m"
|
max-size: '10m'
|
||||||
max-file: "3"
|
max-file: '3'
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
### Systemd
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>systemd</summary>
|
|
||||||
|
|
||||||
Create `/etc/systemd/system/troutbot.service`:
|
Create `/etc/systemd/system/troutbot.service`:
|
||||||
|
|
||||||
```ini
|
```ini
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=Troutbot GitHub Webhook Bot
|
Description=Troutbot GitHub Bot
|
||||||
After=network.target
|
After=network.target
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
|
|
@ -345,10 +402,9 @@ sudo systemctl daemon-reload
|
||||||
sudo systemctl enable --now troutbot
|
sudo systemctl enable --now troutbot
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
### Reverse Proxy (nginx)
|
||||||
|
|
||||||
<details>
|
Only needed for webhook mode:
|
||||||
<summary>Reverse Proxy (nginx)</summary>
|
|
||||||
|
|
||||||
```nginx
|
```nginx
|
||||||
server {
|
server {
|
||||||
|
|
@ -369,7 +425,7 @@ server {
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
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;
|
# limit_req_zone $binary_remote_addr zone=webhook:10m rate=10r/s;
|
||||||
# location /webhook {
|
# location /webhook {
|
||||||
# limit_req zone=webhook burst=20 nodelay;
|
# limit_req zone=webhook burst=20 nodelay;
|
||||||
|
|
@ -378,21 +434,23 @@ server {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## API Endpoints
|
## API Endpoints
|
||||||
|
|
||||||
|
<!--markdownlint-disable MD013-->
|
||||||
|
|
||||||
| Method | Path | Description |
|
| Method | Path | Description |
|
||||||
| -------- | ------------- | ---------------------------------------------------------------------------------------- |
|
| -------- | ------------- | ---------------------------------------------------------------------------------------- |
|
||||||
| `GET` | `/health` | Health check - returns `status`, `uptime` (seconds), `version`, `dryRun`, and `backends` |
|
| `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` | `/dashboard` | Web UI dashboard with status, events, and config editor |
|
||||||
| `GET` | `/api/status` | JSON status: uptime, version, dry-run, backends, repo count |
|
| `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 |
|
| `DELETE` | `/api/events` | Clear the event ring buffer |
|
||||||
| `GET` | `/api/config` | Current runtime configuration as JSON |
|
| `GET` | `/api/config` | Current runtime configuration as JSON |
|
||||||
| `PUT` | `/api/config` | Partial config update: deep-merges, validates, and applies in-place |
|
| `PUT` | `/api/config` | Partial config update: deep-merges, validates, and applies in-place |
|
||||||
|
|
||||||
|
<!--markdownlint-enable MD013-->
|
||||||
|
|
||||||
## Dashboard & Runtime API
|
## Dashboard & Runtime API
|
||||||
|
|
||||||
Troutbot ships with a built-in web dashboard and JSON API for monitoring and
|
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
|
- **Status card** - uptime, version, dry-run state, active backends, and repo
|
||||||
count. Auto-refreshes every 30 seconds.
|
count. Auto-refreshes every 30 seconds.
|
||||||
- **Event log** - table of recent webhook events showing repo, PR/issue number,
|
- **Event log** - table of recent events showing repo, PR/issue number, action,
|
||||||
action, impact rating, and confidence score. Keeps the last 100 events in
|
impact rating, and confidence score. Keeps the last 100 events in memory.
|
||||||
memory.
|
|
||||||
- **Config editor** - read-only JSON view of the current runtime config with an
|
- **Config editor** - read-only JSON view of the current runtime config with an
|
||||||
"Edit" toggle that lets you modify and save changes without restarting.
|
"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
|
### Event Buffer API
|
||||||
|
|
||||||
The event buffer stores the last 100 processed webhook events in memory. Events
|
The event buffer stores the last 100 processed events in memory (from both
|
||||||
are lost on restart.
|
webhooks and polling). Events are lost on restart.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# List recent events
|
# List recent events
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue