orchestra-cli 0.1.3__tar.gz → 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {orchestra_cli-0.1.3 → orchestra_cli-0.3.0}/PKG-INFO +107 -4
- {orchestra_cli-0.1.3 → orchestra_cli-0.3.0}/README.md +106 -3
- orchestra_cli-0.3.0/orchestra_cli/src/cli.py +20 -0
- orchestra_cli-0.3.0/orchestra_cli/src/create_pipeline.py +65 -0
- orchestra_cli-0.3.0/orchestra_cli/src/delete_pipeline.py +39 -0
- orchestra_cli-0.3.0/orchestra_cli/src/fetch_pipelines.py +45 -0
- orchestra_cli-0.3.0/orchestra_cli/src/pipeline_upsert.py +74 -0
- orchestra_cli-0.3.0/orchestra_cli/src/update_pipeline.py +65 -0
- {orchestra_cli-0.1.3 → orchestra_cli-0.3.0}/orchestra_cli/tests/test_cli.py +4 -0
- orchestra_cli-0.3.0/orchestra_cli/tests/test_create_pipeline.py +177 -0
- orchestra_cli-0.3.0/orchestra_cli/tests/test_delete_pipeline.py +82 -0
- orchestra_cli-0.3.0/orchestra_cli/tests/test_fetch_pipelines.py +78 -0
- orchestra_cli-0.3.0/orchestra_cli/tests/test_update_pipeline.py +176 -0
- orchestra_cli-0.3.0/orchestra_cli/utils/constants.py +32 -0
- {orchestra_cli-0.1.3 → orchestra_cli-0.3.0}/orchestra_cli.egg-info/PKG-INFO +107 -4
- {orchestra_cli-0.1.3 → orchestra_cli-0.3.0}/orchestra_cli.egg-info/SOURCES.txt +9 -0
- {orchestra_cli-0.1.3 → orchestra_cli-0.3.0}/pyproject.toml +1 -1
- orchestra_cli-0.1.3/orchestra_cli/src/cli.py +0 -12
- orchestra_cli-0.1.3/orchestra_cli/utils/constants.py +0 -7
- {orchestra_cli-0.1.3 → orchestra_cli-0.3.0}/orchestra_cli/src/__init__.py +0 -0
- {orchestra_cli-0.1.3 → orchestra_cli-0.3.0}/orchestra_cli/src/import_pipeline.py +0 -0
- {orchestra_cli-0.1.3 → orchestra_cli-0.3.0}/orchestra_cli/src/run_pipeline.py +0 -0
- {orchestra_cli-0.1.3 → orchestra_cli-0.3.0}/orchestra_cli/src/validate_pipeline.py +0 -0
- {orchestra_cli-0.1.3 → orchestra_cli-0.3.0}/orchestra_cli/tests/__init__.py +0 -0
- {orchestra_cli-0.1.3 → orchestra_cli-0.3.0}/orchestra_cli/tests/conftest.py +0 -0
- {orchestra_cli-0.1.3 → orchestra_cli-0.3.0}/orchestra_cli/tests/test_import_pipeline.py +0 -0
- {orchestra_cli-0.1.3 → orchestra_cli-0.3.0}/orchestra_cli/tests/test_run_pipeline.py +0 -0
- {orchestra_cli-0.1.3 → orchestra_cli-0.3.0}/orchestra_cli/tests/test_validate_pipeline.py +0 -0
- {orchestra_cli-0.1.3 → orchestra_cli-0.3.0}/orchestra_cli/utils/git.py +0 -0
- {orchestra_cli-0.1.3 → orchestra_cli-0.3.0}/orchestra_cli/utils/styling.py +0 -0
- {orchestra_cli-0.1.3 → orchestra_cli-0.3.0}/orchestra_cli.egg-info/dependency_links.txt +0 -0
- {orchestra_cli-0.1.3 → orchestra_cli-0.3.0}/orchestra_cli.egg-info/entry_points.txt +0 -0
- {orchestra_cli-0.1.3 → orchestra_cli-0.3.0}/orchestra_cli.egg-info/requires.txt +0 -0
- {orchestra_cli-0.1.3 → orchestra_cli-0.3.0}/orchestra_cli.egg-info/top_level.txt +0 -0
- {orchestra_cli-0.1.3 → orchestra_cli-0.3.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: orchestra-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Orchestra CLI. Perform operations with Orchestra locally.
|
|
5
5
|
Author-email: Orchestra Technologies <support@getorchestra.io>
|
|
6
6
|
Requires-Python: >=3.10
|
|
@@ -15,6 +15,8 @@ Orchestra CLI for working with Orchestra pipelines from your terminal.
|
|
|
15
15
|
|
|
16
16
|
Two entrypoints are available: `orchestra` and `orchestra-cli` (they are equivalent).
|
|
17
17
|
|
|
18
|
+
See [`AGENTS.md`](AGENTS.md) for contributor and AI agent guidance (environment setup, code conventions, testing).
|
|
19
|
+
|
|
18
20
|
## Installation
|
|
19
21
|
|
|
20
22
|
```bash
|
|
@@ -29,14 +31,17 @@ pipx install orchestra-cli
|
|
|
29
31
|
|
|
30
32
|
## Environment variables
|
|
31
33
|
|
|
32
|
-
- `ORCHESTRA_API_KEY`: Required for actions that call the API (`import`, `run`).
|
|
33
|
-
- `BASE_URL`: Optional. Override the default
|
|
34
|
-
(`https://app.getorchestra.io/api/engine/public/pipelines/{}`) for non‑production/testing.
|
|
34
|
+
- `ORCHESTRA_API_KEY`: Required for actions that call the API (`import`, `create-pipeline`, `update-pipeline`, `delete-pipeline`, `run`).
|
|
35
|
+
- `BASE_URL`: Optional. Override the default Orchestra host (`https://app.getorchestra.io`) for non‑production/testing.
|
|
35
36
|
|
|
36
37
|
## Commands overview
|
|
37
38
|
|
|
38
39
|
- `validate`: Validate a pipeline YAML locally against the Orchestra API schema.
|
|
39
40
|
- `import`: Register a pipeline YAML (from a git repo) with Orchestra under an alias.
|
|
41
|
+
- `fetch-pipelines`: Fetch the pipelines visible to the current API key as JSON.
|
|
42
|
+
- `create-pipeline`: Create an Orchestra-backed pipeline from a local YAML file.
|
|
43
|
+
- `update-pipeline`: Update an existing Orchestra-backed pipeline from a local YAML file.
|
|
44
|
+
- `delete-pipeline`: Delete an existing pipeline by alias.
|
|
40
45
|
- `run`: Start a pipeline run by alias, optionally pinning branch/commit and waiting for completion.
|
|
41
46
|
|
|
42
47
|
Use `orchestra --help` or `orchestra <command> --help` for built-in help.
|
|
@@ -118,6 +123,104 @@ Common errors
|
|
|
118
123
|
|
|
119
124
|
---
|
|
120
125
|
|
|
126
|
+
## create-pipeline
|
|
127
|
+
|
|
128
|
+
Create an Orchestra-backed pipeline directly from a local YAML file.
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
export ORCHESTRA_API_KEY=...
|
|
132
|
+
|
|
133
|
+
orchestra create-pipeline \
|
|
134
|
+
--alias my-pipeline \
|
|
135
|
+
--path ./pipelines/pipeline.yaml \
|
|
136
|
+
--publish # optional, defaults to --no-publish
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Options
|
|
140
|
+
|
|
141
|
+
- `-a, --alias` (required): Pipeline alias.
|
|
142
|
+
- `-p, --path` (required): Path to pipeline YAML file.
|
|
143
|
+
- `--publish/--no-publish` (optional, default `--no-publish`): Whether the pipeline is published.
|
|
144
|
+
|
|
145
|
+
Behavior
|
|
146
|
+
|
|
147
|
+
- Validates YAML against the Orchestra schema endpoint before creating.
|
|
148
|
+
- Sends pipeline data to `POST /pipelines` with `storage_provider=ORCHESTRA`.
|
|
149
|
+
- On success, prints the pipeline edit URL (`/pipelines/{pipeline_id}/edit`) when an ID is returned.
|
|
150
|
+
- Exit codes: `0` on success, `1` on failure.
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## fetch-pipelines
|
|
155
|
+
|
|
156
|
+
Fetch the pipelines available to the current Orchestra API key.
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
export ORCHESTRA_API_KEY=...
|
|
160
|
+
|
|
161
|
+
orchestra fetch-pipelines
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Behavior
|
|
165
|
+
|
|
166
|
+
- Sends `GET /api/engine/public/pipelines`. Responses always include each pipeline's latest run metadata.
|
|
167
|
+
- Prints the response payload as pretty JSON for scripting and inspection.
|
|
168
|
+
- Exit codes: `0` on success, `1` on failure.
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## update-pipeline
|
|
173
|
+
|
|
174
|
+
Update an existing Orchestra-backed pipeline from a local YAML file.
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
export ORCHESTRA_API_KEY=...
|
|
178
|
+
|
|
179
|
+
orchestra update-pipeline \
|
|
180
|
+
--alias my-pipeline \
|
|
181
|
+
--path ./pipelines/pipeline.yaml \
|
|
182
|
+
--no-publish # default
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Options
|
|
186
|
+
|
|
187
|
+
- `-a, --alias` (required): Pipeline alias to update.
|
|
188
|
+
- `-p, --path` (required): Path to pipeline YAML file.
|
|
189
|
+
- `--publish/--no-publish` (optional, default `--no-publish`): Whether the pipeline is published.
|
|
190
|
+
|
|
191
|
+
Behavior
|
|
192
|
+
|
|
193
|
+
- Validates YAML against the Orchestra schema endpoint before updating.
|
|
194
|
+
- Sends pipeline data to `PUT /pipelines/{alias}` with `storage_provider=ORCHESTRA`.
|
|
195
|
+
- Only Orchestra-backed pipelines can be updated via this endpoint (Git-backed pipelines are rejected).
|
|
196
|
+
- On success, prints the pipeline edit URL (`/pipelines/{pipeline_id}/edit`) when an ID is returned.
|
|
197
|
+
- Exit codes: `0` on success, `1` on failure.
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## delete-pipeline
|
|
202
|
+
|
|
203
|
+
Delete a pipeline by alias.
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
export ORCHESTRA_API_KEY=...
|
|
207
|
+
|
|
208
|
+
orchestra delete-pipeline --alias my-pipeline
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Options
|
|
212
|
+
|
|
213
|
+
- `-a, --alias` (required): Pipeline alias to delete.
|
|
214
|
+
|
|
215
|
+
Behavior
|
|
216
|
+
|
|
217
|
+
- Sends `DELETE /pipelines/{alias}` with API key authentication.
|
|
218
|
+
- Deletes the pipeline resolved by alias within the authenticated account.
|
|
219
|
+
- On success, exits with code `0` after printing a confirmation message.
|
|
220
|
+
- Exit codes: `0` on success, `1` on failure.
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
121
224
|
## run
|
|
122
225
|
|
|
123
226
|
Start a pipeline run by alias. Optionally specify a branch and/or commit. By default, the command waits and polls the run status until completion.
|
|
@@ -4,6 +4,8 @@ Orchestra CLI for working with Orchestra pipelines from your terminal.
|
|
|
4
4
|
|
|
5
5
|
Two entrypoints are available: `orchestra` and `orchestra-cli` (they are equivalent).
|
|
6
6
|
|
|
7
|
+
See [`AGENTS.md`](AGENTS.md) for contributor and AI agent guidance (environment setup, code conventions, testing).
|
|
8
|
+
|
|
7
9
|
## Installation
|
|
8
10
|
|
|
9
11
|
```bash
|
|
@@ -18,14 +20,17 @@ pipx install orchestra-cli
|
|
|
18
20
|
|
|
19
21
|
## Environment variables
|
|
20
22
|
|
|
21
|
-
- `ORCHESTRA_API_KEY`: Required for actions that call the API (`import`, `run`).
|
|
22
|
-
- `BASE_URL`: Optional. Override the default
|
|
23
|
-
(`https://app.getorchestra.io/api/engine/public/pipelines/{}`) for non‑production/testing.
|
|
23
|
+
- `ORCHESTRA_API_KEY`: Required for actions that call the API (`import`, `create-pipeline`, `update-pipeline`, `delete-pipeline`, `run`).
|
|
24
|
+
- `BASE_URL`: Optional. Override the default Orchestra host (`https://app.getorchestra.io`) for non‑production/testing.
|
|
24
25
|
|
|
25
26
|
## Commands overview
|
|
26
27
|
|
|
27
28
|
- `validate`: Validate a pipeline YAML locally against the Orchestra API schema.
|
|
28
29
|
- `import`: Register a pipeline YAML (from a git repo) with Orchestra under an alias.
|
|
30
|
+
- `fetch-pipelines`: Fetch the pipelines visible to the current API key as JSON.
|
|
31
|
+
- `create-pipeline`: Create an Orchestra-backed pipeline from a local YAML file.
|
|
32
|
+
- `update-pipeline`: Update an existing Orchestra-backed pipeline from a local YAML file.
|
|
33
|
+
- `delete-pipeline`: Delete an existing pipeline by alias.
|
|
29
34
|
- `run`: Start a pipeline run by alias, optionally pinning branch/commit and waiting for completion.
|
|
30
35
|
|
|
31
36
|
Use `orchestra --help` or `orchestra <command> --help` for built-in help.
|
|
@@ -107,6 +112,104 @@ Common errors
|
|
|
107
112
|
|
|
108
113
|
---
|
|
109
114
|
|
|
115
|
+
## create-pipeline
|
|
116
|
+
|
|
117
|
+
Create an Orchestra-backed pipeline directly from a local YAML file.
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
export ORCHESTRA_API_KEY=...
|
|
121
|
+
|
|
122
|
+
orchestra create-pipeline \
|
|
123
|
+
--alias my-pipeline \
|
|
124
|
+
--path ./pipelines/pipeline.yaml \
|
|
125
|
+
--publish # optional, defaults to --no-publish
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Options
|
|
129
|
+
|
|
130
|
+
- `-a, --alias` (required): Pipeline alias.
|
|
131
|
+
- `-p, --path` (required): Path to pipeline YAML file.
|
|
132
|
+
- `--publish/--no-publish` (optional, default `--no-publish`): Whether the pipeline is published.
|
|
133
|
+
|
|
134
|
+
Behavior
|
|
135
|
+
|
|
136
|
+
- Validates YAML against the Orchestra schema endpoint before creating.
|
|
137
|
+
- Sends pipeline data to `POST /pipelines` with `storage_provider=ORCHESTRA`.
|
|
138
|
+
- On success, prints the pipeline edit URL (`/pipelines/{pipeline_id}/edit`) when an ID is returned.
|
|
139
|
+
- Exit codes: `0` on success, `1` on failure.
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## fetch-pipelines
|
|
144
|
+
|
|
145
|
+
Fetch the pipelines available to the current Orchestra API key.
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
export ORCHESTRA_API_KEY=...
|
|
149
|
+
|
|
150
|
+
orchestra fetch-pipelines
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Behavior
|
|
154
|
+
|
|
155
|
+
- Sends `GET /api/engine/public/pipelines`. Responses always include each pipeline's latest run metadata.
|
|
156
|
+
- Prints the response payload as pretty JSON for scripting and inspection.
|
|
157
|
+
- Exit codes: `0` on success, `1` on failure.
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## update-pipeline
|
|
162
|
+
|
|
163
|
+
Update an existing Orchestra-backed pipeline from a local YAML file.
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
export ORCHESTRA_API_KEY=...
|
|
167
|
+
|
|
168
|
+
orchestra update-pipeline \
|
|
169
|
+
--alias my-pipeline \
|
|
170
|
+
--path ./pipelines/pipeline.yaml \
|
|
171
|
+
--no-publish # default
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Options
|
|
175
|
+
|
|
176
|
+
- `-a, --alias` (required): Pipeline alias to update.
|
|
177
|
+
- `-p, --path` (required): Path to pipeline YAML file.
|
|
178
|
+
- `--publish/--no-publish` (optional, default `--no-publish`): Whether the pipeline is published.
|
|
179
|
+
|
|
180
|
+
Behavior
|
|
181
|
+
|
|
182
|
+
- Validates YAML against the Orchestra schema endpoint before updating.
|
|
183
|
+
- Sends pipeline data to `PUT /pipelines/{alias}` with `storage_provider=ORCHESTRA`.
|
|
184
|
+
- Only Orchestra-backed pipelines can be updated via this endpoint (Git-backed pipelines are rejected).
|
|
185
|
+
- On success, prints the pipeline edit URL (`/pipelines/{pipeline_id}/edit`) when an ID is returned.
|
|
186
|
+
- Exit codes: `0` on success, `1` on failure.
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## delete-pipeline
|
|
191
|
+
|
|
192
|
+
Delete a pipeline by alias.
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
export ORCHESTRA_API_KEY=...
|
|
196
|
+
|
|
197
|
+
orchestra delete-pipeline --alias my-pipeline
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Options
|
|
201
|
+
|
|
202
|
+
- `-a, --alias` (required): Pipeline alias to delete.
|
|
203
|
+
|
|
204
|
+
Behavior
|
|
205
|
+
|
|
206
|
+
- Sends `DELETE /pipelines/{alias}` with API key authentication.
|
|
207
|
+
- Deletes the pipeline resolved by alias within the authenticated account.
|
|
208
|
+
- On success, exits with code `0` after printing a confirmation message.
|
|
209
|
+
- Exit codes: `0` on success, `1` on failure.
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
110
213
|
## run
|
|
111
214
|
|
|
112
215
|
Start a pipeline run by alias. Optionally specify a branch and/or commit. By default, the command waits and polls the run status until completion.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import typer
|
|
2
|
+
|
|
3
|
+
from .create_pipeline import create_pipeline
|
|
4
|
+
from .delete_pipeline import delete_pipeline
|
|
5
|
+
from .fetch_pipelines import fetch_pipelines
|
|
6
|
+
from .import_pipeline import import_pipeline
|
|
7
|
+
from .run_pipeline import run_pipeline
|
|
8
|
+
from .update_pipeline import update_pipeline
|
|
9
|
+
from .validate_pipeline import validate
|
|
10
|
+
|
|
11
|
+
app = typer.Typer(help="Orchestra CLI – perform operations with Orchestra locally.")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
app.command(name="validate")(validate)
|
|
15
|
+
app.command(name="import")(import_pipeline)
|
|
16
|
+
app.command(name="run")(run_pipeline)
|
|
17
|
+
app.command(name="fetch-pipelines")(fetch_pipelines)
|
|
18
|
+
app.command(name="create-pipeline")(create_pipeline)
|
|
19
|
+
app.command(name="update-pipeline")(update_pipeline)
|
|
20
|
+
app.command(name="delete-pipeline")(delete_pipeline)
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
import httpx
|
|
5
|
+
import typer
|
|
6
|
+
|
|
7
|
+
from ..utils.constants import get_create_pipeline_url
|
|
8
|
+
from ..utils.styling import indent_message, red, yellow
|
|
9
|
+
from .pipeline_upsert import (
|
|
10
|
+
build_upsert_payload,
|
|
11
|
+
emit_success_with_edit_url,
|
|
12
|
+
load_validated_pipeline_data,
|
|
13
|
+
require_api_key,
|
|
14
|
+
require_pipeline_id_from_success_response,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def create_pipeline(
|
|
19
|
+
alias: str = typer.Option(..., "--alias", "-a", help="Pipeline alias"),
|
|
20
|
+
path: Path = typer.Option(
|
|
21
|
+
...,
|
|
22
|
+
"--path",
|
|
23
|
+
"-p",
|
|
24
|
+
exists=True,
|
|
25
|
+
file_okay=True,
|
|
26
|
+
dir_okay=False,
|
|
27
|
+
readable=True,
|
|
28
|
+
resolve_path=True,
|
|
29
|
+
help="Path to pipeline YAML",
|
|
30
|
+
),
|
|
31
|
+
publish: bool = typer.Option(
|
|
32
|
+
False,
|
|
33
|
+
"--publish/--no-publish",
|
|
34
|
+
help="Whether the pipeline is published and can be triggered",
|
|
35
|
+
),
|
|
36
|
+
):
|
|
37
|
+
"""
|
|
38
|
+
Create an Orchestra-backed pipeline from a local YAML file.
|
|
39
|
+
"""
|
|
40
|
+
api_key = require_api_key()
|
|
41
|
+
data = load_validated_pipeline_data(path)
|
|
42
|
+
payload = build_upsert_payload(data, publish, alias=alias)
|
|
43
|
+
|
|
44
|
+
try:
|
|
45
|
+
response = httpx.post(
|
|
46
|
+
get_create_pipeline_url(),
|
|
47
|
+
json=payload,
|
|
48
|
+
timeout=30,
|
|
49
|
+
headers={"Authorization": f"Bearer {api_key}"},
|
|
50
|
+
)
|
|
51
|
+
except Exception as e:
|
|
52
|
+
typer.echo(red(f"HTTP request failed: {e}"))
|
|
53
|
+
raise typer.Exit(code=1)
|
|
54
|
+
|
|
55
|
+
if response.status_code == 201:
|
|
56
|
+
pipeline_id = require_pipeline_id_from_success_response(response, "Create")
|
|
57
|
+
emit_success_with_edit_url(alias, "created", pipeline_id)
|
|
58
|
+
raise typer.Exit(code=0)
|
|
59
|
+
|
|
60
|
+
typer.echo(red(f"❌ Create failed with status {response.status_code}"))
|
|
61
|
+
try:
|
|
62
|
+
typer.echo(yellow(indent_message(json.dumps(response.json(), indent=2))))
|
|
63
|
+
except Exception:
|
|
64
|
+
typer.echo(yellow(indent_message(response.text)))
|
|
65
|
+
raise typer.Exit(code=1)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import json
|
|
2
|
+
|
|
3
|
+
import httpx
|
|
4
|
+
import typer
|
|
5
|
+
|
|
6
|
+
from ..utils.constants import get_delete_pipeline_url
|
|
7
|
+
from ..utils.styling import green, indent_message, red, yellow
|
|
8
|
+
from .pipeline_upsert import require_api_key
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def delete_pipeline(
|
|
12
|
+
alias: str = typer.Option(..., "--alias", "-a", help="Pipeline alias"),
|
|
13
|
+
):
|
|
14
|
+
"""
|
|
15
|
+
Delete a pipeline by alias.
|
|
16
|
+
"""
|
|
17
|
+
api_key = require_api_key()
|
|
18
|
+
|
|
19
|
+
try:
|
|
20
|
+
response = httpx.delete(
|
|
21
|
+
get_delete_pipeline_url(alias),
|
|
22
|
+
timeout=30,
|
|
23
|
+
headers={"Authorization": f"Bearer {api_key}"},
|
|
24
|
+
)
|
|
25
|
+
except Exception as e:
|
|
26
|
+
typer.echo(red(f"HTTP request failed: {e}"))
|
|
27
|
+
raise typer.Exit(code=1)
|
|
28
|
+
|
|
29
|
+
if response.status_code == 204:
|
|
30
|
+
typer.echo(green(f"✅ Pipeline '{alias}' deleted successfully"))
|
|
31
|
+
raise typer.Exit(code=0)
|
|
32
|
+
|
|
33
|
+
typer.echo(red(f"❌ Delete failed with status {response.status_code}"))
|
|
34
|
+
try:
|
|
35
|
+
typer.echo(yellow(indent_message(json.dumps(response.json(), indent=2))))
|
|
36
|
+
except Exception:
|
|
37
|
+
if response.text:
|
|
38
|
+
typer.echo(yellow(indent_message(response.text)))
|
|
39
|
+
raise typer.Exit(code=1)
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import json
|
|
2
|
+
|
|
3
|
+
import httpx
|
|
4
|
+
import typer
|
|
5
|
+
|
|
6
|
+
from ..utils.constants import get_api_url
|
|
7
|
+
from ..utils.styling import indent_message, red, yellow
|
|
8
|
+
from .pipeline_upsert import require_api_key
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def fetch_pipelines():
|
|
12
|
+
"""
|
|
13
|
+
Fetch pipelines available to the current Orchestra API key.
|
|
14
|
+
|
|
15
|
+
The API always includes each pipeline's latest run metadata.
|
|
16
|
+
"""
|
|
17
|
+
api_key = require_api_key()
|
|
18
|
+
|
|
19
|
+
try:
|
|
20
|
+
response = httpx.get(
|
|
21
|
+
get_api_url(""),
|
|
22
|
+
timeout=30,
|
|
23
|
+
headers={"Authorization": f"Bearer {api_key}"},
|
|
24
|
+
)
|
|
25
|
+
except Exception as e:
|
|
26
|
+
typer.echo(red(f"HTTP request failed: {e}"))
|
|
27
|
+
raise typer.Exit(code=1)
|
|
28
|
+
|
|
29
|
+
if response.status_code == 200:
|
|
30
|
+
try:
|
|
31
|
+
pipelines = response.json()
|
|
32
|
+
except Exception:
|
|
33
|
+
typer.echo(red("❌ Fetch pipelines failed: success response was not valid JSON"))
|
|
34
|
+
typer.echo(yellow(indent_message(response.text)))
|
|
35
|
+
raise typer.Exit(code=1)
|
|
36
|
+
|
|
37
|
+
typer.echo(json.dumps(pipelines, indent=2))
|
|
38
|
+
raise typer.Exit(code=0)
|
|
39
|
+
|
|
40
|
+
typer.echo(red(f"❌ Fetch pipelines failed with status {response.status_code}"))
|
|
41
|
+
try:
|
|
42
|
+
typer.echo(yellow(indent_message(json.dumps(response.json(), indent=2))))
|
|
43
|
+
except Exception:
|
|
44
|
+
typer.echo(yellow(indent_message(response.text)))
|
|
45
|
+
raise typer.Exit(code=1)
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
import httpx
|
|
6
|
+
import typer
|
|
7
|
+
|
|
8
|
+
from ..utils.constants import get_pipeline_edit_url
|
|
9
|
+
from ..utils.styling import green, indent_message, red, yellow
|
|
10
|
+
from .import_pipeline import _load_yaml, _validate_yaml_with_api
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def require_api_key() -> str:
|
|
14
|
+
api_key = os.getenv("ORCHESTRA_API_KEY")
|
|
15
|
+
if not api_key:
|
|
16
|
+
typer.echo(red("ORCHESTRA_API_KEY is not set"))
|
|
17
|
+
raise typer.Exit(code=1)
|
|
18
|
+
return api_key
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def load_validated_pipeline_data(path: Path) -> dict:
|
|
22
|
+
if not path.exists():
|
|
23
|
+
typer.echo(red(f"File not found: {path}"))
|
|
24
|
+
raise typer.Exit(code=1)
|
|
25
|
+
|
|
26
|
+
data, err = _load_yaml(path)
|
|
27
|
+
if err is not None:
|
|
28
|
+
typer.echo(red(f"Invalid YAML: {err}"))
|
|
29
|
+
raise typer.Exit(code=1)
|
|
30
|
+
|
|
31
|
+
ok, err_msg = _validate_yaml_with_api(data or {})
|
|
32
|
+
if not ok:
|
|
33
|
+
typer.echo(red("❌ Validation failed"))
|
|
34
|
+
if err_msg:
|
|
35
|
+
typer.echo(yellow(indent_message(err_msg)))
|
|
36
|
+
raise typer.Exit(code=1)
|
|
37
|
+
|
|
38
|
+
return data or {}
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def build_upsert_payload(data: dict, publish: bool, alias: str | None = None) -> dict:
|
|
42
|
+
payload: dict[str, object] = {
|
|
43
|
+
"data": data,
|
|
44
|
+
"published": publish,
|
|
45
|
+
"storage_provider": "ORCHESTRA",
|
|
46
|
+
}
|
|
47
|
+
if alias is not None:
|
|
48
|
+
payload["alias"] = alias
|
|
49
|
+
return payload
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def require_pipeline_id_from_success_response(
|
|
53
|
+
response: httpx.Response,
|
|
54
|
+
action: str,
|
|
55
|
+
) -> str:
|
|
56
|
+
try:
|
|
57
|
+
body = response.json()
|
|
58
|
+
except Exception:
|
|
59
|
+
typer.echo(red(f"❌ {action} failed: success response was not valid JSON"))
|
|
60
|
+
typer.echo(yellow(indent_message(response.text)))
|
|
61
|
+
raise typer.Exit(code=1)
|
|
62
|
+
|
|
63
|
+
pipeline_id = body.get("id")
|
|
64
|
+
if not pipeline_id:
|
|
65
|
+
typer.echo(red(f"❌ {action} failed: success response did not include pipeline id"))
|
|
66
|
+
typer.echo(yellow(indent_message(json.dumps(body, indent=2))))
|
|
67
|
+
raise typer.Exit(code=1)
|
|
68
|
+
|
|
69
|
+
return str(pipeline_id)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def emit_success_with_edit_url(alias: str, action: str, pipeline_id: str) -> None:
|
|
73
|
+
typer.echo(green(f"✅ Pipeline '{alias}' {action} successfully: {pipeline_id}"))
|
|
74
|
+
typer.echo(yellow(f"Edit URL: {get_pipeline_edit_url(pipeline_id)}"))
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
import httpx
|
|
5
|
+
import typer
|
|
6
|
+
|
|
7
|
+
from ..utils.constants import get_update_pipeline_url
|
|
8
|
+
from ..utils.styling import indent_message, red, yellow
|
|
9
|
+
from .pipeline_upsert import (
|
|
10
|
+
build_upsert_payload,
|
|
11
|
+
emit_success_with_edit_url,
|
|
12
|
+
load_validated_pipeline_data,
|
|
13
|
+
require_api_key,
|
|
14
|
+
require_pipeline_id_from_success_response,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def update_pipeline(
|
|
19
|
+
alias: str = typer.Option(..., "--alias", "-a", help="Pipeline alias"),
|
|
20
|
+
path: Path = typer.Option(
|
|
21
|
+
...,
|
|
22
|
+
"--path",
|
|
23
|
+
"-p",
|
|
24
|
+
exists=True,
|
|
25
|
+
file_okay=True,
|
|
26
|
+
dir_okay=False,
|
|
27
|
+
readable=True,
|
|
28
|
+
resolve_path=True,
|
|
29
|
+
help="Path to pipeline YAML",
|
|
30
|
+
),
|
|
31
|
+
publish: bool = typer.Option(
|
|
32
|
+
False,
|
|
33
|
+
"--publish/--no-publish",
|
|
34
|
+
help="Whether the pipeline is published and can be triggered",
|
|
35
|
+
),
|
|
36
|
+
):
|
|
37
|
+
"""
|
|
38
|
+
Update an Orchestra-backed pipeline from a local YAML file.
|
|
39
|
+
"""
|
|
40
|
+
api_key = require_api_key()
|
|
41
|
+
data = load_validated_pipeline_data(path)
|
|
42
|
+
payload = build_upsert_payload(data, publish)
|
|
43
|
+
|
|
44
|
+
try:
|
|
45
|
+
response = httpx.put(
|
|
46
|
+
get_update_pipeline_url(alias),
|
|
47
|
+
json=payload,
|
|
48
|
+
timeout=30,
|
|
49
|
+
headers={"Authorization": f"Bearer {api_key}"},
|
|
50
|
+
)
|
|
51
|
+
except Exception as e:
|
|
52
|
+
typer.echo(red(f"HTTP request failed: {e}"))
|
|
53
|
+
raise typer.Exit(code=1)
|
|
54
|
+
|
|
55
|
+
if response.status_code == 200:
|
|
56
|
+
pipeline_id = require_pipeline_id_from_success_response(response, "Update")
|
|
57
|
+
emit_success_with_edit_url(alias, "updated", pipeline_id)
|
|
58
|
+
raise typer.Exit(code=0)
|
|
59
|
+
|
|
60
|
+
typer.echo(red(f"❌ Update failed with status {response.status_code}"))
|
|
61
|
+
try:
|
|
62
|
+
typer.echo(yellow(indent_message(json.dumps(response.json(), indent=2))))
|
|
63
|
+
except Exception:
|
|
64
|
+
typer.echo(yellow(indent_message(response.text)))
|
|
65
|
+
raise typer.Exit(code=1)
|
|
@@ -10,3 +10,7 @@ def test_help():
|
|
|
10
10
|
assert result.exit_code == 0
|
|
11
11
|
assert "Orchestra CLI" in result.output
|
|
12
12
|
assert "validate" in result.output
|
|
13
|
+
assert "fetch-pipelines" in result.output
|
|
14
|
+
assert "create-pipeline" in result.output
|
|
15
|
+
assert "delete-pipeline" in result.output
|
|
16
|
+
assert "update-pipeline" in result.output
|