flutter_release_checker 0.2.2
flutter_release_checker: ^0.2.2 copied to clipboard
A CLI and library that audits your Flutter app's Android, iOS, Firebase, Supabase, security and store readiness, reporting a Production Ready Score via terminal and HTML report.
flutter_release_checker #
Audit your Flutter app before you ship it. Get a Production Ready Score, a readable terminal report, and a beautiful HTML report — right from your command line, or from your own Dart code.
Part of a small ecosystem of Flutter tooling:
| Package | Purpose |
|---|---|
flutter_architect |
Start your app |
flutter_release_checker |
Ship your app |
flutter_cache |
Manage your app's data |
Contents #
- Install
- Usage
- CLI options
- What it checks (14 checks across 7 categories)
- The HTML report
- Programmatic API
- Roadmap
- Development
- Contributing
Install #
dart pub global activate flutter_release_checker
(Or add it as a dev_dependency in your Flutter app and run it via dart run flutter_release_checker check.)
Usage #
From the root of your Flutter project:
flutter_release_checker check
FLUTTER
⚠ Dart SDK Constraint
ANDROID
✖ Android Manifest
⚠ Permissions
⚠ SDK Versions
✖ Signing Config
⚠ App Icons
IOS
⚠ Info.plist
✖ Privacy Manifest
⚠ App Icons
...
──────────────────────────────────────────
Production Ready Score
🔴 0 / 100
──────────────────────────────────────────
Critical
❌ Debuggable flag enabled
❌ Release build uses debug signing config
❌ Missing Privacy Manifest
High
⚠ Cleartext traffic allowed
⚠ Components missing explicit android:exported
⚠ Sensitive permission: ACCESS_BACKGROUND_LOCATION
⚠ Target SDK version below Play Store requirement (30)
...
Recommendations
✔ Remove android:debuggable from the manifest and let Gradle set it per build type.
✔ Create a dedicated release signing config backed by your upload keystore...
──────────────────────────────────────────
HTML report written to build/release_report.html
Open build/release_report.html in your browser for a shareable, color-coded
report of the same results (see The HTML report).
CLI options #
| Flag | Description |
|---|---|
--path, -p |
Path to the Flutter project root (default: .) |
--output, -o |
Where to write the HTML report (default: build/release_report.html) |
--html / --no-html |
Enable/disable the HTML report (default: on) |
--color / --no-color |
Enable/disable colored terminal output (default: on) |
--only |
Only run specific check ids, comma-separated (e.g. --only android_manifest,android_signing) |
--fail-under |
Exit with code 1 if the score is below this value — useful in CI |
What it checks — 14 checks across 7 categories #
Flutter
- Dart SDK constraint: flags an outdated lower bound in
environment.sdk
Android
- Manifest:
debuggable, cleartext traffic, backup settings, missingandroid:exported - Permissions: sensitive/dangerous permissions requiring Play Console justification
- SDK versions: missing/outdated
compileSdk,minSdk,targetSdk - Signing: release build type falling back to debug signing, missing
key.properties - App icons: missing launcher icon densities, missing adaptive icon
iOS
Info.plist: missing version keys, disabled App Transport Security (NSAllowsArbitraryLoads)- Privacy Manifest: missing
PrivacyInfo.xcprivacy(required by Apple since 2024) - App icons:
AppIcon.appiconsetslots with no image assigned, and slots whose referenced file doesn't actually exist on disk (catching stale/brokenContents.jsonentries that would otherwise fail an Xcode archive)
Firebase
- Config files: missing
google-services.json/GoogleService-Info.plistwhen afirebase_*dependency is present
Supabase
- Service role key: a hardcoded
service_roleJWT inlib/**/*.dart, which bypasses Row Level Security and must never ship in a client app. Detected by decoding the JWT payload'sroleclaim, so the safe, publicanonkey is never flagged. Skipped when there's nosupabase_flutterdependency.
Security
- Hardcoded secrets: AWS/Google/Stripe/Slack/GitHub key patterns and private key blocks found in
lib/**/*.dart. Tool-generated files known to embed client-safe identifiers (e.g.firebase_options.dartfrom the FlutterFire CLI) are skipped to avoid false positives. - Insecure HTTP: plaintext
http://URLs hardcoded in Dart source
Store Readiness
- Version & build number: missing/malformed
versioninpubspec.yaml
Every check is skip-aware — e.g. iOS checks are skipped (not failed) when there's no ios/ directory, and Firebase/Supabase checks are skipped entirely if the project doesn't depend on them.
Note: checks verify configuration and file integrity (e.g. "does an icon file exist for every declared slot?"), not visual/design quality (e.g. "is this icon well-designed?" or "did you replace the default icon?"). They catch things that will break a build or a store submission, or that reviewers commonly flag — not subjective design choices.
The HTML report #
build/release_report.html includes a circular score gauge, a one-line verdict
("Ready to ship" / "Needs work before release" / ...), severity-count pills,
a per-category pass/fail breakdown, a category-grouped checklist, and
issues tagged with both severity and category — all in a single
dependency-free dark-themed HTML file you can open straight in a browser or
attach to a PR.
Programmatic API #
Everything the CLI does is also available as a library — see
example/ for a complete, runnable script:
import 'package:flutter_release_checker/flutter_release_checker.dart';
Future<void> main() async {
final project = FlutterProject.at('.');
final results = <CheckResult>[
for (final check in CheckRegistry.all) await check.run(project),
];
final score = const ScoreCalculator().calculate(results);
final report = ReleaseReport(
projectName: project.projectName,
results: results,
score: score,
generatedAt: DateTime.now(),
);
print(TerminalReporter().render(report));
const HtmlReporter().write(report, defaultHtmlReportPath(project.root.path));
}
Run it with:
dart run example/flutter_release_checker_example.dart path/to/your_flutter_app
Full API reference is generated via dartdoc from the doc comments on every
public class and member (see Development).
Roadmap #
This CLI is the first of three planned surfaces for the same checks engine:
flutter_release_checker
├── CLI ← you are here
├── HTML Report ✔ already included
└── GitHub Action (planned: post the score as a PR comment)
Ideas for future checks, in no particular order: Universal Links/URL scheme validation, entitlements review, APK/IPA size and duplicate-asset detection, dependency/deprecated-package and security-advisory scanning, release notes and privacy-policy presence, screenshot validation, and detecting when an app still uses Flutter's default launcher icon.
Development #
dart pub get
dart analyze # strict: public_member_api_docs is enforced
dart test # 45 tests across unit + integration coverage
dart doc . # generates API docs into doc/api/
dart pub publish --dry-run # validates packaging before a release
test/fixtures/sample_app is a deliberately-broken Flutter project (old
Dart SDK, missing build number, ATS disabled, missing privacy manifest,
missing Firebase config, a fake hardcoded AWS key, a fake Supabase
service_role key, an insecure HTTP call, etc.) used to exercise every
check end to end. Its fake credentials are allow-listed via false_secrets
in pubspec.yaml so they don't block publishing — see
dart.dev/go/false-secrets.
Contributing #
Checks live in lib/src/checks/<category>/ (android/, ios/, firebase/,
security/, flutter/, store_readiness/) and implement the Check
interface (lib/src/checks/check.dart). Register new checks in
lib/src/checks/check_registry.dart — order there determines both terminal
grouping and category card order in the HTML report. See test/checks/ for
the expected test shape, and test/fixtures/ for sample projects to test
against.
Every public class and member should have a dartdoc comment
(public_member_api_docs is enforced by dart analyze).
License #
MIT