Repository navigation
feat(github): Support every GitHub App installation - #2405
Open
sentry-junior[bot] wants to merge 9 commits into
Open
sentry-junior[bot] wants to merge 9 commits into
sentry-junior[bot] wants to merge 9 commits into
Conversation
Work in progress. Webhook tests in webhook-outcomes.test.ts are not yet updated for the removed installation-ID route options. Co-Authored-By: David Cramer <david@sentry.io>
…lations Co-Authored-By: David Cramer <david@sentry.io>
Drop the unused skip log and update webhook tests for the removed installation-ID route options. Co-Authored-By: David Cramer <david@sentry.io>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Sentry Evalsjunior-behavioral
Base commit junior-guardian
Base commit junior-integration
Base commit |
This was referenced Oct 30, 2026
An App has at most one installation per account, so the owner of the target repository or organization identifies the installation. Load the App's installations once, cache them, and reload them on installation webhooks. Lease scopes now name the owner, so one token serves every repository of that account. Co-Authored-By: David Cramer <david@sentry.io>
…lations Co-Authored-By: David Cramer <david@sentry.io>
Co-Authored-By: David Cramer <david@sentry.io>
Keep a plugin-owned table of active installations by account login. installation and installation_target webhooks save, rename, and remove rows. A lookup that finds no row syncs the table from GET /app/installations at most once a minute, which fills it on first use and repairs missed webhooks. This replaces the cached installation map. Co-Authored-By: David Cramer <david@sentry.io>
Contributor
|
1 screenshot change — 1 changed · 0 added · 0 removed Review screenshots in Frameshift
|
…g sync Remove a stored installation when GitHub rejects it as removed or suspended, then sync and retry once. A sync now keeps rows that webhooks wrote while the installation list request ran. Split the issueCredential hook behavior into issue-credential.ts so credential-support.ts stays under the file length limit.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit ab6c225. Configure here.
Uninstall and suspend webhooks, rejected token mints, and syncs now clear the account login instead of deleting the row. The row stays newer than an in-flight sync list, so its insert conflicts and skips the installation.
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

The GitHub plugin only worked with the one installation in
GITHUB_INSTALLATION_ID. Repositories under other installations of the same App, such asfairsource/fair.io, were silently dropped: webhooks returned202 Ignored, and every token was minted for thegetsentryinstallation.This removes the single-installation rule as a hard cutover. A GitHub App has at most one installation per account, so Junior routes each request to the installation on the account that owns its target.
installation.idfrom the signed payload. A delivery with no installation is still ignored.junior_github_installations(migration0010_installations), maps each account login to its installation id.installationwebhooks save the row on install, permission changes, and unsuspend, and remove it on uninstall and suspend.installation_targetwebhooks update the login after an account rename.GET /app/installations, at most once a minute. This fills the table on first use and repairs missed webhooks. Suspended installations are skipped.GET /app(the App owner) is cached for an hour.owner:<login>lease scope. The owner comes from the URL (/repos/{owner}/...,/orgs/{org}/..., git URLs), from thegithub.*:owner/repooperation that host tools send, or from the GraphQLownervariable thatghsends. Remembered egress leases are keyed per scope, so a token for one installation is never reused for another. One token serves every repository of that account.github_resolvePullRequestReviewThread, now nameowner/repoin their operation, so they work for private repositories in other installations.The GitHub App is not installed on <owner>.They never fall back to another installation.GITHUB_INSTALLATION_IDandinstallationIdEnvare gone. Only the App ID, private key, and webhook secret remain. Docs,.env.examplefiles, tests, and eval fixtures are updated. The shared GitHub mock lists installations forgetsentryandacme, the owners that tests and evals write to. ThejuniorPostgres test template now applies the GitHub plugin migrations, asjunior upgradedoes in a deployment.Not in this PR: rejecting a GitHub trigger at save time when the App is not installed on its owner. That needs a small provider-neutral async check hook in core, and it should build on #2407. With the stored installations, the GitHub side is a database read. It goes in a follow-up PR. Until then, triggers for accounts without the App save but get no deliveries, which is the same as today.
Open question: confirm which account owns the prod App and that the App is installed on it. That installation is the default for reads that name no owner.
Deploy:
junior upgradeapplies the new migration. The table fills itself on the first token request. After release, removeGITHUB_INSTALLATION_IDfrom junior-prod.Refs #2404
via David Cramer.
--
View Session [Sentry]