Skip to content

Commit aec80d4

Browse files
docs(readme): mark org_id/workspace_id optional for single-org tokens (#22)
PyPI README's Configuration table marked org_id / workspace_id as required, but single-org / single-workspace tokens (which is what every fresh user starts with) are auto-resolved server-side. The Required label scared fresh devs into looking up IDs they did not need. - README: drop org_id / workspace_id from Quick Start and error-handling examples; restructure Configuration table with Required + Notes columns explaining auto-resolution. - tests: add a regression test confirming Devhelm() can be constructed with just a token (no env vars, no extra args). The constructor itself already accepted None for both args (see DevhelmConfig in src/devhelm/_http.py); this PR aligns the public docs with the long-standing behaviour. No code-path change, no version bump. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 7c7b593 commit aec80d4

2 files changed

Lines changed: 39 additions & 14 deletions

File tree

README.md

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,7 @@ pip install devhelm
1313
```python
1414
from devhelm import Devhelm
1515

16-
client = Devhelm(
17-
token="your-api-token",
18-
org_id="your-org-id",
19-
workspace_id="your-workspace-id",
20-
)
16+
client = Devhelm(token="your-api-token")
2117

2218
# List all monitors
2319
monitors = client.monitors.list()
@@ -55,20 +51,20 @@ client.monitors.delete(monitor.id)
5551
from devhelm import Devhelm
5652

5753
client = Devhelm(
58-
token="your-api-token", # required (or DEVHELM_API_TOKEN env var)
59-
org_id="1", # required (or DEVHELM_ORG_ID env var)
60-
workspace_id="1", # required (or DEVHELM_WORKSPACE_ID env var)
54+
token="your-api-token", # required (or DEVHELM_API_TOKEN env var)
55+
org_id="1", # optional — see notes below
56+
workspace_id="1", # optional — see notes below
6157
base_url="https://api.devhelm.io", # optional, defaults to production
6258
)
6359
```
6460

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

67-
| Parameter | Env Variable |
68-
| -------------- | ----------------------- |
69-
| `token` | `DEVHELM_API_TOKEN` |
70-
| `org_id` | `DEVHELM_ORG_ID` |
71-
| `workspace_id` | `DEVHELM_WORKSPACE_ID` |
63+
| Parameter | Required | Env Variable | Notes |
64+
| -------------- | -------- | ---------------------- | -------------------------------------------------------------------------------------------------------- |
65+
| `token` | Yes | `DEVHELM_API_TOKEN` | Personal or workspace API token. |
66+
| `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. |
67+
| `workspace_id` | No | `DEVHELM_WORKSPACE_ID` | Auto-resolved if your token is scoped to one workspace. Required only when the token spans multiple. |
7268

7369
## Resources
7470

@@ -135,7 +131,7 @@ Every `DevhelmApiError` carries:
135131
```python
136132
from devhelm import Devhelm, DevhelmAuthError, DevhelmError
137133

138-
client = Devhelm(token="bad-token", org_id="1", workspace_id="1")
134+
client = Devhelm(token="bad-token")
139135

140136
try:
141137
client.monitors.list()

tests/test_client.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import pytest
66

77
from devhelm import Devhelm
8+
from devhelm._http import DevhelmConfig
89
from devhelm.resources.alert_channels import AlertChannels
910
from devhelm.resources.api_keys import ApiKeys
1011
from devhelm.resources.dependencies import Dependencies
@@ -131,3 +132,31 @@ def test_domains_sub_resource(self, client: Devhelm) -> None:
131132
assert callable(d.add)
132133
assert callable(d.verify)
133134
assert callable(d.remove)
135+
136+
137+
class TestClientOptionalTenantArgs:
138+
"""`org_id` / `workspace_id` are optional — single-tenant tokens
139+
auto-resolve them server-side, so the README quickstart and the
140+
constructor must work with just a token (the most common case).
141+
"""
142+
143+
def test_constructible_without_org_or_workspace(
144+
self, monkeypatch: pytest.MonkeyPatch
145+
) -> None:
146+
# Strip any env fallback so we prove the constructor itself accepts
147+
# missing tenant args, not that the test environment leaks them in.
148+
monkeypatch.delenv("DEVHELM_ORG_ID", raising=False)
149+
monkeypatch.delenv("DEVHELM_WORKSPACE_ID", raising=False)
150+
151+
client = Devhelm(token="test-token", base_url="http://localhost:8080")
152+
153+
assert client.monitors is not None
154+
assert client.incidents is not None
155+
156+
def test_config_defaults_tenant_ids_to_none(self) -> None:
157+
# Documents the API contract: leaving them unset on the config
158+
# dataclass yields ``None``, which ``build_client`` then resolves
159+
# via env var or the server-side default.
160+
config = DevhelmConfig(token="test-token")
161+
assert config.org_id is None
162+
assert config.workspace_id is None

0 commit comments

Comments
 (0)