Vibe Coding
Back to Multica

Multica / Notifications and Integration

GitHub integration

Connect to GitHub App once, and then if the issue number (such as MUL-123) is written in the branch name, title or body of the PR, it will automatically be linked to that issue - the issue will automatically be transferred to Done when the PR is merged.

GitHub integration key concepts infographic
GitHub integration key concepts infographic

Overview

Connect a GitHub account or organization at once in Settings → GitHub. Any subsequent PR will be automatically associated with that issue as long as the issue number (such as MUL-123) appears in the branch name, title or text, and will appear in the Pull requests block on the right side of the issue details page - when the PR is merged, the issue will automatically be converted to Done.

There is no per-issue configuration, and the entire process is "number-driven".

What does the integration do?

Just mirror the PR itself. Commits, branches without open PRs, and CI check status are not included in the database - the integration intentionally maintains narrow boundaries.

Appearance Behavior
Settings → GitHub Workspace owner / admin sees the GitHub tab, which contains the main switch, Connect GitHub button, and function switches (PR sidebar, Co-authored-by, auto-link). Clicking Connect will open the GitHub App installation page; after installation, jump back to the GitHub tab.
Issue details sidebar → Pull requests Lists all PRs automatically associated with this issue, including title, repository, status (Open / Draft / Merged / Closed) and author. Click a line to jump to GitHub.
Webhook (backend) Each time the pull_request event is triggered: upsert PR line → scan the issue number inside → (re)establish the link. Idempotent - re-delivery will not produce duplicate records.
Merge automatically changes status When PR is converted to merged, all related issues whose status is not Done / Cancelled will be pushed to Done. The timeline is recorded with source as github_pr_merged.

How do the numbers match?

Webhook extracts numbers from three fields, in the order: PR head branch → PR title → PR body. Matching rules:

  • Case insensitive - mul-123, MUL-123, Mul-123 all match
  • Boundary - \b on the left and only numbers on the right to avoid accidentally grabbing v1.2-3, email address, etc.
  • Restrict to this workspace - only matches the issue prefix of this workspace. In a workspace where the prefix is MUL, the PR will not match FOO-1, even if the number collides with another issue.
  • Automatic deduplication - Closes MUL-1, MUL-1 is only associated once

A PR can reference multiple issues at the same time. For example, Closes MUL-1, MUL-2: PR is associated with two issues at the same time. When merging, both issues will be transferred to Done.

Rules for Merge to automatically convert to Done

When the PR's merged field is turned into true, the associated issues are evaluated one by one:

Issue Current Status Result
done unchanged (already the final state)
cancelled unchanged - canceled is a signal for the user to explicitly give up the work, and the integration will not cover it
Others (todo / in_progress / in_review / blocked / backlog) Convert to done

PR Closed but not merged - Only the status of the PR card is updated to Closed, and the issue status remains unchanged. "Close but don't merge" semantics vary from team to team, and Multica doesn't make the decision for the user.

The actor whose state changes is system. Members who have subscribed to the issue will receive an inbox notification, which is the same as when members manually change the status.

What situations will not be automatically associated?

  • Number in Commit message——Only scan the branch/title/body of the PR. A commit message writing MUL-123: fix login will not trigger correlation unless the same string also appears in the PR title or body.
  • Number in PR comment——Only scan the PR’s own metadata, and subsequent GitHub comments will not be read.
  • PR in the repository where the App is not installed - Without the App, Multica cannot receive the webhook
  • Manually associate PR to issue - There is no such UI for the time being. If your agreement puts the number in a place that Multica will not scan, please put it in the PR title or text instead.

Disconnect

There is no installation list in Settings → GitHub - existing installations are managed directly on GitHub:

  • Uninstall from GitHub - Uninstall Multica App at https://github.com/settings/installations for individuals and https://github.com/organizations/<org>/settings/installations for organizations. Multica deletes the row immediately after receiving the installation.deleted webhook; any open Settings tab is updated in real time without refreshing.
  • Multica's disconnection is admin only - The Disconnect control on the GitHub tab is not displayed for non-admins; Disconnect is still available when the main switch is turned off, making it convenient for admins to close the function with one click and then clean up the connected installation separately.

After disconnecting, the mirrored PR rows remain in the database - the historical issue sidebar can still show the associated PR at that time, but new webhook events from this installation are no longer accepted.

Permissions and visibility

  • Connect / Disconnect requires workspace owner or admin. Ordinary members can see the card description but not the Connect button
  • Pull requests The sidebar is visible to all members who can see the issue - the same permissions as other parts of the issue details page
  • GitHub App applies for read-only permissions for PR and Metadata. Multica never pushes commits, comments, or status checks to GitHub

Self-Host configuration

If you are on Multica Cloud, the integration is already configured - skip this section.

Self-Host requires: building a GitHub App, pointing to your server, and setting two environment variables. The complete process is as follows.

1. Create a GitHub App

Go to one of the following pages:

  • Personal account → https://github.com/settings/apps/new
  • Organization → https://github.com/organizations/<org>/settings/apps/new

Fill in the following table:

