wikis / Multica / wiki / concepts / vcs-integration.md view as markdown report a mistake
Definition
VCS integration is how Multica links pull/merge requests to issues, mirrors CI status, and auto-completes issues on merge. GitHub is supported on both Multica Cloud and self-hosted deployments; self-hosted Forgejo, Gitea, and GitLab are supported only on self-hosted Multica, and a workspace can connect any combination of these providers alongside GitHub. Separately, and needing no provider configuration at all, agents open pull requests directly against a repository's own Git host using the daemon runtime's own Git credentials.
How It Works
GitHub integration. A workspace owner or admin opens Settings → GitHub, turns on the master switch, clicks Connect GitHub, and authorizes an account/organization and a set of repositories via GitHub's App install flow. The GitHub App only reads the authorized repositories' PR events — it never pushes commits, comments, or status checks. Three sub-switches control behavior: PR sidebar (show linked PRs on the issue), Co-authored-by (adds Co-authored-by: multica-agent <github@multica.ai> to agent commits), and Auto-link PRs (detect issue identifiers). A fourth item, PR card → CI & mergeability, pulls an authenticated GitHub API snapshot per linked PR to show CI status and mergeability, and requires GITHUB_APP_ID and GITHUB_APP_PRIVATE_KEY to be configured — without them, PRs still auto-link and merge-to-Done still works, just without the CI/mergeability display.
Self-hosted Git providers (Forgejo/Gitea/GitLab). This section only appears once a server operator sets MULTICA_VCS_INTEGRATION_ENABLED=true and a MULTICA_VCS_SECRET_KEY (base64, 32 bytes) on a self-hosted deployment; it is not offered on Multica Cloud. Unlike GitHub's App model, each of these providers is connected per-workspace with an access token (Forgejo/Gitea: Settings → Applications; GitLab: a personal/group/project token with read_api) plus a registered webhook — both the token and webhook secret are encrypted at rest. Connecting shows a webhook URL and a webhook secret once; the operator manually registers the webhook on the repository/organisation/group in the provider's UI (Forgejo/Gitea: trigger on Pull Request + Commit Status; GitLab: Merge request events + Pipeline events). Every webhook delivery is authenticated against the stored secret.
Linking a PR to an issue. Put the issue identifier (e.g. MUL-123) in the branch name or PR/MR title — matching is case-insensitive and scoped to the current workspace's issue prefix, and one PR can link to multiple issues. If the identifier only appears in the body, a GitHub-style close intent is required: Closes MUL-123, Fixes MUL-123, or Resolves MUL-123 (self-hosted providers use the same closing-keyword convention). A reference-only mention like "Related to MUL-123" does not count as a working PR link, and commit messages / PR comments never trigger linking.
Merge-to-Done. A merged PR only moves its issue to Done when all of these hold: (1) at least one merged linked PR used a close intent immediately followed by the identifier (Closes login MUL-123, with words in between, does not count); (2) the issue has no other working PR still Open or Draft; (3) the issue is not already done or cancelled. Titling or branching a PR with just MUL-123 (no close intent) links it but never auto-completes the issue on its own, and a PR closed without merging never completes the issue.
What gets mirrored on the issue's PR sidebar: repository, number, title, author, state (Open/Draft/Merged/Closed), added/deleted lines and changed-file count, CI status (all passed with a count, some failed naming the checks, or in-progress — "no checks configured" is never shown as passing), and mergeability (mergeable only on a clean GitHub-reported merge state, or conflicting/blocked/behind). If GitHub is briefly unreachable, the card keeps the last snapshot and marks it stale rather than going blank; merged/closed PRs stop showing CI or mergeability.
Agents opening PRs. This needs no provider configuration in Multica at all: agents check out repositories inside the daemon runtime and push branches / open PRs using whatever Git credentials the runtime host already has (SSH deploy key, a token in the host's Git credential helper, etc.). Repository checkout works with any Git URL, so any provider works here even without a VCS integration connected.
Key Parameters
MULTICA_VCS_INTEGRATION_ENABLED— self-hosted-only master switch for Forgejo/Gitea/GitLab; the section stays hidden until settrue.MULTICA_VCS_SECRET_KEY— base64-encoded 32-byte key encrypting self-hosted provider tokens and webhook secrets; required alongside the enable flag.MULTICA_PUBLIC_URL— lets Multica show a ready-to-paste webhook URL for self-hosted providers; without it you must prepend your own origin to the shown webhook path.GITHUB_APP_SLUG,GITHUB_WEBHOOK_SECRET,FRONTEND_ORIGIN— required for the GitHub connect button and webhook endpoint to work at all.GITHUB_APP_ID,GITHUB_APP_PRIVATE_KEY— required only for the CI/mergeability snapshot; PR mirroring and merge-to-Done work without them.- Feature switches per GitHub workspace: GitHub integration (master), PR sidebar, Co-authored-by, Auto-link PRs.
- Issue identifier format:
MUL-123-style, workspace-prefix-scoped, case-insensitive match in branch/title; body mentions need a close-intent keyword.
When To Use
- Connect GitHub when repositories live on GitHub, for either Cloud or self-hosted deployments.
- Connect Forgejo/Gitea/GitLab only on a self-hosted Multica deployment reaching an internal Git instance — this path does not exist on Cloud.
- Rely on agents opening PRs directly whenever the goal is just "let the agent push code and open a PR" without needing PR-linking, CI mirroring, or merge-to-Done in Multica's UI.
- Use a close-intent keyword (
Closes MUL-123) whenever you want the issue to auto-complete on merge; a bare identifier in the title/branch is enough only to establish the link, not to close the issue.
Risks & Pitfalls
- A webhook secret (self-hosted providers) or App private key is shown/generated once — losing it means reconnecting.
Closes login MUL-123(words between the keyword and identifier) does not trigger merge-to-Done — the identifier must immediately follow the close-intent keyword.- A body-only mention without a close keyword (e.g. "Related to MUL-123") never shows as a working PR and never triggers Done.
- Disconnecting GitHub in Multica does not uninstall the App on GitHub's side — new events stop flowing but the App keeps running until removed from GitHub's own installation settings.
- Without
GITHUB_APP_ID/GITHUB_APP_PRIVATE_KEY, the PR card silently shows no CI/merge state — this is a graceful degradation, not an error, and easy to mistake for a broken integration. - Mismatched webhook secrets between GitHub and the API produce
401 invalid signatureon every delivery. - "PR sidebar" off only hides the display block; it does not disconnect anything or stop mirroring underneath.
Related Concepts
- communication — comments and inbox notify on issue-status changes triggered by merges.
- chat integrations
- self hosting
- configuration
Sources
- raw/github_doc-apps-docs-content-docs-vcs-integration-mdx.md
- raw/github_doc-apps-docs-content-docs-github-integration-mdx.md
