Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions .github/releases/v10.61.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
## English

### One engine for the native update round

The native cold-start round (the check that runs without JS and rescues bricked devices) now runs on one shared C++ engine on Android, iOS and HarmonyOS, instead of three hand-written loops. The rules were already shared; now the sequence is too, pinned by replayed event traces. This is a native release: rebuild the app, and run `pod install` on iOS.

Where the platforms disagreed, they now behave the same:

- **Request timeouts**: every request of the round has a 10 s idle and a 15 s whole-request limit, capped by the round's deadline.
- **Configuration changes**: a round whose result loses to a configuration change finishes as `cancelled` / `config_changed`.
- **Resumable downloads**: the resume decisions (sidecar check, `Range` / `If-Range`, response handling, `Content-Range` parsing) are shared too. After a complete download every platform now refreshes the sidecar with the final size (previously HarmonyOS only), so a process killed between download and unzip no longer downloads a chunked archive again. Sidecars are capped at 64 KB, and `Content-Range` accepts digits only.
- **Stored items**: a binary upgrade and a reset to the packaged bundle now delete the same items on every platform (version info, the first-load marker, the response cache) and keep the same ones (uuid, native configuration, round breadcrumb, bundle hash cache). Nothing on disk is migrated.

### Behaviour changes

- **JS `client.checkUpdate()`** returns the result resolved for this device (its gray-rollout bucket and running version), as the provider already presented it. The returned object no longer contains `expVersion`. Apps that call `client.checkUpdate()` and then `client.downloadUpdate()` directly now respect rollout percentages instead of installing the root release.
- **JS `useUpdate().switchVersion()` / `switchVersionLater()` without an argument** switch to the downloaded version. Previously they used the last checked version, which turned "switch now" into a silent no-op when a later check found a newer release after the download.
- **iOS `resetToPackagedBundle`** resolves once the reset state is persisted and deletes the downloaded versions in the background, as Android and HarmonyOS already did. `RESET_FAILED` now only means the reset state could not be persisted.
- **Android**: a binary upgrade or a reset no longer clears the uuid and the native configuration. Before, every app upgrade reshuffled gray-rollout buckets, and the native check and crash hold had no configuration until JS ran again.
- **JS endpoint fallback**: one check sends at most 8 endpoint requests, the native round's budget. The remote endpoint list could previously make a failed check fan out to every entry.

### New

- **Bounded `prepareBundle` on Android and HarmonyOS**: `PushyRuntime.prepareBundle(context, timeoutMillis, callback)` and `PushyFileJSBundleProvider.prepareBundle(timeoutMs)`, as iOS already had. On expiry the result is `failed` / `timeout` and the round keeps running in the background. Without a timeout Android now waits at most 30 minutes (the iOS default), and concurrent callers no longer queue behind each other.

### Fixes

- iOS: the native round and crash hold now verify the bundle digest before activating a version (`CheckActivation`), as `switchVersion` and the other platforms do.
- iOS and HarmonyOS: C++ exceptions from the shared core are caught at the iOS entry points and the HarmonyOS NAPI callbacks instead of unwinding into the runtime. iOS falls back to the packaged bundle when the launch state cannot be resolved.
- HarmonyOS: activation and destructive cleanup can no longer race (a cleanup could delete a version that was just verified), and `switchVersion` re-checks for a reset that happened while it verified.
- HarmonyOS: insufficient disk space and oversized archives report `DOWNLOAD_FAILED` during download and `PATCH_FAILED` during unpack, as on Android and iOS, so mirror retries and telemetry agree.
- HarmonyOS: when `meta.json` has no build time, the app install time is used, so a binary upgrade that keeps its `versionName` is still detected. The download connect timeout is 15 s instead of the whole phase budget.
- JS: the "bundle not registered" warning names the brand's own CLI (`cresc` for Cresc).

### For integrators

- The npm package ships only the HDiffPatch / lzma sources the builds compile (910 → 177 files).
- `nativeConfigSource` is now documented in the README options table.

