Modern QA2026Common Quality Gates — tiles
Log inJoin
44 / 48 · 16 CI/CD Pipelines · Quality Gates← prev⊞ allnext →☰ Read as one page

7.2Common Quality Gates

All Tests Pass

The most basic and most important gate. A single test failure blocks the merge or deploy.

# GitHub branch protection: Require status checks to pass
# Settings > Branches > Branch protection rules > Require status checks
# Select: "unit-tests", "integration-tests", "browser-tests"

Why this gate matters: If you allow merging with failing tests, developers quickly learn that test failures are ignorable. Within weeks, nobody trusts the test suite, and the pipeline becomes decoration.

Code Coverage Threshold

Require that coverage does not drop below a baseline.

# Using a coverage check action
- uses: codecov/codecov-action@v4
  with:
    fail_ci_if_error: true
    flags: unittests

# Or enforce in the test command itself
- run: npx jest --coverage --coverageThreshold='{"global":{"branches":75,"functions":80,"lines":80}}'

Better approach: Rather than enforcing an absolute threshold (e.g., "80% overall"), require that new code is covered. A legacy codebase at 60% coverage should not block PRs that add well-tested new features.

# Codecov configuration (codecov.yml)
coverage:
  status:
    patch:
      default:
        target: 90%  # New code must be 90% covered
    project:
      default:
        target: auto  # Overall coverage must not decrease

Security Scanning

Integrate SAST (Static Application Security Testing) and DAST (Dynamic Application Security Testing) scanners and fail on findings above a threshold.

# Example: Snyk security scan
- uses: snyk/actions/node@master
  env:
    SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
  with:
    args: --severity-threshold=high  # Fail on high/critical vulnerabilities

Gate levels:

  • Critical/High vulnerabilities: Block the merge. These must be fixed before shipping.
  • Medium vulnerabilities: Warn but allow merge. Create a follow-up ticket.
  • Low vulnerabilities: Informational only. Track but do not block.

Performance Budgets

Enforce performance standards to prevent gradual degradation.

# Lighthouse CI
- run: npx lhci autorun
  env:
    LHCI_BUILD_CONTEXT__CURRENT_HASH: ${{ github.sha }}

# lighthouse-ci configuration
# lighthouserc.js
module.exports = {
  ci: {
    assert: {
      assertions: {
        'categories:performance': ['error', { minScore: 0.9 }],
        'categories:accessibility': ['error', { minScore: 0.95 }],
        'first-contentful-paint': ['warn', { maxNumericValue: 2000 }],
        'largest-contentful-paint': ['error', { maxNumericValue: 2500 }],
      },
    },
  },
};

Other performance gates:

  • Bundle size limits: Fail if the JavaScript bundle exceeds a threshold
  • API response time p95: Fail if the 95th percentile response time exceeds the budget
  • Image optimization: Fail if unoptimized images are added

Lint and Format Checks

Enforce code style so reviews focus on logic, not formatting.

lint:
  runs-on: ubuntu-latest
  steps:
    - uses: actions/checkout@v4
    - run: npm ci
    - run: npm run lint          # ESLint
    - run: npm run format:check  # Prettier --check
    - run: npm run typecheck     # tsc --noEmit

Why gate on formatting: Without automated enforcement, code reviews devolve into arguments about semicolons and indentation. Automate the trivial decisions so humans focus on architecture and logic.