Skip to content

test(e2e): switch between cases via resetToPackagedBundle, not reinstall #217

test(e2e): switch between cases via resetToPackagedBundle, not reinstall

test(e2e): switch between cases via resetToPackagedBundle, not reinstall #217

Workflow file for this run

name: e2e-ios
on:
pull_request:
branches:
- '**'
paths:
- '.github/workflows/e2e_ios.yml'
- '.gitmodules'
- 'package.json'
- 'bun.lock'
- 'react-native-update.podspec'
- 'react-native.config.js'
- 'expo-module.config.json'
- 'src/**'
- 'scripts/**'
- 'ios/**'
- 'cpp/**'
- 'android/jni/**'
- 'Example/e2etest/**'
push:
branches:
- master
paths:
- '.github/workflows/e2e_ios.yml'
- '.gitmodules'
- 'package.json'
- 'bun.lock'
- 'react-native-update.podspec'
- 'react-native.config.js'
- 'expo-module.config.json'
- 'src/**'
- 'scripts/**'
- 'ios/**'
- 'cpp/**'
- 'android/jni/**'
- 'Example/e2etest/**'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
e2e-ios:
runs-on: macos-26
# 绿色基线 ~16 分钟;40 分钟覆盖最坏情况:一次 --retries 1 失败重试
# (失败用例会等满各级长超时)
timeout-minutes: 40
steps:
- name: Checkout react-native-update
uses: actions/checkout@v7
with:
submodules: recursive
- name: Checkout react-native-update-cli
uses: actions/checkout@v7
with:
repository: reactnativecn/react-native-update-cli
path: react-native-update-cli
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: 22
- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- name: Cache Bun dependencies
uses: actions/cache@v5.0.4
with:
path: ~/.bun/install/cache
key: ${{ runner.os }}-bun-e2e-${{ hashFiles('Example/e2etest/bun.lock', 'react-native-update-cli/bun.lock') }}
restore-keys: |
${{ runner.os }}-bun-e2e-
- name: Setup Xcode
uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: '26.4'
- name: Boot iOS simulator in background
# 模拟器冷启动要 2-5 分钟,提前异步 boot,让它和依赖安装/xcodebuild
# 并行。型号必须用与 .detoxrc.ts 完全同一份探测代码——此前 shell 里
# 另写一份选中了 detox 不用的设备,预热全部白费。
# 失败无害:detox 测试阶段会自己 boot。
run: |
udid=$(node Example/e2etest/scripts/detect-ios-simulator-type.js --udid)
if [ -n "$udid" ]; then
echo "pre-booting $(node Example/e2etest/scripts/detect-ios-simulator-type.js) ($udid)"
xcrun simctl boot "$udid" || true
else
echo "no matching simulator found, skipping pre-boot"
fi
- name: Install applesimutils and ccache
run: brew trust wix/brew && HOMEBREW_NO_AUTO_UPDATE=1 brew install wix/brew/applesimutils ccache
- name: Cache ccache
# ccache 按(预处理后)内容寻址,不受 fresh checkout 的 mtime 影响——
# 这是 DerivedData 缓存在 -UseNewBuildSystem=NO 下做不到的。
# 陈旧条目不影响正确性,只影响命中率,所以 restore-keys 用前缀即可。
uses: actions/cache@v5.0.4
with:
path: ~/Library/Caches/ccache
key: ${{ runner.os }}-ccache-e2e-xcode-26.4-${{ github.sha }}
restore-keys: |
${{ runner.os }}-ccache-e2e-xcode-26.4-
- name: Install e2etest dependencies
run: cd Example/e2etest && bun install --frozen-lockfile
- name: Link local react-native-update
run: |
set -euo pipefail
export LOCAL_RNU_VERSION="$(node -p "require('./Example/e2etest/node_modules/react-native-update/package.json').version")"
LOCAL_RNU_DIR="$PWD/Example/e2etest/.e2e-artifacts/local-react-native-update"
rm -rf "$LOCAL_RNU_DIR" Example/e2etest/node_modules/react-native-update
mkdir -p "$LOCAL_RNU_DIR"
cp package.json react-native-update.podspec react-native.config.js expo-module.config.json "$LOCAL_RNU_DIR"/
rsync -a --exclude='.git' src ios android cpp scripts "$LOCAL_RNU_DIR"/
node -e "const fs = require('fs'); const file = 'Example/e2etest/.e2e-artifacts/local-react-native-update/package.json'; const pkg = JSON.parse(fs.readFileSync(file, 'utf8')); pkg.version = process.env.LOCAL_RNU_VERSION; fs.writeFileSync(file, JSON.stringify(pkg, null, 2) + '\n');"
ln -s ../.e2e-artifacts/local-react-native-update Example/e2etest/node_modules/react-native-update
- name: Install react-native-update-cli dependencies
run: cd react-native-update-cli && bun install --frozen-lockfile && bun run build
- name: Prepare local update artifacts
env:
E2E_PLATFORM: ios
RNU_CLI_ROOT: ${{ github.workspace }}/react-native-update-cli
run: cd Example/e2etest && bun run prepare:e2e
- name: Cache CocoaPods downloads
uses: actions/cache@v5.0.4
with:
path: ~/Library/Caches/CocoaPods
key: ${{ runner.os }}-cocoapods-e2e-${{ hashFiles('Example/e2etest/ios/Podfile.lock', 'Example/e2etest/ios/Podfile', 'Example/e2etest/bun.lock') }}
restore-keys: |
${{ runner.os }}-cocoapods-e2e-
- name: Install CocoaPods dependencies
# USE_CCACHE=1 让 react_native_post_install 给所有 pod target 接上
# RN 自带的 ccache 编译器包装脚本
run: cd Example/e2etest/ios && USE_CCACHE=1 pod install
- name: Cache Detox iOS framework
id: cache-detox-ios-framework
uses: actions/cache@v5.0.4
with:
path: ~/Library/Detox
key: ${{ runner.os }}-detox-ios-framework-xcode-26.4-${{ hashFiles('Example/e2etest/bun.lock') }}
restore-keys: |
${{ runner.os }}-detox-ios-framework-xcode-26.4-
- name: Build Detox iOS framework cache
if: steps.cache-detox-ios-framework.outputs.cache-hit != 'true'
run: cd Example/e2etest && bunx detox build-framework-cache
- name: Detox build (ios.sim.release)
env:
RNU_CLI_ROOT: ${{ github.workspace }}/react-native-update-cli
run: cd Example/e2etest && E2E_PLATFORM=ios bunx detox build --configuration ios.sim.release
- name: Detox test (ios.sim.release)
env:
RNU_CLI_ROOT: ${{ github.workspace }}/react-native-update-cli
RNU_E2E_SKIP_PREPARE: 'true'
run: cd Example/e2etest && E2E_PLATFORM=ios bunx detox test --configuration ios.sim.release --retries 1
- name: Upload Detox artifacts
# cancelled() 覆盖 job 超时被杀的场景,否则超时时拿不到现场
if: failure() || cancelled()
uses: actions/upload-artifact@v7.0.1
with:
name: e2e-ios-detox-artifacts
path: Example/e2etest/artifacts
if-no-files-found: ignore
retention-days: 7