Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .github/workflows/metalava-semver-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on:
pull_request:

jobs:
build:
semver-check:
runs-on: ubuntu-latest
permissions:
pull-requests: write
Expand All @@ -26,6 +26,9 @@ jobs:

- name: Checkout PR
uses: actions/[email protected]
with:
ref: ${{ github.head_ref }}
clean: false

- name: Run Metalava SemVer check
run: ./gradlew metalavaSemver
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2020 Google LLC
* Copyright 2025 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -23,10 +23,8 @@ import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.TaskAction

abstract class CopyApiTask : DefaultTask() {
@get:InputFile
abstract val apiTxtFile: RegularFileProperty
@get:OutputFile
abstract val output: RegularFileProperty
@get:InputFile abstract val apiTxtFile: RegularFileProperty
@get:OutputFile abstract val output: RegularFileProperty

@TaskAction
fun run() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,23 @@
/*
* Copyright 2025 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 com.google.firebase.gradle.plugins.semver.VersionDelta
import java.io.ByteArrayOutputStream
import org.gradle.api.DefaultTask
import org.gradle.api.GradleException
import org.gradle.api.file.RegularFileProperty
Expand All @@ -9,47 +26,39 @@ import org.gradle.api.tasks.Input
import org.gradle.api.tasks.InputFile
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.TaskAction
import java.io.ByteArrayOutputStream

abstract class SemVerTask : DefaultTask() {
@get:InputFile
abstract val apiTxtFile: RegularFileProperty
@get:InputFile
abstract val otherApiFile: RegularFileProperty
@get:Input
abstract val currentVersionString: Property<String>
@get:Input
abstract val previousVersionString: Property<String>
@get:InputFile abstract val apiTxtFile: RegularFileProperty
@get:InputFile abstract val otherApiFile: RegularFileProperty
@get:Input abstract val currentVersionString: Property<String>
@get:Input abstract val previousVersionString: Property<String>

@get:OutputFile
abstract val outputApiFile: RegularFileProperty
@get:OutputFile abstract val outputApiFile: RegularFileProperty

@TaskAction
fun run() {
val regex = Regex("\\d+\\.\\d+\\.\\d.*")
if (!previousVersionString.get().matches(regex) || !currentVersionString.get().matches(regex)) {
val previous = ModuleVersion.fromStringOrNull(previousVersionString.get())
val current = ModuleVersion.fromStringOrNull(currentVersionString.get())
if (previous == null || current == null) {
return // If these variables don't exist, no reason to check API
}
val (previousMajor, previousMinor, previousPatch) = previousVersionString.get().split(".")
val (currentMajor, currentMinor, currentPatch) = currentVersionString.get().split(".")
val bump = if (previousMajor != currentMajor) VersionDelta.MAJOR else if (previousMinor != currentMinor) VersionDelta.MINOR else VersionDelta.PATCH
val bump =
if (previous.major != current.major) VersionDelta.MAJOR
else if (previous.minor != current.minor) VersionDelta.MINOR else VersionDelta.PATCH
val stream = ByteArrayOutputStream()
project.runMetalavaWithArgs(
listOf(
"--source-files",
apiTxtFile.get().asFile.absolutePath,
"--check-compatibility:api:released",
otherApiFile.get().asFile.absolutePath,
)
+ MAJOR.flatMap{ m -> listOf("--error", m) }
+ MINOR.flatMap{ m -> listOf("--error", m) }
+ IGNORED.flatMap{ m -> listOf("--hide", m) }
+ listOf(
"--format=v3",
"--no-color",
),
) +
MAJOR.flatMap { m -> listOf("--error", m) } +
MINOR.flatMap { m -> listOf("--error", m) } +
IGNORED.flatMap { m -> listOf("--hide", m) } +
listOf("--format=v3", "--no-color"),
ignoreFailure = true,
stdOut = stream
stdOut = stream,
)

val string = String(stream.toByteArray())
Expand All @@ -69,20 +78,23 @@ abstract class SemVerTask : DefaultTask() {
}
}
val allChanges =
(majorChanges
.joinToString(separator = "") { m -> " MAJOR: $m\n" }) +
minorChanges
.joinToString(separator = "") { m -> " MINOR: $m\n" }
(majorChanges.joinToString(separator = "") { m -> " MAJOR: $m\n" }) +
minorChanges.joinToString(separator = "") { m -> " MINOR: $m\n" }
if (majorChanges.isNotEmpty()) {
if (bump != VersionDelta.MAJOR) {
throw GradleException("API has non-bumped breaking MAJOR changes\nCurrent version bump is ${bump}, update the gradle.properties or fix the changes\n$allChanges")
throw GradleException(
"API has non-bumped breaking MAJOR changes\nCurrent version bump is ${bump}, update the gradle.properties or fix the changes\n$allChanges"
)
}
} else if (minorChanges.isNotEmpty()) {
if (bump != VersionDelta.MAJOR && bump != VersionDelta.MINOR) {
throw GradleException("API has non-bumped MINOR changes\nCurrent version bump is ${bump}, update the gradle.properties or fix the changes\n$allChanges")
throw GradleException(
"API has non-bumped MINOR changes\nCurrent version bump is ${bump}, update the gradle.properties or fix the changes\n$allChanges"
)
}
}
}

companion object {
private val MAJOR = setOf("AddedFinal")
private val MINOR = setOf("AddedClass", "AddedMethod", "AddedField", "ChangedDeprecated")
Expand Down
Loading