GitHub Sync
Connect a GitHub repository to a connection and CH-UI imports your models from it: .sql files in the repo become models in CH-UI, and every sync keeps them up to date. Git is the source of truth: edit in your repo, merge to your branch, and CH-UI follows.
GitHub Sync is a Pro feature. Without an active license the endpoints return 402.
How it works
Section titled “How it works”- Your branch is the truth. The
.sqlfiles under the configured path define your models. - Sync is one-way (pull). CH-UI fetches the branch, parses each model file, and creates, updates, or deletes models to match the repo.
- Only git-managed models are touched. Models imported from GitHub are tracked with a
githubsource; models you created by hand in the UI are never modified or deleted by a sync. GitHub-managed models are read-only in the model editor. - One commit per sync. CH-UI resolves the branch to a commit SHA once and reads the tree and every file at that SHA, so a push during a sync never mixes two commits.
- Unchanged commits are skipped. CH-UI remembers the last commit that synced without errors and does nothing if the branch hasn’t moved. A sync with errors does not record its commit, so the next sync retries it.
edit .sql ──▶ merge to branch ──▶ push webhook (or Sync now) ──▶ CH-UI pulls and updates modelsGitHub Sync is configured per connection in Admin → GitHub (admin only).
- Create a token. A GitHub fine-grained personal access token with read access to the repository’s contents is enough. The token is encrypted at rest with your server’s
app_secret_key. - Configure the integration. Repository as
owner/repo, branch (defaults tomain), and the path inside the repo where model files live (defaults tomodels/). - Run the first sync. Click Sync now and check the sync log. It reports created, updated, deleted, and unchanged counts plus the commit SHA.
Auto-sync on push
Section titled “Auto-sync on push”To sync automatically when the branch changes, add a push webhook in your repository settings pointing at:
https://your-ch-ui-server/api/github/webhook/{connectionId}The webhook URL for the current connection is shown on the Admin → GitHub page.
A webhook secret is required. CH-UI verifies GitHub’s X-Hub-Signature-256 header on every delivery and rejects requests that don’t match. Until a secret is saved for the connection, every webhook request is refused with 403, so a push never triggers a sync from an unauthenticated caller.
- Generate a random secret of at least 16 characters, for example
openssl rand -hex 32. - Paste it into Webhook secret on the Admin → GitHub page and save (or send it as
webhook_secretwithPUT /api/admin/github/{connectionId}). It is encrypted at rest with your server’sapp_secret_key. Leave the field empty on later saves to keep the stored one. - In the GitHub webhook settings, set Content type to
application/json, paste the same value into Secret, and pick Just the push event.
Payloads are capped at 5 MiB. Only one sync runs per connection at a time: a push that arrives while a sync is running is folded into a single follow-up sync, and Sync now returns 409 until the running sync finishes.
Model file format
Section titled “Model file format”A model is a .sql file, optionally starting with a YAML frontmatter block:
---materialization: table # view (default) or tabletarget_database: analytics # default: defaulttable_engine: MergeTree # tables only, default: MergeTreeorder_by: (event_date, id) # MergeTree-family tables only, default: tuple()description: Daily rollup of events---SELECT toDate(timestamp) AS event_date, count() AS eventsFROM eventsGROUP BY event_dateThese five keys are the only ones read. The filename (minus .sql) becomes the model name, so it must be a valid identifier (^[a-zA-Z_][a-zA-Z0-9_]*$); a file like daily-events.sql is reported as an error. Any materialization other than view or table is an error too. Files without frontmatter are imported as views against the default database.
Reference other models with $ref(model_name), as in the editor. See Models.
Sync semantics
Section titled “Sync semantics”| Repo state | CH-UI result |
|---|---|
New .sql file |
Model created (source: github) |
| File content or frontmatter changed | Model updated |
| File removed | Model deleted (git-managed models only) |
| File unparseable or invalid | Reported in the sync log; an existing model for that file is kept unchanged |
| Repository tree too large for one GitHub response | Sync fails; point the path at a smaller folder |
Every sync (manual or webhook) is recorded in the sync log with its trigger, counts, commit SHA, and any per-file errors.
Disconnecting
Section titled “Disconnecting”Disconnect on the Admin → GitHub page removes the integration and its token. Synced models stay in CH-UI; they just stop following the repo.
