doover-cli 0.5.3__tar.gz → 0.5.4__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.
- {doover_cli-0.5.3 → doover_cli-0.5.4}/PKG-INFO +1 -1
- {doover_cli-0.5.3 → doover_cli-0.5.4}/pyproject.toml +4 -1
- {doover_cli-0.5.3 → doover_cli-0.5.4}/src/doover_cli/__init__.py +2 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/src/doover_cli/apps/apps.py +10 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/tests/test_apps.py +45 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/uv.lock +0 -1
- {doover_cli-0.5.3 → doover_cli-0.5.4}/.github/CONTRIBUTING.md +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/.github/ISSUE_TEMPLATE/bug-report.yaml +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/.github/ISSUE_TEMPLATE/feature-request.yml +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/.github/workflows/lint-test.yml +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/.github/workflows/release-brew.yml +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/.github/workflows/release-pypi.yml +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/.github/workflows/release.yml +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/.gitignore +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/.pre-commit-config.yaml +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/AGENT.md +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/LICENSE +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/README.md +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/debian/changelog +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/debian/control +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/debian/rules +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/docs/user_stories.md +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/src/doover_cli/agent.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/src/doover_cli/api/__init__.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/src/doover_cli/api/auth.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/src/doover_cli/api/errors.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/src/doover_cli/api/session.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/src/doover_cli/apps/app_install.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/src/doover_cli/apps/device.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/src/doover_cli/apps/device_type.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/src/doover_cli/apps/tunnel.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/src/doover_cli/channel.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/src/doover_cli/colours.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/src/doover_cli/config_schema.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/src/doover_cli/dda_logs.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/src/doover_cli/doover_config.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/src/doover_cli/grpc.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/src/doover_cli/login.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/src/doover_cli/renderer/__init__.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/src/doover_cli/renderer/_base.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/src/doover_cli/renderer/_basic.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/src/doover_cli/renderer/_default.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/src/doover_cli/renderer/_json.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/src/doover_cli/report.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/src/doover_cli/simulator.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/src/doover_cli/ui_schema.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/src/doover_cli/user.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/src/doover_cli/utils/__init__.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/src/doover_cli/utils/api.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/src/doover_cli/utils/apps.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/src/doover_cli/utils/context.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/src/doover_cli/utils/crud/__init__.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/src/doover_cli/utils/crud/commands.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/src/doover_cli/utils/crud/lookup.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/src/doover_cli/utils/crud/prompting.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/src/doover_cli/utils/crud/schema.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/src/doover_cli/utils/crud/values.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/src/doover_cli/utils/errors.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/src/doover_cli/utils/formatters.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/src/doover_cli/utils/misc.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/src/doover_cli/utils/parsers.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/src/doover_cli/utils/prompt.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/src/doover_cli/utils/sentry.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/src/doover_cli/utils/shell_commands.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/src/doover_cli/utils/state.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/tests/__init__.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/tests/conftest.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/tests/test_agent.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/tests/test_app_install.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/tests/test_auth_integration.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/tests/test_auth_unit.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/tests/test_basic.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/tests/test_crud_commands.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/tests/test_crud_lookup.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/tests/test_crud_prompting.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/tests/test_crud_schema.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/tests/test_crud_values.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/tests/test_default_renderer.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/tests/test_device.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/tests/test_device_cli_integration.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/tests/test_device_type.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/tests/test_device_type_cli_integration.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/tests/test_prompt.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/tests/test_sentry.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/tests/test_user.py +0 -0
- {doover_cli-0.5.3 → doover_cli-0.5.4}/tests/test_utils_apps.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "doover-cli"
|
|
3
|
-
|
|
3
|
+
dynamic = ["version"]
|
|
4
4
|
description = "CLI for Doover"
|
|
5
5
|
requires-python = ">=3.11"
|
|
6
6
|
dependencies = [
|
|
@@ -26,6 +26,9 @@ dependencies = [
|
|
|
26
26
|
requires = ["hatchling"]
|
|
27
27
|
build-backend = "hatchling.build"
|
|
28
28
|
|
|
29
|
+
[tool.hatch.version]
|
|
30
|
+
path = "src/doover_cli/__init__.py"
|
|
31
|
+
|
|
29
32
|
[project.scripts]
|
|
30
33
|
doover = "doover_cli:main"
|
|
31
34
|
|
|
@@ -1007,6 +1007,16 @@ def publish(
|
|
|
1007
1007
|
|
|
1008
1008
|
client, renderer = get_state()
|
|
1009
1009
|
|
|
1010
|
+
# The publish endpoints are organisation-scoped: without the
|
|
1011
|
+
# X-Doover-Organisation header the control plane rejects the request with
|
|
1012
|
+
# 401 "X-Doover-Organisation header missing" for any non-staff account.
|
|
1013
|
+
# Pin the client to the app's organisation (staging-aware, resolved into the
|
|
1014
|
+
# payload above) so every publish sub-call - create/partial, widget upload,
|
|
1015
|
+
# processor source + version release - carries the header.
|
|
1016
|
+
publish_org_id = payload.get("organisation_id")
|
|
1017
|
+
if publish_org_id is not None:
|
|
1018
|
+
client.organisation_id = int(publish_org_id)
|
|
1019
|
+
|
|
1010
1020
|
rich.print(
|
|
1011
1021
|
f"Updating application on doover site ({_control_base_url() or 'unknown base URL'})...\n"
|
|
1012
1022
|
)
|
|
@@ -491,6 +491,51 @@ def test_app_publish_updates_existing_application(monkeypatch, tmp_path):
|
|
|
491
491
|
assert renderer.render_calls == [{"id": 101, "published": True}]
|
|
492
492
|
|
|
493
493
|
|
|
494
|
+
def test_app_publish_pins_client_to_app_organisation(monkeypatch, tmp_path):
|
|
495
|
+
# Regression: publish must set the org context on the client so the
|
|
496
|
+
# X-Doover-Organisation header is sent. Without it the control plane
|
|
497
|
+
# returns 401 "X-Doover-Organisation header missing" for non-staff accounts.
|
|
498
|
+
captured = {}
|
|
499
|
+
renderer = FakeRenderer()
|
|
500
|
+
app_config = FakeAppConfig(app_id=101)
|
|
501
|
+
|
|
502
|
+
class FakeApplicationsClient:
|
|
503
|
+
@staticmethod
|
|
504
|
+
def partial(application_id, body):
|
|
505
|
+
captured["partial"] = (application_id, body)
|
|
506
|
+
return {"id": int(application_id), "published": True}
|
|
507
|
+
|
|
508
|
+
class FakeControlClient:
|
|
509
|
+
organisation_id = None
|
|
510
|
+
applications = FakeApplicationsClient()
|
|
511
|
+
|
|
512
|
+
client = FakeControlClient()
|
|
513
|
+
|
|
514
|
+
monkeypatch.setattr(
|
|
515
|
+
"doover_cli.apps.apps.get_app_directory", lambda root=None: tmp_path
|
|
516
|
+
)
|
|
517
|
+
monkeypatch.setattr(
|
|
518
|
+
"doover_cli.apps.apps.get_app_config", lambda root_fp, app_name=None: app_config
|
|
519
|
+
)
|
|
520
|
+
monkeypatch.setattr(
|
|
521
|
+
"doover_cli.apps.apps.get_state", lambda: (client, renderer)
|
|
522
|
+
)
|
|
523
|
+
monkeypatch.setattr(
|
|
524
|
+
"doover_cli.apps.apps.export_config_command",
|
|
525
|
+
lambda ctx, app_fp, validate_: None,
|
|
526
|
+
)
|
|
527
|
+
monkeypatch.setattr(
|
|
528
|
+
"doover_cli.apps.apps.export_ui_command",
|
|
529
|
+
lambda ctx, app_fp, validate_: None,
|
|
530
|
+
)
|
|
531
|
+
|
|
532
|
+
result = runner.invoke(app, ["app", "publish", str(tmp_path)])
|
|
533
|
+
|
|
534
|
+
assert result.exit_code == 0
|
|
535
|
+
assert client.organisation_id == 17
|
|
536
|
+
assert captured["partial"][0] == "101"
|
|
537
|
+
|
|
538
|
+
|
|
494
539
|
def test_app_publish_creates_then_updates_when_missing(monkeypatch, tmp_path):
|
|
495
540
|
captured = {}
|
|
496
541
|
renderer = FakeRenderer()
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|