GitHub Actions required status checks prevent merging pull requests until all specified checks pass.
Let’s see this in action. Imagine we have a Python project. We want to ensure every pull request passes linting and runs unit tests before it can be merged.
First, we need a .github/workflows/ci.yml file in our repository:
name: CI
on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.9'
- name: Install dependencies
run: pip install flake8
- name: Lint with flake8
run: flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.9'
- name: Install dependencies
run: pip install pytest
- name: Test with pytest
run: pytest
This workflow defines two jobs: lint and test. When a pull request is opened or updated, these jobs will run automatically.
Now, to make these checks required, we go to our GitHub repository’s settings. Navigate to Settings -> Branches. Under Branch protection rules, we click Add rule. We select our main branch (e.g., main or master).
In the branch protection rule settings, we need to enable Require status checks to pass before merging. Once enabled, a section appears where we can specify which status checks are required. GitHub will automatically list the jobs from our workflows. In our case, we’d see lint and test. We select both.
After saving this rule, any new pull request targeting our protected branch will show the status checks below the commit list. Until both the lint and test jobs complete successfully, the Merge pull request button will be disabled. If either job fails, the button remains disabled, and the PR author will need to fix the failing code and push a new commit. This ensures that only code that meets our quality standards gets merged.
The core problem this solves is preventing regressions and maintaining code quality in a collaborative environment. Without required checks, a developer might accidentally merge code that breaks the build, introduces linting errors, or fails tests, potentially destabilizing the main branch. This system automates the enforcement of these quality gates, shifting the responsibility for fixing issues to the contributor before the code impacts the main codebase.
Internally, GitHub Actions is a distributed system. When a pull_request event occurs, GitHub’s event dispatcher triggers the associated workflows. For each job in the workflow, a runner (a virtual machine or container) is provisioned on GitHub’s infrastructure. This runner checks out the code, executes the defined steps, and reports its status back to GitHub. The branch protection rule then queries these reported statuses. If all required checks report a success status, the merge is permitted. Otherwise, it’s blocked.
The exact levers you control are the on: triggers in your workflow file (e.g., push, pull_request, pull_request_target), the jobs themselves, and the specific commands within each job’s steps. The branch protection rule then acts as the gatekeeper, deciding which of these workflow job statuses must be green before merging. You can also configure "Require branches to be up to date before merging," which forces a re-run of checks if the target branch has new commits since the PR was opened, further ensuring the PR is tested against the latest code.
A common misunderstanding is that all checks listed under "Require status checks" are automatically required. However, GitHub offers a checkbox for "Include administrators." If this is not checked, repository administrators with admin privileges can still merge pull requests even if required checks have failed. This is often overlooked when troubleshooting why a seemingly blocked PR was merged anyway.
The next concept you’ll likely encounter is how to handle different environments or more complex testing scenarios, such as deploying to a staging environment and requiring manual approval before merging.