Quality Gate: where the build pipeline lets defects through
Changes more often reach the main branch not through hacking, but through a loophole in the pipeline itself.
Checks are attached to the merge request, but not to the final state of the branch: two branches are green separately, but after merging they break each other — a semantic conflict that the linter does not see.
Add dependency caching, because of which a step runs on an outdated set of libraries, and the picture is complete.
The second place is bypassed rules. Administrator rights allow a commit to be pushed past the queue, and an urgent fix goes into the main branch without review.
A verification step disabled "temporarily" returns months later — and all that time the code quality threshold is effectively not in effect.
Third — environment discrepancies. Checks in the pipeline run on one set of variables and dependency versions, while the release is built on another: schema migrations pass calmly on staging and fail on the production database. Defects in a release more often come from here than from logic.
Finally, the threshold itself. A Quality Gate reduced to general words lets everything through: the build fails late — the artifact is already built, tests have passed, and only at the final step does it become clear that the version does not pass vulnerability checks. Stopping at this stage is many times more expensive than failing in the first seconds.
Below we analyze how this is closed: which checks become mandatory, where the boundary between warning and blocking is, and how to make a green result mean the same thing on any environment.
The Effect of Unified Code Requirements: What We Measure
Unified code requirements are meaningless without numbers that show they actually work.
We tie a set of metrics to every change and every release, and set thresholds in the rules configuration — for example, in SonarQube or in a custom set of pipeline checks — and then they are calculated automatically, without manual review.
- Release rollback rate. How many deployments were rolled back within 24 hours after release. Critical changes are cut off before merging into the main branch, and the metric falls.
- Change verification time. From opening a merge request to the verdict. A full run should fit into minutes, otherwise developers will start bypassing the rules.
- Share of tasks returned for rework. How many changes go into a second round not because of reviewer comments, but because of red checks. Shows where rules are too strict and where the tests themselves get in the way.
- Classes of escaped defects. Secrets in the repository, vulnerable dependency versions, coverage dropping below the threshold — after checks are enabled, they stop reaching the main branch.
- Coverage of new lines by tests. A threshold for changes, not the whole project: demanding high coverage from old code is meaningless and leads to formal tests.
- Release stability. Number of incidents per release and time to detect a problem. Threshold checks do not remove failures, but shift their detection toward the pipeline, where the cost of fixing is an order of magnitude lower.
These metrics must be viewed together: individually, any of them can be improved by a workaround — coverage grows from empty tests, check speed grows from disabled rules. That is why thresholds are fixed in one place and changed only together with a root-cause analysis.
Quality Gate Options: Comparing Approaches
A Quality Gate can be placed at three levels: on the developer's machine, on the build server, and in a manual acceptance loop.
They do not replace each other — local ones save the build cycle, server ones provide a common source of truth for everyone, manual ones catch what cannot be described by a formal rule.
The choice depends on team maturity and the cost of a missed defect: the more expensive an error in production, the earlier it is worth stopping. Below is a comparison of approaches by applicability and limitations.
| Option | When it fits | Limitations |
|---|---|---|
| Local checks: linters, formatters, tests before commit | Need quick feedback and fewer unnecessary build runs | Bypassed with a single launch option, depend on machine settings, rules quickly take longer than a developer is willing to wait |
| Checks on the build server: a single mandatory minimum | Several developers and a shared repository, need an objective source of truth | Feedback comes later, requires configuration maintenance and a clear separation between "build fails" and "warning" |
| Manual control: review and acceptance | Changes in critical areas — access, payments, data schemas | Depends on reviewer workload, the result is not repeatable, scales poorly as the team grows |
| Hybrid: fast local checks plus a server minimum | Frequent releases and a high cost of error in production | Need to agree on the rules once and keep the configuration in the repository |
The working mode in practice is a hybrid: checks before commit, a mandatory minimum on the build server, manual review for critical areas.
At the same time, rules are not duplicated: each level is responsible for its own class of errors, otherwise the Quality Gate starts to be bypassed.
Implementation Order: From Audit to Handover
Implementing a Quality Gate is not checking a box in the build settings, but a sequence of steps where each next one relies on the result of the previous one.
If you tighten the thresholds right away, the pipeline will stall on the very first build, and the team will return to manually skipping checks. Therefore, we go from observation to restrictions.
-
Pipeline audit. We take a map of the current process: which stages already exist, what runs on every commit, and what only on release branches. We calculate the share of failed builds, average pass time, and the most common causes of failures.
-
Check scheme. We distribute defects by stages: syntax and style — before commit, unit tests — at build, regression and security checks — before merging into the main branch. For each check, we decide whether it blocks the merge or only signals.
-
Rule setup. We write thresholds in the configuration — coverage share, number of critical issues, allowable pass time. We keep rules in the repository next to the code so that changes go through review and do not get lost in the system interface.
-
Pilot loop verification. We enable rules in warning mode on one team or service and watch for a week: how many false positives, where checks slow down the build without benefit. We calibrate thresholds based on facts.
-
Switch to blocking mode. When there is almost no noise, rules begin to stop merges. For critical paths, we leave a conscious bypass with a recorded reason — otherwise the rule will be disabled entirely.
-
Handover to support. We give the team a description of the rules, the procedure for changing thresholds and analyzing failures: who fixes what and within what time, what is considered a reason to weaken a check. We record agreements in the repository.
A sign of readiness is that the rules live without us: thresholds change through review, and new services are connected according to the described template.
Set of Documents and Settings for Pipeline Support
The result of the setup is not verbal agreements, but a set of artifacts that lies next to the code in the repository and continues to work after the team composition changes. Below is what exactly remains with the customer after implementation.
- Settings file for quality control: thresholds for coverage of changed lines, allowable duplication, method length, presence of unresolved tasks; separately marked what blocks a merge and what only warns.
- Pipeline scheme: which checks run on every commit, which — when merging into the main branch, where manual confirmation is required and under what condition it is removed.
- List of rules — a single document with the wording of each requirement and a link to the setting that applies it. A rule without a setting is considered non-working and does not go into the list.
- List of exceptions: legacy modules, auto-generated code, migration scripts — with the reason, responsible person, and review date. An exception without a date automatically expires.
- Instructions for the team: how to reproduce checks on a work machine before sending changes, how to read a violation report, and how to legally challenge a false positive.
- Change procedure: thresholds are edited by a separate change with justification and verification by a second engineer; weakening a requirement is recorded in history and does not drown in correspondence.
- Trigger report: accumulated statistics on blocked merges and false failures — it is used to review thresholds once a quarter.
The set of settings, the scheme, and the procedure are transferred to the project repository, and the instructions — to the team knowledge base. Describe the task — we will return with an estimate and a plan.
Case Study: How We Reduced the Share of Defects per Release
What We Started With
A product with frequent releases: several dozen changes per week, three teams in one repository.
Checks in the pipeline formally existed but were optional — the build did not always fail, no one opened the analyzer report, and code review boiled down to "looks fine." About 40% of defects reached users, and release preparation took almost a day: most of the time went to manual runs and analyzing what had already happened in production.
What We Changed
The Quality Gate was made a mandatory condition for advancing through branches: coverage of new code by tests, absence of critical analyzer issues, a successful test run, and verification by a second engineer.
Thresholds were not set out of thin air — first the current level was fixed as "no worse," then raised one rule per iteration so that the restriction did not stop work.
We configured SonarQube and a rule profile for the product, exceptions — only through explicit approval with a record in the configuration: otherwise the rule is bypassed within a week.
What Happened
The share of defects reaching users decreased by about three times, critical ones — to zero.
Change verification time dropped from several hours to 20 minutes, release preparation — from a day to a couple of hours, the number of rollbacks halved: failures are caught at the verification stage, not in production.
Engineers stopped manually rechecking what was already covered by the pipeline — trust in checks became measurable rather than declarative.
How Does a Check in the Shared Build Differ from a Local One?
A local check runs on the developer's machine before sending changes: it sees the changed file and triggers within seconds. The shared build sees the whole project — with dependencies and other people's edits.
Hence the different cost of error: a local delay is annoying, while a stopped shared build stops everyone.
The practical division is simple. Locally — fast and unambiguous: formatting, static analysis, checking changed files. In the shared build — what requires full context: artifact build, integration tests, coverage, vulnerabilities in dependencies.
The second question is where to warn and where to block. A rule that often triggers falsely is better left as a warning: the developer sees the signal but does not bypass it by disabling it. Blocking on a noisy rule gives the opposite result — checks begin to be bypassed en masse.
It is worth stopping the build where the error is unambiguous: the artifact does not build, integration tests fall apart, coverage drops below the agreed threshold, a critical-level vulnerability is found, a migration schema changes without backward compatibility.
Severity is increased gradually: first the rule works in observation mode and writes a report, then — blocks. This way the threshold is calibrated by real build history, not assumptions, and the team does not lose trust in the checks.
Technical Concerns When Implementing Quality Checks
Most questions come not about the tool itself, but about how it will coexist with an already working pipeline. Checks are added as a separate step: the build, tests, and current linter rules continue to work; we extend the configuration rather than rewriting it from scratch.
Will the check start blocking releases out of nowhere?
False positives appear where a requirement is formulated as "like / don't like" rather than as a measurable condition. Therefore, the rule first goes into warning mode: it writes a report but does not stop the build.
Within a couple of weeks the real share of false positives is visible — and only then does the threshold become blocking.
How long does implementation take and who maintains the rules?
The basic set — successful build, absence of critical vulnerabilities, test coverage of changed code — does not require rewriting code and is configured in the first weeks.
After that, requirements live as an ordinary configuration file: any relaxation goes through a merge request, so it is visible who weakened the threshold and why. We hand over maintenance to your team together with the rule description.
Will the load on developers increase?
The load grows only where a rule catches a real defect. If a check triggers more often than once every few builds, and there are no defects behind it, it is reformulated or removed.
We adjust outdated requirements together with the team rather than keeping them "just in case."
Let's Discuss Your Task and Come Back with a Plan
To discuss the task substantively, the following inputs are enough: how the repository is organized, which branches are used, which checks already run on merge, and at which step releases are most often rolled back. This data is enough to come back with an estimate and work plan, not general words.
As a result, you get a working Quality Gate loop and a clear set of works by stages:
- analysis of the current build pipeline and checks: which steps slow down the release and which let defects through;
- quality profile — which checks block merging into the main branch and which only warn;
- rules and thresholds for your repository: coverage of changed lines, static analysis, vulnerable dependencies;
- bypass procedure: who and how removes a block so that the rule is not disabled entirely;
- set of works by stages, estimate and work plan, including rollout order and implementation start;
- role distribution: what your team takes over for support and what remains with us;
- acceptance criteria — by which metrics we consider implementation complete.
Describe the task: a link to the repository and a couple of builds that raise questions are enough. We will come back with an estimate and work plan, agree on the set of works and the implementation start date.
We will discuss your team's role at each stage separately — so that after launch the rules live in your process, not in someone else's document.







