Repository navigation
feat(no-ticket): get Workspace domains from the v2 API - #476
cloudsmith-iduffy wants to merge 9 commits into
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
Cache partitioning and redirect handling can allow credentials to cross API deployment boundaries.
2 open findings
What changed in this PR
Moves Workspace domain discovery to the configured v2 API, replacing production-specific domain tables.
Changes:
- Adds a shared v2 client and paginated Workspace-domain API.
- Introduces per-API-host domain caching and JSON output version 2.
- Updates credential helpers, tests, dependencies, and documentation.
| File | Description |
|---|---|
uv.lock |
Locks cloudsmith-api 2.0.38. |
pyproject.toml |
Raises the minimum SDK version. |
cloudsmith_cli/credential_helpers/workspace_domains.py |
Implements domain parsing and caching. |
cloudsmith_cli/credential_helpers/pnpm/installer.py |
Uses Workspace discovery. |
cloudsmith_cli/credential_helpers/docker/installer.py |
Uses Workspace discovery. |
cloudsmith_cli/credential_helpers/default_domains.py |
Removes the built-in domain table. |
cloudsmith_cli/credential_helpers/custom_domains.py |
Removes legacy custom-domain discovery. |
cloudsmith_cli/credential_helpers/common.py |
Validates hosts against Workspace domains. |
cloudsmith_cli/credential_helpers/cargo/installer.py |
Uses Workspace discovery. |
cloudsmith_cli/core/tests/test_workspaces.py |
Tests v2 domain requests and pagination. |
cloudsmith_cli/core/api/workspaces.py |
Adds the Workspace domains API wrapper. |
cloudsmith_cli/core/api/v2.py |
Adds the shared v2 HTTP client. |
cloudsmith_cli/core/api/orgs.py |
Removes the legacy domains call. |
cloudsmith_cli/core/api/metadata.py |
Migrates metadata calls to the v2 client. |
cloudsmith_cli/cli/tests/commands/test_workspace_domains.py |
Tests domain parsing and cache isolation. |
cloudsmith_cli/cli/tests/commands/test_domains.py |
Updates command behavior tests. |
cloudsmith_cli/cli/tests/commands/test_default_domains.py |
Removes obsolete table tests. |
cloudsmith_cli/cli/tests/commands/test_custom_domain_precedence.py |
Removes client-side precedence tests. |
cloudsmith_cli/cli/tests/commands/test_credential_helper.py |
Updates helper discovery tests. |
cloudsmith_cli/cli/tests/commands/test_credential_helper_install.py |
Updates installer cache tests. |
cloudsmith_cli/cli/commands/domains.py |
Emits API-supplied domains using schema v2. |
CHANGELOG.md |
Documents the breaking behavior changes. |
.oss-scanner/threat_model.md |
Updates the security-sensitive module path. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| response = client.rest_client.request( | ||
| method, | ||
| url, | ||
| query_params=query_params, | ||
| headers=_build_headers(client.config), | ||
| body=body, | ||
| _request_timeout=REQUEST_TIMEOUT_SECONDS, |
| host = urlparse(api_host).hostname if api_host else None | ||
| cache_dir = ( | ||
| Path(get_default_config_path()) | ||
| / "domains_cache" | ||
| / _safe_name(host or "default") | ||
| ) |
4e43950 to
47f388b
Compare
47f388b to
68a1c40
Compare
|
@copilot Can you modify my change so that its not a breaking change? perhaps we can introduce something like a --version 2 flag and introduce a notice for no flag being specified to say it will eventually be like --version 2 ? |
Implemented in 92ffe0c (test cleanup in 7c92e81).
1,547 non-integration tests passed; hooks passed and CodeQL reports no alerts. Existing repository-wide type-check diagnostics remain. |
|
@copilot can we modify the v1 behaviour slightly? Use the new api but keep the same format adding null fields if the data isn't available. |
Implemented in 7c12c8c.
1,552 non-integration tests passed, along with hooks and command type checking. CodeQL reports no alerts. |
Move the v2 HTTP client from core/api/metadata.py to core/api/v2.py so that other v2 endpoints can use it. Add request_url for absolute URLs such as pagination links. It refuses a URL on another scheme or host, so the API key goes only to the configured host. Give every v2 request a 30-second timeout. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Requests drops the Authorization header on a redirect to another host, but it sends the X-Api-Key header on. The v2 session now drops that header under the same rule. Add the copyright header to the new files. The CHANGELOG now says that the 30-second timeout applies to each attempt, because the CLI retries a request that times out. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ntial The v2 client read the API key and the SSO header back from the SDK Configuration. That copied the auth logic from initialise_api. Now each v2 call takes the CredentialResult that resolve_credentials gives, and uses its auth_headers(). Tests cover the API key, the SAML access token, no credential, the user agent, extra headers, the proxy and SSL verification. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The shared retry setup retries a request after a read timeout for every method. A slow POST that the server accepts is then sent again, and can create a second metadata entry. A v2 POST now gets only a connect timeout. The SAML metadata test now gets its bearer token only from the credential argument. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
create_requests_session now builds the session that drops X-Api-Key on a redirect to another host. The v1 SDK client, uploads, downloads and the v2 client all use it. Requests already drops the Authorization header in the same case. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Replace the built-in table of Cloudsmith hostnames and the v1
custom-domains call with GET /v2/workspaces/{workspace}/domains/. The
configured API host now supplies its own hosts, so the CLI works
against any Cloudsmith API host with no code change.
- Add core/api/workspaces.list_domains, which follows Link pagination.
- Rename credential_helpers/custom_domains.py to workspace_domains.py.
- Keep the domain order that the API returns.
- Keep one domain cache for each API host.
- Remove the [domains] config.ini override.
- Change the domains list JSON to version 2.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: cloudsmith-iduffy <178375997+cloudsmith-iduffy@users.noreply.github.com>
Co-authored-by: cloudsmith-iduffy <178375997+cloudsmith-iduffy@users.noreply.github.com>
Co-authored-by: cloudsmith-iduffy <178375997+cloudsmith-iduffy@users.noreply.github.com>
7c12c8c to
5378e7a
Compare

Description
The CLI kept its own table of Cloudsmith hostnames (
dl.cloudsmith.io,docker.cloudsmith.io, and the rest). That table pinned the CLI to production hostnames. On any other API host,cloudsmith domains listand the credential helpers still showed the production hosts.This PR removes the table. The CLI now asks the configured API host for the domains of a Workspace with
GET /v2/workspaces/{workspace}/domains/. That one call returns the Cloudsmith-owned domains and the Workspace's custom domains, already in preference order. A change of API host now needs no code change.Changes:
core/api/workspaces.list_domains, which follows theLink: rel="next"header through the shared v2 client.credential_helpers/custom_domains.pytoworkspace_domains.py. The CLI no longer sorts domains itself (by repository,primary, thencreated_at). The order the API returns is the priority, and the CLI keeps it. The enabled/validated checks are also removed, because the API lists only active domains.[domains]section inconfig.ini. Its only purpose was to replace the built-in table for other hosts.Type of Change
Additional Notes
Breaking change to
cloudsmith domains list. The JSON document is now version 2:primaryandcreated_atfields are removed. The API now gives the order.domain_typecan also becloudsmith_api.Checked against live API hosts. On production,
cloudsmith domains list --workspace cloudsmith --refreshreturns 23 domains: the custominstall.cloudsmith.comfirst, thendl.cloudsmith.io,docker.cloudsmith.io, and the other Cloudsmith-owned hosts. A second API host returned its own hosts, and the credential helpers matched each custom domain only on its own API host. An API host that does not serve the v2 endpoint yet makesdomains listexit with a 404. The credential helpers then fall back to their default hosts.The CLI docs in cloudsmith-docs need an update for the version 2 output and the removed
[domains]section after this is released.🤖 Generated with Claude Code