diff --git a/ddtrace/sourcecode/_utils.py b/ddtrace/sourcecode/_utils.py index 8397327664c..f41a9f7cce2 100644 --- a/ddtrace/sourcecode/_utils.py +++ b/ddtrace/sourcecode/_utils.py @@ -1,5 +1,5 @@ +import os import re -import subprocess from urllib import parse @@ -56,15 +56,23 @@ def normalize_repository_url(url): def _query_git(args): + import subprocess # don't import subprocess (and maybe activate the integration) if not needed + ver = subprocess.Popen(["git"] + args, stdout=subprocess.PIPE).communicate()[0] return ver.strip().decode("utf-8") def get_commit_sha(): + commit_sha = os.environ.get("DD_GIT_COMMIT_SHA") + if commit_sha: + return commit_sha return _query_git(["rev-parse", "HEAD"]) def get_repository_url(): + repository_url = os.environ.get("DD_GIT_REPOSITORY_URL") + if repository_url: + return repository_url return _query_git(["config", "--get", "remote.origin.url"]) diff --git a/releasenotes/notes/sourcecode-check-env-vars-cab3d9b6311c2695.yaml b/releasenotes/notes/sourcecode-check-env-vars-cab3d9b6311c2695.yaml new file mode 100644 index 00000000000..9f96e3dae8a --- /dev/null +++ b/releasenotes/notes/sourcecode-check-env-vars-cab3d9b6311c2695.yaml @@ -0,0 +1,5 @@ +--- +fixes: + - | + source code integration: check that ``DD_GIT_COMMIT_SHA`` and ``DD_GIT_REPOSITORY_URL`` are defined before + using the git command. diff --git a/tests/sourcecode/test_source_code_env_vars.py b/tests/sourcecode/test_source_code_env_vars.py new file mode 100644 index 00000000000..92c4683700a --- /dev/null +++ b/tests/sourcecode/test_source_code_env_vars.py @@ -0,0 +1,55 @@ +import os +from unittest import mock + +from ddtrace.sourcecode._utils import get_commit_sha +from ddtrace.sourcecode._utils import get_repository_url + + +class TestSourceCodeEnvVars: + def test_get_commit_sha_uses_env_var_when_present(self): + test_sha = "abc123def456" + with mock.patch.dict(os.environ, {"DD_GIT_COMMIT_SHA": test_sha}): + with mock.patch("ddtrace.sourcecode._utils._query_git") as mock_git: + result = get_commit_sha() + assert result == test_sha + mock_git.assert_not_called() + + def test_get_commit_sha_calls_git_when_env_var_not_present(self): + test_sha = "git_result_sha" + with mock.patch.dict(os.environ, {}, clear=True): + with mock.patch("ddtrace.sourcecode._utils._query_git", return_value=test_sha) as mock_git: + result = get_commit_sha() + assert result == test_sha + mock_git.assert_called_once_with(["rev-parse", "HEAD"]) + + def test_get_commit_sha_calls_git_when_env_var_empty(self): + test_sha = "git_result_sha" + with mock.patch.dict(os.environ, {"DD_GIT_COMMIT_SHA": ""}): + with mock.patch("ddtrace.sourcecode._utils._query_git", return_value=test_sha) as mock_git: + result = get_commit_sha() + assert result == test_sha + mock_git.assert_called_once_with(["rev-parse", "HEAD"]) + + def test_get_repository_url_uses_env_var_when_present(self): + test_url = "https://github.com/user/repo.git" + with mock.patch.dict(os.environ, {"DD_GIT_REPOSITORY_URL": test_url}): + with mock.patch("ddtrace.sourcecode._utils._query_git") as mock_git: + result = get_repository_url() + assert result == test_url + mock_git.assert_not_called() + + def test_get_repository_url_calls_git_when_env_var_not_present(self): + test_url = "git_result_url" + with mock.patch.dict(os.environ, {}, clear=True): + with mock.patch("ddtrace.sourcecode._utils._query_git", return_value=test_url) as mock_git: + result = get_repository_url() + assert result == test_url + mock_git.assert_called_once_with(["config", "--get", "remote.origin.url"]) + + def test_get_repository_url_calls_git_when_env_var_empty(self): + test_url = "git_result_url" + with mock.patch.dict(os.environ, {"DD_GIT_REPOSITORY_URL": ""}): + with mock.patch("ddtrace.sourcecode._utils._query_git", return_value=test_url) as mock_git: + result = get_repository_url() + assert result == test_url + mock_git.assert_called_once_with(["config", "--get", "remote.origin.url"])