1
0
mirror of https://gitcode.com/github-mirrors/react-native-update-cli.git synced 2025-09-16 01:41:37 +08:00
Code Issues Packages Projects Releases Wiki Activity GitHub Gitee

Enhance upload commands to support custom versioning and update documentation. Added version option to uploadIpa, uploadApk, and uploadApp commands. Updated README and localization files to reflect changes.

This commit is contained in:
sunnylqm
2025-08-22 10:09:37 +08:00
parent 7e7e555450
commit e6de3eeef3
10 changed files with 361 additions and 213 deletions

3
.gitignore vendored
View File

@@ -105,3 +105,6 @@ dist
lib/
.DS_Store
# react-native-update
.update
.pushy

109
README.md
View File

@@ -49,14 +49,14 @@ const provider = moduleManager.getProvider();
const bundleResult = await provider.bundle({
platform: 'ios',
dev: false,
sourcemap: true
sourcemap: true,
});
// Publish version
const publishResult = await provider.publish({
name: 'v1.2.3',
description: 'Bug fixes and improvements',
rollout: 100
rollout: 100,
});
```
@@ -65,7 +65,11 @@ const publishResult = await provider.publish({
### 1. Define Module
```typescript
import type { CLIModule, CommandDefinition, CustomWorkflow } from 'react-native-update-cli';
import type {
CLIModule,
CommandDefinition,
CustomWorkflow,
} from 'react-native-update-cli';
export const myCustomModule: CLIModule = {
name: 'my-custom',
@@ -79,13 +83,13 @@ export const myCustomModule: CLIModule = {
console.log('Executing custom command...');
return {
success: true,
data: { message: 'Custom command executed' }
data: { message: 'Custom command executed' },
};
},
options: {
param: { hasValue: true, description: 'Custom parameter' }
}
}
param: { hasValue: true, description: 'Custom parameter' },
},
},
],
workflows: [
@@ -99,7 +103,7 @@ export const myCustomModule: CLIModule = {
execute: async (context, previousResult) => {
console.log('Executing step 1...');
return { step1Completed: true };
}
},
},
{
name: 'step2',
@@ -107,10 +111,10 @@ export const myCustomModule: CLIModule = {
execute: async (context, previousResult) => {
console.log('Executing step 2...');
return { ...previousResult, step2Completed: true };
}
}
]
}
},
},
],
},
],
init: (provider) => {
@@ -119,7 +123,7 @@ export const myCustomModule: CLIModule = {
cleanup: () => {
console.log('Custom module cleanup');
}
},
};
```
@@ -135,13 +139,13 @@ moduleManager.registerModule(myCustomModule);
// Execute custom command
const result = await moduleManager.executeCommand('custom-command', {
args: [],
options: { param: 'value' }
options: { param: 'value' },
});
// Execute custom workflow
const workflowResult = await moduleManager.executeWorkflow('my-workflow', {
args: [],
options: {}
options: {},
});
```
@@ -191,6 +195,7 @@ Each workflow step contains:
## 📋 Built-in Modules
### Bundle Module (`bundle`)
- `bundle`: Bundle JavaScript code and optionally publish
- `diff`: Generate differences between two PPK files
- `hdiff`: Generate hdiff between two PPK files
@@ -201,27 +206,31 @@ Each workflow step contains:
- `hdiffFromIpa`: Generate hdiff from IPA files
### Version Module (`version`)
- `publish`: Publish new version
- `versions`: List all versions
- `update`: Update version information
- `updateVersionInfo`: Update version metadata
### App Module (`app`)
- `createApp`: Create new application
- `apps`: List all applications
- `selectApp`: Select application
- `deleteApp`: Delete application
### Package Module (`package`)
- `uploadIpa`: Upload IPA files
- `uploadApk`: Upload APK files
- `uploadApp`: Upload APP files
- `uploadIpa`: Upload IPA files (supports `--version` to override extracted version)
- `uploadApk`: Upload APK files (supports `--version` to override extracted version)
- `uploadApp`: Upload APP files (supports `--version` to override extracted version)
- `parseApp`: Parse APP file information
- `parseIpa`: Parse IPA file information
- `parseApk`: Parse APK file information
- `packages`: List packages
### User Module (`user`)
- `login`: Login
- `logout`: Logout
- `me`: Show user information
@@ -242,14 +251,20 @@ interface CLIProvider {
upload(options: UploadOptions): Promise<CommandResult>;
// Application management
getSelectedApp(platform?: Platform): Promise<{ appId: string; platform: Platform }>;
getSelectedApp(
platform?: Platform,
): Promise<{ appId: string; platform: Platform }>;
listApps(platform?: Platform): Promise<CommandResult>;
createApp(name: string, platform: Platform): Promise<CommandResult>;
// Version management
listVersions(appId: string): Promise<CommandResult>;
getVersion(appId: string, versionId: string): Promise<CommandResult>;
updateVersion(appId: string, versionId: string, updates: Partial<Version>): Promise<CommandResult>;
updateVersion(
appId: string,
versionId: string,
updates: Partial<Version>,
): Promise<CommandResult>;
// Package management
listPackages(appId: string, platform?: Platform): Promise<CommandResult>;
@@ -263,7 +278,10 @@ interface CLIProvider {
// Workflows
registerWorkflow(workflow: CustomWorkflow): void;
executeWorkflow(workflowName: string, context: CommandContext): Promise<CommandResult>;
executeWorkflow(
workflowName: string,
context: CommandContext,
): Promise<CommandResult>;
}
```
@@ -276,8 +294,8 @@ const bundleResult = await moduleManager.executeCommand('custom-bundle', {
options: {
platform: 'android',
validate: true,
optimize: true
}
optimize: true,
},
});
// Generate diff file
@@ -286,8 +304,8 @@ const diffResult = await moduleManager.executeCommand('diff', {
options: {
origin: './build/v1.0.0.ppk',
next: './build/v1.1.0.ppk',
output: './build/diff.patch'
}
output: './build/diff.patch',
},
});
// Generate diff from APK files
@@ -296,8 +314,8 @@ const apkDiffResult = await moduleManager.executeCommand('diffFromApk', {
options: {
origin: './build/app-v1.0.0.apk',
next: './build/app-v1.1.0.apk',
output: './build/apk-diff.patch'
}
output: './build/apk-diff.patch',
},
});
```
@@ -349,29 +367,31 @@ Provider provides a concise programming interface suitable for integrating React
### 📋 Core API Methods
#### Core Business Functions
```typescript
// Bundle application
await provider.bundle({
platform: 'ios',
dev: false,
sourcemap: true
sourcemap: true,
});
// Publish version
await provider.publish({
name: 'v1.0.0',
description: 'Bug fixes',
rollout: 100
rollout: 100,
});
// Upload file
await provider.upload({
filePath: 'app.ipa',
platform: 'ios'
platform: 'ios',
});
```
#### Application Management
```typescript
// Create application
await provider.createApp('MyApp', 'ios');
@@ -384,6 +404,7 @@ const { appId, platform } = await provider.getSelectedApp('ios');
```
#### Version Management
```typescript
// List versions
await provider.listVersions('app123');
@@ -391,11 +412,12 @@ await provider.listVersions('app123');
// Update version
await provider.updateVersion('app123', 'version456', {
name: 'v1.1.0',
description: 'New features'
description: 'New features',
});
```
#### Utility Functions
```typescript
// Get platform
const platform = await provider.getPlatform('ios');
@@ -407,6 +429,7 @@ const session = await provider.loadSession();
### 🎯 Use Cases
#### 1. Automated Build Scripts
```typescript
import { moduleManager } from 'react-native-update-cli';
@@ -417,7 +440,7 @@ async function buildAndPublish() {
const bundleResult = await provider.bundle({
platform: 'ios',
dev: false,
sourcemap: true
sourcemap: true,
});
if (!bundleResult.success) {
@@ -428,7 +451,7 @@ async function buildAndPublish() {
const publishResult = await provider.publish({
name: 'v1.2.3',
description: 'Bug fixes and performance improvements',
rollout: 100
rollout: 100,
});
if (!publishResult.success) {
@@ -440,6 +463,7 @@ async function buildAndPublish() {
```
#### 2. CI/CD Integration
```typescript
async function ciBuild() {
const provider = moduleManager.getProvider();
@@ -447,7 +471,7 @@ async function ciBuild() {
const result = await provider.bundle({
platform: process.env.PLATFORM as 'ios' | 'android',
dev: process.env.NODE_ENV !== 'production',
sourcemap: process.env.NODE_ENV === 'production'
sourcemap: process.env.NODE_ENV === 'production',
});
return result;
@@ -455,6 +479,7 @@ async function ciBuild() {
```
#### 3. Application Management Service
```typescript
class AppManagementService {
private provider = moduleManager.getProvider();
@@ -488,6 +513,7 @@ class AppManagementService {
### 🔧 Advanced Features
#### Custom Workflows
```typescript
// Register custom workflow
provider.registerWorkflow({
@@ -498,7 +524,7 @@ provider.registerWorkflow({
name: 'bundle',
execute: async () => {
return await provider.bundle({ platform: 'ios', dev: false });
}
},
},
{
name: 'publish',
@@ -507,9 +533,9 @@ provider.registerWorkflow({
throw new Error('Bundle failed, cannot publish');
}
return await provider.publish({ name: 'auto-release', rollout: 50 });
}
}
]
},
},
],
});
// Execute workflow
@@ -535,7 +561,7 @@ class ReactNativeUpdateService {
const bundleResult = await this.provider.bundle({
platform,
dev: false,
sourcemap: true
sourcemap: true,
});
if (!bundleResult.success) {
@@ -546,7 +572,7 @@ class ReactNativeUpdateService {
const publishResult = await this.provider.publish({
name: version,
description: `Release ${version}`,
rollout: 100
rollout: 100,
});
if (!publishResult.success) {
@@ -554,11 +580,10 @@ class ReactNativeUpdateService {
}
return { success: true, data: publishResult.data };
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : 'Unknown error'
error: error instanceof Error ? error.message : 'Unknown error',
};
}
}

View File

@@ -47,14 +47,14 @@ const provider = moduleManager.getProvider();
const bundleResult = await provider.bundle({
platform: 'ios',
dev: false,
sourcemap: true
sourcemap: true,
});
// 发布版本
const publishResult = await provider.publish({
name: 'v1.2.3',
description: 'Bug fixes and improvements',
rollout: 100
rollout: 100,
});
```
@@ -63,7 +63,11 @@ const publishResult = await provider.publish({
### 1. 定义模块
```typescript
import type { CLIModule, CommandDefinition, CustomWorkflow } from 'react-native-update-cli';
import type {
CLIModule,
CommandDefinition,
CustomWorkflow,
} from 'react-native-update-cli';
export const myCustomModule: CLIModule = {
name: 'my-custom',
@@ -77,13 +81,13 @@ export const myCustomModule: CLIModule = {
console.log('Executing custom command...');
return {
success: true,
data: { message: 'Custom command executed' }
data: { message: 'Custom command executed' },
};
},
options: {
param: { hasValue: true, description: 'Custom parameter' }
}
}
param: { hasValue: true, description: 'Custom parameter' },
},
},
],
workflows: [
@@ -97,7 +101,7 @@ export const myCustomModule: CLIModule = {
execute: async (context, previousResult) => {
console.log('Executing step 1...');
return { step1Completed: true };
}
},
},
{
name: 'step2',
@@ -105,10 +109,10 @@ export const myCustomModule: CLIModule = {
execute: async (context, previousResult) => {
console.log('Executing step 2...');
return { ...previousResult, step2Completed: true };
}
}
]
}
},
},
],
},
],
init: (provider) => {
@@ -117,7 +121,7 @@ export const myCustomModule: CLIModule = {
cleanup: () => {
console.log('Custom module cleanup');
}
},
};
```
@@ -133,13 +137,13 @@ moduleManager.registerModule(myCustomModule);
// 执行自定义命令
const result = await moduleManager.executeCommand('custom-command', {
args: [],
options: { param: 'value' }
options: { param: 'value' },
});
// 执行自定义工作流
const workflowResult = await moduleManager.executeWorkflow('my-workflow', {
args: [],
options: {}
options: {},
});
```
@@ -189,6 +193,7 @@ const workflowResult = await moduleManager.executeWorkflow('my-workflow', {
## 📋 内置模块
### Bundle 模块 (`bundle`)
- `bundle`: 打包 JavaScript 代码并可选发布
- `diff`: 生成两个 PPK 文件之间的差异
- `hdiff`: 生成两个 PPK 文件之间的 hdiff
@@ -199,27 +204,31 @@ const workflowResult = await moduleManager.executeWorkflow('my-workflow', {
- `hdiffFromIpa`: 从 IPA 文件生成 hdiff
### Version 模块 (`version`)
- `publish`: 发布新版本
- `versions`: 列出所有版本
- `update`: 更新版本信息
- `updateVersionInfo`: 更新版本元数据
### App 模块 (`app`)
- `createApp`: 创建新应用
- `apps`: 列出所有应用
- `selectApp`: 选择应用
- `deleteApp`: 删除应用
### Package 模块 (`package`)
- `uploadIpa`: 上传IPA文件
- `uploadApk`: 上传APK文件
- `uploadApp`: 上传APP文件
- `uploadIpa`: 上传 IPA 文件(支持 `--version` 参数覆盖提取的版本)
- `uploadApk`: 上传 APK 文件(支持 `--version` 参数覆盖提取的版本)
- `uploadApp`: 上传 APP 文件(支持 `--version` 参数覆盖提取的版本)
- `parseApp`: 解析 APP 文件信息
- `parseIpa`: 解析 IPA 文件信息
- `parseApk`: 解析 APK 文件信息
- `packages`: 列出包
### User 模块 (`user`)
- `login`: 登录
- `logout`: 登出
- `me`: 显示用户信息
@@ -240,14 +249,20 @@ interface CLIProvider {
upload(options: UploadOptions): Promise<CommandResult>;
// 应用管理
getSelectedApp(platform?: Platform): Promise<{ appId: string; platform: Platform }>;
getSelectedApp(
platform?: Platform,
): Promise<{ appId: string; platform: Platform }>;
listApps(platform?: Platform): Promise<CommandResult>;
createApp(name: string, platform: Platform): Promise<CommandResult>;
// 版本管理
listVersions(appId: string): Promise<CommandResult>;
getVersion(appId: string, versionId: string): Promise<CommandResult>;
updateVersion(appId: string, versionId: string, updates: Partial<Version>): Promise<CommandResult>;
updateVersion(
appId: string,
versionId: string,
updates: Partial<Version>,
): Promise<CommandResult>;
// 包管理
listPackages(appId: string, platform?: Platform): Promise<CommandResult>;
@@ -261,7 +276,10 @@ interface CLIProvider {
// 工作流
registerWorkflow(workflow: CustomWorkflow): void;
executeWorkflow(workflowName: string, context: CommandContext): Promise<CommandResult>;
executeWorkflow(
workflowName: string,
context: CommandContext,
): Promise<CommandResult>;
}
```
@@ -274,8 +292,8 @@ const bundleResult = await moduleManager.executeCommand('custom-bundle', {
options: {
platform: 'android',
validate: true,
optimize: true
}
optimize: true,
},
});
// 生成差异文件
@@ -284,8 +302,8 @@ const diffResult = await moduleManager.executeCommand('diff', {
options: {
origin: './build/v1.0.0.ppk',
next: './build/v1.1.0.ppk',
output: './build/diff.patch'
}
output: './build/diff.patch',
},
});
// 从APK文件生成差异
@@ -294,8 +312,8 @@ const apkDiffResult = await moduleManager.executeCommand('diffFromApk', {
options: {
origin: './build/app-v1.0.0.apk',
next: './build/app-v1.1.0.apk',
output: './build/apk-diff.patch'
}
output: './build/apk-diff.patch',
},
});
```
@@ -347,29 +365,31 @@ Provider提供了简洁的编程接口适合在应用程序中集成React Nat
### 📋 核心 API 方法
#### 核心业务功能
```typescript
// 打包应用
await provider.bundle({
platform: 'ios',
dev: false,
sourcemap: true
sourcemap: true,
});
// 发布版本
await provider.publish({
name: 'v1.0.0',
description: 'Bug fixes',
rollout: 100
rollout: 100,
});
// 上传文件
await provider.upload({
filePath: 'app.ipa',
platform: 'ios'
platform: 'ios',
});
```
#### 应用管理
```typescript
// 创建应用
await provider.createApp('MyApp', 'ios');
@@ -382,6 +402,7 @@ const { appId, platform } = await provider.getSelectedApp('ios');
```
#### 版本管理
```typescript
// 列出版本
await provider.listVersions('app123');
@@ -389,11 +410,12 @@ await provider.listVersions('app123');
// 更新版本
await provider.updateVersion('app123', 'version456', {
name: 'v1.1.0',
description: 'New features'
description: 'New features',
});
```
#### 工具函数
```typescript
// 获取平台
const platform = await provider.getPlatform('ios');
@@ -405,6 +427,7 @@ const session = await provider.loadSession();
### 🎯 使用场景
#### 1. 自动化构建脚本
```typescript
import { moduleManager } from 'react-native-update-cli';
@@ -415,7 +438,7 @@ async function buildAndPublish() {
const bundleResult = await provider.bundle({
platform: 'ios',
dev: false,
sourcemap: true
sourcemap: true,
});
if (!bundleResult.success) {
@@ -426,7 +449,7 @@ async function buildAndPublish() {
const publishResult = await provider.publish({
name: 'v1.2.3',
description: 'Bug fixes and performance improvements',
rollout: 100
rollout: 100,
});
if (!publishResult.success) {
@@ -438,6 +461,7 @@ async function buildAndPublish() {
```
#### 2. CI/CD 集成
```typescript
async function ciBuild() {
const provider = moduleManager.getProvider();
@@ -445,7 +469,7 @@ async function ciBuild() {
const result = await provider.bundle({
platform: process.env.PLATFORM as 'ios' | 'android',
dev: process.env.NODE_ENV !== 'production',
sourcemap: process.env.NODE_ENV === 'production'
sourcemap: process.env.NODE_ENV === 'production',
});
return result;
@@ -453,6 +477,7 @@ async function ciBuild() {
```
#### 3. 应用管理服务
```typescript
class AppManagementService {
private provider = moduleManager.getProvider();
@@ -486,6 +511,7 @@ class AppManagementService {
### 🔧 高级功能
#### 自定义工作流
```typescript
// 注册自定义工作流
provider.registerWorkflow({
@@ -496,7 +522,7 @@ provider.registerWorkflow({
name: 'bundle',
execute: async () => {
return await provider.bundle({ platform: 'ios', dev: false });
}
},
},
{
name: 'publish',
@@ -505,9 +531,9 @@ provider.registerWorkflow({
throw new Error('打包失败,无法发布');
}
return await provider.publish({ name: 'auto-release', rollout: 50 });
}
}
]
},
},
],
});
// 执行工作流
@@ -533,7 +559,7 @@ class ReactNativeUpdateService {
const bundleResult = await this.provider.bundle({
platform,
dev: false,
sourcemap: true
sourcemap: true,
});
if (!bundleResult.success) {
@@ -544,7 +570,7 @@ class ReactNativeUpdateService {
const publishResult = await this.provider.publish({
name: version,
description: `Release ${version}`,
rollout: 100
rollout: 100,
});
if (!publishResult.success) {
@@ -552,11 +578,10 @@ class ReactNativeUpdateService {
}
return { success: true, data: publishResult.data };
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : 'Unknown error'
error: error instanceof Error ? error.message : 'Unknown error',
};
}
}

View File

@@ -31,9 +31,27 @@
}
}
},
"uploadIpa": {},
"uploadApk": {},
"uploadApp": {},
"uploadIpa": {
"options": {
"version": {
"hasValue": true
}
}
},
"uploadApk": {
"options": {
"version": {
"hasValue": true
}
}
},
"uploadApp": {
"options": {
"version": {
"hasValue": true
}
}
},
"parseApp": {},
"parseIpa": {},
"parseApk": {},

View File

@@ -0,0 +1,53 @@
# Custom Version Parameter Usage
This document demonstrates how to use the `--version` parameter with upload commands to override the version extracted from APK/IPA/APP files.
## Commands Supporting Custom Version
- `uploadApk --version <version>`
- `uploadIpa --version <version>`
- `uploadApp --version <version>`
## Usage Examples
### Upload APK with Custom Version
```bash
# Upload APK and override version to "1.2.3-custom"
cresc uploadApk app-release.apk --version "1.2.3-custom"
```
### Upload IPA with Custom Version
```bash
# Upload IPA and override version to "2.0.0-beta"
cresc uploadIpa MyApp.ipa --version "2.0.0-beta"
```
### Upload APP with Custom Version
```bash
# Upload APP and override version to "3.1.0-harmony"
cresc uploadApp MyApp.app --version "3.1.0-harmony"
```
## Behavior
1. **Without `--version`**: The command uses the version extracted from the package file (APK/IPA/APP)
2. **With `--version`**: The command uses the provided custom version instead of the extracted version
3. **Console Output**: When using a custom version, the CLI will display "Using custom version: <version>" message
## Use Cases
- **Testing**: Upload test builds with specific version identifiers
- **Hotfixes**: Override version numbers for emergency releases
- **Version Alignment**: Ensure consistent versioning across different platforms
- **Manual Override**: When the extracted version is incorrect or inappropriate
## Example Output
```
$ cresc uploadApk app-release.apk --version "1.2.3-hotfix"
Using custom version: 1.2.3-hotfix
Successfully uploaded APK native package (id: 12345, version: 1.2.3-hotfix, buildTime: 2024-01-15T10:30:00Z)
```

View File

@@ -130,4 +130,5 @@ This can reduce the risk of inconsistent dependencies and supply chain attacks.
updateNativePackageQuestion: 'Bind to native package now?(Y/N)',
unnamed: '(Unnamed)',
dryRun: 'Below is the dry-run result, no actual operation will be performed:',
usingCustomVersion: 'Using custom version: {{version}}',
};

View File

@@ -123,4 +123,5 @@ export default {
updateNativePackageQuestion: '是否现在将此热更应用到原生包上?(Y/N)',
unnamed: '(未命名)',
dryRun: '以下是 dry-run 模拟运行结果,不会实际执行任何操作:',
usingCustomVersion: '使用自定义版本:{{version}}',
};

View File

@@ -25,7 +25,7 @@ export async function listPackage(appId: string) {
const versionObj = version as any;
versionInfo = t('boundTo', {
name: versionObj.name || version,
id: versionObj.id || version
id: versionObj.id || version,
});
}
let output = pkg.name;
@@ -57,16 +57,19 @@ export async function choosePackage(appId: string) {
}
export const packageCommands = {
uploadIpa: async ({ args }: { args: string[] }) => {
uploadIpa: async ({
args,
options,
}: {
args: string[];
options: Record<string, any>;
}) => {
const fn = args[0];
if (!fn || !fn.endsWith('.ipa')) {
throw new Error(t('usageUploadIpa'));
}
const ipaInfo = await getIpaInfo(fn);
const {
versionName,
buildTime,
} = ipaInfo;
const { versionName: extractedVersionName, buildTime } = ipaInfo;
const appIdInPkg = (ipaInfo as any).appId;
const appKeyInPkg = (ipaInfo as any).appKey;
const { appId, appKey } = await getSelectedApp('ios');
@@ -79,6 +82,12 @@ export const packageCommands = {
throw new Error(t('appKeyMismatchIpa', { appKeyInPkg, appKey }));
}
// Use custom version if provided, otherwise use extracted version
const versionName = options.version || extractedVersionName;
if (options.version) {
console.log(t('usingCustomVersion', { version: versionName }));
}
const { hash } = await uploadFile(fn);
const { id } = await post(`/app/${appId}/package/create`, {
@@ -89,20 +98,21 @@ export const packageCommands = {
commit: await getCommitInfo(),
});
saveToLocal(fn, `${appId}/package/${id}.ipa`);
console.log(
t('ipaUploadSuccess', { id, version: versionName, buildTime }),
);
console.log(t('ipaUploadSuccess', { id, version: versionName, buildTime }));
},
uploadApk: async ({ args }: { args: string[] }) => {
uploadApk: async ({
args,
options,
}: {
args: string[];
options: Record<string, any>;
}) => {
const fn = args[0];
if (!fn || !fn.endsWith('.apk')) {
throw new Error(t('usageUploadApk'));
}
const apkInfo = await getApkInfo(fn);
const {
versionName,
buildTime,
} = apkInfo;
const { versionName: extractedVersionName, buildTime } = apkInfo;
const appIdInPkg = (apkInfo as any).appId;
const appKeyInPkg = (apkInfo as any).appKey;
const { appId, appKey } = await getSelectedApp('android');
@@ -115,6 +125,12 @@ export const packageCommands = {
throw new Error(t('appKeyMismatchApk', { appKeyInPkg, appKey }));
}
// Use custom version if provided, otherwise use extracted version
const versionName = options.version || extractedVersionName;
if (options.version) {
console.log(t('usingCustomVersion', { version: versionName }));
}
const { hash } = await uploadFile(fn);
const { id } = await post(`/app/${appId}/package/create`, {
@@ -125,20 +141,21 @@ export const packageCommands = {
commit: await getCommitInfo(),
});
saveToLocal(fn, `${appId}/package/${id}.apk`);
console.log(
t('apkUploadSuccess', { id, version: versionName, buildTime }),
);
console.log(t('apkUploadSuccess', { id, version: versionName, buildTime }));
},
uploadApp: async ({ args }: { args: string[] }) => {
uploadApp: async ({
args,
options,
}: {
args: string[];
options: Record<string, any>;
}) => {
const fn = args[0];
if (!fn || !fn.endsWith('.app')) {
throw new Error(t('usageUploadApp'));
}
const appInfo = await getAppInfo(fn);
const {
versionName,
buildTime,
} = appInfo;
const { versionName: extractedVersionName, buildTime } = appInfo;
const appIdInPkg = (appInfo as any).appId;
const appKeyInPkg = (appInfo as any).appKey;
const { appId, appKey } = await getSelectedApp('harmony');
@@ -151,6 +168,12 @@ export const packageCommands = {
throw new Error(t('appKeyMismatchApp', { appKeyInPkg, appKey }));
}
// Use custom version if provided, otherwise use extracted version
const versionName = options.version || extractedVersionName;
if (options.version) {
console.log(t('usingCustomVersion', { version: versionName }));
}
const { hash } = await uploadFile(fn);
const { id } = await post(`/app/${appId}/package/create`, {
@@ -161,9 +184,7 @@ export const packageCommands = {
commit: await getCommitInfo(),
});
saveToLocal(fn, `${appId}/package/${id}.app`);
console.log(
t('appUploadSuccess', { id, version: versionName, buildTime }),
);
console.log(t('appUploadSuccess', { id, version: versionName, buildTime }));
},
parseApp: async ({ args }: { args: string[] }) => {
const fn = args[0];

View File

@@ -110,7 +110,7 @@ export class CLIProviderImpl implements CLIProvider {
const context: CommandContext = {
args: [filePath],
options: { platform, appId },
options: { platform, appId, version: options.version },
};
const { packageCommands } = await import('./package');

View File

@@ -85,6 +85,7 @@ export interface UploadOptions {
platform?: Platform;
filePath: string;
appId?: string;
version?: string;
}
export interface WorkflowStep {