diff --git a/src/main/groovy/nebula/plugin/publishing/verification/PublishVerificationPlugin.groovy b/src/main/groovy/nebula/plugin/publishing/verification/PublishVerificationPlugin.groovy index 8516bd7..075511c 100644 --- a/src/main/groovy/nebula/plugin/publishing/verification/PublishVerificationPlugin.groovy +++ b/src/main/groovy/nebula/plugin/publishing/verification/PublishVerificationPlugin.groovy @@ -10,6 +10,8 @@ import org.gradle.api.artifacts.CacheableRule import org.gradle.api.artifacts.ComponentMetadataContext import org.gradle.api.artifacts.ComponentMetadataDetails import org.gradle.api.artifacts.ComponentMetadataRule +import org.gradle.api.artifacts.Configuration +import org.gradle.api.artifacts.Dependency import org.gradle.api.attributes.Attribute import org.gradle.api.plugins.JavaBasePlugin import org.gradle.api.publish.ivy.tasks.PublishToIvyRepository @@ -49,12 +51,20 @@ class PublishVerificationPlugin implements Plugin { if (!sourceSet) return TaskProvider verificationTask = project.tasks.register("verifyPublication", VerifyPublicationTask) TaskProvider reportTask = getOrCreateReportTask(project, verificationTask) + VerificationViolationsCollectorHolderExtension verificationViolationsCollectorHolderExtension = project.rootProject.extensions.findByType(VerificationViolationsCollectorHolderExtension) verificationTask.configure(new Action() { @Override void execute(VerifyPublicationTask verifyPublicationTask) { - verifyPublicationTask.ignore = extension.ignore - verifyPublicationTask.ignoreGroups = extension.ignoreGroups - verifyPublicationTask.sourceSet = sourceSet + verifyPublicationTask.projectName.set(project.name) + verifyPublicationTask.targetStatus.set(project.status.toString()) + verifyPublicationTask.runtimeClasspath.set(project.configurations.named(sourceSet.getRuntimeClasspathConfigurationName())) + verifyPublicationTask.ignore.set(extension.ignore) + verifyPublicationTask.ignoreGroups.set(extension.ignoreGroups) + verifyPublicationTask.verificationViolationsCollectorHolderExtension.set(verificationViolationsCollectorHolderExtension) + verifyPublicationTask.definedDependencies.set(project.configurations.collect { Configuration configuration -> + configuration.dependencies + }.flatten() as List) + } }) @@ -95,9 +105,12 @@ class PublishVerificationPlugin implements Plugin { } else { verificationReportTask = project.rootProject.tasks.named('verifyPublicationReport', VerificationReportTask) } + VerificationViolationsCollectorHolderExtension verificationViolationsCollectorHolderExtension = project.rootProject.extensions.findByType(VerificationViolationsCollectorHolderExtension) verificationReportTask.configure(new Action() { @Override void execute(VerificationReportTask reportTask) { + reportTask.targetStatus.set(project.status.toString()) + reportTask.verificationViolationsCollectorHolderExtension.set(verificationViolationsCollectorHolderExtension) reportTask.dependsOn(verificationTask) } }) @@ -105,27 +118,15 @@ class PublishVerificationPlugin implements Plugin { } private void configureHooks(Project project, TaskProvider reportTask) { - project.tasks.withType(PublishToIvyRepository) { Task task -> + project.tasks.withType(PublishToIvyRepository).configureEach { Task task -> task.dependsOn(reportTask) } - project.tasks.withType(PublishToMavenRepository) { Task task -> + project.tasks.withType(PublishToMavenRepository).configureEach { Task task -> task.dependsOn(reportTask) } - project.plugins.withId('com.jfrog.artifactory') { - def artifactoryPublishTask = project.tasks.findByName('artifactoryPublish') - if (artifactoryPublishTask) { - artifactoryPublishTask.dependsOn(reportTask) - } - //newer version of artifactory plugin introduced this task to do actual publishing, so we have to - //hook even for this one. - def artifactoryDeployTask = project.tasks.findByName("artifactoryDeploy") - if (artifactoryDeployTask) { - artifactoryDeployTask.dependsOn(reportTask) - } - } } static class VerificationViolationsCollectorHolderExtension { - Map collector = new ConcurrentHashMap<>() + Map collector = new ConcurrentHashMap<>() } } diff --git a/src/main/groovy/nebula/plugin/publishing/verification/VerificationReportTask.groovy b/src/main/groovy/nebula/plugin/publishing/verification/VerificationReportTask.groovy index 3a8fca7..b69fdba 100644 --- a/src/main/groovy/nebula/plugin/publishing/verification/VerificationReportTask.groovy +++ b/src/main/groovy/nebula/plugin/publishing/verification/VerificationReportTask.groovy @@ -2,36 +2,38 @@ package nebula.plugin.publishing.verification import org.gradle.api.BuildCancelledException import org.gradle.api.DefaultTask -import org.gradle.api.Project +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Internal import org.gradle.api.tasks.TaskAction import org.gradle.work.DisableCachingByDefault @DisableCachingByDefault -class VerificationReportTask extends DefaultTask { +abstract class VerificationReportTask extends DefaultTask { protected VerificationReportGenerator verificationReportGenerator = new VerificationReportGenerator() + @Internal + abstract Property getVerificationViolationsCollectorHolderExtension() + + @Input + abstract Property getTargetStatus() + @TaskAction void reportViolatingDependencies() { if (project.rootProject == project) { - reportErrors(getViolations()) + reportErrors(verificationViolationsCollectorHolderExtension.get().collector) } } - private Map getViolations() { - PublishVerificationPlugin.VerificationViolationsCollectorHolderExtension extension = project.rootProject.extensions - .findByType(PublishVerificationPlugin.VerificationViolationsCollectorHolderExtension) - extension.collector - } - - void reportErrors(Map violationsPerProject) { + void reportErrors(Map violationsPerProject) { if (violationsPerProject.any { it.value.hasViolations() } ) { throw new BuildCancelledException(generateReportMessage(violationsPerProject)) } } - private String generateReportMessage(Map violationsPerProject){ - verificationReportGenerator.generateReport(violationsPerProject.collectEntries { [it.key.toString(), it.value] } as Map , project.status.toString()) + private String generateReportMessage(Map violationsPerProject){ + verificationReportGenerator.generateReport(violationsPerProject.collectEntries { [it.key, it.value] } as Map , targetStatus.get()) } } diff --git a/src/main/groovy/nebula/plugin/publishing/verification/VerifyPublicationTask.groovy b/src/main/groovy/nebula/plugin/publishing/verification/VerifyPublicationTask.groovy index bd7481d..1313cc6 100644 --- a/src/main/groovy/nebula/plugin/publishing/verification/VerifyPublicationTask.groovy +++ b/src/main/groovy/nebula/plugin/publishing/verification/VerifyPublicationTask.groovy @@ -1,42 +1,57 @@ package nebula.plugin.publishing.verification import org.gradle.api.DefaultTask -import org.gradle.api.Project import org.gradle.api.artifacts.* import org.gradle.api.artifacts.component.ProjectComponentIdentifier import org.gradle.api.artifacts.result.DependencyResult import org.gradle.api.artifacts.result.ResolvedDependencyResult import org.gradle.api.artifacts.result.UnresolvedDependencyResult +import org.gradle.api.provider.ListProperty +import org.gradle.api.provider.Property +import org.gradle.api.provider.SetProperty +import org.gradle.api.tasks.Classpath import org.gradle.api.tasks.Input -import org.gradle.api.tasks.SourceSet +import org.gradle.api.tasks.InputFiles +import org.gradle.api.tasks.Internal import org.gradle.api.tasks.TaskAction import org.gradle.work.DisableCachingByDefault @DisableCachingByDefault -class VerifyPublicationTask extends DefaultTask { +abstract class VerifyPublicationTask extends DefaultTask { @Input - Set ignore + abstract SetProperty getIgnore() + + @Input + abstract SetProperty getIgnoreGroups() + + @Input + abstract Property getTargetStatus() + + @InputFiles + @Classpath + abstract Property getRuntimeClasspath() + @Input - Set ignoreGroups + abstract Property getProjectName() + @Input - SourceSet sourceSet + abstract ListProperty getDefinedDependencies() + + @Internal + abstract Property getVerificationViolationsCollectorHolderExtension() @TaskAction void verifyDependencies() { - if (sourceSet == null) throw new IllegalStateException('sourceSet must be configured') - Configuration runtimeClasspath = project.configurations.getByName(sourceSet.getRuntimeClasspathConfigurationName()) - Set firstLevel = getNonProjectDependencies(runtimeClasspath) - List violations = new StatusVerification(ignore, ignoreGroups, project.status).verify(firstLevel) + Set firstLevel = getNonProjectDependencies(runtimeClasspath.get()) + List violations = new StatusVerification(ignore.get(), ignoreGroups.get(), targetStatus.get()).verify(firstLevel) - List definedDependencies = getDefinedDependencies() - List versionViolations = new VersionSelectorVerification(ignore, ignoreGroups).verify(definedDependencies) + List versionViolations = new VersionSelectorVerification(ignore.get(), ignoreGroups.get()).verify(definedDependencies.get()) - getViolations().put(project, - new ViolationsContainer(statusViolations: violations, versionSelectorViolations: versionViolations)) + verificationViolationsCollectorHolderExtension.get().collector.put(projectName.get(), new ViolationsContainer(statusViolations: violations, versionSelectorViolations: versionViolations)) } - private Set getNonProjectDependencies(Configuration runtimeClasspath) { + private static Set getNonProjectDependencies(Configuration runtimeClasspath) { Set firstLevelDependencies = runtimeClasspath.incoming.resolutionResult.root.getDependencies() .findAll { !it.constraint } List unresolvedDependencies = firstLevelDependencies.findAll { it instanceof UnresolvedDependencyResult } as List @@ -48,16 +63,4 @@ class VerifyPublicationTask extends DefaultTask { result instanceof ResolvedDependencyResult && ! (result.selected.id instanceof ProjectComponentIdentifier) } as Set } - - private Map getViolations() { - PublishVerificationPlugin.VerificationViolationsCollectorHolderExtension extension = project.rootProject.extensions - .findByType(PublishVerificationPlugin.VerificationViolationsCollectorHolderExtension) - extension.collector - } - - private List getDefinedDependencies() { - project.configurations.collect { Configuration configuration -> - configuration.dependencies - }.flatten() as List - } } diff --git a/src/test/groovy/nebula/plugin/publishing/verification/PublishVerificationPluginIntegrationSpec.groovy b/src/test/groovy/nebula/plugin/publishing/verification/PublishVerificationPluginIntegrationSpec.groovy index 3fc169e..a05670a 100644 --- a/src/test/groovy/nebula/plugin/publishing/verification/PublishVerificationPluginIntegrationSpec.groovy +++ b/src/test/groovy/nebula/plugin/publishing/verification/PublishVerificationPluginIntegrationSpec.groovy @@ -329,39 +329,6 @@ class PublishVerificationPluginIntegrationSpec extends IntegrationSpec { assertStatusFailureMessage(result, expectedFailureDependency, projectStatus) } - def 'should work with artifactoryPublish'() { - given: - def expectedFailureDependency = 'foo:bar:1.0-SNAPSHOT' - def projectStatus = 'release' - DependencyGraphBuilder builder = new DependencyGraphBuilder() - builder.addModule(expectedFailureDependency) - def dependencies = "implementation '$expectedFailureDependency'" - - buildFile << createBuildFileFromTemplate(projectStatus, dependencies, builder) - - when: - def result = runTasksWithFailure('build', 'artifactoryPublish') - - then: - assertStatusFailureMessage(result, expectedFailureDependency, projectStatus) - } - - def 'should work with artifactoryDeploy'() { - given: - def expectedFailureDependency = 'foo:bar:1.0-SNAPSHOT' - def projectStatus = 'release' - DependencyGraphBuilder builder = new DependencyGraphBuilder() - builder.addModule(expectedFailureDependency) - def dependencies = "implementation '$expectedFailureDependency'" - - buildFile << createBuildFileFromTemplate(projectStatus, dependencies, builder) - - when: - def result = runTasksWithFailure('build', 'artifactoryDeploy') - - then: - assertStatusFailureMessage(result, expectedFailureDependency, projectStatus) - } def 'should work with forced dependency'() { given: diff --git a/src/test/groovy/nebula/plugin/publishing/verification/VerificationReportTaskSpec.groovy b/src/test/groovy/nebula/plugin/publishing/verification/VerificationReportTaskSpec.groovy index 20d307e..03b887b 100644 --- a/src/test/groovy/nebula/plugin/publishing/verification/VerificationReportTaskSpec.groovy +++ b/src/test/groovy/nebula/plugin/publishing/verification/VerificationReportTaskSpec.groovy @@ -12,10 +12,12 @@ class VerificationReportTaskSpec extends Specification { def 'build is unaffected when there is no violation'() { given: Project project = ProjectBuilder.builder().build() - project.extensions.create('collectorExtension', PublishVerificationPlugin.VerificationViolationsCollectorHolderExtension) + PublishVerificationPlugin.VerificationViolationsCollectorHolderExtension extension = project.extensions.create('collectorExtension', PublishVerificationPlugin.VerificationViolationsCollectorHolderExtension) VerificationReportTask task = project.tasks.create('report', VerificationReportTask) def generator = Mock(VerificationReportGenerator) task.verificationReportGenerator = generator + task.targetStatus.set(project.status.toString()) + task.verificationViolationsCollectorHolderExtension.set(extension) when: task.reportViolatingDependencies() @@ -37,6 +39,8 @@ class VerificationReportTaskSpec extends Specification { VerificationReportTask task = project.tasks.create('report', VerificationReportTask) def generator = Mock(VerificationReportGenerator) task.verificationReportGenerator = generator + task.targetStatus.set(project.status.toString()) + task.verificationViolationsCollectorHolderExtension.set(extension) when: task.reportViolatingDependencies() diff --git a/src/test/groovy/nebula/plugin/publishing/verification/VerifyPublicationTaskSpec.groovy b/src/test/groovy/nebula/plugin/publishing/verification/VerifyPublicationTaskSpec.groovy index 1f8e43b..4dbe4f9 100644 --- a/src/test/groovy/nebula/plugin/publishing/verification/VerifyPublicationTaskSpec.groovy +++ b/src/test/groovy/nebula/plugin/publishing/verification/VerifyPublicationTaskSpec.groovy @@ -6,6 +6,8 @@ import nebula.test.dependencies.GradleDependencyGenerator import nebula.test.dependencies.ModuleBuilder import org.gradle.api.Project import org.gradle.api.Task +import org.gradle.api.artifacts.Configuration +import org.gradle.api.artifacts.Dependency import org.gradle.api.internal.artifacts.DefaultModuleIdentifier import org.gradle.api.plugins.JavaPlugin import org.gradle.testfixtures.ProjectBuilder @@ -29,7 +31,7 @@ class VerifyPublicationTaskSpec extends Specification { noExceptionThrown() def holderExtension = project.extensions.findByType(PublishVerificationPlugin.VerificationViolationsCollectorHolderExtension) holderExtension.collector.size() == 1 - def violations = holderExtension.collector[project] + def violations = holderExtension.collector[project.name] violations.statusViolations.size() == 0 where: @@ -56,7 +58,7 @@ class VerifyPublicationTaskSpec extends Specification { noExceptionThrown() def holderExtension = project.extensions.findByType(PublishVerificationPlugin.VerificationViolationsCollectorHolderExtension) holderExtension.collector.size() == 1 - def violations = holderExtension.collector[project] + def violations = holderExtension.collector[project.name] violations.statusViolations.size() == 1 def violation = violations.statusViolations.first() violation.id.group == 'foo' @@ -88,7 +90,7 @@ class VerifyPublicationTaskSpec extends Specification { noExceptionThrown() def holderExtension = project.extensions.findByType(PublishVerificationPlugin.VerificationViolationsCollectorHolderExtension) holderExtension.collector.size() == 1 - def violations = holderExtension.collector[project] + def violations = holderExtension.collector[project.name] violations.statusViolations.size() == 0 violations.versionSelectorViolations.size() == 0 } @@ -111,36 +113,13 @@ class VerifyPublicationTaskSpec extends Specification { noExceptionThrown() def holderExtension = project.extensions.findByType(PublishVerificationPlugin.VerificationViolationsCollectorHolderExtension) holderExtension.collector.size() == 1 - def violations = holderExtension.collector[project] + def violations = holderExtension.collector[project.name] violations.statusViolations.size() == 0 violations.versionSelectorViolations.size() == 0 } - def 'test error collection when incorrect version is used'() { - given: - Project project = ProjectBuilder.builder().build() - def task = setupProjectAndTask(project, 'release', 'release') - project.dependencies { - runtimeOnly 'foo:bar:1.0+' - } - - when: - task.verifyDependencies() - - then: - noExceptionThrown() - def holderExtension = project.extensions.findByType(PublishVerificationPlugin.VerificationViolationsCollectorHolderExtension) - holderExtension.collector.size() == 1 - def violations = holderExtension.collector[project] - violations.versionSelectorViolations.size() == 1 - def violation = violations.versionSelectorViolations.first() - violation.dependency.group == 'foo' - violation.dependency.name == 'bar' - } - - Task setupProjectAndTask(Project project, String libraryStatus, String projectStatus) { - project.extensions.create('collectorExtension', PublishVerificationPlugin.VerificationViolationsCollectorHolderExtension) + def extension = project.extensions.create('collectorExtension', PublishVerificationPlugin.VerificationViolationsCollectorHolderExtension) project.plugins.apply(JavaPlugin) project.status = projectStatus @@ -149,9 +128,15 @@ class VerifyPublicationTaskSpec extends Specification { def task = project.task('verify', type: VerifyPublicationTask) task.configure { - ignore = Collections.emptySet() - ignoreGroups = Collections.emptySet() - sourceSet = project.sourceSets.main + ignore.set(Collections.emptySet()) + ignoreGroups.set(Collections.emptySet()) + runtimeClasspath.set(project.configurations.getByName(project.sourceSets.main.getRuntimeClasspathConfigurationName())) + definedDependencies.set(project.configurations.collect { Configuration configuration -> + configuration.dependencies + }.flatten() as List) + projectName.set(project.name) + targetStatus.set(project.status.toString()) + verificationViolationsCollectorHolderExtension.set(extension) } }