diff --git a/buildSrc/src/main/groovy/com/google/firebase/gradle/plugins/publish/Publisher.groovy b/buildSrc/src/main/groovy/com/google/firebase/gradle/plugins/publish/Publisher.groovy index 7d05bd8c686..c2b6861a557 100644 --- a/buildSrc/src/main/groovy/com/google/firebase/gradle/plugins/publish/Publisher.groovy +++ b/buildSrc/src/main/groovy/com/google/firebase/gradle/plugins/publish/Publisher.groovy @@ -16,6 +16,9 @@ package com.google.firebase.gradle.plugins.publish import org.gradle.api.GradleException import org.gradle.api.Project +import org.gradle.api.artifacts.Configuration +import org.gradle.api.artifacts.Dependency +import org.gradle.api.artifacts.ProjectDependency import org.gradle.api.publish.maven.MavenPublication /** Handles publication versioning and pom validation upon release. */ @@ -26,7 +29,7 @@ class Publisher { SNAPSHOT } private final Mode mode; - private final Set projectsToPublish; + private final Set projectsToPublish Publisher(Mode mode, Set projectsToPublish) { this.mode = mode @@ -37,6 +40,7 @@ class Publisher { publication.pom.withXml { def rootNode = asNode() validatePomXml(project, rootNode) + processDependencies(project, rootNode) } } @@ -51,7 +55,7 @@ class Publisher { return UNRELEASED_VERSION } - private void validatePomXml(Project p, Node pom) { + private static void validatePomXml(Project p, Node pom) { def unreleased = pom.dependencies.dependency.findAll { it.version.text() == UNRELEASED_VERSION } .collect { "${it.groupId.text()}:${it.artifactId.text()}"} if(unreleased) { @@ -63,4 +67,53 @@ class Publisher { return "${baseVersion}${mode == Mode.SNAPSHOT ? '-SNAPSHOT' : ''}" } + private static void processDependencies(Project project, Node pom) { + def deps = getDependencyTypes(project) + + pom.dependencies.dependency.each { + // remove multidex as it is supposed to be added by final applications and is needed for + // some libraries only for instrumentation tests to build. + if (it.groupId.text() in ['com.android.support', 'androidx'] && it.artifactId.text() == 'multidex') { + it.parent().remove(it) + } + it.appendNode('type', [:], deps["${it.groupId.text()}:${it.artifactId.text()}"]) + + // change scope to compile to preserve existing behavior + it.scope.replaceNode { + createNode('scope', 'compile') + } + } + } + + private static Map getDependencyTypes(Project project) { + def dummyDependencyConfiguration = project.configurations.create('publisherDummyConfig') + def nonProjectDependencies = project.configurations.releaseRuntimeClasspath.allDependencies.findAll { + !(it instanceof ProjectDependency) + } + dummyDependencyConfiguration.dependencies.addAll(nonProjectDependencies) + try { + return project.configurations.releaseRuntimeClasspath.getAllDependencies().collectEntries { + [("$it.group:$it.name" as String): getType(dummyDependencyConfiguration, it)] + } + } finally { + project.configurations.remove(dummyDependencyConfiguration) + } + + } + + private static String getType(Configuration config, Dependency d) { + if (d instanceof ProjectDependency) { + // we currently only support aar libraries to be produced in this repository + return 'aar' + } + String path = config.find { + it.absolutePath.matches(".*\\Q$d.group/$d.name/$d.version/\\E[a-zA-Z0-9]+/\\Q$d.name-$d.version.\\E[aj]ar") + }?.absolutePath + if (path && path.endsWith (".aar")) { + return "aar" + } else { + return "jar" + } + } + } diff --git a/buildSrc/src/test/groovy/com/google/firebase/gradle/plugins/publish/PublishingPluginSpec.groovy b/buildSrc/src/test/groovy/com/google/firebase/gradle/plugins/publish/PublishingPluginSpec.groovy index 1fff2ee2199..318b63accb1 100644 --- a/buildSrc/src/test/groovy/com/google/firebase/gradle/plugins/publish/PublishingPluginSpec.groovy +++ b/buildSrc/src/test/groovy/com/google/firebase/gradle/plugins/publish/PublishingPluginSpec.groovy @@ -44,6 +44,7 @@ class PublishingPluginSpec extends Specification { } dependencies { <%dependencies.each { println "implementation project(':$it.name')" } %> + <%externalDependencies.each { println "implementation '$it'" } %> } ''' String name @@ -51,6 +52,7 @@ class PublishingPluginSpec extends Specification { String version = 'undefined' String latestReleasedVersion = '' Set projectDependencies = [] + Set externalDependencies = [] Project releaseWith = null String customizePom = null @@ -60,6 +62,7 @@ class PublishingPluginSpec extends Specification { group: group, version: version, dependencies: projectDependencies, + externalDependencies: externalDependencies, releaseWith: releaseWith, latestReleasedVersion: latestReleasedVersion, customizePom: customizePom, @@ -253,6 +256,42 @@ licenses { dependency.version == project1.version } + def "Publish project should correctly set dependency types"() { + Project project1 = new Project(name: 'childProject1', version: '1.0', latestReleasedVersion: '0.8') + Project project2 = new Project( + name: 'childProject2', + version: '0.9', + projectDependencies: [project1], + externalDependencies: [ + 'com.google.dagger:dagger:2.22', + 'com.google.dagger:dagger-android-support:2.22', + 'com.android.support:multidex:1.0.3' + ]) + + when: "publishFirebase invoked" + subprojectsDefined(project1, project2) + def result = publish(Mode.RELEASE, project2) + then: 'poms exist' + def pom1 = project1.getPublishedPom("$testProjectDir.root/build/m2repository") + def pom2 = project2.getPublishedPom("$testProjectDir.root/build/m2repository") + assert !pom1.isPresent() + assert pom2.isPresent() + + and: 'versions and dependency types are valid' + + def xml2 = new XmlSlurper().parseText(pom2.get().text) + xml2.version == project2.version + def dependencies = xml2.dependencies.dependency.collect { + "${it.groupId.text()}:${it.artifactId.text()}:${it.version.text()}:${it.type.text()}:${it.scope.text()}" + } as Set + dependencies == [ + "$project1.group:$project1.name:$project1.latestReleasedVersion:aar:compile", + 'com.google.dagger:dagger:2.22:jar:compile', + 'com.google.dagger:dagger-android-support:2.22:aar:compile' + ] as Set + + } + private BuildResult build(String... args) { GradleRunner.create() .withProjectDir(testProjectDir.root)