Pembaruan Over-The-Air (OTA) memungkinkan pengembang React Native mengirimkan pembaruan JavaScript bundle dan aset secara langsung ke perangkat pengguna tanpa melalui proses peninjauan App Store atau Google Play Store. Mekanisme ini mempercepat siklus rilis, tetapi membawa risiko fatal: kesalahan runtime yang lolos ke produksi langsung berdampak pada seluruh basis pengguna aktif secara bersamaan.
Ketika bundle bermasalah terbit, mitigasi manual membutuhkan waktu respons yang terlalu lambat. Artikel ini membahas implementasi observabilitas menggunakan Sentry Release Health, integrasi alert webhook ke GitHub Actions, dan eksekusi rollback terprogram untuk memulihkan stabilitas aplikasi dalam hitungan menit.
Skenario Insiden: Bundle JS Rusak pada Jalur Produksi
Sebagian besar kegagalan fatal OTA tidak terdeteksi saat proses kompilasi pipeline CI. Bundle JavaScript berhasil dibuat oleh Metro bundler, sintaks TypeScript valid, namun aplikasi mengalami crash loop sesaat setelah mengunduh bundle baru.
Penyebab umum meliputi:
- Akses Native Module yang Belum Tersedia: Bundle JS memanggil native module atau method baru yang belum terkompilasi pada native binary pengguna yang masih berada di versi lama.
- Kesalahan Parsing Skema Remote State: Perubahan struktur data global (misalnya via Redux Persist atau AsyncStorage) yang menyebabkan unhandled exception saat inisialisasi aplikasi.
- Kegagalan Evaluasi Hermes: Kode tertentu yang lolos uji di engine JavaScriptCore atau web mengalami kegagalan sintaksis saat dikompilasi ke bytecode Hermes di lingkungan rilis.
Dampaknya, metrik Crash-Free Sessions turun drastis di bawah Service Level Agreement (SLA). Tanpa automasi, tim engineer harus menerima laporan pengguna, memverifikasi isu, dan menjalankan perintah publish bundle lama secara manual.
Konfigurasi Observabilitas: Sentry Release Health
Untuk mendeteksi penurunan performa bundle seketika, Sentry Release Health harus dikonfigurasi untuk membedakan native binary version dengan OTA bundle revision. Gunakan kombinasi release dan dist yang unik untuk setiap rilis OTA.
import * as Sentry from "@sentry/react-native";
import Constants from "expo-constants";
// Ekstraksi versi native dan identifier update OTA
const nativeVersion = Constants.expoConfig?.version ?? "1.0.0";
const updateId = Constants.expoConfig?.updates?.url
? (Constants.manifest2?.metadata?.updateId ?? "embedded")
: "embedded";
Sentry.init({
dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
enableAutoSessionTracking: true,
// Format release memetakan binary, dist memetakan spesifik OTA bundle hash
release: `com.company.app@${nativeVersion}`,
dist: updateId,
tracesSampleRate: 0.1,
});
Properti enableAutoSessionTracking: true mencatat sesi aplikasi dari foreground hingga background. Jika sesi berakhir karena unhandled JS exception atau fatal native crash, sesi ditandai sebagai crashed session. Metrik ini diagregasikan secara real-time oleh Sentry Release Health.
Konfigurasi Metric Alert
Buat Metric Alert pada dasbor Sentry dengan kriteria berikut:
- Metric: Crash-free session percentage.
- Window: 5 menit.
- Critical Threshold: < 98.0% (sesuai SLA tim).
- Filter:
environment:production. - Action: Trigger Webhook ke Endpoint Automasi CI/CD.
Arsitektur Rollback: Webhook Relay ke GitHub Actions
Sentry webhook mengirimkan payload JSON saat alert terpicu. Karena GitHub API memerlukan token autentikasi khusus dan format payload spesifik untuk endpoint repository_dispatch, gunakan fungsi serverless ringan (misalnya Cloudflare Worker atau AWS Lambda) sebagai perantara (relay).
// Contoh implementasi perantara webhook (Cloudflare Worker)
export default {
async fetch(request, env) {
if (request.method !== "POST") {
return new Response("Method Not Allowed", { status: 405 });
}
const payload = await request.json();
// Validasi apakah alert berasal dari aturan Crash-Free Session
if (payload.action === "triggered" && payload.data?.metric_alert) {
const response = await fetch(
"https://api.github.com/repos/org-name/mobile-app/dispatches",
{
method: "POST",
headers: {
Authorization: `Bearer ${env.GH_PAT_TOKEN}`,
Accept: "application/vnd.github.v3+json",
"User-Agent": "Sentry-Alert-Relay",
},
body: JSON.stringify({
event_type: "sentry_ota_rollback",
client_payload: {
rule_name: payload.data.metric_alert.alert_rule.name,
current_rate: payload.data.metric_alert.incident?.current_value,
},
}),
}
);
return new Response("Dispatched", { status: response.status });
}
return new Response("Ignored", { status: 200 });
},
};
Otomasi GitHub Actions: Eksekusi Revert Target Bundle
Ketika GitHub menerima event sentry_ota_rollback, alur kerja (workflow) segera dijalankan. Pada ekosistem Expo (EAS Update), tindakan pemulihan paling aman adalah mempublikasikan kembali (re-publish) bundle stabil terakhir atau membatalkan penugasan channel update ke branch bermasalah.
name: Automated OTA Rollback
on:
repository_dispatch:
types: [sentry_ota_rollback]
jobs:
rollback:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
- name: Install Dependencies
run: npm ci
- name: Setup Expo EAS
uses: expo/expo-github-action@v8
with:
eas-version: latest
token: ${{ secrets.EAS_TOKEN }}
- name: Revert EAS Update Channel
run: |
echo "SLA Breached! Initiating automated rollback."
# Dapatkan ID update stabil sebelumnya (n-1) pada branch production
PREVIOUS_GROUP_ID=$(eas update:list --branch production --json --limit 2 | jq -r '.[1].group')
# Publikasikan kembali update group stabil ke channel production
eas update:republish --group-id "$PREVIOUS_GROUP_ID" --branch production --message "Automated Rollback triggered by Sentry Release Health"
Catatan Keamanan: Batasi permission token EAS dan GitHub PAT. Gunakan branch protection rule agar workflow automasi rollback memiliki hak eksekusi terisolasi tanpa risiko membatalkan commit di repositori Git.
Format Postmortem Insiden Deployment
Setiap aktivasi rollback otomatis harus diikuti dengan evaluasi postmortem tanpa menyalahkan individu (blameless postmortem). Dokumentasikan temuan dalam format standar berikut:
1. Ringkasan & Dampak
- Waktu Insiden: 24 Oktober 2024, 14:15 WIB – 14:28 WIB (13 menit).
- Dampak: Crash-Free Sessions turun dari 99.8% ke 94.2%. Sekitar 1.200 sesi pengguna mengalami crash saat aplikasi dibuka.
- Resolusi: Otomasi Sentry dan GitHub Actions mempublikasikan bundle stabil sebelumnya dalam 3 menit setelah ambang batas 98% terlampaui.
2. Timeline Kejadian
- 14:15: Bundle OTA commit
a8f12cterbit ke branchproductionvia EAS. - 14:18: Pengguna mulai menerima update. Sentry mencatat lonjakan unhandled promise rejection:
TypeError: Cannot read property 'initializeClient' of undefined. - 14:22: Metrik Crash-Free Session 5 menit menyentuh 97.4% (Threshold: 98%).
- 14:23: Sentry metric alert memicu webhook relay. GitHub Actions workflow
Automated OTA Rollbackdimulai. - 14:25: EAS Update selesai mere-publish bundle stabil
3d4e1b. - 14:28: Klien mengunduh bundle stabil. Crash-Free Session kembali stabil pada 99.8%.
3. Akar Masalah (Root Cause)
Fitur baru mengasumsikan keberadaan modul native push notification versi terbaru. Klien di lapangan masih menggunakan versi binary aplikasi satu versi di bawahnya yang tidak memiliki native bindings tersebut. Evaluasi modul gagal saat app bootstrapping.
4. Langkah Pencegahan Teknis
- Bundle Smoke Test Otomatis: Integrasikan Hermes CLI ke pipeline CI untuk memvalidasi evaluasi bundle sebelum publish:
node node_modules/react-native/scripts/hermes-compiler.js bundle.js -emit-binary -out bundle.hbc - Penerapan Canary Release Bertahap: Hindari penyebaran OTA 100% langsung. Gunakan deployment bertahap (misal: 10% target rollout pada 30 menit pertama) untuk mengisolasi dampak kegagalan runtime sebelum menyentuh seluruh pengguna.
- Runtime Native Guard: Wajibkan pengecekan ketersediaan native module sebelum pemanggilan:
if (!NativeModules.NewFeatureModule) { // Fallback gracefully atau nonaktifkan fitur return; }
Kesimpulan
Pembaruan OTA memberikan fleksibilitas tinggi bagi tim React Native, namun membutuhkan sistem mitigasi yang setara dengan risikonya. Menggabungkan Sentry Release Health dengan pipeline CI/CD GitHub Actions memastikan aplikasi memiliki mekanisme pertahanan mandiri (self-healing) yang membatasi waktu henti layanan secara deterministik.
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!