stylemistake / runner

Simple, lightweight task runner for Bash.
Other
166 stars 15 forks source link

runner_depends (semantics for describing task dependencies) #16

Closed stylemistake closed 5 years ago

stylemistake commented 8 years ago

This commit uses a simple alias to bask_sequence, which is bask_depends. It looks like this:

task_foo() {
  bask_depends bar # runs 'bar', then continues with the rest
  echo 'running foo...'
}

task_bar() {
  echo 'running bar...'
}

This is a very good abstraction; but a simple alias just ain't cutting it.

The problem is that it doesn't know which task has already completed, thus it can run the same task twice; It doesn't care about circular dependencies, too, so you can end up with an endless loop going nowhere.

task_foo() {
  echo 'running foo...'
}

task_bar() {
  bask_depends foo # runs foo before bar
  echo 'running bar...'
}

task_baz() {
  bask_depends foo # runs foo before baz
  echo 'running baz..'
}

task_default() {
  bask_depends bar baz
  ## results in: foo -> bar -> foo -> baz
}

Solution is to keep this declarative syntax, but make it work in such a way that every task is run only once. If task has completed before, don't run it again. Additionally, tasks should be running with maximum concurrency by default.

If there is a circular dependency, drop the outer most dependency and show a warning. This is the default behaviour for GNU Make:

all: one two

one: two
    touch one

two: one
    touch two
$ make
make: Circular two <- one dependency dropped.
touch two
touch one

To implement this feature, we need to implement a DAG in pure Bash first. I believe this is the only proper way to do it, but I'm still researching how other task runners did approach this thing.

stylemistake commented 8 years ago

I have just discovered, that GNU coreutils has a thing for topological sorting: tsort.

Just by sorting the dependency graph with tsort and feeding into runner_sequence, it will do all the tasks in the right order.

mbrodala commented 8 years ago

I am currently playing around with a similar idea these days and quickly hacked up this.

This way the dependencies are declared from the outside which is pretty common IMO. Of course it protects neither against multiple task runs nor circular dependencies. Just wanted to be sure it's recorded somewhere. ;-)

stylemistake commented 8 years ago

Flow with runner_depends:

stylemistake commented 5 years ago

Closing for now.