flutter_buildkit library
Build Flutter apps (APK, AAB, IPA) from an interactive console menu or from code, file every build in a predictable folder tree and keep a ledger of what was built, published, uploaded to Google Play and symbolicated.
Most people use the command line app:
dart pub global activate flutter_buildkit
fbk # inside a Flutter project
The menu (App) and its settings screens are not part of the library API.
The commands that run without a menu are in Cli.
The same pieces are available as a library:
- Configuration: AppConfig reads
flutter_buildkit.yaml. - Projects: FlutterProject finds flavors, entry points, version and package names.
- Building: FlutterBuilder runs
flutter buildfor a BuildRequest and records the result. - Ledger: Ledger, BuildRecord, BuildManager and LedgerExporter store, change, delete and export builds.
- Folders and names: BuildPaths, LayoutPreset and PathTemplate.
- Symbols: SymbolUploader sends them to Crashlytics and Sentry, Symbolicator de-obfuscates crash traces.
- Editor and project setup: suggestConfig, planLaunchJson and mergeLaunchJson.
- Commands without a menu: Cli and ExitCodes.
- Terminal UI: Console, SelectModel and renderTable.
Runnable examples for each area are in the package's example/ folder.
Classes
- AppConfig
-
Settings for one Flutter project, read from
flutter_buildkit.yamlin the project root, with secrets taken from environment variables. - BuildArtifact
- One file produced by a build (an APK per ABI, an AAB, an IPA...).
- BuildEvent
- Something that happened to a build, kept in BuildRecord.events.
- BuildFailure
- Why a build did not finish; set on rows with status BuildStatus.failed.
- BuildManager
- Ledger operations that also touch the build folders on disk.
- BuildNaming
- Everything a name template can use.
- BuildPaths
- Decides where a build and its files are stored.
- BuildRecord
- A single row of the build ledger.
- BuildRequest
- Everything the user chose for one build.
- BuildSigning
- Who signed an Android build, read back from the finished file.
- Cli
- The commands that work without a menu: they take their input from options and arguments, never prompt, and return an ExitCodes value.
- ConfigEditor
-
Edits a
flutter_buildkit.yamltext in place, keeping the comments and the order of everything it does not touch. - ConfigTrust
- Remembers which project configs the user agreed to run.
- Console
- Prompts and styled output for the menu.
- CrashlyticsConfig
-
Firebase Crashlytics symbol upload settings, from the
crashlytics:section. - DartEntry
-
A Dart file that can be run as an app: it defines
main(). - DeleteResult
- What BuildManager.delete did, per build.
- Doctor
- Checks that the tools and settings the other commands rely on are there.
- DoctorCheck
-
One line of the
doctorreport. - EntryPoint
- One Dart file to build. name is null for the default entry point, which keeps the plain names.
- ExitCodes
-
Exit codes of the command line app. They follow
sysexits.hwhere one fits and are stable, so scripts and CI can rely on them. - FlavorConfig
- Per-flavor settings. Every field is optional.
- FlutterBuilder
-
Runs
flutter build, copies the outputs into the build folder tree and records the build in the ledger. - FlutterProject
- What can be learned about a Flutter project from its files.
- GradleFlavor
- An Android product flavor found in Gradle.
- InterruptGuard
- Cleans up when the user presses Ctrl-C during a build: stops the running tool and removes folders of builds that have not finished.
- JsoncScan
- Character classes of a JSONC text: which characters are code (outside strings and comments) and which are inside comments.
- KeyPress
- One key press: a Key plus, for Key.char, the typed character.
- LaunchConfig
-
One Dart/Flutter configuration read from
.vscode/launch.json. - LaunchEntry
-
One run configuration to add to
.vscode/launch.json. - LaunchPlan
- What writing launch.json would do.
- Ledger
- The build ledger, stored as a single JSON document.
- LedgerExporter
- Turns ledger rows into CSV, TSV or JSON text.
- PathTemplate
-
A name or folder template such as
{app}-{flavor}-{mode}-{version}. - PlayConfig
-
Google Play upload settings, from the
play:section. - PlayPublisher
- Uploads an AAB to Google Play through the Android Publisher API.
- PlayUpload
- Where and how a build reached Google Play.
- PreBuildCommand
- One command of the pre-build plan.
- PreBuildConfig
- Which pre-build steps are ticked by default in the build menu.
- PreBuildRunner
- Runs the pre-build plan; stops at the first failing command.
- PreviewContext
- What previews use as the example build.
- ProcessRunner
- Runs external tools (flutter, firebase, sentry-cli). Swappable in tests.
- PruneResult
-
What pruneBuilds removed, or would remove with
dryRun. - PubspecVersion
-
version: 1.2.3+45from pubspec.yaml. - SelectItem
- One row of a selection list.
- SelectModel
- State and key handling of an arrow-key list, single or multi select. Pure and terminal-free, so it can be unit tested.
- SentryConfig
-
Sentry symbol upload settings, from the
sentry:section. - SettingChoice
- One selectable value of a SettingKind.choice setting.
- SettingDef
- One option in the settings screen: where it lives in the YAML file, how to show and edit it, and what it will do (the preview).
- SigningInspector
-
Reads the signing certificate of an APK or AAB with
apksignerorkeytool. Both are optional: without them inspect returns null. - Style
- ANSI colors and glyphs. With enabled false every method returns the text unchanged, so output stays clean in pipes, logs and tests.
- Suggestion
- One value found by reading the project, and why it was chosen.
- Symbolicator
- De-obfuscates stack traces with the symbols stored for a build.
- SymbolTargets
- Names of crash reporting tools symbols can be uploaded to.
- SymbolUploader
-
Uploads a build's debug symbols to Firebase Crashlytics and Sentry by
shelling out to the
firebaseandsentry-clitools. - TraceResult
- Outcome of one symbolication run.
- VerifyIssue
-
One thing
verifyfound wrong with the ledger or its folders. - VerifyReport
- Result of verifyLedger.
Enums
- ArtifactType
-
The kind of artifact
flutter buildproduces. - BuildMode
- Flutter build mode.
- BuildStatus
- Where a build is in its life, most advanced state wins.
- CheckLevel
- How a DoctorCheck came out.
- ExportFormat
- Output format for exporting ledger rows.
- Key
- A key the terminal can report to a prompt.
- LayoutPreset
-
Ready-made folder layouts for the build output. Pick one with
output_layout:in the config, or write your own template. - PreBuildStep
- Steps that can run once before a batch of builds.
- SelectOutcome
- What a key press did to a SelectModel.
- SettingKind
- How a setting is edited in the settings screen.
- TraceKind
- Kind of stack trace to de-obfuscate.
- UiMode
- How prompts read input.
Constants
- buildInfoName → const String
- Name of the file in each build folder that holds the ledger row.
- buildLogName → const String
-
Name of the file in each build folder that holds the
flutter buildoutput. -
launchModes
→ const List<
String> - Run modes written to launch.json, in order.
Functions
-
abiFromTrace(
String text) → String? -
The Android ABI folder name for a crash's
ABI: 'arm64'line, or null. -
addCommandOptions(
ArgParser parser) → void -
Adds the options of the non-interactive commands to
parser. -
addToGitignore(
FlutterProject project, List< String> entries) → void -
Appends
entriesto the project's.gitignore(created if missing). -
availablePreBuildSteps(
FlutterProject project) → List< PreBuildStep> -
Steps that make sense for
project(build_runner and gen-l10n only when the project uses them). -
buildMismatchWarning(
BuildRecord r, String text) → String? -
A warning when the trace's build id is not one of
r's, or null when it matches or the trace names none. -
copyDirectory(
Directory from, Directory to) → Future< void> -
Recursively copies the contents of
fromintoto, creatingtoif needed. -
dartBuildIds(
Directory dir) → Map< String, String> -
Build ids of the Dart symbols files in
dir(app.android-arm64.symbolsand so on), by file name. -
decodeJsonc(
String text) → Object? - Decodes JSONC, throwing FormatException when it is not valid.
-
defaultPreBuildSteps(
AppConfig config, List< PreBuildStep> available) → List<PreBuildStep> -
Which of
availableare ticked by default, from the config. -
describeCommand(
List< String> command) → String - Shell-style rendering of a command, for showing the user what runs.
-
detectEntryPoints(
FlutterProject project, Iterable< String> flavors) → Map<String, String> -
Dart files with a
main()anywhere in the project that are not the default (lib/main.dart) or a flavor's own main:main_admin.dartbecomes the entry pointadmin. -
detectTraceKind(
String text) → TraceKind -
Guesses what kind of stack trace
textis. -
elfBuildId(
Uint8List bytes) → String? - readElfBuildId for bytes already in memory.
-
endsInIncompleteSequence(
List< int> bytes) → bool -
True when
bytesends in the middle of an escape sequence (a lone ESC, orESC [without its final byte). Terminals normally deliver a whole sequence at once, but over a slow link the rest can arrive in a later read, so the caller should wait briefly for more bytes before deciding. -
entryPointPreview(
AppConfig c, PreviewContext x, String name, String path, {String? flavor}) → List< String> -
What building the entry point
name(a Dart file atpath) does. -
entryPointsFor(
AppConfig config, FlutterProject project, String? flavor) → List< EntryPoint> -
The entry points to build for
flavor, in menu order. -
findArray(
String text, String key) → (int, int)? -
Where the array under the top level
keystarts and ends:(open, close)are the indexes of[and]. Null when there is none. -
fitLine(
String line, int width) → String -
Cuts
lineto at mostwidthvisible characters, leaving ANSI escape sequences intact. A line that wraps would take two terminal rows and break the cursor arithmetic used to redraw a list in place. -
flavorSettings(
String flavor) → List< SettingDef> -
Settings of one flavor (
flavors.<name>.*). -
flutterBuildArgs(
BuildRequest r, {String? symbolsDir}) → List< String> -
Arguments after the flutter executable, e.g.
build appbundle --release --flavor dev -t lib/main_dev.dart .... -
formatBytes(
int bytes) → String -
Formats
bytesas a human-readable size such as1.5 MB. -
globalSettings(
) → List< SettingDef> - All project wide settings, in the order shown in the menu.
-
jsonText(
Object? value) → String - Pretty JSON for reports.
-
launchEntriesFor(
AppConfig config, FlutterProject project) → List< LaunchEntry> -
The run configurations for the project: every flavor × entry point ×
mode, with the flavor's dart-define file.
programis only set for an entry point other thanlib/main.dart. -
launchJsonFile(
FlutterProject project) → File -
The
.vscode/launch.jsonfile ofproject; it may not exist. -
launchLabel(
String s) → String -
clientDbandpre_prodbecomeCLIENT DBandPRE PROD. -
matchBuild(
Iterable< BuildRecord> records, String text) → BuildRecord? -
The build that produced the crash in
text, by Dart build id first, then by aversionName+versionCodethat appears in the report. Null when nothing matches or several builds share the version. -
mergeLaunchJson(
String? existing, List< LaunchEntry> entries) → String -
existingwithentriesadded to itsconfigurations, keeping everything else (comments, formatting, other configurations). With no existing text a new file is made. -
missingGitignoreEntries(
FlutterProject project, {required String outputDir, required String configFileName}) → List< String> -
Entries that should be in
.gitignorebut are not: the build output folder and the personal config overlay (flutter_buildkit.local.yaml). The main config is meant to be committed. -
newBuildId(
DateTime time) → String -
20261001-071230-a1b2: sortable and unique enough for a local ledger. -
normalizeName(
String s) → String -
Lower case letters and digits only, so
clientDb,client_dbandClient-DBcompare equal. -
parseDefaultApplicationId(
String gradle) → String? -
applicationIdinsidedefaultConfig { }. -
parseFirebaseAppId(
String googleServicesJson, String? packageName) → String? -
mobilesdk_app_idof the client matchingpackageName(or the first). -
parseGradleFlavors(
String gradle) → List< GradleFlavor> -
Flavor names (and application ids) declared in
productFlavors { }, for both Groovy (dev { }) and Kotlin DSL (create("dev") { }). -
parseKeys(
List< int> bytes) → List<KeyPress> -
Parses the bytes of one terminal read into key presses. A terminal
delivers a whole escape sequence in one read, so a lone ESC byte is the
Escape key and
ESC [ Ais the up arrow. -
parseLaunchConfigs(
String text) → List< LaunchConfig> -
Reads the
dartconfigurations of a launch.json text (JSONC: comments and trailing commas are fine). Throws FormatException for invalid text. -
parseNumberList(
String text) → List< int> ? -
Parses
1,3,1-3or1 3into the numbers they name (1-based), or null when the text is not a number list. -
pickDartSymbols(
String dartSymbolsDir, String traceText) → String - Picks the split-debug-info file for the trace's architecture, or the folder itself when it can't tell (flutter symbolize accepts both).
-
planLaunchJson(
AppConfig config, FlutterProject project) → LaunchPlan - Works out which entries to add to the project's launch.json.
-
planPreBuild(
AppConfig config, Iterable< PreBuildStep> steps) → List<PreBuildCommand> -
Commands for
steps, in the order that works:flutter cleanwipes.dart_tool, so it is always followed bypub getbefore code generation. -
pruneBuilds(
Ledger ledger, BuildManager manager, {int? logDays, int? symbolsKeepLast, bool dryRun = false, DateTime? now}) → Future< PruneResult> - Applies the retention settings.
-
pruneEmptyParents(
String root, Directory dir) → Future< void> -
Deletes
dirand its parents while they are empty, stopping beforerootitself. -
readElfBuildId(
File file) → String? -
The GNU build id of an ELF file as lower case hex, or null when
fileis not an ELF file with one. -
renderSelect(
String title, SelectModel m, {int maxRows = 12, Style style = Style.plain, int? width}) → List< String> -
Renders
modelas lines of text.maxRowsis how many rows the list may take, indicator lines included; the list scrolls to keep the cursor in view. With awidth, every line is cut to fit so none wraps onto a second terminal row. -
renderTable(
List< String> header, List<List< rows, {Style style = Style.plain, String decorate(int column, String paddedCell)?}) → StringString> > -
Renders
rowsas an aligned table. Cells are padded on their plain text first, thendecoratemay color them, so ANSI codes never break the alignment. -
scanDartEntries(
String dir, {Iterable< String> extra = const [], Iterable<String> skip = const []}) → List<DartEntry> -
Finds the entry points of the project at
dir, wherever they are: every Dart file underlib/that definesmain(), and files named likemain.dart,main_x.dartorx_main.dartelsewhere. Platform folders, tests, generated code and hidden folders are skipped.extraadds files (relative paths, e.g. a launch.jsonprogram) that exist even if they do not look like entry points. -
selectListRows(
int terminalRows, SelectModel m) → int -
The rows a list may use for its items and its "more above/below" lines,
given a terminal of
terminalRows. Everything else renderSelect draws (title, help, and the filter, number and error lines when shown) is subtracted, plus one row for the cursor line under the menu, so the menu never grows taller than the screen. Never less than 3. -
selectWindow(
int total, int cursor, int budget) → (int, int) -
Picks which items of a list of
totalto show inbudgetrows, keepingcursorin view. Returns(start, end). The "more above/below" lines take part of the budget, but only when items are really hidden: a list that fits shows every item and no indicator. -
splitCommandLine(
String text) → List< String> -
Splits a command line into arguments on whitespace; text inside single or
double quotes stays together and loses the quotes, so
"C:\Program Files\flutter\bin\flutter.bat" --verboseis two arguments. Backslashes are ordinary characters (they are Windows path separators). An unclosed quote runs to the end. -
stripJsonc(
String text) → String - Removes comments and trailing commas so the text is plain JSON.
-
suggestConfig(
FlutterProject project) → List< Suggestion> - Reads the Flutter project and proposes config values: flavors with their entry point, dart-define file, package name and Firebase app id, extra entry points, whether build_runner / gen-l10n / Crashlytics / Sentry are used, FVM, a layout that fits, and a Play key named in fastlane.
-
traceBuildId(
String text) → String? -
The Dart
build_ida crash report names (build_id: 'abc...'), or null. -
verifyLedger(
Ledger ledger, {bool hash = true}) → Future< VerifyReport> - Compares the ledger with the build folders on disk.
-
writeLaunchJson(
FlutterProject project, String text) → void -
Writes
textto.vscode/launch.json, keeping the old file aslaunch.json.bakonce.
Exceptions / Errors
- BuildException
-
Thrown when a build cannot be run or
flutter buildfails. - ConfigException
- Thrown when the config file or one of its values is invalid.
- ConsoleAbort
- Thrown when the user presses Ctrl-C inside a prompt.
- LaunchJsonException
- Thrown when launch.json cannot be read or changed safely.
- LedgerException
- Thrown when the ledger file cannot be read or a change is invalid.
- PathTemplateException
- Thrown when a name or folder template is invalid.
- PlayException
- Thrown when an upload to Google Play is rejected or cannot be attempted.
- PlayTrackInUseException
-
Thrown when the track already carries a staged or halted rollout that an
upload would drop. Upload again with
replaceExistingto go ahead. - PreBuildException
- Thrown when a pre-build command cannot start or exits non-zero.
- SymbolUploadException
- Thrown when symbols cannot be uploaded, e.g. none exist or settings are missing.
- TraceException
- Thrown when a trace cannot be symbolicated, e.g. symbols are missing.