Files
Genarrative/apps/mobile-shell/scripts/check-eas-build-config.mjs
T
kdletters c4193e27db 补齐移动壳原生包构建配置
移动壳新增 EAS Android 和 iOS 构建 profile

移动壳增加原生包构建配置 smoke 门禁

原生壳总验收接入移动 EAS 配置检查

宿主壳文档同步移动原生包构建口径
2026-06-20 06:11:53 +08:00

105 lines
3.5 KiB
JavaScript

import fs from 'node:fs';
const shellRoot = new URL('../', import.meta.url);
const easConfigPath = new URL('eas.json', shellRoot);
const packagePath = new URL('package.json', shellRoot);
const easConfig = JSON.parse(fs.readFileSync(easConfigPath, 'utf8'));
const packageConfig = JSON.parse(fs.readFileSync(packagePath, 'utf8'));
function assertObject(value, label) {
if (!value || typeof value !== 'object' || Array.isArray(value)) {
throw new Error(`${label} must be an object`);
}
}
function assertNoKeys(value, blockedKeys, label) {
for (const key of blockedKeys) {
if (key in value) {
throw new Error(`${label} must not configure ${key}`);
}
}
}
assertObject(easConfig.cli, 'EAS cli config');
assertObject(easConfig.build, 'EAS build config');
if (easConfig.cli.version !== '>= 20.3.0') {
throw new Error('mobile shell EAS CLI version gate must stay pinned to the checked devDependency floor');
}
if (easConfig.cli.appVersionSource !== 'local') {
throw new Error('mobile shell EAS builds must use local app.json version fields');
}
for (const scriptName of ['build:android', 'build:ios', 'build-config:smoke']) {
if (typeof packageConfig.scripts?.[scriptName] !== 'string') {
throw new Error(`mobile shell package missing ${scriptName} script`);
}
}
if (
packageConfig.scripts['build:android'] !==
'eas build --local --profile production --platform android'
) {
throw new Error('mobile shell Android package build script drifted');
}
if (
packageConfig.scripts['build:ios'] !==
'eas build --local --profile production-simulator --platform ios'
) {
throw new Error('mobile shell iOS package build script drifted');
}
if (packageConfig.scripts['build-config:smoke'] !== 'node scripts/check-eas-build-config.mjs') {
throw new Error('mobile shell EAS config smoke script drifted');
}
const production = easConfig.build.production;
const productionSimulator = easConfig.build['production-simulator'];
assertObject(production, 'EAS Android production profile');
assertObject(productionSimulator, 'EAS iOS simulator production profile');
if (production.distribution !== 'internal' || production.channel !== 'production') {
throw new Error('mobile shell Android production profile must build an internal production package');
}
if (production.android?.buildType !== 'apk') {
throw new Error('mobile shell Android production profile must produce an installable APK');
}
if (production.env?.EXPO_NO_DOTENV !== '1') {
throw new Error('mobile shell Android production profile must ignore local dotenv files');
}
if (
productionSimulator.distribution !== 'internal' ||
productionSimulator.channel !== 'production'
) {
throw new Error('mobile shell iOS simulator production profile must stay internal production');
}
if (productionSimulator.ios?.simulator !== true) {
throw new Error('mobile shell iOS production smoke profile must target simulator builds until signing is configured');
}
if (productionSimulator.env?.EXPO_NO_DOTENV !== '1') {
throw new Error('mobile shell iOS simulator production profile must ignore local dotenv files');
}
for (const [profileName, profile] of Object.entries(easConfig.build)) {
assertObject(profile, `EAS ${profileName} profile`);
assertNoKeys(
profile,
['credentialsSource', 'autoIncrement', 'submit', 'releaseChannel'],
`EAS ${profileName} profile`,
);
}
if ('submit' in easConfig) {
throw new Error('mobile shell EAS config must not include store submit profiles yet');
}
console.log('[mobile-shell:eas-build-config] OK');