← Back to libraryQuestion 227 of 273
🔧CI/CDIntermediate

Quality Gates (Coverage Thresholds & Required Checks)

📌 Definition:

A quality gate is an automated pass/fail condition in the pipeline that blocks code from progressing unless it meets defined criteria — tests passing, coverage above a threshold, no critical security findings, no lint errors. It turns 'we should test' into 'you cannot merge without meeting the bar'.

📖 Detailed Explanation:

Quality gates move quality enforcement from human discipline to automation. They are implemented at two levels: inside the pipeline (a job step that exits non-zero when a threshold is missed, failing the run) and in the repository's branch-protection rules (required status checks that must be green before merge). Common gates: minimum test coverage (e.g. 80% lines, no drop vs base), all tests passing, zero high-severity vulnerabilities from a scanner, no linter/type errors, and sometimes a performance budget. The art is calibration: gates set too loose are theatre; too strict and teams route around them or disable them. A good gate is objective, fast, and fails with a clear message pointing at exactly what to fix.

🔑 Key Points:
  • Two enforcement points: a failing pipeline step, and branch-protection required checks
  • Typical gates: tests green, coverage threshold, security scan, lint/type-check, perf budget
  • Prefer 'no coverage decrease vs base branch' over a flat number to avoid gaming
  • A gate must fail loudly with an actionable message, not a cryptic exit code
  • Miscalibrated gates get bypassed — tune them with the team, not against it
🌍 Real-World Example:

A team keeps merging PRs that quietly drop coverage. They add a gate: the coverage job fails if line coverage falls below 80% OR decreases versus the base branch, and mark it a required check in branch protection. Now a PR that adds untested code goes red with 'coverage 76% < 80%', and cannot be merged until tests are added.

📎 Code Example:
# .github/workflows/ci.yml — coverage quality gate
  coverage-gate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: 20 }
      - run: npm ci
      - run: npm test -- --coverage --coverageReporters=text-summary json-summary
      - name: Enforce 80% line coverage
        run: |
          PCT=$(node -p "require('./coverage/coverage-summary.json').total.lines.pct")
          echo "Line coverage: $PCT%"
          awk "BEGIN { exit !($PCT >= 80) }" \
            || { echo "::error::Coverage $PCT% is below the 80% gate"; exit 1; }
# Then mark 'coverage-gate' a required status check in branch protection.
🎯 Scenario-Based Interview Question:

Scenario: Leadership mandates '100% code coverage as a merge gate' after a production bug slipped through. Two weeks later, coverage is 100% but the same class of bugs still ships, and developers are frustrated. What went wrong and what gate would you propose instead?

💡 Quick Tip:

In interviews, always separate coverage (lines run) from assertion quality (behavior verified) — conflating them is the classic quality-gate trap.