build scripts: propagate log messages to Ant's BuildListeners to show them properly in 'Build Log' when running under TeamCity

This commit is contained in:
nik
2016-11-01 11:13:31 +03:00
parent f2fdef7139
commit 203ef4f0ae
4 changed files with 48 additions and 24 deletions
@@ -30,6 +30,12 @@ class AntTaskLogger implements BuildListener {
BuildMessages defaultHandler
private final Map<Thread, BuildMessages> threadHandlers = [:]
private final Map<RuntimeConfigurable, BuildMessages> taskHandlers = [:]
private final Project antProject
private final ThreadLocal<Boolean> processMessages = ThreadLocal.withInitial { true }
AntTaskLogger(Project antProject) {
this.antProject = antProject
}
void registerThreadHandler(Thread thread, BuildMessages messages) {
threadHandlers[thread] = messages
@@ -41,7 +47,7 @@ class AntTaskLogger implements BuildListener {
@Override
void messageLogged(BuildEvent event) {
if (event.priority > Project.MSG_INFO) return
if (!processMessages.get() || event.priority > Project.MSG_INFO) return
String message
if (event.task != null) {
@@ -66,6 +72,16 @@ class AntTaskLogger implements BuildListener {
}
}
void logMessageToOtherLoggers(String message, int level) {
try {
processMessages.set(false)
antProject.log(message, level)
}
finally {
processMessages.set(true)
}
}
@Override
void buildStarted(BuildEvent event) {
}
@@ -28,15 +28,14 @@ import org.jetbrains.jps.gant.DefaultBuildInfoPrinter
import org.jetbrains.jps.gant.JpsGantProjectBuilder
import org.jetbrains.jps.gant.TeamCityBuildInfoPrinter
import java.util.function.Function
import java.util.function.BiFunction
/**
* @author nik
*/
@CompileStatic
class BuildMessagesImpl implements BuildMessages {
private final BuildMessageLogger logger
private final Function<String, BuildMessageLogger> loggerFactory
private final BiFunction<String, AntTaskLogger, BuildMessageLogger> loggerFactory
private final AntTaskLogger antTaskLogger
private final BuildMessagesImpl parentInstance
private final List<BuildMessagesImpl> forkedInstances = []
@@ -52,9 +51,9 @@ class BuildMessagesImpl implements BuildMessages {
BuildInfoPrinter buildInfoPrinter = underTeamCity ? new TeamCityBuildInfoPrinter() : new DefaultBuildInfoPrinter()
builder.buildInfoPrinter = buildInfoPrinter
disableAntLogging(antProject)
Function<String, BuildMessageLogger> loggerFactory = underTeamCity ? TeamCityBuildMessageLogger.FACTORY : ConsoleBuildMessageLogger.FACTORY
def antTaskLogger = new AntTaskLogger()
def messages = new BuildMessagesImpl(loggerFactory.apply(null), loggerFactory, antTaskLogger, null)
BiFunction<String, AntTaskLogger, BuildMessageLogger> loggerFactory = underTeamCity ? TeamCityBuildMessageLogger.FACTORY : ConsoleBuildMessageLogger.FACTORY
def antTaskLogger = new AntTaskLogger(antProject)
def messages = new BuildMessagesImpl(loggerFactory.apply(null, antTaskLogger), loggerFactory, antTaskLogger, null)
antTaskLogger.defaultHandler = messages
antProject.addBuildListener(antTaskLogger)
antProject.addReference(key, messages)
@@ -72,7 +71,7 @@ class BuildMessagesImpl implements BuildMessages {
}
}
private BuildMessagesImpl(BuildMessageLogger logger, Function<String, BuildMessageLogger> loggerFactory, AntTaskLogger antTaskLogger,
private BuildMessagesImpl(BuildMessageLogger logger, BiFunction<String, AntTaskLogger, BuildMessageLogger> loggerFactory, AntTaskLogger antTaskLogger,
BuildMessagesImpl parentInstance) {
this.logger = logger
this.loggerFactory = loggerFactory
@@ -141,7 +140,7 @@ class BuildMessagesImpl implements BuildMessages {
@Override
BuildMessages forkForParallelTask(String suggestedTaskName) {
String taskName = taskNameGenerator.generateUniqueName(suggestedTaskName)
def forked = new BuildMessagesImpl(loggerFactory.apply(taskName), loggerFactory, antTaskLogger, this)
def forked = new BuildMessagesImpl(loggerFactory.apply(taskName, antTaskLogger), loggerFactory, antTaskLogger, this)
forkedInstances << forked
return forked
}
@@ -19,14 +19,15 @@ import groovy.transform.CompileStatic
import org.jetbrains.intellij.build.BuildMessageLogger
import org.jetbrains.intellij.build.LogMessage
import java.util.function.Function
import java.util.function.BiFunction
/**
* @author nik
*/
@CompileStatic
class ConsoleBuildMessageLogger extends BuildMessageLogger {
public static final Function<String, BuildMessageLogger> FACTORY = { String taskName -> new ConsoleBuildMessageLogger(taskName) } as Function<String, BuildMessageLogger>
public static final BiFunction<String, AntTaskLogger, BuildMessageLogger> FACTORY = { String taskName, AntTaskLogger logger ->
new ConsoleBuildMessageLogger(taskName)
} as BiFunction<String, AntTaskLogger, BuildMessageLogger>
private final String parallelTaskId
private int indent
private static final PrintStream out = BuildUtils.realSystemOut
@@ -16,11 +16,11 @@
package org.jetbrains.intellij.build.impl
import groovy.transform.CompileStatic
import org.apache.tools.ant.Project
import org.jetbrains.intellij.build.BuildMessageLogger
import org.jetbrains.intellij.build.LogMessage
import java.util.function.Function
import java.util.function.BiFunction
/**
* todo[nik] this is replacement for BuildInfoPrinter. BuildInfoPrinter should be deleted after we move its remaining methods to this class.
*
@@ -28,12 +28,16 @@ import java.util.function.Function
*/
@CompileStatic
class TeamCityBuildMessageLogger extends BuildMessageLogger {
public static final Function<String, BuildMessageLogger> FACTORY = { String taskName -> new TeamCityBuildMessageLogger(taskName) } as Function<String, BuildMessageLogger>
public static final BiFunction<String, AntTaskLogger, BuildMessageLogger> FACTORY = { String taskName, AntTaskLogger antLogger ->
new TeamCityBuildMessageLogger(taskName, antLogger)
} as BiFunction<String, AntTaskLogger, BuildMessageLogger>
private static final PrintStream out = BuildUtils.realSystemOut
private final String parallelTaskId
private AntTaskLogger antTaskLogger
TeamCityBuildMessageLogger(String parallelTaskId) {
TeamCityBuildMessageLogger(String parallelTaskId, AntTaskLogger antTaskLogger) {
this.parallelTaskId = parallelTaskId
this.antTaskLogger = antTaskLogger
}
@Override
@@ -45,16 +49,16 @@ class TeamCityBuildMessageLogger extends BuildMessageLogger {
logPlainMessage(message)
break
case LogMessage.Kind.PROGRESS:
out.println "##teamcity[progressMessage '${escape(message.text)}']"
printTeamCityMessage("progressMessage", false, "'${escape(message.text)}'")
break
case LogMessage.Kind.BLOCK_STARTED:
printTeamCityMessage("blockOpened", "name='${escape(message.text)}'")
printTeamCityMessage("blockOpened", true, "name='${escape(message.text)}'")
break
case LogMessage.Kind.BLOCK_FINISHED:
printTeamCityMessage("blockClosed", "name='${escape(message.text)}'")
printTeamCityMessage("blockClosed", true, "name='${escape(message.text)}'")
break
case LogMessage.Kind.ARTIFACT_BUILT:
out.println "##teamcity[publishArtifacts '${escape(message.text)}']"
printTeamCityMessage("publishArtifacts", false, "'${escape(message.text)}'")
break
}
}
@@ -62,16 +66,20 @@ class TeamCityBuildMessageLogger extends BuildMessageLogger {
void logPlainMessage(LogMessage message) {
String status = message.kind == LogMessage.Kind.WARNING ? " status='WARNING'" : ""
if (parallelTaskId != null || !status.isEmpty()) {
printTeamCityMessage("message", "text='${escape(message.text)}'$status")
printTeamCityMessage("message", true, "text='${escape(message.text)}'$status")
}
else {
antTaskLogger.logMessageToOtherLoggers(message.text, Project.MSG_INFO)
out.println message.text
}
}
private void printTeamCityMessage(String messageId, String messageArguments) {
String flowArg = parallelTaskId != null ? " flowId='${escape(parallelTaskId)}'" : ""
out.println "##teamcity[$messageId$flowArg $messageArguments]"
private void printTeamCityMessage(String messageId, boolean includeFlowId, String messageArguments) {
String flowArg = includeFlowId && parallelTaskId != null ? " flowId='${escape(parallelTaskId)}'" : ""
String message = "##teamcity[$messageId$flowArg $messageArguments]"
//TeamCity reads messages from Ant-based builds via BuildListener so we need to send it to listeners
antTaskLogger.logMessageToOtherLoggers(message, Project.MSG_INFO)
out.println(message)
}
private static char escapeChar(char c) {