publish method

  1. @override
Future<void> publish()
override

Implementation

@override
Future<void> publish() async {
  AndroidPlatformBuild platformBuild = this.platformBuild;

  _logger.info('Install dependencies...');
  if (!await isInstalled('fastlane')) {
    await ensureInstalled('ruby');
    await ensureInstalled('ruby-dev');
    await ensureInstalled(
      'fastlane',
      installCommands: ['sudo', 'gem', 'install'],
    );
  }

  await ensureInstalled(
    'bundler',
    installCommands: ['sudo', 'gem', 'install'],
  );

  /// Prepare gradlew executable:
  final configPlatformBuild = platformBuild.copyWith(
    // Only apk supports `config-only` flag
    buildType: BuildType.apk,
    flutterBuild: platformBuild.flutterBuild.copyWith(buildArgs: [
      ...platformBuild.flutterBuild.buildArgs,
      '--config-only'
    ]),
  );
  await configPlatformBuild.build();

  final getApplicationIdScript =
      await getPackageFileUri('gradle/get_android_app_id.gradle');
  // On Unix the executable path must be marked relative!
  final gradlew = Platform.isWindows ? 'gradlew.bat' : './gradlew';
  final result = await runProcess(
    gradlew,
    [
      '-q',
      '--init-script',
      getApplicationIdScript!.path,
      ':app:printApplicationId',
      if (platformBuild.flutterBuild.flavor != null)
        '-Pflavor=${platformBuild.flutterBuild.flavor}',
    ],
    workingDirectory: _androidDirectory,
    printCall: true,
  );

  final packageName = result.stdout.toString().trim();
  if (packageName.isEmpty) throw Exception('Application Id not found');
  _logger.info('Used Application Id: $packageName');

  // Save Google play store credentials file
  final fastlaneSecretsJsonFile =
      File('$_androidDirectory/$_fastlaneSecretsJsonFile');
  await fastlaneSecretsJsonFile
      .writeAsBytes(base64.decode(fastlaneSecretsJsonBase64));

  final fastlaneAppfile = '''
json_key_file("${fastlaneSecretsJsonFile.absolute.path}")
package_name("$packageName")
  ''';
  await Directory(_fastlaneDirectory).create(recursive: true);
  await File('$_fastlaneDirectory/Appfile').writeAsString(fastlaneAppfile);

  // Check if play store credentials are valid
  await runProcess(
    'fastlane',
    [
      'run',
      'validate_play_store_json_key',
      // 'json_key:${fastlaneSecretsJsonFile.absolute.path}',
    ],
    workingDirectory: _androidDirectory,
    runInShell: true,
  );

  final track = switch (flutterPublish.stage) {
    PublishStage.production => 'production',
    PublishStage.beta => 'beta',
    PublishStage.alpha => 'alpha',
    _ => 'internal',
  };

  if (platformBuild.flutterBuild.buildVersion.build.isEmpty) {
    var versionCode = await _getLastVersionCodeFromGooglePlay(track);
    if (versionCode != null) {
      // Increase versionCode by 1, if available:
      versionCode++;
      _logger.info(
        'Use "$versionCode" as next version code (fetched from Google Play).',
      );

      platformBuild = platformBuild.copyWith(
          flutterBuild: platformBuild.flutterBuild.copyWith(
              buildVersion: platformBuild.flutterBuild.buildVersion.copyWith(
        build: versionCode.toString(),
      )));
    }
  } else {
    _logger.info(
      'Using provided version code "${platformBuild.flutterBuild.buildVersion.build}".',
    );
  }

  _logger.info('Build application...');

  final outputPath = await platformBuild.build();
  if (outputPath == null) {
    _logger.severe('Failed to build the app for Android!');
    return;
  }

  _logger.info('Build artifact path: $outputPath');
  final outputFile = File(outputPath);

  if (flutterPublish.isDryRun) {
    _logger.info('Did NOT publish: Remove `--dry-run` flag for publishing.');
  } else {
    _logger.info('Publish...');
    await runProcess(
      'fastlane',
      [
        'supply',
        '--aab',
        outputFile.absolute.path,
        '--track',
        track,
        '--release_status',
        releaseStatus.name,
      ],
      workingDirectory: _androidDirectory,
      printCall: true,
      runInShell: true,
    );
  }
}