Unverified Commit 295530dc authored by Ian Hickson's avatar Ian Hickson Committed by GitHub

Some minor cleanup in devicelab (#36571)

parent d28f3c7c
...@@ -107,7 +107,7 @@ final ArgParser _argParser = ArgParser() ...@@ -107,7 +107,7 @@ final ArgParser _argParser = ArgParser()
'stage', 'stage',
abbr: 's', abbr: 's',
help: 'Name of the stage. Runs all tasks for that stage. ' help: 'Name of the stage. Runs all tasks for that stage. '
'The tasks and their stages are read from manifest.yaml.', 'The tasks and their stages are read from manifest.yaml.',
) )
..addFlag( ..addFlag(
'all', 'all',
......
...@@ -11,6 +11,7 @@ import 'package:flutter_devicelab/framework/utils.dart'; ...@@ -11,6 +11,7 @@ import 'package:flutter_devicelab/framework/utils.dart';
import 'package:path/path.dart' as path; import 'package:path/path.dart' as path;
Future<void> main() async { Future<void> main() async {
final String dot = Platform.isWindows ? '-' : '•';
await task(() async { await task(() async {
final Stopwatch clock = Stopwatch()..start(); final Stopwatch clock = Stopwatch()..start();
final Process analysis = await startProcess( final Process analysis = await startProcess(
...@@ -27,9 +28,9 @@ Future<void> main() async { ...@@ -27,9 +28,9 @@ Future<void> main() async {
print('analyzer stdout: $entry'); print('analyzer stdout: $entry');
if (entry == 'Building flutter tool...') { if (entry == 'Building flutter tool...') {
// ignore this line // ignore this line
} else if (entry.startsWith('info • Document all public members •')) { } else if (entry.startsWith('info $dot Document all public members $dot')) {
publicMembers += 1; publicMembers += 1;
} else if (entry.startsWith('info •') || entry.startsWith('warning •') || entry.startsWith('error •')) { } else if (entry.startsWith('info $dot') || entry.startsWith('warning $dot') || entry.startsWith('error $dot')) {
otherErrors += 1; otherErrors += 1;
} else if (entry.contains(' (ran in ') && !sawFinalLine) { } else if (entry.contains(' (ran in ') && !sawFinalLine) {
// ignore this line once // ignore this line once
......
...@@ -256,9 +256,18 @@ Future<ProcessResult> _resultOfGradleTask({String workingDirectory, String task, ...@@ -256,9 +256,18 @@ Future<ProcessResult> _resultOfGradleTask({String workingDirectory, String task,
'app:$task', 'app:$task',
...?options, ...?options,
]; ];
final String gradle = Platform.isWindows ? 'gradlew.bat' : './gradlew'; final String gradle = path.join(workingDirectory, Platform.isWindows ? 'gradlew.bat' : './gradlew');
print('Running Gradle: ${path.join(workingDirectory, gradle)} ${args.join(' ')}'); print('┌── $gradle');
print(File(path.join(workingDirectory, gradle)).readAsStringSync()); print('│ ' + File(path.join(workingDirectory, gradle)).readAsLinesSync().join('\n│ '));
print('└─────────────────────────────────────────────────────────────────────────────────────');
print(
'Running Gradle:\n'
' Executable: $gradle\n'
' Arguments: ${args.join(' ')}\n'
' Working directory: $workingDirectory\n'
' JAVA_HOME: $javaHome\n'
''
);
return Process.run( return Process.run(
gradle, gradle,
args, args,
......
...@@ -14,11 +14,6 @@ import 'package:stack_trace/stack_trace.dart'; ...@@ -14,11 +14,6 @@ import 'package:stack_trace/stack_trace.dart';
import 'running_processes.dart'; import 'running_processes.dart';
import 'utils.dart'; import 'utils.dart';
/// Maximum amount of time a single task is allowed to take to run.
///
/// If exceeded the task is considered to have failed.
const Duration _kDefaultTaskTimeout = Duration(minutes: 15);
/// Represents a unit of work performed in the CI environment that can /// Represents a unit of work performed in the CI environment that can
/// succeed, fail and be retried independently of others. /// succeed, fail and be retried independently of others.
typedef TaskFunction = Future<TaskResult> Function(); typedef TaskFunction = Future<TaskResult> Function();
...@@ -55,7 +50,7 @@ class _TaskRunner { ...@@ -55,7 +50,7 @@ class _TaskRunner {
(String method, Map<String, String> parameters) async { (String method, Map<String, String> parameters) async {
final Duration taskTimeout = parameters.containsKey('timeoutInMinutes') final Duration taskTimeout = parameters.containsKey('timeoutInMinutes')
? Duration(minutes: int.parse(parameters['timeoutInMinutes'])) ? Duration(minutes: int.parse(parameters['timeoutInMinutes']))
: _kDefaultTaskTimeout; : null;
final TaskResult result = await run(taskTimeout); final TaskResult result = await run(taskTimeout);
return ServiceExtensionResponse.result(json.encode(result.toJson())); return ServiceExtensionResponse.result(json.encode(result.toJson()));
}); });
...@@ -90,7 +85,10 @@ class _TaskRunner { ...@@ -90,7 +85,10 @@ class _TaskRunner {
).toSet(); ).toSet();
beforeRunningDartInstances.forEach(print); beforeRunningDartInstances.forEach(print);
TaskResult result = await _performTask().timeout(taskTimeout); Future<TaskResult> futureResult = _performTask();
if (taskTimeout != null)
futureResult = futureResult.timeout(taskTimeout);
TaskResult result = await futureResult;
section('Checking running Dart$exe processes after task...'); section('Checking running Dart$exe processes after task...');
final List<RunningProcessInfo> afterRunningDartInstances = await getRunningProcesses( final List<RunningProcessInfo> afterRunningDartInstances = await getRunningProcesses(
......
...@@ -11,10 +11,6 @@ import 'package:vm_service_client/vm_service_client.dart'; ...@@ -11,10 +11,6 @@ import 'package:vm_service_client/vm_service_client.dart';
import 'package:flutter_devicelab/framework/utils.dart'; import 'package:flutter_devicelab/framework/utils.dart';
/// Slightly longer than task timeout that gives the task runner a chance to
/// clean-up before forcefully quitting it.
const Duration taskTimeoutWithGracePeriod = Duration(minutes: 26);
/// Runs a task in a separate Dart VM and collects the result using the VM /// Runs a task in a separate Dart VM and collects the result using the VM
/// service protocol. /// service protocol.
/// ///
...@@ -71,21 +67,11 @@ Future<Map<String, dynamic>> runTask( ...@@ -71,21 +67,11 @@ Future<Map<String, dynamic>> runTask(
stderr.writeln('[$taskName] [STDERR] $line'); stderr.writeln('[$taskName] [STDERR] $line');
}); });
String waitingFor = 'connection';
try { try {
final VMIsolateRef isolate = await _connectToRunnerIsolate(await uri.future); final VMIsolateRef isolate = await _connectToRunnerIsolate(await uri.future);
waitingFor = 'task completion'; final Map<String, dynamic> taskResult = await isolate.invokeExtension('ext.cocoonRunTask');
final Map<String, dynamic> taskResult = await runner.exitCode;
await isolate.invokeExtension('ext.cocoonRunTask').timeout(taskTimeoutWithGracePeriod);
waitingFor = 'task process to exit';
await runner.exitCode.timeout(const Duration(seconds: 60));
return taskResult; return taskResult;
} on TimeoutException catch (timeout) {
runner.kill(ProcessSignal.sigint);
return <String, dynamic>{
'success': false,
'reason': 'Timeout in runner.dart waiting for $waitingFor: ${timeout.message}',
};
} finally { } finally {
if (!runnerFinished) if (!runnerFinished)
runner.kill(ProcessSignal.sigkill); runner.kill(ProcessSignal.sigkill);
...@@ -104,14 +90,7 @@ Future<VMIsolateRef> _connectToRunnerIsolate(Uri vmServiceUri) async { ...@@ -104,14 +90,7 @@ Future<VMIsolateRef> _connectToRunnerIsolate(Uri vmServiceUri) async {
pathSegments.add('ws'); pathSegments.add('ws');
final String url = vmServiceUri.replace(scheme: 'ws', pathSegments: final String url = vmServiceUri.replace(scheme: 'ws', pathSegments:
pathSegments).toString(); pathSegments).toString();
final DateTime started = DateTime.now(); final Stopwatch stopwatch = Stopwatch()..start();
// TODO(yjbanov): due to lack of imagination at the moment the handshake with
// the task process is very rudimentary and requires this small
// delay to let the task process open up the VM service port.
// Otherwise we almost always hit the non-ready case first and
// wait a whole 1 second, which is annoying.
await Future<void>.delayed(const Duration(milliseconds: 100));
while (true) { while (true) {
try { try {
...@@ -127,17 +106,9 @@ Future<VMIsolateRef> _connectToRunnerIsolate(Uri vmServiceUri) async { ...@@ -127,17 +106,9 @@ Future<VMIsolateRef> _connectToRunnerIsolate(Uri vmServiceUri) async {
throw 'not ready yet'; throw 'not ready yet';
return isolate; return isolate;
} catch (error) { } catch (error) {
const Duration connectionTimeout = Duration(seconds: 10); if (stopwatch.elapsed > const Duration(seconds: 10))
if (DateTime.now().difference(started) > connectionTimeout) { print('VM service still not ready after ${stopwatch.elapsed}: $error\nContinuing to retry...');
throw TimeoutException( await Future<void>.delayed(const Duration(milliseconds: 50));
'Failed to connect to the task runner process',
connectionTimeout,
);
}
print('VM service not ready yet: $error');
const Duration pauseBetweenRetries = Duration(milliseconds: 200);
print('Will retry in $pauseBetweenRetries.');
await Future<void>.delayed(pauseBetweenRetries);
} }
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment