buildify-cli 1.1.0__tar.gz → 1.2.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.
- {buildify_cli-1.1.0 → buildify_cli-1.2.0}/PKG-INFO +2 -2
- {buildify_cli-1.1.0 → buildify_cli-1.2.0}/README.md +1 -1
- {buildify_cli-1.1.0 → buildify_cli-1.2.0}/pyproject.toml +1 -1
- buildify_cli-1.2.0/src/buildify_cli/__init__.py +1 -0
- {buildify_cli-1.1.0 → buildify_cli-1.2.0}/src/buildify_cli/cli.py +98 -1
- {buildify_cli-1.1.0 → buildify_cli-1.2.0}/src/buildify_cli/client.py +37 -0
- {buildify_cli-1.1.0 → buildify_cli-1.2.0}/src/buildify_cli/usage.md +13 -0
- {buildify_cli-1.1.0 → buildify_cli-1.2.0}/src/buildify_cli.egg-info/PKG-INFO +2 -2
- buildify_cli-1.1.0/src/buildify_cli/__init__.py +0 -1
- {buildify_cli-1.1.0 → buildify_cli-1.2.0}/setup.cfg +0 -0
- {buildify_cli-1.1.0 → buildify_cli-1.2.0}/src/buildify_cli/__main__.py +0 -0
- {buildify_cli-1.1.0 → buildify_cli-1.2.0}/src/buildify_cli/config.py +0 -0
- {buildify_cli-1.1.0 → buildify_cli-1.2.0}/src/buildify_cli/credential_form.py +0 -0
- {buildify_cli-1.1.0 → buildify_cli-1.2.0}/src/buildify_cli/exit_codes.py +0 -0
- {buildify_cli-1.1.0 → buildify_cli-1.2.0}/src/buildify_cli/output.py +0 -0
- {buildify_cli-1.1.0 → buildify_cli-1.2.0}/src/buildify_cli/publish_view.py +0 -0
- {buildify_cli-1.1.0 → buildify_cli-1.2.0}/src/buildify_cli.egg-info/SOURCES.txt +0 -0
- {buildify_cli-1.1.0 → buildify_cli-1.2.0}/src/buildify_cli.egg-info/dependency_links.txt +0 -0
- {buildify_cli-1.1.0 → buildify_cli-1.2.0}/src/buildify_cli.egg-info/entry_points.txt +0 -0
- {buildify_cli-1.1.0 → buildify_cli-1.2.0}/src/buildify_cli.egg-info/requires.txt +0 -0
- {buildify_cli-1.1.0 → buildify_cli-1.2.0}/src/buildify_cli.egg-info/top_level.txt +0 -0
- {buildify_cli-1.1.0 → buildify_cli-1.2.0}/tests/test_auth_config.py +0 -0
- {buildify_cli-1.1.0 → buildify_cli-1.2.0}/tests/test_credential_form.py +0 -0
- {buildify_cli-1.1.0 → buildify_cli-1.2.0}/tests/test_history_view.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: buildify-cli
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.2.0
|
|
4
4
|
Summary: CLI for the Buildify open API: discover bundle nodes, author and test workflows (machine Bearer auth)
|
|
5
5
|
Requires-Python: >=3.10
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -65,7 +65,7 @@ interactive prompt. `config set-key api_key` still updates the current profile,
|
|
|
65
65
|
| — | `health`, `version`, `help` |
|
|
66
66
|
| `key` | `test` |
|
|
67
67
|
| `bundle` | `list`, `nodes`, `node-properties`, `node-relations`, `doc`, `cred-types`, `cred-properties` |
|
|
68
|
-
| `project` | `list`, `create`, `get`, `credentials`, `create-credential`, `workers` |
|
|
68
|
+
| `project` | `list`, `create`, `get`, `update`, `delete`, `credentials`, `create-credential`, `update-credential`, `delete-credential`, `credential-workflows`, `workers` |
|
|
69
69
|
| `workflow` | `list`, `create`, `get-draft`, `save-draft`, `validate`, `test-run`, `cancel-test`, `deploy`, `published`, `deployments`, `deployment`, `versions`, `get-version` |
|
|
70
70
|
| `config` | `init`, `set-key`, `add-profile`, `use`, `profiles`, `remove-profile`, `show` |
|
|
71
71
|
|
|
@@ -52,7 +52,7 @@ interactive prompt. `config set-key api_key` still updates the current profile,
|
|
|
52
52
|
| — | `health`, `version`, `help` |
|
|
53
53
|
| `key` | `test` |
|
|
54
54
|
| `bundle` | `list`, `nodes`, `node-properties`, `node-relations`, `doc`, `cred-types`, `cred-properties` |
|
|
55
|
-
| `project` | `list`, `create`, `get`, `credentials`, `create-credential`, `workers` |
|
|
55
|
+
| `project` | `list`, `create`, `get`, `update`, `delete`, `credentials`, `create-credential`, `update-credential`, `delete-credential`, `credential-workflows`, `workers` |
|
|
56
56
|
| `workflow` | `list`, `create`, `get-draft`, `save-draft`, `validate`, `test-run`, `cancel-test`, `deploy`, `published`, `deployments`, `deployment`, `versions`, `get-version` |
|
|
57
57
|
| `config` | `init`, `set-key`, `add-profile`, `use`, `profiles`, `remove-profile`, `show` |
|
|
58
58
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "buildify-cli"
|
|
7
|
-
version = "1.
|
|
7
|
+
version = "1.2.0"
|
|
8
8
|
description = "CLI for the Buildify open API: discover bundle nodes, author and test workflows (machine Bearer auth)"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "1.2.0"
|
|
@@ -65,7 +65,8 @@ app = typer.Typer(
|
|
|
65
65
|
" health GET /openapi/v1/health (no key)\n"
|
|
66
66
|
" key test Validate the configured key\n"
|
|
67
67
|
" bundle Bundle / node discovery: list, nodes, node-properties, node-relations, doc, cred-types, cred-properties\n"
|
|
68
|
-
" project list, create, get, credentials, create-credential
|
|
68
|
+
" project list, create, get, update, delete, credentials, create-credential,\n"
|
|
69
|
+
" update-credential, delete-credential, credential-workflows, workers\n"
|
|
69
70
|
" workflow list, create, get-draft, save-draft, validate, test-run, cancel-test,\n"
|
|
70
71
|
" deploy, published, deployments, deployment, versions, get-version\n"
|
|
71
72
|
" config Manage the [openapi] section of ~/.buildifyrc\n"
|
|
@@ -449,6 +450,7 @@ project_app = typer.Typer(help="Projects, credentials and workers.")
|
|
|
449
450
|
app.add_typer(project_app, name="project")
|
|
450
451
|
|
|
451
452
|
_OPT_PROJECT = typer.Option(..., "--project", "-p", help="Project public id (proj_...).")
|
|
453
|
+
_OPT_CREDENTIALS = typer.Option(..., "--credentials", help="Credential public id (cred_...).")
|
|
452
454
|
|
|
453
455
|
|
|
454
456
|
@project_app.command("list")
|
|
@@ -629,6 +631,101 @@ def cmd_project_create_credential(
|
|
|
629
631
|
)
|
|
630
632
|
|
|
631
633
|
|
|
634
|
+
@project_app.command("update-credential")
|
|
635
|
+
def cmd_project_update_credential(
|
|
636
|
+
ctx: typer.Context,
|
|
637
|
+
project: str = _OPT_PROJECT,
|
|
638
|
+
credentials: str = _OPT_CREDENTIALS,
|
|
639
|
+
label: Optional[str] = typer.Option(None, "--label", help="New display name. Omit to keep the current one."),
|
|
640
|
+
description: Optional[str] = typer.Option(
|
|
641
|
+
None, "--description", help="New remark. Pass an empty string to clear it. Omit to keep the current one."
|
|
642
|
+
),
|
|
643
|
+
bundle_version: Optional[str] = typer.Option(
|
|
644
|
+
None, "--bundle-version", "-V", help="Bind another version of the same bundle. Omit to keep the current one."
|
|
645
|
+
),
|
|
646
|
+
data_inline: Optional[str] = typer.Option(
|
|
647
|
+
None,
|
|
648
|
+
"--data",
|
|
649
|
+
help="JSON object of form fields. Insecure in argv; prefer --file - / stdin.",
|
|
650
|
+
),
|
|
651
|
+
file: Optional[Path] = typer.Option(
|
|
652
|
+
None,
|
|
653
|
+
"--file",
|
|
654
|
+
"-f",
|
|
655
|
+
help="JSON file of form fields to merge, or '-' for stdin. Omit to keep stored secrets.",
|
|
656
|
+
),
|
|
657
|
+
yes: bool = typer.Option(False, "--yes", "-y", help="Skip the TTY confirmation prompt."),
|
|
658
|
+
) -> None:
|
|
659
|
+
"""Update a credential's label, remark, bundle version, or form data.
|
|
660
|
+
|
|
661
|
+
Omitted fields stay as they are. Secrets are never printed. Masked or blank secret fields
|
|
662
|
+
keep the stored value. Confirm with the user before running.
|
|
663
|
+
"""
|
|
664
|
+
if data_inline:
|
|
665
|
+
human_err("warning: --data is visible in process lists and shell history; prefer --file -")
|
|
666
|
+
data: Optional[dict[str, Any]] = None
|
|
667
|
+
if data_inline is not None or file is not None:
|
|
668
|
+
parsed = _read_json_arg(ctx, data_inline, file, what="credential data")
|
|
669
|
+
if not isinstance(parsed, dict):
|
|
670
|
+
raise _fail_local(ctx, "credential data must be a JSON object")
|
|
671
|
+
data = parsed
|
|
672
|
+
if label is None and description is None and bundle_version is None and data is None:
|
|
673
|
+
raise _fail_local(ctx, "至少提供 --label、--description、--bundle-version 或 --file 之一")
|
|
674
|
+
if label is not None and not label.strip():
|
|
675
|
+
raise _fail_local(ctx, "label 不能为空")
|
|
676
|
+
if _can_prompt_for_key(ctx) and not yes:
|
|
677
|
+
human_err("即将更新访问凭证,请确认:")
|
|
678
|
+
human_err(f" credentials:{credentials}")
|
|
679
|
+
if label is not None:
|
|
680
|
+
human_err(f" label:{label}")
|
|
681
|
+
if description is not None:
|
|
682
|
+
human_err(f" description:{description if description else '(清空)'}")
|
|
683
|
+
if bundle_version is not None:
|
|
684
|
+
human_err(f" bundleVersion:{bundle_version}")
|
|
685
|
+
if data is not None:
|
|
686
|
+
human_err(f" 参数键:{', '.join(data) or '(空)'}(值已隐藏)")
|
|
687
|
+
if not typer.confirm("确认更新?", default=False, err=True):
|
|
688
|
+
raise _fail_local(ctx, "已取消更新", ec.LOCAL_VALIDATION)
|
|
689
|
+
with _client(ctx) as c:
|
|
690
|
+
_call(
|
|
691
|
+
ctx,
|
|
692
|
+
c.project_update_credential,
|
|
693
|
+
project,
|
|
694
|
+
credentials,
|
|
695
|
+
label=label.strip() if label is not None else None,
|
|
696
|
+
description=description,
|
|
697
|
+
bundle_version=bundle_version,
|
|
698
|
+
data=data,
|
|
699
|
+
)
|
|
700
|
+
|
|
701
|
+
|
|
702
|
+
@project_app.command("delete-credential")
|
|
703
|
+
def cmd_project_delete_credential(
|
|
704
|
+
ctx: typer.Context,
|
|
705
|
+
project: str = _OPT_PROJECT,
|
|
706
|
+
credentials: str = _OPT_CREDENTIALS,
|
|
707
|
+
) -> None:
|
|
708
|
+
"""Soft-delete a credential that no workflow references. Confirm with the user first.
|
|
709
|
+
|
|
710
|
+
HTTP 409 when a flow still references it.
|
|
711
|
+
"""
|
|
712
|
+
with _client(ctx) as c:
|
|
713
|
+
_call(ctx, c.project_delete_credential, project, credentials)
|
|
714
|
+
|
|
715
|
+
|
|
716
|
+
@project_app.command("credential-workflows")
|
|
717
|
+
def cmd_project_credential_workflows(
|
|
718
|
+
ctx: typer.Context,
|
|
719
|
+
project: str = _OPT_PROJECT,
|
|
720
|
+
credentials: str = _OPT_CREDENTIALS,
|
|
721
|
+
page: int = typer.Option(1, "--page", min=1, help="Page number, starting at 1."),
|
|
722
|
+
page_size: int = typer.Option(10, "--page-size", min=1, max=100, help="Page size, at most 100."),
|
|
723
|
+
) -> None:
|
|
724
|
+
"""Workflows that reference a credential. No secrets. Requires credentials view."""
|
|
725
|
+
with _client(ctx) as c:
|
|
726
|
+
_call(ctx, c.project_credential_workflows, project, credentials, page=page, page_size=page_size)
|
|
727
|
+
|
|
728
|
+
|
|
632
729
|
def _prompt_credential_data(fields: list[dict[str, Any]]) -> dict[str, Any]:
|
|
633
730
|
values: dict[str, Any] = {}
|
|
634
731
|
if not fields:
|
|
@@ -156,6 +156,43 @@ class OpenApiClient:
|
|
|
156
156
|
payload["description"] = description
|
|
157
157
|
return self._post(f"{API_PREFIX}/projects/{project_id}/credentials", payload)
|
|
158
158
|
|
|
159
|
+
def project_update_credential(
|
|
160
|
+
self,
|
|
161
|
+
project_id: str,
|
|
162
|
+
credentials_id: str,
|
|
163
|
+
*,
|
|
164
|
+
label: Optional[str] = None,
|
|
165
|
+
description: Optional[str] = None,
|
|
166
|
+
bundle_version: Optional[str] = None,
|
|
167
|
+
data: Optional[dict[str, Any]] = None,
|
|
168
|
+
) -> tuple[int, Any]:
|
|
169
|
+
payload: dict[str, Any] = {}
|
|
170
|
+
if label is not None:
|
|
171
|
+
payload["label"] = label
|
|
172
|
+
if description is not None:
|
|
173
|
+
payload["description"] = description
|
|
174
|
+
if bundle_version is not None:
|
|
175
|
+
payload["bundleVersion"] = bundle_version
|
|
176
|
+
if data is not None:
|
|
177
|
+
payload["data"] = data
|
|
178
|
+
return self._post(f"{API_PREFIX}/projects/{project_id}/credentials/{credentials_id}", payload)
|
|
179
|
+
|
|
180
|
+
def project_delete_credential(self, project_id: str, credentials_id: str) -> tuple[int, Any]:
|
|
181
|
+
return self._delete(f"{API_PREFIX}/projects/{project_id}/credentials/{credentials_id}")
|
|
182
|
+
|
|
183
|
+
def project_credential_workflows(
|
|
184
|
+
self,
|
|
185
|
+
project_id: str,
|
|
186
|
+
credentials_id: str,
|
|
187
|
+
*,
|
|
188
|
+
page: int = 1,
|
|
189
|
+
page_size: int = 10,
|
|
190
|
+
) -> tuple[int, Any]:
|
|
191
|
+
return self._get(
|
|
192
|
+
f"{API_PREFIX}/projects/{project_id}/credentials/{credentials_id}/workflows",
|
|
193
|
+
{"page": page, "pageSize": page_size},
|
|
194
|
+
)
|
|
195
|
+
|
|
159
196
|
def project_workers(self, project_id: str, online_only: bool = False) -> tuple[int, Any]:
|
|
160
197
|
return self._get(
|
|
161
198
|
f"{API_PREFIX}/projects/{project_id}/workers",
|
|
@@ -98,6 +98,9 @@ All paths are under `/openapi/v1`.
|
|
|
98
98
|
| `project delete` | DELETE | `/projects/{id}` |
|
|
99
99
|
| `project credentials` | GET | `/projects/{id}/credentials` |
|
|
100
100
|
| `project create-credential` | POST | `/projects/{id}/credentials` |
|
|
101
|
+
| `project update-credential` | POST | `/projects/{id}/credentials/{credentialsId}` |
|
|
102
|
+
| `project delete-credential` | DELETE | `/projects/{id}/credentials/{credentialsId}` |
|
|
103
|
+
| `project credential-workflows` | GET | `/projects/{id}/credentials/{credentialsId}/workflows` |
|
|
101
104
|
| `project workers` | GET | `/projects/{id}/workers` |
|
|
102
105
|
| `workflow list` / `create` | GET / POST | `/projects/{id}/workflows` |
|
|
103
106
|
| `workflow update` | POST | `/projects/{id}/workflows/{wid}/settings` |
|
|
@@ -184,6 +187,16 @@ Requires `--project`. Also pass `--bundle` and `--type`. If `--name` / `--label`
|
|
|
184
187
|
Response is metadata only (`name` / `label` / `type` / `credentialsId`). Duplicate
|
|
185
188
|
`bundle+type+name` in the same project returns HTTP 409.
|
|
186
189
|
|
|
190
|
+
`project credentials` includes `credentialsId` for the commands below. Secrets are never returned.
|
|
191
|
+
|
|
192
|
+
## project update-credential / delete-credential / credential-workflows
|
|
193
|
+
|
|
194
|
+
Ask the user before update or delete.
|
|
195
|
+
|
|
196
|
+
- `project update-credential -p ID --credentials cred_…` changes label, remark, bundle version, or form data. Pass at least one of `--label`, `--description`, `--bundle-version`, `--file`. Omitted fields stay unchanged. An empty `--description` clears the remark. `--file -` merges form fields; masked or blank secret fields keep the stored value. Secrets are never printed. A TTY asks for confirmation unless `--yes`; `--json` does not prompt.
|
|
197
|
+
- `project delete-credential -p ID --credentials cred_…` soft-deletes a credential. HTTP 409 when a workflow still references it.
|
|
198
|
+
- `project credential-workflows -p ID --credentials cred_… [--page 1] [--page-size 10]` lists workflows that use the credential. No secrets. Same view permission as `project credentials`.
|
|
199
|
+
|
|
187
200
|
## Version conflicts on save-draft
|
|
188
201
|
|
|
189
202
|
`workflow save-draft` reads the current draft to obtain the optimistic-lock `version` unless you pass
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: buildify-cli
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.2.0
|
|
4
4
|
Summary: CLI for the Buildify open API: discover bundle nodes, author and test workflows (machine Bearer auth)
|
|
5
5
|
Requires-Python: >=3.10
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -65,7 +65,7 @@ interactive prompt. `config set-key api_key` still updates the current profile,
|
|
|
65
65
|
| — | `health`, `version`, `help` |
|
|
66
66
|
| `key` | `test` |
|
|
67
67
|
| `bundle` | `list`, `nodes`, `node-properties`, `node-relations`, `doc`, `cred-types`, `cred-properties` |
|
|
68
|
-
| `project` | `list`, `create`, `get`, `credentials`, `create-credential`, `workers` |
|
|
68
|
+
| `project` | `list`, `create`, `get`, `update`, `delete`, `credentials`, `create-credential`, `update-credential`, `delete-credential`, `credential-workflows`, `workers` |
|
|
69
69
|
| `workflow` | `list`, `create`, `get-draft`, `save-draft`, `validate`, `test-run`, `cancel-test`, `deploy`, `published`, `deployments`, `deployment`, `versions`, `get-version` |
|
|
70
70
|
| `config` | `init`, `set-key`, `add-profile`, `use`, `profiles`, `remove-profile`, `show` |
|
|
71
71
|
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "1.1.0"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|