"A red X nobody is forced to look at is not a quality gate. Here is how GitHub, GitLab, and SonarQube actually enforce blocking checks."
A red X on a pull request is not a gate. It is a suggestion with a color. Plenty of teams have a dozen checks running on every commit and still ship the same regressions, because nothing about a failing check actually stops the merge button from working.
A check reports status. A gate enforces a consequence. Most CI pipelines are full of the first and nearly empty of the second. Linting runs, tests run, a security scan runs, and all three can fail while someone still clicks merge, because the failure was informational rather than binding.
GitHub's own documentation draws this line explicitly. A status check that runs on a pull request is just data until it gets added to a branch protection rule as a required status check. Only then does GitHub disable the merge button until that check passes. The check existing and the check blocking are two separate configuration steps, and it is common for a team to have done only the first one.
GitLab's documentation describes the equivalent mechanism on its platform: a project setting called Pipelines must succeed, which prevents a merge request from merging if the latest pipeline did not complete successfully or is still running. Without that setting enabled, a failing pipeline is visible but not binding, the same gap GitHub's optional required checks leave open by default.

On GitHub, this means going into branch protection rules and explicitly selecting which status checks are required before merging is allowed. GitHub's documentation notes that a required check must have run successfully on the protected branch within the past seven days to even appear as selectable, which trips up teams setting this up for the first time on a branch that has not had recent activity.
On GitLab, enabling Pipelines must succeed under merge request settings makes a passing pipeline mandatory rather than advisory, and it applies whether the pipeline comes from GitLab CI or an external CI provider connected through the same mechanism.
Neither platform makes blocking the default. Both require someone to deliberately flip a setting, which is exactly why so many pipelines have checks that look authoritative in the UI but do not actually stop anything.
Static analysis tools produce a lot of noise if every finding is treated as equally important, which is where a dedicated quality gate concept helps. SonarQube's documentation describes a quality gate as a set of conditions evaluated against new code, reliability, security, maintainability, and coverage thresholds among them, that produces a single pass or fail verdict. That verdict can decorate a pull request with a status, and critically, it can also report to the CI pipeline itself, which is the piece that lets a required status check on GitHub or a required pipeline stage on GitLab actually enforce the quality gate's verdict rather than just display it.
This is the missing link in a lot of setups. A team adopts a static analysis tool, sees the dashboard, and assumes the quality gate is doing something, without ever wiring that gate's pass or fail output into a required check that can block a merge. If your team is building this kind of pipeline from scratch, the Agentic AI for QA and SDET course covers wiring automated checks into a CI pipeline as enforced gates rather than passive reports.
More blocking gates is not automatically better. Every required check adds friction to every single merge, and a pipeline with fifteen mandatory checks, several of them flaky, trains a team to find workarounds instead of fixing root causes. DORA's research tracks change failure rate and rework rate as the outcome that actually matters, the rate at which deployed changes cause problems, rather than counting how many gates exist in a pipeline. A team can have three well chosen, reliable blocking gates and a lower change failure rate than a team with twelve inconsistent ones that everyone has learned to route around.
Pick the checks that catch the failures that actually reach production in your system, make those specific checks required, and leave the rest informational until you have evidence they belong in the blocking set.
No. Blocking every check turns routine merges into a slow, frustrating process and encourages people to disable or bypass gates entirely. Reserve blocking status for checks tied to failures that have actually caused production incidents.
On most platforms, yes, by design, since an emergency fix sometimes needs to move faster than the normal gate allows. The point of a required check is to make bypass a deliberate, visible action, not to make it physically impossible.
Not by itself. It produces a pass or fail verdict and can report that verdict to the CI pipeline, but someone still has to configure that report as a required status check or an equivalent blocking pipeline stage for it to actually stop a merge.
Look at your own incident history. A check tied to the category of bug that has actually reached production and caused a rollback is a strong candidate. A check that has never once caught a real production issue is a weaker case for blocking every merge.
If your team wants to build a pipeline where quality checks actually enforce outcomes instead of just reporting them, the Master Playwright course covers wiring automated test results into CI so a failing test genuinely blocks a bad deploy.
Categories: : Automation