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
coveragecommand 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_toolkitalready generated atdevtools/- 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:
archipelago generate coverage_managerThe prompts are:
- appName: the name of your app
- isForMonorepo: leave this as
true
Or use a config file:
{
"appName": "MyApp",
"isForMonorepo": true
}archipelago generate coverage_manager --config coverage_config.jsonStep 2: Understand the Generated Structure
The brick adds a script package and registers CoverageCommand in the toolkit.
devtools/
└── scripts/
└── coverage_manager/
└── lib/src/
├── commands/ # init, run, combine, check, full
├── models/coverage_config.dart
└── services/coverage_service.dartStep 3: Create the Config
dart run monorepo_toolkit coverage initThe command writes coverage.yaml at the workspace root. It leaves an existing file alone.
Step 4: Set Thresholds and Exclusions
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: trueA 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
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 4full 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
- 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
| Customization | Where to Change |
|---|---|
| Global thresholds | global in coverage.yaml |
| Per-package thresholds | packages in coverage.yaml |
| Excluded files | exclude_patterns and exclude_files |
| Parallel test runs | The -j flag |
| Test only changed packages | Use affected with affected test --coverage |
Next Steps
- Set up affected detection to test only changed packages
- Add custom lint rules to complement coverage enforcement