There is no CI. Nothing runs dart format, flutter analyze, or flutter test when code is
pushed or a PR is opened, so regressions and lint/format drift can land on main unnoticed.
This doc creates the core CI workflow: a fast, offline gate that every push and PR must pass.
Critical. This workflow is the foundation the entire engineering process rests on — it's
what makes the test suite (../tests/) and every future change actually enforced rather
than aspirational.
.github/workflows/ci.ymltool/check_coverage.sh(if not already created in../tests/08-coverage-and-quality-gates.md)
.github/contains onlypull_request_template.mdand unrelatedmodernize/files.- No
workflows/directory.
A single ci.yml with one job (optionally a matrix). It must:
- Check out the repo.
- Install a pinned Flutter version (which includes the matching Dart).
flutter pub get.- Verify formatting (
dart format --set-exit-if-changed). flutter analyze(treat infos/warnings as failures via--fatal-infos).flutter test --coverage.- Enforce the coverage floor.
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
# Cancel superseded runs on the same ref to save minutes.
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
jobs:
analyze-and-test:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Flutter
uses: subosito/flutter-action@v2
with:
channel: stable
flutter-version: 3.29.0 # pin; must bundle Dart >= 3.7.2
cache: true # cache the Flutter SDK + pub
- name: Install dependencies
run: flutter pub get
- name: Verify formatting
run: dart format --output=none --set-exit-if-changed .
- name: Analyze
run: flutter analyze --fatal-infos
- name: Run tests with coverage
run: flutter test --coverage
- name: Install lcov
run: sudo apt-get update && sudo apt-get install -y lcov
- name: Enforce coverage floor
run: bash tool/check_coverage.sh 85 # match the floor in ../tests/08
- name: Upload coverage artifact
if: always()
uses: actions/upload-artifact@v4
with:
name: coverage
path: coverage/lcov.info
if-no-files-found: warn- Flutter, not Dart-only: the package depends on the Flutter SDK;
flutter_testand theflutter/services.dartasset stubbing in tests require it. --fatal-infos: the project keepsflutter analyzeperfectly clean today; make CI enforce that so it stays clean. If a specific info is intentional, suppress it in code with a justified// ignore:rather than weakening the gate.- Formatting gate:
dart formatis the canonical Dart formatter; failing on drift keeps diffs clean. Rundart format .locally before pushing. - Coverage floor: reuses
tool/check_coverage.shfrom../tests/08. If that script isn't created yet, create it per that doc. The floor (85) must match. - Caching:
subosito/flutter-action'scache: truecaches the SDK and pub packages, cutting cold-start time substantially. - Concurrency: cancels stale runs on force-push/rebase to save CI minutes.
Once green, consider a matrix to catch SDK-specific breakage:
strategy:
matrix:
flutter-version: ['3.29.0', '3.x'] # pinned floor + latest stableKeep the pinned floor matching the package's minimum supported SDK.
- Ensure
tool/check_coverage.shexists (from../tests/08); if not, create it there first. - Create
.github/workflows/ci.ymlwith the YAML above. - Pin
flutter-versionto a stable release bundling Dart ≥ 3.7.2; verify locally thatflutter --versionreports a matching Dart. - Run the gate locally to confirm it passes before pushing:
dart format --output=none --set-exit-if-changed . flutter analyze --fatal-infos flutter test --coverage bash tool/check_coverage.sh 85
- Push to a branch, open a PR, confirm the workflow runs and all steps pass.
- Make the
analyze-and-testjob a required status check onmain(see doc 04).
ci.ymlruns on every push tomainand every PR targetingmain.- It installs Flutter, runs
flutter pub get, checks formatting, runsflutter analyze --fatal-infos, runsflutter test --coverage, and enforces the coverage floor. - The job fails if any step fails (format drift, analyzer issue, test failure, or coverage below floor).
- Coverage
lcov.infois uploaded as an artifact. - Runs complete in a few minutes with caching.
- 02 — coverage reporting (surface coverage on the PR)
- 03 — release and publish (a separate, tag-driven workflow)
- 04 — repo hygiene (make this a required check)
- ../tests/08-coverage-and-quality-gates.md (the floor + script)