Can we enforce use of Kotlin DSL?

We finally migrated all our Groovy build scripts to Kotlin DSL and life is good… for now.

I was wondering, how do we now stop new Groovy build scripts appearing in the project so that I don’t have to keep migrating any new ones which appear?

I know there’s one approach where I just search the entire project for *.gradle files and fail the build if any exist, but the project contains a lot of files, so it will be slow.

Is there some way from within the build to determine whether any of the loaded build scripts are Groovy ones?

As I understand it, Gradle doesn’t care whether the scripts are written in either Groovy or Kotlin, and they can both happily co-exist in the same project. So what problem are you trying to solve here?

FWIW, I personally think that Groovy is a better scripting language than Kotlin anyway. So it sounds as if you are asking how to force people to hit you with sticks :person_shrugging:.

The problem I’m trying to solve is people using Groovy. People who think that a runtime interpreted scripting language is a good thing to write code in.

I’m sick of people adding new Groovy build scripts, and then having to migrate them again, after the ticket to migrate everything to Kotlin has already been supposedly “completed”.

Also, I doubt Groovy was ever a particularly good scripting language. Even back when it was new, it wasn’t great. It didn’t really get any better.

Well, I think this is the underlying problem with Gradle scripts - I utterly hate the fact that they are “code” when all I really want to do is to declare how my tasks join together. Groovy actually works well for me as a scripting language precisely because I use it as a scripting language and not as a programming language.

I’ve also decided that neither Groovy nor Kotlin is the best language to write binary Gradle plugins in, preferring to use Java for that… :thinking:.

To answer your original question, I know of no way of forcing Gradle to use only one of its scripting engines. Because if I did, I’d have used it already to forbid Kotlin scripting :stuck_out_tongue_winking_eye:.


I totally agree on the code aspect. I would have preferred a pure external DSL with no ability to insert custom code at all. But at the same time, I’ve had to suffer Maven before, and that wasn’t really any better - when something broke, I still ended up reading the Maven source code, which is no better than what ends up happening with Gradle.

It’s really the ability to insert code which resulted in us having corners of the build with non-working Groovy code hidden inside. I found 5 such areas during the conversion to Kotlin - converted them, got an error or warning, fixed it. Basic stuff like, some variable can never be null, but the code was checking for null and doing something “important” on the null path. :frowning:

Caveat is, now we know what we have compiles, but technically we still don’t know if it actually works until we run every single path in the code. So a step up from the confidence Groovy gave us, but still not perfect. If we refactor every little bit of custom code out to plugins then at least we can unit test the plugins, so that’s the loose plan going forward - stop people putting complex code into build scripts entirely. That seems even harder to enforce than “no Groovy”, though.

Did you know that Groovy has a @CompileStatic annotation, for when you need Groovy to compile the code immediately?

import groovy.transform.CompileStatic

class MyExtension {
    // etc

I use it occasionally… :nerd_face:


Yeah, but I never found a way to enforce the use of that.

I hardly try to not join that side discussion, so just regarding the original question.
If you want to prevent evil souls from using Groovy, you are pretty lost, because they can for example also have a Kotlin DSL build script consisting of apply(from = "i-want-groovy.gradle") and have the remaining stuff in that file, unless you also do some content checks.

If you just want to prevent the “mistake” of using Groovy instead of Kotlin, that’s fairly easily solved. Just define the build script filenames of the projects in the settings scripts. If the name is explicitly set, only the explicitly set file is used. Only if you specify no filename, it first looks for build.gradle and then for build.gradle.kts.