GitHub Template Sync
Allegro supports syncing templates from a GitHub repository. When connected, templates are automatically synced whenever commits are pushed to the configured default branch.
How It Works
- An organization admin installs the Allegro GitHub App on their GitHub account or organization.
- After installation, Allegro records a sync link pointing the tenant at that installation.
- The admin selects a repository and default branch to sync from, which completes the link and registers a push webhook on the repository.
- On every push to that branch, a sync job is queued to update templates from the repository.
A single GitHub App installation can serve many repositories across many
tenants. Each tenant syncs from at most one repository, but the same repository
can be shared by several tenants. The installation, the per-tenant sync link,
and the per-repository webhook are stored separately so one installation (for
example on an alleyinteractive organization) can map different repositories to
different tenants. See
Mapping Repositories at the Platform Level.
Setting Up the GitHub App
1. Create a GitHub App
In your GitHub organization or personal account, go to Settings → Developer settings → GitHub Apps and create a new app with the following settings:
| Setting | Value |
|---|---|
| GitHub App name | Your app name (e.g. Allegro Template Sync) |
| Homepage URL | Your Allegro instance URL |
| Webhook URL | https://your-app.com/github/webhooks |
| Webhook secret | A random secret string (set as GITHUB_WEBHOOK_SECRET in .env) |
| Post installation → Setup URL | https://your-app.com/github/callback |
| Post installation → Redirect on update | ✅ Enabled |
Permissions required:
- Repository contents: Read-only
Subscribe to events:
- Push
- Installation
- Installation repositories
2. Configure Environment Variables
After creating the GitHub App, add these values to your .env:
# GitHub App credentials
GITHUB_APP_ID=<your_app_id>
GITHUB_APP_PRIVATE_KEY="<your_pem_private_key>"
GITHUB_WEBHOOK_SECRET=<your_webhook_secret>
# The installation URL shown on the GitHub Sync settings page
# Format: https://github.com/apps/<app-slug>/installations/new
GITHUB_APP_URL=https://github.com/apps/your-app-name/installations/new
GITHUB_APP_PRIVATE_KEY should be the full PEM content of the private key
generated in your GitHub App settings.
Installation Flow
When an admin visits Organization Settings → GitHub Sync and clicks Connect GitHub Repository:
- They are sent to
GITHUB_APP_URL?state={encrypted_tenant_id}on GitHub. - They install the app on their GitHub account/organization.
- GitHub fires an
installation.createdwebhook to/github/webhooks, which creates a tenant-lessGitHubAppInstallationrecord on the landlord database. - GitHub redirects the user back to
/github/callback?installation_id=XXX&state={encrypted_tenant_id}. - The callback decrypts the state to identify the tenant and records a
GitHubRepoSyncrow linking that tenant to the installation (with no repository selected yet). - The admin is redirected to the GitHub Sync settings page where they select the repository and default branch.
- Upon submitting the form, the sync link is completed, a push webhook is registered on the repository, and an initial sync is queued.
The Setup URL in your GitHub App settings must be set to
https://your-app.com/github/callback. Without this, the installation cannot be
linked to the tenant.
Mapping Repositories at the Platform Level
The self-serve flow above always returns the admin to the tenant they started from, so it can only ever connect one repository to that one tenant. To map several repositories from a single shared installation to several tenants — for example, when one organization's installation hosts a separate template repository per tenant — super admins use the landlord tenant dashboard.
From Tenants in the landlord navigation, open a tenant's detail page. The
GitHub Template Sync section lists every known installation; pick an
installation, choose one of its repositories, set the branch, and connect. This
creates the same GitHubRepoSync link as the self-serve flow, without a GitHub
round-trip, so different repositories under one installation can be assigned to
different tenants.
Installations only appear here after the GitHub App has been installed on the
organization (which fires the installation.created webhook). There is no
manual way to register an installation ID.
Sync Process
Template sync is handled by the SyncGitHubTemplates job. It:
- Fetches each top-level directory containing an
index.htmlfrom the repository at the configured branch (with optionalindex.css,index.js, andtemplate.json). - Creates or updates corresponding
Templaterecords (matched bygithub_path). - Force-deletes synced templates no longer present in the repository.
Syncs are triggered:
- Automatically when a push arrives on a configured default branch (via webhook). A push to a shared repository fans out: the job is dispatched once for every tenant whose sync link points at that repository and whose branch matches.
- Manually via the Sync Now button on the GitHub Sync settings page (rate-limited to once per minute).
Disconnecting
Admins can disconnect GitHub sync from Organization Settings → GitHub Sync → Disconnect. This:
- Deletes the tenant's
GitHubRepoSynclink. - Deletes the repository's push webhook only if no other tenant still syncs that repository (the webhook is reference-counted per repository).
- Removes the
sync_sourcefrom all templates, making them editable again.
Templates are not deleted when disconnecting.
Disconnecting a tenant from the landlord dashboard removes the sync link and reference-counted webhook the same way, but leaves that tenant's templates untouched.
When the GitHub App is uninstalled (installation.deleted) or loses access to a
repository (installation_repositories removed), Allegro tears down the
affected sync links and webhooks but never deletes synced templates — they
remain in each tenant exactly as they were.
Database Schema
All three tables live on the landlord database. The installation, the per-tenant sync link, and the per-repository webhook are stored separately so one installation can map many repositories to many tenants.
github_app_installations
The GitHub App installation itself — one row per GitHub account/organization.
| Column | Type | Description |
|---|---|---|
installation_id | bigint (unique) | GitHub's installation ID |
account_login | string (nullable) | GitHub account/org login name |
github_repo_syncs
The tenant ↔ repository link — one row per tenant. repository and
default_branch are null between installing the app and selecting a repository.
| Column | Type | Description |
|---|---|---|
tenant_id | bigint (unique) | The linked Allegro tenant |
installation_id | bigint | GitHub installation this link uses |
repository | string (nullable) | Full repository name (e.g. org/repo) |
default_branch | string (nullable) | Branch to sync from |
last_sync_at | timestamp (nullable) | Time of last successful sync |
last_sync_hash | string (nullable) | Commit SHA of last sync |
last_sync_errors | json (nullable) | Errors from the last sync attempt |
github_repo_webhooks
The push webhook registered on a repository — one row per
(installation, repository), shared by every tenant syncing that repository and
reference-counted on disconnect.
| Column | Type | Description |
|---|---|---|
installation_id | bigint | GitHub installation that owns it |
repository | string | Full repository name (e.g. org/repo) |
webhook_id | bigint | GitHub's webhook ID on the repository |