in gradle-runner-agent/src/main/java/jetbrains/buildServer/gradle/runtime/TeamCityGradleLauncher.java [32:178]
public static void main(String[] args) {
final Map<String, String> gradleEnv = new HashMap<>(System.getenv());
String gradleParamsFilePath = getSystemEnvValue(gradleEnv, GradleRunnerConstants.GRADLE_PARAMS_FILE_ENV_KEY);
if (gradleParamsFilePath == null) {
return;
}
final List<String> gradleParams = readParams(gradleParamsFilePath);
if (gradleParams == null) {
return;
}
String jvmArgsFilePath = getSystemEnvValue(gradleEnv, GradleRunnerConstants.GRADLE_JVM_PARAMS_FILE_ENV_KEY);
if (jvmArgsFilePath == null) {
return;
}
final List<String> tcJvmArgs = readParams(jvmArgsFilePath);
if (tcJvmArgs == null) {
return;
}
String gradleTasksPath = getSystemEnvValue(gradleEnv, GradleRunnerConstants.GRADLE_TASKS_FILE_ENV_KEY);
if (gradleTasksPath == null) {
return;
}
final List<String> gradleTasks = readParams(gradleTasksPath);
if (gradleTasks == null) {
return;
}
final String workingDir = gradleEnv.get(GradleRunnerConstants.WORKING_DIRECTORY_ENV_KEY);
if (workingDir == null) {
System.err.println("Parameter " + GradleRunnerConstants.WORKING_DIRECTORY_ENV_KEY
+ " must be present in environment variables.");
return;
}
File tcBuildParametersFile = getTcBuildParametersFile(gradleEnv);
Properties teamCityBuildParameters = getTeamCityBuildParameters(tcBuildParametersFile);
if (teamCityBuildParameters == null) {
return;
}
String buildTempDir = teamCityBuildParameters.getProperty("teamcity.build.tempDir", "");
if (buildTempDir.isEmpty()) {
System.err.println("Parameter teamcity.build.tempDir must be set in teamcity.build.parameters.");
return;
}
String buildNumber = teamCityBuildParameters.getProperty("build.number", "");
final Boolean useWrapper = Boolean.valueOf(gradleEnv.get(GradleRunnerConstants.USE_WRAPPER_ENV_KEY));
final String gradleHome = gradleEnv.get(GradleRunnerConstants.GRADLE_HOME_ENV_KEY);
final String gradleWrapperProperties = gradleEnv.get(GradleRunnerConstants.GRADLE_WRAPPED_DISTRIBUTION_ENV_KEY);
boolean isDebugModeEnabled = gradleParams.stream().anyMatch(task -> task.equals("-d"));
GradleToolingLogger logger = new GradleToolingLoggerImpl(isDebugModeEnabled);
GradleJvmArgsMerger jvmArgsMerger = new GradleJvmArgsMerger(logger);
String taskOutputDir = buildTempDir + File.separator + BUILD_TEMP_DIR_TASK_OUTPUT_SUBDIR;
BuildContext buildContext = new BuildContext(tcBuildParametersFile.getAbsolutePath(), taskOutputDir, gradleParamsFilePath, jvmArgsFilePath, gradleTasksPath);
List<BuildEventListener> eventListeners = new ArrayList<>();
eventListeners.add(new GradleBuildOutputProcessor(logger, buildContext));
BuildLifecycleListener buildLifecycleListener = new GradleBuildLifecycleListener(logger, eventListeners, buildContext);
GradleBuildConfigurator buildConfigurator = new GradleBuildConfigurator(logger);
try {
gradleEnv.put(TEAMCITY_BUILD_INIT_PATH, GradleBuildConfigurator.getInitScriptClasspath());
} catch (IOException e) {
// use existing TEAMCITY_BUILD_INIT_PATH from GradleToolingApiCommandLineComposer.composeCommandLine
if (gradleEnv.get(TEAMCITY_BUILD_INIT_PATH) == null) {
System.err.println("Couldn't launch Gradle via Tooling API: error while trying to build init script classpath");
return;
}
}
final GradleConnector connector;
try {
connector = buildConfigurator.prepareConnector(workingDir, useWrapper, gradleWrapperProperties, gradleHome);
} catch (Exception e) {
System.err.println(e.getMessage());
return;
}
try (ProjectConnection connection = connector.connect()) {
Optional<BuildEnvironment> buildEnvironment = getBuildEnvironment(connection, logger);
List<String> gradleProjectJvmArgs = buildEnvironment.map(env -> env.getJava().getJvmArguments()).orElseGet(Collections::emptyList);
boolean allowJvmArgsOverriding = Boolean.parseBoolean(System.getProperty(GRADLE_RUNNER_ALLOW_JVM_ARGS_OVERRIDING_CONFIG_PARAM));
Collection<String> jvmArgsForOverriding = !allowJvmArgsOverriding || tcJvmArgs.isEmpty()
? Collections.emptyList()
: jvmArgsMerger.mergeJvmArguments(gradleProjectJvmArgs, tcJvmArgs);
Collection<String> tasksAndParams = Stream.concat(gradleTasks.stream(), gradleParams.stream()).collect(Collectors.toList());
BuildLauncher launcher = buildConfigurator.prepareBuildExecutor(gradleEnv, tasksAndParams, jvmArgsForOverriding, buildLifecycleListener, buildNumber, connection);
String buildStartedMessage = composeBuildStartedMessage(buildNumber, tasksAndParams, jvmArgsForOverriding, buildEnvironment.orElse(null), gradleEnv);
buildLifecycleListener.onStart(new BuildStartedEventImpl(System.currentTimeMillis(), buildStartedMessage));
// workaround for https://github.com/gradle/gradle/issues/34491, delete when issue fixed
// shuts down JVM when Gradle build is finished after some timeout
Optional
.ofNullable(System.getenv().get(GradleRunnerConstants.GRADLE_TOOLING_API_LAUNCHER_SHUTDOWN_TIMEOUT_SEC_ENV_KEY))
.map(Integer::parseInt)
.ifPresent(timeoutSec -> {
Thread watchdog = new Thread(() -> {
try {
GRADLE_CONNECTOR_DISCONNECTED.await();
// sleep to let the problematic Tooling API thread finish
// if it happens this daemon thread will be terminated before reaching System.exit(0)
Thread.sleep(timeoutSec * 1000);
System.out.printf(
"##teamcity[message text='Tooling API hang detected: JVM still running %s seconds after Gradle build completed; shutting down' status='WARNING']\n",
timeoutSec
);
System.exit(0);
} catch (InterruptedException ignored) {
}
});
watchdog.setName("Tooling API shutdown watchdog");
watchdog.setDaemon(true);
watchdog.start();
});
launcher.run(new ResultHandler<Void>() {
@Override
public void onComplete(Void unused) {
try {
buildLifecycleListener.onSuccess();
} finally {
connector.disconnect();
GRADLE_CONNECTOR_DISCONNECTED.countDown();
}
}
@Override
public void onFailure(GradleConnectionException e) {
try {
buildLifecycleListener.onFail();
} finally {
connector.disconnect();
GRADLE_CONNECTOR_DISCONNECTED.countDown();
}
throw e;
}
});
}
}