Every pull request goes through a gate you control.
contribution-checker is a self-hosted GitHub App. When someone opens a pull request on a linked repository, it decides whether that author is allowed to contribute. If they are not, it closes the pull request and leaves a comment pointing at your application form. When you approve them, it reopens the pull request.
AGPL-3.0. Runs on your own Postgres.
contribution-checker / decision
Approved contributor for Acme Router.
Open an application for Acme Router to unblock this PR.
Sign the Acme Router CLA to unblock this PR. Your PR stays open and we'll re-check automatically once signed.
Denied until 2026-09-01.
Require this check in branch protection and an unapproved contributor cannot merge.
What lands on the pull request
Three things, at most: a comment, a label, and a status check. Everything below is the real output, rendered by the same functions the webhook calls.
Hi @octocat! Thanks for the PR. Contributions to Acme Router are gated behind an application. Please apply at https://checker.example.com/p/acme-router and we'll reopen this PR once you're approved.
Open an application for Acme Router to unblock this PR.
Hi @octocat! Your application for Acme Router is awaiting review. We'll reopen this PR once it's approved. Status: https://checker.example.com/p/acme-router
Your application for Acme Router is awaiting reviewer action.
Hi @octocat! Before we can accept contributions to Acme Router you need to sign the Contributor License Agreement. Sign here: https://checker.example.com/p/acme-router/cla. Your PR stays open and we'll re-check automatically once signed.
Sign the Acme Router CLA to unblock this PR. Your PR stays open and we'll re-check automatically once signed.
The CLA and DCO gates are the exception. They leave the pull request open and fail a check instead of closing it.
How the decision is made
One function, and the checks run in order. The first match wins.
repo.activeis false. The repository was uninstalled, so nothing happens.checkerEnabledis false. Everything is approved and the pull request is left alone.- A maintainer set a manual denial for this login. Denied, and the pipeline stops here.
- The login matches the bypass list, for example
*[bot]. Bypassed, and exempt from the CLA. - A maintainer set a manual approval. Approved.
- The author is a repository collaborator and
bypassCollabsis on. Bypassed. - The author's latest application decides it: approved, denied, or pending.
An allowing result then passes through the CLA check, and after that the DCO check. The full pipeline
Quality scoring that does not call a model
Every pull request can be scored 0 to 100. The score comes from 36 heuristics that read the diff, the commits, the pull request body, and the author's public profile. They are ordinary functions. There is no API key, no inference, no third party, and no per-pull-request cost. The same pull request scores the same number every time.
Scores are visible to maintainers only. The one public surface is a warning comment, posted when the score falls under the project's threshold.
| Group | Heuristics | On by default |
|---|---|---|
Size size | 4 | 4 |
PR text pr | 11 | 9 |
Commits commit | 5 | 4 |
Code code | 8 | 8 |
Diff cohesion diff | 2 | 1 |
Account account | 6 | 3 |
29 of 36 are on by default.
App mode or GitHub Actions
Install the GitHub App if you can. If org policy will not let you, the same gate runs from inside Actions, authenticated with the workflow's OIDC token. There are no shared secrets to rotate in either case.
| App mode | CI mode | |
|---|---|---|
| Install | GitHub App on the repository | Two workflow files |
| Auth | Installation token | Actions OIDC JWT, verified against GitHub's JWKS |
| Trigger | pull_request | pull_request_target |
| Reopen after approval | Immediate | Up to 10 minutes, on the reconcile cron |
| Collaborator auto-bypass | Yes | No, list them in bypass handles |
| Status checks | Yes | Via the workflow |
| Quality scoring | Yes | Only if the workflow sends qualityContext |
It runs on your infrastructure
- Stack
- Next.js 15, Prisma, PostgreSQL. One Docker image, one database.
- Secrets
- Environment variables, or HashiCorp Vault for the GitHub App key, the webhook secret, and SMTP.
- Data
- Applications, decisions, the audit log and PR scores stay in your database. Nothing is sent anywhere else.
- Licence
- AGPL-3.0-or-later.
Set it up
Create the GitHub App, install it on a repository, then link the repository to a project. The setup page prints the exact URLs and permissions for your instance.