-
Notifications
You must be signed in to change notification settings - Fork 280
223 lines (197 loc) · 9.11 KB
/
Copy pathe2e_ios.yml
File metadata and controls
223 lines (197 loc) · 9.11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
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: Cache Homebrew downloads
# bottle 按 URL 内容寻址,restore-keys 前缀命中即省下载(装/链接照常)
uses: actions/cache@v5.0.4
with:
path: ~/Library/Caches/Homebrew
key: ${{ runner.os }}-brew-e2e-${{ github.sha }}
restore-keys: |
${{ runner.os }}-brew-e2e-
- 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: Cache Metro transform cache
# 内容寻址(等价 ccache 之于 clang):陈旧条目只影响命中率不影响正确性
uses: actions/cache@v5.0.4
with:
path: Example/e2etest/.metro-cache
key: ${{ runner.os }}-metro-e2e-${{ github.sha }}
restore-keys: |
${{ runner.os }}-metro-e2e-
- 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: Cache built e2e app (keyed on native inputs)
# 命中 = native 输入(两个 ios 工程、cpp/jni、podspec、依赖锁、codegen 输入)
# 一字未改,跳过 pod install + xcodebuild,只重新注入 JS bundle(见下)。
# codegen 输入必须参与 key:TurboModule 胶水在 pod install 时由根
# package.json 的 codegenConfig + src/Native*.ts spec 生成,漏了它们
# 会在改 spec 后把新 JS 注入到旧胶水的二进制上。
# 故意不设 restore-keys:部分命中就是错的二进制,宁可全量重建。
id: cache-ios-app
uses: actions/cache@v5.0.4
with:
path: |
Example/e2etest/ios/build/Build/Products/Release-iphonesimulator/AwesomeProject.app
Example/e2etest/ios/build/hermesc
key: ${{ runner.os }}-e2e-app-xcode-26.4-${{ hashFiles('Example/e2etest/ios/**', 'Example/e2etest/package.json', 'Example/e2etest/bun.lock', 'react-native-update.podspec', 'react-native.config.js', 'expo-module.config.json', 'ios/**', 'cpp/**', 'android/jni/**', 'src/Native*.ts', 'package.json') }}
- name: Install CocoaPods dependencies
if: steps.cache-ios-app.outputs.cache-hit != 'true'
# 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)
if: steps.cache-ios-app.outputs.cache-hit != 'true'
env:
RNU_CLI_ROOT: ${{ github.workspace }}/react-native-update-cli
run: |
cd Example/e2etest && E2E_PLATFORM=ios bunx detox build --configuration ios.sim.release
# hermesc 进缓存区:命中 run 没有 Pods,注入脚本需要它编 HBC
cp ios/Pods/hermes-engine/destroot/bin/hermesc ios/build/hermesc
- name: Refresh JS bundle in cached app
if: steps.cache-ios-app.outputs.cache-hit == 'true'
run: cd Example/e2etest && ./scripts/refresh-ios-app-bundle.sh
- 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
with:
name: e2e-ios-detox-artifacts
path: Example/e2etest/artifacts
if-no-files-found: ignore
retention-days: 7