Source Control
Zenfra reads your infrastructure code from a Git provider through a source control integration, managed under Integrations in the sidebar. Adding, changing and removing integrations requires the Admin role (Only organization administrators can add integrations.).
Supported providers
| Provider | Where it runs | How to connect |
|---|---|---|
| GitHub | GitHub.com | GitHub > Add Account installs the Zenfra GitHub App; choose the repositories or organizations it may access. |
| GitHub Enterprise Server | Inside your network | GitHub > Add via connector, through a VCS Connector. |
| GitLab | GitLab.com, or any GitLab reachable from the internet | GitLab > Add Account with Hosting GitLab.com or reachable from the internet, the instance Base URL and a Personal access token with the read_api and read_repository scopes. |
| GitLab | Self-managed, inside your network | Hosting Self-managed, inside your network, through a VCS Connector. |
| Bitbucket Data Center | Inside your network | Through a VCS Connector only. Bitbucket Cloud is not supported. |
| Azure DevOps Server | Inside your network | Through a VCS Connector only. Azure DevOps Services is not supported. |
A stack can also point at a Raw Git URL instead of an integration: a public HTTPS repository. Raw Git sources have no push or pull-request triggers.
Managing an integration
Each provider page lists its connected accounts with a status badge (Connected, Error, Pending or Disabled) and a menu with Verify connection, Enable / Disable and Remove. Open an integration for its detail page:
- Verify connection checks the credentials and records when they last worked.
- Sync Repositories discovers the repositories the integration can see (
Synced {n} repositories ({new} new, {updated} updated)). Each repository has an Enabled switch; only enabled repositories can be selected as a stack's source. - Connection shows
DirectorVia connector {name}with the connector's health. While the connector is offline, repository sync and browsing fail until it reconnects; while it is degraded, browsing works but archive downloads, and therefore runs, do not.
Removing an integration is not guarded by stack usage. Any stack using it loses its source and needs its source selected again. A connector-backed integration also cannot be re-pointed at another connector; removing it and creating a new integration is the only way to reconnect.
How source is used in runs
- A run is pinned to a commit. When a run is created, the branch is resolved to a commit, and both plan and apply use that commit even if the branch moves in between. See Source commit.
- The whole repository is delivered to the worker, and the tool runs in the stack's project root (the Path field, repository root when empty). Files above the project root, such as a local module at
../modules/vpc, are reachable. - The project root must contain a configuration file directly: a
.tfor.tf.jsonfile (OpenTofu 1.8 and later also accept.tofuand.tofu.json). A root whose only Terraform files sit in subdirectories is refused. A wrong root fails the run in the Preparing phase withproject root "<path>" does not exist in the repositoryorcontains no terraform configuration file.
Triggers
Runs start from four sources. The Runs tab of a stack can filter on the first three (Manual, Push, Pull Request); drift runs carry a Drift badge.
- Manual: the stack's Trigger menu.
- Push: enable Push Trigger under Automation Triggers in the stack's source settings. A push runs the stack when a changed file is under its project root or matches one of its Project globs. Globs add paths outside the project root, for example
modules/**for shared modules; with no project root, every push to the branch already triggers the stack and globs add nothing. When the provider cannot say which files changed (very large pushes, pushes with no commits), the stack triggers rather than skips. For self-managed GitLab behind a connector, push events reach Zenfra through the connector's webhook listener (see Optional extras); the connector path relays GitLab push events only today. - Pull Request: on GitHub.com, through the GitHub App, a pull request whose base is the tracked branch creates a proposed (plan-only) run. Pull-request runs are not scoped by project root or globs. Other providers do not deliver pull-request events today.
- Drift: a drift schedule on the stack.
Push triggers became project-root scoped in September 2026; stacks that relied on pushes outside their root need globs. See the September 2026 Upgrade Notes.