UNPKG

appstore-cli

Version:

A command-line interface (CLI) to interact with the Apple App Store Connect API.

176 lines (163 loc) 6.74 kB
import yargs from 'yargs'; import { ConfigurationValidationMiddleware } from '../middleware/configuration-validation-middleware.js'; import fastlaneService from '../services/fastlane-service.js'; import { FastlaneServiceError } from '../services/fastlane-service.js'; import { safeLogger } from '../security/dataHandler.js'; import configurationService from '../services/configuration-service.js'; import migrateBuildAuthConfig from '../scripts/migrate-build-auth.js'; /** * CLI command for running the export process. */ export const exportRunCommand: yargs.CommandModule<{}, { 'archive-path': string; 'output-path'?: string; 'provisioning-profile-path'?: string; 'certificate-path'?: string; 'certificate-password'?: string; 'use-automatic-signing'?: boolean; 'export-options-plist'?: string; 'log-output'?: string; }> = { command: 'run', describe: 'Execute the export process to create an IPA file', builder: (yargs) => { return yargs .option('archive-path', { alias: 'a', describe: 'Path to the archive file', type: 'string', demandOption: true, }) .option('output-path', { alias: 'o', describe: 'Path where the IPA file should be saved', type: 'string', }) .option('provisioning-profile-path', { describe: 'Path to the provisioning profile file (.mobileprovision)', type: 'string', }) .option('certificate-path', { describe: 'Path to the signing certificate file (.p12 or .pem)', type: 'string', }) .option('certificate-password', { describe: 'Password for the signing certificate (if encrypted)', type: 'string', }) .option('use-automatic-signing', { describe: 'Whether to use automatic code signing', type: 'boolean', }) .option('export-options-plist', { describe: 'Custom export options plist content', type: 'string', }) .option('log-output', { alias: 'l', describe: 'Path to save the export log output to a file', type: 'string', }) .check((argv) => { // Validate paths for runtime overrides if (argv['provisioning-profile-path']) { if (!require('fs').existsSync(argv['provisioning-profile-path'])) { throw new Error(`Provisioning profile file not found: ${argv['provisioning-profile-path']}`); } if (!argv['provisioning-profile-path'].endsWith('.mobileprovision')) { throw new Error('Provisioning profile file must have .mobileprovision extension'); } } if (argv['certificate-path']) { if (!require('fs').existsSync(argv['certificate-path'])) { throw new Error(`Certificate file not found: ${argv['certificate-path']}`); } if (!argv['certificate-path'].endsWith('.p12') && !argv['certificate-path'].endsWith('.pem')) { throw new Error('Certificate file must have .p12 or .pem extension'); } } if (argv['certificate-path'] && argv['certificate-path'].endsWith('.p12') && argv['certificate-password'] === undefined) { throw new Error('Certificate password is required for .p12 certificate files'); } if (argv['use-automatic-signing'] && (argv['provisioning-profile-path'] || argv['certificate-path'])) { throw new Error('Cannot use automatic signing with manual provisioning profile or certificate paths'); } // Validate log output path if (argv['log-output']) { const path = require('path'); const dir = path.dirname(argv['log-output']); if (!require('fs').existsSync(dir)) { throw new Error(`Log output directory does not exist: ${dir}`); } } return true; }); }, handler: async (argv) => { try { // Check if we have an old build auth configuration and migrate it const authConfig = configurationService.loadAuthenticationConfiguration(); if (authConfig) { console.warn('⚠️ WARNING: Found deprecated build auth configuration.'); console.warn('Migrating to unified appstore-cli config...'); await migrateBuildAuthConfig(); console.warn('Migration completed. You can now remove the separate build auth configuration.'); console.warn(''); } // Check if we have certificate configuration let certConfig = configurationService.loadCertificateConfiguration() || {}; // Validate configurations using middleware const { exportConfig, authConfig: validatedAuthConfig } = ConfigurationValidationMiddleware.validateAllConfigurations(); if (!exportConfig) { console.error('Export configuration not found. Please run "appstore-cli build export configure" first.'); process.exit(1); } // Merge runtime certificate overrides (do not persist) const runtimeCertOverrides: any = {}; if (argv['provisioning-profile-path']) { runtimeCertOverrides.provisioningProfilePath = argv['provisioning-profile-path']; } if (argv['certificate-path']) { runtimeCertOverrides.certificatePath = argv['certificate-path']; } if (argv['certificate-password']) { runtimeCertOverrides.certificatePassword = argv['certificate-password']; } if (argv['use-automatic-signing'] !== undefined) { runtimeCertOverrides.useAutomaticSigning = argv['use-automatic-signing']; } if (argv['export-options-plist']) { runtimeCertOverrides.exportOptionsPlist = argv['export-options-plist']; } certConfig = { ...certConfig, ...runtimeCertOverrides }; // Execute the export console.log('Starting export process...'); const ipaPath = await fastlaneService.executeExport( exportConfig, validatedAuthConfig || {}, certConfig, argv['archive-path'], argv['output-path'], argv['log-output'] ); // Output success message console.log(`Export completed successfully. IPA saved to: ${ipaPath}`); } catch (error) { if (error instanceof FastlaneServiceError) { console.error(`Export failed: ${error.message}`); safeLogger.error('Export failed with FastlaneServiceError', { error: error.message, code: error.code }); } else { console.error(`Export failed: ${(error as Error).message}`); safeLogger.error('Export failed with unexpected error', { error: (error as Error).message }); } process.exit(1); } }, };