Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into ts/38153_spring-boo…
Browse files Browse the repository at this point in the history
…t-nested-urls
  • Loading branch information
karottenreibe committed Apr 4, 2024
2 parents 71ae847 + ccf0aa5 commit b9b5469
Show file tree
Hide file tree
Showing 57 changed files with 1,645 additions and 699 deletions.
37 changes: 29 additions & 8 deletions .github/workflows/actions.yml
Expand Up @@ -9,17 +9,14 @@ on:

jobs:
build:
name: Build & Deploy
name: Build on Linux & Deploy
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up GraalVM
uses: graalvm/setup-graalvm@v1
- uses: actions/setup-java@v4
with:
java-version: '17.0.8'
distribution: 'graalvm-community'
github-token: ${{ secrets.GITHUB_TOKEN }}
set-java-home: true
distribution: 'temurin'
java-version: '17'
- name: Build with Gradle
run: ./gradlew build
- name: Upload Release Assets
Expand Down Expand Up @@ -71,7 +68,31 @@ jobs:
accesskey: ${{ secrets.CQSE_TEAMSCALE_IO_ACCESSKEY }}
partition: 'Coverage'
format: 'JACOCO'
message: 'Coverage'
message: 'Linux Coverage'
files: '**/jacocoTestReport.xml'

test-windows:
name: Test on Windows
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'
- name: Build with Gradle
run: ./gradlew build
- name: Upload coverage to Teamscale
if: always() && github.event_name == 'push'
uses: cqse/teamscale-upload-action@v9.2.1
with:
server: 'https://cqse.teamscale.io'
project: 'teamscale-jacoco-agent'
user: ${{ secrets.CQSE_TEAMSCALE_IO_USER }}
accesskey: ${{ secrets.CQSE_TEAMSCALE_IO_ACCESSKEY }}
partition: 'Coverage Windows'
format: 'JACOCO'
message: 'Coverage Windows'
files: '**/jacocoTestReport.xml'

