Skip to content
This repository was archived by the owner on Feb 20, 2025. It is now read-only.

Commit 65fdc33

Browse files
committed
Add log error handling to Unity task when the Unity process execution fails
1 parent f611f13 commit 65fdc33

File tree

8 files changed

+417
-52
lines changed

8 files changed

+417
-52
lines changed

src/integrationTest/groovy/wooga/gradle/unity/UnityPluginIntegrationSpec.groovy

-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ package wooga.gradle.unity
2020
import com.wooga.spock.extensions.unity.UnityPathResolution
2121
import com.wooga.spock.extensions.unity.UnityPluginTestOptions
2222
import spock.lang.Unroll
23-
import wooga.gradle.unity.models.BuildTarget
2423
import wooga.gradle.unity.models.UnityCommandLineOption
2524
import wooga.gradle.unity.tasks.Test
2625
import wooga.gradle.unity.utils.ProjectSettingsFile

src/integrationTest/groovy/wooga/gradle/unity/UnityTaskIntegrationSpec.groovy

+19
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import com.wooga.spock.extensions.unity.UnityPathResolution
2121
import com.wooga.spock.extensions.unity.UnityPluginTestOptions
2222
import com.wooga.spock.extensions.uvm.UnityInstallation
2323
import org.gradle.api.logging.LogLevel
24+
import spock.lang.Ignore
2425
import spock.lang.IgnoreIf
2526
import spock.lang.Unroll
2627
import spock.util.environment.RestoreSystemProperties
@@ -406,4 +407,22 @@ abstract class UnityTaskIntegrationSpec<T extends UnityTask> extends UnityIntegr
406407
logFile.text.contains(mockUnityStartupMessage)
407408
}
408409

410+
@Ignore
411+
// TODO: How to make the task fail/throw within the exec block?
412+
def "task action does not invoke post execute if process didn't run"() {
413+
given: "a task that is definitely gonna fail"
414+
appendToSubjectTask("""
415+
environment = null
416+
""".stripIndent())
417+
418+
when:
419+
def result = runTasks(subjectUnderTestName)
420+
421+
then:
422+
!result.success
423+
outputContains(result, "${subjectUnderTestName}.preExecute")
424+
outputContains(result, "${subjectUnderTestName}.execute")
425+
!outputContains(result, "${subjectUnderTestName}.postExecute")
426+
}
427+
409428
}

src/main/groovy/wooga/gradle/unity/UnityPlugin.groovy

+4-3
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,15 @@ import org.gradle.language.base.plugins.LifecycleBasePlugin
3131
import wooga.gradle.unity.models.APICompatibilityLevel
3232
import wooga.gradle.unity.models.DefaultUnityAuthentication
3333
import wooga.gradle.unity.internal.DefaultUnityPluginExtension
34-
import wooga.gradle.unity.models.BuildTarget
3534
import wooga.gradle.unity.models.TestPlatform
3635
import wooga.gradle.unity.tasks.Activate
3736

3837
import wooga.gradle.unity.tasks.ReturnLicense
3938
import wooga.gradle.unity.tasks.SetAPICompatibilityLevel
4039
import wooga.gradle.unity.tasks.Test
4140
import wooga.gradle.unity.utils.ProjectSettingsFile
42-
import wooga.gradle.unity.utils.UnityTestTaskReport
43-
import wooga.gradle.unity.utils.UnityTestTaskReportsImpl
41+
import wooga.gradle.unity.utils.UnityLogErrorParse
42+
import wooga.gradle.unity.utils.UnityLogErrorReader
4443

