๐ก๏ธ flutter_ci_guard
flutter_ci_guard is a lightweight CLI tool for running Flutter quality gates in CI. It checks formatting, static analysis, tests, coverage thresholds, and optional per-file coverage insights from one command.
๐ What does it solve?
CIs often have separate steps for formatting, linting, and testing. If one fails, you might get scattered reports. More importantly, enforcing a minimum coverage percentage usually requires complex shell scripts or heavy third-party services.
flutter_ci_guard orchestrates these "Quality Gates" into a single, reliable command that:
- ๐งน Ensures code is formatted (fails if
dart formatfinds changes). - ๐ Runs static analysis (fails if
flutter analyzefinds issues). - ๐งช Executes tests with coverage (fails if tests fail).
- ๐ Enforces coverage thresholds (fails if coverage is below your limit).
- ๐ Highlights low-coverage files when per-file reporting is configured.
๐ฆ Installation
Add it as a dev dependency in your pubspec.yaml:
dev_dependencies:
flutter_ci_guard: latest_version
Or install it globally:
dart pub global activate flutter_ci_guard
๐ ๏ธ Basic Usage
Run it from the root of your Flutter project:
# Runs everything with default 80% coverage threshold
dart run flutter_ci_guard
Real-world examples
Enforce strict 95% coverage:
dart run flutter_ci_guard --min-coverage 95
Check only analysis and coverage (skipping format and tests runtime):
# Useful if you already ran tests in a previous CI step but need to check the LCOV file
dart run flutter_ci_guard --skip-format --skip-tests --min-coverage 80
Configuration file
You can store defaults in a flutter_ci_guard.yaml file at your project root. The file is loaded automatically when present.
steps:
format: true
analyze: true
test: true
coverage:
min: 85
path: coverage/lcov.info
exclude:
- "**/*.g.dart"
- "**/*.freezed.dart"
per_file_min: 70
show_top_low_files: 5
Supported keys in this release:
steps.formatsteps.analyzesteps.testcoverage.mincoverage.pathcoverage.excludecoverage.per_file_mincoverage.show_top_low_files
You can also point to a custom config file:
dart run flutter_ci_guard --config ci/flutter_ci_guard.yaml
CLI flags still work exactly as before. When the same setting is provided in multiple places, precedence is:
CLI flags > YAML config > built-in defaults
Coverage exclusions
Generated files can distort the global LCOV percentage and make the reported
coverage less representative of the source files you actually maintain.
flutter_ci_guard now supports optional glob-style exclusions so those files
can be removed before the global coverage total is computed.
coverage:
min: 85
path: coverage/lcov.info
exclude:
- "**/*.g.dart"
- "**/*.freezed.dart"
- "**/generated/**"
Exclusions are applied per LCOV file record before global aggregation. This is useful for generated code and other paths you do not want counted in the final percentage.
Per-file insights use the same filtered file set, so excluded files are also removed before low-coverage files are selected.
Supported glob-style patterns include examples such as:
**/*.g.dart**/*.freezed.dart**/generated/**
If you prefer to pass exclusions from the command line, use:
dart run flutter_ci_guard --coverage-exclude "**/*.g.dart,**/*.freezed.dart"
When no exclusions are configured, coverage behavior remains unchanged from previous versions.
Per-file coverage insights
You can optionally show the lowest-coverage files after the global summary:
coverage:
min: 85
path: coverage/lcov.info
exclude:
- "**/*.g.dart"
- "**/*.freezed.dart"
per_file_min: 70
show_top_low_files: 5
coverage.per_file_minshows only files below the configured percentage.coverage.show_top_low_fileslimits output to the lowest N files.
Behavior stays backward compatible:
- If neither key is configured, no per-file output is shown.
- If only
per_file_minis configured, all files below that threshold are shown. - If only
show_top_low_filesis configured, the lowest N files are shown. - If both are configured, files below the threshold are shown up to the limit.
Example output:
Coverage: 82.00% (820/1000 lines)
Low coverage files:
lib/auth/login_cubit.dart -> 54.00%
lib/cart/add_item.dart -> 61.00%
โ๏ธ Configuration Flags
| Flag | Default | Description |
|---|---|---|
--config |
auto-detect flutter_ci_guard.yaml |
Path to a YAML config file. |
--min-coverage |
80 |
Required percentage (0-100). |
--coverage-path |
coverage/lcov.info |
Path to the generated LCOV file. |
--coverage-exclude |
- | Comma-separated glob patterns to exclude from coverage. |
--skip-format |
false |
Skip dart format validation. |
--skip-analyze |
false |
Skip flutter analyze. |
--skip-tests |
false |
Skip flutter test --coverage. |
--help |
- | Show usage information. |
๐ค CI/CD Integration
GitHub Actions
The most common way to use flutter_ci_guard is as a single "Quality Gate" step.
jobs:
check-quality:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: subosito/flutter-action@v2
- name: Install dependencies
run: flutter pub get
- name: Run Quality Gates
run: dart run flutter_ci_guard --min-coverage 90
Publishing releases
This package is intended to publish to pub.dev from GitHub Actions only when a
version tag is pushed. Pushes and pull requests on main run validation only
and do not publish.
Before using automated publishing, configure pub.dev trusted publishing in the
package Admin settings for this repository and use the tag pattern
v{{version}}.
Example release flow:
git tag v0.3.0
git push origin v0.3.0
The version in pubspec.yaml must match the tag version exactly.
๐ช Exit Behavior
flutter_ci_guard returns specific exit codes so your CI can react accordingly:
| Code | Meaning |
|---|---|
| 0 | Success (All gates passed). |
| 1 | Step Failed (Format, Analyze, or Tests failed). |
| 2 | Low Coverage (Coverage is below the threshold). |
| 3 | Missing File (Coverage file not found at the specified path). |
| 4 | Parse Error (The LCOV file is malformed). |
| 64 | Invalid Args (Wrong CLI usage). |
๐ฏ Scope & Philosophy
- Lightweight: Small surface area, fast startup.
- Fail Fast: If formatting fails, it doesn't waste time running tests.
- CI-First: Designed to be the standard way to run checks in pipelines.
- Pure Dart: No need for
lcovorgenhtmlinstalled on the CI machine to check the percentage.
๐จโ๐ป Created & Maintained By
Miguel Angel Oquendo Rincon
๐ License
MIT License - see LICENSE for details.