createEveryModuleApps function

Future<int> createEveryModuleApps(
  1. List<SmfModule> modules, {
  2. required String directory,
  3. required String name,
  4. List<String> options = const [],
  5. Map<String, String?> roleOptions = const {},
  6. EveryModuleApps apps = const EveryModuleApps(),
  7. MatrixCommands commands = const MatrixCommands(),
})

Generates in directory the apps with every module of modules with roleOptions, for CI to build them for Android and iOS and to start them on devices: each as the MatrixApp.packageName of name, such as start_app and start_app_riverpod, with the options of CI and then options, such as --org com.example. It analyzes and tests none of them, which runMatrix does.

With --explain among the options, smf create only prints for each app what it would generate and whether the machine is ready.

The apps are those of apps, each app with every module by default, such as a pairwise covering of them, one by the name that the plan of CI gives a job, whose absence is a problem, or those without the modules whose steps need an external service (see EveryModuleApps).

Returns the exit code: 0 if every app was generated with every module and every step that the options of CI do not leave for later, 1 otherwise, and 64, without generating an app, when name starts with -, which smf create would take for an option. The log of commands gets what happens, and their create generates each app; they analyze and test nothing here.

Implementation

Future<int> createEveryModuleApps(
  List<SmfModule> modules, {
  required String directory,
  required String name,
  List<String> options = const [],
  Map<String, String?> roleOptions = const {},
  EveryModuleApps apps = const EveryModuleApps(),
  MatrixCommands commands = const MatrixCommands(),
}) async {
  // coverage:ignore-start
  // The defaults print to the terminal and create the apps with smf, as CI
  // does; the tests give their own.
  final say = commands.log ?? _print;
  final generate = commands.create ?? _smfCreate(modules);
  // coverage:ignore-end
  if (name.startsWith('-')) {
    say(
      'The name of the apps, $name, starts with -, so smf create would take '
      'it for an option: give the name right after the directory, and the '
      'options of smf create after it.',
    );
    return 64;
  }
  final (apps: every, :failed) = await everyModuleAppsOf(
    modules,
    roleOptions: roleOptions,
    withoutExternalSteps: apps.withoutExternalSteps,
  );
  final selected = apps.selection.select(every, modules);
  final problems = [
    for (final result in failed)
      '${result.contractCase}: ${result.errors.join('; ')}',
    ...apps.selection.problemsOf(selected),
  ];
  for (final app in selected) {
    final packageName = app.packageName(name);
    say('\n=== $packageName: $app');
    final (_, appProblems) = await _generate(
      generate,
      app,
      packageName,
      directory,
      options,
    );
    problems.addAll(appProblems);
  }
  return _exitCode(problems, say);
}