Open nico-arianto opened 1 year ago
Did you check the link shown in the log for details on how to fix this?
Adding a version parameter here won't allow us to override Gradle's dependency resolution rules so I don't see how this will solve the issue.
The solution in https://detekt.dev/docs/gettingstarted/gradle#dependencies, it will cause the dependencies version that we declared in
plugins {
val kotlinVersion = "1.8.22"
kotlin("jvm") version kotlinVersion
...
}
to be override to 1.8.21
, which is the same as
plugins {
val kotlinVersion = "1.8.21"
kotlin("jvm") version kotlinVersion
...
}
I'm wondering if possible for only detekt
task to be able to override the dependencies to specific Kotlin version, but other tasks still using the latest Kotlin version
Or maybe the detekt
plugin is using a shaded jar to avoid the Kotlin compatibility issue, if possible.
Can you please share a build scan, a reproducer, or a full copy of the build file? There's most likely an issue with your Gradle config and it will be simpler to explain with more info.
here is the build scan: https://gradle.com/s/sgxok4toctxju
@nico-arianto I don't know if this is the best way to do this, but I think this works in your project build:
configurations.matching { it.name == "detekt" }.all {
resolutionStrategy.eachDependency {
if (requested.group == "org.jetbrains.kotlin") {
useVersion("1.8.21")
}
}
}
I have a multi-project and have to put it in each sub-project. It seems to limit the 1.8.21 dependency to only detekt. Will probably have to keep on using it since this problem will probably still be around when Kotlin goes 1.9 or 2.0.
@alwyn Yes, it's working as I wanted it to. Thanks
I hope this version overridden can be done automatically within this piece of code shortly in the next release
plugins {
id("io.gitlab.arturbosch.detekt") version "1.23.0"
}
This could be something we look at, but there are a few things to consider. Ultimately though this would just be working around problems caused by build scripts or other plugins, not the detekt plugin itself, and the error message shows a link to documentation that explains what the issue is and how to address it.
I'd rather make changes to the documentation since it seems there's room for improvement - suggestions and PRs are welcome.
@3flex ποΈ, yeah, we can modify the documentation first and revisit it for improvement.
want me to close this issue or leave it open?
For me, this finally worked:
project.afterEvaluate {
configurations["detekt"].resolutionStrategy.eachDependency {
if (requested.group == "org.jetbrains.kotlin") {
useVersion("1.8.21")
}
}
}
Since Kotlin 1.9.0 is released today
detekt was compiled with Kotlin 1.8.21 but is currently running with 1.9.0
Have you read https://detekt.dev/docs/gettingstarted/gradle#dependencies?
This is not a detekt defect. It's an issue with either the Gradle build config or another plugin that's affecting detekt. If the documentation linked above is not clear or doesn't address the issue then we're open to suggestions on how to improve it.
@3flex The problem with the solution described in the docs is that it is very cumbersome and makes it impossible to get detekt updated automatically by dependabot and other similar tools. I would prefer to have single place where detekt version is specified. I think that shadowing jar could be the best option here.
Ok the docs are obviously not clear, because it's not suggesting to hard code the detekt or Kotlin version anywhere, so auto update with dependabot or renovate should not be an issue at all - I'm not sure why that's the takeaway?
I'm open to suggestions on how to improve it.
Shadow jar will fix the issue but it blows out the size of the artifact, slows down builds, complicates our build setup, and the embeddable Kotlin version can't be reused as a dependency by other libraries on user's machines.
I agree with @3flex here. We need your help to make the documentation more clear. This is not a detekt's issue. This is an issue in how the projects apply the kotlin dependency.
I have my projects with detekt and kotlin and I can update/downgrade any of them at my will without the need of any type of hack or workaround. It just work. BUT if the project's configuration overrides the version that detekt uses π₯π₯π₯ it explodes.
So please help us make this more clear. Show us more examples of how you configure kotlin so we can add more examples... We don't know how to improve that documentation.
I would be for providing a shadow variant alongside the normal one. If detect can't work with any Kotlin version then it is on detekt plate.
I've seen similar cases in the past - there was wiremock which used an old jetty that was incompatible with new Spring Boot. What wiremock maintainers did? They provided a standalone version with all dependencies shadowed that just /worked/.
We use the gradle buildSrc to specify our custom plugins. This looks like the following:
plugins {
`kotlin-dsl`
`kotlin-dsl-precompiled-script-plugins`
}
repositories {
gradlePluginPortal() // so that external plugins can be resolved in dependencies section
}
val kotlinVersion = "1.8.21"
val nodePluginVersion = "5.0.0"
val sonarPluginVersion = "4.2.0.3129"
val detektVersion = "1.23.0"
val jacocoToCoberturaVersion = "1.1.2"
dependencies {
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion")
implementation("org.jetbrains.kotlin:kotlin-allopen:$kotlinVersion")
implementation("org.jetbrains.kotlin:kotlin-noarg:$kotlinVersion")
implementation("io.gitlab.arturbosch.detekt:detekt-gradle-plugin:$detektVersion")
implementation("com.github.node-gradle:gradle-node-plugin:$nodePluginVersion")
implementation("org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:$sonarPluginVersion")
implementation("net.razvan:JacocoToCoberturaPlugin:$jacocoToCoberturaVersion")
}
so we only include the kotlin-gradle-plugin in the (most current) version we use for our application. We don't at least not intentionally override the kotlin version for all configurations. (like shown in https://detekt.dev/docs/gettingstarted/gradle/#dependencies)
However, we specify the kotlin language version like this.
val KOTLIN_LANGUAGE = KotlinVersion.KOTLIN_1_8
tasks.withType<KotlinCompile>().configureEach {
compilerOptions{
jvmTarget.set(ToolVersions.JVM_TARGET)
apiVersion.set(ToolVersions.KOTLIN_LANGUAGE)
languageVersion.set(ToolVersions.KOTLIN_LANGUAGE)
freeCompilerArgs.add("-Xjvm-default=all-compatibility")
}
}
I am not sure how helpful this is for you ( @3flex @BraisGabin ) to understand how the this issue might arise for detekt users. Let me know if you need additional information.
Hello, would it be possible to get a 1.23.1 with Kotlin 1.9.0 and JDK 20 support? This is currently blocking our projects from upgrading to kotlin 1.9.0. I along with the community would be very appreciative if we could get a 1.23.1 with minimal changes quickly, but that will allow us to run our builds with detekt. instead of waiting weeks for a new build with proper Kotlin 1.9.0 updates for the new features.
@credmond-git can you please open a new issue? Thanks.
Our snapshot version is updated to Kotlin 1.9.0 which supports Java 20 targets so you could try that in the meantime.
I am not sure I understand the root of the issue discussed, but I am in the current situation. Our project has just be updated to be configured to use Kotlin 1.8.22 (from 1.8.20)
detekt was compiled with Kotlin 1.8.21 but is currently running with 1.8.22.
detekt was compiled with Kotlin 1.9.0 but is currently running with 1.8.22.
What has changed between 1.22 and 1.23 to make detekt so sensitive to particular versions of Kotlin?
I have followed the link to https://detekt.dev/docs/gettingstarted/gradle/#dependencies but I cannot see that we are in the situation described, so I cannot apply the proposed fix (as far as I understand). It looks as if it is going to be difficult to update detekt from now on for people like me who are unable to dive into the subtleties of gradle configurations.
In future I am not sure how we will be able to keep updating detekt.
Update update to Kotlin 1.9.10
detekt was compiled with Kotlin 1.9.0 but is currently running with 1.9.10.
Crated a ticket to track Kotlin 1.9.10 support https://github.com/detekt/detekt/issues/6428 (corrected issue)
@credmond-git I think you're referring to #6428
I've had another look at this, and it really reinforced the value of providing reproducers. I was able to quickly identify the issue in this project, only because this ticket referred to this one so I was able to follow the breadcrumbs.
The culprit seems to be the io.spring.dependency-management
Gradle plugin.
I would like the following users to please confirm if you are using this plugin and whether this workaround works for you:
configurations.detekt {
resolutionStrategy.eachDependency {
if (requested.group == "org.jetbrains.kotlin") {
useVersion("1.9.0") // Add the version of Kotlin that detekt needs
}
}
}
If YES, please π this comment.
If you cannot give a πeither because you're NOT using Spring, or you are using Spring but the workaround doesn't work, please provide a full standalone reproducer.
Assuming Spring is the culprit this can be mentioned in the CLI error message as well as online docs.
I am not using spring, and you can see a reproducer here: https://github.com/gestalt-config/gestalt/tree/test/detekt with a build failure at: https://github.com/gestalt-config/gestalt/actions/runs/6032946662/job/16368897280 The workaround didn't work either. The workaround is at https://github.com/gestalt-config/gestalt/blob/test/detekt/buildSrc/src/main/kotlin/gestalt.kotlin-code-quality-conventions.gradle.kts
@credmond-git a couple of things:
./gradlew detekt
without errors. Running that with --scan
shows that the build is resolving the correct Kotlin version.@3flex
it's not related to spring-boot for my case, it's because of
[Corrected] it's verified because of kotlin("jvm") version "1.9.0"
in my case andspring-boot
)
I'm using this workaround for now:
configurations.matching { it.name == "detekt" }.all {
resolutionStrategy.eachDependency {
if (requested.group == "org.jetbrains.kotlin") {
useVersion("1.9.0")
}
}
}
@3flex Thanks for the help, i corrected it to useVersion("1.9.0")
and it seems to work. Now that i am trying it again without the workaround, it seems to be running on the gestalt project. It is failing on a work spring project that uses io.spring.dependency-management
so i must have gotten them mixed up.
I will try the work around on the spring project tomorrow.
@nico-arianto surely your issue is due to spring? This is from the build scan you uploaded: https://scans.gradle.com/s/sgxok4toctxju/plugins#io.spring.dependency-management-3
@3flex
I will still get the same issue when I create a new Kotlin JVM Gradle project without Spring Boot
[Corrected] Kotlin project without spring-boot
is working as expected)
Please provide a full reproducer of that case - when you create a new Kotlin JVM Gradle project.
The build scan you provided with the original reported issue would have been caused by the spring dependency management plugin being applied in your project per my link in my last comment.
@3flex
Sorry, the issue didn't happen for a new Kotlin JVM Gradle project without Spring Boot
, but looks like it's fine also with Spring Boot π€
[Corrected] it's happen with Spring Boot)
Build Gradle (Kotlin) file:
import org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES
plugins {
kotlin("jvm") version "1.9.0"
kotlin("plugin.spring") version "1.9.0"
application
id("org.springframework.boot") version "3.1.3"
id("io.spring.dependency-management") version "1.1.3"
id("io.gitlab.arturbosch.detekt") version "1.23.1"
}
group = "org.example"
version = "1.0-SNAPSHOT"
repositories {
mavenCentral()
}
dependencies {
detektPlugins("io.gitlab.arturbosch.detekt:detekt-formatting:1.23.1")
detektPlugins("io.gitlab.arturbosch.detekt:detekt-rules-libraries:1.23.1")
testImplementation(kotlin("test"))
}
dependencyManagement {
imports {
mavenBom(BOM_COORDINATES)
}
}
tasks.test {
useJUnitPlatform()
}
kotlin {
jvmToolchain(8)
}
application {
mainClass.set("MainKt")
}
detekt {
source.from("src")
buildUponDefaultConfig = true
allRules = true
}
Gradle Scan: https://scans.gradle.com/s/cvqfejqktotm2/plugins#io.spring.dependency-management-2
Are we sure it's because of the spring.dependency-management
, or it's something else?
Reason: If I tried it with my main project, it still failed, and I needed to use resolutionStrategy
to workaround.
[Corrected] It's fine βπΌ because it's using Kotlin version 1.9.0
which is compatible with detect 1.23.1
I cannot test this till next week because I am not working but I will next week
EDIT: the workaround does the job.
On Thu, 31 Aug 2023, 05:58 Matthew Haughton, @.***> wrote:
I've had another look at this, and it really reinforced the value of providing reproducers. I was able to quickly identify the issue in this project https://github.com/parts-picker/parts-picker-web, only because this ticket https://github.com/parts-picker/parts-picker-web/issues/151 referred to this one https://github.com/detekt/detekt/issues/6428 so I was able to follow the breadcrumbs.
The culprit seems to be the io.spring.dependency-management Gradle plugin.
I would like the following users to please confirm if you are using this plugin and whether this workaround works for you:
configurations.detekt { resolutionStrategy.eachDependency { if (requested.group == "org.jetbrains.kotlin") { useVersion("1.9.10") // Add the appropriate Kotlin version here } } }
If YES, please π this comment.
- @nico-arianto https://github.com/nico-arianto - TBC
- @alwyn https://github.com/alwyn - TBC
- @schowave https://github.com/schowave - TBC
- @xRomZak https://github.com/xRomZak - TBC
- @kkocel https://github.com/kkocel - TBC
- @martinweu https://github.com/martinweu - TBC
- @credmond-git https://github.com/credmond-git - TBC
- @arnodel https://github.com/arnodel - TBC
If you cannot give a πeither because you're NOT using Spring, or you are using Spring but the workaround doesn't work, please provide a full standalone reproducer.
Assuming Spring is the culprit this can be mentioned in the CLI error message as well as online docs.
β Reply to this email directly, view it on GitHub https://github.com/detekt/detekt/issues/6198#issuecomment-1700332653, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAMJKOMLTEKI5RKZB5FKE6TXYADWHANCNFSM6AAAAAAZABN6MY . You are receiving this because you were mentioned.Message ID: @.***>
looks like it's fine also with Spring Boot
In that config you are using Kotlin plugins with version 1.9.0 so I guess the spring dependency management plugin aligns to that, which is what detekt 1.23.1 needs.
I'm quite sure that in the cases where we have enough info to confirm that it's due to the spring dependency management plugin. There could be other ways to configure Gradle to override the dependencies of course but this is a case that we can better document.
If I tried it with my main project, it still failed and need to use resolutionStrategy to workaround.
Without a reproducer I can't confirm.
@3flex
Ah yes, I missed updating the Kotlin version to 1.9.10
And, it's verified because of spring-boot
dependency management.
Thanks
@3flex Yes, we have Gradle multi-module project, where one is modules is spring-boot app with
spring-dependencies = { id = "io.spring.dependency-management", version = "1.1.3" }
Workaround with 1.9.10 doesn't help. I'll try to prepare a reproducer
configurations.detekt {
resolutionStrategy.eachDependency {
if (requested.group == "org.jetbrains.kotlin") {
useVersion("1.9.10") // Add the version of Kotlin that detekt needs
}
}
}
Test 2: removed spring-boot submodule and its dependencies.
Execution failed for task ':detektAll'.
> detekt was compiled with Kotlin 1.9.0 but is currently running with 1.9.10.
This is not supported. See https://detekt.dev/docs/gettingstarted/gradle#dependencies for more information.
detektAll
is a custom task defined in a root build.gradle
DetektReports.metaClass.setup = {
html.required.set(true) // observe findings in your browser with structure and code snippets
xml.required.set(false) // checkstyle like format mainly for integrations like Jenkins
txt.required.set(true) // similar to the console output, contains issue signature to manually edit baseline files
sarif.required.set(false) // standardized SARIF format to support integrations with GitHub Code Scanning
md.required.set(false) // simple Markdown format
}
def setupDetekt = { Detekt detekt ->
detekt.jvmTarget = 20
detekt.languageVersion = '1.9'
detekt.buildUponDefaultConfig = true
detekt.allRules = false
detekt.parallel = true
detekt.config.setFrom(files("$rootDir/config/detekt/detekt.yml")) // custom config
detekt.baseline.set(file("$rootDir/config/detekt/baseline.xml")) // suppress already existing issues
detekt.setSource(file(projectDir))
detekt.include('**/*.kt')
detekt.exclude('**/resources/**', '**/build/**')
detekt.reports.setup()
}
tasks.register('detektAll', Detekt) {
description = 'Custom detekt task for all modules (with type resolution enabled)'
classpath = configurations.detekt // Set classpath and JVM target (enables type resolution)
setupDetekt(it)
}
@xRomZak the best way to help us is to try Kotlin 1.9.10 then respond to this comment, thanks! https://github.com/detekt/detekt/issues/6198#issuecomment-1700332653
Updated my comment above. I'll provide more details as soon as possible.
Use useVersion("1.9.0")
with detekt 1.23.1.
It needs to be set to what detekt needs.
I have the following project (generated from spring starter page): https://github.com/kkocel/detektrepro It works on 1.9.0 but when switched to branch https://github.com/kkocel/detektrepro/tree/1910 (Kotlin 1.9.10) it doesn't.
Is that a public repo? I get a 404 on both links
@3flex I've just changed it to public
@kkocel please see my comment above, you need to apply the workaround withuseVersion("1.9.0")
@3flex This workaround has lots of downsides - eg. dependabot won't know about this workaround, so I need to update the version in the workaround code every time when detekt updates. Once again, please reconsider providing a version of the detekt plugin with shadowed Kotlin dependency - it will resolve this issue permanently.
OK, so it feels to be confirmed that io.spring.dependency-management
generates this issue. (We still don't know if everyone that faced this issue is for that reason so please, keep answering @3flex comment).
But, which should be our action plan for the "incompatibility" with that plugin? Some ideas:
io.spring.dependency-management
.io.spring.dependency-management
or just print the workaround. @3flex This workaround has lots of downsides - eg. dependabot won't know about this workaround, so I need to update the version in the workaround code every time when detekt updates. Once again, please reconsider providing a version of the detekt plugin with shadowed Kotlin dependency - it will resolve this issue permanently.
I don't think we should do that. This is not our issue. It is an issue at io.spring.dependency-management
. Also, we are asking you to see if the workaround works to be sure that we understand the problem. You don't need to add it to your code base if you don't want.
Yes, the workaround works but it's lame.
I see things differently - it's the detekt that strictly requires the exact Kotlin version (and breaks otherwise), so yes it's your issue. If detekt so desperately requires the exact Kotlin version then it should bundle it, instead of requiring every other plugin to adjust.
the workaround works
Thanks for confirming!
requiring every other plugin to adjust
This is not what we're saying. There's a workaround that allows you to use detekt & the Spring dependency management plugin together. We are not saying that any other plugin has to adjust. There might also be better workarounds, so any suggestions for improvement to the documented workaround would be welcome. I see the Spring dependency management plugin is configurable so there might be another way to work around if both plugins are in use.
detekt that strictly requires the exact Kotlin version (and breaks otherwise), so yes it's your issue.
detekt interfaces with a lot of core compiler code and it sensitive to the version in use. This is not going to change. If detekt runs with an unexpected Kotlin compiler version that creates other issues, which get raised and have to be investigated. Instead, detekt errors when this is the case, and asks for this to be fixed, so we don't get strange errors being reported. The error is only shown when the build is misconfigured.
In terms of whether this is our issue or not - it's not. detekt's Gradle plugin configures itself correctly. Another plugin is overriding that configuration. That's not for us to fix.
dependabot won't know about this workaround, so I need to update the version in the workaround code every time when detekt updates
To be frank, this is not our problem. detekt needs to run with a certain version of Kotlin in its classpath. If the Spring dependency management plugin clobbers the configuration, that's caused by that plugin, and if the workaround is not ideal or has some other issues, that's really not in our hands.
You are of course free to stop using the Spring dependency management plugin, come up with an improved workaround and suggest improvements to our documentation, or even stop using detekt. Obviously we want as many people as possible to use detekt as many contributors and the maintainers have put a lot of time and effort into making detekt what it is today, and we like to see others getting value from it.
Back to the options we might consider:
Open an issue to io.spring.dependency-management
If anyone's affected by this directly then it's worth raising here. Perhaps the maintainers of that plugin have other suggested workarounds, even if they don't deliver an actual fix.
Update our documentation and explain this problem
Yes, we should definitely do this.
Check on our gradle plugin if this plugin is applied and, if it is, show a different error message. That different error message I don't know if it should point to the issue to io.spring.dependency-management or just print the workaround.
This is a good idea - though we probably don't want to show it every single time. I think it's better to update the CLI error message to reference Spring since it's going to continue being a common source of this issue.
Hi, all. I'm the primary maintainer of the io.spring.dependency-management
plugin, I'm also a member of the Spring Boot team. A colleague of mine, @marcingrzejszczak, asked me to take a look at this issue.
If you apply only the dependency management plugin to a project, it won't have any effect at all on the version of Kotlin that's used. If you apply both the dependency management plugin and Spring Boot's plugin, the latter will configure the former to import the spring-boot-dependencies
bom and this bom includes dependency management for Kotlin. Furthermore, when you apply a specific version of a Kotlin plugin, Spring Boot's plugin automatically detects that and overrides the managed version of Kotlin to match. This dependency management is applied to every configuration which is why you're seeing an override of the version of Kotlin in the detekt
configuration.
Generally speaking, keeping dependency versions consistent across configurations is useful. However, it sounds like that's not the case here. From what I understand reading the above, Detekt itself needs to run using a specific version of Kotlin, irrespective of the version of Kotlin that's being used elsewhere in the same project.
Assuming that I have understood this situation correctly, I'm afraid I don't have any suggestions for a better workaround. It sounds like what's really needed is a way to tell the dependency management plugin that "global" dependency management should not be applied to the detekt
configuration. That would leave it free to resolve whatever versions Detekt needs.
Expected Behavior
Code:
This line
kotlinVersion = "1.8.21"
will override the Kotlin version and being used bydetekt
Note: Or other alternative approach also can, as long can overcome the Kotlin compatibility issue.
Current Behavior
Code:
Gradle Task:
Context
detekt
didn't locked us to use the latest Kotlin version for other Gradle tasks