Split build-results and build-scan capture into separate files

This commit is contained in:
daz 2024-07-18 14:33:02 -06:00
parent 6d20c16462
commit 94355bbb2f
No known key found for this signature in database
3 changed files with 63 additions and 85 deletions

View file

@ -38,9 +38,7 @@ abstract class BuildResultsRecorder implements BuildService<BuildResultsRecorder
requestedTasks: getParameters().getRequestedTasks().get(),
gradleVersion: GradleVersion.current().version,
gradleHomeDir: getParameters().getGradleHomeDir().get(),
buildFailed: buildFailed,
buildScanUri: null,
buildScanFailed: false
buildFailed: buildFailed
]
def runnerTempDir = System.getProperty("RUNNER_TEMP") ?: System.getenv("RUNNER_TEMP")
@ -50,7 +48,7 @@ abstract class BuildResultsRecorder implements BuildService<BuildResultsRecorder
}
try {
def buildResultsDir = new File(runnerTempDir, ".build-results")
def buildResultsDir = new File(runnerTempDir, ".gradle-actions/build-results")
buildResultsDir.mkdirs()
def buildResultsFile = new File(buildResultsDir, githubActionStep + getParameters().getInvocationId().get() + ".json")
if (!buildResultsFile.exists()) {

View file

@ -13,6 +13,7 @@ def GE_EXTENSION = "gradleEnterprise"
// Only run against root build. Do not run against included builds.
def isTopLevelBuild = gradle.getParent() == null
if (isTopLevelBuild) {
def resultsWriter = new ResultsWriter()
def version = GradleVersion.current().baseVersion
def atLeastGradle3 = version >= GradleVersion.version("3.0")
@ -26,7 +27,7 @@ if (isTopLevelBuild) {
if (useBuildService) {
captureUsingBuildService(invocationId)
} else {
captureUsingBuildFinished(gradle, invocationId)
captureUsingBuildFinished(gradle, invocationId, resultsWriter)
}
// Use the Develocity plugin to also capture build scan links, when available
@ -34,46 +35,63 @@ if (isTopLevelBuild) {
settings.pluginManager.withPlugin(GE_PLUGIN_ID) {
// Only execute if develocity plugin isn't applied.
if (!settings.extensions.findByName(DEVELOCITY_EXTENSION)) {
captureUsingBuildScanPublished(settings.extensions[GE_EXTENSION].buildScan, settings.rootProject, invocationId)
captureUsingBuildScanPublished(settings.extensions[GE_EXTENSION].buildScan, invocationId, resultsWriter)
}
}
settings.pluginManager.withPlugin(DEVELOCITY_PLUGIN_ID) {
captureUsingBuildScanPublished(settings.extensions[DEVELOCITY_EXTENSION].buildScan, settings.rootProject, invocationId)
captureUsingBuildScanPublished(settings.extensions[DEVELOCITY_EXTENSION].buildScan, invocationId, resultsWriter)
}
}
} else if (atLeastGradle3) {
projectsEvaluated { gradle ->
// By default, use 'buildFinished' to capture build results
captureUsingBuildFinished(gradle, invocationId)
captureUsingBuildFinished(gradle, invocationId, resultsWriter)
gradle.rootProject.pluginManager.withPlugin(BUILD_SCAN_PLUGIN_ID) {
// Only execute if develocity plugin isn't applied.
if (!gradle.rootProject.extensions.findByName(DEVELOCITY_EXTENSION)) {
captureUsingBuildScanPublished(gradle.rootProject.extensions[BUILD_SCAN_EXTENSION], gradle.rootProject, invocationId)
captureUsingBuildScanPublished(gradle.rootProject.extensions[BUILD_SCAN_EXTENSION], invocationId, resultsWriter)
}
}
gradle.rootProject.pluginManager.withPlugin(DEVELOCITY_PLUGIN_ID) {
captureUsingBuildScanPublished(gradle.rootProject.extensions[DEVELOCITY_EXTENSION].buildScan, gradle.rootProject, invocationId)
captureUsingBuildScanPublished(gradle.rootProject.extensions[DEVELOCITY_EXTENSION].buildScan, invocationId, resultsWriter)
}
}
}
}
def captureUsingBuildService(invocationId) {
gradle.ext.invocationId = invocationId
apply from: 'gradle-actions.build-result-capture-service.plugin.groovy'
}
void captureUsingBuildFinished(gradle, String invocationId, ResultsWriter resultsWriter) {
gradle.buildFinished { result ->
println "Got buildFinished: ${result}"
def buildResults = [
rootProjectName: rootProject.name,
rootProjectDir: rootProject.projectDir.absolutePath,
requestedTasks: gradle.startParameter.taskNames.join(" "),
gradleVersion: GradleVersion.current().version,
gradleHomeDir: gradle.gradleHomeDir.absolutePath,
buildFailed: result.failure != null
]
resultsWriter.writeToResultsFile("build-results", invocationId, buildResults)
}
}
// The `buildScanPublished` hook allows the capture of the Build Scan URI.
// Results captured this way will overwrite any results from 'buildFinished'.
def captureUsingBuildScanPublished(buildScanExtension, rootProject, invocationId) {
void captureUsingBuildScanPublished(buildScanExtension, String invocationId, ResultsWriter resultsWriter) {
buildScanExtension.with {
def buildResults = new BuildResults(invocationId, gradle, rootProject)
buildFinished { result ->
buildResults.setBuildResult(result)
}
buildScanPublished { buildScan ->
buildResults.setBuildScanUri(buildScan.buildScanUri.toASCIIString())
buildResults.writeToResultsFile(true)
def scanResults = [
buildScanUri: buildScan.buildScanUri.toASCIIString(),
buildScanFailed: false
]
resultsWriter.writeToResultsFile("build-scans", invocationId, scanResults)
def githubOutput = System.getenv("GITHUB_OUTPUT")
if (githubOutput) {
@ -85,63 +103,17 @@ def captureUsingBuildScanPublished(buildScanExtension, rootProject, invocationId
}
onError { error ->
buildResults.setBuildScanFailed()
buildResults.writeToResultsFile(true)
}
}
}
def captureUsingBuildFinished(gradle, invocationId) {
gradle.buildFinished { result ->
println "Got buildFinished: ${result}"
def buildResults = new BuildResults(invocationId, gradle, gradle.rootProject)
buildResults.setBuildResult(result)
buildResults.writeToResultsFile(false)
}
}
def captureUsingBuildService(invocationId) {
gradle.ext.invocationId = invocationId
apply from: 'gradle-actions.build-result-capture-service.plugin.groovy'
}
class BuildResults {
def invocationId
def buildResults
BuildResults(String invocationId, def gradle, def rootProject) {
this.invocationId = invocationId
buildResults = [
rootProjectName: rootProject.name,
rootProjectDir: rootProject.projectDir.absolutePath,
requestedTasks: gradle.startParameter.taskNames.join(" "),
gradleVersion: GradleVersion.current().version,
gradleHomeDir: gradle.gradleHomeDir.absolutePath,
buildFailed: false,
def scanResults = [
buildScanUri: null,
buildScanFailed: false
buildScanFailed: true
]
resultsWriter.writeToResultsFile("build-scans", invocationId, scanResults)
}
}
}
def setBuildResult(def result) {
try {
// Gradle and old Build Scan/Gradle Enterprise plugins report a single optional failure in the build result
buildResults['buildFailed'] = result.failure != null
} catch (Exception e) {
// Develocity plugin unwraps all build failures and reports them as a mandatory array
buildResults['buildFailed'] = !result.failures.empty
}
}
def setBuildScanUri(def buildScanUrl) {
buildResults['buildScanUri'] = buildScanUrl
}
def setBuildScanFailed() {
buildResults['buildScanFailed'] = true
}
def writeToResultsFile(boolean overwrite) {
class ResultsWriter {
void writeToResultsFile(String subDir, String invocationId, def content) {
def runnerTempDir = System.getProperty("RUNNER_TEMP") ?: System.getenv("RUNNER_TEMP")
def githubActionStep = System.getProperty("GITHUB_ACTION") ?: System.getenv("GITHUB_ACTION")
if (!runnerTempDir || !githubActionStep) {
@ -149,19 +121,12 @@ class BuildResults {
}
try {
def buildResultsDir = new File(runnerTempDir, ".build-results")
def buildResultsDir = new File(runnerTempDir, ".gradle-actions/${subDir}")
buildResultsDir.mkdirs()
def buildResultsFile = new File(buildResultsDir, githubActionStep + invocationId + ".json")
// Overwrite any contents written by buildFinished or build service, since this result is a superset.
if (buildResultsFile.exists()) {
if (overwrite) {
buildResultsFile.text = groovy.json.JsonOutput.toJson(buildResults)
if (!buildResultsFile.exists()) {
buildResultsFile << groovy.json.JsonOutput.toJson(content)
}
} else {
buildResultsFile << groovy.json.JsonOutput.toJson(buildResults)
}
} catch (Exception e) {
println "\ngradle action failed to write build-results file. Will continue.\n> ${e.getLocalizedMessage()}"
}

View file

@ -122,6 +122,7 @@ class TestBuildResultRecorder extends BaseInitScriptTest {
then:
assertResults('help', testGradleVersion, false, true)
assert buildResultFile.delete()
assert scanResultFile.delete()
when:
run(['help', '--configuration-cache'], testGradleVersion.gradleVersion)
@ -240,12 +241,16 @@ class TestBuildResultRecorder extends BaseInitScriptTest {
assert results['gradleVersion'] == testGradleVersion.gradleVersion.version
assert results['gradleHomeDir'] != null
assert results['buildFailed'] == hasFailure
assert results['buildScanUri'] == (hasBuildScan ? "${mockScansServer.address}s/${PUBLIC_BUILD_SCAN_ID}" : null)
assert results['buildScanFailed'] == scanUploadFailed
if (hasBuildScan || scanUploadFailed) {
def scanResults = new JsonSlurper().parse(scanResultFile)
assert scanResults['buildScanUri'] == (hasBuildScan ? "${mockScansServer.address}s/${PUBLIC_BUILD_SCAN_ID}" : null)
assert scanResults['buildScanFailed'] == scanUploadFailed
}
}
private File getBuildResultFile() {
def buildResultsDir = new File(testProjectDir, '.build-results')
def buildResultsDir = new File(testProjectDir, '.gradle-actions/build-results')
assert buildResultsDir.directory
assert buildResultsDir.listFiles().size() == 1
def resultsFile = buildResultsDir.listFiles()[0]
@ -253,4 +258,14 @@ class TestBuildResultRecorder extends BaseInitScriptTest {
assert resultsFile.text.count('rootProjectName') == 1
return resultsFile
}
private File getScanResultFile() {
def buildResultsDir = new File(testProjectDir, '.gradle-actions/build-scans')
assert buildResultsDir.directory
assert buildResultsDir.listFiles().size() == 1
def resultsFile = buildResultsDir.listFiles()[0]
assert resultsFile.name.startsWith('github-step-id')
assert resultsFile.text.count('buildScanUri') == 1
return resultsFile
}
}