Skip to content

Commit

Permalink
Merge pull request #215 from Workiva/task-runner-improvements
Browse files Browse the repository at this point in the history
WP-4112 Updating task-runner task based on feedback
  • Loading branch information
maxwellpeterson-wf authored May 19, 2017
2 parents 9500db6 + c4af51b commit 57e6c8b
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 47 deletions.
73 changes: 35 additions & 38 deletions lib/src/tasks/task_runner/api.dart
Original file line number Diff line number Diff line change
@@ -1,29 +1,27 @@
import 'dart:async';
import 'dart:io';

import 'package:dart_dev/util.dart' show reporter, TaskProcess;

import 'package:dart_dev/src/tasks/task.dart';

Future<TaskRunner> runTasks(tasksToRun) async {
var taskGroup = new TaskGroup(tasksToRun);
await taskGroup.start();
taskGroup.output();
await taskGroup.run();

TaskRunner task = new TaskRunner(await taskGroup.checkExitCodes(),
taskGroup.taskGroupStdout, taskGroup.taskGroupStderr);
TaskRunner task = new TaskRunner(taskGroup.failedTask, taskGroup.successful,
taskGroup.taskGroupStderr, taskGroup.tasksNotCompleted);
return task;
}

class TaskRunner extends Task {
final Future done = new Future.value();
final String stdout;
String failedTask;
final String stderr;
bool successful;
List<String> tasksNotCompleted;

TaskRunner(int exitCode, String this.stdout, String this.stderr) {
this.successful = exitCode == 0;
}
TaskRunner(this.failedTask, bool this.successful, String this.stderr,
List<String> this.tasksNotCompleted);
}

class SubTask {
Expand All @@ -50,25 +48,30 @@ class SubTask {
this.taskOutput += '\n$line';
});
taskProcess.stderr.listen((line) {
this.taskOutput += '\n$line';
this.taskError += '\n$line';
});
}
}

class TaskGroup {
/// Failed task
String failedTask = '';

/// List of the individual subtasks executed
List<String> subTaskCommands = <String>[];

/// List of the subtasks making up the TaskGroup
List<SubTask> subTasks = <SubTask>[];

/// TaskGroup stdout
String taskGroupStdout = '';

/// TaskGroup stderr
String taskGroupStderr = '';

/// Status of TaskGroup
bool successful = true;

/// Tasks cancelled prior to completion
List<String> tasksNotCompleted = [];

TaskGroup(this.subTaskCommands) {
for (String taskCommand in subTaskCommands) {
SubTask task = new SubTask(taskCommand);
Expand All @@ -77,42 +80,36 @@ class TaskGroup {
}

/// Begin each subtask and wait for completion
Future start() async {
Future run() async {
List<Future> futures = <Future>[];
var timer = new Timer.periodic(new Duration(seconds: 30), (_) {
reporter.log('Tasks running...');
});
for (SubTask task in subTasks) {
task.startProcess();
futures.add(task.taskProcess.exitCode);
task.taskProcess.exitCode.then((int exitCode) {
reporter.log(task.taskOutput);
// if the task runner kills outstanding tasks it currently sets the exit code to -15
if (exitCode != 0 && exitCode != -15) {
failedTask = task.command;
successful = false;
reporter.log(task.taskError);
this.taskGroupStderr +=
'The command, ${task.command}, contained this in the stderr; ${task.taskOutput}\n ${task.taskError}\n';
for (SubTask task in subTasks) {
task.taskProcess.kill();
}
}
});
futures.add(task.taskProcess.done);
}
await Future.wait(futures);
timer.cancel();
}

/// Retrieve output from subtasks
void output() {
String output = '';
for (SubTask task in subTasks) {
output += task.taskOutput + '\n';
}
this.taskGroupStdout = output;
}

/// Determine if subtasks completed successfully
Future<int> checkExitCodes() async {
for (SubTask task in subTasks) {
if (await task.taskProcess.exitCode != 0) {
exitCode = 1;
this.taskGroupStderr +=
'The command, ${task.command}, contained this in the stderr; \n${task.taskError}\n';
if (await task.taskProcess.exitCode == -15) {
tasksNotCompleted.add(task.command);
}
}
if (exitCode != 0) {
this.taskGroupStderr =
'One of your subtasks exited with a non-zero exit code. '
'See the output below for more information: \n${this.taskGroupStderr}';
}
return exitCode;
timer.cancel();
}
}
13 changes: 9 additions & 4 deletions lib/src/tasks/task_runner/cli.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,19 @@ class TaskRunnerCli extends TaskCli {

TaskRunner task = await runTasks(tasksToRun);

reporter.logGroup('Tasks run: \'${tasksToRun.join('\', \'')}\'',
output: task.stdout);
reporter.logGroup('Tasks run: \'${tasksToRun.join('\', \'')}\'');
if (!task.successful) {
reporter.logGroup('Failure output:', error: task.stderr);
reporter.logGroup(
'Failure output: '
'One of your subtasks exited with a non-zero exit code. '
'See the output below for more information:',
error: task.stderr);
}

return task.successful
? new CliResult.success('Tasks completed successfuly.')
: new CliResult.fail('Some task / tasks failed.');
: new CliResult.fail('Some task failed: ${task.failedTask}'
'\n\nThe following tasks were stopped prior to completion:'
'\n${task.tasksNotCompleted.join('\n')}');
}
}
12 changes: 9 additions & 3 deletions test/integration/task_runner_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const String projectPassingTasks = 'test_fixtures/task_runner/passing_tasks';
const String projectFailingTasks = 'test_fixtures/task_runner/failing_tasks';

