pipo_firebase_app_distribution 0.0.3
pipo_firebase_app_distribution: ^0.0.3 copied to clipboard
A Dart CLI tool to automatically upload APK/IPA to Firebase App Distribution with auto-detection of Firebase configuration from google-services.json and GoogleService-Info.plist
Pipo Firebase App Distribution 🚀 #
A powerful Dart CLI tool that automatically generates build configuration from your Firebase setup and simplifies building and uploading APK/IPA files to Firebase App Distribution.
✨ Features #
-
🔍 Auto-Detection: Automatically scans and extracts Firebase configuration from:
android/app/google-services.json(Android)android/app/src/{flavor}/google-services.json(Flavor-specific)ios/Runner/GoogleService-Info.plist(iOS)ios/Runner/Firebase/{flavor}/GoogleService-Info.plist(Flavor-specific)
-
📝 Smart Template Generation: Generates a complete
build.yamlconfiguration file with:- Project information from
pubspec.yaml - All detected Firebase App IDs (Android & iOS)
- Environment-specific settings (dev, staging, production)
- Build presets for common workflows
- Platform-specific configurations
- Project information from
-
🚀 Automated Build & Deploy: Single command to build and upload to Firebase:
- Build APK/IPA for specific environments
- Auto-increment version numbers
- Generate release notes from git commits
- Upload to Firebase App Distribution
- Create git tags automatically
-
🔐 Service Account Authentication: Secure, CLI-free authentication:
- Google Cloud service account JSON key file
- No Firebase CLI installation required
- Supports
GOOGLE_APPLICATION_CREDENTIALSenvironment variable - CI/CD ready (Jenkins, GitHub Actions, etc.)
-
📊 Error Logging: Comprehensive error logging:
- Build errors saved to
.pipo_logs/ - Upload errors with API response details
- Auto-gitignore for sensitive files
- Build errors saved to
-
🎯 Zero Configuration: Just run
pipo_firebase initand you're ready to go! -
🔄 Multi-Environment Support: Automatically detects environments from:
- File paths (e.g.,
src/dev/,Firebase/staging/) - Bundle IDs (e.g.,
com.example.app.dev) - Product flavors in
build.gradle
- File paths (e.g.,
📦 Installation #
Global Installation (Recommended) #
dart pub global activate pipo_firebase_app_distribution
After installation, you can use the command:
pipo_firebase init
pipo_firebase deploy dev
Local Installation #
Add to your pubspec.yaml:
dev_dependencies:
pipo_firebase_app_distribution: ^0.0.1
Then run:
dart pub get
Use with:
dart run pipo_firebase init
dart run pipo_firebase deploy dev
🚀 Quick Start #
1. Prerequisites #
- Flutter SDK installed and configured
- Firebase project created with App Distribution enabled
- Firebase configuration files in your project:
google-services.jsonfor AndroidGoogleService-Info.plistfor iOS
- Google Cloud service account JSON key file (for upload)
- Go to Google Cloud Console → IAM & Admin → Service Accounts
- Create a service account with Firebase App Distribution Admin role
- Download the JSON key file
- Place it as
.firebase-credentials.jsonin your project root (auto-gitignored)
2. Initialize Configuration #
Navigate to your Flutter project root and run:
pipo_firebase init
This command will:
- Scan for Firebase configuration files
- Extract product flavors from
build.gradle - Match flavors with Firebase clients
- Extract all Firebase App IDs and project settings
- Generate a
build.yamlfile with complete configuration
Example Output:
🔍 Initializing Firebase App Distribution configuration...
📱 Scanning for Firebase configurations
✅ Firebase configurations scanned
📋 Found Firebase configurations:
🤖 ANDROID (dev)
App ID: 1:123:android:abc123
Bundle ID: com.example.app.dev
Project: my-project-123
🤖 ANDROID (staging)
App ID: 1:123:android:def456
Bundle ID: com.example.app.staging
Project: my-project-123
🤖 ANDROID (production)
App ID: 1:123:android:ghi789
Bundle ID: com.example.app
Project: my-project-123
🍎 IOS (dev)
App ID: 1:123:ios:jkl012
Bundle ID: com.example.app.dev
Project: my-project-123
⚙️ Generating build.yaml
✅ build.yaml generated successfully
🎉 Firebase App Distribution initialized successfully!
📄 Generated file: build.yaml
Next steps:
1. Review and customize build.yaml
2. Run build command to test the configuration
3. Upload to Firebase App Distribution
📚 Documentation: https://pub.dev/packages/pipo_firebase_app_distribution
3. Review Generated Configuration #
The generated build.yaml will look like this:
# Firebase App Distribution Build Configuration
# Auto-generated by pipo_firebase
project:
name: "my_app"
version: "1.0.0+1"
firebase:
project_id: "my-project-123"
project_number: "123456789"
timeout: 600
credentials_file: ".firebase-credentials.json" # Path to service account JSON key
# Environment configurations
environments:
dev:
android_app_id: "1:123:android:abc123"
android_bundle_id: "com.example.app.dev"
ios_app_id: "1:123:ios:jkl012"
ios_bundle_id: "com.example.app.dev"
group: "internal-testers"
setup:
build_mode: release
upload: true
obfuscate: false
auto_increment: true
clean: true
staging:
android_app_id: "1:123:android:def456"
android_bundle_id: "com.example.app.staging"
ios_app_id: "1:123:ios:mno345"
ios_bundle_id: "com.example.app.staging"
group: "qa-team"
setup:
build_mode: release
upload: true
obfuscate: true
auto_increment: true
clean: true
production:
android_app_id: "1:123:android:ghi789"
android_bundle_id: "com.example.app"
ios_app_id: "1:123:ios:pqr678"
ios_bundle_id: "com.example.app"
group: "release-team"
setup:
build_mode: release
upload: true
obfuscate: true
auto_increment: true
clean: true
# Build presets
presets:
quick-dev:
environment: dev
build_mode: debug
upload: false
clean: false
test-build:
environment: staging
build_mode: release
upload: false
clean: true
production-release:
environment: production
build_mode: release
upload: true
clean: true
increment: true
# Default settings
defaults:
build_mode: release
upload: true
clean: true
auto_increment: true
obfuscate: false
# Platform-specific settings
platforms:
android:
build_format: apk # or aab for Play Store
flavor_dimension: environment
ios:
export_method: development # or app-store, ad-hoc, enterprise
team_id: "" # Add your Apple Team ID here
4. Customize Configuration #
Edit build.yaml to match your project needs:
- Update distribution groups
- Adjust build settings per environment
- Configure platform-specific options
5. Deploy to Firebase #
Deploy your app to Firebase App Distribution:
# Deploy dev environment (both Android and iOS)
pipo_firebase deploy dev
# Deploy only Android
pipo_firebase deploy dev --platform android
# Deploy only iOS
pipo_firebase deploy staging --platform ios
# Build without uploading
pipo_firebase deploy dev --skip-upload
# Upload existing build without rebuilding
pipo_firebase deploy production --skip-build
📖 Usage #
Available Commands #
# Initialize Firebase App Distribution configuration
pipo_firebase init
# Deploy app to Firebase App Distribution
pipo_firebase deploy <environment> [options]
# Show help
pipo_firebase --help
# Show version
pipo_firebase --version
# Show deploy command help
pipo_firebase deploy --help
Command Details #
init Command
Scans your project for Firebase configuration files and generates a complete build.yaml template.
What it does:
-
Scans Product Flavors (Android):
- Reads
android/app/build.gradle - Extracts
productFlavorsconfiguration - Gets
applicationIdfor each flavor
- Reads
-
Searches for Firebase Config Files:
-
Android:
google-services.jsonin:android/app/google-services.jsonandroid/app/src/{flavor}/google-services.json
-
iOS:
GoogleService-Info.plistin:ios/Runner/GoogleService-Info.plistios/Runner/Firebase/{flavor}/GoogleService-Info.plist
-
-
Extracts Configuration:
- Firebase Project ID and Project Number
- Firebase App ID (for App Distribution)
- Bundle ID / Package Name
- Environment (automatically detected)
-
Matches Flavors with Firebase Clients:
- Only includes flavors defined in
build.gradle - Matches by
applicationIdfrom flavor config - Falls back to environment name matching
- Only includes flavors defined in
-
Reads Project Info:
- Project name from
pubspec.yaml - Current version from
pubspec.yaml
- Project name from
-
Generates
build.yaml:- All detected configurations
- Recommended settings per environment
- Build presets
- Platform-specific options
Usage:
pipo_firebase init
deploy Command
Builds and deploys your app to Firebase App Distribution.
Syntax:
pipo_firebase deploy <environment> [options]
Arguments:
<environment>: Environment to deploy (must match one defined inbuild.yaml)- Examples:
dev,staging,production
- Examples:
Options:
-
--platform, -p: Platform to build (android,ios, orboth)- Default:
both - Example:
--platform android
- Default:
-
--skip-build: Skip building the app- Use when you want to upload an existing build
- Example:
--skip-build
-
--skip-upload: Skip uploading to Firebase- Use when you only want to build without uploading
- Example:
--skip-upload
-
--skip-version-increment: Skip incrementing version number- Default: auto-increments based on
build.yamlconfig - Example:
--skip-version-increment
- Default: auto-increments based on
-
--skip-git-tag: Skip creating git tags- Example:
--skip-git-tag
- Example:
-
--help, -h: Show help for deploy command
What it does:
- ✅ Reads build configuration from
build.yaml - 📊 Auto-increments version number (if configured)
- 🔨 Builds APK/IPA for specified platform(s)
- 📝 Generates release notes from git commits
- ☁️ Uploads to Firebase App Distribution
- 🏷️ Creates git tags and commits changes
Examples:
# Deploy dev environment (both platforms)
pipo_firebase deploy dev
# Deploy staging for Android only
pipo_firebase deploy staging --platform android
# Deploy production for iOS only
pipo_firebase deploy production --platform ios
# Build only, don't upload
pipo_firebase deploy dev --skip-upload
# Upload existing build without rebuilding
pipo_firebase deploy dev --skip-build
# Deploy without incrementing version
pipo_firebase deploy staging --skip-version-increment
# Deploy without git operations
pipo_firebase deploy production --skip-git-tag
Deployment Process:
When you run pipo_firebase deploy dev, the following happens:
╔══════════════════════════════════════════════════════════════╗
║ 🚀 Pipo Firebase App Distribution Deploy 🚀 ║
║ Build & Upload to Firebase App Distribution ║
╚══════════════════════════════════════════════════════════════╝
🚀 Starting deployment for dev environment
📋 Reading build configuration...
✅ Configuration loaded
🔄 Auto-incrementing version: 1.0.0+1 → 1.0.0+2
📱 Platforms: android, ios
═══════════════════════════════════════════════════════════════
BUILD PHASE
═══════════════════════════════════════════════════════════════
╭─────────────────────────────────────────────────────────────╮
│ 🔨 Building ANDROID │
╰─────────────────────────────────────────────────────────────╯
⏳ Building APK for dev (release)
✅ Build completed successfully
📱 Artifact: app-dev-release.apk
📁 Location: /path/to/build/app/outputs/flutter-apk/app-dev-release.apk
📏 Size: 42.5 MB
╭─────────────────────────────────────────────────────────────╮
│ 🔨 Building IOS │
╰─────────────────────────────────────────────────────────────╯
⏳ Building IPA for dev (release)
✅ Build completed successfully
📱 Artifact: my_app.ipa
📁 Location: /path/to/build/ios/ipa/my_app.ipa
📏 Size: 38.2 MB
✅ All builds completed successfully!
📝 Generating release notes...
✅ Release notes generated
═══════════════════════════════════════════════════════════════
UPLOAD PHASE
═══════════════════════════════════════════════════════════════
╭─────────────────────────────────────────────────────────────╮
│ ☁️ Uploading ANDROID to Firebase │
╰─────────────────────────────────────────────────────────────╯
📤 Starting upload to Firebase App Distribution...
App ID: 1:123:android:abc123
Groups: internal-testers
⏳ Uploading artifact
✅ Upload completed successfully
🎉 App successfully distributed to Firebase!
📱 App ID: 1:123:android:abc123
👥 Groups: internal-testers
🔗 Check Firebase Console for distribution link
╭─────────────────────────────────────────────────────────────╮
│ ☁️ Uploading IOS to Firebase │
╰─────────────────────────────────────────────────────────────╯
📤 Starting upload to Firebase App Distribution...
App ID: 1:123:ios:jkl012
Groups: internal-testers
⏳ Uploading artifact
✅ Upload completed successfully
🎉 App successfully distributed to Firebase!
✅ All uploads completed successfully!
🏷️ Creating git tags...
✅ Git tags created
╔══════════════════════════════════════════════════════════════╗
║ 🎉 DEPLOYMENT COMPLETE 🎉 ║
╚══════════════════════════════════════════════════════════════╝
📊 Deployment Summary:
Environment: dev
Version: 1.0.0+2
Platforms: android, ios
Uploaded: ✅ Yes
🔗 Next Steps:
• Check Firebase Console for distribution status
• Notify testers via Firebase App Distribution
• Monitor crash reports and feedback
🔐 Firebase Authentication #
The CLI uses Google Cloud service account credentials to authenticate with the Firebase App Distribution API directly — no Firebase CLI installation required.
Setting Up Credentials #
- Go to Google Cloud Console → IAM & Admin → Service Accounts
- Create a service account (or use an existing one)
- Grant the Firebase App Distribution Admin role
- Create a JSON key and download it
- Place it in your project
Credentials Resolution Order #
The tool looks for credentials in this order:
-
credentials_fileinbuild.yaml— explicit path under thefirebasesection:firebase: credentials_file: "path/to/service-account.json" -
GOOGLE_APPLICATION_CREDENTIALSenvironment variable — standard Google Cloud convention:export GOOGLE_APPLICATION_CREDENTIALS="/path/to/service-account.json" pipo_firebase deploy dev -
.firebase-credentials.jsonin project root — default convention (auto-gitignored)
CI/CD Integration (Jenkins) #
For Jenkins or other CI/CD systems, set the credentials as an environment variable or provide the file path:
// Jenkinsfile example
environment {
GOOGLE_APPLICATION_CREDENTIALS = credentials('firebase-service-account')
}
stages {
stage('Deploy') {
steps {
sh 'pipo_firebase deploy staging --platform android'
}
}
}
Security Notes #
- The
.firebase-credentials.jsonfile is automatically added to.gitignore - Never commit service account key files to version control
- For CI/CD, use secret management (Jenkins credentials, GitHub Secrets, etc.)
- Service account tokens are short-lived (1 hour) and auto-refreshed
🏗️ Project Structure #
Your Flutter project should have the following structure:
my_flutter_app/
├── android/
│ └── app/
│ ├── build.gradle # Product flavors defined here
│ ├── google-services.json # Main Android config (optional)
│ └── src/
│ ├── dev/
│ │ └── google-services.json # Dev flavor
│ ├── staging/
│ │ └── google-services.json # Staging flavor
│ └── production/
│ └── google-services.json # Production flavor
│
├── ios/
│ └── Runner/
│ ├── GoogleService-Info.plist # Main iOS config (optional)
│ └── Firebase/
│ ├── dev/
│ │ └── GoogleService-Info.plist # Dev flavor
│ ├── staging/
│ │ └── GoogleService-Info.plist # Staging flavor
│ └── production/
│ └── GoogleService-Info.plist # Production flavor
│
├── pubspec.yaml
├── build.yaml # Generated by pipo_firebase init
├── .firebase-credentials.json # Service account key (gitignored)
└── .pipo_logs/ # Error logs (gitignored)
🔧 Configuration #
Environment Detection #
The tool automatically detects environments by:
- Reading product flavors from
build.gradle:
android {
flavorDimensions "environment"
productFlavors {
dev {
dimension "environment"
applicationIdSuffix ".dev"
}
staging {
dimension "environment"
applicationIdSuffix ".staging"
}
production {
dimension "environment"
}
}
}
-
Matching with Firebase clients:
- First tries to match by
applicationIdfrom flavor config - Falls back to matching by environment name from file path or bundle ID
- First tries to match by
-
Only includes configured flavors:
- Ignores extra clients in
google-services.json - Only generates config for flavors defined in
build.gradle
- Ignores extra clients in
Build Configuration Options #
Environment Setup
environments:
dev:
setup:
build_mode: release # debug or release
upload: true # Upload to Firebase after build
obfuscate: false # Enable code obfuscation
auto_increment: true # Auto-increment build number
clean: true # Clean before build
Platform Settings
platforms:
android:
build_format: apk # apk or aab
flavor_dimension: environment
ios:
export_method: development # development, app-store, ad-hoc, enterprise
team_id: "ABCDEF1234" # Your Apple Team ID
Distribution Groups #
Default groups assigned per environment:
- dev:
internal-testers - staging:
qa-team - production:
release-team
You can customize these in build.yaml:
environments:
dev:
group: "my-custom-group"
📱 Platform Support #
Android #
Extracts from google-services.json:
{
"project_info": {
"project_id": "my-project-123",
"project_number": "123456789"
},
"client": [{
"client_info": {
"mobilesdk_app_id": "1:123:android:abc123",
"android_client_info": {
"package_name": "com.example.app.dev"
}
}
}]
}
iOS #
Extracts from GoogleService-Info.plist:
<key>PROJECT_ID</key>
<string>my-project-123</string>
<key>GCM_SENDER_ID</key>
<string>123456789</string>
<key>GOOGLE_APP_ID</key>
<string>1:123:ios:jkl012</string>
<key>BUNDLE_ID</key>
<string>com.example.app.dev</string>
🐛 Troubleshooting #
Common Issues #
1. No Firebase configuration found
Error:
❌ No Firebase configuration files found!
Expected files:
Android: android/app/google-services.json
iOS: ios/Runner/GoogleService-Info.plist
Solution:
- Download
google-services.jsonfrom Firebase Console (Android app settings) - Download
GoogleService-Info.plistfrom Firebase Console (iOS app settings) - Place files in the correct directories
- For multi-flavor setup, organize files by flavor
2. Build failed
Error:
❌ Build failed for android
📝 Error log saved to: .pipo_logs/build_android_dev_20240115_143022.log
Solution:
- Check the error log file in
.pipo_logs/ - Common issues:
- Flutter SDK not installed or not in PATH
- Flavor not configured in
build.gradle - Missing dependencies in
pubspec.yaml
- Run
flutter doctorto check Flutter installation - Try building manually:
flutter build apk --flavor dev
3. Upload failed
Error:
❌ Upload failed for android
📝 Error log saved to: .pipo_logs/upload_android_dev_20240115_143525.log
Solution:
- Check that your service account credentials file exists and is valid
- Verify the service account has the Firebase App Distribution Admin role
- Check App ID and project number in
build.yamlmatch Firebase Console - Verify network connection
4. Authentication failed
Error:
No service account credentials found.
Solution:
- Place
.firebase-credentials.jsonin project root, or - Set
credentials_fileinbuild.yamlunderfirebasesection, or - Set
GOOGLE_APPLICATION_CREDENTIALSenvironment variable - Ensure the JSON file is a valid Google Cloud service account key (type:
service_account)
5. Wrong number of flavors detected
Error:
Generated 4 configurations but only have 3 flavors
Solution:
- The CLI now reads flavors from
build.gradle - It only includes flavors defined in
productFlavors - Extra clients in
google-services.jsonare ignored - Re-run
pipo_firebase initto regenerate configuration
Error Logs #
All errors are automatically logged to .pipo_logs/:
- Build errors:
build_{platform}_{environment}_{timestamp}.log - Upload errors:
upload_{platform}_{environment}_{timestamp}.log - Deployment errors:
deployment_{environment}_{timestamp}.log
The .pipo_logs/ directory is automatically added to .gitignore.
🎨 Advanced Usage #
Custom Build Presets #
Define reusable build configurations in build.yaml:
presets:
quick-test:
environment: dev
platform: android
build_mode: debug
upload: false
clean: false
release-candidate:
environment: staging
build_mode: release
upload: true
clean: true
obfuscate: true
Version Management #
Auto-increment version numbers:
environments:
dev:
setup:
auto_increment: true # Increments build number (1.0.0+1 → 1.0.0+2)
Git Integration #
Automatic git operations:
environments:
production:
setup:
auto_increment: true # Increments version
# After build, automatically:
# 1. Commits version change to pubspec.yaml
# 2. Creates git tag (e.g., v1.0.0-production+2)
# 3. Commits build.yaml changes
Disable git operations:
pipo_firebase deploy production --skip-git-tag
Release Notes #
Automatically generated from git commits:
# Generated release notes include:
# - Commits since last tag
# - Environment (dev/staging/production)
# - Build mode (debug/release)
# - Version number
Format:
Environment: dev
Build Mode: release
Version: 1.0.0+2
Recent Changes:
- Add user authentication feature
- Fix image loading bug
- Update app icon
- Improve performance
🤝 Contributing #
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
📄 License #
This project is licensed under the MIT License - see the LICENSE file for details.
🙏 Acknowledgments #
- Inspired by the need to simplify Firebase App Distribution setup
- Built with mason_logger for beautiful CLI output
- Thanks to the Flutter and Firebase communities
📞 Support #
🗺️ Roadmap #
- ✅
Build command to execute builds from build.yaml - ✅
Upload command to distribute to Firebase - ✅
Auto-increment version numbers - ✅
Release notes generation from git commits - ✅
Git tagging support - ✅
Service account API authentication (no Firebase CLI required) - ✅
Error logging and troubleshooting - ✅
CI/CD ready (Jenkins, GitHub Actions) - ❌ Support for multiple Firebase projects
- ❌ GitHub Actions workflow templates
- ❌ Support for iOS schemes (similar to Android flavors)
- ❌ Release notes templates
- ❌ Slack/Discord notifications
Made with ❤️ by the Flutter community