diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index c655e0a..beda58d 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -33,7 +33,7 @@ jobs: matrix: # Test earliest and latest supported version of 5.x, 6.x and 7.x, as well as all patched minor versions of 8.x # Latest 8.x is tested in 'quick-check' job using the wrapper - gradle-version: [ "5.2.1", "5.6.4", "6.0.1", "6.9.4", "7.1.1", "7.6.3", "8.0.2", "8.1.1", "8.2.1", "8.3", "8.4", "8.5"] + gradle-version: [ "5.2.1", "5.6.4", "6.0.1", "6.9.4", "7.1.1", "7.6.4", "8.0.2", "8.1.1", "8.2.1", "8.3", "8.4", "8.5", "8.6"] runs-on: ubuntu-latest env: GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }} diff --git a/plugin-test/src/test/groovy/org/gradle/github/dependencygraph/DependencyLockingDependencyExtractorTest.groovy b/plugin-test/src/test/groovy/org/gradle/github/dependencygraph/DependencyLockingDependencyExtractorTest.groovy new file mode 100644 index 0000000..ba04b1c --- /dev/null +++ b/plugin-test/src/test/groovy/org/gradle/github/dependencygraph/DependencyLockingDependencyExtractorTest.groovy @@ -0,0 +1,99 @@ +package org.gradle.github.dependencygraph + +import org.gradle.test.fixtures.PluginPublisher +import org.gradle.test.fixtures.maven.MavenModule +import org.gradle.util.GradleVersion +import spock.lang.IgnoreIf + +class DependencyLockingDependencyExtractorTest extends BaseExtractorTest { + private MavenModule foo + private MavenModule bar + private MavenModule baz + private File settingsFile + private File buildFile + + def setup() { + establishEnvironmentVariables() + + foo = mavenRepo.module("org.test", "foo", "1.0").publish() + + settingsFile = file("settings.gradle") << """ + rootProject.name = 'a' + """ + + buildFile = file("build.gradle") << """ + apply plugin: 'java' + + repositories { + maven { url "${mavenRepo.uri}" } + } + """ + } + + def "extracts dependencies when dependency locking is enabled"() { + given: + buildFile << """ + dependencies { + implementation "org.test:foo:+" + } + + dependencyLocking { + lockAllConfigurations() + } + """ + + // Write dependency lock file + run("dependencies", "--write-locks") + mavenRepo.module("org.test", "foo", "1.1").publish() + + when: + applyDependencyGraphPlugin() + run() + + then: + def manifest = gitHubManifest() + manifest.sourceFile == "settings.gradle" + + manifest.assertResolved([ + "org.test:foo:1.0": [ + package_url: purlFor(foo) + ] + ]) + } + + @IgnoreIf({ + // `LockMode.STRICT` was introduced in Gradle 6.1 + GradleVersion.version(testGradleVersion) < GradleVersion.version("6.1") + }) + def "extracts dependencies when Strict dependency locking is enabled"() { + given: + buildFile << """ + dependencies { + implementation "org.test:foo:+" + } + + dependencyLocking { + lockAllConfigurations() + lockMode = LockMode.STRICT + } + """ + + // Write dependency lock file + run("dependencies", "--write-locks") + mavenRepo.module("org.test", "foo", "1.1").publish() + + when: + applyDependencyGraphPlugin() + run() + + then: + def manifest = gitHubManifest() + manifest.sourceFile == "settings.gradle" + + manifest.assertResolved([ + "org.test:foo:1.0": [ + package_url: purlFor(foo) + ] + ]) + } +} diff --git a/plugin/src/main/kotlin/org/gradle/forceresolve/AbstractResolveProjectDependenciesTask.kt b/plugin/src/main/kotlin/org/gradle/forceresolve/AbstractResolveProjectDependenciesTask.kt new file mode 100644 index 0000000..224c104 --- /dev/null +++ b/plugin/src/main/kotlin/org/gradle/forceresolve/AbstractResolveProjectDependenciesTask.kt @@ -0,0 +1,43 @@ +package org.gradle.forceresolve + +import org.gradle.api.DefaultTask +import org.gradle.api.artifacts.Configuration +import org.gradle.api.tasks.Internal +import org.gradle.dependencygraph.extractor.ResolvedConfigurationFilter +import org.gradle.work.DisableCachingByDefault +import java.lang.reflect.Method + +@DisableCachingByDefault(because = "Not worth caching") +abstract class AbstractResolveProjectDependenciesTask : DefaultTask() { + private val canSafelyBeResolvedMethod: Method? = getCanSafelyBeResolvedMethod() + + @Internal + var configurationFilter: ResolvedConfigurationFilter? = null + + @Internal + protected fun getReportableConfigurations(): List { + return project.configurations.filter { + canSafelyBeResolved(it) && configurationFilter!!.include(project.path, it.name) + } + } + + /** + * If `DeprecatableConfiguration.canSafelyBeResolve()` is available, use it. + * Else fall back to `Configuration.canBeResolved`. + */ + private fun canSafelyBeResolved(configuration: Configuration): Boolean { + if (canSafelyBeResolvedMethod != null) { + return canSafelyBeResolvedMethod.invoke(configuration) as Boolean + } + return configuration.isCanBeResolved + } + + private fun getCanSafelyBeResolvedMethod(): Method? { + return try { + val dc = Class.forName("org.gradle.internal.deprecation.DeprecatableConfiguration") + dc.getMethod("canSafelyBeResolved") + } catch (e: ReflectiveOperationException) { + null + } + } +} \ No newline at end of file diff --git a/plugin/src/main/kotlin/org/gradle/forceresolve/LegacyResolveProjectDependenciesTask.kt b/plugin/src/main/kotlin/org/gradle/forceresolve/LegacyResolveProjectDependenciesTask.kt index f08bc39..85e1414 100644 --- a/plugin/src/main/kotlin/org/gradle/forceresolve/LegacyResolveProjectDependenciesTask.kt +++ b/plugin/src/main/kotlin/org/gradle/forceresolve/LegacyResolveProjectDependenciesTask.kt @@ -1,22 +1,10 @@ package org.gradle.forceresolve -import org.gradle.api.DefaultTask -import org.gradle.api.artifacts.Configuration -import org.gradle.api.tasks.Internal import org.gradle.api.tasks.TaskAction -import org.gradle.dependencygraph.extractor.ResolvedConfigurationFilter import org.gradle.work.DisableCachingByDefault @DisableCachingByDefault(because = "Not worth caching") -abstract class LegacyResolveProjectDependenciesTask: DefaultTask() { - @Internal - var configurationFilter: ResolvedConfigurationFilter? = null - - private fun getReportableConfigurations(): List { - return project.configurations.filter { - it.isCanBeResolved && configurationFilter!!.include(project.path, it.name) - } - } +abstract class LegacyResolveProjectDependenciesTask: AbstractResolveProjectDependenciesTask() { @TaskAction fun action() { diff --git a/plugin/src/main/kotlin/org/gradle/forceresolve/ResolveProjectDependenciesTask.kt b/plugin/src/main/kotlin/org/gradle/forceresolve/ResolveProjectDependenciesTask.kt index 5c486ed..6d7ef07 100644 --- a/plugin/src/main/kotlin/org/gradle/forceresolve/ResolveProjectDependenciesTask.kt +++ b/plugin/src/main/kotlin/org/gradle/forceresolve/ResolveProjectDependenciesTask.kt @@ -1,34 +1,21 @@ package org.gradle.forceresolve -import org.gradle.api.DefaultTask -import org.gradle.api.artifacts.Configuration import org.gradle.api.artifacts.result.ResolvedComponentResult import org.gradle.api.provider.Provider -import org.gradle.api.tasks.Internal import org.gradle.api.tasks.TaskAction -import org.gradle.dependencygraph.extractor.ResolvedConfigurationFilter import org.gradle.internal.serialization.Cached import org.gradle.work.DisableCachingByDefault @DisableCachingByDefault(because = "Not worth caching") -abstract class ResolveProjectDependenciesTask: DefaultTask() { +abstract class ResolveProjectDependenciesTask: AbstractResolveProjectDependenciesTask() { private val configurationResolvers = Cached.of { createConfigurationResolvers() } - @Internal - var configurationFilter: ResolvedConfigurationFilter? = null - private fun createConfigurationResolvers(): List> { return getReportableConfigurations().map { it.incoming.resolutionResult.rootComponent } } - private fun getReportableConfigurations(): List { - return project.configurations.filter { - it.isCanBeResolved && configurationFilter!!.include(project.path, it.name) - } - } - @TaskAction fun action() { for (configuration in configurationResolvers.get()) {