(Meta) Add top-level "job" with "tasks" in Meltano.yml, refactored from just Schedules to Jobs+Schedules

#### Update 2022-05-26

* Job support added in https://gitlab.com/meltano/meltano/-/merge_requests/2629 - no related issue as MR was scoped down.
* Support for schedules tracked in https://gitlab.com/meltano/meltano/-/issues/3479

----


Currently a "Schedule" in `meltano.yml` is called a "Pipeline" in the UI. (#1673) 

The proposed change is to add `jobs` construct, with one or more steps - similar to the proposal of a multi-step `meltano run` but stored in the yaml file and able to be scheduled.

This is essentially the translation of `meltano run` and `meltano invoke` statements into a DAG definition. Importantly, though, we need to be mindful of how much complexity we want to introduce.

Instead of what we have now that is restricted to just EL pairs:

- A schedule has a tap and target and transform spec (only/skip/etc.).

We'd have:

- A named `job` has one or more `tasks`
- A `schedule` points to a named `job` _or_ the `job` contains a `schedule` description
- Optionally, we can choose to support parallel groups of tasks, such as invoking multiple taps together.
  - Parallel groups might run serially if invoked locally via the CLI, but they'd generate a parallel structure when passed to an external orchestrator such as Airflow.

The assumption is that these would all run using `meltano run`.

For example:

```yaml
jobs:
- name: daily-eltp
  tasks:
  # EL pipelines can run in parallel:
  - - tap-shopify target-snowflake
    - tap-github target-snowflake
  # These dbt build steps run in sequence:
  - dbt:run --full-refresh
  - dbt:test
  # Last mile steps can run in parallel:
  - - superset:build             # BI build
    - tap-snowflake target-yaml  # reverse ETL can run in parallel with BI build
- name: hourly-refresh
  tasks:
  - tap-slack target-snowflake
  - dbt:run

# schedules are separate and can reference jobs
schedules:
# ...
```

## Defining steps with rich metadata (out of scope for iteration 1)

We should plan for future support of rich task definitions (could have `name`, `type`, 'needs', etc.) instead of simple strings. 

The shorthand of simple string representation is easy to understand, read, and maintain. However, this cannot handle advanced dag dependency representations. Supporting both smartly will likely be needed in future for advanced use cases:

```yaml
jobs:
- name: daily-eltp
  tasks:
  # A complex task object could be inlined with string-based tasks
  - type: invoke
    command: dbt:run
    config: ... # perhaps overrides here or perhaps some other future syntax options
  - dbt:test
  - - superset:build             # BI build
    - tap-snowflake target-yaml  # reverse ETL can run in parallel with BI build
```

For each item in the tasks array, if the type is `string`, pass along basically as a `meltano run` arg. If the type is object (dict in python), then parse as a complex task.

## Jobs' relationship to schedules

Schedules likely should be environment specific, but perhaps this should be held until a future iteration.

```yaml
schedules:
- name: daily-eltp-schedule
  job: daily-eltp
  interval: daily
  environments:
  - prod
- name: hourly-refresh-schedule
  job: hourly-refresh
  interval: hourly
  environments:
  - prod
  - dev
#...
```


## Referencing a job from `meltano run`

We would expand `meltano run` to accept job names as well as plugin names.

So assuming 2 jobs are defined, `dbt-daily-refresh` and `daily-el-sync`, these invocations could be valid:

_Possibly out of scope for first iteration_

### Example A: EL steps followed by a named job.

Runs one EL task and then all the tasks in the 'dbt-daily-refresh' job.

```bash
meltano run tap-slack target-snowflake dbt-daily-refresh
```

### Example B: A job followed by a list of commands.

Runs all the EL tasks in the `daily-el-sync` job and then run dbt.

```bash
meltano run daily-el-sync dbt:run dbt:test
```

### Example C: Two sequential jobs.

Runs all the tasks in the `daily-el-sync` job and then all the tasks in the 'dbt-daily-refresh' job.

```bash
meltano run daily-el-sync dbt:run dbt:test
```

## Regarding name collisions

In order for jobs to be referenced in `meltano run`, there cannot be collisions between plugin names and job names.

## CLI Interface

#### jobs

`meltano job <job_name>` add a job

`meltano job <job_name> add schedule <interval>` Schedule the job

`meltano job <job_name> add schedule '[<interval>, ...]' ` Add more schedules

`meltano job <job_name> tasks <run commands>` # should this be set?

`meltano job <job_name> tasks '[<run command>, ...]' `

#### schedules

`meltano schedule <schedule_name> set <job_name> <interval> <environment>` 

`meltano schedule <schedule_name> set <job_name>`

`meltano schedule <schedule_name> set <interval>`

`meltano schedule <schedule_name> set <environment>`

`meltano schedule list [--format=json]`  Does this work with jobs that are scheduled via the job definition?

`meltano schedule run <schedule_name>` Similar to current behavior this would pass any CLI args to `meltano run`

### meltano run syntax

"Run" would accept a job name in place of a command or plugin name.

```
meltano run <job_name>
```

And job names and command/plugin names can be sequenced:

```
meltano run <job_name> dbt:run dbt:build
```

In this scenario, everything runs sequentially but the user doesn't have to type as much.

## Relation to `meltano invoke`

Jobs are not comatible with this syntax: `meltano invoke <job_name>`.

Instead users should use `meltano run <job_name>` or `meltano schedule run <schedule_name` syntax.

Story points: 8.0