Test Real Webhooks in CI With Three Lines of YAML
The new hookbase/setup-tunnel GitHub Action exposes a localhost port via a public Hookbase tunnel during CI runs. Receive real webhooks from Stripe, GitHub, Shopify, or any provider against ephemeral test environments — without managing tunnel lifecycle by hand.
The Setup
You have a webhook handler. You want to know it works against real Stripe events, real GitHub deliveries, real Shopify orders — not handcrafted fixtures that drift out of sync with the provider every six months. The handler runs fine on your laptop with hookbase tunnel 3000. But in CI? Most teams give up and write mocks instead.
That's the gap we're closing today.
Hookbase Setup Tunnel — GitHub Action
- uses: HookbaseApp/setup-tunnel@v1
id: tunnel
with:
port: 3000
api-key: ${{ secrets.HOOKBASE_API_KEY }}
- run: echo "Webhook URL is ${{ steps.tunnel.outputs.tunnel-url }}"
Three lines. The Action installs the Hookbase CLI on the runner, starts a tunnel pointing at port 3000, exposes the public URL as a step output, and tears the tunnel down automatically when the job finishes.
You point Stripe (or GitHub, Shopify, Plaid, whoever) at that URL, fire a test event, and assert your handler processed it. The same trust boundary you'd have in production — real webhook, real signature, real payload — but inside a disposable CI job.
Why This Matters
Mock-based webhook tests have a known failure mode: they pass forever, and your handler breaks the day a provider tweaks their payload format. Schema drift is silent until production.
End-to-end webhook tests catch that drift the day it happens. The reason teams don't write them is operational friction:
- ngrok URLs change every restart, so you can't pre-register them with the provider
- Stripe CLI works for Stripe only, and rotates the signing secret every session
- Self-hosted tunnel solutions need infrastructure you don't want in your CI account
The Action removes all of that. Stable URL pattern, works for every provider Hookbase supports, no infrastructure of your own.
What You Get
- Real signature verification. Hookbase verifies the provider's HMAC before forwarding. Your handler exercises the actual verification path.
- Real retry semantics. If your handler returns 5xx, Hookbase retries with exponential backoff — exactly what production looks like.
- Event history per CI run. Every webhook the tunnel receives is stored in your Hookbase dashboard. When a CI run fails, the payload that broke it is one click away.
- Automatic teardown. No leaked tunnels. The Action's post-step kills the CLI cleanly, and the CLI deletes the tunnel server-side.
A Real Example: GitHub Webhook Round Trip
jobs:
webhook-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- name: Start handler
run: npm run start &
- uses: HookbaseApp/setup-tunnel@v1
id: tunnel
with:
port: 3000
api-key: ${{ secrets.HOOKBASE_API_KEY }}
- name: Register a webhook with the GitHub repo
run: |
gh api repos/${{ github.repository }}/hooks \
-f name=web \
-f config[url]=${{ steps.tunnel.outputs.tunnel-url }} \
-f config[content_type]=json \
-f events[]=push
- name: Push something to trigger the webhook
run: ./scripts/trigger-test-push.sh
- name: Assert handler processed the event
run: ./scripts/assert-handler-saw-push.sh
Every push to that branch now exercises the full webhook path against real GitHub deliveries.
Inputs and Outputs
| Input | Required | Default | Description |
|-------|----------|---------|-------------|
| port | yes | — | Local port to forward |
| api-key | yes | — | Hookbase API key (whr_...) |
| subdomain | no | — | Custom subdomain (Pro plan) |
| cli-version | no | latest | Pin a specific CLI version |
| api-url | no | https://api.hookbase.app | Override the API URL |
| ready-timeout-ms | no | 30000 | Timeout waiting for tunnel to connect |
| Output | Description |
|--------|-------------|
| tunnel-url | Public URL of the tunnel. Also exported as HOOKBASE_TUNNEL_URL env var. |
Get Started
The Action is live on the GitHub Marketplace today: HookbaseApp/setup-tunnel.
You'll need a Hookbase account (free tier covers all CI usage) and an API key from your dashboard. Drop it into your repo's Actions secrets and you're done.