Tiếp nối MR !36 (merged). Không thêm tính năng — sửa hai thứ đã trực tiếp gây ra một buổi debug sai hướng, và ghi lại nguyên nhân để không lặp lại.
Bối cảnh: OTA đã hoạt động, và đây là bằng chứng
Xác minh trên Samsung SM-M346B1 qua adb, trên APK 0.0.8 cài sẵn, không cài lại gì:
| Lúc | Nhãn trên máy | Log dev.expo.updates
|
|---|---|---|
| 15:51 | Deposit OTA4 |
CheckCompleteAvailable → Download → DownloadComplete → Restart |
| 15:54 | Deposit |
cùng chuỗi, chiều ngược lại |
Bản app tải về: 01a06675-9178-7bbd-af2b-7c6d4209a01f, createdAt 2026-09-03T08:49:36Z, runtime 7acadc72….
Nguyên nhân thật của việc "OTA không chạy"
expo-updates so commitTime của bundle nhúng trong binary với createdAt của bản OTA, và chỉ nhận bản mới hơn.
Bundle nhúng trong APK 29c77a75 : 15:09:13
Bản OTA publish : 14:27:52 ← cũ hơn 42 phút
Publish trước rồi mới build ⇒ binary từ chối vĩnh viễn bản OTA đó. App kiểm tra đúng, gọi server đúng, và kết luận đúng — nhưng thông điệp lại nhìn y hệt lỗi cấu hình:
Updates state change: CheckCompleteUnavailable
UpdatesController onBackgroundUpdateFinished: No update available
code: NoUpdatesAvailable
Không có gì sai trong updates.url, channel, hay runtimeVersion. Chỉ là thứ tự.
Thay đổi
1. docs/ota-updates.md — thêm ba mục:
-
Thứ tự bắt buộc: build TRƯỚC, publish SAU — kèm bảng đối chiếu, log thật, và lệnh đọc
commitTimecủa bundle nhúng từ file APK. -
Số phiên bản và
versionCode— cái gì nằm trong fingerprint, cái gì không. -
Đọc log OTA từ thiết bị thật — công thức
adb logcatvà chuỗi trạng thái của một lần cập nhật thành công. Đây là thứ duy nhất chẩn đoán được vấn đề; trước đó chỉ toàn suy đoán.
2. package.json: 0.0.8 → 0.0.9
3. eas.json: autoIncrement: true cho profile staging
Trước đây mọi build staging từ 27/08 đến nay đều mang 0.0.8 / versionCode 1. Tester không có cách nào biết đang chạy artifact nào — và điều đó đã khiến chúng ta debug sai APK một vòng (một bản 27/08 còn tab Benefit bị lẫn với bản mới). development và ui vốn đã bật autoIncrement; staging bị bỏ sót.
Điều reviewer cần biết trước khi merge
autoIncrement không làm đổi runtimeVersion mỗi build — đã kiểm chứng: versionCode lưu phía EAS (appVersionSource: "remote") và không xuất hiện trong danh sách fingerprint source. Nếu nó có mặt thì mỗi build sẽ có runtime mới và OTA sẽ không bao giờ tới được binary cũ; may là không phải vậy.
Nhưng eas.json lại chính là một fingerprint source (reasons: ['easBuild']), nên bản thân việc sửa file này đổi runtime một lần:
0.0.8 -> 7acadc7291de6d270c265e2cb0dc2423107b0bd1
0.0.9 -> e3aebc5cb2c22810c0fc9385f3435ed436e93b38
0.0.9 + autoIncrement staging -> cbb9ed23c60864e84f5e47908cda8f0f2647ca6a
staging đều nằm ở runtime cũ và sẽ không khớp binary mới. Đúng cái bẫy mà MR này ghi vào runbook — nên đừng vướng vào nó ngay ở lần merge này.
Trạng thái channel staging hiện tại
Đã sạch, khớp develop, ở cả hai runtime đang lưu hành (7acadc72… cho 0.0.8 và e3aebc5c… cho 0.0.9). Không còn chuỗi thử nào đang phát.
Đã kiểm chứng
-
pnpm check-allsạch — 320 test / 48 suite pass, lint + type-check + translations OK. - OTA hai chiều trên thiết bị thật (bảng ở đầu MR).
- Fingerprint tính lại sau mỗi thay đổi, giá trị ghi ngay trong runbook.
Ngoài phạm vi
Tự động publish qua GitLab CI; autoIncrement cho production (cố ý không đổi — phát hành store cần quyết định riêng); OTA cho production; code signing.