Skip to content

feat(ENG-13681): add cloudsmith domains list with custom-domain discovery - #337

Merged
cloudsmith-iduffy merged 3 commits into
masterfrom
custom-domains
Aug 9, 2026
Merged

feat(ENG-13681): add cloudsmith domains list with custom-domain discovery#337
cloudsmith-iduffy merged 3 commits into
masterfrom
custom-domains

Conversation

@cloudsmith-iduffy

@cloudsmith-iduffycloudsmith-iduffy commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Description

Adds cloudsmith domains list, which emits a versioned JSON document listing
the hosts Cloudsmith can authenticate — built-in *.cloudsmith.io service hosts
plus an organisation's custom domains.

  • Filters on the domain list.--format keeps the hosts usable for a package format: a host
    serving no single format serves every one, so the download CDN and the
    generic upload endpoint survive any --format. --repo keeps the hosts
    usable for a repository, most-preferred first. --domain-type is an exact match instead — a host has
    exactly one purpose — so pairing it with --format asks for a host
    speaking a format's own protocol.

  • --org is the name of the organisation option.--organization and
    --oidc-org remain as aliases, and org, organization or oidc_org are
    all accepted in config.ini. --oidc-org named the setting after the first
    feature that wanted it; custom-domain discovery reads it too, so it is now
    named after what it is. CLOUDSMITH_ORG is unchanged, and
    credential-helper install no longer carries a separate --org of its own.

  • A replaceable domain table. A dedicated deployment, serving packages from
    its own domains, can replace the built-in hosts via a [domains] section in
    config.ini. Each entry names the package format its host serves, or
    download/upload for the two endpoints no format names; an entry naming
    nothing recognisable is skipped with a warning rather than guessed at. This is
    honoured only from trusted configuration — your config directory,
    ~/.cloudsmith, or an explicit --config-file. A [domains] section in a
    directory-relative config.ini is ignored with a warning, because that file
    can be committed to a repository and this list decides which hosts may receive
    a credential.

  • Server-matching precedence between overlapping domains. A domain bound to
    the repository in hand beats an organisation-wide one, primary beats
    secondary, and the oldest breaks any remaining tie. With --repo the custom
    domains come back most-preferred first, so the first entry is the one
    Cloudsmith would bind for that repository.

  • A seven-day on-disk cache, with --refresh to bypass it

  • With no organisation configured, the command lists whatever custom domains an
    earlier run already cached, at no API cost, rather than enumerating every
    organisation the caller belongs to.

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation update
  • Refactoring
  • Other (please describe)

