flutter_flavor_orchestrator 0.3.0 copy "flutter_flavor_orchestrator: ^0.3.0" to clipboard
flutter_flavor_orchestrator: ^0.3.0 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!

CI pub package pub points popularity likes License: MIT Ko-fi

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.3.0) #

  • Typed Operation ModelsOperationKind, PlannedOperation, ExecutionPlan added as public API; each operation is now a first-class immutable value with toJson() support
  • Shared Planning FoundationFlavorOrchestrator builds an ExecutionPlan before executing any apply; lays the groundwork for the upcoming plan command
  • AssetProcessor.planFileMappings() — generate file-mapping operations without touching the file system (preview without side-effects)

Previous: What's New (v0.2.0) #

  • Dry-run Apply Mode (--dry-run) - Execute full apply processing without changing files
  • Destination Presence Validation - Dry-run validates destination files/directories exist for every write/copy path
  • Safer Preflight for CI/CD - Validate flavor application end-to-end before running a real apply

✨ 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.json and GoogleService-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
  • Typed execution plan - ExecutionPlan, PlannedOperation, OperationKind models with toJson() (foundation for the upcoming plan command)
  • CLI workflow - apply, list, info, and validate commands
  • 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 #

Add flutter_flavor_orchestrator to your pubspec.yaml dev dependencies:

dev_dependencies:
  flutter_flavor_orchestrator: ^0.3.0

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 validate as an early pipeline step
  • Use explicit flavor names (dev, staging, production) in build jobs
  • Keep flavor-specific files under configs/, assets/, and resources/
  • Pass --config to 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:

  1. Dedicated file: flavor_config.yaml in your project root (recommended)
  2. In pubspec.yaml: Under a flavor_config section
  3. 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:

  1. 🔒 Safe Backup: Existing destination directory is temporarily renamed
  2. 📋 Copy New: Complete directory tree is copied from source
  3. Success: Backup directory is removed
  4. 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

# Dry-run apply (execute checks without changing files)
flutter_flavor_orchestrator apply --flavor dev --dry-run

# 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_mappings count for the selected flavor
  • replace_destination_directories value
  • Mapping details (destination <- source) when --verbose is enabled
  • In --dry-run, all operations are validated and no files are modified

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_mappings count
  • replace_destination_directories value

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_mappings entries (destination <- source)
  • replace_destination_directories value
  • 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_mappings count
  • replace_destination_directories value
  • 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 (package attribute)
  • ✏️ 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
│   │   ├── execution_plan.dart      # Ordered plan of PlannedOperations (v0.3.0)
│   │   ├── flavor_config.dart
│   │   ├── operation_kind.dart      # OperationKind enum (v0.3.0)
│   │   ├── planned_operation.dart   # Single step descriptor (v0.3.0)
│   │   └── provisioning_config.dart
│   ├── processors/          # Platform processors
│   │   ├── android_processor.dart
│   │   ├── asset_processor.dart     # planFileMappings() added (v0.3.0)
│   │   └── ios_processor.dart
│   ├── utils/              # Utilities
│   │   ├── file_manager.dart
│   │   └── logger.dart
│   ├── config_parser.dart  # Configuration parsing
│   └── orchestrator.dart   # Main orchestrator (_buildExecutionPlan, v0.3.0)
└── flutter_flavor_orchestrator.dart  # Public API

Key Components #

  • FlavorOrchestrator: Coordinates the entire process; builds an ExecutionPlan before applying
  • ConfigParser: Parses and validates YAML configurations
  • AndroidProcessor: Handles Android-specific modifications
  • IosProcessor: Handles iOS-specific modifications
  • AssetProcessor: Handles file-mapping copy and planning operations
  • ExecutionPlan / PlannedOperation / OperationKind: Typed, immutable operation models with JSON serialisation
  • 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
  • ExecutionPlan: Ordered list of PlannedOperations for a flavor; serialisable via toJson()
  • PlannedOperation: Immutable descriptor of a single orchestration step with kind, paths, and platform
  • OperationKind: Enum — copyFile, copyDirectory, writeFile, skip
  • 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 #

🗺️ Roadmap #

The full roadmap is in ROADMAP.md. Here is a compact summary of progress and upcoming milestones toward the v1.0.0 stable release.

Released #

Version Highlights
v0.1.x Initial CLI (apply, list, info, validate), Android/iOS processors, file mappings, dry-run, external config path
v0.2.0 Dry-run destination-presence validation, safer CI preflight
v0.3.0 OperationKind, PlannedOperation, ExecutionPlan typed models · shared _buildExecutionPlan() in orchestrator · AssetProcessor.planFileMappings()

Upcoming #

Version Theme Key deliverable
v0.4.0 Preview plan command — preview operations without mutating files; reuses ExecutionPlan from v0.3.0
v0.5.0 Safety rollback command + timestamped backup before every non-dry-run apply
v0.6.0 Conflict protection Duplicate-target detection and --force guardrails
v0.7.0 Automation contract --output json for all commands; standardised exit codes
v0.8.0 Schema hardening schema_version enforcement, validate --strict, migration scaffold
v0.9.0 Diagnostics doctor command with categorised findings (error/warning/info)
v1.0.0 Stable Production-ready doctor, docs freeze, no breaking changes without migration path
v1.1.0 Post-1.0 Env-var interpolation (${VAR:-default}), init command

Made with ❤️ for the Flutter community

1
likes
0
points
744
downloads

Publisher

unverified uploader

Weekly Downloads

A build-time orchestrator for managing Flutter flavors, native configurations, and provisioning files across Android and iOS platforms.

Repository (GitHub)
View/report issues

Topics

#flutter #flavor #environment #android #ios

Funding

Consider supporting this project:

ko-fi.com

License

unknown (license)

Dependencies

args, path, xml, yaml

More

Packages that depend on flutter_flavor_orchestrator