diff --git a/tools/pkg/engine_build_configs/lib/src/build_config_runner.dart b/tools/pkg/engine_build_configs/lib/src/build_config_runner.dart index 765b1fc3422e2..dffc8c8c1823a 100644 --- a/tools/pkg/engine_build_configs/lib/src/build_config_runner.dart +++ b/tools/pkg/engine_build_configs/lib/src/build_config_runner.dart @@ -76,7 +76,13 @@ final class RunnerProgress extends RunnerEvent { /// A [RunnerEvent] representing the result of a command. final class RunnerResult extends RunnerEvent { - RunnerResult(super.name, super.command, super.timestamp, this.result); + RunnerResult( + super.name, + super.command, + super.timestamp, + this.result, { + this.okMessage = 'OK', + }); /// The resuilt of running the command. final ProcessRunnerResult result; @@ -84,10 +90,13 @@ final class RunnerResult extends RunnerEvent { /// Whether the command was successful. late final bool ok = result.exitCode == 0; + /// The message to print on a successful result. The default is 'OK'. + final String okMessage; + @override String toString() { if (ok) { - return '[${_timestamp(timestamp)}][$name]: OK'; + return '[${_timestamp(timestamp)}][$name]: $okMessage'; } final StringBuffer buffer = StringBuffer(); buffer.writeln('[$timestamp][$name]: FAILED'); @@ -331,6 +340,38 @@ final class BuildRunner extends Runner { return p.join(engineSrcDir.path, 'flutter', 'buildtools', platformDir); }(); + // Returns the second line of output from reproxystatus, which contains + // RBE statistics, or null if something goes wrong. + Future _reproxystatus() async { + final String reclientPath = p.join(_buildtoolsPath, 'reclient'); + final String exe = platform.isWindows ? '.exe' : ''; + final String restatsPath = p.join(reclientPath, 'reproxystatus$exe'); + final ProcessRunnerResult restatsResult; + if (dryRun) { + restatsResult = ProcessRunnerResult( + 0, // exit code. + utf8.encode('OK\nOK\n'), // stdout. + [], // stderr. + utf8.encode('OK\nOK\n'), // combined, + pid: 0, // pid. + ); + } else { + restatsResult = await processRunner.runProcess( + [restatsPath, '-color', 'off'], + failOk: true, + ); + } + if (restatsResult.exitCode != 0) { + return null; + } + // The second line of output has the stats. + final List lines = restatsResult.stdout.split('\n'); + if (lines.length < 2) { + return null; + } + return lines[1]; + } + Future _bootstrapRbe( RunnerEventHandler eventHandler, { bool shutdown = false, @@ -382,11 +423,16 @@ final class BuildRunner extends Runner { failOk: true, ); } + String okMessage = bootstrapResult.stdout.trim(); + if (shutdown) { + okMessage = await _reproxystatus() ?? okMessage; + } eventHandler(RunnerResult( '${build.name}: RBE ${shutdown ? 'shutdown' : 'startup'}', bootstrapCommand, DateTime.now(), bootstrapResult, + okMessage: okMessage, )); return bootstrapResult.exitCode == 0; } diff --git a/tools/pkg/engine_build_configs/test/build_config_runner_test.dart b/tools/pkg/engine_build_configs/test/build_config_runner_test.dart index 387191a761c50..bdfd50ad4f809 100644 --- a/tools/pkg/engine_build_configs/test/build_config_runner_test.dart +++ b/tools/pkg/engine_build_configs/test/build_config_runner_test.dart @@ -230,6 +230,7 @@ void main() { expect(events[6].name, equals('$buildName: RBE shutdown')); expect(events[7] is RunnerResult, isTrue); expect(events[7].name, equals('$buildName: RBE shutdown')); + expect((events[7] as RunnerResult).okMessage, equals('OK')); }); test('GlobalBuildRunner skips GN when runGn is false', () async {