Comment threadcloudsmith_cli/cli/tests/commands/test_domains.py Fixed
Comment threadcloudsmith_cli/cli/tests/commands/test_domains.py Fixed
Comment threadcloudsmith_cli/cli/tests/commands/test_domains.py Fixed
@cloudsmith-iduffycloudsmith-iduffy changed the title custom domainsfeat(ENG-13681): add credential-helper domains with repository-scoped custom domainsAug 1, 2026
@BartoszBlizniakBartoszBlizniak mentioned this pull request Aug 3, 2026
6 tasks
Base automatically changed from credential-plumbing to masterAugust 4, 2026 15:37
Comment threadcloudsmith_cli/cli/tests/commands/test_domains.py Fixed
Comment threadcloudsmith_cli/cli/tests/commands/test_domains.py Fixed
Comment threadcloudsmith_cli/cli/tests/commands/test_domains.py Fixed
Comment threadcloudsmith_cli/cli/tests/commands/test_domains.py Fixed
Comment threadcloudsmith_cli/cli/tests/commands/test_domains.py Fixed
Comment threadcloudsmith_cli/cli/tests/commands/test_domains.py Fixed
Comment threadcloudsmith_cli/cli/tests/commands/test_domains.py Fixed
@cloudsmith-iduffycloudsmith-iduffy changed the title feat(ENG-13681): add credential-helper domains with repository-scoped custom domainsfeat(ENG-13681): add cloudsmith domains list with custom-domain discoveryAug 4, 2026
Comment threadcloudsmith_cli/cli/tests/commands/test_domains.py Dismissed
Comment threadcloudsmith_cli/cli/tests/commands/test_domains.py Dismissed
Comment threadcloudsmith_cli/cli/tests/commands/test_domains.py Dismissed
Comment threadcloudsmith_cli/cli/tests/commands/test_domains.py Fixed
Comment threadcloudsmith_cli/cli/tests/commands/test_domains.py Fixed
Comment threadcloudsmith_cli/cli/tests/commands/test_domains.py Fixed
Comment threadcloudsmith_cli/cli/tests/commands/test_domains.py Fixed
Comment threadcloudsmith_cli/cli/tests/commands/test_domains.py Fixed
Comment threadcloudsmith_cli/cli/tests/commands/test_domains.py Fixed
Comment threadcloudsmith_cli/cli/tests/commands/test_domains.py Dismissed
Comment threadcloudsmith_cli/cli/tests/commands/test_domains.py Fixed
Comment threadcloudsmith_cli/cli/tests/commands/test_domains.py Fixed
Comment threadcloudsmith_cli/cli/tests/commands/test_domains.py Fixed
Comment threadcloudsmith_cli/cli/tests/commands/test_domains.py Dismissed
Comment threadcloudsmith_cli/cli/tests/commands/test_domains.py Fixed
Comment threadcloudsmith_cli/cli/tests/commands/test_domains.py Dismissed
Emits a versioned JSON document naming the hosts Cloudsmith can authenticate
- the built-in `*.cloudsmith.io` service hosts plus an organisation's custom
domains - with the package format each serves and what each host is for
(`download`, `upload`, `native_api`), so a consumer picks a host without
pattern-matching on hostnames. Like `credential-helper generic` it is for
programmatic consumers and has no human-readable mode.
An organisation's own custom domains are listed ahead of the built-in hosts,
which are the fallback. Only usable hosts are listed: a custom domain that is
disabled or not yet validated serves nothing, so it is left out rather than
offered as somewhere to publish to. `--format`, `--repo` and `--domain-type`
narrow the list; with `--repo` the custom domains come back most-preferred
first, so the first entry is the one Cloudsmith would bind.
Alongside it:
- `--org` is the name of the organisation option, with `--organization` and
`--oidc-org` as aliases and `org`, `organization` or `oidc_org` accepted in
config.ini. `--oidc-org` named the setting after the first feature that
wanted it; custom-domain discovery reads it too. CLOUDSMITH_ORG is
unchanged, and `credential-helper install` no longer carries its own --org.
- A dedicated deployment serving packages from its own domains can replace the
built-in table via a `[domains]` section in config.ini, honoured only from
trusted configuration - your config directory, ~/.cloudsmith, or an explicit
--config-file. A section in a directory-relative config.ini is ignored with
a warning, since that file can be committed to a repository and this table
decides which hosts may receive a credential.
- Custom domain records carry the organisation they were discovered under and,
where the domain serves a single repository, which one. Overlapping domains
are ranked as the server would: bound to the repository in hand, then
primary, then oldest.
- A seven-day on-disk cache, with `--refresh` to bypass it. No failure is ever
cached, so a typo'd organisation fails loudly every time rather than being
replayed as a successful "no custom domains". With no organisation
configured the command lists what earlier runs cached, at no API cost.
Also fixed: `ApiException` was built without passing anything to `Exception`,
so rendering one as a string produced nothing at all and any message built by
interpolation stopped dead at the colon. It now renders as its status plus the
API's detail, which fixes the custom-domain lookup message along with the
`credential-helper install`/`uninstall` failures and the Docker
auto-discovery warning.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@cloudsmith-iduffy
cloudsmith-iduffy marked this pull request as ready for review August 5, 2026 01:30
@cloudsmith-iduffy
cloudsmith-iduffy requested a review from a team as a code ownerAugust 5, 2026 01:30
CopilotAI lite review requested due to automatic review settings August 5, 2026 01:30

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new cloudsmith domains list command to emit a versioned JSON document of Cloudsmith-authenticatable hosts (built-in service hosts plus org custom domains), and renames the organization setting to a unified --org (with aliases) so custom-domain discovery and OIDC exchange share the same configuration surface.

Changes:

  • Introduces cloudsmith domains list with filtering (--format, --repo, --domain-type) and a cache-backed custom-domain lookup.
  • Adds a trusted-config override for the built-in domain table via a [domains] section, while explicitly rejecting cwd config.ini for security.
  • Unifies organization configuration under --org/CLOUDSMITH_ORG/config.ini (org|organization|oidc_org) and threads it through credential-helper flows.

Reviewed changes

