Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 10 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,7 @@ pip install devhelm
```python
from devhelm import Devhelm

client = Devhelm(
token="your-api-token",
org_id="your-org-id",
workspace_id="your-workspace-id",
)
client = Devhelm(token="your-api-token")

# List all monitors
monitors = client.monitors.list()
Expand Down Expand Up @@ -55,20 +51,20 @@ client.monitors.delete(monitor.id)
from devhelm import Devhelm

client = Devhelm(
token="your-api-token", # required (or DEVHELM_API_TOKEN env var)
org_id="1", # required (or DEVHELM_ORG_ID env var)
workspace_id="1", # required (or DEVHELM_WORKSPACE_ID env var)
token="your-api-token", # required (or DEVHELM_API_TOKEN env var)
org_id="1", # optional — see notes below
workspace_id="1", # optional — see notes below
base_url="https://api.devhelm.io", # optional, defaults to production
)
```

Environment variables are used as fallbacks when constructor arguments are not provided:

| Parameter | Env Variable |
| -------------- | ----------------------- |
| `token` | `DEVHELM_API_TOKEN` |
| `org_id` | `DEVHELM_ORG_ID` |
| `workspace_id` | `DEVHELM_WORKSPACE_ID` |
| Parameter | Required | Env Variable | Notes |
| -------------- | -------- | ---------------------- | -------------------------------------------------------------------------------------------------------- |
| `token` | Yes | `DEVHELM_API_TOKEN` | Personal or workspace API token. |
| `org_id` | No | `DEVHELM_ORG_ID` | Auto-resolved if your token is scoped to one org. Required only when the token has access to multiple. |
| `workspace_id` | No | `DEVHELM_WORKSPACE_ID` | Auto-resolved if your token is scoped to one workspace. Required only when the token spans multiple. |

## Resources

Expand Down Expand Up @@ -135,7 +131,7 @@ Every `DevhelmApiError` carries:
```python
from devhelm import Devhelm, DevhelmAuthError, DevhelmError

client = Devhelm(token="bad-token", org_id="1", workspace_id="1")
client = Devhelm(token="bad-token")

try:
client.monitors.list()
Expand Down
29 changes: 29 additions & 0 deletions tests/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import pytest

from devhelm import Devhelm
from devhelm._http import DevhelmConfig
from devhelm.resources.alert_channels import AlertChannels
from devhelm.resources.api_keys import ApiKeys
from devhelm.resources.dependencies import Dependencies
Expand Down Expand Up @@ -131,3 +132,31 @@ def test_domains_sub_resource(self, client: Devhelm) -> None:
assert callable(d.add)
assert callable(d.verify)
assert callable(d.remove)


class TestClientOptionalTenantArgs:
"""`org_id` / `workspace_id` are optional — single-tenant tokens
auto-resolve them server-side, so the README quickstart and the
constructor must work with just a token (the most common case).
"""

def test_constructible_without_org_or_workspace(
self, monkeypatch: pytest.MonkeyPatch
) -> None:
# Strip any env fallback so we prove the constructor itself accepts
# missing tenant args, not that the test environment leaks them in.
monkeypatch.delenv("DEVHELM_ORG_ID", raising=False)
monkeypatch.delenv("DEVHELM_WORKSPACE_ID", raising=False)

client = Devhelm(token="test-token", base_url="http://localhost:8080")

assert client.monitors is not None
assert client.incidents is not None

def test_config_defaults_tenant_ids_to_none(self) -> None:
# Documents the API contract: leaving them unset on the config
# dataclass yields ``None``, which ``build_client`` then resolves
# via env var or the server-side default.
config = DevhelmConfig(token="test-token")
assert config.org_id is None
assert config.workspace_id is None
Loading