GitHub
Preview
Open and update issues, comment on pull requests and start workflows in your repositories.
- Status: Preview
- Shelf: Developer
- How you connect: API key
- Regions: global (not available to Kazakhstan-only workspaces)
- The service’s own API reference: https://docs.github.com/en/rest
Apps open and update issues, comment on issues and pull requests, and start workflows in your
repositories with a fine-grained personal access token. GitHub is reached through the HTTP API
connector with a preset: the gate calls only api.github.com, under /repos, with GET, POST
and PATCH. The token is sealed to the gate and apps never see it.
Connect it#
- On GitHub: Settings → Developer settings → Personal access tokens → Fine-grained tokens → Generate new token (github.com/settings/personal-access-tokens/new).
- Repository access: only the repositories the apps use. Under permissions give Issues
and Pull requests read and write. Add Contents write only if an app starts
workflows with a repository event (
repository_dispatchneeds it). Nothing else. - Copy the token (it starts with
github_pat_; GitHub shows it once). Set an expiry you will remember: an expired token shows as Expired — reconnect. - Qaldy → Connectors → GitHub → Connect GitHub → paste the token → Seal and connect.
Test connection calls GET /rate_limit, which answers for any valid token and does not
count against your rate limit. It proves the token is accepted, not that it can see a repository.
What the gate allows#
| Host | api.github.com (pinned, every resolved address public) |
| Methods | GET, POST, PATCH (no PUT, no DELETE: an app can't merge, delete or change settings) |
| Paths | everything under /repos |
| Key | Authorization: Bearer <token>, added by the gate |
| Fixed headers | Accept: application/vnd.github+json, X-GitHub-Api-Version: 2022-11-28, User-Agent: qaldy-cloud; an app can't override them |
Use it from an app#
{ "id": "http", "actions": ["request"], "scope": "conn_k3v9…" }import { github } from '@qaldy/sdk'
const gh = github(ctx.connectors.http('conn_k3v9…'))
const { issues } = await gh.listIssues({ repo: 'acme/shop', state: 'open', limit: 20 })
await gh.createIssue({ repo: 'acme/shop', title: 'Printer is out of toner', labels: ['ops'] })
await gh.commentOnIssue({ repo: 'acme/shop', number: 42, body: 'Ordered, arrives Friday.' })
await gh.dispatchEvent({ repo: 'acme/shop', eventType: 'rebuild', payload: { reason: 'prices' } })The helper checks the input before anything is sent (repo must be owner/name) and decodes the
reply. Every call still goes through the gate as an ordinary HTTP request held to the fence above.
Start an automation from GitHub#
The other direction is a webhook: GitHub calls Qaldy when an issue is opened.
- Automations → the automation → What starts it → Webhook → Who calls it → GitHub → Set up webhook. Copy the secret (shown once).
- In the repository: Settings → Webhooks → Add webhook. Payload URL: the address shown;
content type
application/json; secret: the one you copied; events: Issues (add what the app handles). The console's example shows the same thing as onecurlor Node call. - GitHub signs each delivery with
X-Hub-Signature-256(HMAC-SHA256 over the raw body). Qaldy checks it, andX-GitHub-Deliverymakes a redelivery a repeat, not a second run.
GitHub sends a ping event first; the automation receives it like any other body, so an app
that only handles issues should ignore a body with no issue. See webhooks.md.
The catalog still lists "An issue is opened" as a planned trigger of the connector: the
webhook above works today but lives on the automation, not on the connection.
When it breaks#
| You see | Why | Do |
|---|---|---|
401 | The token expired, was revoked or mistyped | Replace the token |
404 Not Found on a repository you can open | The token isn't granted that repository (GitHub answers 404 to hide it) | Add the repository to the token |
403 Resource not accessible by personal access token | A permission is missing (Issues, Pull requests, Contents) | Edit the token's permissions on GitHub |
422 Validation Failed | The input is wrong (an unknown label, a closed discussion) | Fix the app's input |
403 with rate limit | GitHub's hourly quota | Wait, or poll less often |
Gaps#
- Not run against a live repository (hence Preview).
- No
PUTorDELETE, so no merging, no deleting, no repository settings: by design. - No GitHub App installation tokens; a personal token belongs to the person who made it, so a workspace should make it from a machine user or a shared account.