[Full changelog](https://github.com/reactnativecn/react-native-update/compare/v10.60.0...v10.61.0)

## 中文

### 原生更新流程只用一个引擎

原生冷启动流程(不依赖 JS、用来救回变砖设备的检查)在 Android、iOS、鸿蒙上改由同一个 C++ 引擎驱动,不再是三份手写的循环。此前规则已经共用,现在连执行顺序也共用,并由回放的事件轨迹锁定。这是原生版本,需要重新构建应用,iOS 请执行 `pod install`。

原来三端不一致的地方,现在行为相同:

- **请求超时**:流程中的每个请求都是空闲 10 秒、整次 15 秒的上限,并受整轮截止时间约束。
- **配置变更**:结果输给配置变更的流程,统一以 `cancelled` / `config_changed` 结束。
- **断点续传**:续传的判断(sidecar 校验、`Range` / `If-Range`、响应处理、`Content-Range` 解析)也改为共用。下载完成后三端都会用最终大小刷新 sidecar(此前只有鸿蒙这样做),进程如果死在下载完成之后、解压之前,不会再把总长未知的归档整包重下。sidecar 上限为 64 KB,`Content-Range` 只接受纯数字。
- **持久化项**:二进制升级和 reset 到内置包时,三端删除同样的内容(版本信息、首次加载标记、响应缓存),保留同样的内容(uuid、原生配置、流程中断标记、bundle 摘要缓存)。不迁移任何已落盘的数据。

### 行为变化

- **JS `client.checkUpdate()`** 返回按本设备解析后的结果(依据它的灰度分桶和正在运行的版本),与 provider 一直呈现的一致。返回对象里不再有 `expVersion`。直接调用 `client.checkUpdate()` 再 `client.downloadUpdate()` 的应用,现在会遵守灰度比例,而不是装上根版本。
- **JS `useUpdate().switchVersion()` / `switchVersionLater()` 不带参数时**,切换到已下载的版本。以前用的是最近一次检查到的版本:下载完成后如果又检查到更新的版本,「立即更新」会变成没有任何提示的空操作。
- **iOS `resetToPackagedBundle`** 在 reset 状态落盘后就返回,已下载的版本在后台删除,与 Android、鸿蒙一致。`RESET_FAILED` 现在只表示 reset 状态没能落盘。
- **Android**:二进制升级和 reset 不再清掉 uuid 与原生配置。以前每次应用升级都会重新洗牌灰度分桶,原生检查和崩溃救援在 JS 再次运行前也没有配置可用。
- **JS 端点回退**:一次检查最多发 8 个端点请求,与原生流程的上限相同。以前远程端点列表可能让一次失败的检查把每个条目都请求一遍。

### 新增

- **Android 与鸿蒙的 `prepareBundle` 可以设置超时**:`PushyRuntime.prepareBundle(context, timeoutMillis, callback)` 和 `PushyFileJSBundleProvider.prepareBundle(timeoutMs)`,iOS 此前已有。超时返回 `failed` / `timeout`,流程继续在后台运行。不传超时时,Android 现在最多等 30 分钟(与 iOS 默认值相同),并发调用者也不再互相排队。

### 修复

- iOS:原生流程和崩溃救援在激活版本前会校验 bundle 摘要(`CheckActivation`),与 `switchVersion` 和其他两端一致。
- iOS 与鸿蒙:共享内核抛出的 C++ 异常会在 iOS 入口和鸿蒙 NAPI 回调处被捕获,不再穿透到运行时。启动状态无法解析时,iOS 回退到内置包。
- 鸿蒙:激活与破坏性清理不会再相互竞争(以前清理可能删掉刚校验过的版本);`switchVersion` 会复查校验期间是否发生过 reset。
- 鸿蒙:磁盘空间不足和归档超限,在下载阶段报 `DOWNLOAD_FAILED`,在解压阶段报 `PATCH_FAILED`,与 Android、iOS 一致,换镜像判定和遥测口径因此统一。
- 鸿蒙:`meta.json` 里没有构建时间时改用应用安装时间,保留 `versionName` 的二进制升级也能被识别。下载的连接超时改为 15 秒,不再等于整个阶段的预算。
- JS:「bundle 未注册」提示里的命令按品牌显示(Cresc 显示 `cresc`)。

### 接入方须知

- npm 包只发布构建实际编译的 HDiffPatch / lzma 源码(文件数 910 → 177)。
- README 的选项表补上了 `nativeConfigSource`。

[完整变更记录](https://github.com/reactnativecn/react-native-update/compare/v10.60.0...v10.61.0)
2 changes: 1 addition & 1 deletion harmony/pushy/oh-package.json5
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
name: 'pushy',
description: '',
main: 'index.ets',
version: '10.60.0',
version: '10.61.0',
dependencies: {
'@rnoh/react-native-openharmony': '>=0.72.96',
},
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-native-update",
"version": "10.60.0",
"version": "10.61.0",
"description": "Hot update (OTA) for React Native with Hermes-optimized diff patches, crash rollback and staged rollout. A CodePush alternative for iOS, Android and HarmonyOS.",
"main": "src/index",
"types": "src/index.ts",
Expand Down
Loading