Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ We use [semantic versioning](http://semver.org/):
- PATCH version when you make backwards compatible bug fixes.

# Next version
- _teamscale-client_: User-Agent header now includes the specific component performing the request (e.g., "Teamscale Gradle Plugin", "Teamscale Maven Plugin") and version number
- _maven-plugin_: Added maven properties for `runImpacted` and `runAllTests` configuration parameters
- _maven-plugin_: The warning "Both baselineRevision and baselineCommit are set but only one of them is needed" was displayed incorrectly
- [fix] _maven-plugin_: Coverage upload used "Now" instead of auto-resolved Git revision when no commit/revision was configured
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import com.teamscale.client.ProfilerRegistration;
import com.teamscale.client.TeamscaleServiceGenerator;
import com.teamscale.jacoco.agent.logging.LoggingUtils;
import com.teamscale.jacoco.agent.util.AgentUtils;
import com.teamscale.report.util.ILogger;
import okhttp3.HttpUrl;
import okhttp3.ResponseBody;
Expand Down Expand Up @@ -57,7 +58,8 @@ public ConfigurationViaTeamscale(ITeamscaleService teamscaleClient, ProfilerRegi
String userName,
String userAccessToken) throws AgentOptionReceiveException {
ITeamscaleService teamscaleClient = TeamscaleServiceGenerator
.createService(ITeamscaleService.class, url, userName, userAccessToken, LONG_TIMEOUT, LONG_TIMEOUT);
.createService(ITeamscaleService.class, url, userName, userAccessToken, AgentUtils.USER_AGENT,
LONG_TIMEOUT, LONG_TIMEOUT);
try {
ProcessInformation processInformation = new ProcessInformationRetriever(logger).getProcessInformation();
Response<ResponseBody> response = teamscaleClient.registerProfiler(configurationId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,8 @@ private void validateTestwiseCoverageConfig(Validator validator) {
if (teamscaleServer.isConfiguredForSingleProjectTeamscaleUpload() ||
!requireSingleProjectUploadConfig && teamscaleServer.isConfiguredForServerConnection()) {
return new TeamscaleClient(teamscaleServer.url.toString(), teamscaleServer.userName,
teamscaleServer.userAccessToken, teamscaleServer.project);
teamscaleServer.userAccessToken, teamscaleServer.project,
AgentUtils.USER_AGENT);
}
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.teamscale.jacoco.agent.logging.LoggingUtils;
import com.teamscale.jacoco.agent.upload.IUploadRetry;
import com.teamscale.jacoco.agent.upload.IUploader;
import com.teamscale.jacoco.agent.util.AgentUtils;
import com.teamscale.jacoco.agent.util.Benchmark;
import com.teamscale.report.jacoco.CoverageFile;
import org.slf4j.Logger;
Expand Down Expand Up @@ -135,7 +136,8 @@ private boolean tryUploading(CoverageFile coverageFile, TeamscaleServer teamscal
// Cannot be executed in the constructor as this causes issues in WildFly server
// (See #100)
ITeamscaleService api = TeamscaleServiceGenerator.createService(ITeamscaleService.class,
teamscaleServer.url, teamscaleServer.userName, teamscaleServer.userAccessToken);
teamscaleServer.url, teamscaleServer.userName, teamscaleServer.userAccessToken,
AgentUtils.USER_AGENT);
ITeamscaleServiceKt.uploadReport(api, teamscaleServer.project, teamscaleServer.commit,
teamscaleServer.revision,
teamscaleServer.repository, teamscaleServer.partition, EReportFormat.JACOCO,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.teamscale.jacoco.agent.util;

import com.teamscale.client.FileSystemUtils;
import com.teamscale.client.TeamscaleServiceGenerator;
import com.teamscale.jacoco.agent.PreMain;
import com.teamscale.jacoco.agent.configuration.ProcessInformationRetriever;

Expand All @@ -18,11 +19,15 @@ public class AgentUtils {
/** Version of this program. */
public static final String VERSION;

/** User-Agent header value for HTTP requests. */
public static final String USER_AGENT;

private static Path mainTempDirectory = null;

static {
ResourceBundle bundle = ResourceBundle.getBundle("com.teamscale.jacoco.agent.app");
VERSION = bundle.getString("version");
USER_AGENT = TeamscaleServiceGenerator.buildUserAgent("Teamscale Java Profiler", VERSION);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.teamscale.test_impacted

import java.util.*

/** Provides access to the Impacted Test Engine version at runtime. */
object BuildVersion {

private val bundle = ResourceBundle.getBundle("com.teamscale.test_impacted.app")

/** The version of the Teamscale Impacted Test Engine. */
val VERSION: String = bundle.getString("version")
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package com.teamscale.test_impacted.engine.options

import com.teamscale.client.CommitDescriptor
import com.teamscale.client.TeamscaleClient
import com.teamscale.client.TeamscaleServiceGenerator
import com.teamscale.test_impacted.BuildVersion
import com.teamscale.test_impacted.engine.ImpactedTestEngineConfiguration
import com.teamscale.test_impacted.engine.TestDataWriter
import com.teamscale.test_impacted.engine.TestEngineRegistry
Expand Down Expand Up @@ -122,7 +124,8 @@ class TestEngineOptions(
serverOptions.userName,
serverOptions.userAccessToken,
serverOptions.project,
File(reportDirectory, "server-request.txt")
File(reportDirectory, "server-request.txt"),
userAgent = TeamscaleServiceGenerator.buildUserAgent("Teamscale Impacted Test Engine", BuildVersion.VERSION)
)
return ImpactedTestsProvider(
client, baseline, baselineRevision, endCommit, endRevision, repository, partition,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
version=%VERSION_TOKEN_REPLACED_DURING_BUILD%
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class HttpRedirectSystemTest {

private fun checkCustomUserAgent(teamscaleMockServer: TeamscaleMockServer) {
val collectedUserAgents = teamscaleMockServer.collectedUserAgents
assertThat(collectedUserAgents).containsExactly(TeamscaleServiceGenerator.USER_AGENT)
assertThat(collectedUserAgents).allMatch { it.matches(Regex("Teamscale Java Profiler/\\d+\\.\\d+.*")) }
}

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,14 @@ open class TeamscaleClient {
user: String,
accessToken: String,
projectId: String?,
userAgent: String,
readTimeout: Duration = HttpUtils.DEFAULT_READ_TIMEOUT,
writeTimeout: Duration = HttpUtils.DEFAULT_WRITE_TIMEOUT
) {
val url = baseUrl?.toHttpUrlOrNull() ?: throw IllegalArgumentException("Invalid URL: $baseUrl")
this.projectId = projectId
service = TeamscaleServiceGenerator.createService(
ITeamscaleService::class.java, url, user, accessToken, readTimeout, writeTimeout
ITeamscaleService::class.java, url, user, accessToken, userAgent, readTimeout, writeTimeout
)
}

Expand All @@ -46,12 +47,13 @@ open class TeamscaleClient {
projectId: String?,
logfile: File?,
readTimeout: Duration = HttpUtils.DEFAULT_READ_TIMEOUT,
writeTimeout: Duration = HttpUtils.DEFAULT_WRITE_TIMEOUT
writeTimeout: Duration = HttpUtils.DEFAULT_WRITE_TIMEOUT,
userAgent: String
) {
val url = baseUrl?.toHttpUrlOrNull() ?: throw IllegalArgumentException("Invalid URL: $baseUrl")
this.projectId = projectId
service = TeamscaleServiceGenerator.createServiceWithRequestLogging(
ITeamscaleService::class.java, url, user, accessToken, logfile, readTimeout, writeTimeout
ITeamscaleService::class.java, url, user, accessToken, logfile, readTimeout, writeTimeout, userAgent
)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package com.teamscale.client

import okhttp3.*
import okhttp3.HttpUrl
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.Response
import retrofit2.Retrofit
import retrofit2.converter.jackson.JacksonConverterFactory
import java.io.File
Expand All @@ -9,8 +12,9 @@ import java.time.Duration

/** Helper class for generating a teamscale compatible service. */
object TeamscaleServiceGenerator {
/** Custom user agent of the requests, used to monitor API traffic. */
const val USER_AGENT = "Teamscale Java Profiler"
/** Builds the User-Agent string for the given tool name and version. */
@JvmStatic
fun buildUserAgent(toolName: String, version: String) = "$toolName/$version"

/**
* Generates a [Retrofit] instance for the given service, which uses basic auth to authenticate against the
Expand All @@ -23,11 +27,12 @@ object TeamscaleServiceGenerator {
baseUrl: HttpUrl,
username: String,
accessToken: String,
userAgent: String,
readTimeout: Duration = HttpUtils.DEFAULT_READ_TIMEOUT,
writeTimeout: Duration = HttpUtils.DEFAULT_WRITE_TIMEOUT,
vararg interceptors: Interceptor
) = createServiceWithRequestLogging(
serviceClass, baseUrl, username, accessToken, null, readTimeout, writeTimeout, *interceptors
serviceClass, baseUrl, username, accessToken, null, readTimeout, writeTimeout, userAgent, *interceptors
)

/**
Expand All @@ -42,6 +47,7 @@ object TeamscaleServiceGenerator {
logfile: File?,
readTimeout: Duration,
writeTimeout: Duration,
userAgent: String,
vararg interceptors: Interceptor
): S = HttpUtils.createRetrofit(
{ retrofitBuilder ->
Expand All @@ -52,7 +58,7 @@ object TeamscaleServiceGenerator {
okHttpBuilder.addInterceptors(*interceptors)
.addInterceptor(HttpUtils.getBasicAuthInterceptor(username, accessToken))
.addInterceptor(AcceptJsonInterceptor())
.addNetworkInterceptor(CustomUserAgentInterceptor())
.addNetworkInterceptor(CustomUserAgentInterceptor(userAgent))
logfile?.let { okHttpBuilder.addInterceptor(FileLoggingInterceptor(it)) }
},
readTimeout, writeTimeout
Expand All @@ -79,12 +85,12 @@ object TeamscaleServiceGenerator {
}

/**
* Sets the custom user agent [.USER_AGENT] header on all requests.
* Sets the custom user agent header on all requests.
*/
class CustomUserAgentInterceptor : Interceptor {
class CustomUserAgentInterceptor(private val userAgent: String) : Interceptor {
@Throws(IOException::class)
override fun intercept(chain: Interceptor.Chain): Response {
val newRequest = chain.request().newBuilder().header("User-Agent", USER_AGENT).build()
val newRequest = chain.request().newBuilder().header("User-Agent", userAgent).build()
return chain.proceed(newRequest)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.teamscale.client

import com.teamscale.client.HttpUtils.PROXY_AUTHORIZATION_HTTP_HEADER
import com.teamscale.client.TeamscaleServiceGenerator.buildUserAgent
import com.teamscale.client.TeamscaleServiceGenerator.createService
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.mockwebserver.MockResponse
Expand Down Expand Up @@ -61,7 +62,8 @@ internal class TeamscaleServiceGeneratorProxyServerTest {
val service = createService(
ITeamscaleService::class.java,
"http://localhost:1337".toHttpUrl(),
"someUser", "someAccesstoken"
"someUser", "someAccesstoken",
userAgent = buildUserAgent("Test Tool", "1.0.0")
)

// First time Retrofit/OkHttp tires without proxy auth.
Expand Down Expand Up @@ -91,4 +93,4 @@ internal class TeamscaleServiceGeneratorProxyServerTest {
mockProxyServer?.shutdown()
mockProxyServer?.close()
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.teamscale.config

import com.teamscale.client.TeamscaleClient
import com.teamscale.client.TeamscaleServiceGenerator
import com.teamscale.utils.BuildVersion
import org.gradle.api.GradleException
import org.gradle.api.provider.Property
import java.io.Serializable
Expand Down Expand Up @@ -33,5 +35,8 @@ abstract class ServerConfiguration : Serializable {
}
}

fun toClient() = TeamscaleClient(url.get(), userName.get(), userAccessToken.get(), project.get())
fun toClient() = TeamscaleClient(
url.get(), userName.get(), userAccessToken.get(), project.get(),
userAgent = TeamscaleServiceGenerator.buildUserAgent("Teamscale Gradle Plugin", BuildVersion.pluginVersion)
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.teamscale.maven;

import java.util.ResourceBundle;

/** Provides access to the Maven plugin version at runtime. */
public class BuildVersion {

private static final ResourceBundle BUNDLE = ResourceBundle.getBundle("com.teamscale.maven.app");

/** The version of the Teamscale Maven plugin. */
public static final String VERSION = BUNDLE.getString("version");
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import com.teamscale.client.CommitDescriptor;
import com.teamscale.client.EReportFormat;
import com.teamscale.client.TeamscaleClient;
import com.teamscale.client.TeamscaleServiceGenerator;
import com.teamscale.maven.BuildVersion;
import com.teamscale.maven.DependencyUtils;
import com.teamscale.maven.TeamscaleMojoBase;
import com.teamscale.maven.tia.TestwiseCoverageReportMojo;
Expand Down Expand Up @@ -32,9 +34,9 @@
import java.util.stream.Collectors;

/**
* Run this goal after the Jacoco and Testwise Coverage report generation to upload them to a configured Teamscale instance.
* The configuration can be specified in the root Maven project.
* The goal should only be run in the aggregator module.
* Run this goal after the Jacoco and Testwise Coverage report generation to upload them to a configured Teamscale
* instance. The configuration can be specified in the root Maven project. The goal should only be run in the aggregator
* module.
* <p>
* Offers the following functionality:
* <ol>
Expand Down Expand Up @@ -130,7 +132,8 @@ public void execute() throws MojoFailureException, MojoExecutionException {
getLog().debug("Skipping since skip is set to true");
return;
}
teamscaleClient = new TeamscaleClient(teamscaleUrl, username, accessToken, projectId);
teamscaleClient = new TeamscaleClient(teamscaleUrl, username, accessToken, projectId,
TeamscaleServiceGenerator.buildUserAgent("Teamscale Maven Plugin", BuildVersion.VERSION));
getLog().debug("Resolving end commit");
resolveCommitOrRevision();
getLog().debug("Parsing Jacoco plugin configurations");
Expand Down Expand Up @@ -257,7 +260,8 @@ private void uploadCoverage(String partition, Map<String, List<File>> reportsByF
getLog().info(
String.format("Uploading %d report for project %s to %s", reportsByFormat.values().stream().mapToLong(
Collection::size).sum(), projectId, partition));
teamscaleClient.uploadReports(reportsByFormat, CommitDescriptor.parse(resolvedCommit), resolvedRevision, repository,
teamscaleClient.uploadReports(reportsByFormat, CommitDescriptor.parse(resolvedCommit), resolvedRevision,
repository,
partition, COVERAGE_UPLOAD_MESSAGE);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
version=%VERSION_TOKEN_REPLACED_DURING_BUILD%
Loading