run method
Runs this command.
The return value is wrapped in a Future if necessary and returned by
CommandRunner.runCommand.
Implementation
@override
Future<void> run() async {
buildStartTime = DateTime.now();
// 1. Initialize Services
config = ConfigService(projectDir);
whiteLabel = WhiteLabelService(projectDir: projectDir, config: config);
cleanup = CleanupService(projectDir: projectDir, config: config);
final client = argResults!['client'] as String;
final isTest = argResults!['test'] as bool;
final enableSlack = argResults!['slack'] as bool;
String? version;
String? errorMessage;
bool buildSuccess = false;
if (enableSlack) {
slackService =
await _initializeSlackService(argResults!['slack-channel']);
}
try {
// PHASE 1: VALIDATION & SETUP
print('--- โ๏ธ Phase 1: Validation & Setup ---');
version = await config.getPubspecVersion();
await _notifyBuildStep('Whitelabel Started', client, '', 'started',
additionalInfo: 'Version: $version, Type: ' '');
final envVars = await config.parseEnvFile(
File('$projectDir/clients/$client/${isTest ? '.env_test' : '.env'}'));
await config.copyToRootEnv(
File('$projectDir/clients/$client/${isTest ? '.env_test' : '.env'}'));
final appName = envVars['APP_NAME_PROD']!;
final bundleId = envVars['BUNDLE_ID']!;
final clientAssetsPath = envVars['ASSETS_PATH']!;
final appIconPath = envVars['APP_ICON_PATH']!;
appNameForCleanup = appName;
// PHASE 2: PROJECT CONFIGURATION
print('\n--- โ๏ธ Phase 2: Project Configuration ---');
await _notifyBuildStep('Project Configuration', client, '', 'started');
await config.createBackup(File('$projectDir/pubspec.yaml'));
await config
.createBackup(File('$projectDir/flutter_launcher_icons.yaml'));
await config.updateYamlValue(
File('$projectDir/flutter_launcher_icons.yaml'),
['flutter_launcher_icons', 'image_path'],
appIconPath);
print(
'Updated `flutter_launcher_icons.yaml` image_path to `$appIconPath`');
await config.updateYamlValue(File('$projectDir/pubspec.yaml'),
['splash_master', 'image'], appIconPath);
print('Updated `pubspec.yaml` splash_master image to `$appIconPath`');
await whiteLabel.syncBrandingAssets(client, clientAssetsPath);
await whiteLabel.applyClientFonts(clientAssetsPath);
// Update YAMLs via Config Service
await config.updatePubspecAssets(
clientAssetPath: client, requiredExtraAssets: ['.env']);
// PHASE 3: RUNNING EXTERNAL TOOLS
print('\n--- ๐ Phase 3: Running Build Commands ---');
await runShell('flutter pub get');
await runShell(
'dart run rename setBundleId --targets ios,android --value "$bundleId"');
await runShell(
'dart run rename setAppName --targets ios,android --value "$appName"');
await runShell('dart run flutter_launcher_icons');
await runShell('dart run splash_master create');
await whiteLabel.patchIosSplash(appName);
await whiteLabel.cleanAndroidIconCache();
buildSuccess = true;
print('\nโ
โ
โ
Whitelabelling process completed successfully! โ
โ
โ
');
} catch (e) {
buildSuccess = false;
errorMessage = e.toString();
await _notifyBuildStep('Build Process', client, '', 'failed',
errorMessage: errorMessage);
rethrow; // Ensure cleanup runs but user sees the error
} finally {
// FINAL PHASE: CLEANUP (ALWAYS RUNS)
print('\n--- ๐งน Final Phase: Cleaning Up ---');
await cleanup.performFullCleanup(
appNameForCleanup: appNameForCleanup,
fontsWereChanged: true,
);
if (slackService != null && version != null) {
final buildDuration = DateTime.now().difference(buildStartTime!);
await slackService!.sendBuildSummary(
client: client,
platform: '',
type: '',
version: version,
success: buildSuccess,
buildTime: buildDuration,
errorMessage: errorMessage,
artifactFile: builtApkFile,
);
}
buildSuccess = false;
}
}