Skip to content
Back to archipelago.banuacoder.com

DevTools

How to enforce a Flutter test coverage gate in CI ​

Pro Reference for coverage_manager: every variable, option and package it generates. Command: archipelago generate coverage_manager

Add the coverage command, set thresholds and exclusions in coverage.yaml, merge reports, and fail CI when coverage drops.

What you'll learn ​

  • Adding the coverage command to your monorepo toolkit
  • Setting thresholds and exclusions in coverage.yaml
  • Running tests, merging reports and checking thresholds
  • Enforcing a coverage gate in CI

Prerequisites ​

  • An existing Archipelago monorepo (see Monorepo Scaffolding)
  • monorepo_toolkit already generated at devtools/
  • A Pro or Enterprise subscription

Step 1: Generate the Coverage Manager Command ​

New Pro projects already include this brick. Run it on an older project:

bash
archipelago generate coverage_manager

The prompts are:

  • appName: the name of your app
  • isForMonorepo: leave this as true

Or use a config file:

json
{
  "appName": "MyApp",
  "isForMonorepo": true
}
bash
archipelago generate coverage_manager --config coverage_config.json

Step 2: Understand the Generated Structure ​

The brick adds a script package and registers CoverageCommand in the toolkit.

text
devtools/
└── scripts/
    └── coverage_manager/
        └── lib/src/
            ├── commands/     # init, run, combine, check, full
            ├── models/coverage_config.dart
            └── services/coverage_service.dart

Step 3: Create the Config ​

bash
dart run monorepo_toolkit coverage init

The command writes coverage.yaml at the workspace root. It leaves an existing file alone.

Step 4: Set Thresholds and Exclusions ​

yaml
global:
  min_line_threshold: 80
  min_branch_threshold: 70
  min_function_threshold: 80

  exclude_patterns:
    - "*.g.dart"
    - "*.freezed.dart"
    - "**/generated/**"

  exclude_files:
    - "lib/main.dart"
    - "**/injector.dart"

packages:
  auth_impl:
    min_line_threshold: 90
  monitoring_noop:
    skip: true

A package entry overrides the global values. Use skip: true for a package with no testable code. The line threshold always applies. The branch and function thresholds apply only when the report has that data.

Step 5: Run the Pipeline ​

bash
dart run monorepo_toolkit coverage run -j 4
dart run monorepo_toolkit coverage run -p auth_impl
dart run monorepo_toolkit coverage combine -o coverage/lcov.info
dart run monorepo_toolkit coverage check
dart run monorepo_toolkit coverage full -j 4

full runs tests, merges the reports and checks the thresholds. run and full stop at the first failure unless you pass --no-fail-fast.

Step 6: Enforce in CI ​

yaml
- name: Run coverage pipeline
  run: dart run monorepo_toolkit coverage full -j 4

- name: Upload coverage report
  uses: actions/upload-artifact@v4
  with:
    name: coverage-report
    path: coverage/

check exits with code 1 when a package falls below its threshold.

Key Customization Points ​

CustomizationWhere to Change
Global thresholdsglobal in coverage.yaml
Per-package thresholdspackages in coverage.yaml
Excluded filesexclude_patterns and exclude_files
Parallel test runsThe -j flag
Test only changed packagesUse affected with affected test --coverage

Next Steps ​