feat: add comprehensive CLI documentation and release workflow
- Add CLI reference documentation with command examples - Add CLI quick reference card for quick lookups - Add troubleshooting guide for common issues - Add GitHub Actions release workflow for binary builds - Add CHANGELOG.md for release tracking - Add webhook integration examples - Add setup and verification script - Update README with installation instructions and CLI overview Addresses ELF-169: Document CLI and add standalone binary releases Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
parent
57a9eb6835
commit
9ff4876b56
189
.github/workflows/release.yml
vendored
Normal file
189
.github/workflows/release.yml
vendored
Normal file
@ -0,0 +1,189 @@
|
||||
name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: 'Release tag (e.g., v1.0.0)'
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build ${{ matrix.os }}/${{ matrix.arch }}
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
arch: amd64
|
||||
goos: linux
|
||||
goarch: amd64
|
||||
- os: linux
|
||||
arch: arm64
|
||||
goos: linux
|
||||
goarch: arm64
|
||||
- os: darwin
|
||||
arch: amd64
|
||||
goos: darwin
|
||||
goarch: amd64
|
||||
- os: darwin
|
||||
arch: arm64
|
||||
goos: darwin
|
||||
goarch: arm64
|
||||
- os: windows
|
||||
arch: amd64
|
||||
goos: windows
|
||||
goarch: amd64
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.25'
|
||||
cache: true
|
||||
|
||||
- name: Determine version
|
||||
id: version
|
||||
run: |
|
||||
if [ "${{ github.ref_type }}" = "tag" ]; then
|
||||
echo "version=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "version=dev-$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Build binary
|
||||
env:
|
||||
GOOS: ${{ matrix.goos }}
|
||||
GOARCH: ${{ matrix.goarch }}
|
||||
CGO_ENABLED: 0
|
||||
run: |
|
||||
EXT=""
|
||||
if [ "${{ matrix.goos }}" = "windows" ]; then
|
||||
EXT=".exe"
|
||||
fi
|
||||
|
||||
BINARY_NAME="hatch-${{ matrix.os }}-${{ matrix.arch }}${EXT}"
|
||||
|
||||
go build \
|
||||
-ldflags="-s -w -X main.version=${{ steps.version.outputs.version }}" \
|
||||
-o "${BINARY_NAME}" \
|
||||
./cmd/hatch
|
||||
|
||||
echo "BINARY_NAME=${BINARY_NAME}" >> $GITHUB_ENV
|
||||
|
||||
- name: Generate checksum
|
||||
run: |
|
||||
sha256sum "${BINARY_NAME}" > "${BINARY_NAME}.sha256"
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.os }}-${{ matrix.arch }}
|
||||
path: |
|
||||
${{ env.BINARY_NAME }}
|
||||
${{ env.BINARY_NAME }}.sha256
|
||||
retention-days: 1
|
||||
|
||||
release:
|
||||
name: Create Release
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Determine version
|
||||
id: version
|
||||
run: |
|
||||
if [ "${{ github.ref_type }}" = "tag" ]; then
|
||||
echo "version=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "version=dev-$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Download all artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: artifacts
|
||||
merge-multiple: true
|
||||
|
||||
- name: List artifacts
|
||||
run: |
|
||||
ls -la artifacts/
|
||||
echo "---"
|
||||
for f in artifacts/*; do
|
||||
echo "$f: $(du -h "$f" | cut -f1)"
|
||||
done
|
||||
|
||||
- name: Create release notes
|
||||
id: notes
|
||||
run: |
|
||||
# Extract changelog for this version if exists
|
||||
VERSION="${{ steps.version.outputs.version }}"
|
||||
NOTES=""
|
||||
|
||||
if [ -f CHANGELOG.md ]; then
|
||||
# Extract notes for this version
|
||||
NOTES=$(awk "/^## ${VERSION}/,/^## [0-9]/" CHANGELOG.md | head -n -1)
|
||||
fi
|
||||
|
||||
if [ -z "$NOTES" ]; then
|
||||
NOTES="## Changes in ${VERSION}
|
||||
|
||||
- Standalone binary releases for Linux, macOS, and Windows
|
||||
- Updated CLI documentation
|
||||
- See [CLI Reference](https://github.com/elfoundation/hatch/blob/main/docs/engineering/cli.md) for usage"
|
||||
fi
|
||||
|
||||
echo "notes<<EOF" >> $GITHUB_OUTPUT
|
||||
echo "$NOTES" >> $GITHUB_OUTPUT
|
||||
echo "EOF" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Create GitHub Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
name: "Hatch ${{ steps.version.outputs.version }}"
|
||||
body: ${{ steps.notes.outputs.notes }}
|
||||
draft: false
|
||||
prerelease: ${{ contains(steps.version.outputs.version, '-') }}
|
||||
files: |
|
||||
artifacts/*
|
||||
fail_on_unmatched_files: false
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Generate SBOM
|
||||
run: |
|
||||
# Create a simple SBOM with version info
|
||||
cat > sbom.json << EOF
|
||||
{
|
||||
"name": "hatch",
|
||||
"version": "${{ steps.version.outputs.version }}",
|
||||
"buildDate": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
|
||||
"goVersion": "$(go version | awk '{print $3}')",
|
||||
"platforms": [
|
||||
"linux/amd64",
|
||||
"linux/arm64",
|
||||
"darwin/amd64",
|
||||
"darwin/arm64",
|
||||
"windows/amd64"
|
||||
]
|
||||
}
|
||||
EOF
|
||||
|
||||
# Upload SBOM as release asset
|
||||
gh release upload "${{ steps.version.outputs.version }}" sbom.json --clobber || true
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
120
CHANGELOG.md
Normal file
120
CHANGELOG.md
Normal file
@ -0,0 +1,120 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to Hatch will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
- CLI documentation with comprehensive command reference
|
||||
- GitHub Actions release workflow for binary builds
|
||||
- Standalone binaries for Linux, macOS, and Windows
|
||||
- SHA256 checksums for all binaries
|
||||
- SBOM generation for releases
|
||||
|
||||
### Changed
|
||||
- Updated README with CLI installation instructions
|
||||
|
||||
### Fixed
|
||||
- N/A
|
||||
|
||||
## [0.1.0] - 2024-01-15
|
||||
|
||||
### Added
|
||||
- Initial release of Hatch
|
||||
- HTTP request capture and storage
|
||||
- Request inspection and search
|
||||
- Request replay functionality
|
||||
- Mock response configuration
|
||||
- OpenAPI documentation generation
|
||||
- Web UI for visual inspection
|
||||
- Docker support with Caddy reverse proxy
|
||||
- SQLite storage backend
|
||||
- REST API v1
|
||||
|
||||
### Changed
|
||||
- N/A
|
||||
|
||||
### Fixed
|
||||
- N/A
|
||||
|
||||
## [0.0.1] - 2024-01-01
|
||||
|
||||
### Added
|
||||
- Project scaffolding
|
||||
- Basic architecture design
|
||||
- Development environment setup
|
||||
|
||||
### Changed
|
||||
- N/A
|
||||
|
||||
### Fixed
|
||||
- N/A
|
||||
|
||||
---
|
||||
|
||||
## Release Process
|
||||
|
||||
### Creating a Release
|
||||
|
||||
1. **Update CHANGELOG.md** with the new version and changes
|
||||
2. **Create a git tag** for the version:
|
||||
```bash
|
||||
git tag -a v1.0.0 -m "Release v1.0.0"
|
||||
git push origin v1.0.0
|
||||
```
|
||||
3. **GitHub Actions will automatically**:
|
||||
- Build binaries for all platforms
|
||||
- Create SHA256 checksums
|
||||
- Generate SBOM
|
||||
- Create GitHub Release with assets
|
||||
|
||||
### Manual Release
|
||||
|
||||
For manual releases or testing:
|
||||
|
||||
```bash
|
||||
# Trigger workflow manually
|
||||
gh workflow run release.yml -f tag=v1.0.0
|
||||
|
||||
# Or create tag and push
|
||||
git tag -a v1.0.0 -m "Release v1.0.0"
|
||||
git push origin v1.0.0
|
||||
```
|
||||
|
||||
### Platform Support
|
||||
|
||||
| Platform | Architecture | Binary Name |
|
||||
|----------|--------------|-------------|
|
||||
| Linux | x86_64 | `hatch-linux-amd64` |
|
||||
| Linux | ARM64 | `hatch-linux-arm64` |
|
||||
| macOS | Intel | `hatch-darwin-amd64` |
|
||||
| macOS | Apple Silicon | `hatch-darwin-arm64` |
|
||||
| Windows | x86_64 | `hatch-windows-amd64.exe` |
|
||||
|
||||
### Binary Installation
|
||||
|
||||
After downloading:
|
||||
|
||||
```bash
|
||||
# Linux/macOS
|
||||
chmod +x hatch-*
|
||||
sudo mv hatch-* /usr/local/bin/hatch
|
||||
|
||||
# Windows (PowerShell)
|
||||
Rename-Item hatch-windows-amd64.exe hatch.exe
|
||||
```
|
||||
|
||||
### Verification
|
||||
|
||||
Verify binary integrity using SHA256 checksums:
|
||||
|
||||
```bash
|
||||
# Linux/macOS
|
||||
sha256sum -c hatch-linux-amd64.sha256
|
||||
|
||||
# Windows (PowerShell)
|
||||
Get-FileHash hatch-windows-amd64.exe -Algorithm SHA256
|
||||
```
|
||||
62
README.md
62
README.md
@ -14,6 +14,41 @@ El Foundation builds institutions that outlast their founders. We create technol
|
||||
4. Read [docs/engineering/local-dev.md](docs/engineering/local-dev.md) for the day-to-day workflow.
|
||||
5. Read [docs/engineering/hatch-architecture.md](docs/engineering/hatch-architecture.md) for the component map.
|
||||
|
||||
## Installation
|
||||
|
||||
### Pre-built Binaries (Recommended)
|
||||
|
||||
Download the latest binary for your platform from the [Releases page](https://github.com/elfoundation/hatch/releases):
|
||||
|
||||
- **Linux (x64)**: `hatch-linux-amd64`
|
||||
- **Linux (ARM64)**: `hatch-linux-arm64`
|
||||
- **macOS (Intel)**: `hatch-darwin-amd64`
|
||||
- **macOS (Apple Silicon)**: `hatch-darwin-arm64`
|
||||
- **Windows (x64)**: `hatch-windows-amd64.exe`
|
||||
|
||||
After downloading:
|
||||
|
||||
```bash
|
||||
# Linux/macOS
|
||||
chmod +x hatch-*
|
||||
sudo mv hatch-* /usr/local/bin/hatch
|
||||
|
||||
# Windows (PowerShell)
|
||||
Rename-Item hatch-windows-amd64.exe hatch.exe
|
||||
# Move to a directory in your PATH
|
||||
```
|
||||
|
||||
### Build from Source
|
||||
|
||||
Requires Go 1.25 or later:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/elfoundation/hatch.git
|
||||
cd hatch
|
||||
CGO_ENABLED=0 go build -o hatch ./cmd/hatch
|
||||
sudo mv hatch /usr/local/bin/
|
||||
```
|
||||
|
||||
## Repository Layout
|
||||
|
||||
```
|
||||
@ -23,6 +58,7 @@ El Foundation builds institutions that outlast their founders. We create technol
|
||||
│ ├── company/ # Founding documents (charter, org, etc.)
|
||||
│ ├── engineering/ # Engineering standards, architecture, local dev
|
||||
│ └── adrs/ # Architecture Decision Records
|
||||
├── examples/ # Usage examples and integration guides
|
||||
├── internal/ # Go packages (handler, store, ...)
|
||||
├── Dockerfile # Multi-stage static binary build (golang → scratch)
|
||||
├── docker-compose.yml # Local stack with optional Caddy sidecar
|
||||
@ -76,6 +112,32 @@ Internet → :443 (Caddy) → hatch:8080 (Go binary, internal network)
|
||||
|
||||
Caddy terminates TLS and reverse-proxies to the Hatch Go binary. The Hatch container only listens on `127.0.0.1:8080` — it's never directly exposed to the internet.
|
||||
|
||||
## CLI Reference
|
||||
|
||||
Hatch includes a powerful CLI for interacting with the server from the command line:
|
||||
|
||||
```bash
|
||||
# Capture requests
|
||||
hatch capture https://api.example.com/webhook
|
||||
|
||||
# Inspect captured traffic
|
||||
hatch inspect my-webhook
|
||||
|
||||
# Search for specific requests
|
||||
hatch search my-webhook -query 'status:500'
|
||||
|
||||
# Replay requests to other services
|
||||
hatch replay <request-id> -endpoint my-webhook -target https://httpbin.org/post
|
||||
|
||||
# Configure mock responses
|
||||
hatch mock set my-webhook -status 200 -body '{"ok":true}'
|
||||
|
||||
# Generate OpenAPI documentation
|
||||
hatch doc generate my-webhook > openapi.json
|
||||
```
|
||||
|
||||
For detailed CLI documentation, see [docs/engineering/cli.md](docs/engineering/cli.md).
|
||||
|
||||
## Technology Stack
|
||||
|
||||
See [docs/engineering/tech-stack.md](docs/engineering/tech-stack.md) for current choices and rationale, and [docs/adrs/](docs/adrs/) for the decision records that produced them.
|
||||
|
||||
118
docs/engineering/cli-quick-reference.md
Normal file
118
docs/engineering/cli-quick-reference.md
Normal file
@ -0,0 +1,118 @@
|
||||
# Hatch CLI Quick Reference
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
# Download binary (Linux example)
|
||||
curl -L https://github.com/elfoundation/hatch/releases/latest/download/hatch-linux-amd64 -o hatch
|
||||
chmod +x hatch
|
||||
sudo mv hatch /usr/local/bin/
|
||||
```
|
||||
|
||||
## Commands
|
||||
|
||||
| Command | Description | Example |
|
||||
|---------|-------------|---------|
|
||||
| `hatch serve` | Start server | `hatch serve` |
|
||||
| `hatch capture <url>` | Capture request | `hatch capture /api/webhook` |
|
||||
| `hatch inspect <endpoint>` | View requests | `hatch inspect my-webhook` |
|
||||
| `hatch search <endpoint>` | Search traffic | `hatch search my-webhook -query 'status:500'` |
|
||||
| `hatch replay <id>` | Replay request | `hatch replay abc123 -endpoint api -target http://localhost:3000` |
|
||||
| `hatch mock set <endpoint>` | Configure mock | `hatch mock set api -status 200 -body '{}'` |
|
||||
| `hatch doc generate <endpoint>` | Generate OpenAPI | `hatch doc generate api > openapi.json` |
|
||||
| `hatch version` | Print version | `hatch version` |
|
||||
|
||||
## Common Flags
|
||||
|
||||
| Flag | Description | Example |
|
||||
|------|-------------|---------|
|
||||
| `-method METHOD` | HTTP method | `hatch capture /api -method PUT` |
|
||||
| `-body BODY` | Request body | `hatch capture /api -body '{"key":"value"}'` |
|
||||
| `-header KEY:VALUE` | Add header | `hatch capture /api -header 'Auth:token'` |
|
||||
| `-limit N` | Limit results | `hatch inspect api -limit 10` |
|
||||
| `-query QUERY` | Search query | `hatch search api -query 'status:500'` |
|
||||
| `-endpoint ENDPOINT` | Source endpoint | `hatch replay abc -endpoint api` |
|
||||
| `-target URL` | Target URL | `hatch replay abc -target http://localhost:3000` |
|
||||
| `-status CODE` | HTTP status | `hatch mock set api -status 200` |
|
||||
|
||||
## Environment Variables
|
||||
|
||||
| Variable | Description | Default |
|
||||
|----------|-------------|---------|
|
||||
| `HATCH_URL` | Server URL | `http://localhost:8080` |
|
||||
| `PORT` | Server port | `8080` |
|
||||
|
||||
## Quick Examples
|
||||
|
||||
### Capture a Webhook
|
||||
|
||||
```bash
|
||||
hatch capture /webhooks/stripe \
|
||||
-method POST \
|
||||
-header 'Stripe-Signature:whsec_test' \
|
||||
-body '{"type":"payment_intent.succeeded"}'
|
||||
```
|
||||
|
||||
### Debug Failed Requests
|
||||
|
||||
```bash
|
||||
# Find 500 errors
|
||||
hatch search api -query 'status:500'
|
||||
|
||||
# Get details
|
||||
hatch inspect api -limit 5
|
||||
|
||||
# Replay to debug
|
||||
hatch replay <id> -endpoint api -target http://localhost:8080/debug
|
||||
```
|
||||
|
||||
### Mock API for Frontend
|
||||
|
||||
```bash
|
||||
hatch mock set api/users \
|
||||
-status 200 \
|
||||
-header 'Content-Type:application/json' \
|
||||
-body '[{"id":1,"name":"John"}]'
|
||||
```
|
||||
|
||||
### Generate API Docs
|
||||
|
||||
```bash
|
||||
hatch doc generate api/users > users-api.json
|
||||
hatch doc generate api/posts > posts-api.json
|
||||
```
|
||||
|
||||
## Query Syntax
|
||||
|
||||
| Query | Description |
|
||||
|-------|-------------|
|
||||
| `status:500` | Filter by status code |
|
||||
| `POST` | Filter by HTTP method |
|
||||
| `user.created` | Search in body |
|
||||
| `Content-Type:application/json` | Filter by header |
|
||||
|
||||
## Exit Codes
|
||||
|
||||
| Code | Meaning |
|
||||
|------|---------|
|
||||
| 0 | Success |
|
||||
| 1 | General error |
|
||||
| 2 | Invalid arguments |
|
||||
| 3 | Network error |
|
||||
| 4 | Auth error |
|
||||
| 5 | Not found |
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
```bash
|
||||
# Check server health
|
||||
curl http://localhost:8080/healthz
|
||||
|
||||
# Verify binary works
|
||||
hatch version
|
||||
|
||||
# Test connection
|
||||
hatch inspect default -limit 1
|
||||
```
|
||||
|
||||
For detailed troubleshooting, see [cli-troubleshooting.md](cli-troubleshooting.md).
|
||||
670
docs/engineering/cli-troubleshooting.md
Normal file
670
docs/engineering/cli-troubleshooting.md
Normal file
@ -0,0 +1,670 @@
|
||||
# CLI Troubleshooting Guide
|
||||
|
||||
Comprehensive troubleshooting guide for Hatch CLI issues.
|
||||
|
||||
## Quick Diagnostics
|
||||
|
||||
### Health Check
|
||||
|
||||
First, verify the Hatch server is running and accessible:
|
||||
|
||||
```bash
|
||||
# Check if server is responding
|
||||
curl -s http://localhost:8080/healthz
|
||||
|
||||
# Expected output: ok
|
||||
|
||||
# If using custom URL
|
||||
curl -s $HATCH_URL/healthz
|
||||
```
|
||||
|
||||
### Version Check
|
||||
|
||||
Verify you're using the correct version:
|
||||
|
||||
```bash
|
||||
hatch version
|
||||
# Expected output: hatch v0.1.0
|
||||
|
||||
# Check if binary is working
|
||||
hatch --help
|
||||
```
|
||||
|
||||
### Connectivity Test
|
||||
|
||||
Test network connectivity to the server:
|
||||
|
||||
```bash
|
||||
# Test with verbose output
|
||||
curl -v http://localhost:8080/healthz
|
||||
|
||||
# Test with specific timeout
|
||||
curl --connect-timeout 5 http://localhost:8080/healthz
|
||||
```
|
||||
|
||||
## Common Error Messages
|
||||
|
||||
### Connection Issues
|
||||
|
||||
#### `Error: request failed: connection refused`
|
||||
|
||||
**Cause:** The Hatch server is not running or not accessible.
|
||||
|
||||
**Solutions:**
|
||||
|
||||
1. Start the Hatch server:
|
||||
```bash
|
||||
hatch serve
|
||||
```
|
||||
|
||||
2. Check if the server is listening on the expected port:
|
||||
```bash
|
||||
# Linux/macOS
|
||||
netstat -tlnp | grep 8080
|
||||
# or
|
||||
lsof -i :8080
|
||||
|
||||
# Windows
|
||||
netstat -ano | findstr :8080
|
||||
```
|
||||
|
||||
3. Verify the HATCH_URL environment variable:
|
||||
```bash
|
||||
echo $HATCH_URL
|
||||
# Should be http://localhost:8080 or your server URL
|
||||
```
|
||||
|
||||
4. Check firewall settings:
|
||||
```bash
|
||||
# Linux
|
||||
sudo iptables -L -n | grep 8080
|
||||
|
||||
# macOS
|
||||
sudo pfctl -sr | grep 8080
|
||||
```
|
||||
|
||||
#### `Error: request failed: dial tcp: lookup localhost: no such host`
|
||||
|
||||
**Cause:** DNS resolution failure.
|
||||
|
||||
**Solutions:**
|
||||
|
||||
1. Use IP address instead of hostname:
|
||||
```bash
|
||||
export HATCH_URL=http://127.0.0.1:8080
|
||||
```
|
||||
|
||||
2. Check `/etc/hosts` file:
|
||||
```bash
|
||||
grep localhost /etc/hosts
|
||||
# Should contain: 127.0.0.1 localhost
|
||||
```
|
||||
|
||||
#### `Error: request failed: context deadline exceeded`
|
||||
|
||||
**Cause:** Request timeout.
|
||||
|
||||
**Solutions:**
|
||||
|
||||
1. Check server load:
|
||||
```bash
|
||||
top -bn1 | grep hatch
|
||||
```
|
||||
|
||||
2. Increase timeout (if using curl):
|
||||
```bash
|
||||
curl --max-time 30 http://localhost:8080/healthz
|
||||
```
|
||||
|
||||
3. Check network latency:
|
||||
```bash
|
||||
ping localhost
|
||||
```
|
||||
|
||||
### Authentication Errors
|
||||
|
||||
#### `Error (HTTP 401): unauthorized`
|
||||
|
||||
**Cause:** Authentication required but not provided.
|
||||
|
||||
**Solutions:**
|
||||
|
||||
1. Check if authentication is enabled:
|
||||
```bash
|
||||
# Check server configuration
|
||||
docker exec hatch-container env | grep AUTH
|
||||
```
|
||||
|
||||
2. Provide authentication token:
|
||||
```bash
|
||||
# For API requests
|
||||
curl -H "Authorization: Bearer $HATCH_AUTH_TOKEN" http://localhost:8080/v1/endpoints
|
||||
```
|
||||
|
||||
3. For development, disable authentication:
|
||||
```bash
|
||||
# Start server without auth
|
||||
HATCH_AUTH_ENABLED=false hatch serve
|
||||
```
|
||||
|
||||
#### `Error (HTTP 403): forbidden`
|
||||
|
||||
**Cause:** Insufficient permissions.
|
||||
|
||||
**Solutions:**
|
||||
|
||||
1. Check user roles and permissions
|
||||
2. Verify API token has required scopes
|
||||
3. Contact administrator for access
|
||||
|
||||
### Request/Response Errors
|
||||
|
||||
#### `Error (HTTP 400): bad request`
|
||||
|
||||
**Cause:** Invalid request format.
|
||||
|
||||
**Solutions:**
|
||||
|
||||
1. Validate JSON format:
|
||||
```bash
|
||||
echo '{"invalid":json}' | jq .
|
||||
# Should show parse error
|
||||
```
|
||||
|
||||
2. Check Content-Type header:
|
||||
```bash
|
||||
curl -H "Content-Type: application/json" -d '{"valid":"json"}' ...
|
||||
```
|
||||
|
||||
3. Verify request body size:
|
||||
```bash
|
||||
# Check body size
|
||||
echo -n '{"data":"..."}' | wc -c
|
||||
```
|
||||
|
||||
#### `Error (HTTP 404): endpoint not found`
|
||||
|
||||
**Cause:** Requested resource doesn't exist.
|
||||
|
||||
**Solutions:**
|
||||
|
||||
1. List available endpoints:
|
||||
```bash
|
||||
curl http://localhost:8080/v1/endpoints
|
||||
```
|
||||
|
||||
2. Check endpoint ID spelling:
|
||||
```bash
|
||||
# Case-sensitive
|
||||
hatch inspect MyEndpoint # Wrong
|
||||
hatch inspect myendpoint # Correct
|
||||
```
|
||||
|
||||
3. Verify endpoint has captured requests:
|
||||
```bash
|
||||
hatch inspect myendpoint -limit 1
|
||||
```
|
||||
|
||||
#### `Error (HTTP 413): payload too large`
|
||||
|
||||
**Cause:** Request body exceeds size limit.
|
||||
|
||||
**Solutions:**
|
||||
|
||||
1. Reduce request body size
|
||||
2. Compress data before sending
|
||||
3. Split into smaller chunks
|
||||
|
||||
#### `Error (HTTP 429): too many requests`
|
||||
|
||||
**Cause:** Rate limiting.
|
||||
|
||||
**Solutions:**
|
||||
|
||||
1. Implement backoff:
|
||||
```bash
|
||||
# Exponential backoff script
|
||||
for i in {1..5}; do
|
||||
sleep $((2**i))
|
||||
hatch capture /api -body '{"retry":'$i'}' && break
|
||||
done
|
||||
```
|
||||
|
||||
2. Check rate limit headers:
|
||||
```bash
|
||||
curl -I http://localhost:8080/v1/endpoints
|
||||
# Look for X-RateLimit-* headers
|
||||
```
|
||||
|
||||
### Data Errors
|
||||
|
||||
#### `Error: invalid character '}' looking for beginning of value`
|
||||
|
||||
**Cause:** Malformed JSON in request body.
|
||||
|
||||
**Solutions:**
|
||||
|
||||
1. Validate JSON:
|
||||
```bash
|
||||
echo '{"key":"value"}' | jq .
|
||||
```
|
||||
|
||||
2. Use proper escaping:
|
||||
```bash
|
||||
# Bash
|
||||
hatch capture /api -body '{"key":"value with \"quotes\""}'
|
||||
|
||||
# Use file input
|
||||
echo '{"key":"value"}' > request.json
|
||||
hatch capture /api -body @request.json
|
||||
```
|
||||
|
||||
3. Check for invisible characters:
|
||||
```bash
|
||||
cat -A request.json
|
||||
```
|
||||
|
||||
#### `Error: unexpected end of JSON input`
|
||||
|
||||
**Cause:** Incomplete JSON response.
|
||||
|
||||
**Solutions:**
|
||||
|
||||
1. Check server logs for errors
|
||||
2. Verify network connection wasn't interrupted
|
||||
3. Try with smaller payload
|
||||
|
||||
### Storage Errors
|
||||
|
||||
#### `Error: database is locked`
|
||||
|
||||
**Cause:** SQLite database contention.
|
||||
|
||||
**Solutions:**
|
||||
|
||||
1. Reduce concurrent operations
|
||||
2. Check for long-running transactions:
|
||||
```bash
|
||||
# Monitor database locks
|
||||
sqlite3 hatch.db "PRAGMA journal_mode=WAL;"
|
||||
```
|
||||
|
||||
3. Consider using PostgreSQL for production
|
||||
|
||||
#### `Error: no space left on device`
|
||||
|
||||
**Cause:** Disk space exhausted.
|
||||
|
||||
**Solutions:**
|
||||
|
||||
1. Check disk space:
|
||||
```bash
|
||||
df -h
|
||||
du -sh /var/lib/hatch
|
||||
```
|
||||
|
||||
2. Clean old data:
|
||||
```bash
|
||||
# Remove requests older than 7 days
|
||||
curl -X DELETE "http://localhost:8080/v1/endpoints/myendpoint/requests?older_than=7d"
|
||||
```
|
||||
|
||||
3. Configure data retention:
|
||||
```bash
|
||||
# Set retention policy
|
||||
HATCH_RETENTION_DAYS=30 hatch serve
|
||||
```
|
||||
|
||||
## Platform-Specific Issues
|
||||
|
||||
### Linux
|
||||
|
||||
#### Permission Denied
|
||||
|
||||
```bash
|
||||
# Fix binary permissions
|
||||
chmod +x /usr/local/bin/hatch
|
||||
|
||||
# Or install to user directory
|
||||
mkdir -p ~/.local/bin
|
||||
mv hatch ~/.local/bin/
|
||||
export PATH="$HOME/.local/bin:$PATH"
|
||||
```
|
||||
|
||||
#### SELinux Issues
|
||||
|
||||
```bash
|
||||
# Check SELinux status
|
||||
getenforce
|
||||
|
||||
# If enabled, add context
|
||||
sudo semanage fcontext -a -t bin_t /usr/local/bin/hatch
|
||||
sudo restorecon -v /usr/local/bin/hatch
|
||||
```
|
||||
|
||||
### macOS
|
||||
|
||||
#### Gatekeeper Blocked
|
||||
|
||||
```bash
|
||||
# Remove quarantine attribute
|
||||
xattr -d com.apple.quarantine /usr/local/bin/hatch
|
||||
|
||||
# Or allow in System Preferences > Security & Privacy
|
||||
```
|
||||
|
||||
#### Homebrew Path Issues
|
||||
|
||||
```bash
|
||||
# Ensure Homebrew bin is in PATH
|
||||
export PATH="/usr/local/bin:$PATH"
|
||||
|
||||
# Or create symlink
|
||||
ln -s /usr/local/bin/hatch /opt/homebrew/bin/hatch
|
||||
```
|
||||
|
||||
### Windows
|
||||
|
||||
#### Windows Defender Blocked
|
||||
|
||||
1. Open Windows Security
|
||||
2. Go to Virus & threat protection
|
||||
3. Allow app through firewall
|
||||
|
||||
#### PowerShell Execution Policy
|
||||
|
||||
```bash
|
||||
# Run as Administrator
|
||||
Set-ExecutionPolicy RemoteSigned
|
||||
|
||||
# Or bypass for current session
|
||||
powershell -ExecutionPolicy Bypass -File script.ps1
|
||||
```
|
||||
|
||||
#### PATH Not Updated
|
||||
|
||||
```bash
|
||||
# Add to PATH permanently
|
||||
$env:PATH += ";C:\path\to\hatch"
|
||||
|
||||
# Or use System Properties > Environment Variables
|
||||
```
|
||||
|
||||
## Performance Issues
|
||||
|
||||
### Slow Response Times
|
||||
|
||||
#### Diagnose
|
||||
|
||||
```bash
|
||||
# Measure response time
|
||||
time curl -s http://localhost:8080/v1/endpoints > /dev/null
|
||||
|
||||
# Check server resources
|
||||
top -bn1 | grep hatch
|
||||
|
||||
# Monitor network
|
||||
iftop -i eth0
|
||||
```
|
||||
|
||||
#### Solutions
|
||||
|
||||
1. **Increase server resources:**
|
||||
```bash
|
||||
# Docker
|
||||
docker update --cpus="2.0" --memory="2g" hatch-container
|
||||
```
|
||||
|
||||
2. **Optimize database:**
|
||||
```bash
|
||||
# Vacuum SQLite database
|
||||
sqlite3 hatch.db "VACUUM;"
|
||||
```
|
||||
|
||||
3. **Enable caching:**
|
||||
```bash
|
||||
HATCH_CACHE_TTL=300 hatch serve
|
||||
```
|
||||
|
||||
### High Memory Usage
|
||||
|
||||
#### Diagnose
|
||||
|
||||
```bash
|
||||
# Check memory usage
|
||||
ps aux | grep hatch
|
||||
pmap -x $(pgrep hatch) | tail -1
|
||||
|
||||
# Monitor over time
|
||||
while true; do
|
||||
echo "$(date): $(ps -o rss= -p $(pgrep hatch))KB"
|
||||
sleep 60
|
||||
done
|
||||
```
|
||||
|
||||
#### Solutions
|
||||
|
||||
1. **Limit request history:**
|
||||
```bash
|
||||
HATCH_MAX_REQUESTS=10000 hatch serve
|
||||
```
|
||||
|
||||
2. **Enable pagination:**
|
||||
```bash
|
||||
hatch inspect myendpoint -limit 100
|
||||
```
|
||||
|
||||
3. **Restart periodically:**
|
||||
```bash
|
||||
# Cron job
|
||||
0 0 * * * systemctl restart hatch
|
||||
```
|
||||
|
||||
### High CPU Usage
|
||||
|
||||
#### Diagnose
|
||||
|
||||
```bash
|
||||
# Check CPU usage
|
||||
top -bn1 | grep hatch
|
||||
|
||||
# Profile if needed
|
||||
go tool pprof http://localhost:6060/debug/pprof/profile
|
||||
```
|
||||
|
||||
#### Solutions
|
||||
|
||||
1. **Reduce logging:**
|
||||
```bash
|
||||
HATCH_LOG_LEVEL=warn hatch serve
|
||||
```
|
||||
|
||||
2. **Limit concurrent connections:**
|
||||
```bash
|
||||
HATCH_MAX_CONNECTIONS=100 hatch serve
|
||||
```
|
||||
|
||||
## Network Issues
|
||||
|
||||
### Proxy Configuration
|
||||
|
||||
```bash
|
||||
# Set proxy environment variables
|
||||
export HTTP_PROXY=http://proxy.example.com:8080
|
||||
export HTTPS_PROXY=http://proxy.example.com:8080
|
||||
export NO_PROXY=localhost,127.0.0.1
|
||||
|
||||
# Or configure in hatch
|
||||
HATCH_PROXY=$HTTP_PROXY hatch serve
|
||||
```
|
||||
|
||||
### SSL/TLS Issues
|
||||
|
||||
```bash
|
||||
# Skip SSL verification (development only)
|
||||
curl -k https://hatch.example.com/healthz
|
||||
|
||||
# Or add certificate
|
||||
curl --cacert /path/to/ca.crt https://hatch.example.com/healthz
|
||||
|
||||
# For self-signed certificates
|
||||
export CURL_CA_BUNDLE=/path/to/cert.pem
|
||||
```
|
||||
|
||||
### DNS Resolution
|
||||
|
||||
```bash
|
||||
# Test DNS resolution
|
||||
nslookup localhost
|
||||
dig localhost
|
||||
|
||||
# Use IP address
|
||||
export HATCH_URL=http://127.0.0.1:8080
|
||||
```
|
||||
|
||||
## Docker Issues
|
||||
|
||||
### Container Won't Start
|
||||
|
||||
```bash
|
||||
# Check container logs
|
||||
docker logs hatch-container
|
||||
|
||||
# Check container status
|
||||
docker ps -a | grep hatch
|
||||
|
||||
# Inspect container
|
||||
docker inspect hatch-container
|
||||
```
|
||||
|
||||
### Port Conflicts
|
||||
|
||||
```bash
|
||||
# Find what's using port 8080
|
||||
lsof -i :8080
|
||||
netstat -tlnp | grep 8080
|
||||
|
||||
# Use different port
|
||||
docker run -p 9090:8080 hatch:latest
|
||||
```
|
||||
|
||||
### Volume Mount Issues
|
||||
|
||||
```bash
|
||||
# Check volume permissions
|
||||
ls -la /path/to/volume
|
||||
|
||||
# Fix permissions
|
||||
sudo chown -R 1000:1000 /path/to/volume
|
||||
|
||||
# Test mount
|
||||
docker run -v /path/to/volume:/data busybox ls -la /data
|
||||
```
|
||||
|
||||
## Debugging Techniques
|
||||
|
||||
### Enable Debug Logging
|
||||
|
||||
```bash
|
||||
# Set debug level
|
||||
DEBUG=true hatch serve
|
||||
|
||||
# Or use environment variable
|
||||
HATCH_LOG_LEVEL=debug hatch serve
|
||||
```
|
||||
|
||||
### Verbose Output
|
||||
|
||||
```bash
|
||||
# Use curl verbose mode
|
||||
curl -v http://localhost:8080/v1/endpoints
|
||||
|
||||
# Capture full request/response
|
||||
curl -v -w '\n' http://localhost:8080/v1/endpoints > debug.txt 2>&1
|
||||
```
|
||||
|
||||
### Network Tracing
|
||||
|
||||
```bash
|
||||
# Linux
|
||||
strace -e trace=network hatch serve
|
||||
|
||||
# macOS
|
||||
dtruss -n hatch
|
||||
|
||||
# Windows
|
||||
netsh trace start capture=yes tracefile=trace.etl
|
||||
```
|
||||
|
||||
### Core Dumps
|
||||
|
||||
```bash
|
||||
# Enable core dumps
|
||||
ulimit -c unlimited
|
||||
|
||||
# Run with core dump
|
||||
hatch serve &
|
||||
echo $! > /tmp/hatch.pid
|
||||
|
||||
# If crash occurs, analyze
|
||||
gdb /usr/local/bin/hatch core
|
||||
```
|
||||
|
||||
## Getting Help
|
||||
|
||||
### Documentation
|
||||
|
||||
- [CLI Reference](cli.md) - Command documentation
|
||||
- [Examples](../../examples/) - Usage examples
|
||||
- [Architecture](hatch-architecture.md) - System design
|
||||
|
||||
### Community
|
||||
|
||||
- [GitHub Issues](https://github.com/elfoundation/hatch/issues) - Bug reports
|
||||
- [Discussions](https://github.com/elfoundation/hatch/discussions) - Questions
|
||||
|
||||
### Logs
|
||||
|
||||
```bash
|
||||
# Check application logs
|
||||
docker logs -f hatch-container
|
||||
|
||||
# Check system logs
|
||||
journalctl -u hatch -f
|
||||
|
||||
# Check access logs
|
||||
tail -f /var/log/hatch/access.log
|
||||
```
|
||||
|
||||
## Reporting Issues
|
||||
|
||||
When reporting issues, include:
|
||||
|
||||
1. **Environment details:**
|
||||
```bash
|
||||
hatch version
|
||||
go version
|
||||
uname -a # Linux/macOS
|
||||
systeminfo # Windows
|
||||
```
|
||||
|
||||
2. **Configuration:**
|
||||
```bash
|
||||
env | grep HATCH
|
||||
```
|
||||
|
||||
3. **Reproduction steps:**
|
||||
- Exact commands run
|
||||
- Expected behavior
|
||||
- Actual behavior
|
||||
|
||||
4. **Logs:**
|
||||
```bash
|
||||
# Attach relevant logs
|
||||
docker logs hatch-container > hatch.log 2>&1
|
||||
```
|
||||
|
||||
5. **Network info:**
|
||||
```bash
|
||||
curl -v http://localhost:8080/healthz > network-debug.txt 2>&1
|
||||
```
|
||||
429
docs/engineering/cli.md
Normal file
429
docs/engineering/cli.md
Normal file
@ -0,0 +1,429 @@
|
||||
# Hatch CLI Reference
|
||||
|
||||
The `hatch` CLI provides a powerful interface for interacting with Hatch servers. Use it to capture requests, inspect traffic, search logs, replay requests, configure mocks, and generate API documentation.
|
||||
|
||||
## Installation
|
||||
|
||||
### Pre-built Binaries (Recommended)
|
||||
|
||||
Download the latest binary for your platform from the [Releases page](https://github.com/elfoundation/hatch/releases):
|
||||
|
||||
- **Linux (x64)**: `hatch-linux-amd64`
|
||||
- **Linux (ARM64)**: `hatch-linux-arm64`
|
||||
- **macOS (Intel)**: `hatch-darwin-amd64`
|
||||
- **macOS (Apple Silicon)**: `hatch-darwin-arm64`
|
||||
- **Windows (x64)**: `hatch-windows-amd64.exe`
|
||||
|
||||
After downloading:
|
||||
|
||||
```bash
|
||||
# Linux/macOS
|
||||
chmod +x hatch-*
|
||||
sudo mv hatch-* /usr/local/bin/hatch
|
||||
|
||||
# Windows (PowerShell)
|
||||
Rename-Item hatch-windows-amd64.exe hatch.exe
|
||||
# Move to a directory in your PATH
|
||||
```
|
||||
|
||||
### Build from Source
|
||||
|
||||
Requires Go 1.25 or later:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/elfoundation/hatch.git
|
||||
cd hatch
|
||||
CGO_ENABLED=0 go build -o hatch ./cmd/hatch
|
||||
sudo mv hatch /usr/local/bin/
|
||||
```
|
||||
|
||||
### Docker
|
||||
|
||||
```bash
|
||||
docker pull ghcr.io/elfoundation/hatch:latest
|
||||
docker run --rm -it ghcr.io/elfoundation/hatch:latest --help
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### Environment Variables
|
||||
|
||||
| Variable | Description | Default |
|
||||
|----------|-------------|---------|
|
||||
| `HATCH_URL` | Hatch server URL | `http://localhost:8080` |
|
||||
|
||||
### Global Options
|
||||
|
||||
All commands support these flags:
|
||||
|
||||
- `-h, --help`: Show help for the command
|
||||
- `version`: Print version information
|
||||
|
||||
## Commands
|
||||
|
||||
### `hatch serve`
|
||||
|
||||
Start the Hatch server. This is the default command when no subcommand is specified.
|
||||
|
||||
```bash
|
||||
# Start server on default port (8080)
|
||||
hatch serve
|
||||
|
||||
# Start with custom port (use environment variable)
|
||||
PORT=9090 hatch serve
|
||||
```
|
||||
|
||||
### `hatch capture <url>`
|
||||
|
||||
Send a request to an endpoint and store it in Hatch.
|
||||
|
||||
**Options:**
|
||||
|
||||
- `-method METHOD`: HTTP method (default: `POST`)
|
||||
- `-body BODY`: Request body as JSON string
|
||||
- `-header KEY:VALUE`: Request header (repeatable)
|
||||
|
||||
**Examples:**
|
||||
|
||||
```bash
|
||||
# Capture a simple POST request
|
||||
hatch capture https://api.example.com/webhook
|
||||
|
||||
# Capture with custom method and body
|
||||
hatch capture /my-endpoint -method PUT -body '{"status":"active"}'
|
||||
|
||||
# Capture with headers
|
||||
hatch capture /api/events \
|
||||
-header 'Content-Type:application/json' \
|
||||
-header 'X-Webhook-Secret:abc123' \
|
||||
-body '{"event":"user.created","data":{"id":123}}'
|
||||
```
|
||||
|
||||
**URL Handling:**
|
||||
|
||||
- Full URLs: `https://api.example.com/webhook` → endpoint ID derived from path
|
||||
- Relative paths: `/my-endpoint` → used directly as endpoint ID
|
||||
- Empty/`/` → defaults to `default` endpoint
|
||||
|
||||
### `hatch inspect <endpoint>`
|
||||
|
||||
Fetch captured requests as JSON.
|
||||
|
||||
**Options:**
|
||||
|
||||
- `-limit N`: Maximum number of requests to return (default: 100)
|
||||
|
||||
**Examples:**
|
||||
|
||||
```bash
|
||||
# Inspect all requests for an endpoint
|
||||
hatch inspect my-webhook
|
||||
|
||||
# Limit to 10 most recent requests
|
||||
hatch inspect my-webhook -limit 10
|
||||
|
||||
# Pretty-print JSON output
|
||||
hatch inspect my-webhook | jq .
|
||||
```
|
||||
|
||||
**Output Format:**
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": "abc123",
|
||||
"method": "POST",
|
||||
"path": "/webhook",
|
||||
"headers": {"Content-Type": "application/json"},
|
||||
"body": "{\"event\":\"test\"}",
|
||||
"status": 200,
|
||||
"created_at": "2024-01-15T10:30:00Z"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
### `hatch search <endpoint>`
|
||||
|
||||
Search captured traffic with query syntax.
|
||||
|
||||
**Options:**
|
||||
|
||||
- `-query QUERY`: Search query (required)
|
||||
- `-limit N`: Maximum number of results (default: 100)
|
||||
|
||||
**Query Syntax:**
|
||||
|
||||
| Query | Description |
|
||||
|-------|-------------|
|
||||
| `status:500` | Filter by HTTP status code |
|
||||
| `POST` | Filter by HTTP method |
|
||||
| `user.created` | Search in request body |
|
||||
| `Content-Type:application/json` | Filter by header |
|
||||
|
||||
**Examples:**
|
||||
|
||||
```bash
|
||||
# Find all 500 errors
|
||||
hatch search my-webhook -query 'status:500'
|
||||
|
||||
# Find POST requests
|
||||
hatch search my-webhook -query 'POST'
|
||||
|
||||
# Search for specific content in body
|
||||
hatch search my-webhook -query 'user.created'
|
||||
|
||||
# Combine queries
|
||||
hatch search my-webhook -query 'status:500 POST'
|
||||
```
|
||||
|
||||
### `hatch replay <request-id>`
|
||||
|
||||
Replay a previously captured request to a target URL.
|
||||
|
||||
**Options:**
|
||||
|
||||
- `-endpoint ENDPOINT`: Source endpoint ID (required)
|
||||
- `-target URL`: Target URL to replay to (required)
|
||||
|
||||
**Examples:**
|
||||
|
||||
```bash
|
||||
# Replay a request
|
||||
hatch replay abc123 -endpoint my-webhook -target https://httpbin.org/post
|
||||
|
||||
# Replay to a local development server
|
||||
hatch replay def456 -endpoint api-calls -target http://localhost:3000/webhook
|
||||
|
||||
# Replay to a different environment
|
||||
hatch replay ghi789 -endpoint production-webhook -target https://staging.example.com/webhook
|
||||
```
|
||||
|
||||
**Use Cases:**
|
||||
|
||||
- Test webhook handlers in development
|
||||
- Reproduce bugs by replaying failed requests
|
||||
- Load testing with captured traffic patterns
|
||||
- Migrating traffic between environments
|
||||
|
||||
### `hatch mock set <endpoint>`
|
||||
|
||||
Configure mock responses for an endpoint.
|
||||
|
||||
**Options:**
|
||||
|
||||
- `-status CODE`: HTTP status code (default: 200)
|
||||
- `-body BODY`: Response body (string or base64)
|
||||
- `-header KEY:VALUE`: Response header (repeatable)
|
||||
|
||||
**Examples:**
|
||||
|
||||
```bash
|
||||
# Return 200 with JSON body
|
||||
hatch mock set my-webhook -status 200 -body '{"ok":true}'
|
||||
|
||||
# Return error response
|
||||
hatch mock set my-webhook -status 500 -body '{"error":"internal error"}'
|
||||
|
||||
# Return with custom headers
|
||||
hatch mock set my-webhook \
|
||||
-status 200 \
|
||||
-header 'X-RateLimit-Remaining:100' \
|
||||
-header 'Cache-Control:no-cache'
|
||||
|
||||
# Simulate rate limiting
|
||||
hatch mock set my-webhook \
|
||||
-status 429 \
|
||||
-header 'Retry-After:60' \
|
||||
-body '{"error":"rate limited"}'
|
||||
```
|
||||
|
||||
**Mock Behavior:**
|
||||
|
||||
- Once configured, all requests to the endpoint return the mock response
|
||||
- Mock configuration persists until server restart or explicit reconfiguration
|
||||
- Original request capture continues alongside mock responses
|
||||
|
||||
### `hatch doc generate <endpoint>`
|
||||
|
||||
Generate OpenAPI 3.1 specification for an endpoint based on captured traffic.
|
||||
|
||||
**Examples:**
|
||||
|
||||
```bash
|
||||
# Generate OpenAPI spec
|
||||
hatch doc generate my-webhook
|
||||
|
||||
# Save to file
|
||||
hatch doc generate my-webhook > openapi.json
|
||||
|
||||
# Use with Swagger UI
|
||||
hatch doc generate my-webhook > openapi.json
|
||||
docker run -p 8081:8080 -e SWAGGER_JSON=/openapi.json -v $(pwd):/usr/share/nginx/html/swagger swaggerapi/swagger-ui
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
Generates a complete OpenAPI 3.1 JSON specification including:
|
||||
|
||||
- All captured request/response patterns
|
||||
- Schema definitions inferred from traffic
|
||||
- Example values from real requests
|
||||
- Endpoint documentation
|
||||
|
||||
## Common Workflows
|
||||
|
||||
### Development Environment Setup
|
||||
|
||||
```bash
|
||||
# 1. Start Hatch server
|
||||
hatch serve &
|
||||
|
||||
# 2. Capture incoming webhooks
|
||||
hatch capture /api/webhooks -method POST -body '{"test":true}'
|
||||
|
||||
# 3. Inspect captured traffic
|
||||
hatch inspect api/webhooks
|
||||
|
||||
# 4. Configure mock for frontend development
|
||||
hatch mock set api/webhooks -status 200 -body '{"status":"ok"}'
|
||||
```
|
||||
|
||||
### Bug Reproduction
|
||||
|
||||
```bash
|
||||
# 1. Find the failing request
|
||||
hatch search api/payments -query 'status:500'
|
||||
|
||||
# 2. Get request details
|
||||
hatch inspect api/payments -limit 5
|
||||
|
||||
# 3. Replay to debug
|
||||
hatch replay <request-id> -endpoint api/payments -target http://localhost:8080/debug
|
||||
```
|
||||
|
||||
### API Documentation Generation
|
||||
|
||||
```bash
|
||||
# 1. Capture representative traffic
|
||||
for endpoint in users posts comments; do
|
||||
curl -X POST http://hatch:8080/$endpoint -d '{"sample":"data"}'
|
||||
done
|
||||
|
||||
# 2. Generate OpenAPI specs
|
||||
hatch doc generate users > users-api.json
|
||||
hatch doc generate posts > posts-api.json
|
||||
|
||||
# 3. Combine into single spec (using jq)
|
||||
jq -s '.[0] * .[1]' users-api.json posts-api.json > combined-api.json
|
||||
```
|
||||
|
||||
### Load Testing Preparation
|
||||
|
||||
```bash
|
||||
# 1. Capture production traffic patterns
|
||||
hatch inspect api/critical-path -limit 1000 > traffic.json
|
||||
|
||||
# 2. Extract request patterns
|
||||
jq -r '.[] | "\(.method) \(.path)"' traffic.json | sort | uniq -c | sort -rn
|
||||
|
||||
# 3. Replay to load testing tool
|
||||
hatch inspect api/critical-path -limit 100 | \
|
||||
jq -r '.[] | "hatch replay \(.id) -endpoint api/critical-path -target https://loadtest.example.com"'
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Connection Issues
|
||||
|
||||
**Problem:** `Error: request failed: connection refused`
|
||||
|
||||
**Solution:** Ensure the Hatch server is running:
|
||||
|
||||
```bash
|
||||
# Check if server is running
|
||||
curl http://localhost:8080/healthz
|
||||
|
||||
# Start server if not running
|
||||
hatch serve
|
||||
```
|
||||
|
||||
### Authentication Errors
|
||||
|
||||
**Problem:** `Error (HTTP 401): unauthorized`
|
||||
|
||||
**Solution:** Check if your Hatch instance requires authentication:
|
||||
|
||||
```bash
|
||||
# For local development, ensure no auth is configured
|
||||
# For production, check HATCH_AUTH_TOKEN environment variable
|
||||
```
|
||||
|
||||
### Request Not Found
|
||||
|
||||
**Problem:** `Error (HTTP 404): endpoint not found`
|
||||
|
||||
**Solution:** Verify the endpoint ID exists:
|
||||
|
||||
```bash
|
||||
# List available endpoints
|
||||
curl http://localhost:8080/v1/endpoints
|
||||
|
||||
# Check if endpoint has captured requests
|
||||
hatch inspect <endpoint-id> -limit 1
|
||||
```
|
||||
|
||||
### JSON Parsing Errors
|
||||
|
||||
**Problem:** `Error: invalid character '}' looking for beginning of value`
|
||||
|
||||
**Solution:** Ensure request body is valid JSON:
|
||||
|
||||
```bash
|
||||
# Use proper JSON escaping
|
||||
hatch capture /api -body '{"key":"value"}'
|
||||
|
||||
# Or use a file
|
||||
hatch capture /api -body @request.json
|
||||
```
|
||||
|
||||
### Permission Denied on Binary
|
||||
|
||||
**Problem:** `Permission denied: ./hatch`
|
||||
|
||||
**Solution:** Make the binary executable:
|
||||
|
||||
```bash
|
||||
chmod +x hatch
|
||||
# Or move to a directory in PATH
|
||||
sudo mv hatch /usr/local/bin/
|
||||
```
|
||||
|
||||
## Environment Variables Reference
|
||||
|
||||
| Variable | Description | Default | Example |
|
||||
|----------|-------------|---------|---------|
|
||||
| `HATCH_URL` | Hatch server URL | `http://localhost:8080` | `https://hatch.example.com` |
|
||||
| `PORT` | Server listening port | `8080` | `9090` |
|
||||
|
||||
## Exit Codes
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 0 | Success |
|
||||
| 1 | General error |
|
||||
| 2 | Invalid command or arguments |
|
||||
| 3 | Network error |
|
||||
| 4 | Authentication error |
|
||||
| 5 | Resource not found |
|
||||
|
||||
## Getting Help
|
||||
|
||||
- **Command help:** `hatch <command> -h`
|
||||
- **General help:** `hatch --help`
|
||||
- **Version:** `hatch version`
|
||||
- **Issues:** [GitHub Issues](https://github.com/elfoundation/hatch/issues)
|
||||
- **Documentation:** [docs/](../README.md)
|
||||
|
||||
## Examples Repository
|
||||
|
||||
For more examples, see the [examples/](../../examples/) directory or visit our [documentation site](https://hatch.sh/examples).
|
||||
189
examples/README.md
Normal file
189
examples/README.md
Normal file
@ -0,0 +1,189 @@
|
||||
# Hatch Examples
|
||||
|
||||
Real-world examples and integration guides for using Hatch.
|
||||
|
||||
## Examples Index
|
||||
|
||||
| Example | Description | Use Case |
|
||||
|---------|-------------|----------|
|
||||
| [Webhook Integration](webhook-integration.md) | Comprehensive webhook capture, testing, and debugging | Payment processors, GitHub, Slack, API integrations |
|
||||
|
||||
## Quick Start Examples
|
||||
|
||||
### Capture Your First Request
|
||||
|
||||
```bash
|
||||
# Start Hatch server
|
||||
hatch serve &
|
||||
|
||||
# Capture a request
|
||||
curl -X POST http://localhost:8080/my-endpoint \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"event":"test","data":{"id":123}}'
|
||||
|
||||
# View captured requests
|
||||
hatch inspect my-endpoint
|
||||
```
|
||||
|
||||
### Mock API for Development
|
||||
|
||||
```bash
|
||||
# Configure mock response
|
||||
hatch mock set api/users \
|
||||
-status 200 \
|
||||
-header "Content-Type:application/json" \
|
||||
-body '[{"id":1,"name":"John Doe"}]'
|
||||
|
||||
# Test your frontend
|
||||
curl http://localhost:8080/api/users
|
||||
```
|
||||
|
||||
### Debug Failed Webhooks
|
||||
|
||||
```bash
|
||||
# Find errors
|
||||
hatch search webhooks -query "status:500"
|
||||
|
||||
# Replay to debug
|
||||
hatch replay <request-id> \
|
||||
-endpoint webhooks \
|
||||
-target http://localhost:3000/debug
|
||||
```
|
||||
|
||||
## Integration Guides
|
||||
|
||||
### Stripe Webhooks
|
||||
|
||||
See [Webhook Integration - Stripe Example](webhook-integration.md#example-1-stripe-webhook-testing)
|
||||
|
||||
### GitHub Webhooks
|
||||
|
||||
See [Webhook Integration - GitHub Example](webhook-integration.md#example-2-github-webhook-debugging)
|
||||
|
||||
### Slack Integration
|
||||
|
||||
See [Webhook Integration - Slack Example](webhook-integration.md#example-3-slack-integration-testing)
|
||||
|
||||
## Use Cases
|
||||
|
||||
### 1. Development Environment
|
||||
|
||||
Use Hatch as a local mock server for frontend development.
|
||||
|
||||
```bash
|
||||
# Configure mocks for your API
|
||||
hatch mock set api/users -status 200 -body '[]'
|
||||
hatch mock set api/auth -status 200 -body '{"token":"mock-token"}'
|
||||
|
||||
# Frontend code uses http://localhost:8080 as API base
|
||||
```
|
||||
|
||||
### 2. Testing & QA
|
||||
|
||||
Capture production traffic patterns and replay them in testing.
|
||||
|
||||
```bash
|
||||
# Capture traffic
|
||||
hatch inspect api/critical-path -limit 1000 > traffic.json
|
||||
|
||||
# Replay in test environment
|
||||
cat traffic.json | jq -r '.[].id' | while read id; do
|
||||
hatch replay "$id" -endpoint api/critical-path -target http://staging:8080
|
||||
done
|
||||
```
|
||||
|
||||
### 3. API Documentation
|
||||
|
||||
Generate OpenAPI specs from real traffic.
|
||||
|
||||
```bash
|
||||
# Capture representative traffic
|
||||
hatch capture /api/users -method GET
|
||||
hatch capture /api/users -method POST -body '{"name":"test"}'
|
||||
|
||||
# Generate documentation
|
||||
hatch doc generate api/users > users-api.json
|
||||
```
|
||||
|
||||
### 4. Load Testing
|
||||
|
||||
Replay captured traffic for load testing.
|
||||
|
||||
```bash
|
||||
# Capture production patterns
|
||||
hatch inspect api/critical-path -limit 1000 > load-test-traffic.json
|
||||
|
||||
# Create load test script
|
||||
cat > load-test.sh << 'EOF'
|
||||
#!/bin/bash
|
||||
for i in {1..100}; do
|
||||
hatch inspect api/critical-path -limit 10 | \
|
||||
jq -r '.[] | "hatch replay \(.id) -endpoint api/critical-path -target http://loadtest:8080"' | \
|
||||
bash &
|
||||
done
|
||||
wait
|
||||
EOF
|
||||
chmod +x load-test.sh
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Use descriptive endpoint names**
|
||||
```bash
|
||||
# Good
|
||||
hatch capture /webhooks/stripe-payments
|
||||
hatch capture /api/v2/users
|
||||
|
||||
# Bad
|
||||
hatch capture /a
|
||||
hatch capture /test
|
||||
```
|
||||
|
||||
2. **Include relevant headers**
|
||||
```bash
|
||||
hatch capture /webhooks/github \
|
||||
-header 'X-GitHub-Event:push' \
|
||||
-header 'X-Hub-Signature:sha1=abc123'
|
||||
```
|
||||
|
||||
3. **Organize by environment**
|
||||
```bash
|
||||
# Development
|
||||
hatch mock set dev/api/users -status 200 -body '[]'
|
||||
|
||||
# Staging
|
||||
hatch mock set staging/api/users -status 200 -body '[{"id":1}]'
|
||||
```
|
||||
|
||||
4. **Use search for debugging**
|
||||
```bash
|
||||
# Find all errors
|
||||
hatch search api/webhooks -query 'status:500'
|
||||
|
||||
# Find specific events
|
||||
hatch search webhooks/stripe -query 'payment_intent'
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
See [CLI Troubleshooting Guide](../docs/engineering/cli-troubleshooting.md) for common issues and solutions.
|
||||
|
||||
## Contributing Examples
|
||||
|
||||
To add a new example:
|
||||
|
||||
1. Create a markdown file in this directory
|
||||
2. Follow the naming convention: `<use-case>.md`
|
||||
3. Include:
|
||||
- Clear use case description
|
||||
- Step-by-step instructions
|
||||
- Complete code examples
|
||||
- Expected output
|
||||
- Common pitfalls
|
||||
4. Update this README.md to include your example in the index
|
||||
|
||||
## Resources
|
||||
|
||||
- [CLI Reference](../docs/engineering/cli.md) - Complete command documentation
|
||||
- [Quick Reference](../docs/engineering/cli-quick-reference.md) - Command cheat sheet
|
||||
- [Troubleshooting](../docs/engineering/cli-troubleshooting.md) - Common issues and solutions
|
||||
389
examples/webhook-integration.md
Normal file
389
examples/webhook-integration.md
Normal file
@ -0,0 +1,389 @@
|
||||
# Webhook Integration Examples
|
||||
|
||||
Real-world examples of using Hatch for webhook capture, testing, and debugging.
|
||||
|
||||
## Example 1: Stripe Webhook Testing
|
||||
|
||||
Capture and test Stripe webhook events in development.
|
||||
|
||||
### Setup
|
||||
|
||||
```bash
|
||||
# Start Hatch server
|
||||
hatch serve &
|
||||
|
||||
# Capture Stripe webhook events
|
||||
hatch capture /webhooks/stripe \
|
||||
-method POST \
|
||||
-header 'Stripe-Signature:whsec_test123' \
|
||||
-body '{"id":"evt_123","type":"payment_intent.succeeded","data":{"object":{"id":"pi_456","amount":2000,"currency":"usd"}}}'
|
||||
```
|
||||
|
||||
### Development Workflow
|
||||
|
||||
```bash
|
||||
# 1. Capture incoming webhook
|
||||
hatch capture /webhooks/stripe -body '{"type":"checkout.session.completed","data":{"object":{"id":"cs_789"}}}'
|
||||
|
||||
# 2. Inspect captured events
|
||||
hatch inspect webhooks/stripe
|
||||
|
||||
# 3. Search for specific event types
|
||||
hatch search webhooks/stripe -query 'payment_intent.succeeded'
|
||||
|
||||
# 4. Replay to test handler
|
||||
hatch replay <event-id> \
|
||||
-endpoint webhooks/stripe \
|
||||
-target http://localhost:3000/stripe/webhook
|
||||
|
||||
# 5. Configure mock for frontend testing
|
||||
hatch mock set webhooks/stripe \
|
||||
-status 200 \
|
||||
-body '{"received":true}'
|
||||
```
|
||||
|
||||
### Load Testing
|
||||
|
||||
```bash
|
||||
# Capture multiple events
|
||||
for i in {1..10}; do
|
||||
hatch capture /webhooks/stripe \
|
||||
-body "{\"id\":\"evt_$i\",\"type\":\"payment_intent.succeeded\"}"
|
||||
done
|
||||
|
||||
# Replay all to load test handler
|
||||
hatch inspect webhooks/stripe -limit 10 | \
|
||||
jq -r '.[] | "hatch replay \(.id) -endpoint webhooks/stripe -target http://localhost:3000/stripe/webhook"' | \
|
||||
bash
|
||||
```
|
||||
|
||||
## Example 2: GitHub Webhook Debugging
|
||||
|
||||
Debug GitHub webhook delivery issues.
|
||||
|
||||
### Capture GitHub Events
|
||||
|
||||
```bash
|
||||
# Capture push events
|
||||
hatch capture /webhooks/github \
|
||||
-method POST \
|
||||
-header 'X-GitHub-Event:push' \
|
||||
-header 'X-Hub-Signature:sha1=abc123' \
|
||||
-body '{"ref":"refs/heads/main","commits":[{"id":"def456","message":"Fix bug"}]}'
|
||||
|
||||
# Capture pull request events
|
||||
hatch capture /webhooks/github \
|
||||
-method POST \
|
||||
-header 'X-GitHub-Event:pull_request' \
|
||||
-body '{"action":"opened","pull_request":{"number":42,"title":"New feature"}}'
|
||||
```
|
||||
|
||||
### Debug Failed Deliveries
|
||||
|
||||
```bash
|
||||
# Find failed webhook deliveries
|
||||
hatch search webhooks/github -query 'status:500'
|
||||
|
||||
# Get details of failed request
|
||||
hatch inspect webhooks/github -limit 5
|
||||
|
||||
# Replay to local debugging server
|
||||
hatch replay <request-id> \
|
||||
-endpoint webhooks/github \
|
||||
-target http://localhost:8080/debug
|
||||
```
|
||||
|
||||
### Mock GitHub API Responses
|
||||
|
||||
```bash
|
||||
# Mock GitHub API for local development
|
||||
hatch mock set api/github \
|
||||
-status 200 \
|
||||
-header 'Content-Type:application/json' \
|
||||
-body '{"login":"test-user","id":12345}'
|
||||
```
|
||||
|
||||
## Example 3: Slack Integration Testing
|
||||
|
||||
Test Slack app integrations without hitting real Slack APIs.
|
||||
|
||||
### Capture Slack Events
|
||||
|
||||
```bash
|
||||
# Capture Slack events
|
||||
hatch capture /slack/events \
|
||||
-method POST \
|
||||
-header 'X-Slack-Signature:v0=abc123' \
|
||||
-body '{"type":"event_callback","event":{"type":"message","text":"Hello world"}}'
|
||||
|
||||
# Capture Slack interactive payloads
|
||||
hatch capture /slack/actions \
|
||||
-method POST \
|
||||
-header 'X-Slack-Signature:v0=def456' \
|
||||
-body '{"type":"interactive_message","actions":[{"type":"button","value":"approve"}]}'
|
||||
```
|
||||
|
||||
### Development Setup
|
||||
|
||||
```bash
|
||||
# Mock Slack API responses
|
||||
hatch mock set slack/api \
|
||||
-status 200 \
|
||||
-header 'Content-Type:application/json' \
|
||||
-body '{"ok":true}'
|
||||
|
||||
# Test message sending
|
||||
hatch replay <message-event-id> \
|
||||
-endpoint slack/events \
|
||||
-target http://localhost:3000/slack/events
|
||||
```
|
||||
|
||||
## Example 4: Payment Provider Integration
|
||||
|
||||
Test payment provider webhooks across different environments.
|
||||
|
||||
### Multi-Environment Setup
|
||||
|
||||
```bash
|
||||
# Development environment
|
||||
hatch mock set payments/webhook \
|
||||
-status 200 \
|
||||
-body '{"status":"received"}'
|
||||
|
||||
# Staging environment
|
||||
hatch capture payments/webhook \
|
||||
-body '{"type":"payment.completed","amount":1000,"currency":"USD"}'
|
||||
|
||||
# Replay to different environments
|
||||
hatch replay <payment-id> \
|
||||
-endpoint payments/webhook \
|
||||
-target http://localhost:8080/payments/webhook # Local
|
||||
hatch replay <payment-id> \
|
||||
-endpoint payments/webhook \
|
||||
-target https://staging.example.com/payments/webhook # Staging
|
||||
```
|
||||
|
||||
### Error Simulation
|
||||
|
||||
```bash
|
||||
# Simulate payment failure
|
||||
hatch mock set payments/webhook \
|
||||
-status 200 \
|
||||
-body '{"status":"failed","error":"insufficient_funds"}'
|
||||
|
||||
# Simulate network timeout (use with caution)
|
||||
hatch mock set payments/webhook \
|
||||
-status 504 \
|
||||
-body '{"error":"gateway_timeout"}'
|
||||
```
|
||||
|
||||
## Example 5: API Documentation Generation
|
||||
|
||||
Generate OpenAPI documentation from real traffic patterns.
|
||||
|
||||
### Capture API Traffic
|
||||
|
||||
```bash
|
||||
# Capture various endpoints
|
||||
hatch capture /api/users -method GET
|
||||
hatch capture /api/users -method POST -body '{"name":"John Doe"}'
|
||||
hatch capture /api/users/123 -method GET
|
||||
hatch capture /api/users/123 -method PUT -body '{"name":"Jane Doe"}'
|
||||
hatch capture /api/posts -method GET
|
||||
hatch capture /api/posts -method POST -body '{"title":"Hello World"}'
|
||||
```
|
||||
|
||||
### Generate Documentation
|
||||
|
||||
```bash
|
||||
# Generate OpenAPI specs for each endpoint
|
||||
hatch doc generate api/users > users-api.json
|
||||
hatch doc generate api/posts > posts-api.json
|
||||
|
||||
# Combine into single spec
|
||||
jq -s '.[0] * .[1]' users-api.json posts-api.json > combined-api.json
|
||||
|
||||
# Serve with Swagger UI
|
||||
docker run -p 8081:8080 \
|
||||
-e SWAGGER_JSON=/openapi.json \
|
||||
-v $(pwd):/usr/share/nginx/html/swagger \
|
||||
swaggerapi/swagger-ui
|
||||
```
|
||||
|
||||
## Example 6: Load Testing with Real Traffic
|
||||
|
||||
Capture and replay production traffic for load testing.
|
||||
|
||||
### Capture Production Patterns
|
||||
|
||||
```bash
|
||||
# Capture high-traffic endpoint
|
||||
hatch capture /api/critical-path -limit 1000
|
||||
|
||||
# Export traffic patterns
|
||||
hatch inspect api/critical-path -limit 1000 > traffic-patterns.json
|
||||
```
|
||||
|
||||
### Analyze Traffic
|
||||
|
||||
```bash
|
||||
# Analyze request distribution
|
||||
jq -r '.[] | "\(.method) \(.path)"' traffic-patterns.json | \
|
||||
sort | uniq -c | sort -rn
|
||||
|
||||
# Find slow requests (if timing data available)
|
||||
jq '.[] | select(.duration > 1000)' traffic-patterns.json
|
||||
|
||||
# Identify error patterns
|
||||
jq '.[] | select(.status >= 400)' traffic-patterns.json
|
||||
```
|
||||
|
||||
### Replay for Load Testing
|
||||
|
||||
```bash
|
||||
# Create load test script
|
||||
cat > load-test.sh << 'EOF'
|
||||
#!/bin/bash
|
||||
ENDPOINT="api/critical-path"
|
||||
TARGET="https://loadtest.example.com"
|
||||
REQUESTS=$(hatch inspect $ENDPOINT -limit 100)
|
||||
|
||||
echo "$REQUESTS" | jq -r '.[] | .id' | while read -r id; do
|
||||
echo "Replaying request $id"
|
||||
hatch replay "$id" -endpoint "$ENDPOINT" -target "$TARGET"
|
||||
sleep 0.1 # Rate limiting
|
||||
done
|
||||
EOF
|
||||
|
||||
chmod +x load-test.sh
|
||||
./load-test.sh
|
||||
```
|
||||
|
||||
## Example 7: Mock Server for Frontend Development
|
||||
|
||||
Set up a comprehensive mock server for frontend development.
|
||||
|
||||
### Create Mock Endpoints
|
||||
|
||||
```bash
|
||||
# User API mock
|
||||
hatch mock set api/users \
|
||||
-status 200 \
|
||||
-header 'Content-Type:application/json' \
|
||||
-body '[
|
||||
{"id":1,"name":"John Doe","email":"john@example.com"},
|
||||
{"id":2,"name":"Jane Smith","email":"jane@example.com"}
|
||||
]'
|
||||
|
||||
# Authentication mock
|
||||
hatch mock set api/auth \
|
||||
-status 200 \
|
||||
-header 'Content-Type:application/json' \
|
||||
-body '{"token":"mock-jwt-token-123","expires_in":3600}'
|
||||
|
||||
# Error responses
|
||||
hatch mock set api/errors \
|
||||
-status 401 \
|
||||
-header 'Content-Type:application/json' \
|
||||
-body '{"error":"unauthorized","message":"Invalid credentials"}'
|
||||
```
|
||||
|
||||
### Frontend Integration
|
||||
|
||||
```javascript
|
||||
// Frontend code using mock API
|
||||
const API_BASE = 'http://localhost:8080';
|
||||
|
||||
// Fetch users
|
||||
const response = await fetch(`${API_BASE}/api/users`);
|
||||
const users = await response.json();
|
||||
|
||||
// Login
|
||||
const loginResponse = await fetch(`${API_BASE}/api/auth`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ email: 'user@example.com', password: 'pass' })
|
||||
});
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### 1. Use Descriptive Endpoint Names
|
||||
|
||||
```bash
|
||||
# Good
|
||||
hatch capture /webhooks/stripe-payments
|
||||
hatch capture /api/v2/users
|
||||
|
||||
# Bad
|
||||
hatch capture /a
|
||||
hatch capture /test
|
||||
```
|
||||
|
||||
### 2. Include Relevant Headers
|
||||
|
||||
```bash
|
||||
# Capture with all relevant headers
|
||||
hatch capture /webhooks/github \
|
||||
-header 'X-GitHub-Event:push' \
|
||||
-header 'X-Hub-Signature:sha1=abc123' \
|
||||
-header 'Content-Type:application/json'
|
||||
```
|
||||
|
||||
### 3. Organize by Environment
|
||||
|
||||
```bash
|
||||
# Development
|
||||
hatch mock set dev/api/users -status 200 -body '[]'
|
||||
|
||||
# Staging
|
||||
hatch mock set staging/api/users -status 200 -body '[{"id":1}]'
|
||||
```
|
||||
|
||||
### 4. Use Search for Debugging
|
||||
|
||||
```bash
|
||||
# Find all errors
|
||||
hatch search api/webhooks -query 'status:500'
|
||||
|
||||
# Find specific event types
|
||||
hatch search webhooks/stripe -query 'payment_intent'
|
||||
```
|
||||
|
||||
### 5. Document Your Mocks
|
||||
|
||||
```bash
|
||||
# Add comments to mock configuration
|
||||
hatch mock set api/users \
|
||||
-status 200 \
|
||||
-header 'X-Mock-Description:Returns list of test users'
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
1. **Connection refused**: Ensure Hatch server is running (`hatch serve`)
|
||||
2. **Endpoint not found**: Check endpoint ID with `curl http://localhost:8080/v1/endpoints`
|
||||
3. **Request not captured**: Verify request format and headers
|
||||
4. **Mock not working**: Check if mock is configured for the correct endpoint
|
||||
|
||||
### Debug Mode
|
||||
|
||||
```bash
|
||||
# Enable debug logging
|
||||
DEBUG=true hatch serve
|
||||
|
||||
# Check server logs
|
||||
docker logs -f hatch-container
|
||||
```
|
||||
|
||||
### Performance Issues
|
||||
|
||||
```bash
|
||||
# Limit concurrent connections
|
||||
hatch inspect api/heavy-endpoint -limit 10
|
||||
|
||||
# Use pagination for large datasets
|
||||
hatch inspect api/large-dataset -limit 50
|
||||
```
|
||||
280
scripts/hatch-setup.sh
Executable file
280
scripts/hatch-setup.sh
Executable file
@ -0,0 +1,280 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Hatch CLI Setup and Verification Script
|
||||
# This script helps users install and verify the Hatch CLI
|
||||
|
||||
set -e
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Function to print colored output
|
||||
print_status() {
|
||||
local status=$1
|
||||
local message=$2
|
||||
|
||||
case $status in
|
||||
"OK")
|
||||
echo -e "${GREEN}✓${NC} $message"
|
||||
;;
|
||||
"WARN")
|
||||
echo -e "${YELLOW}⚠${NC} $message"
|
||||
;;
|
||||
"ERROR")
|
||||
echo -e "${RED}✗${NC} $message"
|
||||
;;
|
||||
"INFO")
|
||||
echo -e "${BLUE}ℹ${NC} $message"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Function to check if command exists
|
||||
command_exists() {
|
||||
command -v "$1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
# Function to get latest release version from GitHub
|
||||
get_latest_version() {
|
||||
if command_exists curl; then
|
||||
curl -s https://api.github.com/repos/elfoundation/hatch/releases/latest | grep -o '"tag_name": "[^"]*"' | cut -d'"' -f4
|
||||
elif command_exists wget; then
|
||||
wget -qO- https://api.github.com/repos/elfoundation/hatch/releases/latest | grep -o '"tag_name": "[^"]*"' | cut -d'"' -f4
|
||||
else
|
||||
echo "unknown"
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to detect platform
|
||||
detect_platform() {
|
||||
local os=$(uname -s | tr '[:upper:]' '[:lower:]')
|
||||
local arch=$(uname -m)
|
||||
|
||||
case $os in
|
||||
linux)
|
||||
case $arch in
|
||||
x86_64|amd64)
|
||||
echo "linux-amd64"
|
||||
;;
|
||||
aarch64|arm64)
|
||||
echo "linux-arm64"
|
||||
;;
|
||||
*)
|
||||
echo "linux-unknown"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
darwin)
|
||||
case $arch in
|
||||
x86_64|amd64)
|
||||
echo "darwin-amd64"
|
||||
;;
|
||||
arm64)
|
||||
echo "darwin-arm64"
|
||||
;;
|
||||
*)
|
||||
echo "darwin-unknown"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
mingw*|msys*|cygwin*)
|
||||
echo "windows-amd64"
|
||||
;;
|
||||
*)
|
||||
echo "unknown"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Function to install hatch
|
||||
install_hatch() {
|
||||
local platform=$(detect_platform)
|
||||
local version=$(get_latest_version)
|
||||
|
||||
if [ "$platform" = "unknown" ]; then
|
||||
print_status "ERROR" "Unsupported platform: $(uname -s) $(uname -m)"
|
||||
echo "Please install manually from https://github.com/elfoundation/hatch/releases"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$version" = "unknown" ] || [ -z "$version" ]; then
|
||||
print_status "WARN" "Could not determine latest version"
|
||||
print_status "INFO" "Please check https://github.com/elfoundation/hatch/releases"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local binary_name="hatch-${platform}"
|
||||
local download_url="https://github.com/elfoundation/hatch/releases/download/${version}/${binary_name}"
|
||||
|
||||
if [ "$platform" = "windows-amd64" ]; then
|
||||
binary_name="hatch-windows-amd64.exe"
|
||||
download_url="https://github.com/elfoundation/hatch/releases/download/${version}/${binary_name}"
|
||||
fi
|
||||
|
||||
print_status "INFO" "Detected platform: ${platform}"
|
||||
print_status "INFO" "Latest version: ${version}"
|
||||
print_status "INFO" "Download URL: ${download_url}"
|
||||
|
||||
# Create temporary directory
|
||||
local temp_dir=$(mktemp -d)
|
||||
local temp_file="${temp_dir}/${binary_name}"
|
||||
|
||||
print_status "INFO" "Downloading hatch..."
|
||||
|
||||
# Download binary
|
||||
if command_exists curl; then
|
||||
curl -L -o "$temp_file" "$download_url"
|
||||
elif command_exists wget; then
|
||||
wget -O "$temp_file" "$download_url"
|
||||
else
|
||||
print_status "ERROR" "Neither curl nor wget found. Please install one."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "$temp_file" ]; then
|
||||
print_status "ERROR" "Failed to download binary"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Make executable (Unix only)
|
||||
if [[ "$platform" != windows-* ]]; then
|
||||
chmod +x "$temp_file"
|
||||
fi
|
||||
|
||||
# Determine installation directory
|
||||
local install_dir=""
|
||||
if [ -d "/usr/local/bin" ] && [ -w "/usr/local/bin" ]; then
|
||||
install_dir="/usr/local/bin"
|
||||
elif [ -d "$HOME/.local/bin" ]; then
|
||||
install_dir="$HOME/.local/bin"
|
||||
# Ensure PATH includes ~/.local/bin
|
||||
if [[ ":$PATH:" != *":$HOME/.local/bin:"* ]]; then
|
||||
print_status "WARN" "Adding ~/.local/bin to PATH"
|
||||
echo 'export PATH="$HOME/.local/bin:$PATH"' >> "$HOME/.bashrc"
|
||||
echo 'export PATH="$HOME/.local/bin:$PATH"' >> "$HOME/.zshrc" 2>/dev/null || true
|
||||
fi
|
||||
else
|
||||
install_dir="$HOME/.local/bin"
|
||||
mkdir -p "$install_dir"
|
||||
fi
|
||||
|
||||
local install_path="${install_dir}/hatch"
|
||||
|
||||
# Install binary
|
||||
if [ -w "$install_dir" ]; then
|
||||
mv "$temp_file" "$install_path"
|
||||
else
|
||||
print_status "INFO" "Using sudo to install to ${install_dir}"
|
||||
sudo mv "$temp_file" "$install_path"
|
||||
fi
|
||||
|
||||
# Clean up
|
||||
rm -rf "$temp_dir"
|
||||
|
||||
print_status "OK" "Hatch installed to ${install_path}"
|
||||
|
||||
# Verify installation
|
||||
if command_exists hatch; then
|
||||
print_status "OK" "Hatch is in PATH"
|
||||
hatch version
|
||||
else
|
||||
print_status "WARN" "Hatch installed but not in PATH"
|
||||
print_status "INFO" "You may need to restart your shell or add ${install_dir} to PATH"
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to verify installation
|
||||
verify_installation() {
|
||||
print_status "INFO" "Verifying Hatch installation..."
|
||||
|
||||
# Check if hatch is installed
|
||||
if ! command_exists hatch; then
|
||||
print_status "ERROR" "Hatch is not installed or not in PATH"
|
||||
echo "Please install hatch first:"
|
||||
echo " $0 install"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check version
|
||||
print_status "INFO" "Checking version..."
|
||||
if hatch version; then
|
||||
print_status "OK" "Version check passed"
|
||||
else
|
||||
print_status "ERROR" "Version check failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check help
|
||||
print_status "INFO" "Checking help..."
|
||||
if hatch --help > /dev/null 2>&1; then
|
||||
print_status "OK" "Help command works"
|
||||
else
|
||||
print_status "ERROR" "Help command failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if server is running
|
||||
print_status "INFO" "Checking server connectivity..."
|
||||
if curl -s http://localhost:8080/healthz > /dev/null 2>&1; then
|
||||
print_status "OK" "Server is running and accessible"
|
||||
|
||||
# Test capture command (dry run)
|
||||
print_status "INFO" "Testing CLI commands..."
|
||||
|
||||
# Test inspect (will fail if no endpoints, but that's OK)
|
||||
if hatch inspect default -limit 1 > /dev/null 2>&1; then
|
||||
print_status "OK" "CLI commands working"
|
||||
else
|
||||
print_status "WARN" "CLI commands may have issues (server might not have data)"
|
||||
fi
|
||||
else
|
||||
print_status "WARN" "Server not running at http://localhost:8080"
|
||||
print_status "INFO" "Start server with: hatch serve"
|
||||
fi
|
||||
|
||||
print_status "OK" "Installation verification complete"
|
||||
}
|
||||
|
||||
# Function to show usage
|
||||
show_usage() {
|
||||
echo "Hatch CLI Setup and Verification Script"
|
||||
echo ""
|
||||
echo "Usage: $0 [command]"
|
||||
echo ""
|
||||
echo "Commands:"
|
||||
echo " install Download and install the latest hatch binary"
|
||||
echo " verify Verify hatch installation and connectivity"
|
||||
echo " help Show this help message"
|
||||
echo ""
|
||||
echo "Examples:"
|
||||
echo " $0 install # Install hatch"
|
||||
echo " $0 verify # Verify installation"
|
||||
echo ""
|
||||
echo "Manual installation:"
|
||||
echo " 1. Download from https://github.com/elfoundation/hatch/releases"
|
||||
echo " 2. chmod +x hatch-*"
|
||||
echo " 3. sudo mv hatch-* /usr/local/bin/hatch"
|
||||
}
|
||||
|
||||
# Main script
|
||||
main() {
|
||||
local command=${1:-help}
|
||||
|
||||
case $command in
|
||||
install)
|
||||
install_hatch
|
||||
;;
|
||||
verify)
|
||||
verify_installation
|
||||
;;
|
||||
help|*)
|
||||
show_usage
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Loading…
Reference in New Issue
Block a user