Capture build results when GE plugin is applied but no build-scan is published

This commit is contained in:
Daz DeBoer 2022-06-05 00:18:20 -06:00
parent 6001bc9edc
commit 3f2d9cde44
No known key found for this signature in database
GPG key ID: DD6B9F0B06683D5D
3 changed files with 46 additions and 18 deletions

View file

@ -6,8 +6,9 @@ import org.gradle.util.GradleVersion
// But projectsEvaluated is good enough, since the build service won't catch configuration failures anyway // But projectsEvaluated is good enough, since the build service won't catch configuration failures anyway
projectsEvaluated { projectsEvaluated {
def projectTracker = gradle.sharedServices.registerIfAbsent("gradle-build-action-buildResultsRecorder", BuildResultsRecorder, { spec -> def projectTracker = gradle.sharedServices.registerIfAbsent("gradle-build-action-buildResultsRecorder", BuildResultsRecorder, { spec ->
spec.getParameters().getRootProject().set(gradle.rootProject.name); spec.getParameters().getRootProject().set(gradle.rootProject.name)
spec.getParameters().getRequestedTasks().set(gradle.startParameter.taskNames.join(" ")); spec.getParameters().getRequestedTasks().set(gradle.startParameter.taskNames.join(" "))
spec.getParameters().getInvocationId().set(gradle.ext.invocationId)
}) })
gradle.services.get(BuildEventsListenerRegistry).onTaskCompletion(projectTracker) gradle.services.get(BuildEventsListenerRegistry).onTaskCompletion(projectTracker)
@ -16,8 +17,9 @@ projectsEvaluated {
abstract class BuildResultsRecorder implements BuildService<BuildResultsRecorder.Params>, OperationCompletionListener, AutoCloseable { abstract class BuildResultsRecorder implements BuildService<BuildResultsRecorder.Params>, OperationCompletionListener, AutoCloseable {
private boolean buildFailed = false private boolean buildFailed = false
interface Params extends BuildServiceParameters { interface Params extends BuildServiceParameters {
Property<String> getRootProject(); Property<String> getRootProject()
Property<String> getRequestedTasks(); Property<String> getRequestedTasks()
Property<String> getInvocationId()
} }
public void onFinish(FinishEvent finishEvent) { public void onFinish(FinishEvent finishEvent) {
@ -38,7 +40,7 @@ abstract class BuildResultsRecorder implements BuildService<BuildResultsRecorder
def buildResultsDir = new File(System.getenv("RUNNER_TEMP"), ".build-results") def buildResultsDir = new File(System.getenv("RUNNER_TEMP"), ".build-results")
buildResultsDir.mkdirs() buildResultsDir.mkdirs()
def buildResultsFile = new File(buildResultsDir, System.getenv("GITHUB_ACTION") + System.currentTimeMillis() + ".json") def buildResultsFile = new File(buildResultsDir, System.getenv("GITHUB_ACTION") + getParameters().getInvocationId().get() + ".json")
buildResultsFile << groovy.json.JsonOutput.toJson(buildResults) buildResultsFile << groovy.json.JsonOutput.toJson(buildResults)
} }
} }

View file

@ -11,29 +11,34 @@ if (isTopLevelBuild) {
def atLeastGradle3 = version >= GradleVersion.version("3.0") def atLeastGradle3 = version >= GradleVersion.version("3.0")
def atLeastGradle6 = version >= GradleVersion.version("6.0") def atLeastGradle6 = version >= GradleVersion.version("6.0")
def invocationId = "-${System.currentTimeMillis()}"
if (atLeastGradle6) { if (atLeastGradle6) {
def useBuildService = version >= GradleVersion.version("6.6") def useBuildService = version >= GradleVersion.version("6.6")
settingsEvaluated { settings -> settingsEvaluated { settings ->
// The `buildScanPublished` hook is the only way to capture the build scan URI.
if (settings.pluginManager.hasPlugin("com.gradle.enterprise")) { if (settings.pluginManager.hasPlugin("com.gradle.enterprise")) {
captureUsingBuildScanPublished(settings.extensions["gradleEnterprise"].buildScan, settings.rootProject.name) captureUsingBuildScanPublished(settings.extensions["gradleEnterprise"].buildScan, settings.rootProject.name, invocationId)
} else if (useBuildService) { }
captureUsingBuildService(settings) // We also need to add hooks in case the plugin is applied but no build scan is published
if (useBuildService) {
captureUsingBuildService(settings, invocationId)
} else { } else {
captureUsingBuildFinished(gradle) captureUsingBuildFinished(gradle, invocationId)
} }
} }
} else if (atLeastGradle3) { } else if (atLeastGradle3) {
projectsEvaluated { gradle -> projectsEvaluated { gradle ->
if (gradle.rootProject.pluginManager.hasPlugin("com.gradle.build-scan")) { if (gradle.rootProject.pluginManager.hasPlugin("com.gradle.build-scan")) {
captureUsingBuildScanPublished(gradle.rootProject.extensions["buildScan"], gradle.rootProject.name) captureUsingBuildScanPublished(gradle.rootProject.extensions["buildScan"], gradle.rootProject.name, invocationId)
} else {
captureUsingBuildFinished(gradle)
} }
// 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 { buildScanExtension.with {
def requestedTasks = gradle.startParameter.taskNames.join(" ") def requestedTasks = gradle.startParameter.taskNames.join(" ")
def gradleVersion = GradleVersion.current().version def gradleVersion = GradleVersion.current().version
@ -56,15 +61,21 @@ def captureUsingBuildScanPublished(buildScanExtension, rootProjectName) {
def buildResultsDir = new File(System.getenv("RUNNER_TEMP"), ".build-results") def buildResultsDir = new File(System.getenv("RUNNER_TEMP"), ".build-results")
buildResultsDir.mkdirs() 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)
// 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}") println("::set-output name=build-scan-url::${buildScan.buildScanUri}")
} }
} }
} }
def captureUsingBuildFinished(gradle) { def captureUsingBuildFinished(gradle, invocationId) {
gradle.buildFinished { result -> gradle.buildFinished { result ->
def buildResults = [ def buildResults = [
rootProject: gradle.rootProject.name, rootProject: gradle.rootProject.name,
@ -76,11 +87,12 @@ def captureUsingBuildFinished(gradle) {
def buildResultsDir = new File(System.getenv("RUNNER_TEMP"), ".build-results") def buildResultsDir = new File(System.getenv("RUNNER_TEMP"), ".build-results")
buildResultsDir.mkdirs() 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) 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' apply from: 'build-result-capture-service.plugin.groovy'
} }

View file

@ -68,6 +68,20 @@ class TestBuildResultRecorder extends BaseInitScriptTest {
testGradleVersion << ALL_VERSIONS 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"() { def "produces build results file for failing build on #testGradleVersion with build scan published"() {
assumeTrue testGradleVersion.compatibleWithCurrentJvm assumeTrue testGradleVersion.compatibleWithCurrentJvm