CI as a reviewer: status checks
Intermediate
Why this matters
A pipeline that reports is advice; a pipeline that blocks the merge button is a reviewer. Understanding the difference explains why some red checks stop everything and others do not, and it turns "the reviewer keeps saying the same thing" into a solvable problem.
How a check becomes a requirement
Two things must both be true:
- The job runs and reports a status for the commit.
- The branch rules require that status before merging.
The second is a setting on the protected branch or ruleset, not on the pipeline (lesson 9.5, lesson 10.5). This is why a failing job sometimes blocks the merge and sometimes does not: only the required ones block.
| Platform | Where it is configured |
|---|---|
| GitLab | Settings → Merge requests → Pipelines must succeed, plus protected branch rules |
| GitHub | A ruleset's Require status checks to pass, naming each required check |
Both also offer a job-level escape: allow_failure: true on GitLab, continue-on-error: true on GitHub, which lets a check report without ever blocking.
What the merge box tells you
The panel above the merge button lists every unmet requirement, and it is a checklist rather than an error message (lesson 9.7):
| Message | Means |
|---|---|
| Pipeline must succeed | A required check is red or still running |
| Requires N approvals | Human reviewers, not CI |
| This branch is out of date | The rules require the branch to include current main |
| Unresolved threads | A review requirement, not a CI one |
| Ready to merge | Nothing is missing |
Read it before asking. It is accurate, it updates itself, and it distinguishes machine requirements from human ones.
When a required check is wrong
It happens: a flaky test, a check that fails for reasons unrelated to your change, a service outage.
- Confirm it is not yours. Does the same check fail on
main? - Retry once, if the failure looks like infrastructure.
- Say so where the work is, with a link to the job and the error text (lesson 13.9).
- Do not push empty commits to re-trigger it. They clutter the history and often do not help.
- Ask a maintainer, who can merge past a required check when it is genuinely broken. That is their decision, not yours, and it should be recorded in the merge request.
An override is normal and occasionally necessary. What matters is that it is deliberate and visible, rather than achieved by turning the rule off and forgetting.
The checks worth having
For a documentation contributor, four are worth more than any others, and none of them needs application knowledge:
| Check | Catches |
|---|---|
| Markdown linting | Heading levels, list formatting, trailing spaces |
| Link checking | Links to pages that were renamed or deleted |
| Spell checking, with a project dictionary | The typos every reviewer would otherwise mention |
| A built preview | Whether the page actually renders as intended |
The argument for each is the same: any review comment that a machine could make should be made by a machine. A human reviewer who spends their attention on heading levels has less of it left for whether the instructions are correct.
Turning a repeated comment into a check
The most useful thing this lesson can leave you with:
- Notice a comment appearing in review after review: "add a changelog entry", "headings skip a level", "this link is dead".
- Ask whether a tool exists for it. For all three of those, one does.
- Add it as non-blocking, so everyone sees it without being stopped (lesson 14.4).
- Clear the existing problems it reports, over a sprint or two.
- Make it required, and the comment never has to be written again.
That sequence is a genuinely valuable contribution, it is mostly YAML and conversation, and it is the kind of improvement that a non-developer is often best placed to notice.
How to do it
Run the required checks before pushing, which is the whole point of them being written down:
$ cat .gitlab-ci.yml
$ npx --yes markdownlint-cli "**/*.md" --ignore node_modulesInstall the same linters the pipeline uses so you see the warnings while writing, not after pushing. Most have VS Code extensions that read the project's own configuration file.
The same: install the corresponding inspections or plugins so the editor reports what CI would.
Settings → Merge requests has Pipelines must succeed and All threads must be resolved. Protected branches add approval rules. The merge request's merge box lists whatever is unmet.
A ruleset's Require status checks to pass names each check, and Require branches to be up to date forces the branch to include current main first. The pull request's merge box lists what is missing.
Common mistakes
- Assuming every red check blocks. Only required ones do.
- Pushing empty commits to re-trigger a stuck check.
- Asking for a required check to be disabled rather than fixed or overridden once.
- Adding a new check as required immediately.
- Treating "the pipeline is green" as "the change is correct". It means the checks that exist passed.
Try it yourself
Goal: find out which checks actually block, and propose one more.
- On your project, open a recent merge request and read its merge box.
- Separate the requirements into machine ones (checks) and human ones (approvals, threads).
- Find where the required checks are configured, and list which are required and which merely report.
- Look through the last ten review comments on the project and find one a tool could have made.
- Write the two-sentence proposal for adding it: what it catches, and that it would start non-blocking.
Expected result: a clear picture of what gates a merge on your project, and a concrete, small proposal that would save a reviewer's attention.
Show solution
Step 4 is where the value is. Repeated review comments are a measurement of what a project's tooling is missing, and they are visible to anyone who reads merge requests, which makes this an improvement a non-developer is unusually well placed to spot and propose.