Skip to content

Commit d5ec939

Browse files
committed
Refactor pom validator
1 parent 658fc46 commit d5ec939

File tree

2 files changed

+50
-36
lines changed

2 files changed

+50
-36
lines changed

buildSrc/src/main/java/com/google/firebase/gradle/plugins/BaseFirebaseLibraryPlugin.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ abstract class BaseFirebaseLibraryPlugin : Plugin<Project> {
7878

7979
protected fun getIsPomValidTask(project: Project, firebaseLibrary: FirebaseLibraryExtension) {
8080
project.tasks.register<PomValidator>("isPomDependencyValid") {
81-
pomFilePath.value(project.file("build/publications/mavenAar/pom-default.xml"))
81+
pomFile.value(project.file("build/publications/mavenAar/pom-default.xml"))
8282
groupId.value(firebaseLibrary.groupId.get())
8383
artifactId.value(firebaseLibrary.artifactId.get())
8484
dependsOn("generatePomFileForMavenAarPublication")

buildSrc/src/main/java/com/google/firebase/gradle/plugins/PomValidator.kt

Lines changed: 49 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -16,63 +16,77 @@ package com.google.firebase.gradle.plugins
1616

1717
import java.io.File
1818
import java.net.URL
19-
import javax.xml.parsers.DocumentBuilder
2019
import javax.xml.parsers.DocumentBuilderFactory
2120
import org.gradle.api.DefaultTask
2221
import org.gradle.api.GradleException
2322
import org.gradle.api.provider.Property
2423
import org.gradle.api.tasks.Input
2524
import org.gradle.api.tasks.InputFile
2625
import org.gradle.api.tasks.TaskAction
27-
import org.w3c.dom.Document
2826
import org.w3c.dom.Element
29-
import org.w3c.dom.Node
30-
import org.w3c.dom.NodeList
3127

28+
/**
29+
* Ensures that pom dependencies are not accidently downgraded.
30+
*
31+
* Compares the latest pom at gmaven for the given artifact with the one generate for the current
32+
* release.
33+
*
34+
* @throws GradleException if a dependency is found with a degraded version
35+
*
36+
* @property pomFile The pom file for the current release
37+
* @property artifactId The artifactId for the pom parent
38+
* @property groupId The groupId for the pom parent
39+
*/
3240
abstract class PomValidator : DefaultTask() {
33-
@get:InputFile abstract val pomFilePath: Property<File>
41+
@get:InputFile abstract val pomFile: Property<File>
3442
@get:Input abstract val artifactId: Property<String>
3543
@get:Input abstract val groupId: Property<String>
3644

3745
@TaskAction
3846
fun run() {
39-
val gMavenHelper = GmavenHelper(groupId.get(), artifactId.get())
40-
val latestReleasedVersion = gMavenHelper.getLatestReleasedVersion()
41-
val releasedVersionPomUrl = gMavenHelper.getPomFileForVersion(latestReleasedVersion)
42-
var output: String = diffWithPomFileUrl(releasedVersionPomUrl).trim()
43-
if (output.isNotEmpty()) {
44-
throw GradleException("${output}\nPlease fix the above errors")
47+
var diff = diffWithPomFromURL(getLatestReleasePomUrl())
48+
49+
if (diff.isNotEmpty()) {
50+
throw GradleException("Dependency version errors found:\n${diff}")
4551
}
4652
}
4753

48-
fun getMapFromXml(pomNodeList: NodeList): Map<String, String> {
49-
val pomMap = mutableMapOf<String, String>()
50-
for (i in 0..pomNodeList.length - 1) {
51-
val node: Node = pomNodeList.item(i)
52-
if (node.getNodeType() == Node.ELEMENT_NODE) {
53-
val element = node as Element
54-
val artifact = element.getElementsByTagName("artifactId").item(0).getTextContent()
55-
val version = element.getElementsByTagName("version").item(0).getTextContent()
56-
pomMap[artifact] = version
57-
}
54+
private fun getLatestReleasePomUrl() =
55+
with(GmavenHelper(groupId.get(), artifactId.get())) {
56+
getPomFileForVersion(getLatestReleasedVersion())
5857
}
59-
return pomMap
60-
}
6158

62-
fun diffWithPomFileUrl(pomUrl: String): String {
63-
val factory: DocumentBuilderFactory = DocumentBuilderFactory.newInstance()
64-
val oldPomBuilder: DocumentBuilder = factory.newDocumentBuilder()
65-
val oldPomDoc: Document = oldPomBuilder.parse(URL(pomUrl).openStream())
66-
val currentPomBuilder: DocumentBuilder = factory.newDocumentBuilder()
67-
val currentPomDoc: Document = currentPomBuilder.parse(pomFilePath.get())
68-
val oldPomMap = getMapFromXml(oldPomDoc.getElementsByTagName("dependency"))
69-
val currentPomMap = getMapFromXml(currentPomDoc.getElementsByTagName("dependency"))
59+
private fun getMapOfDependencies(doc: Element) =
60+
doc
61+
.findElementsByTag("dependency")
62+
.associate { it.textByTag("artifactId") to it.textByTag("version") }
63+
.filter { it.key != "javax.inject" } // javax.inject doesn't respect SemVer and doesn't update
64+
.mapValues {
65+
ModuleVersion.fromStringOrNull(it.value)
66+
?: throw RuntimeException("Invalid module version found for '${it.key}': ${it.value}")
67+
}
68+
69+
data class DependencyDiff(
70+
val artifactId: String,
71+
val oldVersion: ModuleVersion,
72+
val currentVersion: ModuleVersion
73+
)
74+
75+
fun diffWithPomFromURL(url: String): String {
76+
val documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder()
77+
78+
val oldPom = documentBuilder.parse(URL(url).openStream())
79+
val currentPom = documentBuilder.parse(pomFile.get())
80+
81+
val oldDependencies = getMapOfDependencies(oldPom.documentElement)
82+
val currentDependencies = getMapOfDependencies(currentPom.documentElement)
7083

71-
return currentPomMap
72-
.filter {
73-
(oldPomMap.get(it.key) != null) && (oldPomMap.get(it.key)!!.trim()) > it.value.trim()
84+
return currentDependencies
85+
.map { DependencyDiff(it.key, oldDependencies.getOrDefault(it.key, it.value), it.value) }
86+
.filter { it.oldVersion > it.currentVersion }
87+
.map {
88+
"Dependency on ${it.artifactId} has been degraded from ${it.oldVersion} to ${it.currentVersion}"
7489
}
75-
.map { "Artifacts ${it.key} has been degraded to ${it.value} from ${oldPomMap.get(it.key)}" }
7690
.joinToString("\n")
7791
}
7892
}

0 commit comments

Comments
 (0)