GitHub deploy hooks
Connect the TestFinch GitHub App once, pick a repository in a FlowQA project, and every successful deployment of that repository runs the project's regression against the deployed URL.
The commit gets a check named FlowQA: <project>, in progress while the run queues and then success or failure with a table of every test.
Nothing is added to your workflow files; the hook listens to GitHub's deployment events.
Three steps
- In Snag, open Settings, then Integrations, and choose Connect GitHub. GitHub asks which repositories the app may see; the app needs to read deployments and write checks. GitHub also asks you to authorize the app as yourself, which is how Snag knows the installation is yours. You return to Snag, signed in as yourself, and Snag connects the installation to this workspace.
- In FlowQA, open the project's Settings, then Schedules & CI, and add a hook under GitHub: the repository, an optional GitHub environment name, the FlowQA environment, the tests, and whether to run against the deployment's URL.
- Deploy. When GitHub records the deployment as successful, the run starts and the check appears on the commit within seconds.
What produces a deployment event
GitHub's deployment events come from whatever deploys your code and tells GitHub about it.
- Vercel, Netlify and Railway create a deployment and mark it successful when the site is live, with the deployment's URL.
- Heroku's GitHub integration creates deployments for auto-deploys and pipeline promotions.
- A GitHub Actions workflow can create one with the
deploymentspermission, for example throughchrnorm/deployment-actionor agh apicall. - Only a deployment status with state
successruns anything. Pending, failure, error and inactive are acknowledged and ignored.
If your deploys do not reach GitHub as deployments, keep using a CI trigger from your workflow instead; see the schedules and CI document.
Which URL the run uses
A hook runs against the deployment's URL when the hook says so (the default) and the deployment carries an https: URL in its status or payload.
The project's chosen environment is pointed at that URL for the run only, and the URL's host is allowed for the run; nothing in the project changes.
Preview deployments therefore run against their own preview URL, and production deployments against production.
When the deployment carries no URL or an http: one, the run uses the environment's own base URL and the check's summary says why.
Tests whose steps navigate to an absolute URL go where they say; relative navigation follows the deployment.
Protected previews, such as Vercel previews behind Deployment Protection, answer the run with a login wall, so every test fails.
Either allow the protection bypass for the FlowQA hosts, or turn the deployment URL off on the hook so the run uses the environment's base URL.
The check
One check per run, named FlowQA: <project>; a project with more than 100 tests starts several runs and the checks are numbered (1 of 3).
The title counts passed and failed tests.
The summary names the run, the environment, the URL, the duration and links to the run in FlowQA.
The details hold a table of every test with its result, time and the failing step's error.
A cancelled or expired run completes the check as neutral with the reason.
Require the check in branch protection to block merging on a red regression.
Alerts, limits and history
A hook's runs act as the person who created the hook, with their access, and alert the people named on the hook the way schedules and triggers do.
Runs count against the workspace's cloud run allowance and appear in the project's run history with the label deploy <sha> to <environment>.
Disconnecting GitHub in Snag revokes every hook in the workspace; uninstalling the app on GitHub does the same.
For agents
An agent with a member role sets this up through the API or the MCP tool. Creating and changing hooks needs a signed-in session token or the MCP connector, which signs in with OAuth. A personal access token is refused there: it can read the installation and list hooks, and with write scope it can also remove a hook or run one now, but it cannot create or change one.
Check the workspace's installation (any token works here):
curl -sS "$SNAG_API/v1/integrations/github?workspace_id=$WORKSPACE_ID" -H "Authorization: Bearer $SNAG_TOKEN"
{ "available": true, "connected": true,
"installation": { "installation_id": "777", "account_login": "acme", "account_type": "Organization", "repos": ["acme/shop"], "connected_by": "usr_...", "connected_at": "2026-10-11T09:00:00.000Z" },
"install_url": null, "manage_url": "https://github.com/settings/installations/777" }
When connected is false, a workspace admin must open install_url in a browser; the API cannot install the app on the person's behalf.
List, create and remove hooks (/v1/projects/:projectId/qa/github-hooks).
Creating one is run with a session token, not a personal access token:
curl -sS -X POST "$SNAG_API/v1/projects/$PROJECT_ID/qa/github-hooks" -H "Authorization: Bearer $SNAG_SESSION_TOKEN" -H 'content-type: application/json' \
-d '{"name":"Preview deploys","repo":"acme/shop","github_environment":"Preview","environment":"preview","use_deployment_url":true}'
{ "hook_id": "qtr_...", "project_id": "prj_...", "name": "Preview deploys", "repo": "acme/shop", "github_environment": "Preview", "environment": "preview",
"test_ids": [], "use_deployment_url": true, "alert_emails": ["you@company.com"], "alert_slack_channel": null, "alert_on": "failure",
"last_delivery_at": null, "last_execution_id": null, "last_error": null, "revoked_at": null,
"created_by": "usr_...", "created_at": "2026-10-11T09:00:00.000Z" }
repo must be one of the installation's repos; environment is a FlowQA environment id; github_environment is GitHub's environment name and null means any; test_ids empty means every recorded test.
alert_emails, alert_slack_channel and alert_on (failure or always) are settable too and default to the creator's email on failure.
PATCH the same path with /:hookId to change any of these; DELETE revokes; POST /:hookId/run runs now against the environment's base URL.
Over MCP the same three operations are the tool flowqa_github_hook with action list, create or delete; flowqa_get_run reads a run.