flutter_flavor_orchestrator 0.1.9
flutter_flavor_orchestrator: ^0.1.9 copied to clipboard
A build-time orchestrator for managing Flutter flavors, native configurations, and provisioning files across Android and iOS platforms.
Flutter Flavor Orchestrator #
โ Buy me a coffee on Ko-fi - If this package helps you, consider supporting my work!
Build-time orchestration for Flutter flavors across Android and iOS. Configure environment-specific app identity, native metadata, provisioning files, and resource mappings from a single YAML source.
What's New (v0.1.9) #
- External YAML Config Path (
--config) - Load flavor configuration from a YAML file outside project root (absolute or relative path) - CI/CD Friendly Workflow - Keep production config outside repository and inject it at runtime (for example Jenkins)
- Programmatic Config Path Support -
FlavorOrchestratorsupportsconfigPathfor explicit external configuration loading - Backward-Compatible Fallback - Existing
flavor_config.yaml/pubspec.yamlbehavior remains unchanged when--configis not provided
โจ Features #
- Flavor management - Configure dev, staging, production, and custom environments
- Cross-platform native updates - Apply changes to Android and iOS project files
- Native file processors - Update AndroidManifest, Gradle/Gradle KTS, Info.plist, and Xcode project settings
- Format preservation - Keep original AndroidManifest indentation and structure
- Provisioning support - Manage
google-services.jsonandGoogleService-Info.plist - File mappings - Copy flavor-specific files and recursive directories
- Atomic directory replacement - Backup/restore-safe replacement of destination directories
- Safe operations - Automatic backup and rollback on failures
- YAML-driven configuration - Single declarative config for all flavors
- CLI workflow -
apply,list,info, andvalidatecommands - Validation and error handling - Pre-checks for config, files, and required fields
- Documentation and examples - Full example project and practical guides
๐ Table of Contents #
- Installation
- What's New (v0.1.9)
- Quick Start
- Pub.dev Workflow
- Configuration
- CLI Usage
- What Gets Modified
- Advanced Configuration
- Architecture
- Examples
- Example Project Hints
- API Documentation
- Contributing
- License
๐ Installation #
Add flutter_flavor_orchestrator to your pubspec.yaml dev dependencies:
dev_dependencies:
flutter_flavor_orchestrator: ^0.1.9
Then run:
flutter pub get
Activate the CLI tool globally (optional):
dart pub global activate flutter_flavor_orchestrator
โก Quick Start #
1. Create Configuration File #
Create a flavor_config.yaml file in your project root:
dev:
bundle_id: com.example.myapp.dev
app_name: MyApp Dev
metadata:
API_URL: https://dev-api.example.com
provisioning:
android_google_services: configs/dev/google-services.json
ios_google_service: configs/dev/GoogleService-Info.plist
production:
bundle_id: com.example.myapp
app_name: MyApp
metadata:
API_URL: https://api.example.com
provisioning:
android_google_services: configs/production/google-services.json
ios_google_service: configs/production/GoogleService-Info.plist
2. Apply a Flavor #
# From your project root
flutter pub run flutter_flavor_orchestrator apply --flavor dev
# Alternative (Dart-native invocation)
dart run flutter_flavor_orchestrator apply --flavor dev
3. Build Your App #
flutter clean
flutter pub get
flutter build apk # or flutter build ios
That's it! Your app is now configured for the dev flavor.
Pub.dev Workflow #
Use this sequence when integrating the package into a real app:
# 1) Install deps
flutter pub get
# 2) Validate configuration before applying
flutter pub run flutter_flavor_orchestrator validate
# 3) Inspect available flavors
flutter pub run flutter_flavor_orchestrator list
# 4) Apply flavor
flutter pub run flutter_flavor_orchestrator apply --flavor dev --verbose
# 5) Build or run
flutter run
Recommended for CI/CD:
- Run
validateas an early pipeline step - Use explicit flavor names (
dev,staging,production) in build jobs - Keep flavor-specific files under
configs/,assets/, andresources/ - Pass
--configto load a YAML file from a secure external path (for example Jenkins workspace/secret mounts)
โ๏ธ Configuration #
Configuration File Location #
You can place your flavor configuration in either:
- Dedicated file:
flavor_config.yamlin your project root (recommended) - In pubspec.yaml: Under a
flavor_configsection - External file path: Any YAML file passed at runtime with
--config
External path examples:
flutter_flavor_orchestrator apply --flavor production --config /secure/jenkins/flavor_config.yaml
flutter_flavor_orchestrator validate --config ./ci/flavor_config.yaml
Configuration Options #
Each flavor supports the following configuration options:
| Option | Type | Required | Description |
|---|---|---|---|
bundle_id |
String | โ | Bundle identifier (iOS) / Package name (Android) |
app_name |
String | โ | Display name of the application |
icon_path |
String | โ | Path to app icon assets |
metadata |
Map | โ | Custom key-value pairs to inject into manifests |
assets |
List | โ | Flavor-specific asset paths |
dependencies |
Map | โ | Flavor-specific dependency overrides |
provisioning |
Object | โ | Provisioning file configuration |
android_min_sdk_version |
Integer | โ | Android minimum SDK version |
android_target_sdk_version |
Integer | โ | Android target SDK version |
android_compile_sdk_version |
Integer | โ | Android compile SDK version |
ios_min_version |
String | โ | iOS minimum deployment target |
custom_gradle_config |
Map | โ | Custom Gradle configuration snippets |
custom_info_plist_entries |
Map | โ | Custom Info.plist entries |
file_mappings |
Map | โ | Flavor-specific file/folder copying (sourceโdestination) |
replace_destination_directories |
Boolean | โ | Replace existing directories completely (default: false) |
Provisioning Configuration #
provisioning:
android_google_services: path/to/google-services.json
ios_google_service: path/to/GoogleService-Info.plist
additional_files:
destination/path: source/path
File Mappings (New in v0.1.7) #
Copy flavor-specific files and folders from source to destination paths. Supports both individual files and recursive directory copying:
dev:
bundle_id: com.example.app.dev
app_name: MyApp Dev
# Enable complete directory replacement (optional, default: false)
replace_destination_directories: true
file_mappings:
# Copy individual configuration files
'lib/config/app_config.dart': 'configs/dev/app_config.dart'
'lib/config/constants.dart': 'configs/shared/constants.dart'
# Copy flavor-specific icons
'assets/app_icon.svg': 'assets/icons/dev/app_icon.svg'
# Recursively copy entire directories
'android/app/src/main/res/drawable': 'assets/dev/android/drawables'
'ios/Runner/Assets.xcassets': 'assets/dev/ios/assets'
# Replace entire theme directory (useful with replace_destination_directories)
'lib/theme': 'resources/dev/themes'
production:
bundle_id: com.example.app
app_name: MyApp
replace_destination_directories: true
file_mappings:
'lib/config/app_config.dart': 'configs/production/app_config.dart'
'lib/config/constants.dart': 'configs/shared/constants.dart'
'assets/app_icon.svg': 'assets/icons/production/app_icon.svg'
'lib/theme': 'resources/production/themes'
Features:
- ๐ Copy individual files or entire directory trees recursively
- ๐ Automatically replaces existing files at destination
- ๐ Creates destination directories if they don't exist
- ๐ Detailed logging for each file operation
- โ ๏ธ Skips non-existent source paths with warnings
- ๐ Full backup and rollback support
Directory Replacement Mode:
When replace_destination_directories: true:
- ๐ Safe Backup: Existing destination directory is temporarily renamed
- ๐ Copy New: Complete directory tree is copied from source
- โ Success: Backup directory is removed
- โ Failure: Original directory is automatically restored
This ensures atomic directory replacement - the destination is either completely replaced or left unchanged.
See example/assets/icons/README.md and example/resources/README.md for practical examples.
Complete Example #
See example/flavor_config.yaml for a comprehensive configuration example.
๐ฎ CLI Usage #
The package provides a powerful command-line interface:
Apply Command #
Apply a flavor configuration to your project:
# Apply to both platforms
flutter_flavor_orchestrator apply --flavor dev
# Apply using an external YAML config file
flutter_flavor_orchestrator apply --flavor production --config /secure/jenkins/flavor_config.yaml
# Apply to Android only
flutter_flavor_orchestrator apply --flavor staging --platform android
# Apply to iOS only
flutter_flavor_orchestrator apply --flavor production --platform ios
# Enable verbose output
flutter_flavor_orchestrator apply --flavor dev --verbose
Output includes:
file_mappingscount for the selected flavorreplace_destination_directoriesvalue- Mapping details (
destination <- source) when--verboseis enabled
List Command #
List all available flavors:
flutter_flavor_orchestrator list
# List flavors from external YAML
flutter_flavor_orchestrator list --config ./ci/flavor_config.yaml
Output includes, for each flavor:
file_mappingscountreplace_destination_directoriesvalue
Info Command #
Display detailed information about a specific flavor:
flutter_flavor_orchestrator info --flavor production
# Inspect a flavor from external YAML
flutter_flavor_orchestrator info --flavor production --config ./ci/flavor_config.yaml
Output includes:
- Full
file_mappingsentries (destination <- source) replace_destination_directoriesvalue- Explanation of when directory replacement applies and rollback behavior
Validate Command #
Validate all flavor configurations:
flutter_flavor_orchestrator validate
# Validate external YAML
flutter_flavor_orchestrator validate --config ./ci/flavor_config.yaml
Output includes, for each flavor:
file_mappingscountreplace_destination_directoriesvalue- A note when directory replacement is enabled for directory mappings
Help #
Display help information:
flutter_flavor_orchestrator --help
๐จ What Gets Modified #
Android #
When you apply a flavor, the following Android files are automatically updated:
android/app/src/main/AndroidManifest.xml
- โ๏ธ Package name (
packageattribute) - โ๏ธ Application label (
android:label) - โ๏ธ Metadata entries (
<meta-data>tags) - ๐จ Preserves original formatting - Maintains exact indentation, whitespace, and structure
android/app/build.gradle or android/app/build.gradle.kts
- โ๏ธ Application ID (
applicationId) - โ๏ธ SDK versions (
minSdkVersion,targetSdkVersion,compileSdkVersion) - โ๏ธ Custom Gradle configuration
- ๐ Supports both Groovy (
.gradle) and Kotlin (.gradle.kts) build scripts
android/app/google-services.json
- ๐ Copied from configured path
iOS #
ios/Runner/Info.plist
- โ๏ธ Bundle display name (
CFBundleDisplayName) - โ๏ธ Bundle identifier (
CFBundleIdentifier) - โ๏ธ Minimum OS version (
MinimumOSVersion) - โ๏ธ Custom plist entries
ios/Runner.xcodeproj/project.pbxproj
- โ๏ธ Product bundle identifier (
PRODUCT_BUNDLE_IDENTIFIER) - โ๏ธ Deployment target (
IPHONEOS_DEPLOYMENT_TARGET)
ios/Runner/GoogleService-Info.plist
- ๐ Copied from configured path
๐๏ธ Advanced Configuration #
Custom Gradle Configuration #
Inject custom Gradle snippets:
custom_gradle_config:
defaultConfig: |
buildConfigField "String", "API_URL", "\"https://api.example.com\""
buildConfigField "boolean", "DEBUG_MODE", "false"
buildTypes: |
release {
shrinkResources true
minifyEnabled true
}
Custom Info.plist Entries #
Add custom iOS configuration:
custom_info_plist_entries:
NSAppTransportSecurity:
NSAllowsArbitraryLoads: true
UIBackgroundModes:
- fetch
- remote-notification
ITSAppUsesNonExemptEncryption: false
Metadata Injection #
Add custom metadata to both platforms:
metadata:
API_URL: https://api.example.com
API_KEY: your_api_key
FEATURE_FLAG_X: true
MAX_RETRIES: 3
Android: Added as <meta-data> tags in AndroidManifest.xml
iOS: Added as custom entries in Info.plist
๐๏ธ Architecture #
The package follows Clean Architecture principles:
lib/
โโโ src/
โ โโโ models/ # Data models
โ โ โโโ flavor_config.dart
โ โ โโโ provisioning_config.dart
โ โโโ processors/ # Platform processors
โ โ โโโ android_processor.dart
โ โ โโโ ios_processor.dart
โ โโโ utils/ # Utilities
โ โ โโโ file_manager.dart
โ โ โโโ logger.dart
โ โโโ config_parser.dart # Configuration parsing
โ โโโ orchestrator.dart # Main orchestrator
โโโ flutter_flavor_orchestrator.dart # Public API
Key Components #
- FlavorOrchestrator: Coordinates the entire process
- ConfigParser: Parses and validates YAML configurations
- AndroidProcessor: Handles Android-specific modifications
- IosProcessor: Handles iOS-specific modifications
- FileManager: Provides safe file operations with backup/rollback
๐ Examples #
Check out the example directory for a complete working example with:
- โ Multiple flavor configurations
- โ Firebase integration
- โ Custom metadata
- โ Platform-specific configurations
- โ Complete Flutter app
- โ File mappings and safe directory replacement
- โ Visual flavor verification in the running UI
Example Project Hints #
The example app is designed so you can immediately see flavor changes on screen.
Quick demo in example/ #
cd example
flutter pub get
# Apply development flavor
flutter pub run flutter_flavor_orchestrator apply --flavor dev --verbose
flutter run
Then switch flavor and run again:
flutter pub run flutter_flavor_orchestrator apply --flavor staging --verbose
flutter run
What to look for in the UI:
- Flavor-specific SVG icon
- Environment/debug banner values
- Color and typography preview from copied theme files
- API/config values from copied
lib/config/app_config.dart
Useful example references:
- Full config: example/flavor_config.yaml
- File mapping assets: example/assets/icons/README.md
- Theme replacement resources: example/resources/README.md
- Gradle syntax notes: example/CUSTOM_GRADLE_CONFIG.md
๐ API Documentation #
Programmatic Usage #
You can also use the package programmatically in your Dart code:
import 'package:flutter_flavor_orchestrator/flutter_flavor_orchestrator.dart';
void main() async {
final orchestrator = FlavorOrchestrator(
projectRoot: '/path/to/project',
configPath: '/secure/jenkins/flavor_config.yaml',
verbose: true,
);
// Apply a flavor
final success = await orchestrator.applyFlavor(
'dev',
platforms: ['android', 'ios'],
);
// List flavors
final flavors = await orchestrator.listFlavors();
// Validate configurations
final valid = await orchestrator.validateConfigurations();
}
Core Classes #
- FlavorConfig: Represents a complete flavor configuration
- ProvisioningConfig: Provisioning file configuration
- ConfigParser: Configuration parsing and validation
- FlavorOrchestrator: Main orchestration logic
See the API documentation for detailed class and method documentation.
๐ Safety Features #
Automatic Backups #
The orchestrator automatically creates backups of all modified files before making changes. If an error occurs, all changes are automatically rolled back.
Validation #
All configurations are validated before being applied:
- โ Required fields presence
- โ Bundle ID format validation
- โ File existence checks
- โ YAML syntax validation
Error Handling #
Comprehensive error handling with clear, actionable error messages:
- ๐ด Missing configuration files
- ๐ด Invalid bundle ID formats
- ๐ด Missing native directories
- ๐ด File operation failures
๐งช Testing #
The package includes a comprehensive test suite:
# Run all tests
dart test
# Run with coverage
dart test --coverage
๐ค Contributing #
Contributions are welcome! Please read our Contributing Guide for details on our code of conduct and the process for submitting pull requests.
๐ License #
This project is licensed under the MIT License - see the LICENSE file for details.
๐ Acknowledgments #
- Built with โค๏ธ by Alessio La Mantia
- Inspired by the need for better flavor management in Flutter projects
- Uses excellent packages:
args,yaml,xml,path
๐ Support #
- ๐ง Report issues on GitHub Issues
- ๐ฌ Ask questions on Stack Overflow
- ๐ Read the documentation
๐บ๏ธ Roadmap #
- โ Support for additional platforms (macOS, Windows, Linux)
- โ Icon generation integration
- โ Enhanced scheme management for iOS
- โ Build flavor integration with flutter build commands
- โ Interactive CLI mode
- โ Configuration templates
- โ Migration tools from other flavor solutions
Made with โค๏ธ for the Flutter community