Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CP-3183 Create dart_dev task to allow for tasks to run con-currently #199

Merged
merged 7 commits into from
Jan 25, 2017

Conversation

jayudey-wf
Copy link
Contributor

@jayudey-wf jayudey-wf commented Dec 16, 2016

Issue

  • There is no way to easily run dart tasks asynchronously.

Changes

Source:

  • Created a task to allow for a user to specify dart commands that they wish to run in parallel.

Tests:

  • added

Areas of Regression

  • n/a (new tasks was added)

Testing

  • passing CI
  • install into this branch into a repo and ensure that the tasks complete as expected (I tried doing this on travis CI for dart_dev and I don't think the instance could handle running the tasks)

Code Review

@Workiva/web-platform-pp

@rmconsole-wf rmconsole-wf changed the title Create dart_dev task to allow for tasks to run con-currently CP-3183 Create dart_dev task to allow for tasks to run con-currently Dec 16, 2016
Copy link
Member

@maxwellpeterson-wf maxwellpeterson-wf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks awesome!
Just a few small nits. I can't wait to use this.

Future<TaskRunner> runTasks({List<String> tasksToRun}) async {
var taskGroup = new TaskGroup(tasksToRun);
await taskGroup.startTaskGroup();
taskGroup.taskGroupOutput();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider renaming this method to output() to reduce redundancy in the name

bool successful;

TaskRunner(int exitCode, String this.stdout, String this.stderr) {
exitCode == 0 ? this.successful = true : this.successful = false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be simplified to:

this.successful = exitCode == 0;

}

/// Begin each subtask and wait for completion
startTaskGroup() async {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider renaming this method to start


const List<String> defaultTasks = const [
'pub run dart_dev format --check',
'pub run dart_dev analyze'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add test to the default list?

@@ -96,6 +96,7 @@ local tasks.
- **Applying a License to Source Files:** copies a LICENSE file to all applicable files.
- **Generate a test runner file:** that allows for faster test execution.
- **Running dart unit tests on Sauce Labs** compiles dart unit tests that can be run in the browser and executes them on various platforms using Sauce Labs.
- **Running concurrent dart commands** allows for continuous integration systems to run concurrently rather then serially.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"allows continuous integration..."

@@ -251,6 +252,7 @@ ddev examples
ddev format
ddev gen-test-runner
ddev saucelabs
ddev task-runner
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#nit the other task names are imperative, "format", "test". Obviously there are exceptions ("saucelabs"). I prefer the former. Could we change the name to "run-task" or "run-async" or something?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given the description above it might actually be nice to name the command something to do with CI. Liked run-ci or something, to make it clear that this isn't meant to be used interactively.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I could go either way on this update. I'll let the other reviewers weigh in since it could theoretically be used outside of CI (even though I agree that is the most common use case)


TaskProcess taskProcess;

SubTask(String task) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SubTask(this.command);


class SubTask {
/// Process to be executed
String command;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can mark this final.

@codecov-io
Copy link

codecov-io commented Jan 12, 2017

Current coverage is 23.56% (diff: 100%)

Merging #199 into master will not change coverage

@@             master       #199   diff @@
==========================================
  Files             7          7          
  Lines           157        157          
  Methods           0          0          
  Messages          0          0          
  Branches          0          0          
==========================================
  Hits             37         37          
  Misses          120        120          
  Partials          0          0          

Powered by Codecov. Last update 6de67f6...c8c5d50

@maxwellpeterson-wf
Copy link
Member

+1

Copy link
Contributor

@bencampbell-wf bencampbell-wf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had a few questions and some nits.

@@ -96,6 +96,7 @@ local tasks.
- **Applying a License to Source Files:** copies a LICENSE file to all applicable files.
- **Generate a test runner file:** that allows for faster test execution.
- **Running dart unit tests on Sauce Labs** compiles dart unit tests that can be run in the browser and executes them on various platforms using Sauce Labs.
- **Running concurrent dart commands** allows continuous integration systems to run concurrently rather then serially.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🌵 The upper elements in the use a colon, the bottom two do not.

}
});

await process.done;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❓ Can you explain the necessity of this line? This appears to the be only consumer of the final Future value on TaskRunner Class .

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that is waiting for the TaskProcess that is checking for the task that is executing the task runner https://github.com/Workiva/dart_dev/pull/199/files#diff-f47564d08708b67413d675e327f15302R34

/// TaskGroup stderr
String taskGroupStderr = '';

TaskGroup(List<String> this.subTaskCommands) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think you need the type here if you are referring to the class member subTaskCommands.


class TaskGroup {
/// List of the individual subtasks executed
List<String> subTaskCommands = [];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🌵 List<String> subTaskCommands = <String>[];

List<String> subTaskCommands = [];

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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🌵 List<SubTask> subTasks = <SubTask>[];

}

/// Begin each subtask and wait for completion
start() async {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🌵 `void start() async {

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Future start() async ;)

/// Determine if subtasks completed successfully
Future<int> checkExitCodes() async {
for (SubTask task in subTasks) {
if (await task.taskProcess.exitCode != 0) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔮 Is it good practice to include awaits in a if statement?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO I don't see a problem with it ¯_(ツ)_/¯

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've always kind of avoided the practice and rarely see it done elsewhere. Its no biggie, I thought I would just ask.

var args = ['run', 'dart_dev', 'task-runner'];
TaskProcess process =
new TaskProcess('pub', args, workingDirectory: projectPath);
List<String> failedTasks = [];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🌵 List<String> failedTasks = <String>[];

TaskProcess process =
new TaskProcess('pub', args, workingDirectory: projectPath);
List<String> failedTasks = [];
List<String> successfulTasks = [];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🌵 List<String> successfulTasks = <String>[];


TaskRunner task = await runTasks(tasksToRun: tasksToRun);

reporter.logGroup('Tasks run: \'${tasksToRun.join('\', \'')}\'',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😄 So much escaping!

@maxwellpeterson-wf
Copy link
Member

+1

<tr>
<td><code>tasksToRun</code></td>
<td><code>List&lt;String&gt;</code></td>
<td><code>['pub run dart_dev format --check','pub run dart_dev analyze']</code></td>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason not to default it to run the unit tests too?

@maxwellpeterson-wf
Copy link
Member

+1


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

Future<TaskRunner> runTasks({List<String> tasksToRun}) async {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This param shouldn't be optional since you're not defaulting it to anything in that scenario.

@@ -251,6 +252,7 @@ ddev examples
ddev format
ddev gen-test-runner
ddev saucelabs
ddev run-ci
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The command is task-runner

@@ -262,6 +264,7 @@ pub run dart_dev examples
pub run dart_dev format
pub run dart_dev gen-test-runner
pub run dart_dev saucelabs
pub run dart_dev run-ci
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

<tr>
<td><code>tasksToRun</code></td>
<td><code>List&lt;String&gt;</code></td>
<td><code>['pub run dart_dev format --check','pub run dart_dev analyze','pub run dart_dev test']</code></td>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you might want to include examples of running other things besides dart_dev (if it indeed supports that, which it looks like it does)

final String command;

/// A string consisting of all the subtask's output
String taskOutput = '';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does buffering the output in a string mean we can't display output from subtasks as it happens but instead all at once once it succeeds or fails? No change requested here, just wondering.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, it comes all at once

List longList = [
'one',
'two',
'three', 'four',
Copy link
Member

@robbecker-wf robbecker-wf Jan 19, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

total #nit why is four not on its own line?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is to cause the task to fail to verify that a failed task ran fails the parent task

@robbecker-wf
Copy link
Member

+1 with a question and an optional nit. FWIW I'm ok with the name task-runner.

@maxwellpeterson-wf
Copy link
Member

+1

@maxwellpeterson-wf
Copy link
Member

+1

1 similar comment
@evanweible-wf
Copy link
Contributor

+1

@maxwellpeterson-wf
Copy link
Member

+10

@maxwellpeterson-wf
Copy link
Member

QA +1

  • Testing instruction
  • Dev +1's
  • Dev/QA +10 with detail of what was tested
  • Unit tests created/updated
  • All unit tests pass

Merging into master.

@maxwellpeterson-wf maxwellpeterson-wf merged commit 5c429fe into master Jan 25, 2017
@maxwellpeterson-wf maxwellpeterson-wf deleted the task-runner branch January 25, 2017 17:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants