锁定原生壳生成物忽略规则

总验收校验原生壳生成物未被追踪

总验收校验原生壳生成物仍被 gitignore 覆盖

同步宿主壳方案文档和项目决策记录
This commit is contained in:
2026-06-21 21:05:29 +08:00
parent 3dfd61f0a0
commit facbd29f06
3 changed files with 55 additions and 1 deletions
@@ -16,6 +16,14 @@
---
## 2026-06-21 原生壳生成物必须被 gitignore 覆盖
- 背景:移动壳和桌面壳验收会生成 Expo `.expo/`、Expo export smoke、Tauri `target/`、Tauri schema、自动生成权限目录和根目录 `build/native/` 分发产物;只检查这些路径未被 Git 追踪,不能防止后续误删 `.gitignore` 条目后把生成物暴露给开发者手动误加。
- 决策:`npm run check:native-shells` 必须同时用 `git ls-files` 确认原生壳生成物未被追踪,并用 `git check-ignore -v` 确认这些生成物路径仍被 `.gitignore` 覆盖。手写 capability、权限配置和壳源码仍在生产扫描范围内,不得借生成目录排除规则绕开检查。
- 影响范围:`.gitignore``scripts/check-native-shells.mjs`、Expo / Tauri 构建和分发烟测。
- 验证方式:`npm run check:native-shells``npm run check:encoding``git diff --check`
- 关联文档:`docs/【前端架构】ExpoReactNative与Tauri宿主壳方案-2026-06-17.md`
## 2026-06-21 原生壳依赖版本门禁不可移除
- 背景:Expo / React Native / Tauri 的依赖版本会影响 WebView、权限、capability、构建产物和宿主桥接行为;两端单端配置检查已经锁定 package、lockfile 和 Cargo 解析版本,但根级总验收也需要防止未来重构时把这些锁版本检查从单端脚本中移除。
@@ -554,7 +554,7 @@ GameBridge 禁止:
2026-06-19 追加:微信小程序壳路由一致性进入原生壳统一验收。`npm run check:native-shells` 会反查 `miniprogram/app.json.pages``miniprogram/host-bridge/protocol.js` 页面 URL 常量一致,H5 `src/services/host-bridge/hostBridge.ts` 的小程序登录、支付、九宫切图页面常量、H5 `src/services/wechatMiniProgramSubscribe.ts` 的订阅授权页面常量与微信协议常量一致,`miniprogram/host-bridge/webView.js` 的 WebView 分享入口和分享目标消息类型不漂移;同时会校验 `miniprogram/config.js` 的生产 / 开发 H5 入口与 API base URL 都是显式配置的纯 HTTPS 域名,`WEB_VIEW_SOURCE_QUERY` 与共享 `HOST_BRIDGE_WECHAT_MINI_PROGRAM_SOURCE_QUERY` 一致,`miniprogram/shell/webView.js` 请求头从 `WEB_VIEW_SOURCE_QUERY` 读取 `clientType` / `clientRuntime`H5 runtime parser 读取共享 `HOST_BRIDGE_RUNTIME_CONTEXT_QUERY_KEY`H5 路由保留字段读取共享 `HOST_BRIDGE_PRESERVED_RUNTIME_CONTEXT_QUERY_KEYS`。运行时对开发域名的生产域名回退只作为异常兜底,不作为配置口径;新增小程序页面、改页面路径、调整来源 query 或切换域名格式时,必须同步协议常量、H5 HostBridge / 订阅服务常量、`app.json`、共享 HostBridge query 契约和这条门禁。
2026-06-18 追加:原生壳本地生成物不作为生产源码门禁输入。Expo `.expo/`、Expo export smoke 临时目录、Tauri `target/`、Tauri schema `gen/`Tauri 自动生成权限目录都必须保持 gitignored;根级生产壳敏感词扫描只检查可提交的壳源码和配置,避免本机工具输出影响生产门禁。手写 capability / 权限配置仍需保留在扫描范围内。
2026-06-18 追加:原生壳本地生成物不作为生产源码门禁输入。Expo `.expo/`、Expo export smoke 临时目录、Tauri `target/`、Tauri schema `gen/`Tauri 自动生成权限目录和根目录 `build/native/` 都必须保持 gitignored;根级生产壳敏感词扫描只检查可提交的壳源码和配置,避免本机工具输出影响生产门禁。`npm run check:native-shells` 会同时检查这些目录没有被 Git 追踪,并用 `git check-ignore -v` 确认对应 gitignore 规则仍然生效。手写 capability / 权限配置仍需保留在扫描范围内。
2026-06-18 追加:移动壳启动页与 Android adaptive icon 复用现有真实品牌图标 `apps/mobile-shell/assets/icon.png`,背景色固定为 H5 壳根背景 `#fffdf9`。该 PNG 是 1024x1024 RGBA 透明前景品牌资产,不新增占位图;Expo `splash` 使用同一图标 `contain` 展示,Android `adaptiveIcon.foregroundImage` 使用同一透明前景图,`check-config.mjs` 会校验图标尺寸、透明像素、启动页和 adaptive icon 配置。
+46
View File
@@ -1679,6 +1679,15 @@ const generatedNativeShellArtifactPaths = [
'apps/desktop-shell/src-tauri/gen',
'apps/desktop-shell/src-tauri/permissions/autogenerated',
];
const generatedNativeShellArtifactIgnoreProbePaths = [
'build/native/probe',
'dist/probe',
'apps/mobile-shell/.expo/probe',
'apps/mobile-shell/.expo-export-smoke/probe',
'apps/desktop-shell/src-tauri/target/probe',
'apps/desktop-shell/src-tauri/gen/probe',
'apps/desktop-shell/src-tauri/permissions/autogenerated/probe',
];
const productionShellDevScaffoldTerms = [
'mo' + 'ck',
'fa' + 'ke',
@@ -1871,6 +1880,42 @@ function assertNoTrackedGeneratedNativeShellArtifacts() {
}
}
function assertGeneratedNativeShellArtifactsAreIgnored() {
const result = spawnSync(
'git',
['check-ignore', '-v', ...generatedNativeShellArtifactIgnoreProbePaths],
{
cwd: process.cwd(),
encoding: 'utf8',
},
);
if (result.error) {
throw new Error(
`unable to check generated native shell artifact gitignore rules: ${result.error.message}`,
);
}
if (result.status !== 0) {
throw new Error(
`generated native shell artifacts must be gitignored: ${result.stderr.trim() || result.stdout.trim()}`,
);
}
const ignoredArtifacts = new Set(
result.stdout
.split('\n')
.map((entry) => entry.trim().split(/\t/).pop())
.filter(Boolean),
);
const missingArtifacts = generatedNativeShellArtifactIgnoreProbePaths.filter(
(artifactPath) => !ignoredArtifacts.has(artifactPath),
);
if (missingArtifacts.length > 0) {
throw new Error(
`generated native shell artifacts missing gitignore coverage: ${missingArtifacts.join(', ')}`,
);
}
}
function collectProductionShellFiles(entryPath) {
const normalizedPath = entryPath.split(path.sep).join('/');
if (productionShellExcludedPaths.has(normalizedPath)) {
@@ -4299,6 +4344,7 @@ assertH5NativeAppTransportFacadeBoundary();
console.log('[check:native-shells] generated-native-shell-artifact-boundary');
assertNoTrackedGeneratedNativeShellArtifacts();
assertGeneratedNativeShellArtifactsAreIgnored();
console.log('[check:native-shells] production-shell-dev-scaffold-scan');
assertNoProductionShellDevScaffoldTerms();