4544
/**
4645
* A {@link org.gradle.api.Plugin} which provides tasks to run unity batch-mode commands.
@@ -111,6 +110,7 @@ class UnityPlugin implements Plugin<Project> {
111110
extension.pluginsDir.convention(extension.assetsDir.dir("Plugins"))
112111
extension.logsDir.convention(UnityPluginConventions.logDirectory.getDirectoryValueProvider(project))
113112

113+
extension.logErrorReader.convention(new UnityLogErrorReader())
114114
extension.logCategory.convention(UnityPluginConventions.logCategory.getStringValueProvider(project))
115115
final ReportingExtension reportingExtension = (ReportingExtension) project.extensions.getByName(ReportingExtension.NAME)
116116
extension.reportsDir.convention(project.layout.buildDirectory.dir(project.provider({ reportingExtension.file("unity").path })))
@@ -149,6 +149,7 @@ class UnityPlugin implements Plugin<Project> {
149149
t.projectDirectory.convention(extension.projectDirectory)
150150
t.projectSettings.convention(extension.projectSettings)
151151
t.logCategory.convention(extension.logCategory)
152+
t.logErrorReader.convention(extension.logErrorReader)
152153

153154
t.unityLogFile.convention(extension.logsDir.file(project.provider {
154155
t.logCategory.get().isEmpty() ? "${t.name}.log" : "${t.logCategory.get()}/${t.name}.log"

src/main/groovy/wooga/gradle/unity/UnityPluginExtension.groovy

-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import org.gradle.api.file.DirectoryProperty
2424
import org.gradle.api.provider.Property
2525
import org.gradle.api.provider.Provider
2626
import org.gradle.api.tasks.Internal
27-
import wooga.gradle.unity.models.BuildTarget
2827
import wooga.gradle.unity.traits.APICompatibilityLevelSpec
2928
import wooga.gradle.unity.traits.UnityAuthenticationSpec
3029
import wooga.gradle.unity.traits.UnityLicenseSpec

src/main/groovy/wooga/gradle/unity/UnityTask.groovy

+38-7
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,13 @@ import org.gradle.internal.io.LineBufferingOutputStream
2727
import org.gradle.internal.io.TextStream
2828
import org.gradle.process.ExecResult
2929
import org.gradle.process.ExecSpec
30-
import sun.reflect.misc.FieldUtil
3130
import wooga.gradle.unity.models.UnityCommandLineOption
3231
import wooga.gradle.unity.traits.ArgumentsSpec
3332
import wooga.gradle.unity.traits.UnityCommandLineSpec
3433
import wooga.gradle.unity.traits.UnitySpec
3534
import wooga.gradle.unity.utils.FileUtils
3635
import wooga.gradle.unity.utils.ForkTextStream
36+
import wooga.gradle.unity.utils.UnityLogErrorReader
3737
import wooga.gradle.unity.utils.UnityVersionManager
3838

3939
abstract class UnityTask extends DefaultTask
@@ -47,21 +47,24 @@ abstract class UnityTask extends DefaultTask
4747
// and also an additional one for our custom use
4848
wooga_gradle_unity_traits_ArgumentsSpec__arguments = project.provider({ getUnityCommandLineOptions() })
4949
wooga_gradle_unity_traits_ArgumentsSpec__additionalArguments = project.objects.listProperty(String)
50-
wooga_gradle_unity_traits_ArgumentsSpec__environment = project.objects.mapProperty(String, Object)
50+
wooga_gradle_unity_traits_ArgumentsSpec__environment = project.objects.mapProperty(String, Object)
5151
}
5252

5353
@TaskAction
5454
void exec() {
55+
// Invoked before the unity process
56+
logger.info("${name}.preExecute")
57+
preExecute()
58+
// Execute the unity process
59+
logger.info("${name}.execute")
5560
ExecResult execResult = project.exec(new Action<ExecSpec>() {
5661
@Override
5762
void execute(ExecSpec exec) {
5863

64+
// TODO: Should these be moved before preExecute?
5965
if (!unityPath.present) {
6066
throw new GradleException("Unity path is not set")
6167
}
62-
63-
preExecute()
64-
6568
def unityPath = unityPath.get().asFile.absolutePath
6669
def unityArgs = getAllArguments()
6770
def unityEnvironment = environment.get()
@@ -76,8 +79,11 @@ abstract class UnityTask extends DefaultTask
7679
}
7780
}
7881
})
79-
80-
execResult.assertNormalExitValue()
82+
if (execResult.exitValue != 0) {
83+
handleUnityProcessError(execResult)
84+
}
85+
// Invoked after the unity process (even if it failed)
86+
logger.info("${name}.postExecute")
8187
postExecute(execResult)
8288
}
8389

@@ -97,6 +103,31 @@ abstract class UnityTask extends DefaultTask
97103
protected void postExecute(ExecResult result) {
98104
}
99105

106+
/**
107+
* Invoked whenever the Unity process executed by the task exits with an error,
108+
* @param result The execution result of the Unity process
109+
*/
110+
protected void handleUnityProcessError(ExecResult result) {
111+
logger.error("Unity process failed with exit value ${result.exitValue}...")
112+
113+
// Look up the log
114+
if (!unityLogFile.isPresent()) {
115+
logger.warn("No log file was configured for the task ${this.name}")
116+
return
117+
}
118+
119+
File logFile = unityLogFile.get().asFile
120+
if (!logFile.exists()) {
121+
logger.warn("No log file was written for the task ${this.name}")
122+
return
123+
}
124+
125+
// TODO: Gracefully show the error here?
126+
UnityLogErrorReader reader = new UnityLogErrorReader()
127+
def errorParse = reader.parse(logFile)
128+
logger.error(errorParse.toString())
129+
}
130+
100131
@Internal
101132
protected ArtifactVersion getUnityVersion() {
102133
File file = unityPath.present ? unityPath.get().asFile : null

src/main/groovy/wooga/gradle/unity/traits/UnitySpec.groovy

+10-9
Original file line numberDiff line numberDiff line change
@@ -16,25 +16,17 @@
1616

1717
package wooga.gradle.unity.traits
1818

19-
import org.gradle.api.model.ObjectFactory
2019
import org.gradle.api.file.Directory
2120
import org.gradle.api.file.DirectoryProperty
2221
import org.gradle.api.file.RegularFile
2322
import org.gradle.api.file.RegularFileProperty
2423
import org.gradle.api.provider.Property
2524
import org.gradle.api.provider.Provider
26-
import org.gradle.api.provider.ProviderFactory
27-
import org.gradle.api.tasks.Input
28-
import org.gradle.api.tasks.InputDirectory
2925
import org.gradle.api.tasks.InputFile
3026
import org.gradle.api.tasks.Internal
31-
import org.gradle.api.tasks.Optional
3227
import org.gradle.api.tasks.OutputFile
33-
import org.gradle.api.tasks.SkipWhenEmpty
34-
import org.gradle.internal.impldep.org.eclipse.jgit.errors.NotSupportedException
35-
import wooga.gradle.unity.UnityPluginConventions
36-
import wooga.gradle.unity.models.BuildTarget
3728
import wooga.gradle.unity.utils.ProjectSettingsFile
29+
import wooga.gradle.unity.utils.UnityLogErrorReader
3830

3931
import javax.inject.Inject
4032

@@ -115,5 +107,14 @@ trait UnitySpec extends UnityBaseSpec {
115107
logToStdout
116108
}
117109

110+
private final Property<UnityLogErrorReader> logErrorReader = objects.property(UnityLogErrorReader)
111+
/**
112+
* @return The reader used for parsing the Unity Editor log whenever the exits with a failure code
113+
*/
114+
@Internal
115+
Property<UnityLogErrorReader> getLogErrorReader(){
116+
logErrorReader
117+
}
118+
118119
}
119120

0 commit comments

Comments
 (0)