Build & Release #

Proses kompilasi aplikasi untuk tahap produksi (rilis) memiliki perbedaan arsitektural yang sangat mendasar dibandingkan dengan proses kompilasi selama tahap pengembangan (development/debugging). Pada kompilasi rilis, Dart AOT (Ahead-of-Time) compiler akan menerjemahkan seluruh kode kita menjadi instruksi biner mesin native secara langsung demi performa eksekusi maksimal, melakukan penghapusan kode mati (tree shaking), serta mematikan seluruh port dan asersi debugging.

Agar sistem operasi seluler target bersedia memasang aplikasi produksi kita, file biner yang dihasilkan (APK/AAB pada Android dan IPA pada iOS) wajib ditandatangani secara kriptografis (cryptographically signed) menggunakan sertifikat digital sah milik pengembang. Artikel ini akan mengupas secara tuntas prosedur penandatanganan, pembuatan build rilis optimal, hingga manajemen peluncuran aplikasi ke Google Play Store dan Apple App Store.

Siklus Hidup Penomoran Versi (Semantic Versioning) #

Sebelum memulai kompilasi rilis, kita harus menetapkan versi rilis yang tepat di dalam file pubspec.yaml proyek kita. Flutter mengadopsi standar Semantic Versioning (SemVer) untuk mengelola siklus penomoran rilis ini.

Struktur penulisan versi di pubspec.yaml diatur pada baris parameter version:

version: 2.3.1+45
#        │   │ │ └── Build Number (versionCode di Android, CFBundleVersion di iOS)
#        │   │ └──── Patch Version (Perbaikan bug, backward-compatible)
#        │   └────── Minor Version (Fitur baru, backward-compatible)
#        └────────── Major Version (Perubahan besar yang tidak kompatibel dengan versi sebelumnya)

Aturan dasar pengelolaan versi rilis:

  • Major (2.x.x): Dinaikkan ketika terjadi perombakan besar arsitektur (breaking changes), perombakan ulang UI secara masif (redesign), atau perubahan struktur data yang membuat versi baru tidak dapat langsung memperbarui versi lama.
  • Minor (x.3.x): Dinaikkan ketika kita merilis fitur fungsional baru yang kompatibel dengan versi sebelumnya.
  • Patch (x.x.1): Dinaikkan ketika kita merilis perbaikan bug kecil (hotfix) yang tidak memperkenalkan fitur baru.
  • Build Number (+45): Angka integer tunggal yang mewakili iterasi kompilasi build kita. Build number harus selalu dinaikkan (increment) secara konsisten setiap kali kita mengunggah file biner baru ke toko aplikasi, meskipun nomor versinya tidak berubah. Toko aplikasi akan menolak biner baru yang memiliki build number sama dengan biner yang sudah ada di konsol mereka.

Android: Proses Penandatanganan (Signing) & Build #

Sistem operasi Android mewajibkan setiap berkas instalasi APK atau AAB ditandatangani menggunakan sertifikat digital rilis yang disimpan di dalam berkas aman bernama Keystore.

Langkah 1: Membuat Berkas Keystore Baru #

Buka konsol terminal dan gunakan utilitas keytool bawaan Java SDK untuk membuat kunci penandatanganan baru:

# Buat direktori aman di luar folder proyek git kita
mkdir ~/keystore

# Buat berkas keystore rilis
keytool -genkey -v \
  -keystore ~/keystore/toko-kita-release.jks \
  -storetype JKS \
  -keyalg RSA \
  -keysize 2048 \
  -validity 10000 \
  -alias upload

Pada proses ini, kita wajib memasukkan password keystore dan melengkapi data identitas pengembang. Simpan password ini di tempat yang aman (misalnya di password manager tim), karena jika berkas keystore atau password ini hilang, kita tidak akan pernah bisa memperbarui aplikasi kita lagi di Google Play Store selamanya.

Langkah 2: Membuat File key.properties secara Aman #

Buat file baru bernama key.properties di dalam direktori android/ proyek kita. Berkas ini digunakan untuk menyimpan detail lokasi keystore dan password secara lokal. Jangan pernah mengunggah berkas ini ke repositori Git.

