Skip to content

Using RevAPI to determine the version #159

@austek

Description

@austek

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?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions