run method

  1. @override
FutureOr? run()
override

Runs this command.

The return value is wrapped in a Future if necessary and returned by CommandRunner.runCommand.

Implementation

@override
FutureOr? run() async {
  /// 是否跳过Unity自动更新
  final skipUnityUpdate = JSON(argResults?['skipUnityUpdate']).boolValue;
  logger.log('skipUnityUpdate: $skipUnityUpdate', status: LogStatus.debug);

  final tag = JSON(argResults?['tag']).string;
  logger.log('tag: $tag', status: LogStatus.debug);

  final sentryPropertiesPath =
      JSON(argResults?['sentry_properties_path']).string;
  logger.log(
    'sentryPropertiesPath: $sentryPropertiesPath',
    status: LogStatus.debug,
  );

  final fastfile = JSON(argResults?['fastfile']).string;
  logger.log('fastfile: $fastfile', status: LogStatus.debug);

  /// 初始化环境变量 提示用户必须设置对应的环境变量
  environment.setup(!skipUnityUpdate);

  /// 初始化打包配置管理器
  final buildConfigManager = getBuildConfigManager(
      appwriteEnvironment: environment.appwriteEnvironment);

  /// 本地的Unity提交
  String? localUnityCommit;

  /// 远程的Unity提交
  String? remoteUnityCommit;

  /// 如果不跳过Unity自动更新则获取对应的Uity提交
  if (unityFullPath != null) {
    await gitReset(unityFullPath!);

    /// 如果当前的分支和目标分支不是一个分支 则切换
    if (await getLocalBranchName(unityFullPath!) !=
        environment.unityBranchName) {
      await runCommand(
        unityFullPath!,
        'git switch ${environment.unityBranchName} -f',
      );
    }

    /// 获取Unity项目的本地提交
    localUnityCommit = await getGitLastCommitHash(unityFullPath!);
    logger.log('本地Unity提交: $localUnityCommit');

    /// 获取网络上最新的Unity提交
    remoteUnityCommit = await getGitLastRemoteCommitHash(unityFullPath!);
    logger.log('网络上最新的Unity提交: $remoteUnityCommit');
  }

  /// 获取当前打包平台的上一次打包配置
  var buildInfo = await buildConfigManager.getBuildConfig();
  buildInfo ??= BuildInfo.fromJson({});

  /// 获取上一次Unity打包的ID
  final lastUnityBuildId = buildInfo.unity.cache;

  /// Unity是否需要更新 通过本地和远程的对比 可以防止打包失败了 但是依然需要重新导包
  bool needUpdateUnity = lastUnityBuildId != remoteUnityCommit &&
      environment.unityEnvironment != null;

  if (environment.forceBuild) {
    needUpdateUnity = true;
  }

  /// 如果当前的分支和目标分支不是一个分支 则切换
  if (await getLocalBranchName(environment.workspace) != environment.branch) {
    await gitReset(environment.workspace);

    await runCommand(
      environment.workspace,
      'git switch ${environment.branch} -f',
    );
  }

  /// 获取当前本地工程的最后一次提交
  final localRootCommit = await getGitLastCommitHash(environment.workspace);
  logger.log('本地项目提交: $localRootCommit');

  /// 获取当前本地工程的最后一次远程的提交
  final remoteRootCommit = await getGitLastRemoteCommitHash(
    environment.workspace,
  );
  logger.log('网络上最新的项目提交: $remoteRootCommit');

  var log = '';

  String flutterLog = '';
  String unityLog = '';

  /// 如果unity最后一次日志的ID和目前远程的不是一致 并且没有跳过Unity更新
  if (buildInfo.unity.log != remoteUnityCommit && unityFullPath != null) {
    /// 将Unity更新到最新
    await updateGitBranch(unityFullPath!);

    var currentCommitId = JSON(buildInfo.unity.log).stringValue;
    if (currentCommitId.isEmpty) {
      currentCommitId = environment.unityLastCommitHash;
    }
    // if (currentCommitId.isEmpty) {
    //   throw Exception('请使用UNITY_LAST_COMMIT_HASH设置上一次Unity打包的Commit ID');
    // }

    /// 获取Unity更新日志
    unityLog = await GetGitLog(
          root: unityFullPath!,
          lastCommitId: remoteUnityCommit!,
          currentCommitId: currentCommitId,
        ).get() ??
        '';

    if (JSON(unityLog).stringValue.isNotEmpty) {
      unityLog += '''
Unity更新日志:$remoteUnityCommit
$unityLog
''';
    }
  }

  if (buildInfo.flutter != remoteRootCommit) {
    /// 更新当前打包工程的代码
    await updateGitBranch(environment.workspace);

    var currentCommitId = JSON(buildInfo.flutter).stringValue;
    if (currentCommitId.isEmpty) {
      currentCommitId = environment.flutterLastCommitHash;
    }
    // if (currentCommitId.isEmpty) {
    //   throw Exception('请使用FLUTTER_LAST_COMMIT_HASH设置上一次Flutter打包的Commit ID');
    // }

    /// 获取当前打包工程的更新日志
    flutterLog = await GetGitLog(
          root: environment.workspace,
          lastCommitId: remoteRootCommit,
          currentCommitId: currentCommitId,
        ).get() ??
        '';

    if (JSON(flutterLog).stringValue.isNotEmpty) {
      flutterLog += '''
Flutter更新日志:$remoteRootCommit
$flutterLog
''';
    }
  }

  /// 格式化当前的日志
  log = formatGitLog(flutterLog, unityLog);

  if (log.isNotEmpty) {
    log = '''
[Flutter]: ${environment.branch}
[Unity]: ${environment.unityBranchName}
[Tag]: ${tag ?? ''}
[version]: ${environment.buildName}(${environment.buildNumber})
$logHeader
-----------------------
$log
-----------------------
$logFooter
''';
  }

  _log =
      '[Tag:$tag][Flutter(${environment.branch})][Unity(${environment.unityBranchName})]  新版本发布了,请下载体验!';

  logger.log('''
更新日志:
${log.isEmpty ? "暂无更新内容" : log}
''', status: LogStatus.warning);

  final unityEnvironment = environment.unityEnvironment;
  if (unityEnvironment != null && unityFullPath != null) {
    /// 原始的对应打包平台Unity的出包位置
    final fromUnityFrameworkPath = join(
      unityEnvironment.unityWorkspace,
      unityFrameworkPath,
    );

    /// 如果需要更新Unity 并且本地的Unity不存在
    if (needUpdateUnity ||
        !await Directory(fromUnityFrameworkPath).exists()) {
      /// 导出Unity包
      await updateUnity(unityEnvironment);
      buildInfo.unity.cache = remoteUnityCommit!;

      /// 更新当前最后一次Unity缓存的ID
      await buildConfigManager.setBuildConfig(
        buildInfo: buildInfo,
        buildName: environment.buildName,
        buildTime: environment.buildNumber,
      );
    }

    /// 复制最新的Unity包所到的位置
    final toUnityFrameworkPath = join(
      environment.workspace,
      unityFrameworkPath,
    );

    /// 将最新的Unity复制到打包的项目
    if (await Directory(toUnityFrameworkPath).exists()) {
      await Directory(toUnityFrameworkPath).delete(recursive: true);
    }

    /// 复制缓存到对应的目录
    await runCommand(
      environment.workspace,
      'cp -rf $fromUnityFrameworkPath $toUnityFrameworkPath',
    );

    /// 如果是安卓项目则删除build目录
    final buildUnityDir = Directory(join(toUnityFrameworkPath, 'build'));
    if (await buildUnityDir.exists()) {
      await buildUnityDir.delete(recursive: true);
    }
  }

  /// 判断是否需要更新
  bool needUpdateRoot = buildInfo.flutter != remoteRootCommit;
  if (!needUpdateRoot && !needUpdateUnity && !environment.forceBuild) {
    logger.log('没有任何的变动,打包停止!', status: LogStatus.warning);
    exit(0);
  }

  /// 对于Flutter 进行pub get
  await Shell(workingDirectory: environment.flutterDir)
      .run('fvm flutter pub get');

  final dartDefineFile =
      File(join(environment.flutterDir, 'assets', 'dart_define.json'));
  if (await dartDefineFile.exists()) {
    await dartDefineFile.delete();
  }

  /// 生成dart-define变量文件
  await Shell(workingDirectory: environment.flutterDir)
      .run('fvm flutter pub run dart_define generate');

  /// 初始化Fastlane 支持后面上传iPA或者APK
  final fastfileContent =
      await Unwrap(fastfile).map((e) => File(e).readAsString()).value;
  await setupFastlane.setup(fastfileContent);

  /// 进行打包
  await build(environment.workspace);

  logger.log('正在上传安装包');
  await upload(environment.workspace);
  logger.log('上传安装包完成', status: LogStatus.success);

  if (environment.sendLog) {
    /// 发送更新日志到企业微信
    logger.log('正在发送更新日志到企业微信');
    await sendWeChat(log);
    logger.log('发送更新日志到企业微信完成', status: LogStatus.success);

    logger.log('正在发送更新日志到钉钉');
    await sendTextToWeixinWebhooks(log, dingdingHookUrl);
    logger.log('发送更新日志到钉钉完成', status: LogStatus.success);
  }

  /// 打包完毕更新打包配置
  buildInfo.flutter = remoteRootCommit;
  if (!skipUnityUpdate) {
    buildInfo.unity.log = remoteUnityCommit!;
  }
  await buildConfigManager.setBuildConfig(
    buildInfo: buildInfo,
    buildName: environment.buildName,
    buildTime: environment.buildNumber,
  );

  await UploadSentrySymbols(environment: environment).run();

  logger.log('✅打包完成', status: LogStatus.success);
  exit(0);
}