Skip to content

Commit 82da97b

Browse files
Add cicd in user agent
1 parent 267d369 commit 82da97b

File tree

2 files changed

+98
-0
lines changed

2 files changed

+98
-0
lines changed

databricks/sdk/useragent.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,4 +148,58 @@ def to_string(alternate_product_info: Optional[Tuple[str, str]] = None,
148148
base.extend(_extra)
149149
base.extend(_get_upstream_user_agent_info())
150150
base.extend(_get_runtime_info())
151+
if cicd_provider() != "":
152+
base.append((CICD_KEY, cicd_provider()))
151153
return " ".join(f"{k}/{v}" for k, v in base)
154+
155+
156+
# List of CI/CD providers and pairs of envvar/value that are used to detect them.
157+
_PROVIDERS = {
158+
"github": [("GITHUB_ACTIONS", "true")],
159+
"gitlab": [("GITLAB_CI", "true")],
160+
"jenkins": [("JENKINS_URL", "")],
161+
"azure-devops": [("TF_BUILD", "True")],
162+
"circle": [("CIRCLECI", "true")],
163+
"travis": [("TRAVIS", "true")],
164+
"bitbucket": [("BITBUCKET_BUILD_NUMBER", "")],
165+
"google-cloud-build": [("PROJECT_ID", ""), ("BUILD_ID", ""), ("PROJECT_NUMBER", ""), ("LOCATION", "")],
166+
"aws-code-build": [("CODEBUILD_BUILD_ARN", "")],
167+
"tf-cloud": [("TFC_RUN_ID", "")],
168+
}
169+
170+
# Private variable to store the CI/CD provider. This value is computed at
171+
# the first invocation of cicd_providers() and is cached for subsequent calls.
172+
_cicd_provider = None
173+
174+
175+
def cicd_provider() -> str:
176+
"""Return the CI/CD provider if detected, or an empty string otherwise."""
177+
178+
# This function is safe because (i) assignation are atomic, and (ii)
179+
# computating the CI/CD provider is idempotent.
180+
global _cicd_provider
181+
if _cicd_provider is not None:
182+
return _cicd_provider
183+
184+
providers = []
185+
for p in _PROVIDERS:
186+
found = True
187+
for envvar, value in _PROVIDERS[p]:
188+
v = os.getenv(envvar)
189+
if v is None or (value != "" and v != value):
190+
found = False
191+
break
192+
193+
if found:
194+
providers.append(p)
195+
196+
if len(providers) == 0:
197+
_cicd_provider = ""
198+
else:
199+
# TODO: reconsider what to do if multiple providers are detected.
200+
# The current mechanism as the benefit of being deterministic and
201+
# robust to ordering changes in _PROVIDERS.
202+
providers.sort()
203+
_cicd_provider = providers[0]
204+
205+
return _cicd_provider

tests/test_user_agent.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import os
2+
13
import pytest
24

35
from databricks.sdk.version import __version__
@@ -40,3 +42,45 @@ def test_user_agent_with_partner(user_agent):
4042
user_agent.with_partner('differenttest')
4143
assert 'partner/test' in user_agent.to_string()
4244
assert 'partner/differenttest' in user_agent.to_string()
45+
46+
47+
@pytest.fixture(scope="session")
48+
def clear_cicd():
49+
# Save and clear env vars.
50+
original_env = os.environ
51+
os.environ.clear()
52+
53+
# Clear cached CICD provider.
54+
from databricks.sdk import useragent
55+
useragent._cicd_provider = None
56+
57+
yield
58+
59+
# Restore env vars.
60+
os.environ = original_env
61+
62+
63+
def test_user_agent_cicd_no_provider(clear_cicd):
64+
from databricks.sdk import useragent
65+
user_agent = useragent.to_string()
66+
67+
assert 'cicd' not in user_agent
68+
69+
70+
def test_user_agent_cicd_one_provider(clear_cicd):
71+
os.environ['GITHUB_ACTIONS'] = 'true'
72+
73+
from databricks.sdk import useragent
74+
user_agent = useragent.to_string()
75+
76+
assert 'cicd/github' in user_agent
77+
78+
79+
def test_user_agent_cicd_two_provider(clear_cicd):
80+
os.environ['GITHUB_ACTIONS'] = 'true'
81+
os.environ['GITLAB_CI'] = 'true'
82+
83+
from databricks.sdk import useragent
84+
user_agent = useragent.to_string()
85+
86+
assert 'cicd/github' in user_agent

0 commit comments

Comments
 (0)