diff --git a/src/resources/build-result-capture-service.plugin.groovy b/src/resources/build-result-capture-service.plugin.groovy index 2942529..e4a29a1 100644 --- a/src/resources/build-result-capture-service.plugin.groovy +++ b/src/resources/build-result-capture-service.plugin.groovy @@ -6,8 +6,9 @@ import org.gradle.util.GradleVersion // But projectsEvaluated is good enough, since the build service won't catch configuration failures anyway projectsEvaluated { def projectTracker = gradle.sharedServices.registerIfAbsent("gradle-build-action-buildResultsRecorder", BuildResultsRecorder, { spec -> - spec.getParameters().getRootProject().set(gradle.rootProject.name); - spec.getParameters().getRequestedTasks().set(gradle.startParameter.taskNames.join(" ")); + spec.getParameters().getRootProject().set(gradle.rootProject.name) + spec.getParameters().getRequestedTasks().set(gradle.startParameter.taskNames.join(" ")) + spec.getParameters().getInvocationId().set(gradle.ext.invocationId) }) gradle.services.get(BuildEventsListenerRegistry).onTaskCompletion(projectTracker) @@ -16,8 +17,9 @@ projectsEvaluated { abstract class BuildResultsRecorder implements BuildService, OperationCompletionListener, AutoCloseable { private boolean buildFailed = false interface Params extends BuildServiceParameters { - Property getRootProject(); - Property getRequestedTasks(); + Property getRootProject() + Property getRequestedTasks() + Property getInvocationId() } public void onFinish(FinishEvent finishEvent) { @@ -38,7 +40,7 @@ abstract class BuildResultsRecorder implements BuildService= GradleVersion.version("3.0") def atLeastGradle6 = version >= GradleVersion.version("6.0") + def invocationId = "-${System.currentTimeMillis()}" + if (atLeastGradle6) { def useBuildService = version >= GradleVersion.version("6.6") settingsEvaluated { settings -> + // The `buildScanPublished` hook is the only way to capture the build scan URI. if (settings.pluginManager.hasPlugin("com.gradle.enterprise")) { - captureUsingBuildScanPublished(settings.extensions["gradleEnterprise"].buildScan, settings.rootProject.name) - } else if (useBuildService) { - captureUsingBuildService(settings) + captureUsingBuildScanPublished(settings.extensions["gradleEnterprise"].buildScan, settings.rootProject.name, invocationId) + } + // We also need to add hooks in case the plugin is applied but no build scan is published + if (useBuildService) { + captureUsingBuildService(settings, invocationId) } else { - captureUsingBuildFinished(gradle) + captureUsingBuildFinished(gradle, invocationId) } } } else if (atLeastGradle3) { projectsEvaluated { gradle -> if (gradle.rootProject.pluginManager.hasPlugin("com.gradle.build-scan")) { - captureUsingBuildScanPublished(gradle.rootProject.extensions["buildScan"], gradle.rootProject.name) - } else { - captureUsingBuildFinished(gradle) + captureUsingBuildScanPublished(gradle.rootProject.extensions["buildScan"], gradle.rootProject.name, invocationId) } + // We need to capture in buildFinished in case the plugin is applied but no build scan is published + captureUsingBuildFinished(gradle, invocationId) } } } -def captureUsingBuildScanPublished(buildScanExtension, rootProjectName) { +def captureUsingBuildScanPublished(buildScanExtension, rootProjectName, invocationId) { buildScanExtension.with { def requestedTasks = gradle.startParameter.taskNames.join(" ") def gradleVersion = GradleVersion.current().version @@ -56,15 +61,21 @@ def captureUsingBuildScanPublished(buildScanExtension, rootProjectName) { def buildResultsDir = new File(System.getenv("RUNNER_TEMP"), ".build-results") buildResultsDir.mkdirs() - def buildResultsFile = new File(buildResultsDir, System.getenv("GITHUB_ACTION") + System.currentTimeMillis() + ".json") - buildResultsFile << groovy.json.JsonOutput.toJson(buildResults) + def buildResultsFile = new File(buildResultsDir, System.getenv("GITHUB_ACTION") + invocationId + ".json") + + // Overwrite any contents written by buildFinished or build service, since this result is a superset. + if (buildResultsFile.exists()) { + buildResultsFile.text = groovy.json.JsonOutput.toJson(buildResults) + } else { + buildResultsFile << groovy.json.JsonOutput.toJson(buildResults) + } println("::set-output name=build-scan-url::${buildScan.buildScanUri}") } } } -def captureUsingBuildFinished(gradle) { +def captureUsingBuildFinished(gradle, invocationId) { gradle.buildFinished { result -> def buildResults = [ rootProject: gradle.rootProject.name, @@ -76,11 +87,12 @@ def captureUsingBuildFinished(gradle) { def buildResultsDir = new File(System.getenv("RUNNER_TEMP"), ".build-results") buildResultsDir.mkdirs() - def buildResultsFile = new File(buildResultsDir, System.getenv("GITHUB_ACTION") + System.currentTimeMillis() + ".json") + def buildResultsFile = new File(buildResultsDir, System.getenv("GITHUB_ACTION") + invocationId + ".json") buildResultsFile << groovy.json.JsonOutput.toJson(buildResults) } } -def captureUsingBuildService(settings) { +def captureUsingBuildService(settings, invocationId) { + gradle.ext.invocationId = invocationId apply from: 'build-result-capture-service.plugin.groovy' } diff --git a/test/test-init-scripts/src/test/groovy/com/gradle/gradlebuildaction/TestBuildResultRecorder.groovy b/test/test-init-scripts/src/test/groovy/com/gradle/gradlebuildaction/TestBuildResultRecorder.groovy index cadec01..6b564c3 100644 --- a/test/test-init-scripts/src/test/groovy/com/gradle/gradlebuildaction/TestBuildResultRecorder.groovy +++ b/test/test-init-scripts/src/test/groovy/com/gradle/gradlebuildaction/TestBuildResultRecorder.groovy @@ -68,6 +68,20 @@ class TestBuildResultRecorder extends BaseInitScriptTest { testGradleVersion << ALL_VERSIONS } + def "produces build results file for #testGradleVersion with ge-plugin and no build scan published"() { + assumeTrue testGradleVersion.compatibleWithCurrentJvm + + when: + declareGePluginApplication(testGradleVersion.gradleVersion) + run(['help', '--no-scan'], initScript, testGradleVersion.gradleVersion) + + then: + assertResults('help', testGradleVersion, false, false) + + where: + testGradleVersion << ALL_VERSIONS + } + def "produces build results file for failing build on #testGradleVersion with build scan published"() { assumeTrue testGradleVersion.compatibleWithCurrentJvm