Deploy on every push
Add an app's push webhook to GitLab, Gitea, Forgejo, Gogs or GitHub so that each push to the app's branch builds and deploys that commit.
Every app that builds from git has a push webhook. Add its address and secret to the repository at your git host, and each push to the app's branch starts a release of the pushed commit. It works with GitHub, GitLab, Gitea, Forgejo and Gogs.
For a repository on GitHub, connecting the GitHub App on the deployment's Git tab does the same without a webhook, and adds previews and commit statuses (Connect GitHub). Use the push webhook for a repository on another host. Its address and secret are read and made through the Apps API; the dashboard does not show them.
Before you begin
Section titled Before you begin- The app must build from git. An app that runs an image has no push webhook.
- Send your access token as
Authorization: Bearer $CORITAN_TOKEN(Authentication). The requests take the app'suuid, whichGET /api/v1/client/appslists. - You need the webhook's secret. It appears once, in the answer to the request that creates the app. If you did not save it, make a new secret.
- You need permission to add webhooks to the repository at your git host.
- For an organization's app, you need the owner or admin role in the organization to make a new secret.
Add the webhook at your git host
Section titled Add the webhook at your git host- Find the webhook's address: the app's
webhook.urlinGET /api/v1/client/apps/{app_uuid}, such ashttps://api.coritan.com/api/v1/apps/hooks/3c9e2f4a-8b1d-4f6e-a2c7-5d8b9e0f1a21. - At your git host, open the repository's webhook settings and add a webhook with that address.
- Where the host asks for a content type, choose
application/json. GitHub's form encoded deliveries work too. - Paste the app's webhook secret into the webhook's secret field. GitLab calls it the secret token.
- Choose push events. The webhook ignores every other event, so choosing more only adds deliveries that do nothing.
- Save the webhook. GitHub then sends a test delivery called a ping, which the webhook answers with
200, so GitHub shows the webhook as working.
The address takes no access token. The secret proves that a delivery comes from your git host. The app's webhook.secret_set says whether it has a secret, and webhook.secret_hint shows its last four characters. While no secret is set, pushes are refused.
What a push deploys
Section titled What a push deploysA delivery starts a release when all of these hold:
- It is a push to a branch, and that branch is the app's branch. A push to a tag deploys nothing, and neither does a push to another branch unless the app makes previews.
- It comes from the app's own repository. When the delivery names its repository, we compare the host and path with the app's repository address.
- It names the commit at the head of the push.
- The app is
active. - When the app has watch paths, the push changed at least one file they name (Choose which pushes build).
The release builds the pushed commit and records its message and author. Its trigger is push and its actor_type is webhook, so you can tell it apart from one you started. The Releases tab reads it as Push to the branch's name. When several pushes arrive close together, each starts a release, and the newest to go live cancels any older one still on its way (Releases).
When the app makes previews, a push to another branch builds a preview of that branch instead, and deleting the branch closes its previews (Turn on previews).
A delivery deploys at most once. We remember each delivery's ID for a day, so a redelivery from your git host is ignored. A push of the commit that the app's latest push release already has is ignored too. To run the same commit again, rebuild the app.
An app can deploy 30 pushes in 5 minutes. Past that, the webhook answers 429 until the 5 minutes have passed.
How a delivery is checked
Section titled How a delivery is checkedWe check the delivery against the app's secret before we read it. The header depends on the git host:
| Git host | Header | What it holds |
|---|---|---|
| GitHub | X-Hub-Signature-256 |
sha256= and the HMAC SHA-256 of the body, keyed with the secret |
| Gitea, Forgejo, Gogs | X-Gitea-Signature, X-Forgejo-Signature or X-Gogs-Signature |
The HMAC SHA-256 of the body, keyed with the secret |
| GitLab | X-Gitlab-Token |
The secret itself |
We read the delivery's ID from the host's delivery header, such as X-GitHub-Delivery or X-Gitlab-Event-UUID. A delivery can be up to 10 MB.
Make a new secret
Section titled Make a new secretMake a new secret when you have lost the old one, or when someone who should not have it may have seen it. The new secret appears once, and the old one stops working at once. Paste the new secret into your git host's webhook straight away, or pushes answer 401 and deploy nothing.
POST /api/v1/client/apps/{app_uuid}/webhook/rotate makes a new secret, or the first one for an app that has none. For an organization's app, send it to POST /api/v1/orgs/{org_slug}/apps/{app_uuid}/webhook/rotate.
curl -X POST https://api.coritan.com/api/v1/client/apps/3c9e2f4a-8b1d-4f6e-a2c7-5d8b9e0f1a21/webhook/rotate \
-H "Authorization: Bearer $CORITAN_TOKEN"
{
"webhook": {
"url": "https://api.coritan.com/api/v1/apps/hooks/3c9e2f4a-8b1d-4f6e-a2c7-5d8b9e0f1a21",
"secret": "4f1d2c3b5a69788796a5b4c3d2e1f0a94f1d2c3b5a69788796a5b4c3d2e1f0a9"
}
}
secret appears in this answer only. Afterwards the app's webhook.secret_hint shows its last four characters, so you can check which secret your git host holds. An app that runs an image answers 409 with {"error": "not_git", "message": "Only an app that builds from git has a push webhook"}.
Result
Section titled ResultEach push to the app's branch appears as a new release in the app's history, with the commit's ID, message and author, and on the app's Releases tab. Through the API its trigger is push. Your git host's delivery log shows each answer: 201 for a push that started a release, 202 for a delivery the webhook ignored and why, and 200 for a ping or a deleted branch whose previews it closed.
Troubleshooting
Section titled TroubleshootingYour git host's delivery log shows the webhook's answer to each delivery. A 202 answer names what the webhook ignored in ignored:
push to feature; the app deploys main- The push was to another branch, and the app makes no previews. Push to the app's branch, or change the branch the app deploys (Change the settings). When the answer also has
"previews": "the plan does not include previews", previews are on for the app but the plan of the account it bills to does not include them (Turn on previews). no changed file matches the watch paths- The push changed none of the files the app's watch paths name, so it builds nothing.
tag push- Tags do not deploy on their own. GitLab's tag pushes show as
not a push: tag_push. Deploy the tag yourself (Choose what to deploy). push from another repository- The delivery came from a repository other than the app's, such as a fork, or the repository moved. Correct the app's repository address.
the app is suspended- We suspended the app. Contact support to find out why.
this delivery was already receivedorthe latest push release already has this commit- The push was deployed already. Rebuild the app to run it again.
not a push: issues- The webhook sends other events. Choose push events only.
The webhook refuses a delivery with one of these, in detail:
Sign the delivery with the app's webhook secret.- The delivery has no signature. Paste the secret into the webhook at your git host.
The signature does not match the app's webhook secret.- Your git host holds another secret, often one from before you made a new one. Paste the current secret, or make a new one.
This app has no webhook secret. Create one in its settings.- The app has no secret yet. Make a new secret, then paste it into your git host.
No git app with this id.- The address does not belong to an app that builds from git. The app may have been deleted. Read
webhook.urlfrom the app again. The delivery is not JSON.- Set the webhook's content type to
application/json. Too many pushes to deploy. Wait a few minutes.- The app deployed 30 pushes in the last 5 minutes. Later pushes deploy again once the 5 minutes have passed.
Related
Section titled RelatedWith the API
Section titled With the APIThe webhook's answers
Section titled The webhook's answersYour git host sends deliveries to POST /api/v1/apps/hooks/{app_uuid}, the address in webhook.url. It is not in the API reference, because only a git host calls it. A success answers with ok set to true and the header Cache-Control: no-store:
{"ok": true, "deployment": "0b6f3d2e-7a41-4c59-8e1d-2f9a6b3c4d5e", "status": "queued"}
| Status | Body | Meaning |
|---|---|---|
200 |
{"ok": true, "event": "ping", "app": "<app uuid>", "branch": "main"} |
A ping. Nothing deploys. |
200 |
{"ok": true, "closed": ["<deployment uuid>"], "branch": "feature"} |
The branch was deleted, and its previews closed. |
201 |
{"ok": true, "deployment": "<deployment uuid>", "status": "queued"} |
The push started this release, which the answer calls deployment. |
202 |
{"ok": true, "ignored": "tag push"} |
The delivery deploys nothing, for the reason given. A repeated delivery also has "duplicate": true. |
A refusal has the error in detail, as in {"detail": {"ok": false, "error": "signature_mismatch", "message": "The signature does not match the app's webhook secret."}}:
| Status | error |
Cause |
|---|---|---|
400 |
invalid_payload |
The body is not JSON. |
401 |
signature_missing |
The delivery has no signature header. |
401 |
signature_mismatch |
The signature does not match the app's secret. |
403 |
webhook_not_configured |
The app has no secret. |
404 |
not_found |
No app that builds from git has this ID, or Apps is turned off (Not found.). |
409 |
refused |
The release was refused, and message says why. |
413 |
too_large |
The body is larger than 10 MB. |
422 |
repository_invalid |
The app's repository address cannot be built from, and message says why. |
429 |
rate_limited |
The app deployed 30 pushes in 5 minutes. Retry-After gives the wait in seconds. |
To deploy from a CI job instead, send a deploy request with an access token (Deploy through the API), or use a deploy hook (Deploy with a hook).
API operations on this page
| Method | Path | What it does |
|---|---|---|
POST | /api/v1/client/apps/{app_uuid}/webhook/rotate | A new secret for the push webhook, shown once; the old one stops verifying at once |
POST | /api/v1/orgs/{org_slug}/apps/{app_uuid}/webhook/rotate | A new secret for the push webhook, shown once; the old one stops verifying at once |