Group dependencies

An Engage file with a handful of groups and tasks might look like this:

interpreter = ["bash", "-euo", "pipefail", "-c"]

[[task]]
name = "cargo"
group = "versions"
script = "cargo --version"

[[task]]
name = "cargo-fmt"
group = "versions"
script = "cargo fmt --version"
depends = ["cargo"]

[[task]]
name = "cargo-clippy"
group = "versions"
script = "cargo clippy --version"
depends = ["cargo"]

[[task]]
name = "rustc"
group = "versions"
script = "rustc --version"
depends = ["cargo-fmt", "cargo-clippy"]

[[task]]
name = "wait"
group = "database"
# Pretend this is a command that exists
script = "wait-for-database-to-be-ready"

[[task]]
name = "migrate"
group = "database"
# Pretend this is a command that exists too
script = "run-database-migrations"
depends = ["wait"]

[[task]]
name = "cargo"
group = "tests"
script = "cargo test"

Which results in this graph:

Graph of Engage file 3

This will correctly wait for the database to become ready before running the migrations, but it will also start the test suite before either of those have finished! This can be fixed by using group dependencies like so:

interpreter = ["bash", "-euo", "pipefail", "-c"]

[[task]]
name = "cargo"
group = "versions"
script = "cargo --version"

[[task]]
name = "cargo-fmt"
group = "versions"
script = "cargo fmt --version"
depends = ["cargo"]

[[task]]
name = "cargo-clippy"
group = "versions"
script = "cargo clippy --version"
depends = ["cargo"]

[[task]]
name = "rustc"
group = "versions"
script = "rustc --version"
depends = ["cargo-fmt", "cargo-clippy"]

[[task]]
name = "wait"
group = "database"
# Pretend this is a command that exists
script = "wait-for-database-to-be-ready"

[[task]]
name = "migrate"
group = "database"
# Pretend this is a command that exists too
script = "run-database-migrations"
depends = ["wait"]

# New section!
[[group]]
name = "tests"
depends = ["database"]

[[task]]
name = "cargo"
group = "tests"
script = "cargo test"

Which results in this graph:

Graph of Engage file 4

Here, it can be seen that the database group must finish before the tests group can start.

Groups encapsulate multiple tasks into a single unit, and group dependencies allow depending upon those units as a whole. This makes it easy to reuse groups of tasks with their intended ordering by depending on the entire group. Without these features, reuse of mulitple tasks becomes difficult as one must recall which tasks belong to the "group" each time that "group" needs to be depended upon, which is error-prone.