execute method

  1. @override
Future<ReleaseResult> execute(
  1. ReleaseContext context
)
override

Executes the release workflow represented by this strategy.

Implementation

@override
Future<ReleaseResult> execute(ReleaseContext context) async {
  final steps = <String>[
    'Initialized ReleaseContext',
    'Selected NormalReleaseStrategy',
  ];

  // Determine platform and format
  final platformStr = context.targetPlatform ?? 'android';
  final platform = BuildPlatform.parse(platformStr);

  BuildFormat format;
  if (context.config.format != null && context.config.format!.isNotEmpty) {
    format = BuildFormat.parse(context.config.format!);
  } else {
    format = BuildFormat.defaultForPlatform(platform);
  }

  final buildContext = BuildContext(
    projectPath: context.projectPath,
    platform: platform,
    format: format,
    versionName: context.versionName,
    buildNumber: context.buildNumber,
    dryRun: context.dryRun,
    isReleaseMode: true,
  );

  steps.add('Configured build for platform $platform with format $format');

  if (context.dryRun) {
    steps.add('Executed build subsystem in dry-run mode.');
    final buildResults = await _buildManager.executeBuild(buildContext);

    if (context.config.deploy) {
      steps.add('Executing store deployment subsystem in dry-run mode...');
      final deployContext = DeploymentContext(
        projectPath: context.projectPath,
        platform: platform,
        lane: context.config.lane,
        versionName: context.versionName,
        buildNumber: context.buildNumber?.toString(),
        dryRun: true,
      );
      final deployResults = await _deploymentManager.deploy(deployContext);
      for (final dRes in deployResults) {
        steps.addAll(dRes.executedSteps);
      }
    }

    if (context.config.createTag) {
      final tagName =
          '${context.config.tagPrefix}${context.versionName ?? "1.0.0"}';
      final tagRes = await _gitClient.createTag(
        context.projectPath,
        tagName,
        message: 'Release $tagName',
        dryRun: true,
      );
      steps.add(tagRes.message);
    }

    return ReleaseResult.success(
      type: type,
      message:
          '[DRY-RUN] Normal Flutter Release build preview executed successfully.',
      versionName: context.versionName,
      buildNumber: context.buildNumber,
      targetPlatform: platformStr,
      executedSteps: [
        ...steps,
        ...buildResults.expand((r) => r.executedSteps),
      ],
      metadata: {
        'dryRun': true,
        'buildResults': buildResults,
      },
    );
  }

  steps.add('Executing Flutter build compilation...');
  final buildResults = await _buildManager.executeBuild(buildContext);
  final allSuccessful = buildResults.every((r) => r.success);

  final errors = <String>[];
  final warnings = <String>[];
  final artifactPaths = <String, String>{};

  for (final res in buildResults) {
    if (res.success && res.artifactPath != null) {
      artifactPaths[res.platform.name] = res.artifactPath!;
    }
    errors.addAll(res.errors);
    warnings.addAll(res.warnings);
  }

  if (!allSuccessful) {
    return ReleaseResult.failure(
      type: type,
      message: 'Normal Flutter Release build failed.',
      executedSteps: [
        ...steps,
        ...buildResults.expand((r) => r.executedSteps),
      ],
      errors:
          errors.isNotEmpty ? errors : ['One or more build targets failed.'],
      warnings: warnings,
    );
  }

  steps.add('Build compilation finished cleanly for all targets.');

  if (context.config.deploy) {
    steps.add('Triggering store deployment via Fastlane...');
    final deployContext = DeploymentContext(
      projectPath: context.projectPath,
      platform: platform,
      artifactPath: artifactPaths[platform.name],
      lane: context.config.lane,
      versionName: context.versionName,
      buildNumber: context.buildNumber?.toString(),
      dryRun: false,
    );
    final deployResults = await _deploymentManager.deploy(deployContext);
    final deploySuccess = deployResults.every((r) => r.success);

    for (final dRes in deployResults) {
      steps.addAll(dRes.executedSteps);
      warnings.addAll(dRes.warnings);
      errors.addAll(dRes.errors);
    }

    if (!deploySuccess) {
      return ReleaseResult.failure(
        type: type,
        message: 'Store deployment failed after successful build.',
        executedSteps: steps,
        errors: errors,
        warnings: warnings,
      );
    }
  }

  // Handle Git Tagging
  String? createdTagName;
  if (context.config.createTag) {
    final tagName =
        '${context.config.tagPrefix}${context.versionName ?? "1.0.0"}';
    final tagRes = await _gitClient.createTag(
      context.projectPath,
      tagName,
      message: 'Release $tagName',
      dryRun: false,
    );

    if (tagRes.success) {
      createdTagName = tagName;
      steps.add(tagRes.message);
    } else {
      warnings.add(tagRes.message);
    }
  }

  // Save Release Metadata
  final commitSha = await _gitClient.getCurrentCommitSha(context.projectPath);
  final branch = await _gitClient.getCurrentBranch(context.projectPath);

  final metadata = ReleaseMetadata(
    versionName: context.versionName ?? '1.0.0',
    buildNumber: context.buildNumber?.toString() ?? '1',
    releaseMode: 'normal',
    platforms: [platformStr],
    tag: createdTagName,
    commitSha: commitSha,
    branch: branch,
    artifacts: artifactPaths,
    deploymentStatus: context.config.deploy ? 'Deployed' : 'Built',
  );

  await _metadataManager.saveMetadata(context.projectPath, metadata);
  steps.add('Persisted release manifest to .flutter_setup/releases/');

  return ReleaseResult.success(
    type: type,
    message: 'Normal Flutter Release build completed successfully.',
    versionName: context.versionName,
    buildNumber: context.buildNumber,
    targetPlatform: platformStr,
    executedSteps: [
      ...steps,
      ...buildResults.expand((r) => r.executedSteps),
    ],
    warnings: warnings,
    metadata: {
      'artifactPaths': artifactPaths,
      'buildResults': buildResults,
      'tag': createdTagName,
      'commitSha': commitSha,
    },
  );
}