Git integration
Connect GitHub, GitLab, Azure DevOps, Bitbucket, Gitea, Forgejo or plain SSH - commits and pull requests link themselves to tickets, step by step.
Connect a repository and orboto keeps tickets and code in sync: commits and pull requests that mention a ticket key appear on the ticket automatically, and pull-request state (open / merged / closed) updates itself as the PR progresses. All communication is HTTPS REST - orboto never clones the repository or pushes to it, and no SSH access to your Git host is required (except for the dedicated SSH-poll connection type, covered below).
Setting this up is two separate jobs, done by two different people in a larger org:
- Workspace setup (Admin -> Git integration) - a one-time, instance-wide step where a workspace admin registers the credentials every project's connections will reuse: a GitHub App and/or a GitLab OAuth application.
- Per-project connection (each project's own Settings -> Git tab) - a project owner connects that specific project's repository, using either the workspace app from step 1 or a manually pasted token.
You need step 1 done (by an admin) before step 2 becomes the easy path; step 2 also works entirely on its own with a manual token, for any provider, even if nobody has set up an App at all.

Step 1 - workspace setup (Admin -> Git integration)

Open Admin -> Git integration. The page has two independent sections
- set up either or both, depending on which Git hosts your teams actually use.
GitHub - the one-click App flow
Click Connect GitHub App. This does NOT ask you to fill in any fields yet - it takes you straight to github.com to confirm the App's name. GitHub then redirects you back to orboto, which automatically:
- fills in the App's required permissions and webhook URL from a manifest orboto generated for you,
- receives and stores the App ID, private key and webhook secret GitHub issued,
- shows a success banner with the App's slug once it lands back on this page.
You never see or copy an App ID, a PEM private key, or a webhook secret by hand with this path - that's the entire point of it.
If an App is already configured, the same button reads Re-register GitHub App instead - clicking it replaces the stored credentials with a freshly generated App. The OLD App registration on github.com is left in place untouched; if you don't need it anymore, go uninstall it manually on GitHub's side (orboto has no way to reach in and remove it for you).
Advanced: configure manually is a collapsed panel below the App card, for anyone who'd rather register the GitHub App by hand on github.com and paste the results in themselves:
- GitHub App ID - the numeric ID from the App's registration page.
- GitHub App slug - the URL-safe handle from the App's URL (used to build the install link shown to project owners).
- GitHub App private key (PEM) - paste the full
.pemfile GitHub gave you when you created the App. It's shown as a large text box; after saving, the field goes blank again (the stored value is masked, not re-displayed) - pasting a new value and saving replaces it, leaving it empty and unsaved keeps the old key. - GitHub App webhook secret - the shared secret you set on the App's webhook config on GitHub's side. Same masked-on-read behavior.
- Disable GitHub App flow - a checkbox. When on, the GitHub App card disappears from every project's "Add connection" picker workspace-wide, even though the credentials stay saved. Use this during a planned migration or an incident, without losing the configuration.
After either path, click Validate connection. orboto pings GitHub with the stored credentials and, on success, shows the App's name, its owner (with account type), and a link to the App's page on github.com - proof the credentials actually work, not just that they were saved.
If you are a super-admin, a third control appears once an App is configured: Sync installations from GitHub. GitHub lets an organization admin install your App directly from github.com, bypassing orboto entirely - this button reconciles against GitHub's own installation list, adding any installation orboto doesn't know about yet and deactivating the connections for any installation that was removed on GitHub's side. The result panel lists every installation it found, with a "suspended" tag on any GitHub has itself suspended.
GitLab - the guided manual flow
GitLab has no equivalent one-click App-creation flow, so this section walks you through the manual steps instead of doing them for you:
- Open GitLab - a button deep-links to GitLab's own application-settings page (your self-hosted instance's base URL if you set one in the field below, otherwise gitlab.com).
- On that GitLab page, register a new OAuth application. Two copy
buttons on the orboto page give you the exact values to paste:
- Redirect / Callback URL - must match exactly, or GitLab's OAuth handshake will refuse orboto's callback.
- Scopes - copy this exact string into GitLab's scopes field.
Read-only connections need
read_api+read_repository; branch creation from a ticket needsapi+write_repository. Mark the application Confidential on GitLab's side - this is required for the OAuth flow to work as a server-side integration rather than a public client.
- Back on orboto, paste GitLab's Application ID and Application Secret into the two fields at the bottom of this section, plus the GitLab base URL if you're on a self-hosted instance (leave empty for gitlab.com) and the Redirect URI if you need to override the default.
- A Disable GitLab OAuth flow checkbox works the same way as the GitHub one - hides the card everywhere without discarding the saved credentials.
There's no "validate" button on the GitLab side; the first project that connects through it will surface any credential problem immediately, at which point re-checking the pasted Client ID/Secret against GitLab's application page is the fix.
Step 2 - connecting one project's repository

