flutter_flavor_orchestrator 0.5.0
flutter_flavor_orchestrator: ^0.5.0 copied to clipboard
A build-time orchestrator for managing Flutter flavors, native configurations, and provisioning files across Android and iOS platforms.
Changelog #
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
0.5.0 - 2026-02-28 #
Fixed #
build.gradle.ktsnot backed up or restored — The execution plan previously hardcodedandroid/app/build.gradleas the Gradle destination, so projects using Kotlin DSL (build.gradle.kts) were not included in the backup and their Gradle file remained modified after a rollback._buildAndroidOperationsis now async and checks forbuild.gradle.ktsfirst, mirroring the detection logic ofAndroidProcessor.- Newly created files and directories not removed on rollback — Files and
directories that did not exist before an
apply(e.g. a newlib/config/constants.dart, or an entirelib/theme/directory populated viafile_mappings) remained in the project after a rollback because the backup only tracked files that were present before the apply.BackupRecordnow carries anewPathslist (serialised asnew_pathsinmetadata.json) of absolute paths that were tracked as non-existent at backup time.BackupManager.restoredeletes every path innewPathsafter restoring the backed-up files. - Existing destination directories not fully backed up —
copyDirectoryplan operations with an existing destination only recorded the top-level path in the old code; the individual files inside were never snapshotted.createBackupnow iterates the directory tree and backs up each file, enabling full restore of any directory that was overwritten by apply.
Added (0.5.0 original features) #
- Automatic backup before non-dry-run
apply— Before eachapplyrun (when--dry-runis not set) the orchestrator snapshots every destination file referenced by the execution plan into.ffo/backups/<id>/. Ametadata.jsonfile records the flavor name, timestamp, file list, pre-apply checksums, and (after the apply completes) post-apply checksums. rollbackCLI command — Restores project files to their pre-apply state.rollback --latest— Restores from the most recent backup.rollback --id <id>— Restores from a specific backup by its identifier (shown in the apply log).rollback --force— Overrides checksum conflicts when files have been manually edited after the last apply.- Exit code
0on success;1if no backup is found or a conflict prevents the restore.
FlavorOrchestrator.rollbackLatest({bool force})— Public method that restores the most recent backup programmatically.FlavorOrchestrator.rollbackById(String id, {bool force})— Public method that restores a specific backup by ID.FlavorOrchestrator.listBackups()— Public method returning all available backups sorted newest-first.BackupManager(lib/src/utils/backup_manager.dart) — New utility class that implements persistent backup creation, finalisation (post-apply checksums), listing, and file restoration with conflict detection.BackupRecordandBackupEntry— Immutable data models describing a backup snapshot and its per-file entries, both withtoJson()/fromJson()support and exported as public API.cryptopackage dependency — Used for SHA-256 checksum computation..ffo/in.gitignore— Backup artifacts are not tracked by Git.- Tests —
test/utils/backup_manager_test.dartcovers:- Backup directory and
metadata.jsoncreation - Backed-up file content integrity
- Pre-apply checksum correctness
- Skipping non-existent destination files
- Post-apply checksum persistence via
finalizeBackup listBackups/latestBackup(empty, single, newest-first ordering)- Successful restore with content verification
- Empty-entries restore returning
true - Conflict detection (returns
falsewithout--force) --forceoverrides conflict and restores correctly- Restore without post-apply checksums (no false conflicts)
BackupRecordJSON roundtrip
- Backup directory and
- Integration tests —
test/orchestrator_rollback_test.dartcovers:rollbackLatestreturnsfalsewhen no backups exist- Full apply → rollback cycle restoring original file content
- Dry-run apply does not create a backup
rollbackByIdreturnsfalsefor unknown IDlistBackupsreturns empty list before any applylistBackupsreturns backup after a non-dry-run apply
Changed #
FlavorOrchestrator.applyFlavor()— Now creates a persistent backup (viaBackupManager.createBackup) before mutating files, and finalises it (viaBackupManager.finalizeBackup) after a successful commit. Dry-run mode is unchanged.- CLI help —
rollbackcommand added toCOMMANDSsection with usage examples. - Version bumped to
0.5.0.
0.4.0 - 2026-02-24 #
Added #
plancommand - Preview the operations that would be performed for a flavor without mutating any files.- Options:
--flavor(required),--config,--platform,--verbose,--output(text|json). - Text output shows a per-platform summary with operation kind, description, source and destination paths.
- JSON output is the serialised
ExecutionPlan.toJson()— deterministic and CI-friendly. - Exit code
0on success;1if the flavor is not found or config is invalid.
- Options:
FlavorOrchestrator.planFlavor()- New public method that returns theExecutionPlanfor a flavor without executing it. Reuses the private_buildExecutionPlan()pipeline, so the plan is guaranteed to match the operations thatapplyFlavor()would perform.- Tests —
test/orchestrator_plan_test.dartcovers:- Flavor name and platform propagation
- Android-only and iOS-only plan filtering
- Asset
copyFileoperation for existing file mappings skipoperation for missing source paths- No-mutation guarantee (file system unchanged after
planFlavor) - Operation order (android → ios → assets)
toJson()top-level key stabilitytoJson()operation entries contain required keys- Error path: unknown flavor throws
FormatException - Provisioning path adds
copyFileoperation in Android plan
Changed #
- CLI help —
plancommand added toCOMMANDSsection and usage examples. - Version bumped to
0.4.0.
0.3.0 - 2026-02-22 #
Added #
- Typed Operation Models - New immutable models provide a structured representation of every step the orchestrator performs:
OperationKindenum — four operation types:copyFile,copyDirectory,writeFile,skip.PlannedOperation— describes a single step (kind, description, source/destination paths, platform). Serialisable viatoJson().ExecutionPlan— ordered collection ofPlannedOperations for a flavor apply, with computed counts (totalOperations,activeOperations,skippedOperations) andtoJson()for machine-readable output. Includes static platform constants (platformAndroid,platformIos,platformAssets).
- Shared Planning Refactor -
FlavorOrchestratornow builds anExecutionPlanas an internal planning phase before executing operations, via the new private_buildExecutionPlan()method. This is the foundation reused by bothapplyand the upcomingplancommand (v0.4.0). AssetProcessor.planFileMappings()- New method generates aList<PlannedOperation>describing file-mapping operations without touching the file system. Used by_buildExecutionPlan()and available for future preview commands.- Exported Models -
ExecutionPlan,PlannedOperation, andOperationKindare now part of the public library API. - Test Coverage - New
test/models/execution_plan_test.dartcovers:OperationKindenum values and namesPlannedOperationconstruction,toJson()serialization, and null-omissionExecutionPlancounts,forPlatform()filtering,toJson()shapeAssetProcessor.planFileMappings()for file, directory, and missing-source scenarios, including a no-mutation guarantee
Changed #
FlavorOrchestrator.applyFlavor()- Now calls_buildExecutionPlan()at the start of each apply run and logs active/skipped operation counts at debug level. Execution behavior is unchanged.- Documentation - README updated with v0.3.0 highlights and architecture description.
0.2.0 - 2026-02-22 #
Added #
- Apply Dry-run Mode - New
--dry-run(-d) option forapplyexecutes the full apply flow without changing files. - Dry-run Destination Validation - Dry-run now validates destination files/directories exist for write/copy operations.
- Dry-run Test Coverage - Added tests for dry-run validation behavior and no-write guarantees.
Changed #
- CLI Help and Usage - Updated command help, examples, and version output for
0.2.0. - Documentation Refresh - README updated with dry-run examples and behavior details.
0.1.9 - 2026-02-22 #
Added #
- External YAML Configuration Path - New CLI option
--config(-c) for loading flavor configuration from a YAML file outside the project root, designed for CI/CD workflows (for example Jenkins). - Programmatic External Config Support -
FlavorOrchestratornow acceptsconfigPathto load configuration from an explicit external YAML file. - Parser External Path Handling -
ConfigParsernow supports explicit external config paths (absolute or project-relative) with clear missing-file errors. - Test Coverage for External Config - Added parser tests for:
- absolute external config path
- project-relative external config path
- missing external config file behavior
Changed #
- CLI Commands Updated -
apply,list,info, andvalidatenow accept--config. - Documentation Updates - README and example docs updated with 0.1.9 references and CI/CD examples for external config usage.
0.1.8 - 2026-02-16 #
Added #
- Enhanced Example App UI - Completely redesigned example app to visually demonstrate flavor-specific resources:
- App Icon Display - Shows flavor-specific SVG icons (dev/staging/production) with rounded corners and shadow
- Environment Info Section - Displays current flavor label and debug banner status
- Color Showcase - Visual color chips displaying all flavor colors (primary, accent, background, success, warning, error, text)
- Typography Preview - Live examples of heading, body, and caption text with size information
- Configuration Display - Shows all flavor-specific config values (API URL, environment, timeout, analytics, debug mode)
- Scrollable Layout - ListView with card-based sections for better organization and readability
- flutter_svg Dependency - Added
flutter_svg: ^2.0.10+1to example app for SVG icon rendering - Icon Assets Configuration - Added asset paths for flavor-specific SVG icons in example pubspec.yaml
- Fallback Files - Created placeholder files in
lib/theme/andlib/config/that display "NO FLAVOR" when orchestrator hasn't been appliedlib/theme/app_theme.dart- Fallback AppTheme class with grey colorslib/theme/colors.dart- Fallback ColorPalette classlib/theme/typography.dart- Fallback Typography classlib/config/app_config.dart- Fallback AppConfig class
Changed #
- Example App Structure - Updated
example/lib/main.dartto use class-based theme/config imports matching the flavor orchestrator's file structure - Theme Integration - App now uses
AppTheme.lightThemeandAppTheme.showDebugBannerfrom copied flavor files - Color Handling - Updated to work with hex color strings from
ColorPaletteclass, converting to Flutter Color objects - Typography Namespace - Added import prefix
app_typographyto avoid conflicts with Flutter's built-in Typography class - Example App Behavior - App now provides immediate visual feedback when different flavors are applied, making testing more intuitive
Fixed #
- Import Conflicts - Resolved naming conflicts between custom Typography class and Flutter's Typography
- Const TextStyle Issues - Removed const modifiers where dynamic values from flavor configs are used
- Compilation Errors - Fixed all type mismatches and undefined reference errors when flavor files are applied
Technical Details #
- Example app now correctly imports and uses:
AppThemeclass for theme configuration and environment labelsColorPaletteclass for hex color definitionsTypographyclass for font and size specificationsAppConfigclass for API and feature configuration
- Hex color string to Color conversion implemented for visual color chips
- Dynamic icon path selection based on environment label (dev/staging/production)
0.1.7 - 2026-02-15 #
Added #
- File Mappings Feature - New
file_mappingsconfiguration field inFlavorConfigfor flavor-specific file and folder copying - AssetProcessor - New processor for handling recursive file and directory copying from source to destination paths
- Directory Replacement Mode - New
replace_destination_directoriesconfiguration option for safe atomic directory replacement:- Existing directories are temporarily renamed before copying new content
- Automatic rollback on failure restores original directory
- Ensures atomic replacement - destination is either completely replaced or unchanged
- Only affects directory mappings in
file_mappings, not individual files
- Automatic Directory Traversal - Supports both individual files and recursive directory copying with automatic subdirectory creation
- Comprehensive Logging - Detailed logging for every file and folder operation with progress tracking
- Example Assets - Added example icon files organized by flavor (dev/staging/production) in
example/assets/icons/ - Example Resources - Added flavor-specific theme directories in
example/resources/demonstrating directory replacement - Example Configuration Files - Added flavor-specific app configuration examples in
example/configs/ - Extensive Test Coverage - New test suite for
AssetProcessorcovering:- Single file copying
- Multiple file mappings
- Recursive directory copying
- File replacement scenarios
- Mixed file and directory operations
- Empty directory handling
- Non-existent source path handling
- Multi-flavor scenarios
- Directory replacement with backup/restore
- Failure recovery and rollback
- Nested directory structure handling
Changed #
- FlavorConfig Model - Extended with
fileMappingsproperty (Map<String, String>) for defining source→destination path mappings - Orchestrator Integration - Updated
FlavorOrchestrator.applyFlavor()to process file mappings after platform-specific processors - Example Configuration - Updated
example/flavor_config.yamlwith practicalfile_mappingsexamples for all flavors
Features #
- Copy individual files from source to destination with automatic directory creation
- Recursively copy entire directory trees while maintaining structure
- Automatically replace existing files at destination
- Skip non-existent source paths with warning logs
- Track all operations for backup and rollback support
- Detailed logging of each copied file with relative paths
0.1.6 - 2026-02-15 #
Fixed #
- Android SDK version handling - Fixed regex patterns to properly match and replace SDK versions that reference variables (e.g.,
flutter.minSdkVersion) - SDK version insertion now properly adds missing values to
defaultConfigorandroidblocks when they don't exist - Custom Gradle configuration now preserves proper indentation and provides warning about syntax compatibility
Changed #
- Improved regex patterns for
minSdk,targetSdk, andcompileSdkto match both numeric values and variable references (e.g.,[\w.]+instead of\d+) - Added fallback logic to insert SDK version entries when they are missing from build files
- Enhanced
_addCustomGradleConfig()to detect and preserve existing indentation patterns
Added #
- Comprehensive test coverage for SDK version insertion scenarios
- Tests for updating SDK versions with variable references (e.g.,
flutter.minSdkVersion) - Test for validating build.gradle.kts structure after modifications
- Documentation file
CUSTOM_GRADLE_CONFIG.mdin example project explaining Groovy vs Kotlin DSL syntax differences - Fixed example project's build.gradle.kts to use proper Kotlin DSL syntax for product flavors
0.1.5 - 2026-02-08 #
Changed #
- AndroidManifest.xml formatting preservation - The processor now preserves the original structure, indentation, and whitespace when updating AndroidManifest.xml files
- Replaced XML document parsing and serialization with string-based regex replacements to maintain exact formatting
- Intelligent indentation detection for metadata entries (automatically detects spaces or tabs)
Added #
- New helper methods for format-preserving updates:
_updateManifestPackage(),_updateManifestAppName(), and_detectMetadataIndentation() - Comprehensive test coverage for formatting preservation including:
- Tests for space-based indentation
- Tests for tab-based indentation
- Tests for mixed whitespace scenarios
- Tests for metadata addition with correct indentation detection
Fixed #
- All flutter analyze issues resolved for code quality compliance
0.1.3 - 2026-02-08 #
Added #
- Support for both Groovy (
build.gradle) and Kotlin (build.gradle.kts) build scripts in Android processor - Automatic detection of build script type with preference for
.ktsfiles when both exist - Comprehensive test coverage for both Groovy and Kotlin build script formats
Changed #
- Enhanced Android processor to handle multiple build script syntaxes
- Updated documentation to reflect support for both build script types
Fixed #
- Fixed all flutter analyze issues for code quality compliance
0.1.2 - 2026-02-08 #
0.1.0 - 2026-02-08 #
Added #
- Initial release of Flutter Flavor Orchestrator
- CLI tool for managing Flutter flavor configurations
- YAML-based configuration parser supporting:
- Bundle ID and Package Name management
- App name customization
- Icon asset paths configuration
- Custom metadata injection
- Asset management per flavor
- Provisioning file handling (Firebase configurations)
- Android native file manipulation:
- AndroidManifest.xml modification via XML package
- build.gradle flavor configuration injection
- google-services.json automatic placement
- iOS native file manipulation:
- Info.plist configuration updates
- Bundle identifier management
- GoogleService-Info.plist automatic placement
- Scheme configuration support
- File management utilities with backup and rollback capabilities
- Comprehensive error handling and logging system
- Clean architecture implementation with separation of concerns
- Full API documentation with doc comments
- Unit test suite for core functionality
- Example project demonstrating all features
- Enterprise-level code quality with strict linting rules
Features #
- Command-line interface with intuitive arguments
- Support for multiple flavors (dev, staging, production, etc.)
- Atomic file operations with automatic rollback on errors
- Detailed logging for debugging and auditing
- Extensible architecture for future enhancements