Copilot reviewed 23 out of 23 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
cloudsmith_cli/credential_helpers/docker/runtime.pyThreads org into Docker credential helper runtime matching.
cloudsmith_cli/credential_helpers/docker/installer.pyAdjusts Docker installer discovery logic for custom domains.
cloudsmith_cli/credential_helpers/default_domains.pyAdds built-in domain table with trusted-config override and untrusted-cwd guard.
cloudsmith_cli/credential_helpers/custom_domains.pyExpands custom-domain records, precedence ordering, and cache format/versioning.
cloudsmith_cli/credential_helpers/common.pyUpdates Cloudsmith-domain matching to accept resolved org rather than reading env directly.
cloudsmith_cli/credential_helpers/backends.pyAdds NIX backend kind.
cloudsmith_cli/core/credentials/providers/oidc_provider.pySwitches OIDC provider to use unified context.org.
cloudsmith_cli/core/credentials/models.pyRenames credential context field from oidc_org to org.
cloudsmith_cli/core/api/exceptions.pyImproves ApiException string rendering for clearer error messages.
cloudsmith_cli/conftest.pyAdds an autouse fixture to restore SDK default configuration between tests.
cloudsmith_cli/cli/tests/test_org_option.pyTests --org and config/env aliases all map to one organization value.
cloudsmith_cli/cli/tests/commands/test_domains.pyAdds test coverage for cloudsmith domains list document shape and filters.
cloudsmith_cli/cli/tests/commands/test_default_domains.pyTests built-in domain table plus trusted/untrusted config override behavior.
cloudsmith_cli/cli/tests/commands/test_custom_domain_precedence.pyTests precedence ordering and cache survivability of ranking fields.
cloudsmith_cli/cli/tests/commands/test_credential_helper.pyUpdates credential-helper tests for new cache format and org threading.
cloudsmith_cli/cli/tests/commands/test_credential_helper_install.pyUpdates installer tests for revised discovery behavior and org handling.
cloudsmith_cli/cli/decorators.pyAdds --org/--organization/--oidc-org aliasing and threads org into credential resolution.
cloudsmith_cli/cli/config.pyAdds org/organization config keys and maps legacy oidc_org to the same value.
cloudsmith_cli/cli/commands/domains.pyImplements cloudsmith domains list command and JSON document output.
cloudsmith_cli/cli/commands/credential_helper/manage.pyRemoves installer-specific --org and relies on shared resolved opts.org.
cloudsmith_cli/cli/commands/credential_helper/docker.pyPasses resolved opts.org through to Docker credential helper execution.
cloudsmith_cli/cli/commands/init.pyRegisters the new domains command module.
CHANGELOG.mdDocuments new domains command, org rename/aliasing, and [domains] override feature.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadcloudsmith_cli/cli/commands/domains.py
Comment threadcloudsmith_cli/credential_helpers/docker/installer.py Outdated
Comment threadcloudsmith_cli/credential_helpers/custom_domains.py
Comment threadcloudsmith_cli/cli/tests/commands/test_domains.py Dismissed
Review of `domains list` and the custom-domain path it shares with the
credential helpers turned up three defects.
- Restored the `dry_run` short-circuit ahead of discovery, and the two test
scenarios deleted with it. A preview was issuing a live authenticated call
and rewriting the on-disk cache.
- Custom domains are ranked by precedence whether or not `--repo` is given, so
the document agrees with `get_format_domains` about which host is active.
Records from a no-org listing are grouped by org first, since ranking one
organisation's hosts against another's expressed a preference the server
never made. A missing `created_at` sorted as the empty string, i.e. older
than every real timestamp, so the one domain whose age is unknown won
precedence.
- Creating the cache directory is no longer fatal, so `domains list` still
answers on a read-only HOME as its "always listed" promise implies.
`UnicodeDecodeError` escaped both readers, which catch `JSONDecodeError` and
`configparser.Error`; one corrupt cache file or a config.ini in a non-UTF-8
locale aborted the command instead of reading as absent.
Also: dropped `DomainType.API`. No domain is ever the Cloudsmith API, so the
value only ever matched nothing while being advertised as a valid purpose.
`get_format_domains` now forwards `configure_api` like its siblings.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Comment threadcloudsmith_cli/credential_helpers/default_domains.py

@BartoszBlizniakBartoszBlizniak left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one nit but lgtm

Comment threadcloudsmith_cli/cli/commands/domains.py
Add the same --page/--page-size/--page-all options other `list`
commands use, applied client-side to the combined built-in + custom
domain list. Unlike other commands it defaults to --page-all since
the list is small and locally assembled rather than backed by a live
paginated endpoint; passing --page or --page-size opts into paged
output with a `meta.pagination` block matching other JSON list output.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@cloudsmith-iduffy
cloudsmith-iduffy merged commit 8504c21 into masterAug 9, 2026
26 checks passed
@cloudsmith-iduffy
cloudsmith-iduffy deleted the custom-domains branch August 9, 2026 01:15
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@cloudsmith-iduffy@BartoszBlizniak@github-advanced-security