# android/key.properties (PENTING: tambahkan file ini ke .gitignore)
storePassword=passwordKeystoreKita
keyPassword=passwordKunciKita
keyAlias=upload
storeFile=/Users/nama_user_kita/keystore/toko-kita-release.jks

Langkah 3: Menghubungkan Signing Config ke Gradle #

Ubah file konfigurasi android/app/build.gradle agar secara otomatis membaca berkas properti penandatanganan dan menerapkannya pada kompilasi rilis:

// android/app/build.gradle
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
if (keystorePropertiesFile.exists()) {
    keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}

android {
    ...
    signingConfigs {
        release {
            keyAlias keystoreProperties['keyAlias']
            keyPassword keystoreProperties['keyPassword']
            storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
            storePassword keystoreProperties['storePassword']
        }
    }

    buildTypes {
        release {
            // Terapkan konfigurasi penandatanganan digital rilis
            signingConfig signingConfigs.release
            
            // Konfigurasi minifikasi R8/Proguard
            minifyEnabled true
            shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

Langkah 4: Menjalankan Perintah Build Android #

  • Android App Bundle (AAB) - Rekomendasi Play Store: Format ini wajib digunakan jika kita meluncurkan aplikasi ke Google Play Store. Google Play akan memilah AAB menjadi APK-APK kecil yang disesuaikan dengan arsitektur CPU dan resolusi layar perangkat pengguna saat diunduh.
    flutter build appbundle --release --dart-define-from-file=.dart_define/production.json
    # Output: build/app/outputs/bundle/release/app-release.aab
    
  • Split APK - Untuk Distribusi Mandiri: Jika kita ingin mendistribusikan berkas APK secara langsung (misalnya melalui website internal perusahaan atau dikirim manual), jalankan perintah split per ABI untuk memperkecil ukuran APK per arsitektur CPU:
    flutter build apk --release --split-per-abi --dart-define-from-file=.dart_define/production.json
    # Output APK akan terbagi menjadi:
    # 1. build/app/outputs/flutter-apk/app-arm64-v8a-release.apk
    # 2. build/app/outputs/flutter-apk/app-armeabi-v7a-release.apk
    

iOS: Proses Penandatanganan (Signing) & Build #

Proses penandatanganan biner iOS menggunakan ekosistem Apple Developer Portal yang memerlukan akun Apple Developer berbayar ($99/tahun).

Prasyarat di Apple Developer Portal #

  1. Distribution Certificate: Sertifikat digital p12 terenkripsi yang membuktikan identitas kita sebagai developer resmi Apple.
  2. App ID & Bundle ID: Pengenal unik aplikasi kita yang terdaftar di portal Apple (misalnya com.unisbadri.tokokita).
  3. Provisioning Profile (App Store Distribution): Berkas otorisasi yang mengikat sertifikat digital kita dengan App ID aplikasi untuk diizinkan dipasang pada perangkat non-pengembang.

Mengonfigurasi Xcode Signing #

Buka folder ios menggunakan Xcode:

  1. Pilih target Runner di panel sebelah kiri.
  2. Masuk ke tab Signing & Capabilities.
  3. Pilih tim Apple Developer kita pada menu drop-down Team.
  4. Pada komputer lokal pengembang, kita dapat mencentang opsi Automatically manage signing untuk kemudahan pendaftaran profil pengujian otomatis. Namun, untuk otomatisasi build rilis atau server CI/CD, disarankan untuk mengonfigurasi profil secara manual (Manual Signing).

Melakukan Build iOS IPA #

Jalankan kompilasi awal untuk memproduksi berkas Xcode Archive (.xcarchive):

flutter build ios --release --dart-define-from-file=.dart_define/production.json

Setelah proses kompilasi Dart selesai, buka Xcode untuk mengekspor berkas archive menjadi biner IPA rilis, atau kita dapat menggunakan perintah CLI terpadu Flutter dengan menyertakan file opsi ekspor:

flutter build ipa --release \
  --dart-define-from-file=.dart_define/production.json \
  --export-options-plist=ios/ExportOptions.plist
# Output: build/ios/ipa/toko_kita.ipa

Berkas ExportOptions.plist adalah berkas XML konfigurasi ekspor iOS standar. Berikut contoh isi berkas tersebut:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>method</key>
  <string>app-store</string>
  <key>teamID</key>
  <string>AB12345XYZ</string> <!-- Tim ID Apple Developer kita -->
  <key>uploadBitcode</key>
  <false/>
  <key>uploadSymbols</key>
  <true/>
</dict>
</plist>

Alur Kerja Kompilasi dan Distribusi Rilis #

Secara keseluruhan, alur kerja dari penulisan versi hingga pengunggahan biner rilis ke konsol masing-masing toko aplikasi dapat digambarkan dalam bagan berikut:

flowchart TD
    Start(["Mulai Proses Rilis"]) --> VersionCheck["Update Versi & Build Number di pubspec.yaml"]
    VersionCheck --> SelectPlatform{"Pilih Platform Target"}

    SelectPlatform -- Android --> SignAndroid["Android Signing:<br/>1. Baca key.properties<br/>2. Load Keystore (.jks)"]
    SignAndroid --> BuildAAB["Kompilasi AAB:<br/>flutter build appbundle --release"]
    BuildAAB --> ValidateAAB["Validasi AAB via bundletool"]
    ValidateAAB --> UploadGoogle["Upload ke Google Play Console<br/>(Internal / Closed / Production)"]

    SelectPlatform -- iOS --> SigniOS["iOS Signing:<br/>1. Cocokkan Team & Bundle ID<br/>2. Load Certificate & Provisioning Profile"]
    SigniOS --> BuildIPA["Kompilasi IPA:<br/>flutter build ipa --release"]
    BuildIPA --> UploadApple["Upload ke App Store Connect<br/>(TestFlight / App Store Review)"]

    UploadGoogle --> End(["Aplikasi Siap Didistribusikan"])
    UploadApple --> End

Distribusi dan Rilis ke Google Play Store #

Setelah menghasilkan berkas AAB yang ditandatangani, kita dapat masuk ke Google Play Console (play.google.com/console) untuk memulai proses distribusi.

1. Menentukan Jalur Uji Rilis (Release Tracks) #

Google Play Console menyediakan empat jalur rilis utama untuk menguji stabilitas aplikasi sebelum dipublikasikan secara luas:

  • Internal Testing: Jalur tercepat. Rilis dapat langsung dinikmati oleh maksimal 100 orang penguji internal yang diundang tanpa perlu melalui proses review ketat oleh Google. Sangat cocok untuk pengujian rilis harian (daily builds).
  • Closed Testing (Alpha/Beta): Mengundang kelompok penguji berskala menengah (hingga 2000 orang) menggunakan tautan email atau grup Google Groups. Cocok untuk pengujian pra-rilis oleh tim eksternal.
  • Open Testing: Rilis beta publik di mana siapa saja dapat mendaftar melalui halaman Play Store untuk menguji versi beta aplikasi kita.
  • Production: Rilis resmi yang dapat diunduh oleh semua pengguna umum di wilayah/negara yang dipilih.

2. Strategi Rollout Bertahap (Staged Rollout) #

Saat meluncurkan pembaruan besar di jalur Production, hindari merilisnya secara langsung $100%$ sekaligus. Hal ini sangat berisiko jika ada bug tersembunyi yang lolos dari fase QA.

Gunakan fitur Staged Rollout untuk mempublikasikan rilis secara bertahap:

$$\text{Rollout Stages} = 1% \rightarrow 5% \rightarrow 10% \rightarrow 20% \rightarrow 50% \rightarrow 100%$$

Pantau grafik laporan error di Google Play Console atau Firebase Crashlytics secara real-time pada setiap tahap persentase. Jika terdeteksi adanya lonjakan error (crash rate) pada persentase $5%$, kita dapat menghentikan rilis (halt release) segera, memperbaiki bug, lalu meluncurkan rilis perbaikan tanpa memengaruhi $95%$ sisa basis pengguna kita.


Distribusi dan Rilis ke Apple App Store #

Untuk platform iOS, kita menggunakan App Store Connect (appstoreconnect.apple.com) untuk mendistribusikan file IPA kita.

1. Distribusi via TestFlight #

TestFlight adalah platform resmi Apple untuk menguji aplikasi iOS sebelum dirilis ke App Store.

  • Internal Testers: Maksimal 100 anggota tim kita (yang terdaftar di App Store Connect). File build rilis langsung dapat dipasang secara instan.
  • External Testers: Maksimal 10.000 penguji publik melalui tautan undangan terbuka atau email. Build ini memerlukan review singkat dari Apple (biasanya memakan waktu kurang dari 24 jam) sebelum dapat diuji.

2. Menyiapkan Data untuk Reviewer Apple #

Proses review aplikasi oleh Apple terkenal sangat ketat. Banyak aplikasi ditolak (rejected) karena masalah sepele yang sebenarnya dapat dihindari. Berikut adalah taktik untuk memuluskan proses review:

  • Sertakan Akun Demo Valid: Jika aplikasi kita membutuhkan login, sertakan username dan password akun pengujian (demo account) yang valid pada bagian Notes for Reviewer. Pastikan data transaksi akun tersebut sudah terisi dan tidak kosong.
  • Jelaskan Izin Permission: Jika aplikasi kita mengakses lokasi latar belakang, kamera, atau Bluetooth, jelaskan secara mendalam mengapa aplikasi membutuhkan izin tersebut dan bagaimana cara mencobanya di aplikasi.
  • Sertakan Video Demo: Jika alur kerja fitur kita melibatkan interaksi dengan perangkat fisik eksternal (seperti koneksi ke perangkat IoT via Bluetooth), rekam video demonstrasi singkat penggunaan perangkat tersebut dan unggah tautan videonya untuk membantu reviewer Apple memahami cara kerja aplikasi.

Checklist Kesiapan Rilis Komprehensif #

Sebelum mengetuk tombol rilis final, pastikan kita memverifikasi seluruh komponen berikut:

1. Analisis Kode & Kualitas #

  • Perintah flutter analyze berjalan bersih tanpa peringatan (warning) atau kesalahan (error).
  • Seluruh unit test, widget test, dan integration test berhasil lolos pengujian tanpa kegagalan.
  • Nomor versi (version name) dan build number (version code) telah dinaikkan secara benar di pubspec.yaml.
  • Berkas CHANGELOG telah diperbarui untuk mencatat daftar fitur baru dan perbaikan bug.

2. Konfigurasi Build & Lingkungan #

  • Kompilasi dijalankan menggunakan flag --release secara eksplisit.
  • Berkas konfigurasi --dart-define-from-file menggunakan file profil produksi rilis yang valid.
  • Sertifikat penandatanganan native digital yang digunakan sesuai dengan akun rilis (bukan debug certificate).
  • Aplikasi telah diuji jalankan langsung pada perangkat fisik rilis (bukan emulator) dan performanya lancar.

3. Metadata & Hukum Toko Aplikasi #

  • Semua ukuran gambar tangkapan layar (screenshots) yang disyaratkan telah diperbarui sesuai tampilan aplikasi terbaru.
  • Deskripsi singkat, deskripsi lengkap, dan catatan rilis (release notes) telah diterjemahkan ke dalam bahasa yang didukung.
  • Tautan URL kebijakan privasi (privacy policy) aktif dan dapat diakses secara publik.
  • Kuesioner rating konten (content rating rating) telah diisi secara jujur dan akurat.

Ringkasan #

  • Semantic Versioning: Kelola penomoran rilis dengan struktur major.minor.patch+buildNumber. Build number wajib selalu naik pada setiap pengunggahan biner baru.
  • Android Signing: Buatlah berkas Keystore secara aman menggunakan keytool, simpan di luar repositori Git, dan hubungkan konfigurasinya secara lokal via key.properties. Gunakan format App Bundle (.aab) untuk pengunggahan di Play Store.
  • iOS Signing: Manfaatkan Apple Distribution Certificate dan App Store Provisioning Profile yang sah, serta konfigurasikan proses ekspor IPA menggunakan file ExportOptions.plist.
  • Rollout Play Store: Terapkan metode Staged Rollout secara bertahap ($1% \rightarrow 5% \rightarrow 10% \rightarrow 100%$) untuk memitigasi risiko crash pasca-rilis massal.
  • Review App Store: Hindari penolakan aplikasi oleh Apple dengan menyertakan akun uji coba aktif, penjelasan kebutuhan permission, dan tautan kebijakan privasi yang valid pada bagian informasi peninjauan.

← Sebelumnya: Flavors & Environment   Berikutnya: CI/CD →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact