execute method
Executes the command with the provided arguments.
Returns an integer exit code (0 for success).
Implementation
@override
Future<int> execute(List<String> args) async {
final parser = buildArgParser();
ArgResults results;
try {
results = parser.parse(args);
} catch (e) {
_output.error('Invalid arguments for build command: $e');
_output.info('\nUsage:');
_output.info(parser.usage);
return 1;
}
final projectPath = results['path'] as String;
final pubspecFile = File('$projectPath/pubspec.yaml');
if (!pubspecFile.existsSync()) {
_output.error(
'Flutter project not found at path "$projectPath". Missing pubspec.yaml.');
return 1;
}
final platformStr = results['platform'] as String;
final platform = BuildPlatform.parse(platformStr);
BuildFormat format;
if (results.wasParsed('format')) {
format = BuildFormat.parse(results['format'] as String);
} else {
format = BuildFormat.defaultForPlatform(platform);
}
try {
format.validateForPlatform(platform);
} on ValidationException catch (e) {
_output.error('Format validation failed: ${e.message}');
return 1;
}
final isDryRun = results['dry-run'] as bool;
final isDebug = results['debug'] as bool;
final isRelease = isDebug ? false : (results['release'] as bool);
String? versionName = results['version'] as String?;
int? buildNumber;
if (results.wasParsed('build-number')) {
buildNumber = int.tryParse(results['build-number'] as String);
if (buildNumber == null || buildNumber <= 0) {
_output.error('Build number must be a positive integer.');
return 1;
}
}
// Attempt reading project version if explicit overrides not provided
if (versionName == null || buildNumber == null) {
try {
final currentVer = _versionManager.getCurrentVersion(projectPath);
versionName ??= currentVer.versionName;
buildNumber ??= currentVer.buildNumber;
} catch (_) {
// Fallback silently if pubspec parsing fails
}
}
final envArg =
results['environment'] as String? ?? results['env'] as String?;
final rawDefines =
(results['dart-define'] as List<String>?) ?? const <String>[];
final parsedDefines = EnvironmentResolver.parseDartDefines(rawDefines);
final resolver = const EnvironmentResolver();
final envConfig = resolver.resolve(
cliEnvironment: envArg,
cliFlavor: results['flavor'] as String?,
cliDartDefines: parsedDefines,
envVars: Platform.environment,
);
final extraArgs = <String>[];
for (final entry in envConfig.dartDefines.entries) {
extraArgs.addAll(['--dart-define', '${entry.key}=${entry.value}']);
}
final context = BuildContext(
projectPath: projectPath,
platform: platform,
format: format,
versionName: versionName,
buildNumber: buildNumber,
dryRun: isDryRun,
isReleaseMode: isRelease,
flavor: envConfig.flavor,
target: results['target'] as String?,
extraArgs: extraArgs,
);
_output.info('Flutter Build Automation');
_output.info('Platform: $platform');
_output.info('Format: $format');
if (versionName != null && buildNumber != null) {
_output.info('Version: $versionName+$buildNumber');
}
final buildResults = await _buildManager.executeBuild(context);
final allPassed = buildResults.every((r) => r.success);
_output.info('\n--- BUILD SUMMARY ---');
for (final res in buildResults) {
if (res.success) {
_output.success('${res.platform} (${res.format}): SUCCESS');
if (res.artifactPath != null) {
_output.info(' Artifact: ${res.artifactPath}');
}
} else {
_output.error('${res.platform} (${res.format}): FAILED');
for (final err in res.errors) {
_output.error(' • $err');
}
}
}
return allPassed ? 0 : 1;
}