5.0 KiB
AGENTS.md
Flutter/Dart mobile app (iOS + Android, Russian-market nutrition/consulting product).
Gitea-hosted; CI is Gitea Actions in .gitea/workflows/ (not GitHub Actions, though it references github.com/actions/*).
Toolchain (trust these over README — README version numbers are stale)
- CI runs Flutter 3.41.2 stable, Java/JDK 21 (
.gitea/workflows/test.yml). pubspec.yamlrequires Dart SDK ^3.10.4; app version is1.3.23+105(README claims 1.3.0+79 — wrong).- Build/test/lint via Flutter directly or the
Makefile. The repo has apackage.jsononly to wire a git pre-push hook viasimple-git-hooks; it is not a Node project.
CRITICAL: generated code is NOT committed
.gitignore excludes *.g.dart, *.freezed.dart, *.gr.dart, *.mocks.dart. After any checkout / pull / model change you must regenerate before flutter analyze, flutter test, or any build, or they fail on missing files:
dart run build_runner build --delete-conflicting-outputs
# or: make build-generated-files
Generators in use: freezed, json_serializable, retrofit_generator, mockito (build_runner).
Exception: lib/generated/ (l10n output from intl_utils / flutter_intl) is committed — don't regenerate-and-clobber it casually.
.env (required for running the app, NOT for unit tests)
- The app loads
.envat startup (lib/core/app_initializer.dart→dotenv.load) and ships it as a Flutter asset (pubspec.yamlassets). - There is no
env.examplein the repo despite README/ENV_SETUP.mdsayingcp env.example .env. Locally you must obtain.envfrom the team. In CI it is checked out from a privateeatvio/eatvio_app_envrepo. flutter testdoes not need.env: tests seed env viadotenv.loadFromString(...)(seetest/core/app_config_test.dart). Access values only throughlib/core/env_config.dart(EnvConfig).- Build types:
AppBuildType { prod, tests, dev }(lib/core/app_initializer.dart).prod→BASE_URL;tests/dev→DEV_BASE_URL.main.darthardcodesprod.
Commands
make run-analyse # flutter analyze
make run-tests # flutter test
make run-checks # analyze THEN test (also the pre-push hook)
make build-generated-files # build_runner --delete-conflicting-outputs
make clean-coverage # strips generated files from coverage/lcov.info
Run a single test file / single test:
flutter test test/core/app_config_test.dart
flutter test test/core/app_config_test.dart --plain-name "creates config with prod build type"
Coverage (must be run with the flag): flutter test --coverage, then make clean-coverage. analyze_coverage.py / analyze_coverage_by_uncovered.py summarize coverage/lcov.info.
CI gate (binding constraint on PRs)
.gitea/workflows/test.yml runs on every PR, in order:
flutter clean→flutter pub get→dart run build_runner build --delete-conflicting-outputsflutter analyzeflutter test --coverage- Coverage must be ≥ 70% (generated files excluded) or the job fails — keep this in mind when adding untested code.
flutter build apk --release --dart-define=HIDE_PLANS=false --dart-define=BUILD_DATE=...
Note: other workflow files (build.yml, docker-run-tests.yml) are simpler/older and do not run build_runner; test.yml is the authoritative one.
Architecture map
- Entry:
lib/main.dart→AppInitializer.initialize(env → DI → Sentry → Firebase → analytics) → runs app under Sentry. - DI:
get_it(slglobal), registered inlib/core/locator_service.dartvialib/core/di/*_registrations.dart(app_config, external, service, repository, cubit). - State:
flutter_bloc(Cubits/Blocs). Global providers declared inlib/core/app_config.dart(globalBlocProviders). - Routing:
go_router(lib/core/app_router.dart), with deep-link/push handling inlib/core/notifications/. - Networking:
dio+retrofit(→.gr.dart); auth token interceptor inlib/core/interceptors/. - Models:
freezed+json_serializable(→.freezed.dart/.g.dart). - Realtime: Pusher channels via
lib/core/websockets/(WsManager). - Features: ~40 self-contained folders under
lib/features/<feature>/, conventionally.../presentation/bloc/<name>_cubit/<name>_cubit.dart. Tests mirrorlib/undertest/with fixtures intest/fixtures/. - Localization: Russian only (
ru); strings via generatedSclass fromlib/generated/l10n.dart.
Conventions / gotchas
analysis_options.yamlenablesflutter_lints+ extraprefer_const_*rules and excludes generated + l10n files from analysis.dart_code_metricsis also configured (cyclomatic ≤20, ≤50 lines executable, ≤4 params, nesting ≤5) but metrics excludetest/**.- Don't commit secrets:
.env,android/key.properties,*.jkskeystores are all gitignored. - Comments and many code identifiers are in Russian (UI strings, doc comments like
/// Загрузка переменных окружения); match surrounding style.