Open the project you want to connect, go to Settings -> Git -> Add connection. A three-option picker appears:
-
GitHub App - shown as the recommended option (with a "recommended" tag) once a workspace App is configured; greyed out with an explanation if it isn't. Clicking Continue to GitHub takes you to GitHub's own installation screen. Important: on that screen, choose "Only select repositories" and pick just the ones this project actually needs - GitHub defaults to "All repositories", which orboto cannot narrow for you from its side; a small in-page note reminds you of this right before you leave for GitHub. Once you return, the repository is connected with no token to manage - GitHub issues short-lived installation tokens on demand instead of a long-lived secret sitting in orboto.
-
GitLab OAuth - shown once a workspace OAuth app is configured; authorize once, orboto mints short-lived tokens automatically after that.
-
Manual token - works for every provider: GitHub, GitLab, Azure DevOps / TFS, Bitbucket Cloud, Bitbucket Server, Gitea, Forgejo, or a read-only SSH poll connection. Picking a provider here shows a Get a token button that deep-links straight to the right token-creation page on that provider (GitHub's token-creation form pre-filled with the right scopes, GitLab's personal-access-token page, Azure DevOps's PAT settings for the org you type in, Bitbucket's App Passwords page, or the Forgejo/Gitea applications page on your self-hosted base URL). Self-hosted providers (GitLab self-managed, Azure DevOps, Bitbucket Server, Gitea, Forgejo) additionally need that instance's base URL; Azure DevOps also needs the org/project name since PATs there are org-scoped.
The SSH poll option is different in kind from the rest: there is no token at all. orboto generates an ED25519 keypair itself when you save the connection and shows you the public key to add as a deploy key (or to your server's
authorized_keys) on the repository's side. Use this for a self-hosted Git server that has no webhook support and no API to poll - orboto instead periodically checks the remote HEAD over SSH. It only supports read-only, poll-based updates (no branch creation, no webhook).
Every connection - regardless of provider or path - defaults to read-only. Flip the read-only switch off, and supply a token with write scope, if you want to let tickets create branches directly from orboto. If the token you provide has webhook-admin scope on the provider's side, orboto installs the inbound webhook automatically when you save; otherwise the connection screen shows you the exact URL and secret to paste into the provider's webhook settings by hand.
How ticket linking actually works
Mention a ticket's key anywhere in a commit message or a pull-request
title - ACME-42: fix the flux capacitor - and that activity appears on
ticket ACME-42, tagged with its current state (open, merged, closed for a
PR; just "committed" for a plain commit). The activity feed on the ticket
is append-only for commits, but a pull request's entry updates itself
in place as the PR's state changes - you see one PR row that flips from
"open" to "merged", not a new row each time something changes on it.
Connection health
Each connection on the project's Git tab shows a health badge with two independently-tracked signals, refreshed periodically in the background:
- Outbound reachable - can orboto currently reach the provider's API using the stored credentials.
- Inbound delivering - are webhook events actually arriving from the provider.
Hovering the badge shows both signals explicitly (a checkmark or cross for each), the last time orboto probed, and - on failure - the specific error orboto received. This is what makes a silently-broken integration visible: a connection can look "fine" in the connection list while quietly failing, and this badge is where that shows up first, before someone notices commits aren't appearing.
Troubleshooting
- Health badge shows outbound failing - the token expired, was revoked, or lost scope on the provider's side. Regenerate it via the "Get a token" deep-link and update the connection; for a GitHub App connection specifically, re-register the App (Admin -> Git integration) or re-check its installation via Sync installations.
- Health badge shows inbound not delivering - the webhook was deleted or its secret rotated on the provider's side, outside orboto. If the token has webhook-admin scope, removing and re-adding the connection reinstalls the webhook automatically; otherwise re-paste the URL and secret manually into the provider's webhook settings.
- Commits aren't appearing on a ticket even though the message looks right - ticket-key matching is case-sensitive and must match the project's actual key exactly; also confirm the connection covers the exact repository the commit landed in, not a fork of it (a fork is a separate repository as far as the webhook is concerned).
- A GitHub org installed the App directly from github.com and nothing shows up in orboto - run Sync installations from GitHub (Admin -> Git integration, super-admin only) to pick it up.
- The GitLab OAuth card is greyed out on a project's Add-connection screen - the workspace-level Client ID / Secret haven't been set yet; a workspace admin configures them under Admin -> Git integration first, or you fall back to the Manual token path for GitLab in the meantime.
- An SSH-poll connection never updates - check the public key orboto
generated was actually added as a deploy key (or to
authorized_keys) on the target server, and that the server allows the SSH user/port you configured; there's no webhook to fall back on for this connection type, so a wrong key silently means "never polls successfully".