aggregate: run steps in parallel

Performs the given steps in parallel.

If any sub-steps in an aggregate result in an error, the aggregate step as a whole is considered to have errored.

Similarly, when aggregating task steps, if any fail, the aggregate step will fail. This is useful for build matrixes:

plan:
- get: some-repo
- aggregate:
  - task: unit-windows
    file: some-repo/ci/windows.yml
  - task: unit-linux
    file: some-repo/ci/linux.yml
  - task: unit-darwin
    file: some-repo/ci/darwin.yml

The aggregate step is also useful for performing arbitrary steps in parallel, for the sake of speeding up the build. It is often used to fetch all dependent resources together:

plan:
- aggregate:
  - get: component-a
  - get: component-b
  - get: integration-suite
- task: integration
  file: integration-suite/task.yml