Skip to content

Commit 61dc52d

Browse files
fix: deduplicate ids in --oidc-detector-order
Duplicate 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>
1 parent 19d1519 commit 61dc52d

2 files changed

Lines changed: 24 additions & 5 deletions

File tree

cloudsmith_cli/core/credentials/oidc/detectors/__init__.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,24 +61,25 @@ def _ordered_detectors(order: str | None) -> list[type[EnvironmentDetector]]:
6161
6262
When ``order`` is unset/empty the default registration order is used.
6363
Otherwise only the listed ids are considered, in the listed order;
64-
unknown ids are logged and skipped.
64+
unknown ids are logged and skipped, and duplicate ids keep their first
65+
position so each detector is evaluated at most once.
6566
"""
6667
raw_order = (order or "").strip()
6768
if not raw_order:
6869
return list(_DETECTORS)
6970

7071
detectors_by_id = {detector_cls.id: detector_cls for detector_cls in _DETECTORS}
71-
ordered: list[type[EnvironmentDetector]] = []
72+
ordered: dict[str, type[EnvironmentDetector]] = {}
7273
for token in raw_order.split(","):
7374
identifier = token.strip().lower()
74-
if not identifier:
75+
if not identifier or identifier in ordered:
7576
continue
7677
detector_cls = detectors_by_id.get(identifier)
7778
if detector_cls is None:
7879
logger.debug("Ignoring unknown OIDC detector id: %s", identifier)
7980
continue
80-
ordered.append(detector_cls)
81-
return ordered
81+
ordered[identifier] = detector_cls
82+
return list(ordered.values())
8283

8384

8485
def _enabled_detectors(
@@ -99,6 +100,8 @@ def detect_environment(
99100
enabled = _enabled_detectors(
100101
context.oidc_detector_order, context.oidc_disabled_detectors
101102
)
103+
if not enabled:
104+
logger.debug("No OIDC detectors enabled after applying order/disable controls")
102105
for detector_cls in enabled:
103106
detector = detector_cls(context=context)
104107
try:

cloudsmith_cli/core/tests/test_detector_controls.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Copyright 2026 Cloudsmith Ltd
22
"""Tests for OIDC detector selection controls (disable set + order)."""
33

4+
import logging
45
from unittest import mock
56

67
import pytest
@@ -116,6 +117,21 @@ def test_empty_order_falls_back_to_default(self, fake_detectors):
116117
detector = detect_environment(_context(oidc_detector_order=" "))
117118
assert isinstance(detector, AlphaDetector)
118119

120+
def test_duplicate_ids_run_each_detector_once(self, fake_detectors):
121+
with mock.patch.object(
122+
AlphaDetector, "detect", return_value=False
123+
) as alpha_detect:
124+
detector = detect_environment(
125+
_context(oidc_detector_order="alpha,alpha,bravo")
126+
)
127+
assert isinstance(detector, BravoDetector)
128+
assert alpha_detect.call_count == 1
129+
130+
def test_order_with_no_usable_ids_disables_detection(self, fake_detectors, caplog):
131+
with caplog.at_level(logging.DEBUG):
132+
assert detect_environment(_context(oidc_detector_order="nope,!")) is None
133+
assert "No OIDC detectors enabled" in caplog.text
134+
119135

120136
class TestOrderAndDisableCompose:
121137
def test_disable_wins_over_order(self, fake_detectors):

0 commit comments

Comments
 (0)