Skip to content

Commit 22cd4d3

Browse files
committed
chore: avoid printing project stactraces multiple times
Previously, each subproject printed failure, thus it ended up in multiple messages for the same failure
1 parent 983b78b commit 22cd4d3

File tree

6 files changed

+176
-30
lines changed

6 files changed

+176
-30
lines changed
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* Copyright 2019 Vladimir Sitnikov <[email protected]>
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
*/
17+
18+
package com.github.vlsi.gradle
19+
20+
import org.gradle.api.flow.BuildWorkResult
21+
import org.gradle.api.flow.FlowAction
22+
import org.gradle.api.flow.FlowParameters
23+
import org.gradle.api.provider.Property
24+
import org.gradle.api.tasks.Input
25+
26+
interface BuildFailurePrintFlowParameters: FlowParameters {
27+
@get:Input
28+
val enableStyle: Property<Boolean>
29+
@get:Input
30+
val fullTrace: Property<Boolean>
31+
@get:Input
32+
val buildWorkResult: Property<BuildWorkResult>
33+
}
34+
35+
abstract class BuildFailurePrintFlowAction: FlowAction<BuildFailurePrintFlowParameters> {
36+
override fun execute(parameters: BuildFailurePrintFlowParameters) {
37+
val buildWorkResult = parameters.buildWorkResult.get()
38+
buildWorkResult.failure.ifPresent { failure ->
39+
printBuildFailures(
40+
failure,
41+
"Build",
42+
enableStyle = parameters.enableStyle.get(),
43+
fullTrace = parameters.fullTrace.get()
44+
)
45+
}
46+
}
47+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright 2019 Vladimir Sitnikov <[email protected]>
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
*/
17+
18+
package com.github.vlsi.gradle
19+
20+
import org.gradle.api.services.BuildService
21+
import org.gradle.api.services.BuildServiceParameters
22+
23+
interface BuildFailurePrintServiceParameters: BuildServiceParameters {
24+
}
25+
26+
abstract class BuildFailurePrintService: BuildService<BuildFailurePrintServiceParameters> {
27+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright 2019 Vladimir Sitnikov <[email protected]>
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
*/
17+
18+
package com.github.vlsi.gradle
19+
20+
import org.gradle.api.flow.FlowProviders
21+
import org.gradle.api.flow.FlowScope
22+
import javax.inject.Inject
23+
24+
interface FlowScopedServices {
25+
@get:Inject
26+
val flowScope: FlowScope
27+
@get:Inject
28+
val flowProviders: FlowProviders
29+
}

plugins/gradle-extensions-plugin/src/main/kotlin/com/github/vlsi/gradle/ProjectExtensionsPlugin.kt

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ import org.gradle.api.invocation.Gradle
2626
import org.gradle.api.tasks.testing.AbstractTestTask
2727
import org.gradle.api.tasks.testing.logging.TestLogEvent
2828
import org.gradle.build.event.BuildEventsListenerRegistry
29+
import org.gradle.kotlin.dsl.always
30+
import org.gradle.kotlin.dsl.newInstance
2931
import org.gradle.kotlin.dsl.registerIfAbsent
3032
import org.gradle.kotlin.dsl.support.serviceOf
3133
import org.gradle.kotlin.dsl.withType
@@ -50,16 +52,23 @@ class ProjectExtensionsPlugin : Plugin<Project> {
5052
default = System.getProperty("os.name").contains("windows", ignoreCase = true)
5153
)
5254
val fullTrace = target.props.bool("fulltrace")
53-
if (!target.gradle.configurationCacheEnabled) {
54-
target.gradle.addBuildListener(
55-
ReportBuildFailures(
56-
enableStyle = enableStyle,
57-
fullTrace = fullTrace
58-
)
55+
val buildServiceId = "BuildFailurePrintService.sharedService"
56+
val sharedServices = target.gradle.sharedServices
57+
if (sharedServices.registrations.findByName(buildServiceId) == null) {
58+
sharedServices.registerIfAbsent(
59+
buildServiceId,
60+
BuildFailurePrintService::class,
5961
)
62+
if (GradleVersion.current() >= GradleVersion.version("8.1")) {
63+
reportBuildFailure(target, enableStyle, fullTrace)
64+
} else if (!target.gradle.configurationCacheEnabled) {
65+
target.gradle.addBuildListener(
66+
ReportBuildFailures(enableStyle, fullTrace)
67+
)
68+
}
6069
}
6170
if (GitHubActionsLogger.isEnabled) {
62-
val gitHubMarkers = target.gradle.sharedServices.registerIfAbsent(
71+
val gitHubMarkers = sharedServices.registerIfAbsent(
6372
"PrintGitHubActionsMarkersForFailingTasks",
6473
PrintGitHubActionsMarkersForFailingTasks::class
6574
) {
@@ -81,6 +90,17 @@ class ProjectExtensionsPlugin : Plugin<Project> {
8190
printTestResults()
8291
}
8392
}
93+
94+
private fun reportBuildFailure(target: Project, enableStyle: Boolean, fullTrace: Boolean) {
95+
val flowScopeServices = target.objects.newInstance<FlowScopedServices>()
96+
flowScopeServices.flowScope.always(BuildFailurePrintFlowAction::class) {
97+
parameters {
98+
this.enableStyle.set(enableStyle)
99+
this.fullTrace.set(fullTrace)
100+
this.buildWorkResult.set(flowScopeServices.flowProviders.buildWorkResult)
101+
}
102+
}
103+
}
84104
}
85105

86106
internal fun createThrowablePrinter(fullTrace: Boolean) = ThrowablePrinter().apply {

plugins/gradle-extensions-plugin/src/main/kotlin/com/github/vlsi/gradle/ReportBuildFailures.kt

Lines changed: 36 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -21,33 +21,46 @@ import com.github.vlsi.gradle.styledtext.Style
2121
import com.github.vlsi.gradle.styledtext.StyledTextBuilder
2222
import org.gradle.BuildAdapter
2323
import org.gradle.BuildResult
24+
import java.util.concurrent.atomic.AtomicBoolean
2425

2526
class ReportBuildFailures(
26-
val enableStyle: Boolean,
27-
val fullTrace: Boolean,
28-
) : BuildAdapter() {
27+
private val enableStyle: Boolean,
28+
private val fullTrace: Boolean
29+
): BuildAdapter() {
30+
companion object {
31+
private val buildCompleted = AtomicBoolean()
32+
}
2933
override fun buildFinished(result: BuildResult) {
30-
val failure = result.failure ?: return
31-
val gradle = result.gradle
32-
val sb = StyledTextBuilder(enableStyle = enableStyle)
33-
val throwablePrinter = createThrowablePrinter(fullTrace = fullTrace)
34-
throwablePrinter.indent = " "
35-
sb.appendPlatformLine()
36-
sb.append(result.action).append(" ")
37-
sb.withStyle(Style.BOLD) {
38-
append(gradle?.rootProject?.name ?: "unknown rootProject")
39-
sb.append(" ")
40-
sb.withStyle(
41-
StandardColor.RED.foreground) {
42-
append("FAILURE")
43-
}
34+
if (!buildCompleted.compareAndSet(false, true)) {
35+
return
4436
}
45-
// Sometimes the message interferes with Gradle's progress bar.
46-
// So we print extra spaces so the garbage after "reason" is wiped out.
47-
sb.appendPlatformLine(" reason: ")
48-
throwablePrinter.print(failure, sb)
49-
if (throwablePrinter.interestingCases > 0 || throwablePrinter.classExcludes.isEmpty()) {
50-
println(sb.toString())
37+
printBuildFailures(
38+
result.failure ?: return,
39+
action = result.action,
40+
enableStyle = enableStyle,
41+
fullTrace = fullTrace
42+
)
43+
}
44+
}
45+
46+
fun printBuildFailures(failure: Throwable, action: String = "Build", enableStyle: Boolean, fullTrace: Boolean) {
47+
val sb = StyledTextBuilder(enableStyle = enableStyle)
48+
val throwablePrinter = createThrowablePrinter(fullTrace = fullTrace)
49+
throwablePrinter.indent = " "
50+
sb.appendPlatformLine()
51+
sb.append(action).append(" ")
52+
sb.withStyle(Style.BOLD) {
53+
sb.append(" ")
54+
sb.withStyle(
55+
StandardColor.RED.foreground) {
56+
append("FAILURE")
5157
}
5258
}
59+
// Sometimes the message interferes with Gradle's progress bar.
60+
// So we print extra spaces so the garbage after "reason" is wiped out.
61+
sb.appendPlatformLine(" reason: ")
62+
throwablePrinter.print(failure, sb)
63+
if (throwablePrinter.interestingCases > 0 || throwablePrinter.classExcludes.isEmpty()) {
64+
println(sb.toString())
65+
}
5366
}

plugins/gradle-extensions-plugin/src/main/kotlin/com/github/vlsi/gradle/ThrowablePrinter.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,11 @@ import com.github.vlsi.gradle.styledtext.StandardColor
2020
import com.github.vlsi.gradle.styledtext.Style
2121
import com.github.vlsi.gradle.styledtext.StyledTextBuilder
2222
import org.gradle.api.GradleException
23+
import org.gradle.api.InvalidUserDataException
2324
import org.gradle.api.UncheckedIOException
2425
import org.gradle.api.internal.tasks.TaskDependencyResolveException
2526
import org.gradle.api.tasks.TaskExecutionException
27+
import org.gradle.execution.MultipleBuildFailures
2628
import org.gradle.execution.TaskSelectionException
2729
import org.gradle.execution.commandline.TaskConfigurationException
2830
import org.gradle.internal.UncheckedException
@@ -126,6 +128,14 @@ class ThrowablePrinter {
126128
{
127129
it.message?.startsWith("The following files have format violations") == true
128130
},
131+
{
132+
it is MultipleBuildFailures
133+
},
134+
{
135+
it is InvalidUserDataException &&
136+
it.message?.startsWith("Cannot perform signing task") == true &&
137+
it.message?.endsWith("because it has no configured signatory") == true
138+
},
129139
{
130140
it.javaClass.name == "org.opentest4j.MultipleFailuresError"
131141
},

0 commit comments

Comments
 (0)