Skip to content

What are required status checks?

Required status checks are CI results that must pass before a pull request can merge into a protected branch, set by branch protection rules or rulesets.

Last updated , 9 min read

What are required status checks?

Required status checks are named check results that must pass on the last commit before a pull request can merge into a protected branch. On GitHub, a branch protection rule or a ruleset lists them by name. A failed or missing result stops the merge until a later run passes.

A status check is a result that an outside system, e.g. a continuous integration and delivery (CI/CD) pipeline, reports on one commit. A protected branch is a branch with rules on how changes reach it. GitHub's documentation calls these branch protection rules, and required status checks are one of their settings.

A ruleset is a named list of rules for branches or tags, described in GitHub's ruleset documentation. Several rulesets and a branch protection rule can apply to one branch, and the most restrictive version of each rule applies.

Required checks are a common way to put a quality gate in front of the main branch.

How do required status checks work?

A required status check works in six steps:

  1. An admin adds a rule for a branch, e.g. main, in the repository's Branches or Rules settings, and lists by name the checks that must pass.
  2. A developer or a coding agent pushes a commit to a pull request that targets that branch.
  3. CI runs on that commit and reports each result under a name. In GitHub Actions, each job reports a check named after the job, and the job fails when a step returns a nonzero exit code.
  4. GitHub matches the results on the pull request's last commit to the required names.
  5. GitHub counts a required check as passed when its result is successful, skipped, or neutral.
  6. GitHub allows the merge only when each required check has passed. A failed check blocks the merge, and a check that has not reported shows "Waiting for status to be reported."
How a branch rule reads status checks Last commit pull request Check run set by a GitHub App Commit status set by a user or service Branch rule required names Merge allowed each one passed Merge blocked failed or missing
GitHub reads both types of status check by name on the last commit. The merge waits until each required name has passed.

GitHub calls required checks strict when the rule's "Require branches to be up to date before merging" option is on. The strict setting blocks the merge until the branch has every commit on main. A rule can also name the app that must report each check, and then a status from anyone else blocks the merge. The rule matches names, so a renamed job leaves it waiting for the old name. A branch protection rule's search lists only checks that passed in the past 7 days, so a job must pass once first.

What is an example of a required status check?

Here is an illustrative example. Acme Co. sells furniture online. The workflow for its web store runs two jobs on each pull request:

name: ci
on: pull_request
jobs:
  unit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - run: npm ci && npm test
  e2e:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - run: npm ci && npx playwright install --with-deps
      - run: npx playwright test

An admin at Acme adds a branch protection rule for main that requires both jobs, names the GitHub Actions app as their source, and turns on the strict setting. GitHub's REST API returns the rule's status check settings like this, with URL fields left out:

{
  "strict": true,
  "contexts": ["unit", "e2e"],
  "checks": [
    { "context": "unit", "app_id": 15368 },
    { "context": "e2e", "app_id": 15368 }
  ]
}

A developer asks a coding agent to "Let customers edit their delivery address during checkout." The change then meets the rule:

  1. The agent opens a pull request, and both jobs run on its commit.
  2. The unit check passes, and e2e fails on the cart test. The address saved, but the cart emptied.
  3. GitHub lists e2e as a failed required check and blocks the merge.
  4. The agent fixes the code that cleared the cart and pushes again.
  5. Both checks pass, but another pull request has merged into main. The strict setting makes the agent update the branch from main, and the checks run again.

This example is simplified. A real project would also require an approving review.

What changes when a coding agent writes the code?

GitHub's documentation says any person or integration with write permissions can set any status check, and an agent often has that access. If Acme later adds a path filter that skips the ci workflow, no e2e check reports. An agent told to merge the change can then post a success status named e2e through the API. A rule that names no app counts it, but Acme's rule names the GitHub Actions app and blocks the merge.

Naming the app does not stop job edits. For a pull_request event, GitHub Actions runs the workflow file from the pull request's trial merge commit. If an agent adds if: false to the e2e job, the skipped job reports success from the right app. The checkout test never runs.

A practical adjustment is to pin each required check to its app and require a code owner's review for .github/workflows. Give the agent a token without admin rights or permission to update workflow files, so its pushes cannot change the jobs. A CI step can restore the test files from the base branch before the tests run, e.g. git checkout FETCH_HEAD -- tests/ after git fetch origin main. An agent editing tests in its branch then cannot turn the run green. Avoid pull_request_target for this, because it runs with the repository's secrets.

Which checks should be required?

A required check stops each merge it fails, so it should fail only on a problem the team would refuse to ship. In the software testing life cycle, a required check is an exit criterion. Good candidates have these traits:

  • Reliable. The check gives the same result on the same code. A flaky test blocks correct changes at random, so it runs as a report until someone fixes it.
  • Always reported. No path or branch filter can skip the workflow. With a merge queue, the workflow also runs on the merge_group event.
  • Stable in name. Matrix jobs report one check per leg, e.g. unit (20). A team can require one final job that needs: the others, runs with if: always(), and fails unless each succeeded.
  • Fast. Each change waits for the check, so a slow check becomes a queue for teams using trunk-based development.
  • Tied to behavior. At least one required check tests a main user flow end to end, e.g. checkout, not only the build.

Checks whose results need judgment, e.g. AI review comments, work better as reports than as blocking checks.

What are the limits of required status checks?

Required status checks have these limits:

  • A pass covers only what ran. The rule reads a name and a result, not the tests behind it. A green e2e check says nothing about flows that e2e does not test.
  • Skipped work can pass or stall. A job skipped by an if condition reports success, but a workflow skipped by a path filter leaves its check pending.
  • Checks can pass on a stale base. Without the strict setting or a merge queue, the checks may have tested the branch against an older main.
  • Admins can bypass them. A branch protection rule does not apply to admins until someone turns on "Do not allow bypassing the above settings." A ruleset exempts only those on its bypass list.
  • They check code, not intent. A change can pass each check and still do the wrong thing, so code review stays part of the merge rule.

How are status checks different from check runs?

A status check on GitHub is either a check run or a commit status. A rule can require either type by name.

GitHub's status checks reference says GitHub Actions creates check runs, not commit statuses. Only a GitHub App can create a check run through the Checks API. They differ on these attributes:

AttributeCheck runCommit status
Created byA GitHub App, e.g. GitHub ActionsA user or service with write access
ResultA status, then a conclusion, e.g. failureOne of error, failure, pending, or success
DetailA summary and line annotationsA short description and a link
Grouped inA check suite for each app and commitA combined status for the commit

FAQs

Can an admin merge without the required checks?

Under a GitHub branch protection rule, an admin can merge without the required checks by default. The rule does not apply to admins until its "Do not allow bypassing the above settings" option is on. A ruleset exempts only those on its bypass list, so an admin who is not on it must wait for the checks.

Why is a required check stuck waiting for status?

A required check waits for status when no result with its name reaches the pull request's last commit. A path filter can skip the whole workflow, or a renamed job can report under a name the rule does not list.

What is a GitHub ruleset?

A GitHub ruleset is a named list of rules for branches or tags, e.g. a rule that requires checks to pass. One branch can have several rulesets and a branch protection rule at once, and GitHub applies the strictest version of each rule.

Should a flaky test be a required check?

A flaky test should not be a required check, because it blocks correct changes at random. The team can quarantine it, so it reports without blocking until someone fixes it, then require it again.