diff --git a/.github/workflows/version-check.yml b/.github/workflows/version-check.yml new file mode 100644 index 00000000000..2661e06da23 --- /dev/null +++ b/.github/workflows/version-check.yml @@ -0,0 +1,17 @@ +name: Version Check + +on: + workflow_dispatch: + pull_request: + branches: + - 'releases/**' + +jobs: + version-check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3.5.3 + + - name: Build + run: | + ./gradlew gmavenVersionCheck diff --git a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/FirebaseJavaLibraryPlugin.kt b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/FirebaseJavaLibraryPlugin.kt index 879bb02fb0a..56f557cee3b 100644 --- a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/FirebaseJavaLibraryPlugin.kt +++ b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/FirebaseJavaLibraryPlugin.kt @@ -56,11 +56,17 @@ class FirebaseJavaLibraryPlugin : BaseFirebaseLibraryPlugin() { setupStaticAnalysis(project, firebaseLibrary) setupApiInformationAnalysis(project) getIsPomValidTask(project, firebaseLibrary) - getSemverTaskJar(project, firebaseLibrary) + setupVersionCheckTasks(project, firebaseLibrary) configurePublishing(project, firebaseLibrary) } - private fun getSemverTaskJar(project: Project, firebaseLibrary: FirebaseLibraryExtension) { + private fun setupVersionCheckTasks(project: Project, firebaseLibrary: FirebaseLibraryExtension) { + project.tasks.register("gmavenVersionCheck") { + groupId.value(firebaseLibrary.groupId.get()) + artifactId.value(firebaseLibrary.artifactId.get()) + version.value(firebaseLibrary.version) + latestReleasedVersion.value(firebaseLibrary.latestReleasedVersion.orElseGet { "" }) + } project.mkdir("semver") project.tasks.register("copyPreviousArtifacts") { dependsOn("jar") diff --git a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/FirebaseLibraryPlugin.kt b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/FirebaseLibraryPlugin.kt index 4660b859a21..5843d1dd850 100644 --- a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/FirebaseLibraryPlugin.kt +++ b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/FirebaseLibraryPlugin.kt @@ -85,11 +85,17 @@ class FirebaseLibraryPlugin : BaseFirebaseLibraryPlugin() { android.testServer(FirebaseTestServer(project, firebaseLibrary.testLab, android)) setupStaticAnalysis(project, firebaseLibrary) getIsPomValidTask(project, firebaseLibrary) - getSemverTaskAar(project, firebaseLibrary) + setupVersionCheckTasks(project, firebaseLibrary) configurePublishing(project, firebaseLibrary, android) } - private fun getSemverTaskAar(project: Project, firebaseLibrary: FirebaseLibraryExtension) { + private fun setupVersionCheckTasks(project: Project, firebaseLibrary: FirebaseLibraryExtension) { + project.tasks.register("gmavenVersionCheck") { + groupId.value(firebaseLibrary.groupId.get()) + artifactId.value(firebaseLibrary.artifactId.get()) + version.value(firebaseLibrary.version) + latestReleasedVersion.value(firebaseLibrary.latestReleasedVersion.orElseGet { "" }) + } project.mkdir("semver") project.tasks.register("copyPreviousArtifacts") { dependsOn("bundleReleaseAar") diff --git a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/GmavenHelper.kt b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/GmavenHelper.kt index 2f2618cb898..62f32e97b97 100644 --- a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/GmavenHelper.kt +++ b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/GmavenHelper.kt @@ -37,17 +37,35 @@ class GmavenHelper(val groupId: String, val artifactId: String) { return "${GMAVEN_ROOT}/${groupIdAsPath}/${artifactId}/${version}/${fileName}" } + fun hasReleasedVersion(version: String): Boolean { + val doc: Document? = getMavenMetadata() + if (doc != null) { + val versions = doc.getElementsByTagName("version") + for (i in 0..versions.length - 1) { + if (versions.item(i).textContent == version) { + return true + } + } + } + return false + } + fun getLatestReleasedVersion(): String { + val doc: Document? = getMavenMetadata() + return doc?.getElementsByTagName("latest")?.item(0)?.getTextContent() ?: "" + } + + fun getMavenMetadata(): Document? { + val groupIdAsPath = groupId.replace(".", "/") + val mavenMetadataUrl = "${GMAVEN_ROOT}/${groupIdAsPath}/${artifactId}/maven-metadata.xml" + val factory: DocumentBuilderFactory = DocumentBuilderFactory.newInstance() + val builder: DocumentBuilder = factory.newDocumentBuilder() try { - val groupIdAsPath = groupId.replace(".", "/") - val mavenMetadataUrl = "${GMAVEN_ROOT}/${groupIdAsPath}/${artifactId}/maven-metadata.xml" - val factory: DocumentBuilderFactory = DocumentBuilderFactory.newInstance() - val builder: DocumentBuilder = factory.newDocumentBuilder() val doc: Document = builder.parse(URL(mavenMetadataUrl).openStream()) doc.documentElement.normalize() - return doc.getElementsByTagName("latest").item(0).getTextContent() + return doc } catch (e: FileNotFoundException) { - return "" + return null } } } diff --git a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/GmavenVersionChecker.kt b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/GmavenVersionChecker.kt new file mode 100644 index 00000000000..41dd3f1be33 --- /dev/null +++ b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/GmavenVersionChecker.kt @@ -0,0 +1,78 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.firebase.gradle.plugins + +import org.gradle.api.DefaultTask +import org.gradle.api.GradleException +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.TaskAction + +abstract class GmavenVersionChecker : DefaultTask() { + + @get:Input abstract val groupId: Property + + @get:Input abstract val artifactId: Property + + @get:Input abstract val latestReleasedVersion: Property + + @get:Input abstract val version: Property + + @TaskAction + fun run() { + val mavenHelper = GmavenHelper(groupId.get(), artifactId.get()) + val latestMavenVersion = mavenHelper.getLatestReleasedVersion() + val info = + "\n latestReleasedVersion in gradle.properties should match the latest release on GMaven (${latestMavenVersion})" + + "\n version in gradle.properties should be a version bump above this, following SemVer, and should not be released on GMaven" + // Either the Maven metadata does not exist, or the library hasn't been released + if (latestMavenVersion.isEmpty()) { + return + } + // TODO(b/285892320): Remove condition when bug fixed + if (artifactId.get() == "protolite-well-known-types") { + return + } + if (version.get() == latestReleasedVersion.get()) { + throw GradleException( + "version and latestReleasedVersion from gradle.properties are the same (${version.get()})" + + info + ) + } + if (latestMavenVersion == version.get()) { + throw GradleException( + "version from gradle.properties (${version.get()}) is already the latest release on GMaven" + + info + ) + } else if (mavenHelper.hasReleasedVersion(version.get())) { + throw GradleException( + "version from gradle.properties (${version.get()}) has already been released on GMaven" + + info + ) + } + if (latestMavenVersion != latestReleasedVersion.get()) { + if (mavenHelper.hasReleasedVersion(latestReleasedVersion.get())) { + throw GradleException( + "latestReleasedVersion from gradle.properties (${latestReleasedVersion.get()}) has been released but is not the latest release on GMaven (${latestMavenVersion})" + ) + } else { + throw GradleException( + "latestReleasedVersion from gradle.properties (${latestReleasedVersion.get()}) has not been released on GMaven" + + info + ) + } + } + } +} diff --git a/firebase-messaging/gradle.properties b/firebase-messaging/gradle.properties index fefeeb69447..8b691765bfb 100644 --- a/firebase-messaging/gradle.properties +++ b/firebase-messaging/gradle.properties @@ -1,3 +1,3 @@ version=23.2.2 -latestReleasedVersion=23.2.2 +latestReleasedVersion=23.2.1 android.enableUnitTestBinaryResources=true diff --git a/transport/transport-backend-cct/gradle.properties b/transport/transport-backend-cct/gradle.properties index 74fa8f92932..2567f579c8a 100644 --- a/transport/transport-backend-cct/gradle.properties +++ b/transport/transport-backend-cct/gradle.properties @@ -12,5 +12,5 @@ # See the License for the specific language governing permissions and # limitations under the License. -version=3.1.9 -latestReleasedVersion=3.1.8 +version=3.1.10 +latestReleasedVersion=3.1.9 diff --git a/transport/transport-runtime/gradle.properties b/transport/transport-runtime/gradle.properties index 173c7edf124..6b2d69c3466 100644 --- a/transport/transport-runtime/gradle.properties +++ b/transport/transport-runtime/gradle.properties @@ -12,6 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -version=3.1.9 -latestReleasedVersion=3.1.8 +version=3.1.10 +latestReleasedVersion=3.1.9 android.enableUnitTestBinaryResources=true