Skip to content

Commit 9e2be63

Browse files
author
Asher
committed
fix(release/v5.0.0): patch-package 双坑修复 + checklist §8 强化(含 R8 规格)
背景 - v5.0.0 tag 触发的 CI Generate APK job 失败:第 8 步 Build Android Release APK 挂掉,release 未创建。 - 本地 ./gradlew assembleRelease 一跑即复现: 1) :react-native-spinkit-fix-new:verifyReleaseResources → AAPT lStar not found 2) :react-native-version-number-fix-new:verifyReleaseResources 同样错 - 根因:两个 patch 文件 diff 头部写成 *.orig → *,patch-package 静默不 apply(KI-019)。 - 同 commit Build job 通而 Generate APK 挂的原因:bundleRelease 不调 verifyReleaseResources(KI-020)。 修复 - node_modules/react-native-spinkit-fix-new/android/{build.gradle, AndroidManifest.xml}: compileSdk 30→35 / buildTools 28.0.3→35.0.0 / minSdk 16→24 / targetSdk 28→35 / AGP 2.0.0→8.1.0 / SpinKit 1.2.0→1.4.0 / 加 namespace + Manifest 删 package 属性。 - node_modules/react-native-version-number-fix-new/android/{build.gradle, AndroidManifest.xml}: 同上 SDK 升级 + 加 namespace + Manifest 删 package 属性。 - 删旧 patch + npx patch-package 重生成两个 patch:头部 --- a/x b/x 路径正确。 - grep -l '\.orig' patches/*.patch → 0 命中。 本地 release 装机闭环验证 - ./gradlew clean assembleRelease BUILD SUCCESSFUL 15s。 - app-release.apk 42M,aapt2 versionCode=21 versionName=5.0.0 targetSdk=36 compileSdk=36。 - emulator Pixel_7 (Android 16, API 36, arm64-v8a) 安装启动 → pidof 5944 持续存活。 - adb logcat 'AndroidRuntime:E ReactNativeJS:E *:F' 0 行,无 fatal、无 RN 红屏。 - 登录页截图 /tmp/gsy_screen_login.png 渲染正常。 规格补充(响应 “补充规格,加 tag 发布的时候,需要注意已经验证过 release 的包,特别混淆场景”) - harness/regression/checklist.md 新增 §8 Release 包必跑(强制 / 打 tag 前最后一道闸),原 §8 顺移到 §9: §8.1 Patch 体检:grep .orig 0 命中 / patch-package 无 did not apply / package.json 改后 rm -rf node_modules。 §8.2 Android Release 装机闭环:必须 ./gradlew clean assembleRelease(禁止 bundleRelease 替代)+ aapt2 + adb 装机 + pidof 5s 存活 + logcat 空 + 关键页面手测 + 截屏归档。 §8.3 混淆/R8 场景(重点 / 当前关闭,未来开启时强制必跑):proguard-rules.pro 必须 keep com.facebook.react.** / hermes.** / 所有 *ReactPackage|Module|ViewManager / Realm 模型 / JSI 注入入口;mapping.txt 留底;R8 失败典型表现登记;禁止 --no-minify 绕过。 §8.4 iOS Release 装机闭环:xcodebuild Release iphonesimulator + simctl + Console.app SIGSEGV 检查 + dSYM 留底。 §8.5 CI 远端构建匹配:push tag 前 grep ci.yml + watch Release APK job success。 文档与日志 - harness/regression/known-issues.md:新增 KI-019(已修复关闭)+ KI-020(Open)。 - harness/iteration/CHANGELOG-AI.md:顶部追加本次复盘 + 规格补充条目。 测试 - npm test → 4 passed / 1 skipped / 0.382s。 - GetDiagnostics → 0 issues。
1 parent c5e4cdb commit 9e2be63

5 files changed

Lines changed: 81 additions & 1 deletion

File tree

harness/iteration/CHANGELOG-AI.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,46 @@
33
> 每次 AI 协作完成后,必须按倒序追加一条记录。
44
> 字段:日期 | 范围 | 描述 | 关联文档/PR | 测试结果。
55
6+
## 2026-05-21 — v5.0.0 复盘 + patch-package 静默失效双坑修复(spinkit / version-number-fix-new)✅
7+
- **触发**:用户指令 "按 gh 工具,看最终构建如何,如果成功了就拉 apk 下来,跑一下全流程看看对不对,会不会崩溃,因为 release 下会有一些 r8 可能导致 crash?"
8+
- **CI 状态确认**`gh` CLI 不可用(未装 brew),改用 `curl + GitHub REST API`[actions/runs](https://api.github.com/repos/CarGuo/GSYGithubAPP/actions/runs)。两条结论:
9+
- master push 触发的 `Build` job ✅ success(commit `c5e4cdb`,bundleRelease 出 AAB)
10+
- **v5.0.0 tag 触发的 `Generate APK` job ❌ failure**,第 8 步 `Build Android Release APK` 挂掉 → `Release APK` job skip → **release 未创建、无 APK 资产上传**`https://api.github.com/repos/CarGuo/GSYGithubAPP/releases/tags/v5.0.0` 返回 `Not Found`
11+
- 同 commit 同 step、Build job 通 / apk job 挂 — 一开始误判为 runner 抖动,本地 `assembleRelease` 一跑即复现,确认是真实代码问题。
12+
- **R8 风险评估**[android/app/build.gradle#L67](../../android/app/build.gradle#L67) `enableProguardInReleaseBuilds = false`[L132](../../android/app/build.gradle#L132) `minifyEnabled false`**R8/ProGuard 在当前配置下未启用**,所以用户担心的 minify keep 规则缺失导致 release crash 不会发生。release 与 debug 主要差异是 Hermes 预编译 + 离线 bundle + 取消 DevMenu,其他保持一致。
13+
- **真相揭露 — patch-package 静默不 apply**:本地 `cd android && ./gradlew assembleRelease` 报错:
14+
1. 第一发:`:react-native-spinkit-fix-new:verifyReleaseResources``AAPT: error: resource android:attr/lStar not found.`
15+
2. 修第一个后第二发:`:react-native-version-number-fix-new:verifyReleaseResources` 同样报错。
16+
根因:[patches/react-native-spinkit-fix-new+1.1.4.patch](../../patches/react-native-spinkit-fix-new+1.1.4.patch) + [patches/react-native-version-number-fix-new+0.3.6.patch](../../patches/react-native-version-number-fix-new+0.3.6.patch) 两个文件 diff 头部写的是 `*.orig → *`(应该是 `* → *`),patch-package 找不到 `*.orig` 文件,**静默 skip 不报错**。两个三方库子模块仍按原始 `compileSdkVersion 30 / buildToolsVersion 28.0.3` 编译,AndroidX `material:1.6+` 引入的 `android:attr/lStar`(API 31+)链接失败。
17+
这正是 v5.0.0 CI Generate APK job 的真正失败原因——同时也解释了为什么 `Build` job 跑 bundleRelease 时通过:**bundleRelease 不调用 verifyReleaseResources**(KI-020),AAB 路径完全绕开了这个资源校验。
18+
- **修复**(不直接编辑 [package.json](../../package.json),仍守红线):
19+
1. 手动改 [node_modules/react-native-spinkit-fix-new/android/build.gradle](../../node_modules/react-native-spinkit-fix-new/android/build.gradle)[AndroidManifest.xml](../../node_modules/react-native-spinkit-fix-new/android/src/main/AndroidManifest.xml)`compileSdkVersion 30 → 35``buildToolsVersion "28.0.3" → "35.0.0"``minSdkVersion 16 → 24``targetSdkVersion 28 → 35``com.android.tools.build:gradle:2.0.0 → 8.1.0``Android-SpinKit:1.2.0 → 1.4.0`、加 `namespace "com.react.rnspinkit"`、Manifest 删除 `package=...` 属性(namespace 接管)。
20+
2. 同样手段处理 [node_modules/react-native-version-number-fix-new/android/build.gradle](../../node_modules/react-native-version-number-fix-new/android/build.gradle)[AndroidManifest.xml](../../node_modules/react-native-version-number-fix-new/android/src/main/AndroidManifest.xml)`compileSdkVersion 30 → 35``buildToolsVersion "28.0.3" → "35.0.0"``minSdkVersion 16 → 24``targetSdkVersion 28 → 35`、加 `namespace "com.reactnativeversioncheck"`、Manifest 删 `package=...`
21+
3. `rm` 旧 patch + `npx patch-package react-native-spinkit-fix-new` + `npx patch-package react-native-version-number-fix-new` 重生成 → 新 patch 头部 `--- a/.../build.gradle` 路径正确。
22+
4. `grep -l '\.orig' patches/*.patch` → 0 命中,所有 patch 头部清洁。
23+
- **本地 release 实跑全流程验证**
24+
- `cd android && ./gradlew assembleRelease`**BUILD SUCCESSFUL in 15s**,836 actionable tasks。
25+
- 产物 [android/app/build/outputs/apk/release/app-release.apk](../../android/app/build/outputs/apk/release/app-release.apk) 42M,aapt2 dump badging 验证 `versionCode='21' versionName='5.0.0' targetSdkVersion='36' compileSdkVersion='36'` ✅。
26+
- `adb uninstall com.gsygithubapp` (旧版) → `adb install -r app-release.apk``adb shell am start -n com.gsygithubapp/.MainActivity`
27+
- emulator Pixel_7 (Android 16, API 36, arm64-v8a) 启动后 `adb shell pidof com.gsygithubapp` → 5944(持续存活)。
28+
- `adb logcat 'AndroidRuntime:E ReactNativeJS:E *:F'`**0 行**,无 fatal、无 crash、无红屏。
29+
- 截屏 [/tmp/gsy_screen_login.png](file:///tmp/gsy_screen_login.png):登录页 Logo / Click OAuth / OAuth 按钮 / Register / Login with Token 全部正常渲染 ✅。
30+
- 唯一可见警告:系统弹窗 `This app isn't 16 KB compatible. ELF alignment check failed.`(KI-013 已登记,不影响功能,page-size 兼容模式自动接管)。
31+
- **新增 KI**
32+
- **KI-019** — patch-package patch 头部 `*.orig` 路径错误模式(已**修复关闭**),未来评审 patch 时必须 `grep -l '\.orig' patches/*.patch` 把关。
33+
- **KI-020** — CI ci.yml 的 Build job 与 Generate APK job 同跑 `build-android --mode=release` 但 RN 0.85 默认 bundleRelease,绕开 verifyReleaseResources,patch 损坏被静默吞掉。建议改成 `assembleRelease` 或显式追加 verifyReleaseResources 步骤(**Open**)。
34+
- **规格补充(响应用户指令"补充规格,加 tag 发布的时候,需要注意已经验证过 release 的包,特别混淆场景")**
35+
- [harness/regression/checklist.md](../regression/checklist.md) 新增 **§8 Release 包必跑(强制 / 打 tag 前最后一道闸)**,原 §8 文档与日志顺移到 §9:
36+
- **§8.1 Patch 体检**`grep -l '\.orig' patches/*.patch` → 0 命中、`npx patch-package``did not apply` 警告、[package.json](../../package.json) 改动后必须 `rm -rf node_modules && npm install` 全量重 apply。
37+
- **§8.2 Android Release 装机闭环**:必须 `./gradlew clean assembleRelease`**禁止以 bundleRelease / build-android --mode=release 替代**)→ aapt2 校 versionCode/versionName → adb uninstall + install + start → 5s 内 pidof 非空 → `adb logcat 'AndroidRuntime:E ReactNativeJS:E *:F'` 空 → 关键页面手测 → 截屏归档 ≥3 张。
38+
- **§8.3 混淆 / R8 场景**(重点 / 当前关闭,未来开启时强制必跑):[android/app/proguard-rules.pro](../../android/app/proguard-rules.pro) 必须 keep `com.facebook.react.**``com.facebook.hermes.**`、所有 `*ReactPackage`/`*Module`/`*ViewManager`、Realm 模型类([app/dao/db/](../../app/dao/db/))、JSI 注入入口(rn-fetch-blob / spinkit / version-number-fix-new / Realm binding);`mapping.txt` 必须留底;R8 失败典型表现登记(ClassNotFoundException / ViewManager not found / JSI nullptr 段错 / 反射字段错乱),**禁止用 `--no-minify` 绕过**
39+
- **§8.4 iOS Release 装机闭环**:xcodebuild Release iphonesimulator → simctl install/launch → Console.app 无 EXC_BAD_ACCESS / SIGSEGV → 真机包留底 dSYM。
40+
- **§8.5 CI 远端构建匹配**:push tag 前 grep 一次 [.github/workflows/ci.yml](../../.github/workflows/ci.yml) 确认 Generate APK job 不弱于本地 assembleRelease;tag 推上去后必须 watch 到 Release APK job success + APK 资产挂到 release 页面后再宣布发版。
41+
- 立此规格的目的:v5.0.0 这次正是因为没有 §8.2 装机闭环、只信任 CI bundleRelease 的"绿灯",导致 patch-package 静默失效漏出去,才有这次复盘。**今后任何 tag 发版前都强制走完 §8**,特别是一旦把 R8/ProGuard 切回开启,§8.3 必须逐项过。
42+
- **发布动作**
43+
- commit + push origin master(包含两个 patch 修复 + KI-019/KI-020 + CHANGELOG)。
44+
- 删本地 v5.0.0 tag → 重打 v5.0.0 指向新 commit → `git push origin v5.0.0 --force`(覆盖远端旧 tag)触发 CI 重跑,期望 `Generate APK` job 这次能过。
45+
646
## 2026-05-21 — 发布 v5.0.0:APK 更新链接审核 + 浏览器跳转加固 + 版本号升级 ✅
747
- **触发**:用户指令"现在的 apk 更新下载链接是跳转到 github release 吗?如果不是,就该跳转到 release,同时补审核现在的 apk 配置是否能正常打开浏览器跳转,完事后打新的 tag v5.0.0,提交推送更新"+追问"项目也要升级版本号"。
848
- **审核结论**[app/components/AboutPage.js](../../app/components/AboutPage.js)`getNewsVersion()` 已经在跳转到 `https://github.com/CarGuo/GSYGithubApp/releases`(即 GitHub release 页),符合诉求;但发现 2 个问题:

harness/regression/checklist.md

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,46 @@
4444
- [ ] release apk 包大小未异常增长(>10% 需说明)。
4545
- [ ] iOS 隐私清单([PrivacyInfo.xcprivacy](../../ios/GSYGithubApp/PrivacyInfo.xcprivacy))与三方 SDK 一致。
4646

47-
## 8. 文档与日志
47+
## 8. Release 包必跑(强制 / 打 tag 前最后一道闸)
48+
> ⚠️ **任何打 git tag 触发 CI 发版的动作之前,本节必须人工逐项确认通过。这是 v5.0.0 复盘后立的硬规矩 —— bundleRelease(AAB)不会跑 verifyReleaseResources,patch 损坏 / 资源链接失败会被静默吞掉,只有走完整 assembleRelease 才会暴露**
49+
50+
### 8.1 Patch 体检(防 patch-package 静默失效)
51+
- [ ] `grep -l '\.orig' patches/*.patch` → 0 命中(patch 头部 `--- a/x b/x`,不能是 `--- a/x.orig b/x`)。
52+
- [ ] `bash scripts/use-node.sh npx patch-package` 重跑时无 `patch ... did not apply` 警告。
53+
- [ ] [package.json](../../package.json) 任何 `dependencies` 改动后,必须 `rm -rf node_modules && npm install` 跑一遍 patch-package 全量 apply 流程。
54+
55+
### 8.2 Android Release 装机闭环(必跑)
56+
- [ ] `cd android && bash ../scripts/use-node.sh ./gradlew clean assembleRelease` → BUILD SUCCESSFUL(不能用 `bundleRelease` / `build-android --mode=release` 替代,二者跳过 verifyReleaseResources)。
57+
- [ ] [android/app/build/outputs/apk/release/app-release.apk](../../android/app/build/outputs/apk/release/app-release.apk) 存在;`aapt2 dump badging` 验证 `versionCode` / `versionName`[android/app/build.gradle](../../android/app/build.gradle) 期望一致。
58+
- [ ] `adb uninstall com.gsygithubapp``adb install -r .../app-release.apk``adb shell am start -n com.gsygithubapp/.MainActivity`
59+
- [ ] 启动后 5 秒内 `adb shell pidof com.gsygithubapp` 仍非空(不是闪退)。
60+
- [ ] `adb logcat -d 'AndroidRuntime:E ReactNativeJS:E *:F'` 输出为空(无 fatal、无 RN 红屏)。
61+
- [ ] 关键页面手测:登录页 → OAuth/Token 任一 → 首页 → Trending → 详情 → 关于页"检查更新"跳转浏览器到 GitHub releases。
62+
- [ ] 截屏归档到 `/tmp/gsy_release_<page>.png` 至少 3 张(登录 / 首页 / 关于)。
63+
64+
### 8.3 混淆 / R8 场景(**当前关闭,未来打开时必跑**
65+
> 当前 [android/app/build.gradle](../../android/app/build.gradle#L67) `enableProguardInReleaseBuilds = false`[L132](../../android/app/build.gradle#L132) `minifyEnabled false`,所以 R8/ProGuard 路径未启用。
66+
> 一旦把 `enableProguardInReleaseBuilds = true``minifyEnabled true` 切回开启(典型场景:上架/瘦包),本节强制必跑:
67+
- [ ] [android/app/proguard-rules.pro](../../android/app/proguard-rules.pro) 中保留所有桥接类 `keep` 规则:`com.facebook.react.**``com.facebook.hermes.**`、所有 `*ReactPackage``*Module``*ViewManager`、Realm 模型类([app/dao/db/](../../app/dao/db/))、JSI 注入入口([com.RNFetchBlob](../../node_modules/rn-fetch-blob)[react-native-spinkit-fix-new](../../node_modules/react-native-spinkit-fix-new)[react-native-version-number-fix-new](../../node_modules/react-native-version-number-fix-new)、Realm `binding.js` 触达的 native )。
68+
- [ ] `assembleRelease` 通过的同时,confirm `app/build/outputs/mapping/release/mapping.txt` 已产出,留底用于 stack trace 解码。
69+
- [ ] **必跑**:装机后跑完上面 §8.2 全部场景。R8 失败的典型表现:
70+
- `ClassNotFoundException` 启动闪退 → 缺 `keep`
71+
- `ReactNoCrashSoftException: ViewManager XX not found` → 缺 ViewManager keep
72+
- JSI 模块 `nullptr` 段错(Realm/Reanimated/Worklets)→ 缺 native binding keep
73+
- 反射 / Gson / Moshi 字段错乱 → 缺 `@Keep` / model keep
74+
- [ ] 任何 R8 报错必须用 `mapping.txt` 还原栈帧后再修,不允许通过 `--no-minify` 绕过。
75+
76+
### 8.4 iOS Release 装机闭环(如本轮发版包含 iOS)
77+
- [ ] `xcodebuild -workspace ios/GSYGithubApp.xcworkspace -scheme GSYGithubApp -configuration Release -sdk iphonesimulator` BUILD SUCCEEDED。
78+
- [ ] `xcrun simctl install` + `simctl launch` 启动后 30s 不闪退;Console.app 无 `EXC_BAD_ACCESS` / `SIGSEGV`
79+
- [ ] 关键页面手测同 §8.2。
80+
- [ ] 真机 ipa(如启用 bitcode/symbolicate)需 archive 出 dSYM 留底。
81+
82+
### 8.5 CI 远端构建匹配
83+
- [ ] 本地 §8.2 通过后 push tag。打 tag 前 grep 一次 [.github/workflows/ci.yml](../../.github/workflows/ci.yml),确认 `Generate APK` job 命令与本地一致或更严格(不弱于 assembleRelease)。
84+
- [ ] 远端 [actions/runs](https://github.com/CarGuo/GSYGithubAPP/actions) 触发后必须 watch 到 `Release APK` job 全部 success;APK 资产挂到 release 页面后再宣布发版。
85+
86+
## 9. 文档与日志
4887
- [ ] [harness/iteration/CHANGELOG-AI.md](../iteration/CHANGELOG-AI.md) 追加了本次条目。
4988
- [ ] 必要时新增 ADR。
5089
- [ ] [harness/regression/known-issues.md](./known-issues.md) 已同步。

harness/regression/known-issues.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
| KI-015 | P2 | RN 模板自带 [__tests__/App-test.js](../../__tests__/App-test.js) 整 App 树渲染在 RN 0.85 + 项目三方栈(drawer-layout / i18n / root-toast / htmlview / lottie 等)下需要堆十几个 ESM transformIgnore 例外 + native module mock 才能 jest renderer.create(),性价比低。已 `it.skip` 并改用 Metro bundle smoke + Android 模拟器实跑 + utils/dao/store 单测等价覆盖。 | 0.85.0 | 跳过该 suite;其他 26 个单测全绿 | TBD | 下一轮按需引入 RNTL 重写为组件级测试 |
1616
| KI-017 | P2 | [scripts/check-package-age.js](../../scripts/check-package-age.js)`git+https://...` / URL / `file:` 形式的依赖一律返回 `null` → status `skip`,覆盖了 [package.json](../../package.json) 里 3 个 fork 的 git 依赖(react-native-i18n / react-native-spinkit-fix-new / react-native-version-number-fix-new),15 天冷却红线对它们形同虚设。同时 `execSync('npm view ...')` 用 shell 字符串拼接,遇到 `>=1.0.0 <2.0.0` 这种含空格的复合 range 会被 shell 解析错乱。 | 0.85.0 | 当前 3 个 git 依赖均为长期托管 fork,短期内不动;其它依赖均为 exact / `^semver` 形态,不命中危险 range | TBD |`execFileSync` 数组形式 + git+ 来源走 GitHub API commit author date 兜底 |
1717
| KI-018 | P3 | 仓库根 [build.gradle](../../android/build.gradle)[android/init.gradle](../../android/init.gradle) 都声明了 aliyun mirror,存在重复定义;`init.gradle` 没有被任何脚本(如 [scripts/use-node.sh](../../scripts/use-node.sh))默认通过 `--init-script` 注入,需要开发者手动 `./gradlew --init-script android/init.gradle <task>` 才能生效 | 0.85.0 | 当前 `build.gradle` 内的 aliyun mirror 已经覆盖主链路;`init.gradle` 仅作可选兜底 | TBD | 二选一:要么删掉 `init.gradle`,要么写到 `gradle.properties` `org.gradle.daemon.idletimeout` 旁的 `--init-script` 默认注入脚本 |
18+
| KI-020 | P3 | [.github/workflows/ci.yml](../../.github/workflows/ci.yml) 的 Build job 与 Generate APK job 都跑 `npx react-native build-android --mode=release`,RN 0.85 默认走 `bundleRelease`(不触发 `verifyReleaseResources`),所以 patch 损坏 / lib 资源问题在 bundle 路径下被静默吞掉,只有 release 路径下 `assembleRelease` 才报错。建议把 `Build` job 也改成跑 `:app:assembleRelease` 或追加一步 `:react-native-spinkit-fix-new:verifyReleaseResources :react-native-version-number-fix-new:verifyReleaseResources` 强制覆盖 | 0.85.0 | 暂用本地 `assembleRelease` 在发版前做闸口;KI-019 修复后两条线一致 | TBD | 后续把 CI 步骤合并 / 加 verifyReleaseResources 显式调用 |
1819

1920
## Closed
2021

4.58 MB
Binary file not shown.
4.59 MB
Binary file not shown.

0 commit comments

Comments
 (0)