Uh oh!
There was an error while loading. Please reload this page.
feat: add OIDC detector enable/order controls - #311
Conversation
There was a problem hiding this comment.
Pull request overview
Integrates multiple new OIDC environment detectors (Bitbucket Pipelines, CircleCI, GitLab CI, GCP, and a generic fallback) into the CLI’s OIDC credential auto-discovery chain, and adds environment-variable controls to disable and/or reorder detector evaluation.
Changes:
- Added new OIDC detectors (Bitbucket, CircleCI, GitLab, GCP) plus a generic fallback, each with stable
slugs. - Implemented detector selection controls via
CLOUDSMITH_OIDC_<SLUG>_DISABLED=trueandCLOUDSMITH_OIDC_DETECTOR_ORDER=.... - Updated docs/packaging/CI to support the new detectors and optional
gcpdependency, and added unit tests for detectors + control logic.
Reviewed changes
Copilot reviewed 19 out of 19 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| setup.py | Adds google-auth under the gcp and all extras. |
| README.md | Documents GCP support, new detectors, and detector control env vars. |
| CHANGELOG.md | Records the new detectors and detector-control functionality under Unreleased. |
| .github/workflows/test.yml | Installs the editable package with the gcp extra so GCP tests run in CI. |
| cloudsmith_cli/core/credentials/oidc/detectors/base.py | Introduces shared DEFAULT_AUDIENCE and adds a base slug. |
| cloudsmith_cli/core/credentials/oidc/detectors/init.py | Registers new detectors and adds ordering/disable controls + registry accessor. |
| cloudsmith_cli/core/credentials/oidc/detectors/aws.py | Moves DEFAULT_AUDIENCE import to base and adds slug. |
| cloudsmith_cli/core/credentials/oidc/detectors/azure_devops.py | Adds slug to the detector. |
| cloudsmith_cli/core/credentials/oidc/detectors/github_actions.py | Moves DEFAULT_AUDIENCE import to base and adds slug. |
| cloudsmith_cli/core/credentials/oidc/detectors/bitbucket_pipelines.py | New Bitbucket Pipelines detector implementation. |
| cloudsmith_cli/core/credentials/oidc/detectors/circleci.py | New CircleCI detector implementation. |
| cloudsmith_cli/core/credentials/oidc/detectors/gitlab_ci.py | New GitLab CI detector implementation. |
| cloudsmith_cli/core/credentials/oidc/detectors/gcp.py | New Google Cloud detector implementation backed by google-auth. |
| cloudsmith_cli/core/credentials/oidc/detectors/generic.py | New generic env-var detector implementation for CLOUDSMITH_OIDC_TOKEN. |
| cloudsmith_cli/core/tests/test_bitbucket_pipelines_detector.py | Unit tests for Bitbucket detector + integration selection. |
| cloudsmith_cli/core/tests/test_circleci_detector.py | Unit tests for CircleCI detector + integration selection. |
| cloudsmith_cli/core/tests/test_gitlab_ci_detector.py | Unit tests for GitLab detector + integration selection. |
| cloudsmith_cli/core/tests/test_generic_detector.py | Unit tests for generic detector + integration selection. |
| cloudsmith_cli/core/tests/test_gcp_detector.py | Unit tests for GCP detector behavior and registration ordering. |
| cloudsmith_cli/core/tests/test_detector_controls.py | Unit tests for disable/order controls and slug uniqueness. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
b9338ea to
68ab21dCompareAdd two controls for OIDC detector selection, resolved through the credential context rather than read ad hoc from the environment: - CLOUDSMITH_OIDC_<ID>_DISABLED skips a specific detector (only the literal "true", case-insensitive, disables). The credentials decorator resolves these into context.oidc_disabled_detectors. - --oidc-detector-order (env var CLOUDSMITH_OIDC_DETECTOR_ORDER) overrides which detectors are considered and the order they are tried in (comma-separated ids; unlisted/unknown ids are skipped). When both are set the order list defines the candidate set and sequence, then the disabled set is applied on top, so a disabled detector is always skipped. Each detector gains a stable `id` attribute and a public `registered_detectors()` accessor is added. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
68ab21d to
19d1519CompareDuplicate detector ids in the order list previously ran the same detector once per occurrence, which is wasteful for detectors that hit metadata endpoints (e.g. AWS STS/IMDS). Duplicates now keep their first position so each detector is evaluated at most once. Also log at debug when the order/disable controls leave no detectors enabled, so an order string with no usable ids is diagnosable. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
BartoszBlizniak
left a comment
There was a problem hiding this comment.
Few comments there but overall happy to merge in 👍
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Address PR #311 review feedback: - Allow oidc_detector_order and oidc_disabled_detectors to be set in config.ini (under [default] or a profile). The config disabled list is additive with the per-detector CLOUDSMITH_OIDC_<ID>_DISABLED env vars; the --oidc-detector-order flag / env var still override the config order. - Surface a warning (in the CLI layer, where click lives) when --oidc-detector-order names unknown ids, or when the order/disable controls leave no detector enabled. Advisory only: the credential fallback chain is preserved rather than aborting with a UsageError, and the core detectors module stays click-free. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
What
Adds controls for OIDC detector selection to the credential auto-discovery chain, so a detector that matches an environment you don't want it to (for example, the AWS detector matching ambient instance credentials) can be disabled or reordered.
Controls
Both controls are resolved through the credential context — the same plumbing as the other
--oidc-*options — sodetect_environment()reads only from the context, never directly from the environment.CLOUDSMITH_OIDC_<ID>_DISABLED=trueskips it. Only the literal stringtrue(case-insensitive) disables; anything else leaves it enabled. The credentials decorator resolves these intocontext.oidc_disabled_detectors.--oidc-detector-order(or theCLOUDSMITH_OIDC_DETECTOR_ORDERenv var) takes a comma-separated list of detector ids and overrides both which detectors are considered and the order they are tried in (first match wins). Ids not listed are skipped; unknown ids are logged at debug and ignored.Precedence: the order list defines the candidate set and sequence, then the disabled set is applied on top — a disabled detector is always skipped even if it appears in the order list. With neither set, behaviour is identical to today's fixed priority order.
Detector ids:
aws,azure_devops,bitbucket,circleci,generic,github,gitlab.How
idattribute; theEnvironmentDetectorbase getsid = "base".detect_environment()selects via_ordered_detectors(order)+_enabled_detectors(order, disabled); a publicregistered_detectors()accessor is added;disabled_detectors_from_env()resolves the per-detector disable env vars.CredentialContextfieldsoidc_detector_orderandoidc_disabled_detectors, wired throughdecorators.py(the--oidc-detector-orderoption) andconfig.py, following the existing OIDC-option chain.Testing
cloudsmith_cli/core/tests/test_detector_controls.py(TDD): default order, per-detector disable (via context), env-var truthiness (trueonly), env resolution + var naming, order reordering, order limiting the candidate set, unknown-id-ignored, empty-order fallback, order+disable composition, and a registry id-uniqueness guard.black/flake8/isort/pyupgrade/pylint(10/10)/typosall pass.Note for reviewers
Google Cloud (
gcp) is not part of this PR — it isn't inmasteryet. #306 layers the GCP detector (and itsid = "gcp") on top of this branch and is targeted at it.🤖 Generated with Claude Code