diff --git a/ddtrace/internal/ci_visibility/git_client.py b/ddtrace/internal/ci_visibility/git_client.py index 3e8f35844b2..7bc08ca4195 100644 --- a/ddtrace/internal/ci_visibility/git_client.py +++ b/ddtrace/internal/ci_visibility/git_client.py @@ -22,6 +22,7 @@ from ddtrace.ext.git import extract_commit_sha from ddtrace.ext.git import extract_git_version from ddtrace.ext.git import extract_remote_url +from ddtrace.ext.git import extract_workspace_path from ddtrace.internal.agent import get_trace_url from ddtrace.internal.compat import JSONDecodeError from ddtrace.internal.logger import get_logger @@ -94,8 +95,20 @@ def __init__( elif self._requests_mode == REQUESTS_MODE.AGENTLESS_EVENTS: self._base_url = "https://api.{}{}".format(os.getenv("DD_SITE", AGENTLESS_DEFAULT_SITE), GIT_API_BASE_PATH) + def _get_git_dir(self, cwd=None): + # type: (Optional[str]) -> Optional[str] + try: + return extract_workspace_path(cwd=cwd) + except (FileNotFoundError, ValueError): + return None + def upload_git_metadata(self, cwd=None): # type: (Optional[str]) -> None + if not self._get_git_dir(cwd=cwd): + log.debug("Missing .git directory; skipping git metadata upload") + self._metadata_upload_status.value = METADATA_UPLOAD_STATUS.FAILED # type: ignore[attr-defined] + return + self._tags = ci.tags(cwd=cwd) if self._worker is None: self._worker = Process( diff --git a/releasenotes/notes/ci_visibility-fix_logged_errors_when_gitless-66a6cb3245314f3e.yaml b/releasenotes/notes/ci_visibility-fix_logged_errors_when_gitless-66a6cb3245314f3e.yaml new file mode 100644 index 00000000000..f248c2ad640 --- /dev/null +++ b/releasenotes/notes/ci_visibility-fix_logged_errors_when_gitless-66a6cb3245314f3e.yaml @@ -0,0 +1,4 @@ +--- +fixes: + - CI Visibility: fixes unnecessary logging of an exception that would appear when trying to upload git metadata in + an environment without functioning git (eg: missing ``git`` binary or ``.git`` directory) diff --git a/tests/ci_visibility/test_ci_visibility.py b/tests/ci_visibility/test_ci_visibility.py index 86cdd96012a..c2f0723c031 100644 --- a/tests/ci_visibility/test_ci_visibility.py +++ b/tests/ci_visibility/test_ci_visibility.py @@ -999,6 +999,7 @@ def mock_git_client(self): _get_filtered_revisions=mock.Mock(return_value="latest3\nlatest4"), _upload_packfiles=mock.Mock(side_effec=NotImplementedError), _do_request=mock.Mock(side_effect=NotImplementedError), + _get_git_dir=mock.Mock(return_value="does_not_matter"), ), mock.patch( "ddtrace.internal.ci_visibility.git_client._build_git_packfiles_with_details" ) as mock_build_packfiles: @@ -1082,6 +1083,15 @@ def test_upload_git_metadata_upload_unnecessary(self, api_key, requests_mode): git_client.upload_git_metadata() assert git_client.wait_for_metadata_upload_status() == METADATA_UPLOAD_STATUS.UNNECESSARY + @pytest.mark.parametrize("api_key, requests_mode", api_key_requests_mode_parameters) + def test_upload_git_metadata_upload_no_git_dir(self, api_key, requests_mode): + with mock.patch.object(CIVisibilityGitClient, "_get_git_dir", mock.Mock(return_value=None)): + git_client = CIVisibilityGitClient(api_key, requests_mode) + git_client.upload_git_metadata() + + # Notably, this should _not_ raise ValueError + assert git_client.wait_for_metadata_upload_status() == METADATA_UPLOAD_STATUS.FAILED + def test_get_filtered_revisions(): with mock.patch( diff --git a/tests/contrib/pytest/test_pytest.py b/tests/contrib/pytest/test_pytest.py index 33cc6ebc811..ee0188d1489 100644 --- a/tests/contrib/pytest/test_pytest.py +++ b/tests/contrib/pytest/test_pytest.py @@ -3940,7 +3940,11 @@ def test_add_two_number_list(): ) self.testdir.chdir() - with mock.patch("ddtrace.ext.git._get_executable_path", return_value=None): + with mock.patch("ddtrace.ext.git._get_executable_path", return_value=None), mock.patch( + "ddtrace.internal.ci_visibility.recorder.ddconfig", + _get_default_civisibility_ddconfig(), + ) as mock_ddconfig: + mock_ddconfig._ci_visibility_agentless_enabled = True self.inline_run("--ddtrace") spans = self.pop_spans()