flutter_release 0.3.7
flutter_release: ^0.3.7 copied to clipboard
A tool for building and publishing Flutter apps, e.g. on GitHub, the Google Play Store and Apple's App Store.
flutter_release #
A tool for building and publishing Flutter apps, e.g. on GitHub, the Google Play Store and Apple's App Store. See also the according GitHub action.
Example #
Build:
flutter_release build apk \
--app-name example \ # Using name in pubspec by default
--app-version v0.0.1-alpha.1 \ # Using version in pubspec by default
--build-arg=--dart-define=API_URL=https://example.com \
--build-arg=--dart-define=API_KEY=12345678
Publish:
flutter_release publish android-google-play \
--dry-run \
--stage internal \
--app-name example \
--app-version v0.0.1-alpha.1 \
--build-arg=--dart-define=API_URL=https://example.com \
--build-arg=--dart-define=API_KEY=12345678 \
--fastlane-secrets-json-base64=$(base64 --wrap=0 android/fastlane-secrets.json) \
--keystore-file-base64=$(base64 --wrap=0 android/keystore.jks) \
--keystore-password=<mykeystorepassword> \
--key-alias=<mykeyalias> \
--key-password=<mykeypassword>
If the command is not found (in the PATH), try: dart pub global run flutter_release ....
Note that you have to pass the base64 arguments without any newline characters:
MY_BASE_64=$(base64 --wrap=0 /myfile)
Or remove them afterward:
MY_BASE_64="${MY_BASE_64//$'\n'/}"
Options & Flags #
Options:
app-name: The name of the app executableapp-version: Semantic version of the release (likev1.2.3), see https://semver.org/build-metadata: Specify the build number (also used as version code for Android, but is handled automatically)build-type: Release one of the following options:apk,web,ipk,macos,windows,msix,debianbuild-arg: Add options such as--dart-defineto the flutter build command
Flags:
verbose: Enable verbose logging
Supported Features #
| Platform | Android | iOS | web | Windows | macOS | Linux | |||
|---|---|---|---|---|---|---|---|---|---|
| Build | apk ✓ | aab ✓ | ipa ❌ | web ✓ | windows ✓ | msix ✓ | macos ✓ | linux ✓ | debian ✓ |
| Publish | Google Play ✓ | iOS App Store ✓ | Web Server ✓ | Microsoft Store ✓ | Mac App Store ❌ | Snap ❌ | Ubuntu ❌ |
Support for other app distributors is planned.
Setup #
Android - Google Play Store (via Debian only) #
- Create an App in your Google Play Console.
- Make sure you have these files ignored in your
./android/.gitignore:key.properties **/*.keystore **/*.jks # Google Play Store credentials fastlane-*.json play-store-credentials.json - Configure signing in gradle.
This is needed to be able to execute the build via Flutter and not via Gradle.
Convert the keystore to a base64 string e.g.
base64 --wrap=0 android/keystore.jks - Follow the guide of fastlane for setting up supply. No need to add the path to the Fastlane AppFile (as it should not exist at this point).
- Convert the Google Play Store credentials json (downloaded from cloud.google.com) to base64 e.g.
base64 --wrap=0 android/fastlane-secrets.json - Manually build a signed app bundle and publish it on the Google Play Store at least once to be able to automate the
process, e.g.:
flutter build appbundle \ --release - Run flutter_release
For flavor support, add:flutter_release publish android-google-play \ --dry-run \ --stage internal \ --fastlane-secrets-json-base64=$(base64 --wrap=0 android/fastlane-secrets.json) \ --keystore-file-base64=$(base64 --wrap=0 android/keystore.jks) \ --keystore-password=<mykeystorepassword> \ --key-alias=<mykeyalias> \ --key-password=<mykeypassword>
To set the release status (default--flavor=prod \ --main-path lib/main_prod.dart # Using "lib/main.dart" by defaultdraft), add:
You need to have released an alpha version for--release-status=completedcompletedstatus to work: https://github.com/fastlane/fastlane/discussions/18293
iOS - App Store #
- Make sure you have these files ignored in your
./ios/.gitignore:*.cer *.certSigningRequest *.mobileprovision *.p12 *.p8 - Create an App Store connect API Team key with
App Managerpermissions. Copy the key into youriosfolder. Also copy theKey IDand theIssuer IDfor later. - Execute
flutter_release prepare ios. Follow the steps. To delete existing certificates, visit: https://developer.apple.com/account/resources/certificates/list - Make sure the certificate is selected in the App Store provisioning profile
- Extract the information from the
ios/fastlane/Appfilefile. - Run flutter_release
Optionally add theflutter_release publish ios-app-store \ --dry-run \ --apple-username=<apple_id> \ --api-key-id=<api-key-id> \ --api-issuer-id=<api-issuer-id> \ --api-private-key-base64=<api-private-key> \ --content-provider-id=<itc_team_id> \ --team-id=<team_id> \ --distribution-private-key-base64=<distribution-private-key> \ --distribution-cert-base64=<distribution-cert>--team-enterpriseflag, if your team is in the Apple Developer Enterprise Program. For flavor support add:--flavor=prod \ --main-path lib/main_prod.dart \ # Using "lib/main.dart" by default --xcode-scheme prod # Optional, uses flavor if set, or "Runner" by default
To force renew the certificates run:
flutter_release prepare ios cert
To create additional provisioning profiles, run in the ios directory:
fastlane sigh -a com.example.ios.to.be.added --api_key_path ApiAuth.json
Windows - MSIX installer #
The MSIX installer is created via the msix package.
Configure it in the msix_config section of your pubspec.yaml, e.g.:
msix_config:
display_name: Example
logo_path: assets/images/logo.png
The version is derived from the app version (a.b.c.0), the architecture from the build machine.
To sign the installer, pass your certificate:
flutter_release build msix `
--certificate-file-base64=$([Convert]::ToBase64String([IO.File]::ReadAllBytes((Resolve-Path certificate.pfx)))) `
--certificate-password=<mycertificatepassword>
Otherwise, the installer is signed with the test certificate of the msix package, which users have to trust manually.
For the Microsoft Store, build an unsigned installer with the --store flag, as the store signs it on submission.
Take the identity name, the publisher and the publisher display name from the
Partner Center (Product identity) of your app:
flutter_release build msix --store `
--identity-name=Example.ExampleApp `
--publisher="CN=00000000-0000-0000-0000-000000000000" `
--publisher-display-name="Example Publisher"
Alternatively, set them via identity_name, publisher and publisher_display_name in the msix_config.
Windows - Microsoft Store (via Windows only) #
- Reserve the app name in the Partner Center and submit the app manually at least once,
e.g. with an installer built via
flutter_release build msix --store(see above). - In Account settings > Organization profile > Tenants, associate a Microsoft Entra tenant with your account. If you don't have one, create a new tenant there at no charge.
- In Account settings > User management > Microsoft Entra applications, create a new Microsoft Entra application
(see Microsoft Store submission API):
- Name: e.g.
flutter_release - Reply URL: e.g.
http://localhost(not used, but required) - Role:
Developer
- Name: e.g.
- Select the created application and copy the
Tenant IDand theClient ID. Then select Add new key and copy theKey(as client secret), as it is only shown once. Keys expire, so renew them there in time. - Copy the
Seller IDfrom Account settings > Organization profile > Legal info > Developer. - Copy the
Store ID(as product id) from Product management > Product identity of your app. - Install the Microsoft Store Developer CLI (
msstore). - Build the installers via
flutter_release build msix --store(see above), e.g. one per architecture on the respective machine. The publish command does not build the app. - Run flutter_release
By default, the packages of the app version (flutter_release publish windows-ms-store ` --dry-run ` --tenant-id=<tenant-id> ` --client-id=<client-id> ` --client-secret=<key> ` --seller-id=<seller-id> ` --product-id=<store-id>--app-versionor from thepubspec.yaml) are taken frombuild/releases. Alternatively, pass them via--package=<path>(repeatable). Multiple packages are published at once as.msixbundle, using the app version as bundle version. To publish to a package flight, add--flight-id=<flight-id>. The submission is kept as draft by default (--release-status=draft). To submit it for certification, add--release-status=completed. For a gradual rollout, add--rollout-percentage=<0-100>.
Web - Server (via Debian only) #
- Generate a key pair on your client
ssh-keygen -t ed25519 -f $HOME/.ssh/id_ed25519_flutter_release -C flutter_releasewithout a passphrase - Add the output of
cat $HOME/.ssh/id_ed25519_flutter_release.pubto your servers$HOME/.ssh/authorized_keys - Convert the private key to a base64 string e.g.
base64 --wrap=0 $HOME/.ssh/id_ed25519_flutter_release - Run flutter_release
flutter_release publish web-server \ --dry-run \ --host=host.example.com \ --path=/var/www/html \ --ssh-port=22 \ --ssh-user=<user> \ --ssh-private-key-base64=<private-key>