Pre-merge Checks
Pre-merge checks are quality gates that run automatically after every PR review. They evaluate the review findings against your defined thresholds and post a commit status to GitHub, allowing you to block merges when code quality standards are not met. Checks are configured in the CodePeel dashboard and apply across all your repositories.
Overview
Pre-merge checks bridge the gap between code review findings and merge enforcement. While CodePeel's review engine identifies issues, pre-merge checks turn those findings into actionable gates that integrate with GitHub's branch protection rules.
Each check defines a condition (for example, "no security issues found") and a severity level that determines whether a failure blocks the merge or serves as a soft warning. When a PR review completes, all enabled checks are evaluated against the review metrics. The results are posted as a GitHub commit status under the codepeel/premerge context.
This feature works with GitHub's branch protection rules. When you require the codepeel/premerge status check to pass before merging, any check failure with error severity will prevent the PR from being merged until the issues are resolved.
Pre-merge checks are available on all plans including Free. They do not consume additional reviews -- they evaluate the findings that were already produced by the standard review. The only requirement is that a review must complete successfully for checks to run.
How It Works
The pre-merge check system operates as a post-review evaluation pipeline. It runs automatically after every PR review completes, requires no manual intervention, and integrates directly with GitHub's status checks API.
Step-by-step flow
-
A PR is opened or updated. CodePeel receives the webhook and runs the standard review (secret scanning, AI analysis, SAST, architecture review).
-
Review completes with metrics. The review produces aggregate metrics: bugs caught, security issues found, performance issues detected, and critical-severity findings count.
-
Checks are loaded. CodePeel loads your enabled checks for evaluation.
-
Each check is evaluated. For each enabled check, the system compares the review metrics against the check's threshold and type. A pass/fail result is determined.
-
Events are recorded. Each check evaluation is stored with the result, details, repository, commit SHA, and timestamp. The check's pass/fail counters are updated.
-
Results are stored on the review. The computed results for all checks are saved with the review, making them visible in the dashboard.
-
GitHub commit status is posted. A single commit status is posted to the PR's head commit under the
codepeel/premergecontext. If all checks pass, the status issuccess. If any check witherrorseverity fails, the status isfailure.
Commit status details
The commit status posted to GitHub includes:
| Field | Value |
|---|---|
| Context | codepeel/premerge |
| State | success or failure |
| Description | "All pre-merge checks passed" or "Pre-merge check failed" |
| Target URL | https://codepeel.app/app/premerge-checks |
The description is capped at 140 characters per GitHub's API limit. The target URL links to your pre-merge checks dashboard where you can see detailed results.
Check Types
CodePeel provides four predefined check types, each evaluating a different aspect of the review findings. You can enable any combination of these checks simultaneously.
Security Blocker
Fails if any security issue is found in the review. This is a zero-tolerance check with no threshold -- even a single security finding causes failure.
| Property | Value |
|---|---|
| Check type | security_blocker |
| Default severity | error (blocks merge) |
| Threshold | None (any security issue fails) |
| Evaluation | Any security issue fails the check |
Use this for repositories that handle sensitive data, authentication, or payment processing where any security vulnerability must be addressed before merging.
Bug Density
Fails if the number of bugs found exceeds your configured threshold. This allows you to tolerate a small number of minor bugs while blocking PRs with many issues.
| Property | Value |
|---|---|
| Check type | bug_density |
| Default severity | warning |
| Default threshold | 5 |
| Evaluation | Bug count at or below the threshold |
Set the threshold based on your team's tolerance. A threshold of 0 means zero bugs allowed. A threshold of 5 means up to 5 bugs are acceptable before the check fails.
Max Issues
Fails if the total number of issues (bugs + security + performance) exceeds your configured threshold. This provides a single aggregate gate across all finding categories.
| Property | Value |
|---|---|
| Check type | max_issues |
| Default severity | error (blocks merge) |
| Default threshold | 10 |
| Evaluation | Total bug + security + performance findings at or below the threshold |
This is the most flexible check type. Set a higher threshold for large PRs or repositories with known technical debt, and a lower threshold for critical services.
Missing threshold passes by default. For
bug_densityandmax_issueschecks that are saved without a threshold value, the evaluation short-circuits to "passed". A check saved with no threshold always passes — it is effectively a no-op rather than a zero-tolerance gate. If you want zero tolerance, set the threshold to0.
Critical Findings
Fails if any critical-severity finding is detected. Critical findings represent the most serious issues: security vulnerabilities, data loss risks, crashes, and race conditions.
| Property | Value |
|---|---|
| Check type | critical_findings |
| Default severity | error (blocks merge) |
| Threshold | None (any critical finding fails) |
| Evaluation | Any critical finding fails the check |
This check is independent of finding category. A critical bug, critical security issue, or critical performance problem all trigger failure.
Check type comparison
| Check Type | What it evaluates | Has threshold | Default severity |
|---|---|---|---|
security_blocker | Any security findings | No | error |
bug_density | Bug count | Yes | warning |
max_issues | Total issues (bugs + security + performance) | Yes | error |
critical_findings | Critical-severity findings | No | error |
Severity Levels
Each check has a severity level that determines its impact on the merge workflow.
Error severity
Checks with error severity block the merge. When any error-severity check fails, GitHub shows a red X on the commit status. If you have branch protection rules requiring the codepeel/premerge status to pass, the PR cannot be merged until all error-severity checks pass.
This is the recommended severity for security blockers and critical findings checks. Use it when you want hard enforcement that cannot be bypassed without fixing the underlying issues.
Warning severity
Checks with warning severity record the failure but do not block the merge. The commit status remains success even if warning-severity checks fail. The failure is visible in the CodePeel dashboard and check history, but it does not prevent merging.
Use warning severity for checks that track quality trends without enforcing hard gates. For example, a bug density check with warning severity lets you monitor how many bugs are introduced per PR without blocking the development workflow.
How severity affects the commit status
The commit status is determined by evaluating all enabled checks:
- If all checks pass: status is
success - If only warning-severity checks fail: status is
success(warnings do not block) - If any error-severity check fails: status is
failure
Setting Up Pre-merge Checks
Creating a check
- Navigate to Pre-merge Checks in the sidebar
- Find the check type you want to enable
- Toggle the check to enabled
- Set the severity level (
errorto block merges,warningfor soft alerts) - For threshold-based checks (
bug_density,max_issues), set your threshold value - The check is immediately active for all future PR reviews
Enabling branch protection
To enforce pre-merge checks as a merge requirement:
- Go to your GitHub repository settings
- Navigate to Branches > Branch protection rules
- Click Add rule (or edit an existing rule for your main branch)
- Under "Require status checks to pass before merging", search for
codepeel/premerge - Select it and save the rule
Once configured, GitHub will not allow merging any PR where the codepeel/premerge status is failure.
Recommended configuration
For most teams, we recommend starting with:
| Check | Severity | Threshold | Rationale |
|---|---|---|---|
| Security Blocker | error | -- | Zero tolerance for security issues |
| Critical Findings | error | -- | Critical issues must be fixed |
| Bug Density | warning | 5 | Track bug introduction without blocking |
| Max Issues | error | 10 | Block PRs that exceed overall issue count |
This configuration blocks merges only for security and critical issues while providing visibility into bug density and total issue counts.
Dashboard
The Pre-merge Checks page in the dashboard provides a complete view of your checks, their status, and recent history.
Check cards
Each check is displayed as a card showing:
- Name and description -- what the check evaluates
- Enabled/disabled toggle -- activate or deactivate the check
- Severity badge --
error(red) orwarning(yellow) - Threshold -- for threshold-based checks, the current value
- Pass/fail ratio -- a bar showing the proportion of passes to failures
- Last triggered -- when the check last ran (empty if never triggered)
Statistics
Each check tracks cumulative statistics:
| Stat | Description |
|---|---|
| Pass count | Total number of times this check has passed |
| Fail count | Total number of times this check has failed |
| Last triggered | Timestamp of the most recent failure |
These statistics update after every PR review across all your repositories.
Recent History
The Recent History section shows paginated check events (both passes and failures) across all repositories. Each event includes:
- Result -- pass or fail
- Check name -- which check was evaluated
- Repository -- which repo the PR belongs to
- Commit SHA -- the specific commit that was checked
- PR number and URL -- link to the pull request
- Timestamp -- when the check ran
- Details -- human-readable explanation (e.g., "Check failed: 2 security issues found")
History is paginated with configurable page sizes and supports loading additional pages.
Check Events
Every time a check is evaluated, an event is recorded. These events provide a complete audit trail of all check evaluations.
Detail messages
Each event includes a details field with a human-readable explanation of why the check passed or failed:
| Check Type | Pass message | Fail message |
|---|---|---|
security_blocker | "Check passed: 0 security issues found" | "Check failed: 3 security issues found" |
bug_density | "Check passed: 1 bug found (threshold: 5)" | "Check failed: 7 bugs found (threshold: 5)" |
max_issues | "Check passed: 3 total issues (threshold: 10)" | "Check failed: 12 total issues (threshold: 10)" |
critical_findings | "Check passed: 0 critical findings" | "Check failed: 2 critical findings" |
Integration with Reviews
Pre-merge check results are saved with the review itself, making them accessible from the review detail page in the dashboard.
After checks are evaluated, the results are saved alongside the review:
[
{
"name": "Security Blocker",
"checkType": "security_blocker",
"result": true,
"details": "Check passed: 0 security issues found"
},
{
"name": "Bug Density",
"checkType": "bug_density",
"result": false,
"details": "Check failed: 5 bugs found (threshold: 5)"
}
]
This allows you to see which checks passed or failed for any specific review without needing a separate query.
API Reference
Pre-merge checks can be managed programmatically through the REST API.
List checks
GET /api/app/checks
Authorization: Bearer <token>
Returns an array of all checks for the authenticated user.
Create a check
POST /api/app/checks
Authorization: Bearer <token>
Content-Type: application/json
{
"name": "Security Blocker",
"description": "Block merge if any security issue is found",
"enabled": true,
"severity": "error",
"checkType": "security_blocker",
"failureMessage": "Security issues must be resolved before merging"
}
Required fields: name, severity, checkType. For threshold-based checks, include threshold.
Update a check
PATCH /api/app/checks
Authorization: Bearer <token>
Content-Type: application/json
{
"id": "check-id-here",
"enabled": false,
"threshold": 10
}
Delete a check
DELETE /api/app/checks?id=check-id-here
Authorization: Bearer <token>
Troubleshooting
Commit status not appearing on PR
If the codepeel/premerge status does not appear on your PR:
- Verify you have at least one enabled check in the dashboard
- Confirm the PR review completed successfully (check the review in your dashboard)
- Ensure the GitHub App has
statuses:writepermission on the repository - Check if the review was skipped (WIP title, draft PR, or base branch not in
auto_review.base_branches)
The commit status is only posted when at least one check is enabled. If all checks are disabled, no status is posted.
Check always passes even with issues
Verify the check type matches what you expect:
security_blockeronly evaluates security-type findings, not bugs or performance issuesbug_densityonly counts bug-type findingscritical_findingsonly counts findings withcriticalseverity, regardless of typemax_issuescounts bugs + security + performance (but not architecture-only findings)
Also verify your threshold is set correctly. A threshold of 5 means the check passes if there are 5 or fewer issues (it fails at 6+).
Check fails but PR can still be merged
This means either:
- The check has
warningseverity (warnings do not block merges) - Branch protection rules are not configured to require the
codepeel/premergestatus - The repository admin has bypassed branch protection
To enforce blocking, ensure the check severity is error AND the codepeel/premerge status is required in your branch protection rules.
"Last triggered" is empty
The "Last triggered" field only updates on failures. If a check has never failed, this field remains empty even if the check has been evaluated many times (all passes). Check the pass count to confirm the check is running.
Checks not running on incremental reviews
Pre-merge checks run after every review completion, including incremental reviews triggered by new commits. If checks are not running on subsequent pushes, verify that auto_review.auto_incremental_review is true in your configuration.
Frequently Asked Questions
Do pre-merge checks require a paid plan?
Pre-merge checks are available on all plans including Free. However, the checks evaluate findings from the review, so you need available reviews in your quota for the PR to be reviewed in the first place. See Billing for plan details.
Can I have different checks for different repositories?
No. Pre-merge checks are configured at the account level and apply to all repositories where you have the GitHub App installed. All enabled checks are evaluated on every PR review regardless of which repository the PR belongs to.
Do checks run on IDE reviews from the VS Code extension?
No. Pre-merge checks only run on GitHub PR reviews. IDE reviews from the VS Code extension or MCP server do not trigger check evaluation or post commit statuses.
What happens if the check evaluation fails?
If the check evaluation itself encounters an error, the error is logged but does not affect the PR. No commit status is posted in this case, which means the PR is not blocked. This is graceful degradation — a system error should not prevent developers from merging.
Can I create custom check types beyond the four predefined ones?
Not currently. The four check types (security_blocker, bug_density, max_issues, critical_findings) cover the most common quality gate scenarios. The max_issues type with a custom threshold provides flexibility for most use cases. If you need a check type that is not supported, contact support.
How do I see why a specific check failed?
Each check event includes a details field with a human-readable explanation. View this in the Recent History section of the Pre-merge Checks dashboard page. The detail message includes the actual count and threshold (e.g., "Check failed: 5 bugs found (threshold: 5)").
Do checks evaluate architecture findings?
Architecture findings are not included in the max_issues total. The max_issues check counts bugs + security + performance issues only. Architecture findings are evaluated by the critical_findings check if they have critical severity, but they do not contribute to the aggregate issue count used by bug_density or max_issues.
Can I temporarily disable all checks?
Yes. You can toggle each check individually from the dashboard. Disabled checks are not evaluated and do not affect the commit status. If all checks are disabled, no codepeel/premerge status is posted to GitHub at all.
What is the difference between pre-merge checks and custom rules?
Custom rules are regex-based pattern matchers defined in .codepeel.yml that produce individual findings on specific lines. Pre-merge checks are aggregate quality gates that evaluate the total findings from a review and post a pass/fail commit status. Custom rules produce findings; pre-merge checks evaluate the aggregate result of all findings.
Best Practices
Start with warnings, then promote to errors
When first enabling pre-merge checks, set all checks to warning severity. Monitor the results for a few weeks to understand your baseline. Once you are confident the thresholds are appropriate for your team, promote critical checks to error severity.
This approach prevents disruption to your development workflow while you calibrate thresholds. A check that fails too often with error severity will frustrate developers and may lead to the check being disabled entirely.
Use security blocker and critical findings as hard gates
These two checks have no threshold -- they fail on any occurrence. This makes them ideal for hard enforcement because the condition is unambiguous. A single security vulnerability or critical finding is always worth blocking a merge.
For threshold-based checks like bug_density and max_issues, the appropriate threshold depends on your team size, PR size norms, and quality standards. Start with generous thresholds (5-10) and tighten them as your codebase improves.
Combine with health score monitoring
Pre-merge checks evaluate individual metrics (bug count, security count, critical count). For a holistic view of PR quality, also monitor the health score which provides a weighted aggregate across all finding types and severities.
A PR might pass all pre-merge checks (no security issues, bugs under threshold) but still have a low health score due to many medium-severity findings. Use the health score as a complementary signal alongside pre-merge checks.
Set up notifications for failures
When a pre-merge check fails, the commit status on GitHub is the primary notification mechanism. Developers see the red X on their PR and can click through to the CodePeel dashboard for details. For additional visibility, configure GitHub notifications to alert you when status checks fail on your repositories.
Review check history regularly
The Recent History section in the dashboard shows patterns over time. If a particular check fails frequently, it may indicate a systemic issue in your codebase or that the threshold needs adjustment. Conversely, a check that never fails may have too generous a threshold to be useful.
Limitations
Account-level scope
Pre-merge checks are configured at the account level, not per-repository. All enabled checks apply to every repository where you have the GitHub App installed. If you need different thresholds for different repositories, you currently need separate CodePeel accounts.
Single commit status
All checks are aggregated into a single codepeel/premerge commit status. GitHub does not show individual check results in the status -- only the aggregate pass/fail. To see which specific check failed, developers must click through to the CodePeel dashboard.
No custom evaluation logic
Check types are predefined. You cannot write custom evaluation expressions or combine multiple conditions into a single check. For complex quality gates, use multiple checks together -- for example, a security_blocker with error severity AND a max_issues check with warning severity.
Timing dependency
Pre-merge checks only run after a review completes. If the review fails (due to quota exhaustion, rate limiting, or API errors), no checks are evaluated and no commit status is posted. Ensure your account has available reviews for the checks to function.
No retroactive evaluation
Checks are only evaluated at the time a review completes. If you create a new check or change a threshold, existing PRs are not re-evaluated. The new check configuration applies to the next review that runs. To re-evaluate an existing PR, push a new commit to trigger an incremental review.
Related Documentation
- Features -- How findings are categorized and scored
- Configuration --
.codepeel.ymlsettings that affect what findings are produced - Billing -- Plans and quotas that determine whether reviews run