ciToolRunner function

ToolRunner ciToolRunner({
  1. required ToolDefinition tool,
  2. required Future<String> runStages(
    1. List<String> stages,
    2. StringSink console
    ),
  3. StringSink? console,
})

Builds the runner of a CI tool.

Every stage command shares one executor: the first one the runner invokes hands all stages named on the command line, in the order given, to runStages, and turns the summary line it returns into the result — green when it starts with CI GREEN. The rest find the work done. (Run one at a time, the commands would stop at the first red, which is the wrong policy for a verification run: every red is worth knowing.)

Implementation

ToolRunner ciToolRunner({
  required ToolDefinition tool,
  required Future<String> Function(List<String> stages, StringSink console)
  runStages,
  StringSink? console,
}) {
  var done = false;
  Future<ToolResult> runAll(CliArgs args) async {
    if (done) return const ToolResult.success();
    done = true;
    final requested = [
      for (final name in args.commands) tool.findCommand(name)!.name,
    ];
    final out = console ?? stdout;
    final line = await runStages(requested, out);
    out.writeln(line);
    return line.startsWith('CI GREEN')
        ? const ToolResult.success()
        : ToolResult.failure(line);
  }

  final executor = CallbackExecutor(
    onExecute: (context, args) async => ItemResult.skipped(
      path: context.path,
      name: context.name,
      message: 'stages do not traverse',
    ),
    onExecuteWithoutTraversal: runAll,
  );
  return ToolRunner(
    tool: tool,
    executors: {for (final command in tool.commands) command.name: executor},
  );
}