mirror of
https://gitcode.com/github-mirrors/react-native-update-cli.git
synced 2025-09-16 01:41:37 +08:00

* add logic to support SENTRY_PROPERTIES parameter * remove update.json and meta.json files in ppk * udpapte * refactor modles * update * add package-module file * update * update readme file * modifu cli.json file * fix command issues * improve version workflow logic * udpate * update * update * update * udpate * udpate * add example * update readme file * udpate version * change logic to use pushy command uniformly
1553 lines
47 KiB
TypeScript
1553 lines
47 KiB
TypeScript
import type {
|
||
CLIProvider,
|
||
CommandContext,
|
||
CustomWorkflow,
|
||
} from '../../src/types';
|
||
|
||
/**
|
||
* 核心模块增强工作流集合
|
||
* 为app-module、bundle-module、package-module、user-module、version-module设计的高级工作流
|
||
*/
|
||
|
||
// ==================== APP MODULE WORKFLOWS ====================
|
||
|
||
/**
|
||
* 完整应用初始化工作流
|
||
*/
|
||
export const appInitializationWorkflow: CustomWorkflow = {
|
||
name: 'app-initialization',
|
||
description: '完整应用初始化流程 - 创建、配置、验证',
|
||
steps: [
|
||
{
|
||
name: 'validate-input',
|
||
description: '验证输入参数',
|
||
execute: async (context: CommandContext) => {
|
||
console.log('🔍 验证应用创建参数...');
|
||
|
||
const { name, platform, downloadUrl } = context.options;
|
||
const errors = [];
|
||
|
||
if (!name || name.trim().length === 0) {
|
||
errors.push('应用名称不能为空');
|
||
}
|
||
|
||
if (!platform || !['ios', 'android', 'harmony'].includes(platform)) {
|
||
errors.push('平台必须是 ios、android 或 harmony');
|
||
}
|
||
|
||
if (downloadUrl && !/^https?:\/\//.test(downloadUrl)) {
|
||
errors.push('下载URL格式不正确');
|
||
}
|
||
|
||
if (errors.length > 0) {
|
||
throw new Error(`参数验证失败: ${errors.join(', ')}`);
|
||
}
|
||
|
||
console.log(`✅ 参数验证通过: ${name} (${platform})`);
|
||
return { validated: true, name, platform, downloadUrl };
|
||
},
|
||
},
|
||
{
|
||
name: 'check-existing-app',
|
||
description: '检查应用是否已存在',
|
||
execute: async (context: CommandContext, previousResult: any) => {
|
||
console.log('🔍 检查应用是否已存在...');
|
||
|
||
try {
|
||
// 模拟检查逻辑 - 在实际应用中应该调用API
|
||
const { platform } = previousResult;
|
||
console.log(`检查 ${platform} 平台的应用...`);
|
||
|
||
// 模拟API调用
|
||
await new Promise((resolve) => setTimeout(resolve, 500));
|
||
|
||
const appExists = Math.random() < 0.1; // 10%概率应用已存在
|
||
|
||
if (appExists && !context.options.force) {
|
||
throw new Error('应用已存在,使用 --force 参数强制创建');
|
||
}
|
||
|
||
console.log(`✅ 应用检查完成${appExists ? ' (将覆盖现有应用)' : ''}`);
|
||
|
||
return { ...previousResult, appExists, checkCompleted: true };
|
||
} catch (error) {
|
||
console.error('❌ 应用检查失败:', error);
|
||
throw error;
|
||
}
|
||
},
|
||
},
|
||
{
|
||
name: 'create-app',
|
||
description: '创建应用',
|
||
execute: async (context: CommandContext, previousResult: any) => {
|
||
console.log('🚀 创建应用...');
|
||
|
||
const { name, platform, downloadUrl } = previousResult;
|
||
|
||
try {
|
||
// 在实际应用中,这里应该调用真实的createApp命令
|
||
console.log(`创建应用: ${name}`);
|
||
console.log(`平台: ${platform}`);
|
||
if (downloadUrl) {
|
||
console.log(`下载URL: ${downloadUrl}`);
|
||
}
|
||
|
||
// 模拟创建过程
|
||
await new Promise((resolve) => setTimeout(resolve, 1500));
|
||
|
||
const appId = `app_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
||
|
||
console.log(`✅ 应用创建成功,ID: ${appId}`);
|
||
|
||
return { ...previousResult, appId, created: true };
|
||
} catch (error) {
|
||
console.error('❌ 应用创建失败:', error);
|
||
throw error;
|
||
}
|
||
},
|
||
},
|
||
{
|
||
name: 'configure-app',
|
||
description: '配置应用基本设置',
|
||
execute: async (context: CommandContext, previousResult: any) => {
|
||
console.log('⚙️ 配置应用基本设置...');
|
||
|
||
const configurations = [
|
||
'设置更新策略',
|
||
'配置安全参数',
|
||
'初始化版本控制',
|
||
'设置通知配置',
|
||
];
|
||
|
||
for (const config of configurations) {
|
||
console.log(` - ${config}...`);
|
||
await new Promise((resolve) => setTimeout(resolve, 300));
|
||
console.log(` ✅ ${config} 完成`);
|
||
}
|
||
|
||
console.log('✅ 应用配置完成');
|
||
|
||
return { ...previousResult, configured: true };
|
||
},
|
||
},
|
||
{
|
||
name: 'select-app',
|
||
description: '选择新创建的应用',
|
||
execute: async (context: CommandContext, previousResult: any) => {
|
||
console.log('📱 选择新创建的应用...');
|
||
|
||
const { appId, platform } = previousResult;
|
||
|
||
try {
|
||
// 模拟选择应用
|
||
await new Promise((resolve) => setTimeout(resolve, 500));
|
||
|
||
console.log(`✅ 应用已选择: ${appId}`);
|
||
|
||
return { ...previousResult, selected: true };
|
||
} catch (error) {
|
||
console.error('❌ 应用选择失败:', error);
|
||
throw error;
|
||
}
|
||
},
|
||
},
|
||
{
|
||
name: 'verify-setup',
|
||
description: '验证应用设置',
|
||
execute: async (context: CommandContext, previousResult: any) => {
|
||
console.log('🔍 验证应用设置...');
|
||
|
||
const verifications = [
|
||
{ name: '应用可访问性', check: () => true },
|
||
{ name: '配置完整性', check: () => true },
|
||
{ name: '权限设置', check: () => Math.random() > 0.1 },
|
||
{ name: '网络连接', check: () => Math.random() > 0.05 },
|
||
];
|
||
|
||
const results = [];
|
||
|
||
for (const verification of verifications) {
|
||
console.log(` 检查 ${verification.name}...`);
|
||
await new Promise((resolve) => setTimeout(resolve, 200));
|
||
|
||
const passed = verification.check();
|
||
results.push({ name: verification.name, passed });
|
||
console.log(` ${passed ? '✅' : '❌'} ${verification.name}`);
|
||
}
|
||
|
||
const allPassed = results.every((r) => r.passed);
|
||
|
||
if (!allPassed) {
|
||
console.log('⚠️ 部分验证未通过,但应用仍可使用');
|
||
} else {
|
||
console.log('✅ 所有验证通过');
|
||
}
|
||
|
||
return {
|
||
...previousResult,
|
||
verified: true,
|
||
verificationResults: results,
|
||
allVerificationsPassed: allPassed,
|
||
};
|
||
},
|
||
},
|
||
],
|
||
validate: (context: CommandContext) => {
|
||
if (!context.options.name) {
|
||
console.error('❌ 应用初始化需要提供应用名称');
|
||
return false;
|
||
}
|
||
if (!context.options.platform) {
|
||
console.error('❌ 应用初始化需要指定平台');
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
options: {
|
||
name: {
|
||
hasValue: true,
|
||
description: '应用名称 (必需)',
|
||
},
|
||
platform: {
|
||
hasValue: true,
|
||
description: '目标平台 (ios/android/harmony, 必需)',
|
||
},
|
||
downloadUrl: {
|
||
hasValue: true,
|
||
description: '应用下载URL (可选)',
|
||
},
|
||
force: {
|
||
hasValue: false,
|
||
default: false,
|
||
description: '强制创建,覆盖现有应用',
|
||
},
|
||
},
|
||
};
|
||
|
||
/**
|
||
* 多平台应用管理工作流
|
||
*/
|
||
export const multiPlatformAppManagementWorkflow: CustomWorkflow = {
|
||
name: 'multi-platform-app-management',
|
||
description: '多平台应用统一管理工作流',
|
||
steps: [
|
||
{
|
||
name: 'scan-platforms',
|
||
description: '扫描所有平台的应用',
|
||
execute: async (context: CommandContext) => {
|
||
console.log('🔍 扫描所有平台的应用...');
|
||
|
||
const platforms = ['ios', 'android', 'harmony'];
|
||
const appsData = {};
|
||
|
||
for (const platform of platforms) {
|
||
console.log(` 扫描 ${platform} 平台...`);
|
||
|
||
// 模拟获取应用列表
|
||
await new Promise((resolve) => setTimeout(resolve, 500));
|
||
|
||
const appCount = Math.floor(Math.random() * 5) + 1;
|
||
const apps = Array.from({ length: appCount }, (_, i) => ({
|
||
id: `${platform}_app_${i + 1}`,
|
||
name: `App ${i + 1}`,
|
||
platform,
|
||
version: `1.${i}.0`,
|
||
status: Math.random() > 0.2 ? 'active' : 'inactive',
|
||
}));
|
||
|
||
appsData[platform] = apps;
|
||
console.log(` ✅ 找到 ${appCount} 个应用`);
|
||
}
|
||
|
||
console.log('✅ 平台扫描完成');
|
||
|
||
return { platforms, appsData, scanned: true };
|
||
},
|
||
},
|
||
{
|
||
name: 'analyze-apps',
|
||
description: '分析应用状态',
|
||
execute: async (context: CommandContext, previousResult: any) => {
|
||
console.log('📊 分析应用状态...');
|
||
|
||
const { appsData } = previousResult;
|
||
const analysis = {
|
||
totalApps: 0,
|
||
activeApps: 0,
|
||
inactiveApps: 0,
|
||
platformDistribution: {},
|
||
issues: [],
|
||
};
|
||
|
||
for (const [platform, apps] of Object.entries(appsData)) {
|
||
const platformApps = apps as any[];
|
||
analysis.totalApps += platformApps.length;
|
||
analysis.platformDistribution[platform] = platformApps.length;
|
||
|
||
for (const app of platformApps) {
|
||
if (app.status === 'active') {
|
||
analysis.activeApps++;
|
||
} else {
|
||
analysis.inactiveApps++;
|
||
analysis.issues.push(`${platform}/${app.name}: 应用不活跃`);
|
||
}
|
||
}
|
||
}
|
||
|
||
console.log('📈 分析结果:');
|
||
console.log(` 总应用数: ${analysis.totalApps}`);
|
||
console.log(` 活跃应用: ${analysis.activeApps}`);
|
||
console.log(` 非活跃应用: ${analysis.inactiveApps}`);
|
||
|
||
if (analysis.issues.length > 0) {
|
||
console.log('⚠️ 发现问题:');
|
||
analysis.issues.forEach((issue) => console.log(` - ${issue}`));
|
||
}
|
||
|
||
return { ...previousResult, analysis };
|
||
},
|
||
},
|
||
{
|
||
name: 'optimize-apps',
|
||
description: '优化应用配置',
|
||
execute: async (context: CommandContext, previousResult: any) => {
|
||
console.log('⚡ 优化应用配置...');
|
||
|
||
const { appsData, analysis } = previousResult;
|
||
const optimizations = [];
|
||
|
||
if (analysis.inactiveApps > 0) {
|
||
console.log(' 处理非活跃应用...');
|
||
optimizations.push('重新激活非活跃应用');
|
||
}
|
||
|
||
if (analysis.totalApps > 10) {
|
||
console.log(' 应用数量较多,建议分组管理...');
|
||
optimizations.push('创建应用分组');
|
||
}
|
||
|
||
// 模拟优化过程
|
||
for (const optimization of optimizations) {
|
||
console.log(` 执行: ${optimization}...`);
|
||
await new Promise((resolve) => setTimeout(resolve, 800));
|
||
console.log(` ✅ ${optimization} 完成`);
|
||
}
|
||
|
||
console.log('✅ 应用优化完成');
|
||
|
||
return { ...previousResult, optimizations, optimized: true };
|
||
},
|
||
},
|
||
],
|
||
options: {
|
||
includeInactive: {
|
||
hasValue: false,
|
||
default: true,
|
||
description: '包含非活跃应用',
|
||
},
|
||
autoOptimize: {
|
||
hasValue: false,
|
||
default: true,
|
||
description: '自动优化配置',
|
||
},
|
||
},
|
||
};
|
||
|
||
// ==================== BUNDLE MODULE WORKFLOWS ====================
|
||
|
||
/**
|
||
* 智能打包工作流
|
||
*/
|
||
export const intelligentBundleWorkflow: CustomWorkflow = {
|
||
name: 'intelligent-bundle',
|
||
description: '智能打包工作流 - 自动优化和多平台构建',
|
||
steps: [
|
||
{
|
||
name: 'environment-detection',
|
||
description: '检测构建环境',
|
||
execute: async (context: CommandContext) => {
|
||
console.log('🔍 检测构建环境...');
|
||
|
||
const environment = {
|
||
nodeVersion: process.version,
|
||
platform: process.platform,
|
||
arch: process.arch,
|
||
memory: Math.round(process.memoryUsage().heapTotal / 1024 / 1024),
|
||
cwd: process.cwd(),
|
||
};
|
||
|
||
console.log('🖥️ 环境信息:');
|
||
console.log(` Node.js: ${environment.nodeVersion}`);
|
||
console.log(` 平台: ${environment.platform}`);
|
||
console.log(` 架构: ${environment.arch}`);
|
||
console.log(` 内存: ${environment.memory}MB`);
|
||
|
||
// 检查环境兼容性
|
||
const compatibility = {
|
||
nodeVersionOk:
|
||
Number.parseFloat(environment.nodeVersion.slice(1)) >= 14,
|
||
memoryOk: environment.memory >= 512,
|
||
platformSupported: ['win32', 'darwin', 'linux'].includes(
|
||
environment.platform,
|
||
),
|
||
};
|
||
|
||
const isCompatible = Object.values(compatibility).every(Boolean);
|
||
|
||
if (!isCompatible) {
|
||
console.log('⚠️ 环境兼容性警告:');
|
||
if (!compatibility.nodeVersionOk)
|
||
console.log(' - Node.js版本过低,建议升级到14+');
|
||
if (!compatibility.memoryOk)
|
||
console.log(' - 可用内存不足,可能影响打包性能');
|
||
if (!compatibility.platformSupported) console.log(' - 平台支持有限');
|
||
} else {
|
||
console.log('✅ 环境检查通过');
|
||
}
|
||
|
||
return { environment, compatibility, isCompatible };
|
||
},
|
||
},
|
||
{
|
||
name: 'project-analysis',
|
||
description: '分析项目结构',
|
||
execute: async (context: CommandContext, previousResult: any) => {
|
||
console.log('📂 分析项目结构...');
|
||
|
||
const projectInfo = {
|
||
hasPackageJson: true, // 模拟检查
|
||
hasNodeModules: true,
|
||
hasReactNative: true,
|
||
projectType: 'react-native',
|
||
dependencies: ['react', 'react-native'],
|
||
devDependencies: ['@babel/core', 'metro'],
|
||
estimatedSize: Math.floor(Math.random() * 50) + 10, // 10-60MB
|
||
};
|
||
|
||
console.log('📋 项目信息:');
|
||
console.log(` 类型: ${projectInfo.projectType}`);
|
||
console.log(` 依赖数: ${projectInfo.dependencies.length}`);
|
||
console.log(` 预估大小: ${projectInfo.estimatedSize}MB`);
|
||
|
||
// 优化建议
|
||
const recommendations = [];
|
||
if (projectInfo.estimatedSize > 40) {
|
||
recommendations.push('启用代码分割以减小包大小');
|
||
}
|
||
if (projectInfo.dependencies.length > 50) {
|
||
recommendations.push('检查并移除未使用的依赖');
|
||
}
|
||
|
||
if (recommendations.length > 0) {
|
||
console.log('💡 优化建议:');
|
||
recommendations.forEach((rec) => console.log(` - ${rec}`));
|
||
}
|
||
|
||
return { ...previousResult, projectInfo, recommendations };
|
||
},
|
||
},
|
||
{
|
||
name: 'optimization-setup',
|
||
description: '设置优化选项',
|
||
execute: async (context: CommandContext, previousResult: any) => {
|
||
console.log('⚙️ 设置优化选项...');
|
||
|
||
const { projectInfo } = previousResult;
|
||
const { platform, dev } = context.options;
|
||
|
||
const optimizations = {
|
||
minification: !dev,
|
||
sourceMaps: dev || context.options.sourcemap,
|
||
treeshaking: !dev,
|
||
bundleSplitting: projectInfo.estimatedSize > 30,
|
||
compression: !dev,
|
||
};
|
||
|
||
console.log('🔧 优化配置:');
|
||
Object.entries(optimizations).forEach(([key, value]) => {
|
||
console.log(` ${key}: ${value ? '✅' : '❌'}`);
|
||
});
|
||
|
||
return { ...previousResult, optimizations };
|
||
},
|
||
},
|
||
{
|
||
name: 'multi-platform-build',
|
||
description: '多平台构建',
|
||
execute: async (context: CommandContext, previousResult: any) => {
|
||
console.log('🏗️ 执行多平台构建...');
|
||
|
||
const targetPlatforms = context.options.platform
|
||
? [context.options.platform]
|
||
: ['ios', 'android'];
|
||
|
||
const buildResults = [];
|
||
|
||
for (const platform of targetPlatforms) {
|
||
console.log(`\\n构建 ${platform} 平台...`);
|
||
|
||
const buildSteps = [
|
||
'准备构建环境',
|
||
'编译JavaScript',
|
||
'优化资源',
|
||
'生成Bundle',
|
||
'创建PPK文件',
|
||
];
|
||
|
||
for (const step of buildSteps) {
|
||
console.log(` ${step}...`);
|
||
await new Promise((resolve) =>
|
||
setTimeout(resolve, step.includes('编译') ? 2000 : 500),
|
||
);
|
||
console.log(` ✅ ${step} 完成`);
|
||
}
|
||
|
||
const buildResult = {
|
||
platform,
|
||
success: Math.random() > 0.1, // 90% 成功率
|
||
buildTime: Math.floor(Math.random() * 30) + 10, // 10-40秒
|
||
bundleSize: Math.floor(Math.random() * 10) + 5, // 5-15MB
|
||
outputPath: `./build/${platform}.ppk`,
|
||
};
|
||
|
||
buildResults.push(buildResult);
|
||
|
||
if (buildResult.success) {
|
||
console.log(`✅ ${platform} 构建成功`);
|
||
console.log(` 时间: ${buildResult.buildTime}秒`);
|
||
console.log(` 大小: ${buildResult.bundleSize}MB`);
|
||
} else {
|
||
console.log(`❌ ${platform} 构建失败`);
|
||
}
|
||
}
|
||
|
||
const allSuccess = buildResults.every((r) => r.success);
|
||
|
||
console.log(
|
||
`\\n🎯 构建汇总: ${buildResults.filter((r) => r.success).length}/${buildResults.length} 成功`,
|
||
);
|
||
|
||
return { ...previousResult, buildResults, allSuccess };
|
||
},
|
||
},
|
||
{
|
||
name: 'quality-check',
|
||
description: '质量检查',
|
||
execute: async (context: CommandContext, previousResult: any) => {
|
||
console.log('🔍 执行质量检查...');
|
||
|
||
const { buildResults } = previousResult;
|
||
const qualityChecks = [];
|
||
|
||
for (const build of buildResults) {
|
||
if (!build.success) continue;
|
||
|
||
console.log(`检查 ${build.platform} 构建质量...`);
|
||
|
||
const checks = {
|
||
bundleSize: build.bundleSize < 20, // 小于20MB
|
||
buildTime: build.buildTime < 60, // 小于60秒
|
||
hasSourceMap: Math.random() > 0.1,
|
||
hasAssets: Math.random() > 0.05,
|
||
};
|
||
|
||
const score =
|
||
(Object.values(checks).filter(Boolean).length /
|
||
Object.keys(checks).length) *
|
||
100;
|
||
|
||
qualityChecks.push({
|
||
platform: build.platform,
|
||
checks,
|
||
score: Math.round(score),
|
||
passed: score >= 80,
|
||
});
|
||
|
||
console.log(` 质量评分: ${Math.round(score)}%`);
|
||
}
|
||
|
||
const averageScore =
|
||
qualityChecks.reduce((sum, check) => sum + check.score, 0) /
|
||
qualityChecks.length;
|
||
|
||
console.log(`\\n📊 平均质量评分: ${Math.round(averageScore)}%`);
|
||
|
||
return { ...previousResult, qualityChecks, averageScore };
|
||
},
|
||
},
|
||
],
|
||
validate: (context: CommandContext) => {
|
||
return true; // 智能打包工作流不需要特殊验证
|
||
},
|
||
options: {
|
||
platform: {
|
||
hasValue: true,
|
||
description: '目标平台 (不指定则构建所有平台)',
|
||
},
|
||
dev: {
|
||
hasValue: false,
|
||
default: false,
|
||
description: '开发模式构建',
|
||
},
|
||
sourcemap: {
|
||
hasValue: false,
|
||
default: false,
|
||
description: '生成源码映射',
|
||
},
|
||
optimize: {
|
||
hasValue: false,
|
||
default: true,
|
||
description: '启用自动优化',
|
||
},
|
||
},
|
||
};
|
||
|
||
/**
|
||
* 增量构建工作流
|
||
*/
|
||
export const incrementalBuildWorkflow: CustomWorkflow = {
|
||
name: 'incremental-build',
|
||
description: '增量构建工作流 - 生成差异包',
|
||
steps: [
|
||
{
|
||
name: 'detect-base-version',
|
||
description: '检测基准版本',
|
||
execute: async (context: CommandContext) => {
|
||
console.log('🔍 检测基准版本...');
|
||
|
||
const { baseVersion, platform } = context.options;
|
||
|
||
if (baseVersion) {
|
||
console.log(`✅ 使用指定基准版本: ${baseVersion}`);
|
||
return { baseVersion, specified: true };
|
||
}
|
||
|
||
// 自动检测最新版本
|
||
console.log('自动检测最新版本...');
|
||
await new Promise((resolve) => setTimeout(resolve, 800));
|
||
|
||
const autoDetectedVersion = `v${Math.floor(Math.random() * 3) + 1}.${Math.floor(Math.random() * 10)}.${Math.floor(Math.random() * 10)}`;
|
||
|
||
console.log(`✅ 自动检测到基准版本: ${autoDetectedVersion}`);
|
||
|
||
return { baseVersion: autoDetectedVersion, specified: false };
|
||
},
|
||
},
|
||
{
|
||
name: 'build-current-version',
|
||
description: '构建当前版本',
|
||
execute: async (context: CommandContext, previousResult: any) => {
|
||
console.log('🏗️ 构建当前版本...');
|
||
|
||
const { platform } = context.options;
|
||
|
||
console.log(`构建 ${platform} 平台...`);
|
||
|
||
// 模拟构建过程
|
||
const buildSteps = ['编译代码', '打包资源', '生成Bundle'];
|
||
|
||
for (const step of buildSteps) {
|
||
console.log(` ${step}...`);
|
||
await new Promise((resolve) => setTimeout(resolve, 1000));
|
||
console.log(` ✅ ${step} 完成`);
|
||
}
|
||
|
||
const currentBuild = {
|
||
version: `v${Math.floor(Math.random() * 3) + 2}.0.0`,
|
||
platform,
|
||
bundlePath: `./build/current_${platform}.ppk`,
|
||
size: Math.floor(Math.random() * 15) + 10,
|
||
buildTime: Date.now(),
|
||
};
|
||
|
||
console.log(`✅ 当前版本构建完成: ${currentBuild.version}`);
|
||
|
||
return { ...previousResult, currentBuild };
|
||
},
|
||
},
|
||
{
|
||
name: 'download-base-bundle',
|
||
description: '下载基准版本Bundle',
|
||
execute: async (context: CommandContext, previousResult: any) => {
|
||
console.log('📥 下载基准版本Bundle...');
|
||
|
||
const { baseVersion } = previousResult;
|
||
const { platform } = context.options;
|
||
|
||
console.log(`下载 ${baseVersion} (${platform})...`);
|
||
|
||
// 模拟下载过程
|
||
for (let i = 0; i <= 100; i += 20) {
|
||
console.log(` 下载进度: ${i}%`);
|
||
await new Promise((resolve) => setTimeout(resolve, 200));
|
||
}
|
||
|
||
const baseBuild = {
|
||
version: baseVersion,
|
||
platform,
|
||
bundlePath: `./build/base_${platform}.ppk`,
|
||
size: Math.floor(Math.random() * 12) + 8,
|
||
};
|
||
|
||
console.log(`✅ 基准版本下载完成`);
|
||
|
||
return { ...previousResult, baseBuild };
|
||
},
|
||
},
|
||
{
|
||
name: 'generate-diff',
|
||
description: '生成差异包',
|
||
execute: async (context: CommandContext, previousResult: any) => {
|
||
console.log('🔄 生成差异包...');
|
||
|
||
const { baseBuild, currentBuild } = previousResult;
|
||
|
||
console.log(
|
||
`比较版本: ${baseBuild.version} -> ${currentBuild.version}`,
|
||
);
|
||
|
||
// 模拟差异计算
|
||
const diffSteps = [
|
||
'分析文件变更',
|
||
'计算差异算法',
|
||
'生成补丁文件',
|
||
'压缩差异包',
|
||
];
|
||
|
||
for (const step of diffSteps) {
|
||
console.log(` ${step}...`);
|
||
await new Promise((resolve) => setTimeout(resolve, 800));
|
||
console.log(` ✅ ${step} 完成`);
|
||
}
|
||
|
||
const diffPackage = {
|
||
fromVersion: baseBuild.version,
|
||
toVersion: currentBuild.version,
|
||
diffPath: `./build/diff_${baseBuild.version}_to_${currentBuild.version}.patch`,
|
||
originalSize: currentBuild.size,
|
||
diffSize: Math.floor(currentBuild.size * (0.1 + Math.random() * 0.3)), // 10-40% 大小
|
||
compressionRatio: 0,
|
||
};
|
||
|
||
diffPackage.compressionRatio = Math.round(
|
||
(1 - diffPackage.diffSize / diffPackage.originalSize) * 100,
|
||
);
|
||
|
||
console.log(`✅ 差异包生成完成`);
|
||
console.log(` 原始大小: ${diffPackage.originalSize}MB`);
|
||
console.log(` 差异包大小: ${diffPackage.diffSize}MB`);
|
||
console.log(` 压缩比: ${diffPackage.compressionRatio}%`);
|
||
|
||
return { ...previousResult, diffPackage };
|
||
},
|
||
},
|
||
{
|
||
name: 'validate-diff',
|
||
description: '验证差异包',
|
||
execute: async (context: CommandContext, previousResult: any) => {
|
||
console.log('🔍 验证差异包...');
|
||
|
||
const { diffPackage } = previousResult;
|
||
|
||
const validationSteps = [
|
||
'校验文件完整性',
|
||
'测试应用补丁',
|
||
'验证功能完整性',
|
||
];
|
||
|
||
const validationResults = [];
|
||
|
||
for (const step of validationSteps) {
|
||
console.log(` ${step}...`);
|
||
await new Promise((resolve) => setTimeout(resolve, 600));
|
||
|
||
const success = Math.random() > 0.05; // 95% 成功率
|
||
validationResults.push({ step, success });
|
||
|
||
console.log(` ${success ? '✅' : '❌'} ${step}`);
|
||
}
|
||
|
||
const allValid = validationResults.every((r) => r.success);
|
||
|
||
if (allValid) {
|
||
console.log('✅ 差异包验证通过');
|
||
} else {
|
||
console.log('❌ 差异包验证失败');
|
||
}
|
||
|
||
return {
|
||
...previousResult,
|
||
validationResults,
|
||
allValid,
|
||
validated: true,
|
||
};
|
||
},
|
||
},
|
||
],
|
||
validate: (context: CommandContext) => {
|
||
if (!context.options.platform) {
|
||
console.error('❌ 增量构建需要指定平台');
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
options: {
|
||
platform: {
|
||
hasValue: true,
|
||
description: '目标平台 (必需)',
|
||
},
|
||
baseVersion: {
|
||
hasValue: true,
|
||
description: '基准版本 (不指定则自动检测)',
|
||
},
|
||
skipValidation: {
|
||
hasValue: false,
|
||
default: false,
|
||
description: '跳过差异包验证',
|
||
},
|
||
},
|
||
};
|
||
|
||
// ==================== PACKAGE MODULE WORKFLOWS ====================
|
||
|
||
/**
|
||
* 批量包处理工作流
|
||
*/
|
||
export const batchPackageProcessingWorkflow: CustomWorkflow = {
|
||
name: 'batch-package-processing',
|
||
description: '批量包处理工作流 - 上传、解析、验证',
|
||
steps: [
|
||
{
|
||
name: 'scan-packages',
|
||
description: '扫描待处理包',
|
||
execute: async (context: CommandContext) => {
|
||
console.log('🔍 扫描待处理包...');
|
||
|
||
const { directory, pattern } = context.options;
|
||
const scanDir = directory || './packages';
|
||
|
||
console.log(`扫描目录: ${scanDir}`);
|
||
console.log(`文件模式: ${pattern || '*.{ipa,apk,app}'}`);
|
||
|
||
// 模拟文件扫描
|
||
await new Promise((resolve) => setTimeout(resolve, 1000));
|
||
|
||
const packages = [
|
||
{
|
||
path: './packages/app_v1.0.0.ipa',
|
||
type: 'ipa',
|
||
size: 45.2,
|
||
platform: 'ios',
|
||
},
|
||
{
|
||
path: './packages/app_v1.0.0.apk',
|
||
type: 'apk',
|
||
size: 38.7,
|
||
platform: 'android',
|
||
},
|
||
{
|
||
path: './packages/app_v1.0.0.app',
|
||
type: 'app',
|
||
size: 42.1,
|
||
platform: 'harmony',
|
||
},
|
||
{
|
||
path: './packages/app_v1.1.0.ipa',
|
||
type: 'ipa',
|
||
size: 46.8,
|
||
platform: 'ios',
|
||
},
|
||
{
|
||
path: './packages/app_v1.1.0.apk',
|
||
type: 'apk',
|
||
size: 39.2,
|
||
platform: 'android',
|
||
},
|
||
];
|
||
|
||
console.log(`✅ 发现 ${packages.length} 个包文件:`);
|
||
packages.forEach((pkg) => {
|
||
console.log(` ${pkg.path} (${pkg.size}MB, ${pkg.platform})`);
|
||
});
|
||
|
||
return { packages, scanned: true };
|
||
},
|
||
},
|
||
{
|
||
name: 'analyze-packages',
|
||
description: '分析包信息',
|
||
execute: async (context: CommandContext, previousResult: any) => {
|
||
console.log('📊 分析包信息...');
|
||
|
||
const { packages } = previousResult;
|
||
const analysis = {
|
||
totalPackages: packages.length,
|
||
totalSize: 0,
|
||
platformDistribution: {},
|
||
versions: new Set(),
|
||
issues: [],
|
||
};
|
||
|
||
for (const pkg of packages) {
|
||
analysis.totalSize += pkg.size;
|
||
|
||
if (!analysis.platformDistribution[pkg.platform]) {
|
||
analysis.platformDistribution[pkg.platform] = 0;
|
||
}
|
||
analysis.platformDistribution[pkg.platform]++;
|
||
|
||
// 提取版本信息
|
||
const versionMatch = pkg.path.match(/v(\d+\.\d+\.\d+)/);
|
||
if (versionMatch) {
|
||
analysis.versions.add(versionMatch[1]);
|
||
}
|
||
|
||
// 检查问题
|
||
if (pkg.size > 50) {
|
||
analysis.issues.push(`${pkg.path}: 包大小过大 (${pkg.size}MB)`);
|
||
}
|
||
if (pkg.size < 1) {
|
||
analysis.issues.push(`${pkg.path}: 包大小异常小`);
|
||
}
|
||
}
|
||
|
||
console.log('📈 分析结果:');
|
||
console.log(` 总包数: ${analysis.totalPackages}`);
|
||
console.log(` 总大小: ${analysis.totalSize.toFixed(1)}MB`);
|
||
console.log(` 版本数: ${analysis.versions.size}`);
|
||
console.log(' 平台分布:');
|
||
Object.entries(analysis.platformDistribution).forEach(
|
||
([platform, count]) => {
|
||
console.log(` ${platform}: ${count} 个`);
|
||
},
|
||
);
|
||
|
||
if (analysis.issues.length > 0) {
|
||
console.log('⚠️ 发现问题:');
|
||
analysis.issues.forEach((issue) => console.log(` - ${issue}`));
|
||
}
|
||
|
||
return { ...previousResult, analysis };
|
||
},
|
||
},
|
||
{
|
||
name: 'parse-packages',
|
||
description: '解析包内容',
|
||
execute: async (context: CommandContext, previousResult: any) => {
|
||
console.log('🔍 解析包内容...');
|
||
|
||
const { packages } = previousResult;
|
||
const parseResults = [];
|
||
|
||
for (const pkg of packages) {
|
||
console.log(`\\n解析 ${pkg.path}...`);
|
||
|
||
// 模拟解析过程
|
||
await new Promise((resolve) => setTimeout(resolve, 800));
|
||
|
||
const parseResult = {
|
||
path: pkg.path,
|
||
platform: pkg.platform,
|
||
appInfo: {
|
||
bundleId: `com.example.app.${pkg.platform}`,
|
||
version: `1.${Math.floor(Math.random() * 3)}.0`,
|
||
buildNumber: Math.floor(Math.random() * 100) + 1,
|
||
minOSVersion: pkg.platform === 'ios' ? '11.0' : '6.0',
|
||
permissions: ['camera', 'location', 'storage'].slice(
|
||
0,
|
||
Math.floor(Math.random() * 3) + 1,
|
||
),
|
||
},
|
||
assets: {
|
||
icons: Math.floor(Math.random() * 5) + 3,
|
||
images: Math.floor(Math.random() * 20) + 10,
|
||
fonts: Math.floor(Math.random() * 3) + 1,
|
||
},
|
||
success: Math.random() > 0.05, // 95% 成功率
|
||
};
|
||
|
||
parseResults.push(parseResult);
|
||
|
||
if (parseResult.success) {
|
||
console.log(` ✅ 解析成功`);
|
||
console.log(` Bundle ID: ${parseResult.appInfo.bundleId}`);
|
||
console.log(
|
||
` 版本: ${parseResult.appInfo.version} (${parseResult.appInfo.buildNumber})`,
|
||
);
|
||
} else {
|
||
console.log(` ❌ 解析失败`);
|
||
}
|
||
}
|
||
|
||
const successCount = parseResults.filter((r) => r.success).length;
|
||
console.log(
|
||
`\\n📊 解析汇总: ${successCount}/${parseResults.length} 成功`,
|
||
);
|
||
|
||
return { ...previousResult, parseResults };
|
||
},
|
||
},
|
||
{
|
||
name: 'upload-packages',
|
||
description: '上传包文件',
|
||
execute: async (context: CommandContext, previousResult: any) => {
|
||
console.log('📤 上传包文件...');
|
||
|
||
const { packages, parseResults } = previousResult;
|
||
const uploadResults = [];
|
||
|
||
const successfulParsed = parseResults.filter((r) => r.success);
|
||
|
||
for (const parseResult of successfulParsed) {
|
||
console.log(`\\n上传 ${parseResult.path}...`);
|
||
|
||
// 模拟上传进度
|
||
const progressSteps = [20, 40, 60, 80, 100];
|
||
for (const progress of progressSteps) {
|
||
console.log(` 上传进度: ${progress}%`);
|
||
await new Promise((resolve) => setTimeout(resolve, 300));
|
||
}
|
||
|
||
const uploadResult = {
|
||
path: parseResult.path,
|
||
platform: parseResult.platform,
|
||
success: Math.random() > 0.1, // 90% 成功率
|
||
uploadTime: Math.floor(Math.random() * 30) + 10, // 10-40秒
|
||
packageId: Math.random().toString(36).substr(2, 8),
|
||
};
|
||
|
||
uploadResults.push(uploadResult);
|
||
|
||
if (uploadResult.success) {
|
||
console.log(` ✅ 上传成功,包ID: ${uploadResult.packageId}`);
|
||
} else {
|
||
console.log(` ❌ 上传失败`);
|
||
}
|
||
}
|
||
|
||
const uploadSuccessCount = uploadResults.filter(
|
||
(r) => r.success,
|
||
).length;
|
||
console.log(
|
||
`\\n📊 上传汇总: ${uploadSuccessCount}/${uploadResults.length} 成功`,
|
||
);
|
||
|
||
return { ...previousResult, uploadResults };
|
||
},
|
||
},
|
||
{
|
||
name: 'generate-report',
|
||
description: '生成处理报告',
|
||
execute: async (context: CommandContext, previousResult: any) => {
|
||
console.log('📋 生成处理报告...');
|
||
|
||
const { packages, analysis, parseResults, uploadResults } =
|
||
previousResult;
|
||
|
||
const report = {
|
||
summary: {
|
||
totalPackages: packages.length,
|
||
parsedSuccessfully: parseResults.filter((r) => r.success).length,
|
||
uploadedSuccessfully: uploadResults.filter((r) => r.success).length,
|
||
totalSize: analysis.totalSize,
|
||
processingTime: Date.now(),
|
||
},
|
||
platformBreakdown: analysis.platformDistribution,
|
||
issues: analysis.issues,
|
||
failedOperations: [
|
||
...parseResults
|
||
.filter((r) => !r.success)
|
||
.map((r) => ({ operation: 'parse', file: r.path })),
|
||
...uploadResults
|
||
.filter((r) => !r.success)
|
||
.map((r) => ({ operation: 'upload', file: r.path })),
|
||
],
|
||
};
|
||
|
||
console.log('\\n📊 处理报告:');
|
||
console.log('='.repeat(50));
|
||
console.log(`总包数: ${report.summary.totalPackages}`);
|
||
console.log(`解析成功: ${report.summary.parsedSuccessfully}`);
|
||
console.log(`上传成功: ${report.summary.uploadedSuccessfully}`);
|
||
console.log(`总大小: ${report.summary.totalSize.toFixed(1)}MB`);
|
||
|
||
if (report.failedOperations.length > 0) {
|
||
console.log('\\n❌ 失败操作:');
|
||
report.failedOperations.forEach((op) => {
|
||
console.log(` ${op.operation}: ${op.file}`);
|
||
});
|
||
}
|
||
|
||
console.log('='.repeat(50));
|
||
|
||
return { ...previousResult, report };
|
||
},
|
||
},
|
||
],
|
||
options: {
|
||
directory: {
|
||
hasValue: true,
|
||
description: '包文件目录 (默认: ./packages)',
|
||
},
|
||
pattern: {
|
||
hasValue: true,
|
||
description: '文件匹配模式 (默认: *.{ipa,apk,app})',
|
||
},
|
||
skipUpload: {
|
||
hasValue: false,
|
||
default: false,
|
||
description: '跳过上传步骤',
|
||
},
|
||
},
|
||
};
|
||
|
||
// ==================== VERSION MODULE WORKFLOWS ====================
|
||
|
||
/**
|
||
* 版本发布管理工作流
|
||
*/
|
||
export const versionReleaseManagementWorkflow: CustomWorkflow = {
|
||
name: 'version-release-management',
|
||
description: '版本发布管理工作流 - 完整的版本发布生命周期',
|
||
steps: [
|
||
{
|
||
name: 'pre-release-check',
|
||
description: '发布前检查',
|
||
execute: async (context: CommandContext) => {
|
||
console.log('🔍 执行发布前检查...');
|
||
|
||
const { name, platform } = context.options;
|
||
|
||
const checks = [
|
||
{ name: '版本号格式', check: () => /^v?\d+\.\d+\.\d+/.test(name) },
|
||
{
|
||
name: '平台支持',
|
||
check: () => ['ios', 'android', 'harmony'].includes(platform),
|
||
},
|
||
{ name: '构建环境', check: () => Math.random() > 0.1 },
|
||
{ name: '依赖完整性', check: () => Math.random() > 0.05 },
|
||
{ name: '测试覆盖率', check: () => Math.random() > 0.2 },
|
||
];
|
||
|
||
const results = [];
|
||
|
||
for (const check of checks) {
|
||
console.log(` 检查 ${check.name}...`);
|
||
await new Promise((resolve) => setTimeout(resolve, 300));
|
||
|
||
const passed = check.check();
|
||
results.push({ name: check.name, passed });
|
||
|
||
console.log(` ${passed ? '✅' : '❌'} ${check.name}`);
|
||
}
|
||
|
||
const criticalIssues = results.filter(
|
||
(r) => !r.passed && ['版本号格式', '平台支持'].includes(r.name),
|
||
);
|
||
const warnings = results.filter(
|
||
(r) => !r.passed && !['版本号格式', '平台支持'].includes(r.name),
|
||
);
|
||
|
||
if (criticalIssues.length > 0) {
|
||
throw new Error(
|
||
`关键检查失败: ${criticalIssues.map((i) => i.name).join(', ')}`,
|
||
);
|
||
}
|
||
|
||
if (warnings.length > 0) {
|
||
console.log(`⚠️ 警告: ${warnings.map((w) => w.name).join(', ')}`);
|
||
}
|
||
|
||
console.log('✅ 发布前检查完成');
|
||
|
||
return { checks: results, criticalIssues, warnings };
|
||
},
|
||
},
|
||
{
|
||
name: 'version-validation',
|
||
description: '版本验证',
|
||
execute: async (context: CommandContext, previousResult: any) => {
|
||
console.log('🔍 验证版本信息...');
|
||
|
||
const { name, description, platform } = context.options;
|
||
|
||
// 检查版本是否已存在
|
||
console.log('检查版本冲突...');
|
||
await new Promise((resolve) => setTimeout(resolve, 800));
|
||
|
||
const versionExists = Math.random() < 0.1; // 10% 概率版本已存在
|
||
|
||
if (versionExists && !context.options.force) {
|
||
throw new Error(`版本 ${name} 已存在,使用 --force 参数强制覆盖`);
|
||
}
|
||
|
||
// 验证版本规范
|
||
const versionInfo = {
|
||
name,
|
||
description: description || `Release ${name}`,
|
||
platform,
|
||
timestamp: new Date().toISOString(),
|
||
isPreRelease: name.includes('beta') || name.includes('alpha'),
|
||
isMajorRelease: name.endsWith('.0.0'),
|
||
};
|
||
|
||
console.log('📋 版本信息:');
|
||
console.log(` 名称: ${versionInfo.name}`);
|
||
console.log(` 描述: ${versionInfo.description}`);
|
||
console.log(` 平台: ${versionInfo.platform}`);
|
||
console.log(` 预发布: ${versionInfo.isPreRelease ? '是' : '否'}`);
|
||
console.log(` 主要版本: ${versionInfo.isMajorRelease ? '是' : '否'}`);
|
||
|
||
if (versionExists) {
|
||
console.log('⚠️ 将覆盖现有版本');
|
||
}
|
||
|
||
console.log('✅ 版本验证完成');
|
||
|
||
return { ...previousResult, versionInfo, versionExists };
|
||
},
|
||
},
|
||
{
|
||
name: 'release-preparation',
|
||
description: '准备发布',
|
||
execute: async (context: CommandContext, previousResult: any) => {
|
||
console.log('⚙️ 准备发布...');
|
||
|
||
const { versionInfo } = previousResult;
|
||
|
||
const preparationSteps = [
|
||
'生成发布说明',
|
||
'准备分发包',
|
||
'设置发布参数',
|
||
'配置回滚策略',
|
||
];
|
||
|
||
for (const step of preparationSteps) {
|
||
console.log(` ${step}...`);
|
||
await new Promise((resolve) => setTimeout(resolve, 600));
|
||
console.log(` ✅ ${step} 完成`);
|
||
}
|
||
|
||
const releaseConfig = {
|
||
rollout: Number.parseInt(context.options.rollout) || 100,
|
||
packageVersion: context.options.packageVersion,
|
||
minPackageVersion: context.options.minPackageVersion,
|
||
maxPackageVersion: context.options.maxPackageVersion,
|
||
metaInfo: context.options.metaInfo,
|
||
dryRun: context.options.dryRun,
|
||
};
|
||
|
||
console.log('🔧 发布配置:');
|
||
Object.entries(releaseConfig).forEach(([key, value]) => {
|
||
if (value !== undefined) {
|
||
console.log(` ${key}: ${value}`);
|
||
}
|
||
});
|
||
|
||
console.log('✅ 发布准备完成');
|
||
|
||
return { ...previousResult, releaseConfig };
|
||
},
|
||
},
|
||
{
|
||
name: 'execute-release',
|
||
description: '执行发布',
|
||
execute: async (context: CommandContext, previousResult: any) => {
|
||
console.log('🚀 执行版本发布...');
|
||
|
||
const { versionInfo, releaseConfig } = previousResult;
|
||
|
||
if (releaseConfig.dryRun) {
|
||
console.log('🔍 模拟发布 (Dry Run)...');
|
||
|
||
console.log('模拟操作:');
|
||
console.log(' - 上传版本包');
|
||
console.log(' - 更新版本信息');
|
||
console.log(' - 配置分发策略');
|
||
console.log(' - 通知用户');
|
||
|
||
await new Promise((resolve) => setTimeout(resolve, 2000));
|
||
|
||
console.log('✅ 模拟发布完成 (未实际发布)');
|
||
|
||
return {
|
||
...previousResult,
|
||
released: false,
|
||
dryRun: true,
|
||
simulationSuccessful: true,
|
||
};
|
||
}
|
||
|
||
// 实际发布流程
|
||
const releaseSteps = [
|
||
{ name: '上传版本包', duration: 3000 },
|
||
{ name: '更新版本信息', duration: 1000 },
|
||
{ name: '配置分发策略', duration: 800 },
|
||
{ name: '激活版本', duration: 500 },
|
||
{ name: '发送通知', duration: 600 },
|
||
];
|
||
|
||
const releaseResults = [];
|
||
|
||
for (const step of releaseSteps) {
|
||
console.log(` ${step.name}...`);
|
||
|
||
// 模拟进度
|
||
if (step.duration > 2000) {
|
||
for (let i = 20; i <= 100; i += 20) {
|
||
console.log(` 进度: ${i}%`);
|
||
await new Promise((resolve) =>
|
||
setTimeout(resolve, step.duration / 5),
|
||
);
|
||
}
|
||
} else {
|
||
await new Promise((resolve) => setTimeout(resolve, step.duration));
|
||
}
|
||
|
||
const success = Math.random() > 0.02; // 98% 成功率
|
||
releaseResults.push({ step: step.name, success });
|
||
|
||
if (success) {
|
||
console.log(` ✅ ${step.name} 完成`);
|
||
} else {
|
||
console.log(` ❌ ${step.name} 失败`);
|
||
throw new Error(`发布失败于步骤: ${step.name}`);
|
||
}
|
||
}
|
||
|
||
const releaseId = Math.random().toString(36).substr(2, 10);
|
||
|
||
console.log(`✅ 版本发布成功`);
|
||
console.log(` 发布ID: ${releaseId}`);
|
||
console.log(` 版本: ${versionInfo.name}`);
|
||
console.log(` 覆盖率: ${releaseConfig.rollout}%`);
|
||
|
||
return {
|
||
...previousResult,
|
||
released: true,
|
||
releaseId,
|
||
releaseResults,
|
||
releaseTime: new Date().toISOString(),
|
||
};
|
||
},
|
||
},
|
||
{
|
||
name: 'post-release-monitoring',
|
||
description: '发布后监控',
|
||
execute: async (context: CommandContext, previousResult: any) => {
|
||
if (!previousResult.released) {
|
||
console.log('跳过发布后监控 (未实际发布)');
|
||
return { ...previousResult, monitoringSkipped: true };
|
||
}
|
||
|
||
console.log('📊 发布后监控...');
|
||
|
||
const { releaseId, versionInfo } = previousResult;
|
||
|
||
console.log(`监控发布 ${releaseId}...`);
|
||
|
||
const monitoringMetrics = [
|
||
{
|
||
name: '下载成功率',
|
||
value: 95 + Math.random() * 4,
|
||
unit: '%',
|
||
threshold: 90,
|
||
},
|
||
{
|
||
name: '安装成功率',
|
||
value: 92 + Math.random() * 6,
|
||
unit: '%',
|
||
threshold: 85,
|
||
},
|
||
{
|
||
name: '启动成功率',
|
||
value: 96 + Math.random() * 3,
|
||
unit: '%',
|
||
threshold: 95,
|
||
},
|
||
{
|
||
name: '崩溃率',
|
||
value: Math.random() * 1,
|
||
unit: '%',
|
||
threshold: 2,
|
||
inverse: true,
|
||
},
|
||
{
|
||
name: '用户反馈评分',
|
||
value: 4.2 + Math.random() * 0.7,
|
||
unit: '/5',
|
||
threshold: 4.0,
|
||
},
|
||
];
|
||
|
||
console.log('📈 监控指标:');
|
||
|
||
const alerts = [];
|
||
|
||
for (const metric of monitoringMetrics) {
|
||
const value = Number.parseFloat(metric.value.toFixed(2));
|
||
const passed = metric.inverse
|
||
? value <= metric.threshold
|
||
: value >= metric.threshold;
|
||
|
||
console.log(
|
||
` ${metric.name}: ${value}${metric.unit} ${passed ? '✅' : '⚠️'}`,
|
||
);
|
||
|
||
if (!passed) {
|
||
alerts.push(
|
||
`${metric.name} 低于阈值 (${value}${metric.unit} < ${metric.threshold}${metric.unit})`,
|
||
);
|
||
}
|
||
}
|
||
|
||
if (alerts.length > 0) {
|
||
console.log('\\n⚠️ 监控警告:');
|
||
alerts.forEach((alert) => console.log(` - ${alert}`));
|
||
} else {
|
||
console.log('\\n✅ 所有监控指标正常');
|
||
}
|
||
|
||
console.log('✅ 发布后监控完成');
|
||
|
||
return {
|
||
...previousResult,
|
||
monitoring: {
|
||
metrics: monitoringMetrics,
|
||
alerts,
|
||
allMetricsHealthy: alerts.length === 0,
|
||
},
|
||
};
|
||
},
|
||
},
|
||
{
|
||
name: 'release-summary',
|
||
description: '发布总结',
|
||
execute: async (context: CommandContext, previousResult: any) => {
|
||
console.log('📋 生成发布总结...');
|
||
|
||
const {
|
||
versionInfo,
|
||
releaseConfig,
|
||
released,
|
||
dryRun,
|
||
releaseId,
|
||
monitoring,
|
||
} = previousResult;
|
||
|
||
console.log('\\n' + '='.repeat(60));
|
||
console.log('📊 版本发布总结');
|
||
console.log('='.repeat(60));
|
||
|
||
console.log(`版本名称: ${versionInfo.name}`);
|
||
console.log(`平台: ${versionInfo.platform}`);
|
||
console.log(`发布时间: ${versionInfo.timestamp}`);
|
||
console.log(`覆盖率: ${releaseConfig.rollout}%`);
|
||
|
||
if (dryRun) {
|
||
console.log('状态: 模拟发布 ✅');
|
||
} else if (released) {
|
||
console.log(`状态: 发布成功 ✅`);
|
||
console.log(`发布ID: ${releaseId}`);
|
||
|
||
if (monitoring && !monitoring.allMetricsHealthy) {
|
||
console.log(`监控状态: 有警告 ⚠️`);
|
||
} else if (monitoring) {
|
||
console.log(`监控状态: 正常 ✅`);
|
||
}
|
||
} else {
|
||
console.log('状态: 发布失败 ❌');
|
||
}
|
||
|
||
console.log('='.repeat(60));
|
||
|
||
const summary = {
|
||
version: versionInfo.name,
|
||
platform: versionInfo.platform,
|
||
success: released || dryRun,
|
||
releaseId: releaseId || null,
|
||
monitoringHealthy: monitoring?.allMetricsHealthy ?? true,
|
||
completedAt: new Date().toISOString(),
|
||
};
|
||
|
||
return { ...previousResult, summary };
|
||
},
|
||
},
|
||
],
|
||
validate: (context: CommandContext) => {
|
||
if (!context.options.name) {
|
||
console.error('❌ 版本发布需要指定版本名称');
|
||
return false;
|
||
}
|
||
if (!context.options.platform) {
|
||
console.error('❌ 版本发布需要指定平台');
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
options: {
|
||
name: {
|
||
hasValue: true,
|
||
description: '版本名称 (必需)',
|
||
},
|
||
description: {
|
||
hasValue: true,
|
||
description: '版本描述',
|
||
},
|
||
platform: {
|
||
hasValue: true,
|
||
description: '目标平台 (必需)',
|
||
},
|
||
rollout: {
|
||
hasValue: true,
|
||
default: 100,
|
||
description: '发布覆盖率百分比',
|
||
},
|
||
packageVersion: {
|
||
hasValue: true,
|
||
description: '包版本号',
|
||
},
|
||
minPackageVersion: {
|
||
hasValue: true,
|
||
description: '最小包版本',
|
||
},
|
||
maxPackageVersion: {
|
||
hasValue: true,
|
||
description: '最大包版本',
|
||
},
|
||
metaInfo: {
|
||
hasValue: true,
|
||
description: '元信息',
|
||
},
|
||
dryRun: {
|
||
hasValue: false,
|
||
default: false,
|
||
description: '模拟发布,不实际执行',
|
||
},
|
||
force: {
|
||
hasValue: false,
|
||
default: false,
|
||
description: '强制发布,覆盖现有版本',
|
||
},
|
||
},
|
||
};
|
||
|
||
/**
|
||
* 导出所有增强的核心工作流
|
||
*/
|
||
export const enhancedCoreWorkflows = [
|
||
// App Module Workflows
|
||
appInitializationWorkflow,
|
||
multiPlatformAppManagementWorkflow,
|
||
|
||
// Bundle Module Workflows
|
||
intelligentBundleWorkflow,
|
||
incrementalBuildWorkflow,
|
||
|
||
// Package Module Workflows
|
||
batchPackageProcessingWorkflow,
|
||
|
||
// Version Module Workflows
|
||
versionReleaseManagementWorkflow,
|
||
];
|