Skip to content

Commit 11103af

Browse files
authored
fix: honor org git metadata settings for experiments (#486)
Experiments now capture commit and branch metadata when an organization has enabled git metadata collection, even if callers do not pass git_metadata_settings explicitly. This restores the expected default behavior for orgs collecting all git fields or selected fields, while keeping metadata disabled for orgs without a saved collection policy.
1 parent db9f564 commit 11103af

2 files changed

Lines changed: 69 additions & 4 deletions

File tree

py/src/braintrust/logger.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1659,10 +1659,13 @@ def compute_metadata():
16591659
if repo_info:
16601660
repo_info_arg = repo_info
16611661
else:
1662-
merged_git_metadata_settings = GitMetadataSettings.merge(
1663-
state.git_metadata_settings or GitMetadataSettings(collect="all"),
1664-
git_metadata_settings or GitMetadataSettings(collect="none"),
1665-
)
1662+
if git_metadata_settings is None:
1663+
merged_git_metadata_settings = state.git_metadata_settings or GitMetadataSettings(collect="none")
1664+
else:
1665+
merged_git_metadata_settings = GitMetadataSettings.merge(
1666+
state.git_metadata_settings or GitMetadataSettings(collect="all"),
1667+
git_metadata_settings,
1668+
)
16661669
repo_info_arg = get_repo_info(merged_git_metadata_settings)
16671670

16681671
if repo_info_arg:

py/src/braintrust/test_logger.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
logger,
2424
)
2525
from braintrust.db_fields import AUDIT_METADATA_FIELD
26+
from braintrust.git_fields import GitMetadataSettings, RepoInfo
2627
from braintrust.gitutil import get_repo_info
2728
from braintrust.id_gen import OTELIDGenerator, get_id_generator
2829
from braintrust.logger import (
@@ -175,6 +176,67 @@ def test_init_disable_atexit_flush(self):
175176
_HTTPBackgroundLogger(LazyValue(api_con_response, use_mutex=False)) # type: ignore
176177
mock_register.assert_not_called()
177178

179+
def test_init_without_git_metadata_override_uses_org_policy(self):
180+
for org_settings in (
181+
GitMetadataSettings(collect="all"),
182+
GitMetadataSettings(collect="some", fields=["commit", "branch"]),
183+
):
184+
with self.subTest(org_settings=org_settings):
185+
mock_conn = MagicMock()
186+
mock_conn.post_json.return_value = {
187+
"project": {"id": "test-project-id", "name": "test-project"},
188+
"experiment": {"id": "test-exp-id", "name": "test-exp"},
189+
}
190+
191+
simulate_login()
192+
logger._state.git_metadata_settings = org_settings
193+
with patch.object(logger._state, "app_conn", return_value=mock_conn):
194+
with patch(
195+
"braintrust.logger.get_repo_info", return_value=RepoInfo(commit="abc123")
196+
) as mock_get_repo_info:
197+
exp = braintrust.init(project="test-project")
198+
exp._lazy_metadata.get()
199+
200+
actual_settings = mock_get_repo_info.call_args.args[0]
201+
assert actual_settings == org_settings
202+
203+
def test_init_git_metadata_override_merges_with_org_policy(self):
204+
mock_conn = MagicMock()
205+
mock_conn.post_json.return_value = {
206+
"project": {"id": "test-project-id", "name": "test-project"},
207+
"experiment": {"id": "test-exp-id", "name": "test-exp"},
208+
}
209+
210+
simulate_login()
211+
logger._state.git_metadata_settings = GitMetadataSettings(collect="some", fields=["commit", "branch"])
212+
with patch.object(logger._state, "app_conn", return_value=mock_conn):
213+
with patch("braintrust.logger.get_repo_info", return_value=None) as mock_get_repo_info:
214+
exp = braintrust.init(
215+
project="test-project",
216+
git_metadata_settings=GitMetadataSettings(collect="some", fields=["commit"]),
217+
)
218+
exp._lazy_metadata.get()
219+
220+
actual_settings = mock_get_repo_info.call_args.args[0]
221+
assert actual_settings == GitMetadataSettings(collect="some", fields=["commit"])
222+
223+
def test_init_without_git_metadata_policy_collects_none(self):
224+
mock_conn = MagicMock()
225+
mock_conn.post_json.return_value = {
226+
"project": {"id": "test-project-id", "name": "test-project"},
227+
"experiment": {"id": "test-exp-id", "name": "test-exp"},
228+
}
229+
230+
simulate_login()
231+
assert logger._state.git_metadata_settings is None
232+
with patch.object(logger._state, "app_conn", return_value=mock_conn):
233+
with patch("braintrust.logger.get_repo_info", return_value=None) as mock_get_repo_info:
234+
exp = braintrust.init(project="test-project")
235+
exp._lazy_metadata.get()
236+
237+
actual_settings = mock_get_repo_info.call_args.args[0]
238+
assert actual_settings == GitMetadataSettings(collect="none")
239+
178240
def test_init_with_saved_parameters_attaches_reference(self):
179241
mock_conn = MagicMock()
180242
mock_conn.post_json.return_value = {

0 commit comments

Comments
 (0)