gradle-git-versioning-plugin icon indicating copy to clipboard operation
gradle-git-versioning-plugin copied to clipboard

Using RevAPI to determine the version

Open austek opened this issue 8 months ago • 2 comments

I've tried to use RevAPI to determine the version number for source/binary compatible changes programatically

val majorVersionIncrement: String = "\${describe.tag.version.major.next}.0.0"
val minorVersionIncrement: String = "\${describe.tag.version.major}." +
        "\${describe.tag.version.minor.next}.0"
val patchVersionIncrement: String = "\${describe.tag.version.major}." +
        "\${describe.tag.version.minor}." +
        "\${describe.tag.version.patch.next}"
val patchVersionIncrementSnapshot: String =  "${patchVersionIncrement}-SNAPSHOT"

tasks.version {
    dependsOn(tasks.revapiAnalyze)
}

gitVersioning.apply {
    refs {
        branch("main") {
            val file: File = layout.buildDirectory.file("revapi/revapi-results.json").get().asFile
            val compatibility = revApiResultsIndicateCompatibilityIssues(file)
            version = when(compatibility) {
                "BINARY_BREAKING" -> majorVersionIncrement
                "SOURCE_BREAKING" -> minorVersionIncrement
                else -> patchVersionIncrement
            }
        }
        tag("v(?<version>.*)") {
            version = "\${ref.version}"
        }
    }

    // optional fallback configuration in case of no matching ref configuration
    rev {
        version = patchVersionIncrementSnapshot
    }
}

fun revApiResultsIndicateCompatibilityIssues(file: File): String {
    val jsonString = file.readText().replace(Regex(",(?=\\s*[}\\]])"), "")
    val jsonReader = JsonReader(StringReader(jsonString))
    jsonReader.strictness = Strictness.LENIENT
    val rootElement = JsonParser.parseReader(jsonReader)

    var breakingChangeFound = false

    if (rootElement.isJsonObject && rootElement.asJsonObject.has("results") && rootElement.asJsonObject.get("results").isJsonArray) {
        val resultsArray = rootElement.asJsonObject.getAsJsonArray("results")

        for (resultElement in resultsArray) {
            if (resultElement.isJsonObject) {
                val resultObject = resultElement.asJsonObject
                if (resultObject.has("classification") && resultObject.get("classification").isJsonObject) {
                    val classificationObject = resultObject.getAsJsonObject("classification")
                    if (classificationObject.has("BINARY") && classificationObject.get("BINARY").isJsonPrimitive && classificationObject.get("BINARY").asString == "BREAKING") {
                        return "BINARY_BREAKING";
                    } else if (classificationObject.has("SOURCE") && classificationObject.get("SOURCE").isJsonPrimitive && classificationObject.get("SOURCE").asString == "BREAKING") {
                        breakingChangeFound = true
                    }
                }
            }
        }
    }
    return if (breakingChangeFound) {
        "SOURCE_BREAKING"
    } else {
        "COMPATIBLE"
    }
}

However, as this plugin is run via an extension and very early on the project load, I couldn't find a way to generate the revapi/revapi-results.json file.

Is it possible to add such a feature or provide a way to add such behaviour?

austek avatar Mar 27 '25 03:03 austek

you could try

plugins {
    id("org.revapi.revapi-gradle-plugin") version "1.8.0" apply false
}

tasks.revapiAnalyze.get().execute()

gitVersioning.apply {
  // ...
}

qoomon avatar Mar 27 '25 07:03 qoomon

however I'm not familiar with revapi-gradle-plugin

qoomon avatar Mar 27 '25 07:03 qoomon