step method
Runs commands as one step into the log logName, recording its
outcome. counts reads the test counts of the last progress line into
the detail; produces is a file the step must leave behind, so an exit
code of 0 with nothing built is red.
Implementation
Future<void> step(
String stage,
String subject,
String logName,
List<CiCommand> commands, {
bool needsFlutter = false,
bool counts = false,
String? produces,
}) async {
final logPath = p.join(runDir, logName);
final label = subject == stage ? '[$stage]' : '[$stage] $subject';
console.write('$label …');
if (needsFlutter && flutter == null) {
console.writeln();
fail(
stage,
subject,
logName,
'flutter not found — put it on PATH or set FLUTTER_ROOT',
);
return;
}
final result = await runner.run(commands, logPath: logPath);
var ok = result.ok;
var detail = '';
if (counts) {
final c = parseCiTestCounts(result.tail);
detail = c?.toString() ?? 'no test progress line';
}
if (ok && produces != null && !File(produces).existsSync()) {
ok = false;
detail = 'exit 0 but no ${relative(produces)}';
}
if (!ok && detail.isEmpty) detail = 'exit ${result.exitCode}';
if (!ok && counts && result.exitCode != 0) {
detail = '$detail, exit ${result.exitCode}';
}
_record(stage, subject, logPath, ok, detail, result.elapsed);
console.writeln(
' ${ok ? 'green' : 'RED'} $detail '
'(${formatCiDuration(result.elapsed)})'
'${ok ? '' : ' -> ${relative(logPath)}'}',
);
}