const String failedFormatting = 'The Dart formatter needs to be run.';
const String failedTesting = 'Some tests failed.';
const String successfulFormatting = 'Your Dart code is good to go!';
const String successfulAnalysis = 'Analysis completed.';
const String successfulTesting = 'All tests passed!';
Expand All @@ -37,6 +38,8 @@ Future<TasksRun> runTasks(String projectPath) async {
List<String> successfulTasks = <String>[];

process.stdout.listen((line) {
// leaving this logging in to help debug issues
print(line);
if (line.contains(successfulFormatting)) {
successfulTasks.add(successfulFormatting);
}
Expand All @@ -49,6 +52,9 @@ Future<TasksRun> runTasks(String projectPath) async {
if (line.contains(successfulTesting)) {
successfulTasks.add(successfulTesting);
}
if (line.contains(failedTesting)) {
failedTasks.add(failedTesting);
}
});

await process.done;
Expand All @@ -73,13 +79,13 @@ void main() {
expect(tasks.successfulTasks.contains(successfulTesting), isTrue);
});

test('a task failed', () async {
test('a task failed causing the task runner to exit', () async {
TasksRun tasks = await runTasks(projectFailingTasks);
expect(tasks.exitCode, isNonZero);
expect(tasks.successfulTasks.contains(successfulAnalysis), isTrue);
expect(tasks.successfulTasks.contains(successfulFormatting), isFalse);
expect(tasks.successfulTasks.contains(successfulTesting), isFalse);
expect(tasks.failedTasks.contains(failedFormatting), isTrue);
expect(tasks.successfulTasks.contains(successfulTesting), isTrue);
expect(tasks.failedTasks.contains(failedTesting), isFalse);
});
});
}
3 changes: 2 additions & 1 deletion test_fixtures/coverage/functional_test/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
name: functional_test
version: 0.0.0
dev_dependencies:
analyzer: 0.29.7
browser: any
coverage: "^0.7.2"
coverage: "^0.7.3"
test: '^0.12.0'
webdriver: '^1.0.0'
dart_dev:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import 'dart:async';

import 'package:test/test.dart';

void main() {
test('passes', () {
test('passes', () async {
await new Future.delayed(new Duration(seconds:5));
expect(true, isTrue);
});
}

0 comments on commit 57e6c8b

Please sign in to comment.