field value
GitHub App name Any recognizable name, such as Multica or Multica (staging)
Homepage URL Your Multica frontend, e.g. https://multica.example.com
Callback URL Leave blank - this integration does not use OAuth user identities
Setup URL https://<api-host>/api/github/setup. Check "Redirect on update"
Webhook → Active Enable
Webhook URL https://<api-host>/api/webhooks/github
Webhook secret Generate a long random string (e.g. openssl rand -hex 32). This value will also be filled in the env of step 2
Permissions → Repository → Pull requests Read-only
Permissions → Repository → Metadata Read-only (required)
Subscribe to events Check Pull request
Where can this GitHub App be installed? Optional. For single-organization deployment, it is recommended to select Only on this account

After clicking Create GitHub App, write down two things from the details page:

  • The tail of the top public link is the slug. https://github.com/apps/multica-acme → slug = multica-acme
  • The webhook secret you just generated (GitHub won't let you read this value again - save it now)

**Webhook secret ≠ Client secret. ** The two fields are next to each other on the App settings page. Webhook secret is used to sign the pull_request payload, which is what Multica needs; Client secret is used by OAuth and has nothing to do with this integration. Confusing the two will result in the weird symptom of "every webhook is 401 invalid signature".

2. Configure environment variables

On the API server:

GITHUB_WEBHOOK_SECRET=<the webhook secret you just generated>

# Optional but recommended configuration - get the associated account name directly when the installation is completed, instead of waiting for the first webhook to refresh:
GITHUB_APP_ID=
GITHUB_APP_PRIVATE_KEY=<Full PEM block, including BEGIN/END lines>

GITHUB_APP_SLUG and GITHUB_WEBHOOK_SECRET are required. Any one is missing:

  • The Connect GitHub button in Settings will be disable and a "not configured" prompt will be displayed.
  • /api/webhooks/github directly returns 503 github webhooks not configured——Multica refuses to process events when the secret is not configured, and there will be no security pitfall of "accepting webhooks without a secret"

GITHUB_APP_ID and GITHUB_APP_PRIVATE_KEY optional. After matching, the setup callback can use App JWT authentication to call GitHub /app/installations/{id}, and get the real organization name/user name the moment the installation is completed. If not, the connection card will first display Connected to unknown. When GitHub's installation.created webhook arrives (usually within a few seconds), Multica will refresh the row and use realtime push to update the Settings page without manual refresh. The private key is generated from the App settings page Private keys → Generate a private key. Paste the entire PEM (including the two lines -----BEGIN/END RSA PRIVATE KEY-----) into env and keep the newlines.

FRONTEND_ORIGIN must also be set (any production self-host will already have it set) - use this to jump the user back to FRONTEND_ORIGIN/settings?tab=github` after the setup callback.

After setting env, restart the API.

3. Execute migration

The integration table is in migration 079_github_integration. If you are upgrading an existing deployment:

make migrate-up

Three tables will be created: github_installation, github_pull_request, issue_pull_request. All three tables cascade follow the workspace - deleting the workspace will automatically clean it up.

4. Connect in UI

To Multica:

  1. Open Settings → GitHub as owner or admin
  2. Click Connect GitHub, GitHub will open in a new tab
  3. Select the repository to be authorized and click Install4. GitHub jumps back to <api-host>/api/github/setup, and then jumps to FRONTEND_ORIGIN/settings?tab=github&github_connected=1` after dropping the library.

Then open a PR in any repository/title/text with the issue number of this workspace - you will see the Pull requests block on the details page of the corresponding issue within a few seconds.

5. Use curl to self-check

If the first PR event in GitHub's Recent Deliveries reports 401 invalid signature, it means that the secrets on both sides are inconsistent. Bypassing GitHub and testing the server directly is the fastest way to locate it:

SECRET="<The value you filled in for GITHUB_WEBHOOK_SECRET>"
BODY='{"zen":"test"}'
SIG=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "$SECRET" -hex | awk '{print $NF}')
curl -i -X POST https://<api-host>/api/webhooks/github \
  -H "X-Hub-Signature-256: sha256=$SIG" \
  -H "X-GitHub-Event: ping" \
  -H "Content-Type: application/json" \
  -d "$BODY"
HTTP Status Meaning Amendment
200 {"ok":"pong"} The secret loaded by the server is consistent with your $SECRET - the secret from GitHub is wrong Edit App → Webhook secret field Paste the same valueMust click Save changes (not clicking Save means no changes) → Redeliver
401 invalid signature The secret loaded by the server is not the one you thought Enter the container to confirm that the env actually takes effect (for example, kubectl exececho -n "$GITHUB_WEBHOOK_SECRET" | wc -c), redeploy
503 github webhooks not configured GITHUB_WEBHOOK_SECRET is empty in the process Match env and restart the API

Known limitations

A few boundaries that haven’t been made yet:

  • Manual link UI is not available yet - The only way to associate a PR is to write the issue number to the PR branch/title/body
  • Do not read CI / check status - only mirror the PR itself, the build status, reviewer comments, and reviewer list are not connected to Multica
  • No workspace level merge → status mapping configuration - the default is fixed to merged → done (except canceled). Configurable mapping is subsequent iteration
  • When there are multiple PRs for the same issue, the merge behavior is more aggressive - When both PRs reference MUL-123, the first merge will convert the issue to Done. The optimization of "waiting for all related PRs to be resolved before advancing the issue status" is already being done.

Next step

  • Issues - the source of the issue number (MUL-123) cited by the PR
  • Workspace —— The setting location of the workspace issue prefix
  • Environment Variables - Complete env list, including the GitHub variables mentioned above