Episode ini menyusun pipeline CI untuk Hermes builds: mendefinisikan job yang memproduksi bytecode secara deterministik, menangkap dan memvalidasi bytecode serta source maps, lalu menegakkan deployment checks untuk release Android dan iOS.

Episode 18 menutup dengan crash reporting dan native stack traces — bagaimana menyimbolkan laporan crash menjadi informasi yang bisa ditindaklanjuti. Sekarang kita masuk Fase 6 dan mulai menutup lubang terakhir sebelum production: kepercayaan terhadap build. Kalau setiap developer membangun dengan cara berbeda, yang sampai ke pengguna bukanlah artefak yang kalian validasi.
Roadmap episode 19: pipeline CI untuk Hermes builds, menangkap artefak yang konsisten, validasi bytecode dan source maps, lalu deployment checks untuk release Android dan iOS.
Pipeline CI untuk aplikasi Hermes harus menghasilkan artefak yang sama seperti build lokal yang tervalidasi. Setiap push ke cabang main (atau PR) seharusnya memicu job yang: checkout source, pasang dependencies, kompilasi bytecode Hermes, lalu membangun release. Contoh pipeline GitHub Actions:
name: hermes-release
on:
pull_request:
branches: [main]
push:
branches: [main]
jobs:
build-android:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- name: Install dependencies
run: bun install --frozen-lockfile
- name: Generate bytecode Hermes
run: |
npx react-native bundle --platform android --dev false \
--entry-file index.js --bundle-output index.android.bundle
hermesc -O -emit-binary -out index.android.hbc index.android.bundle
- name: Build release APK
working-directory: android
run: ./gradlew assembleRelease
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: android-release
path: android/app/build/outputs/apk/release/Info
CI membutuhkan environment yang deterministik. Gunakan runner yang terpisah antara Android (Ubuntu) dan iOS (macOS), dan pastikan versi JDK, Node, serta Hermes dikunci — jangan pernah membiarkan CI mengambil "versi terbaru" secara liar.
Pipeline di atas memproduksi bytecode secara eksplisit dengan hermesc. Di React Native modern, gradle melakukan langkah ini otomatis saat assembleRelease; memproduksinya eksplisit di CI memberi kalian kontrol dan artefak yang bisa divalidasi lebih dulu sebelum masuk ke dalam APK.
Validasi tidak ada gunanya kalau artefak hilang. Untuk build Hermes, minimal simpan empat artefak yang diindeks oleh versi:
.hbc (atau .bundle hasil Hermes)..hbc.map untuk deobfuscation stack trace..so di Android atau dSYM di iOS).Konsistensi dimulai dari flag kompiler yang sama untuk semua developer dan CI. Kunci flag di gradle supaya tidak bisa diganti diam-diam:
react {
hermesFlags = ["-O", "-output-source-map"]
}Dengan -output-source-map, gradle menghasilkan file .hbc.map berpasangan dengan bytecode. Arsipkan keduanya dengan nama yang memuat versi rilis, misalnya app-1.4.0.hbc dan app-1.4.0.hbc.map — karena stack trace produksi tanpa source map yang cocok hanya akan menjadi teka-teki.
CI harus gagal jika bytecode aneh. hbcdump bisa memeriksa isi file .hbc — jumlah function, versi bytecode, hingga disassembly jika perlu:
hbcdump -function-sources index.android.hbc
shasum -a 256 index.android.hbc index.android.hbc.map
node scripts/verify-sourcemap.mjs index.android.hbc.mapLangkah wajib lainnya: verifikasi source map. Ambil beberapa alamat dari stack trace contoh, petakan lewat tool symbolication, dan pastikan hasilnya mengarah ke baris file sumber yang benar. Source map yang "tidak nyambung" akan membuat error produksi tidak bisa dilacak. Untuk menjalankan pemeriksaan ini otomatis, tambahkan step node scripts/verify-sourcemap.mjs ke pipeline sebagai gerbang sebelum upload artefak.
Warning
Bytecode Hermes terkunci ke versi engine. Jika versi Hermes di gradle berbeda dari versi hermesc yang dipakai membuat .hbc di CI, hasilnya bisa menjadi bytecode yang tidak bisa dieksekusi atau error misterius di runtime. Selalu pakai versi yang sama di semua langkah.
Sebelum APK dirilis, jalankan verifikasi otomatis:
cd android && ./gradlew assembleRelease
apksigner verify --print-certs app/build/outputs/apk/release/app-release.apk
unzip -p app/build/outputs/apk/release/app-release.apk \
assets/index.android.bundle | head -c 4 | xxdTiga hal yang dicek: build sukses, APK ditandatangani dengan sertifikat yang benar, dan aset bundle dimulai dengan magic bytes bytecode Hermes (bukan JavaScript polos). Magic bytes yang tampil sebagai opcode Hermes memastikan runtime Hermes yang akan mengeksekusi, bukan JavaScript interpreter yang lambat. Verifikasi ini juga melindungi kalian dari build yang tanpa sengaja mematikan Hermes.
Di macOS, gunakan xcodebuild untuk archive dan verifikasi tanda tangan serta konten:
xcodebuild archive -workspace App.xcworkspace -scheme App -configuration Release
codesign --verify --deep --strict build/Release-iphoneos/App.app
file build/Release-iphoneos/App.app/main.jsbundlefile pada main.jsbundle di iOS juga harus melaporkan bytecode Hermes. Jika laporan menunjukkan teks (alias JavaScript polos), berarti kompilasi Hermes tidak berjalan dan performa startup kalian akan mengecewakan di production.
Build yang bisa direproduksi adalah fondasi dari semua diskusi observability dan release automation di dua episode terakhir nanti. CI bukan tempat untuk "menemukan" masalah — itu harus menjadi gerbang yang menolak artefak yang tidak sesuai standar sebelum mencapai pengguna.
Inti yang harus dibawa pulang:
hbcdump dan verifikasi source map dengan symbolication contoh.apksigner dan codesign) sebelum upload ke toko.Di episode 20, kita lanjut ke Observability & Performance Monitoring: memantau metrik runtime startup, memori, dan eksekusi JavaScript, lalu menetapkan performance budgets yang bisa ditegakkan. Sampai jumpa!