https://kotlinlang.org logo
#detekt
Title
# detekt
m

Michael Marshall

10/14/2021, 12:13 AM
In our CI pipeline we run
detekt
,
detektMain
and then
detektTest
so we get type resolution running across both main and test source sets. However when we do this the report files seem to overwrite each other, and only one is left at the end (seems to be a random one). Any idea how we can keep all the report files - or merge them as we go along?
e

ephemient

10/14/2021, 12:25 AM
you could force them to different paths with something like
Copy code
tasks.withType<Detekt>().configureEach {
    reportsDir.set(layout.buildDirectory.dir("reports/$name").map { it.asFile })
}
but it does feel like this should be handled automatically…
m

Michael Marshall

10/14/2021, 12:27 AM
It would be nice if there was a task with type resolution that ran against all the source sets, like
detekt
does, and that handled reporting properly. Thanks I’ll try that!
g

gammax

10/14/2021, 12:27 AM
What @ephemient suggested is correct. Are you by any chance using the
reports{}
block? We merged a change that is addressing this and will be shipped in the upcoming release
The
detewtWithTypeResolution
was also an idea we had some times ago. I believe we should go for it as more and more users get to start using type resolution
🙌 1
m

Michael Marshall

10/14/2021, 12:48 AM
Yes I’ve got my block set up like this
Copy code
reports {
    xml {
        enabled = true
        destination = file("${project.buildDir}/reports/detekt/detekt.xml")
    }
    html {
        enabled = true
    }
    txt {
        enabled = false
    }
    sarif {
        enabled = false
    }
}
Sidenote: Do I need to run
detekt
if I’m also doing
detektMain
and
detektTest
? I don’t need to run detekt on debug/release
g

gammax

10/14/2021, 9:44 AM
Yes I’ve got my block set up like this
Yeah the problem is that that
destination
is used by all the Gradle task. So you’re effectively telling all of your tasks to write in the same file ¯\_(ツ)_/¯ That’s a bug in the design of the Gradle extention and we deprecated it.
Do I need to run 
detekt
 if I’m also doing 
detektMain
 and 
detektTest
?
Not really.
👍 1
m

Michael Marshall

10/15/2021, 3:51 AM
@gammax is just the
destination
field deprecated or the whole
reports
block? I can’t see any deprecation warnings in the source code
@ephemient I tried your code but no luck. The file names seemed to be super random like “debug.xml” even when running
detektTest
. I’m now trying this
Copy code
tasks.withType<io.gitlab.arturbosch.detekt.Detekt> {
    reports {
        xml.enabled = true
        xml.destination = file("${project.buildDir}/reports/detekt/$name.xml")
        html.enabled = true
        html.destination = file("${project.buildDir}/reports/detekt/$name.html")
        txt.enabled = false
        sarif.enabled = false
    }
}
but the
name
appears to just be
detekt
no matter whether I run
detektMain
,
detektTest
or
detekt
- so my report file still gets overriden 😢
e

ephemient

10/15/2021, 6:53 AM
hmm, testing here it seems that something is re-setting the report paths before the task runs. haven't dug into it but it's probably a bug
m

Michael Marshall

10/15/2021, 6:54 AM
Any idea how I could distinguish between a
detektMain
and
detektTest
aside from the
name
? If I can do that I can work around it with the above code
e

ephemient

10/15/2021, 7:28 AM
dug into it. multiple problems: • detekt gradle plugin overwrites every task's
reports
with the same
extension.reports
instance • detekt gradle plugin configures each report to have default "${sourceSet.name}.extension", which normally isn't noticed due to the above, but is exposed when we start changing
reports
ourselves
this terrible hack works in my testing but really ought to be fixed upstream
Copy code
afterEvaluate {
    tasks.withType<io.gitlab.arturbosch.detekt.Detekt>().configureEach {
        reports = io.gitlab.arturbosch.detekt.extensions.DetektReports().apply {
            xml.destination = file("build/reports/detekt/${this@configureEach.name}.xml")
            html.destination = file("build/reports/detekt/${this@configureEach.name}.html")
            txt.destination = file("build/reports/detekt/${this@configureEach.name}.txt")
            sarif.destination = file("build/reports/detekt/${this@configureEach.name}.sarif")
        }
    }
}
m

Michael Marshall

10/15/2021, 7:42 AM
I tried that block and had to change the paths to
Copy code
file("${project.buildDir}/reports/detekt/${this@configureEach.name}.xml")
since for some reason they won’t appear in the build file otherwise. Even with that the output file names are random, since I guess the order in which the tasks are completed isn’t consistent?
e

ephemient

10/15/2021, 7:44 AM
are you trying to do this from within an
subprojects {}
block or something? given the previous issues I don't know if that can be done reliably
m

Michael Marshall

10/15/2021, 7:45 AM
I’m trying your code from the top level
build.gradle.kts
e

ephemient

10/15/2021, 7:46 AM
with
reports =
? then I don't know, I think you'll have to wait for Detekt plugin fix
😓 1
g

gammax

10/15/2021, 9:16 AM
Could you use one of the
-SNAPSHOT
version where this got fixed?
m

Michael Marshall

10/15/2021, 9:20 AM
I can't do that for our production code but I can test it out
Nvm I can’t get the snapshot working, corporate VPN getting in the way. This is my workaround in the meantime
Copy code
// Hack to rename both main and test detekt reports to something consistent, assumes we run detektMain and then detektTest in order
    tasks.withType<io.gitlab.arturbosch.detekt.Detekt> {
        val mainReportFile = project.buildDir.resolve("reports/detekt/detektMain.xml")
        doFirst {
            // We run detektTest after detektMain, so the main report file will already exist
            val newReportName = if (mainReportFile.exists()) "detektTest" else "detektMain"
            reports {
                xml.destination = file("${project.buildDir}/reports/detekt/$newReportName.xml")
                html.destination = file("${project.buildDir}/reports/detekt/$newReportName.html")
                txt.enabled = false
                sarif.enabled = false
            }
        }
    }
e

ephemient

10/15/2021, 11:42 AM
… what if you run the build again?
although if you use something else to ensure always starts from a clean slate, I suppose that would work
that bit with modifying properties in doFirst worries me a bit with regards to build caching, but I'm haven't thought through what might (or might not) go wrong
actually maybe that's not an issue; if it were, the current state of the detekt plugin would also be problematic
m

Michael Marshall

10/18/2021, 11:59 PM
What’s the potential cache issue with doFirst? Would be good to understand more
g

gammax

10/19/2021, 12:01 AM
If you add a
doFirst
to a task, that task’s cache will be considered invalid whenever you edit the
build.gradle
That is kind of an overkill, as basically just by say, bumping a version of a library, you’re invalidating that task cache and forcing it to re-run. That also applies to
doLast
m

Michael Marshall

10/19/2021, 12:12 AM
Thanks! We’re not running detekt manually often (although we do use the IDE plugin so that could be affected too?), as long as the task runs as intended on our CI pipeline, which always has a fresh
build
folder, I’m okay with it
g

gammax

10/19/2021, 12:13 AM
The IDE plugin is not affected
🙌 1
The thing will affect your local builds however
👍 1
Like it will make them somehow slower as detekt is hooked up in the
check
task
m

Michael Marshall

10/19/2021, 12:18 AM
Great point. I think it’s okay as only
detekt
, not
detektMain
, is hooked up to
check
and that runs pretty quick. Our
build.gradle
isn’t edited very often either 🤷
107 Views