11package com .databricks .sdk .core ;
22
33import java .util .ArrayList ;
4+ import java .util .Arrays ;
5+ import java .util .Collections ;
6+ import java .util .HashMap ;
47import java .util .List ;
8+ import java .util .Map ;
59import java .util .regex .Pattern ;
610import java .util .stream .Collectors ;
11+ import org .slf4j .Logger ;
12+ import org .slf4j .LoggerFactory ;
713
814public class UserAgent {
15+ private static final Logger log = LoggerFactory .getLogger (UserAgent .class );
916 private static String product = "unknown" ;
1017 private static String productVersion = "0.0.0" ;
1118
@@ -121,6 +128,10 @@ public static String asString() {
121128 segments .add (String .format ("databricks-sdk-java/%s" , version ));
122129 segments .add (String .format ("jvm/%s" , jvmVersion ()));
123130 segments .add (String .format ("os/%s" , osName ()));
131+ String ciProvider = cicdProvider ();
132+ if (!ciProvider .isEmpty ()) {
133+ segments .add (String .format ("ci/%s" , ciProvider ));
134+ }
124135 // Concurrent iteration over ArrayList must be guarded with synchronized.
125136 synchronized (otherInfo ) {
126137 segments .addAll (
@@ -130,4 +141,60 @@ public static String asString() {
130141 }
131142 return segments .stream ().collect (Collectors .joining (" " ));
132143 }
144+
145+ // Map of CI/CD providers that are used to detect them.
146+ private static final Map <String , List <EnvVar >> PROVIDERS = new HashMap <>();
147+
148+ static {
149+ PROVIDERS .put ("github" , Collections .singletonList (new EnvVar ("GITHUB_ACTIONS" , "true" )));
150+ PROVIDERS .put ("gitlab" , Collections .singletonList (new EnvVar ("GITLAB_CI" , "true" )));
151+ PROVIDERS .put ("jenkins" , Collections .singletonList (new EnvVar ("JENKINS_URL" , "" )));
152+ PROVIDERS .put ("azure-devops" , Collections .singletonList (new EnvVar ("TF_BUILD" , "True" )));
153+ PROVIDERS .put ("circle" , Collections .singletonList (new EnvVar ("CIRCLECI" , "true" )));
154+ PROVIDERS .put ("travis" , Collections .singletonList (new EnvVar ("TRAVIS" , "true" )));
155+ PROVIDERS .put ("bitbucket" , Collections .singletonList (new EnvVar ("BITBUCKET_BUILD_NUMBER" , "" )));
156+ PROVIDERS .put (
157+ "google-cloud-build" ,
158+ Arrays .asList (
159+ new EnvVar ("PROJECT_ID" , "" ),
160+ new EnvVar ("BUILD_ID" , "" ),
161+ new EnvVar ("PROJECT_NUMBER" , "" ),
162+ new EnvVar ("LOCATION" , "" )));
163+ PROVIDERS .put (
164+ "aws-code-build" , Collections .singletonList (new EnvVar ("CODEBUILD_BUILD_ARN" , "" )));
165+ PROVIDERS .put ("tf-cloud" , Collections .singletonList (new EnvVar ("TFC_RUN_ID" , "" )));
166+ }
167+
168+ // This is a static private variable to store the CI/CD provider.
169+ // This is thread-safe because static initializers are executed
170+ // in a thread-safe manner by the Java ClassLoader.
171+ private static final String cicdProvider = lookupCiCdProvider ();
172+
173+ private static class EnvVar {
174+ private final String name ;
175+ private final String expectedValue ;
176+
177+ public EnvVar (String name , String expectedValue ) {
178+ this .name = name ;
179+ this .expectedValue = expectedValue ;
180+ }
181+
182+ public boolean detect () {
183+ String value = System .getProperty (name );
184+ return value != null && (expectedValue .isEmpty () || value .equals (expectedValue ));
185+ }
186+ }
187+
188+ private static String lookupCiCdProvider () {
189+ for (Map .Entry <String , List <EnvVar >> entry : PROVIDERS .entrySet ()) {
190+ if (entry .getValue ().stream ().allMatch (EnvVar ::detect )) {
191+ return entry .getKey ();
192+ }
193+ }
194+ return "" ;
195+ }
196+
197+ public static String cicdProvider () {
198+ return cicdProvider ;
199+ }
133200}
0 commit comments