Skip to content

Commit

Permalink
Only write dependency-graph on build success
Browse files Browse the repository at this point in the history
Fixes #115
  • Loading branch information
bigdaz committed Feb 12, 2024
1 parent 952d6c5 commit 6ce888b
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,16 @@ abstract class BaseExtractorTest extends Specification {
return result
}

protected BuildResult runAndFail() {
return runAndFail("ForceDependencyResolutionPlugin_resolveAllDependencies")
}

protected BuildResult runAndFail(String... names) {
executer.withTasks(names)
result = getExecuter().runWithFailure()
return result
}

@CompileDynamic
protected void applyDependencyGraphPlugin() {
File pluginJar = TEST_CONFIG.asFile("extractorPlugin.jar.path")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,17 @@ class DependencyExtractorConfigTest extends BaseExtractorTest {
assert job.id == environmentVars.jobId
}

def "fails gracefully if configuration values not set"() {
when:
def envVars = environmentVars.asEnvironmentMap()
envVars.remove("GITHUB_DEPENDENCY_GRAPH_JOB_CORRELATOR")
executer.withEnvironmentVars(envVars)
def result = executer.runWithFailure()

then:
result.output.contains("> The configuration parameter 'GITHUB_DEPENDENCY_GRAPH_JOB_CORRELATOR' must be set")
}

@IgnoreIf({
// There is an issue where BuildService is closed too early in Gradle 8.0,
// resulting in empty dependency graph.
Expand Down Expand Up @@ -88,14 +99,38 @@ class DependencyExtractorConfigTest extends BaseExtractorTest {
!dependencyGraphFile.exists()
}

def "fails gracefully if configuration values not set"() {
def "does not generate dependency-graph on configuration failure"() {
given:
buildFile << """
throw new RuntimeException("Failure during configuration")
"""

when:
def envVars = environmentVars.asEnvironmentMap()
envVars.remove("GITHUB_DEPENDENCY_GRAPH_JOB_CORRELATOR")
executer.withEnvironmentVars(envVars)
def result = executer.runWithFailure()
def buildResult = runAndFail()

then:
result.output.contains("> The configuration parameter 'GITHUB_DEPENDENCY_GRAPH_JOB_CORRELATOR' must be set")
buildResult.output.contains("Gradle Build did not complete successfully: Dependency Graph file will not be generated.")
!dependencyGraphFile.exists()
}

def "does not generate dependency-graph on task failure"() {
given:
buildFile << """
tasks.register("taskThatSucceeds") {
doLast {}
}
tasks.register("taskThatFails") {
doLast {
throw new RuntimeException("Failure in task")
}
}
"""

when:
def buildResult = runAndFail("taskThatSucceeds", "taskThatFails")

then:
buildResult.output.contains("Gradle Build did not complete successfully: Dependency Graph file will not be generated.")
!dependencyGraphFile.exists()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import org.gradle.api.logging.Logging
import org.gradle.dependencygraph.DependencyGraphRenderer
import org.gradle.dependencygraph.model.*
import org.gradle.dependencygraph.model.DependencyScope.*
import org.gradle.dependencygraph.util.*
import org.gradle.dependencygraph.util.PluginParameters
import org.gradle.execution.RunRootBuildWorkBuildOperationType
import org.gradle.initialization.EvaluateSettingsBuildOperationType
import org.gradle.initialization.LoadProjectsBuildOperationType
import org.gradle.internal.exceptions.DefaultMultiCauseException
Expand Down Expand Up @@ -38,6 +39,8 @@ abstract class DependencyExtractor :
private val pluginParameters = PluginParameters()

private var settingsEvaluated = false
private var buildWorkCompleted = false
private var buildWorkFailure = false

private val resolvedConfigurations = Collections.synchronizedList(mutableListOf<ResolvedConfiguration>())

Expand All @@ -60,6 +63,7 @@ abstract class DependencyExtractor :
abstract fun getRendererClassName(): String

override fun started(buildOperation: BuildOperationDescriptor, startEvent: OperationStartEvent) {
println("Got started operation: $buildOperation --- $startEvent")
// This method will never be called when registered in a `BuildServiceRegistry` (i.e. Gradle 6.1 & higher)
// No-op
}
Expand All @@ -70,6 +74,7 @@ abstract class DependencyExtractor :
}

override fun finished(buildOperation: BuildOperationDescriptor, finishEvent: OperationFinishEvent) {

handleBuildOperationType<
ResolveConfigurationDependenciesBuildOperationType.Details,
ResolveConfigurationDependenciesBuildOperationType.Result
Expand All @@ -82,6 +87,10 @@ abstract class DependencyExtractor :
handleBuildOperationType<
EvaluateSettingsBuildOperationType.Details,
EvaluateSettingsBuildOperationType.Result>(buildOperation, finishEvent) { details, _ -> extractSettings(details) }

if (buildOperation.details is RunRootBuildWorkBuildOperationType.Details) {
handleRunWorkCompleted(finishEvent)
}
}

private inline fun <reified D, reified R> handleBuildOperationType(
Expand Down Expand Up @@ -341,6 +350,13 @@ abstract class DependencyExtractor :
)
}

private fun handleRunWorkCompleted(finishEvent: OperationFinishEvent) {
buildWorkCompleted = true
if (finishEvent.failure != null) {
buildWorkFailure = true
}
}

override fun close() {
if (thrownExceptions.isNotEmpty()) {
throw DefaultMultiCauseException(
Expand All @@ -358,6 +374,13 @@ abstract class DependencyExtractor :
)
return
}
// We use the absence of Settings Evaluated to determine if the build was loaded from the configuration-cache
if (!buildWorkCompleted || buildWorkFailure) {
LOGGER.lifecycle(
"Gradle Build did not complete successfully: Dependency Graph file will not be generated."
)
return
}
try {
writeDependencyGraph()
} catch (e: RuntimeException) {
Expand Down

0 comments on commit 6ce888b

Please sign in to comment.