Commande release
La commande tk-ota-push release compile l'application Flutter en mode --release avec la toolchain Shorebird, extrait de manière déterministe le binaire Dart de référence (binaire d'application sur Android, diff_base sur iOS), calcule les empreintes d'intégrité (pubspec_lock_hash, assets_manifest_hash, native_code_hash) et verrouille la Release sur le serveur OTA (POST /api/admin/v1/releases).
Syntaxe générale
tk-ota-push release [version] [options] [-- <arguments-flutter>]
- Si
[version]est omis, la version complète (x.y.z+build) est lue danspubspec.yaml. - Si
[version]est fourni (ex:1.0.0+3) et diffère depubspec.yaml, la CLI met automatiquement à jourpubspec.yamluniquement après avoir vérifié que le serveur OTA est joignable (prepare(version, sync: true)).
Flux d'exécution complet (Publisher.prepare & releaseAndroid / releaseIos)
- Configuration des clés : Synchronisation de la clé publique dans
shorebird.yaml. - Compilation de l'application : Exécution de
flutter buildpour générer le binaire complet. - Enregistrement sur le serveur : Téléversement du binaire de référence sur TkushPatch.
- Soumission aux magasins : Publication du binaire (
.aabou.ipa) sur Google Play ou l'App Store.
1. Garde-fou pré-compilation contre le Release Overwrite
Avant même de lancer flutter build, la méthode guardNoOverwrite interroge GET /api/admin/v1/releases/lookup pour chaque plateforme et architecture ciblée. Si la Release est déjà enregistrée sur le serveur, la CLI interrompt immédiatement l'opération avec le message suivant :
HTTP 409 CONFLICT - PROTECTION CONTRE LE 'RELEASE OVERWRITE'
La Release '1.0.0+1' (android/aarch64) est DÉJÀ verrouillée.
SHA-256 de référence : <baseSha256Hash>
Recompiler sous le même numéro changerait les adresses mémoire et ferait
crasher (Segfault) les téléphones qui exécutent déjà cette Release.
- Publier un patch : tk-ota-push patch 1.0.0+1 --platform android
- Nouvelle Release : tk-ota-push release <version avec build incrémenté>
2. Spécificités Android (apk vs aab et multi-ABI)
Choix du format d'artefact (--artifact)
--artifact apk(défaut) : nettoiebuild/app/outputs/apkpuis exécuteflutter build apk --release.--artifact aab: nettoiebuild/app/outputs/bundlepuis exécuteflutter build appbundle --release(recommandé pour Google Play Store).
Architecture cible (--arch / -a)
--arch all(défaut) : verrouille successivement les deux ABI Android :aarch64(correspondant àlib/arm64-v8a/binaire d'applicationoubase/lib/arm64-v8a/binaire d'application)arm(correspondant àlib/armeabi-v7a/binaire d'applicationoubase/lib/armeabi-v7a/binaire d'application)
--arch aarch64: verrouille uniquement le binaire 64 bits.--arch arm: verrouille uniquement le binaire 32 bits.
Règle d'or OTA : extraction directe depuis l'archive finale
Pour éviter toute erreur Update rejected: hash mismatch entre les dossiers intermédiaires de Gradle et le téléphone physique :
- La CLI localise l'archive finale signée/alignée dans
build/app/outputs/(_findBuiltPackage). - Elle décompresse en mémoire l'APK ou l'AAB via
ZipDecoder(_extractLibAppFromPackage) et extraitlib/<abi>/binaire d'application(oubase/lib/<abi>/binaire d'application) dansbuild/ota_extracted_libs/<version>/<arch>/binaire d'application. - En cas de repli uniquement, elle recherche dans
build/en donnant priorité absolue aux dossiersstripped_native_libs.
3. Spécificités iOS (ios vs ipa et cache local de référence)
Choix du format d'artefact (--artifact)
--artifact ios(ou défaut horsipa) : nettoiebuild/ios/iphoneoset exécuteflutter build ios --release.--artifact ipa: nettoiebuild/ios/archiveetbuild/ios/ipa, puis exécuteflutter build ipa --releaseen relayant--export-method=<methode>(ad-hoc,app-store,enterprise,development) et--export-options-plist=<chemin>.
Résolution du bundle .app et création du cache .ota_ios_release_cache
- En mode
ipa, la CLI cherche en priorité le bundle.appcontenantFrameworks/App.framework/Appdansbuild/ios/archive/(archive.xcarchive), puis dansbuild/ios/iphoneos/. - Elle crée le répertoire local
.ota_ios_release_cache/<version>/à la racine du projet Flutter et y sauvegarde :Runner.app(copie intégrale signée)App(binaire Mach-OFrameworks/App.framework/App)release_version.txtsupplement/(fichiersApp.*.link,App.*_table.json,App.dd_resolution.tsv)
- Elle extrait le snapshot de base via
aot-tools.dill dump_blobs:<dart> <aot-tools.dill> dump_blobs \
--analyze-snapshot=<analyze_snapshot_arm64> \
--snapshot=.ota_ios_release_cache/<version>/App \
--output=.ota_ios_release_cache/<version>/diff_base - Le fichier
diff_baseest envoyé au serveur OTA avecplatform=iosetarch=aarch64.
.ota_ios_release_cache/<version>Sur iOS, l'assemblage d'un patch (aot_tools link) nécessite le binaire App et le fichier diff_base générés lors de la Release. Conservez ou mettez en cache .ota_ios_release_cache/<version> dans votre pipeline CI/CD pour pouvoir publier des patchs iOS ultérieurement.
4. Scellement des 3 empreintes d'intégrité
Lors de l'appel multipart POST /api/admin/v1/releases, la CLI transmet trois condensats SHA-256 :
pubspec_lock_hash: SHA-256 depubspec.lock.assets_manifest_hash: SHA-256 canonique de la déclarationflutter: assets:et du contenu de chaque fichier d'asset (computeAssetsManifestHash()).native_code_hash: SHA-256 calculé parNativeIntegrityScannersurclasses*.dex,AndroidManifest.xmletlib/<arch>/*.so(horsbinaire d'application) sur Android, ouInfo.plist, exécutable principal etFrameworks/(horsApp.framework) sur iOS.
Exemples de commandes release
# Release Zero-Config (Android + iOS, version lue dans pubspec.yaml, obfuscation active)
tk-ota-push release
# Release Android AppBundle (.aab) pour Google Play avec Flavor prod
tk-ota-push release 2.1.0+105 -p android \
--flavor prod \
-t lib/main_prod.dart \
--dart-define-from-file=env/prod.json \
--artifact aab
# Release iOS (.ipa) pour App Store / TestFlight avec Flavor prod
tk-ota-push release 2.1.0+105 -p ios \
--flavor prod \
-t lib/main_prod.dart \
--dart-define-from-file=env/prod.json \
--artifact ipa \
--export-method app-store
Exemple de reçu de verrouillage Release
┌──────────────────────────────────────────────────────────────────────────
│ 📦 REÇU DE VERROUILLAGE RELEASE (COFFRE-FORT OTA)
├──────────────────────────────────────────────────────────────────────────
│ ID Release (UUID) : a42e271a-31ab-4476-ae69-24e5d2b8448f
│ Application / Tenant: sara-money-demo (sara-money)
│ Version & Cible : v1.0.0+3 • android (aarch64)
│ Statut : LIVE_ON_STORE
│ Binaire Référence : binaire d'application (Scellé)
│ SHA-256 Binaire : 6b6929c8ff345cf008496328d7bff081a8ccfb89498bf9916ed668be3c3dedcf
│ Garde-Fou Natif : 42d889f8f4b6bf9d3abb767d... (pubspec.lock)
│ Garde-Fou Assets : 99e887f4f4b6bf9d3abb767d... (AssetManifest)
│ Symboles (.symbols) : Archivés (app.android-arm64.symbols • SHA-256 : abcdef123456...)
│ Horodatage (UTC) : 2026-11-03T11:05:55.847643091Z
└──────────────────────────────────────────────────────────────────────────