JavierSegoviaCordoba / semver-gradle-plugin

Set projects versions based on git tags and following semantic versioning
https://semver-gradle-plugin.javiersc.com
Other
25 stars 3 forks source link

Overriding the version seems to be broken #175

Open tkrah opened 1 day ago

tkrah commented 1 day ago

I tried to override the version like described here (using Gradle 8.10.2):

https://github.com/JavierSegoviaCordoba/semver-gradle-plugin?tab=readme-ov-file#override-the-version

semver {
    version.set("1.0.0")
}

does not work and fails with a gradle error:

No signature of method: com.javiersc.semver.project.gradle.plugin.VersionProperty.set() is applicable for argument types: (String) values: [1.0.0]
  Possible solutions: get(), get(), getAt(java.lang.String), use([Ljava.lang.Object;), wait(), grep()

So I tried:

semver {
    setVersion("1.0.0")
}

which does not fail but it just gets ignored, printSemVer task still does print its calculated version number:

semver for sub1: 0.1.0.0+195c209+DIRTY

instead of the expected:

semver for sub1: 1.0.0

I am lost here, how to override the version, it seems not to work at all.

JavierSegoviaCordoba commented 1 day ago

I will recheck but I think I deleted that method some time ago due some order problems.

As workaround you can use mapVersion.

Thank you for reporting this, I will update the docs 😄

JavierSegoviaCordoba commented 1 day ago

About +DIRTY, it is shown when the repository has some uncommitted changes, you can pass -P semver.checkClean=false (or set it on gradle.properties).

tkrah commented 1 day ago

I will recheck but I think I deleted that method some time ago due some order problems.

As workaround you can use mapVersion.

Thank you for reporting this, I will update the docs 😄

Do you have an example for the mapVersion syntax to override it, the example from the docs is failing for me too or I am just unable to get the syntax right.

JavierSegoviaCordoba commented 1 day ago

You can see it in this test:

https://github.com/JavierSegoviaCordoba/semver-gradle-plugin/blob/main/semver-project-gradle-plugin/testFunctional/resources/version-mapping/v1_0_0%20to%20v1_0_0+1_9_0/build.gradle.kts

It should be something like:

semver {
    mapVersion { "1.0.0" }
}

Sorry I am replying from mobile so I cannot directly check.

tkrah commented 1 day ago

You can see it in this test:

https://github.com/JavierSegoviaCordoba/semver-gradle-plugin/blob/main/semver-project-gradle-plugin/testFunctional/resources/version-mapping/v1_0_0%20to%20v1_0_0+1_9_0/build.gradle.kts

This fails for me with:

> Could not create task ':printSemver'.
   > Could not isolate value com.javiersc.semver.project.gradle.plugin.valuesources.VersionValueSource$Params_Decorated@2b159202 of type VersionValueSource.Params
      > Could not serialize value of type $Proxy208

Using:

semver {
    mapVersion { gradleVersion ->
        "${gradleVersion.copy(metadata = "1.1.0")}"
    }
}

I tried:


semver {
    mapVersion { "1.0.0" }
}

too, but the same Proxy error message.

PS: No need to be sorry, I appreciate the feedback and suggestions.

JavierSegoviaCordoba commented 1 day ago

Is it your project open source?

I would need a reproducer but it look like an issue with configuration cache or project isolation.

I haven't tested my plugin with isolated projects so it is possible I may update it to support IP. If you confirm you have it enabled I can try to take a look into it this week.

tkrah commented 1 day ago

It is just a mini playground locally, nothing fancy. I post a link to a sample github repo asap - I just did what you wrote in the docs under apply the plugin, the second proposal, applied from settings.gradle:


pluginManagement {
    plugins {
        id 'com.javiersc.semver' version '0.7.1'
    }
}

plugins {
    id 'com.javiersc.semver'
}
JavierSegoviaCordoba commented 1 day ago

@tkrah I can reproduce it. For some reason, the test with configuration cache is passing but on a real project I am getting the issue you have reported.

JavierSegoviaCordoba commented 1 day ago

@tkrah the reproducer I have is failing due I was capturing a value that has Project as a reference.

semver {
    mapVersion { gradleVersion ->
        val isDirty: Boolean = gradleVersion.metadata == "DIRTY"
        val metadata: String =
            if (isDirty) "${getKotlinPluginVersion()}+DIRTY" else getKotlinPluginVersion()
        "${gradleVersion.copy(metadata = metadata)}"
    }
}

It can be fixed by extracting the calculation of Project::getKotlinPluginVersion outside of mapVersion

semver {
    mapVersion { gradleVersion ->
        val isDirty: Boolean = gradleVersion.metadata == "DIRTY"
        val metadata: String =
            if (isDirty) "${getKotlinPluginVersion()}+DIRTY" else getKotlinPluginVersion()
        "${gradleVersion.copy(metadata = metadata)}"
    }
}

Can you share your reproducer? I have tried to do the next but it is working without issues on my side.

semver {
    mapVersion { "1.0.0" }
}
tkrah commented 1 day ago

@JavierSegoviaCordoba https://github.com/tkrah/semver-gradle-plugin-playground here you go.

JavierSegoviaCordoba commented 1 day ago

@tkrah the problem is related to using Groovy in the build.gradle files instead of using Kotlin and build.gradle.kts.

I will try to fix it.

tkrah commented 1 day ago

Bummer, that's interesting, I was under the impression that it should not matter (from a users perspective) if I use groovy or kotlin - unfortunately I have a groovy destination and I am unable to migrate the whole stack to kotlin at the moment. I hope you can fix that, thx.

tkrah commented 10 hours ago

I tried that workaround @JavierSegoviaCordoba - see here, but the version is still wrong in the subprojects:

> Task :printSemver
semver for semver-gradle-plugin-playground: 1.0.0

> Task :sub1:printSemver
semver for sub1: 0.1.0.0+1cf0ef9

> Task :sub2:printSemver
semver for sub2: 0.1.0.0+1cf0ef9

BUILD SUCCESSFUL in 668ms
9 actionable tasks: 7 executed, 2 from cache

Something is still not right, suggestions?

JavierSegoviaCordoba commented 9 hours ago

Have you put the workaround in each subproject? Each project is independent including the root project one.

Another option is to do it on the settings script with a combination of the beforeProject and the withPlugin callbacks. So you don't need to put the workaround on each project.

I will share the code later when I come back to home.

JavierSegoviaCordoba commented 9 hours ago

This would be a good feature request for the settings plugin to avoid adding the manual boilerplate I commented before.

tkrah commented 9 hours ago

I tried:

allprojects {
    pluginManager.withPlugin('com.javiersc.semver') {
        semver {
            mapVersion Map.per
        }

    }
}

but this did not work.

JavierSegoviaCordoba commented 8 hours ago

@tkrah can you try to do this on the settings.gradle?

import com.javiersc.gradle.version.GradleVersion
import com.javiersc.semver.project.gradle.plugin.SemverExtension
import com.javiersc.semver.project.gradle.plugin.SemverExtension.VersionMapper

pluginManagement {
    repositories {
        gradlePluginPortal()
        mavenCentral()
    }
}

plugins {
    id("com.javiersc.semver") version "0.7.1"
}

dependencyResolutionManagement {
    repositories {
        gradlePluginPortal()
        mavenCentral()
    }
}

class Map {
    static per = new VersionMapper() {
        @Override
        String map(GradleVersion gradleVersion) {
            "1.0.0"
        }
    }
}

gradle.beforeProject { project ->
    project.pluginManager.withPlugin('com.javiersc.semver') {
        project.extensions.configure(SemverExtension) { semver ->
            semver.mapVersion Map.per
        }
    }
}
JavierSegoviaCordoba commented 8 hours ago

@tkrah the problem is, that it is not working if the plugin is not explicitly applied on each subproject.

I will need to revisit the settings plugin as this is a bug for sure.

tkrah commented 8 hours ago

@tkrah the problem is, that it is not working if the plugin is not explicitly applied on each subproject.

I will need to revisit the settings plugin as this is a bug for sure.

Yeah that was my observation too, with your proposal in the settings.gradle I need to add:

id 'com.javiersc.semver'

to every build.gradle in my project to have it working.

tkrah commented 8 hours ago

And another thing, the workaround moves that to a static context which is a problem, because my goal is this:

semver {
    mapVersion { determineVersion() }
}

Where determineVersion() for example is something like:

String evaluateProjectVersion() {
    if (System.env.BUILD_NUMBER != null) {
        version = version.toString().replaceAll("\\+.*", "+build${String.format("%05d", Integer.parseInt(System.env.BUILD_NUMBER as String))}")
    }
    logger.lifecycle("${project.name} Version ${project.version}")
    return version
}

This is not possible in the settings.gradle because I can't use project from a static context.

JavierSegoviaCordoba commented 8 hours ago

@tkrah

It is not necessary, the problem is I am using a synthetic ID on the projects ("com.javiersc.semver.project"), so to get the workaround working it is necessary to do:

gradle.beforeProject { project ->
    project.pluginManager.withPlugin('com.javiersc.semver.project') {
        project.extensions.configure(SemverExtension) { semver ->
            semver.mapVersion Map.per
        }
    }
}

I will improve this to not having to know that ID and just use only the main one.

About the static issue, this code is picking and changing the project.version? You should avoid doing anything with project.version and do everything with mapVersion function.

version = version.toString().replaceAll("\\+.*", "+build${String.format("%05d", Integer.parseInt(System.env.BUILD_NUMBER as String))}")

Here you can get the version (and you can do toString) to do the replacements you are doing on the evaluateProjectVersion method:

class Map {
    static per = new VersionMapper() {
        @Override
        String map(GradleVersion gradleVersion) {
            gradleVersion.toString() // do whatever you need with it
        }
    }
}

gradle.beforeProject { project ->
    project.pluginManager.withPlugin('com.javiersc.semver.project') {
        project.extensions.configure(SemverExtension) { semver ->
            semver.mapVersion Map.per
        }
    }
}
tkrah commented 7 hours ago

@JavierSegoviaCordoba Gotcha, thanks - that synthetic id is tricky - got the workaround working now, including your proposal of the version mapper. Thanks for your support.

JavierSegoviaCordoba commented 6 hours ago

@tkrah I have removed the synthetic IDs, so everything will use the ID com.javiersc.semver.

Furthermore, I have added the semver extension to the settings file, so you will be able to remove some boilerplate with the next version, 0.8.0:

// settings.gradle.kts
class SemverWorkaround {
    static mapper = new VersionMapper() {
        @Override
        String map(GradleVersion gradleVersion) {
            "1.0.0"
        }
    }
}

semver {
    mapVersion SemverWorkaround.mapper
}

If you want to test it before the version 8.0.0 is released, you can test the version 0.7.2-SNAPSHOT. It is in the snapshot repository.

The workaround has been added to the README as well.

I will keep this issue open until I get a reply from Gradle engineers here.

tkrah commented 5 hours ago

@JavierSegoviaCordoba I would like to try the changes ... but which snapshot repository do you refer to here (sorry if that is obvious, I don't know it yet).

JavierSegoviaCordoba commented 4 hours ago

@tkrah you need to add maven("https://oss.sonatype.org/content/repositories/snapshots") to the repositories blocks

tkrah commented 3 hours ago

Thx, works like you told :).