Ship Flutter and Dart apps faster, with lanes written in Dart.
Release automation for Flutter and Dart. Define lanes, compose actions, run anywhere: locally on developer machines or natively in CI.
Everything you need to ship. Nothing you don't.
Say goodbye to opaque fastfiles, flaky Gemfile setups, and fragmented build tools. Control every stage from compilation to storefront delivery using native Dart idioms.
Lanes: Plain Dart Workflows
Organize complex deployment pipelines into intuitive, asynchronous Dart functions. Chain tasks, handle failures cleanly, and reuse workflow logic across apps.
Actions: Composable Steps
Typed, reusable steps for analyzing, testing, building Android APKs and app bundles, bumping pubspec versions, and uploading to Firebase. Write your own when you need more.
Firebase App Distribution
Upload builds to your tester groups straight from a lane. Play Store and App Store publishing are not supported yet.
CI-Ready Everywhere
The lane you run on your laptop runs the same way on GitHub Actions, with no prompts and error annotations. Other CI that sets CI=true gets the same behavior with plain output.
Define your pipelines in 100% Dart.
No Ruby gems, no Groovy scripting, no YAML nightmare logic. Enjoy complete language coherence across your entire stack.
Instant IDE Autocomplete
Full parameter suggestions, documentation hints, and jump-to-definition in VS Code and Android Studio.
Compile-Time Sanity
Catch missing variables, broken arguments, and typing mistakes before launching an expensive 30-minute CI run.
Zero Context Switching
Your team already knows Dart. Build scripts become native codebase assets rather than devops friction.
import 'package:dartlane_core/dartlane_core.dart';
import 'package:dartlane_firebase/dartlane_firebase.dart';
import 'package:dartlane_flutter/dartlane_flutter.dart';
import 'config.dart';
Future<void> main(List<String> args) => dartlane(
args,
lanes: {
'beta': Lane('Build and ship to QA', (ctx) async {
// 1. Static analysis gate
await ctx.run(const FlutterAnalyze());
// 2. Build the Android APK
final build = await ctx.run(FlutterBuild.apk(flavor: Config.flavor));
// 3. Upload to Firebase App Distribution
await ctx.run(
FirebaseDistribute(
build.path,
app: Config.firebaseAppId,
groups: ['qa'],
),
);
}),
},
);How Dartlane works
Three steps from install to a build on your testers' phones.
Install globally
Activate the Dartlane CLI globally with dart pub global activate. No Ruby, no bundler.
Set up and define a lane
Run dartlane init in your app. It creates dartlane/lanes.dart, where you chain build and upload actions.
Run locally or in CI
Execute dartlane run beta, or preview it first with --dry-run. The same command works in CI.
Runs the same on your laptop and on CI
Lanes are plain Dart, so a CI job only needs Dart and Flutter. GitHub Actions gets error and warning annotations, and any CI that sets CI=true runs without prompts.
- uses: actions/checkout@v4
- uses: subosito/flutter-action@v2
- name: Install lane dependencies
working-directory: dartlane
run: dart pub get
# Same lane you run on your laptop
- name: Run the beta lane
run: dart run dartlane/lanes.dart beta