Monorepo Toolkit
Test Coverage Pipeline
What you'll learn
- Setting up per-package coverage thresholds
- Generating and merging lcov reports across a monorepo
- Configuring file and pattern exclusions
- Integrating coverage checks into CI with pass/fail gates
Prerequisites
- An existing Archipelago monorepo (see Monorepo Scaffolding)
- The coverage command generated in your monorepo toolkit
lcovinstalled (brew install lcovon macOS)
Step 1: Get the Coverage Command
The coverage command comes from the coverage_manager brick (Pro). Pro and Enterprise projects get it automatically when generated. Otherwise add it to an existing project with archipelago generate coverage_manager. It registers a coverage command on the monorepo_toolkit CLI.
Step 2: Understand the Generated Structure
devtools/scripts/coverage_manager/
└── lib/src/
├── commands/ # init, run, combine, check, full
├── models/ # coverage_config.dart (coverage.yaml parsing)
└── services/ # coverage_service.dart (run, lcov merge, thresholds)The root pubspec.yaml already has melos shortcuts: coverage:init, coverage:run, coverage:combine, coverage:check, coverage:full and coverage:run:parallel.
Step 3: Configure Coverage Thresholds
Create the config with dart run monorepo_toolkit coverage init, which writes coverage.yaml in your monorepo root. Edit it:
global:
min_line_threshold: 80
min_branch_threshold: 70
min_function_threshold: 80
exclude_patterns:
- "*.g.dart"
- "*.freezed.dart"
- "**/generated/**"
- "*.config.dart"
exclude_files:
- "lib/main.dart"
- "**/injector.dart"
packages:
core_network:
min_line_threshold: 90
monitoring_noop:
skip: true- global: Thresholds, glob patterns and files applied to every package
- packages: Per-package overrides, keyed by package name.
skip: trueexcludes a package
Step 4: Run Coverage Locally
# Run tests with coverage for all packages
dart run monorepo_toolkit coverage run
# 4 packages in parallel
dart run monorepo_toolkit coverage run -j 4
# One package only
dart run monorepo_toolkit coverage run -p core_network
# Keep going after a failure
dart run monorepo_toolkit coverage run --no-fail-fastTo limit coverage to changed packages (Enterprise), use dart run monorepo_toolkit affected devtool coverage --base main.
Step 5: Merge lcov Reports and Check Thresholds
# Merge per-package lcov.info files (default: coverage/lcov.info)
dart run monorepo_toolkit coverage combine
dart run monorepo_toolkit coverage combine -o coverage/merged_lcov.info
# Verify each package against its threshold, exits 1 if any fails
dart run monorepo_toolkit coverage check
# Or all in one: run + combine + check
dart run monorepo_toolkit coverage full -j 4
# Optional HTML report (requires lcov)
genhtml coverage/lcov.info -o coverage/html
open coverage/html/index.htmlStep 6: Integrate with CI
- name: Run coverage pipeline
run: dart run monorepo_toolkit coverage full -j 4
- name: Upload coverage report
if: always()
uses: actions/upload-artifact@v4
with:
name: coverage-report
path: coverage/lcov.infocoverage full fails the step when any package is below its threshold.
Key Customization Points
| Customization | Where to Change |
|---|---|
| Default thresholds | coverage.yaml - global.min_line_threshold, min_branch_threshold, min_function_threshold |
| Per-package thresholds | coverage.yaml - packages.<name> |
| Excluded patterns and files | coverage.yaml - exclude_patterns, exclude_files |
| Skip a package | coverage.yaml - packages.<name>.skip: true |
| Parallelism | -j / --concurrency flag |
| Merged report path | coverage combine --output |
Next Steps
- Set up affected detection to run coverage only on changed packages
- Visualize dependencies to understand your monorepo structure