This guide explains how to set up and use the reusable Flutter release workflow for your projects.
This workflow automates the build and release process for Flutter applications:
- ✅ Builds Android APK and AAB (App Bundle)
- ✅ Builds Windows executable
- ✅ Uploads to Google Play Store (production track)
- ✅ Creates GitHub Release with all artifacts
- ✅ Handles debug symbols and ProGuard mapping files
Before setting up the workflow, you need:
-
Flutter project with the following structure:
your-repo/ ├── .github/ │ └── workflows/ │ └── release.yml ├── your-app-name/ # Flutter app directory │ ├── .fvmrc # Flutter version config │ ├── pubspec.yaml │ └── android/ ├── distribution/ │ └── whatsnew/ # Google Play release notes └── CHANGELOG.md -
Android keystore for signing releases
-
Google Play Service Account JSON for automated uploads
-
GitHub repository secrets (see setup below)
You need to add the following secrets to your GitHub repository:
Create a secret with all your Android signing properties:
keyAlias=your_key_alias
keyPassword=your_key_password
storePassword=your_store_passwordHow to get these values:
- These come from your Android keystore file
- If you don't have one, generate it using Android Studio or
keytool
Your Android keystore file encoded in Base64:
# On Linux/Mac:
base64 -i your-keystore.jks | tr -d '\n'
# On Windows (PowerShell):
[Convert]::ToBase64String([IO.File]::ReadAllBytes("your-keystore.jks"))Copy the entire output and paste it as the secret value.
Google Play Service Account JSON (for automated Play Store uploads):
- Go to Google Play Console
- Navigate to:
Setup→API access - Create or use existing service account
- Download the JSON key file
- Copy the entire contents of the JSON file and paste as the secret value
In your Flutter app directory, create .fvmrc:
{
"flutter": "3.24.0"
}Replace 3.24.0 with your desired Flutter version.
Create the directory structure for Google Play release notes:
distribution/
└── whatsnew/
├── whatsnew-ar-EG # Arabic release notes
├── whatsnew-en-US # English release notes
└── whatsnew-xx-XX # Other languages
Each file should contain the release notes for that language (max 500 characters).
In your project repository, create .github/workflows/release.yml:
name: Build and Release [Your App Name]
on:
push:
tags:
- 'v*.*.*'
jobs:
release:
uses: muslimpack/.github/workflows/flutter_release.yaml@main
with:
app_directory: your-app-name
package_name: com.yourcompany.yourapp
java_version: '18'
secrets:
KEY_PROPERTIES: ${{ secrets.KEY_PROPERTIES }}
KEYSTORE_BASE64: ${{ secrets.KEYSTORE_BASE64 }}
SERVICE_ACCOUNT_JSON: ${{ secrets.SERVICE_ACCOUNT_JSON }}Update these values:
app_directory: Name of your Flutter app directory (e.g.,hisnelmoslem,alazkar,qadaa)package_name: Your Android package name (e.g.,com.hassaneltantawy.hisnelmoslem)java_version: Java version to use (default:'18')
Your android/app/build.gradle should have a prod flavor:
android {
flavorDimensions "default"
productFlavors {
prod {
dimension "default"
applicationId "com.yourcompany.yourapp"
}
}
}Update your app version in pubspec.yaml:
version: 3.0.0+30 # version_name+version_codeAdd release notes to your CHANGELOG.md:
## [3.0.0] - 2024-01-15
### Added
- New feature X
- New feature Y
### Fixed
- Bug fix A
- Bug fix B# Create a git tag
git tag v3.0.0
# Push the tag to GitHub
git push origin v3.0.0- Go to your repository on GitHub
- Click on
Actionstab - Watch the workflow run
- The workflow will:
- Build Android APK and AAB
- Build Windows executable
- Upload to Google Play Store
- Create GitHub Release with all artifacts
After the workflow completes:
- GitHub Release: Check
Releasestab for the new release - Google Play: Check Google Play Console → Your App → Production track
The workflow produces the following artifacts:
yourapp_3.0.0_android.apk- Direct download APKyourapp_3.0.0_android.aab- App Bundleyourapp_3.0.0_windows.zip- Windows executable
- App Bundle uploaded to Production track
- ProGuard mapping files for crash reports
- Debug symbols for native code
Problem: Workflow can't find uploaded artifacts.
Solution: Ensure artifact names match between upload and download steps.
Problem: Trying to upload the same version twice.
Solution:
- Increment version code in
pubspec.yaml - Create a new tag (e.g.,
v3.0.1) - Or delete the existing tag and fix issues before re-releasing
Problem: Secret not properly configured.
Solution:
- Go to repository Settings → Secrets
- Verify
KEY_PROPERTIESexists and has correct format - Ensure no extra spaces or newlines
Problem: Workflow uses wrong Flutter version.
Solution:
- Check
.fvmrcfile in your app directory - Ensure it has valid JSON format
- Verify Flutter version exists
Problem: Service account doesn't have permissions.
Solution:
- Go to Google Play Console → Setup → API access
- Ensure service account has "Release to production" permission
- Verify JSON key is not expired
If you want to skip Google Play upload (for testing):
Comment out the Google Play upload step in the reusable workflow, or create a custom workflow without that step.
To release to a different track (internal/alpha/beta):
In the reusable workflow, change:
track: productionto:
track: internal # or alpha, betaTo add iOS or other platforms, extend the reusable workflow with additional jobs.
- HisnElmoslem: muslimpack/HisnElmoslem_App
- Alazkar: Similar setup with
app_directory: alazkar - Qadaa: Similar setup with
app_directory: qadaa
If you encounter issues:
- Check the Actions log for detailed error messages
- Verify all secrets are properly configured
- Ensure your project structure matches the expected format
- Review this guide for missed steps
- Initial release with Android and Windows support
- Google Play integration
- GitHub Release creation
- Debug symbols handling