Skip to content

GitHub Action

The hookbridge/hookbridge-action GitHub Action creates a short-lived inbound endpoint for a single workflow run, starts a listener that forwards deliveries to your application, and exposes the receive URL as a step output. A matching cleanup action deletes the endpoint and stops the listener when the job finishes.

Source and full README: github.com/hookbridge/hookbridge-action

- uses: hookbridge/hookbridge-action@v1
id: hookbridge
with:
api-key: ${{ secrets.HOOKBRIDGE_API_KEY }}
- run: ./run-my-webhook-tests.sh
env:
WEBHOOK_URL: ${{ steps.hookbridge.outputs.url }}
- uses: hookbridge/hookbridge-action/cleanup@v1
if: always()
with:
api-key: ${{ secrets.HOOKBRIDGE_API_KEY }}
endpoint-id: ${{ steps.hookbridge.outputs.endpoint-id }}
listener-pid: ${{ steps.hookbridge.outputs.listener-pid }}
listener-identity: ${{ steps.hookbridge.outputs.listener-identity }}

A complete job that starts an application, points a webhook provider (or a test script) at it for the duration of the run, then tears everything down:

name: Webhook Tests
on:
pull_request:
workflow_dispatch:
jobs:
webhook-tests:
runs-on: ubuntu-latest
if: github.event_name == 'workflow_dispatch' || github.event.pull_request.head.repo.full_name == github.repository
steps:
- uses: actions/checkout@v4
- name: Start application
run: ./start-app.sh &
- uses: hookbridge/hookbridge-action@v1
id: hookbridge
with:
api-key: ${{ secrets.HOOKBRIDGE_API_KEY }}
port: 3000
- name: Run webhook tests
run: ./run-my-webhook-tests.sh
env:
WEBHOOK_URL: ${{ steps.hookbridge.outputs.url }}
- uses: hookbridge/hookbridge-action/cleanup@v1
if: always()
with:
api-key: ${{ secrets.HOOKBRIDGE_API_KEY }}
endpoint-id: ${{ steps.hookbridge.outputs.endpoint-id }}
listener-pid: ${{ steps.hookbridge.outputs.listener-pid }}
listener-identity: ${{ steps.hookbridge.outputs.listener-identity }}

The if: condition on the job is explained in Fork Pull Requests below.

Input Required Default Description
api-key Yes HookBridge API key for creating and managing endpoints. Pass it via an encrypted GitHub Actions secret, never as a plain value.
cli-version No v1.1.2 Version of the HookBridge CLI to download and run.
port No 3000 Local port your application listens on. Ignored when forward is set.
forward No '' Full URL to forward incoming deliveries to. When set, overrides port entirely.
ttl-minutes No 30 How long the endpoint stays alive, in minutes (1–1440). A safety net in case cleanup never runs.
name No '' Name for the HookBridge endpoint. When empty, derived from the repository, run ID, and run attempt.
Output Description
url The receive URL. Deliveries sent here are forwarded to your app. Embeds a secret path component and is masked in workflow logs.
endpoint-id ID of the endpoint created for this run. Pass to the cleanup action.
listener-pid Process ID of the background listener. Pass to the cleanup action.
listener-identity Identity of the background listener process. Pass to the cleanup action.
cli-version The CLI version actually resolved for this run.

Because composite actions have no post: hook, cleanup is a separate step rather than something that runs automatically at the end of the job. Add it with if: always() so it still runs when an earlier step in the job fails.

Input Required Default Description
api-key Yes Must be the same key used by the main action step.
endpoint-id Yes From steps.<id>.outputs.endpoint-id.
listener-pid No '' From steps.<id>.outputs.listener-pid. Leave unset to skip stopping the listener.
listener-identity No '' From steps.<id>.outputs.listener-identity. Leave unset to skip stopping the listener.
cli-version No v1.1.2 If you overrode cli-version on the main action, pass steps.<id>.outputs.cli-version here too.

The cleanup action produces no outputs.

If a job is cancelled before the cleanup step runs, the endpoint’s TTL (ttl-minutes) deletes it automatically once it expires — that TTL is the backstop for the case where cleanup never runs at all.

  • Linux only, amd64 or arm64. The action does not work on macOS or Windows runners and hard-fails, naming the OS or architecture it does not recognize, because only a Linux build of the CLI is shipped.
  • Runs under bash, not POSIX sh.
  • Needs jq and curl on the runner. jq and sha256sum are checked before use and fail with a message naming the missing tool; a missing curl or tar instead surfaces as a raw “command not found.” GitHub-hosted ubuntu-latest runners already have all of these — this only matters on a self-hosted runner built from a stripped-down base image.
  • You do not need to install hb yourself — the action downloads and checksum-verifies it.

A pull_request workflow triggered from a fork gets no access to repository or organization secrets. secrets.HOOKBRIDGE_API_KEY arrives empty, and the action cannot create an endpoint. This is a GitHub security boundary, not a bug, and there is no workaround inside the action.

Guard the job so it skips cleanly instead of failing confusingly:

if: github.event_name == 'workflow_dispatch' || github.event.pull_request.head.repo.full_name == github.repository

If you need webhook testing that must run from a fork, or that needs no HookBridge account at all, point contributors at test.hookbridge.io, the public no-signup webhook testing tool.

HookBridge API keys carry no scopes and no read-only mode — a key has full access to whatever project it belongs to, including deleting endpoints and reading the webhook payloads that pass through them. Use a key from a dedicated HookBridge CI project, never your production key, so a compromised CI run cannot reach production traffic.

The action masks both the API key and the receive URL in workflow logs before either can be printed.

Personalize Examples

Enter your credentials to populate code examples throughout the docs.