docker:
Expand Down
5 changes: 5 additions & 0 deletions .idea/codeStyles/Project.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions CHANGELOG.md
Expand Up @@ -6,7 +6,12 @@ We use [semantic versioning](http://semver.org/):

# Next Release
- [feature] Add support for git.properties in Spring Boot 3.2
- [feature] Read configuration file path from `TEAMSCALE_JAVA_PROFILER_CONFIG_FILE` environment variable
- [feature] add installer for Windows
- [feature] Docker: agent copies itself to `/transfer` if this is mounted into the container
- [fix] Disable warning about proxy port not being correct when no proxy port was set at all
- [fix] _agent_: `GET /commit` and `GET /revision` endpoints did return 500 error
- [feature] _agent_: Added stable support for Java 22 and experimental support for Java 23

# 33.1.2
- [fix] _teamscale-maven-plugin_: Revision and end commit could not be set via command line (user property)
Expand Down
5 changes: 3 additions & 2 deletions agent/README.md
Expand Up @@ -51,8 +51,9 @@ The following options are available:
- `out` (optional): the path to a writable directory where the generated coverage XML files will be stored. (For details
see path format section below). Defaults to the subdirectory `coverage` inside the agent's installation directory.
- `config-file` (optional): a file which contains one or more of the previously named options as `key=value` entries
which are separated by line breaks. The file may also contain comments starting with `#`. (For details see path format
section below)
which are separated by line breaks. The file may also contain comments starting with `#`. For details see path format
section below.
Alternatively you can also set the `TEAMSCALE_JAVA_PROFILER_CONFIG_FILE` environment variable to that value.
- `config-id` (optional): a profiler configuration ID as defined in Teamscale. This allows to centrally manage the
profiler configuration in Teamscale's UI (under Project Configuration > Profilers since Teamscale 9.4).
Alternatively you can also set the `TEAMSCALE_JAVA_PROFILER_CONFIG_ID` environment variable to that value.
Expand Down
4 changes: 2 additions & 2 deletions agent/build.gradle.kts
Expand Up @@ -84,8 +84,8 @@ distributions {
named("shadow") {
distributionBaseName.set("teamscale-jacoco-agent")
contents {
from(project(":installer").tasks["nativeCompile"]) {
include("installer")
from(project(":installer").tasks["jlink"]) {
into("installer")
}

from(tasks.readmeToPdf) {
Expand Down
9 changes: 9 additions & 0 deletions agent/src/dist/installer.bat
@@ -0,0 +1,9 @@
@echo off
set DIR="%~dp0"
set BAT_EXEC="%DIR:"=%\installer\installer-windows-x86_64\bin\installer.bat"

rem ensure that we don't accidentally profile the uninstaller
set JAVA_TOOL_OPTIONS=
set _JAVA_OPTIONS=

pushd %DIR% & %BAT_EXEC% %* & popd
8 changes: 8 additions & 0 deletions agent/src/dist/installer.sh
@@ -0,0 +1,8 @@
#!/bin/sh
DIR="${0%/*}"

# ensure that we don't accidentally profile the uninstaller
unset JAVA_TOOL_OPTIONS
unset _JAVA_OPTIONS

exec "$DIR/installer/installer-linux-x86_64/bin/installer" "$@"
4 changes: 3 additions & 1 deletion agent/src/docker/Dockerfile
@@ -1,6 +1,8 @@
# --- build image ---

FROM openjdk:8 as build
FROM openjdk:17 as build
# install xargs which is needed during the build
RUN microdnf install findutils
ADD . /src
WORKDIR /src
RUN ./gradlew :agent:shadowJar
Expand Down
Expand Up @@ -13,14 +13,15 @@

package com.teamscale.jacoco.agent;

import org.jacoco.agent.rt.internal_4742761.Agent;
import org.jacoco.agent.rt.internal_4742761.AgentModule;
import org.jacoco.agent.rt.internal_4742761.CoverageTransformer;
import org.jacoco.agent.rt.internal_4742761.IExceptionLogger;
import org.jacoco.agent.rt.internal_4742761.core.runtime.AgentOptions;
import org.jacoco.agent.rt.internal_4742761.core.runtime.IRuntime;
import org.jacoco.agent.rt.internal_4742761.core.runtime.InjectedClassRuntime;
import org.jacoco.agent.rt.internal_4742761.core.runtime.ModifiedSystemClassRuntime;
import org.jacoco.agent.rt.internal_aeaf9ab.Agent;
import org.jacoco.agent.rt.internal_aeaf9ab.AgentModule;
import org.jacoco.agent.rt.internal_aeaf9ab.CoverageTransformer;
import org.jacoco.agent.rt.internal_aeaf9ab.IExceptionLogger;
import org.jacoco.agent.rt.internal_aeaf9ab.PreMain;
import org.jacoco.agent.rt.internal_aeaf9ab.core.runtime.AgentOptions;
import org.jacoco.agent.rt.internal_aeaf9ab.core.runtime.IRuntime;
import org.jacoco.agent.rt.internal_aeaf9ab.core.runtime.InjectedClassRuntime;
import org.jacoco.agent.rt.internal_aeaf9ab.core.runtime.ModifiedSystemClassRuntime;
import org.slf4j.Logger;

import java.lang.instrument.Instrumentation;
Expand Down
@@ -1,8 +1,8 @@
package com.teamscale.jacoco.agent;

import org.jacoco.agent.rt.internal_4742761.CoverageTransformer;
import org.jacoco.agent.rt.internal_4742761.core.runtime.AgentOptions;
import org.jacoco.agent.rt.internal_4742761.core.runtime.IRuntime;
import org.jacoco.agent.rt.internal_aeaf9ab.CoverageTransformer;
import org.jacoco.agent.rt.internal_aeaf9ab.core.runtime.AgentOptions;
import org.jacoco.agent.rt.internal_aeaf9ab.core.runtime.IRuntime;
import org.slf4j.Logger;

import java.lang.instrument.IllegalClassFormatException;
Expand Down
22 changes: 15 additions & 7 deletions agent/src/main/java/com/teamscale/jacoco/agent/PreMain.java
Expand Up @@ -42,9 +42,13 @@ public class PreMain {
*/
private static final String LOCKING_SYSTEM_PROPERTY = "TEAMSCALE_JAVA_PROFILER_ATTACHED";

/** Environment variable from which to read the config file to use. */
/** Environment variable from which to read the config ID to use.
* This is an ID for a profiler configuration that is stored in Teamscale. */
private static final String CONFIG_ID_ENVIRONMENT_VARIABLE = "TEAMSCALE_JAVA_PROFILER_CONFIG_ID";

/** Environment variable from which to read the config file to use. */
private static final String CONFIG_FILE_ENVIRONMENT_VARIABLE = "TEAMSCALE_JAVA_PROFILER_CONFIG_FILE";

/**
* Entry point for the agent, called by the JVM.
*/
Expand All @@ -55,15 +59,16 @@ public static void premain(String options, Instrumentation instrumentation) thro
System.setProperty(LOCKING_SYSTEM_PROPERTY, "true");

String environmentConfigId = System.getenv(CONFIG_ID_ENVIRONMENT_VARIABLE);
if (StringUtils.isEmpty(options) && environmentConfigId == null) {
String environmentConfigFile = System.getenv(CONFIG_FILE_ENVIRONMENT_VARIABLE);
if (StringUtils.isEmpty(options) && environmentConfigId == null && environmentConfigFile == null) {
// profiler was registered globally and no config was set explicitly by the user, thus ignore this process
// and don't profile anything
return;
}

AgentOptions agentOptions;
try {
agentOptions = getAndApplyAgentOptions(options, environmentConfigId);
agentOptions = getAndApplyAgentOptions(options, environmentConfigId, environmentConfigFile);
} catch (AgentOptionReceiveException e) {
// When Teamscale is not available, we don't want to fail hard to still allow for testing even if no
// coverage is collected (see TS-33237)
Expand All @@ -85,8 +90,9 @@ public static void premain(String options, Instrumentation instrumentation) thro
}

@NotNull
private static AgentOptions getAndApplyAgentOptions(String options,
String environmentConfigId) throws AgentOptionParseException, IOException, AgentOptionReceiveException {
private static AgentOptions getAndApplyAgentOptions(String options, String environmentConfigId,
String environmentConfigFile) throws AgentOptionParseException, IOException, AgentOptionReceiveException {

DelayedLogger delayedLogger = new DelayedLogger();
List<String> javaAgents = CollectionUtils.filter(ManagementFactory.getRuntimeMXBean().getInputArguments(),
s -> s.contains("-javaagent"));
Expand All @@ -103,7 +109,7 @@ private static AgentOptions getAndApplyAgentOptions(String options,
}
AgentOptions agentOptions;
try {
agentOptions = AgentOptionsParser.parse(options, environmentConfigId, credentials, delayedLogger);
agentOptions = AgentOptionsParser.parse(options, environmentConfigId, environmentConfigFile, credentials, delayedLogger);
} catch (AgentOptionParseException e) {
try (LoggingUtils.LoggingResources ignored = initializeFallbackLogging(options, delayedLogger)) {
delayedLogger.errorAndStdErr("Failed to parse agent options: " + e.getMessage(), e);
Expand All @@ -112,7 +118,9 @@ private static AgentOptions getAndApplyAgentOptions(String options,
}
} catch (AgentOptionReceiveException e) {
try (LoggingUtils.LoggingResources ignored = initializeFallbackLogging(options, delayedLogger)) {
delayedLogger.errorAndStdErr( e.getMessage() + " The application should start up normally, but NO coverage will be collected!", e);
delayedLogger.errorAndStdErr(
e.getMessage() + " The application should start up normally, but NO coverage will be collected!",
e);
attemptLogAndThrow(delayedLogger);
throw e;
}
Expand Down
Expand Up @@ -12,6 +12,8 @@
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.Optional;

Expand Down Expand Up @@ -48,13 +50,15 @@ public String getMessage() {
/** Returns revision information for the Teamscale upload. */
@GET
@Path("/revision")
@Produces(MediaType.APPLICATION_JSON)
public RevisionInfo getRevision() {
return this.getRevisionInfo();
}

/** Returns revision information for the Teamscale upload. */
@GET
@Path("/commit")
@Produces(MediaType.APPLICATION_JSON)
public RevisionInfo getCommit() {
return this.getRevisionInfo();
}
Expand Down
Expand Up @@ -50,27 +50,30 @@ public class AgentOptionsParser {
private final FilePatternResolver filePatternResolver;
private final TeamscaleConfig teamscaleConfig;
private final String environmentConfigId;
private final String environmentConfigFile;
private final TeamscaleCredentials credentials;

/**
* Parses the given command-line options.
*
* @param environmentConfigId The Profiler configuration ID given via the
* {@link com.teamscale.jacoco.agent.PreMain#CONFIG_ID_ENVIRONMENT_VARIABLE} environment
* variable.
* @param environmentConfigId The Profiler configuration ID given via an environment variable.
* @param environmentConfigFile The Profiler configuration file given via an environment variable.
*/
public static AgentOptions parse(String optionsString, String environmentConfigId,
public static AgentOptions parse(String optionsString, String environmentConfigId, String environmentConfigFile,
TeamscaleCredentials credentials,
ILogger logger) throws AgentOptionParseException, AgentOptionReceiveException {
return new AgentOptionsParser(logger, environmentConfigId, credentials).parse(optionsString);
return new AgentOptionsParser(logger, environmentConfigId, environmentConfigFile, credentials).parse(
optionsString);
}

@VisibleForTesting
AgentOptionsParser(ILogger logger, String environmentConfigId, TeamscaleCredentials credentials) {
AgentOptionsParser(ILogger logger, String environmentConfigId, String environmentConfigFile,
TeamscaleCredentials credentials) {
this.logger = logger;
this.filePatternResolver = new FilePatternResolver(logger);
this.teamscaleConfig = new TeamscaleConfig(logger, filePatternResolver);
this.environmentConfigId = environmentConfigId;
this.environmentConfigFile = environmentConfigFile;
this.credentials = credentials;
}

Expand Down Expand Up @@ -99,9 +102,7 @@ public static AgentOptions parse(String optionsString, String environmentConfigI
}
}

if (environmentConfigId != null) {
handleOption(options, "config-id=" + environmentConfigId);
}
handleConfigFromEnvironment(options);

Validator validator = options.getValidator();
if (!validator.isValid()) {
Expand All @@ -110,6 +111,23 @@ public static AgentOptions parse(String optionsString, String environmentConfigI
return options;
}

private void handleConfigFromEnvironment(
AgentOptions options) throws AgentOptionParseException, AgentOptionReceiveException {
if (environmentConfigId != null) {
handleOption(options, "config-id=" + environmentConfigId);
}

if (environmentConfigFile != null) {
handleOption(options, "config-file=" + environmentConfigFile);
}

if (environmentConfigId != null && environmentConfigFile != null) {
logger.warn("You specified both an ID for a profiler configuration in Teamscale and a config file." +
" The config file will override the Teamscale configuration." +
" Please use one or the other.");
}
}

/**
* Parses and stores the given option in the format <code>key=value</code>.
*/
Expand Down Expand Up @@ -267,7 +285,8 @@ private void readConfigFromTeamscale(AgentOptions options,
options.teamscaleServer.userName,
options.teamscaleServer.userAccessToken);
options.configurationViaTeamscale = configuration;
logger.debug("Received the following options from Teamscale: " + configuration.getProfilerConfiguration().configurationOptions);
logger.debug(
"Received the following options from Teamscale: " + configuration.getProfilerConfiguration().configurationOptions);
readConfigFromString(options, configuration.getProfilerConfiguration().configurationOptions);
}

Expand Down

0 comments on commit b9b5469

Please sign in to comment.