Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Gradle Kotlin DSL #334

Closed
sdeleuze opened this issue Jan 2, 2017 · 25 comments
Closed

Support Gradle Kotlin DSL #334

sdeleuze opened this issue Jan 2, 2017 · 25 comments

Comments

@sdeleuze
Copy link
Contributor

sdeleuze commented Jan 2, 2017

Linked to #331, I think it could make sense to support Gradle builds written in Kotlin instead of Groovy.

I am experimenting on that for a few month, and it works pretty well, see for example mixit or spring-boot-kotlin-demo build.gradle.kts. As a bonus, that would be nice to make that the default for Kotlin project.

This feature is also valuable for Java projects since it provides full autocomplete and validation of Gradle builds unlike the Groovy variant.

This feature works with regular IntelliJ IDEA Kotlin plugin, but you need to use Kotlin 1.1 EAP plugin to get autocomplete and validation of your build file.

I plan to contribute this feature, that IMO makes sense as part of the Kotlin support provided by Spring Framework 5 (so a good fit with Spring Boot 2.0).

@snicoll
Copy link
Contributor

snicoll commented Jan 3, 2017

This comes with several challenges. Right now, the UI (and the metadata) offers a "Maven-based" or "Gradle-based" project/build. The introduction of Kotlin makes it a "flavor" of a build type for which we have no concept right now. I am not keen to introduce one.

Also, this would be really weird to offer a way to build a Kotlin-based build with Groovy and a Groovy-based build with Kotlin.

As things stand, I'd be in favor of waiting for it to become a bit more mainstream and use it when a Kotlin project type is created. We might do the same thing for Java type, probably later.

Any other opinion?

@snicoll snicoll added the status: waiting-for-feedback We need additional information before we can continue label Jan 3, 2017
@wilkinsona
Copy link
Contributor

Can we automatically generate a Kotlin-powered build.gradle.kts when the users selects Gradle as the build system and Kotlin as the language? That way we'd avoid another UI option at least.

@snicoll
Copy link
Contributor

snicoll commented Jan 3, 2017

Looks like I did a terrible job at phrasing my proposal. That's exactly what I meant.

@sdeleuze
Copy link
Contributor Author

sdeleuze commented Jan 3, 2017

Sure we could, but I tend to think it would be better to be explicit. From both user and Initilizr POV, Gradle Groovy and Gradle Kotlin are 2 distinct build systems.

Gradle Kotlin will be IMO quickly asked by Java users given the huge gain in term of autocomplete and validation. On the other way, some people creating Kotlin projects will still want to use Gradle Groovy flavor because for example it is the only thing supported in there company or they want to keep using something stable they know for a very long time.

The combo box allowing selecting the build system contain only 2 items (Maven and Gradle), so I would be for simply adding a Gradle Script Kotlin line, and eventually hide this line in the UI when Groovy and Java languages are selected. When we will consider this mature enough, we will be able to unlock Gradle Script Kotlin for Java projects.

Any thoughts?

@snicoll
Copy link
Contributor

snicoll commented Jan 3, 2017

Please, do not forget that Initiliazr has many clients and we should offer whatever customization we support to all of them. That idea of hiding stuff in the web ui is a big no no. This isn't just a line in a combo box, there is a meta-data element behind it. You need to convey that to remote clients as well.

Frankly, I'd be up to generate a Kotlin-based build with Kotlin only and see how folks react to that.

@sdeleuze
Copy link
Contributor Author

sdeleuze commented Jan 4, 2017

I will follow your recommandation, and I understand that you don't want to introduce some UI tricks, but doing another trick to generate a special Gradle Script Kotlin based build when Kotlin is the selected language seems to be the wrong path to me. How will we do when Java users will require such support? What will be our answer to users using Kotlin language but regular Gradle Groovy based build?

To me Gradle Script Kotlin (btw this name is likely to change before GA) is really another build system, and unlike in Maven World where polyglot Maven seems to stay niche, Gradle clearly said Gradle Script Kotlin is their long term default solution whatever language your use. So since Initializr supports already 2 ones, I still think we should add this as a 3rd regular one.

My hiding stuff proposal was more to provide an answer to your concern about Groovy language projects that don't want to see Gradle Script Kotlin as a build system. But IMO these are orthogonal concerns, I would just list the 3 build systems whatever language you choose, even if for sure Groovy langage project will likely to use more often regular Gradle Groovy builds and if Kotlin projects are more likely to use Gradle Script Kotlin.

Optionally, I could also contribute as a distinct issue/PR a feature that allows to specify in the metadata what is the default build tool for a specific language. In term of UI, we could select by default Groovy Gradle for Groovy project and Gradle Script Kotlin for Kotlin projects. In term of REST API that would enable to generate a project without specifying the build system in the request with the most popular one by default.

Any thoughts?

@fitzoh
Copy link

fitzoh commented Jan 5, 2017

Found my way here from some of the Kotlin blog posts.
Adding in Gradle Script Kotlin as a third build option seems like the simplest approach to me.
No changes to the web UI required, and it shouldn't require any updates to the intellij initializr screen either (which is where I normally use it).

I also want to say that I'm against automatically generating a Gradle Script Kotlin build file if Kotlin is selected as the language. That could potentially be pretty jarring/confusing for someone who knows gradle and is using initializr to get started with kotlin, especially if they weren't already aware that Gradle Script Kotlin exists.

@snicoll
Copy link
Contributor

snicoll commented Jan 6, 2017

Some more brainstorming with @sdeleuze

It looks like the consensus is to let the user chose the format of the build so we need a dedicated concept for it. We've discussed the possibility to have a third element in the first combo ("Generate a") with "Gradle" and "Gradle Kotlin" or something but I am really not a fan of the idea.

We still need to figure out how that would work UI wise for us but a third combo that lists the available format seems to be one way out. For Maven that would be XML and Gradle could have Groovy and Kotlin as options.

Metadata wise, we need a "format" concept with a label and links in each "type". Each type would also define a default "format".

The CLI can be upgraded to understand this new format, something like:

To create a web/data-jpa gradle Kotlin-based project unpacked:
        $ spring init -d=web,jpa --build=gradle --format=kotlin my-dir

IDEs that do not support the concept would just provide the usual parameters and the default format would apply for them. New versions could offer a selection for the available format and pass that along the request. Regardless, this change must be fully backward compatible with existing clients.

@bclozel @wilkinsona @dsyer (and anyone else watching here) thoughts?

@wilkinsona
Copy link
Contributor

Adding a format option feels overly complicated to me, particularly as it would only be applicable to Gradle (unless we're going to support polyglot Maven too). My vote would be for a third build option. Sorry, @snicoll

@dsyer
Copy link
Contributor

dsyer commented May 12, 2017

I agree with Andy. It's not going to get combinatorial - there are just a couple more options in the build format.

@wilkinsona
Copy link
Contributor

@bclozel @snicoll and I were discussing this a bit again today, and apparently I've changed my mind a bit from what I said in January.

I still dislike the format option, i.e. I don't want the main sentence to have a dropdown for Gradle/Maven or another for the build system format (Groovy/Kotlin for Gradle and, I guess, XML/Groovy for Maven).

In terms of the Web UI, I'd be quite happy to see one of:

  1. A single dropdown that offers Maven, Gradle (Groovy), and Gradle (Kotlin) in the main heading.
  2. The existing Maven/Gradle option in the main heading and an advanced option when Gradle is chosen for choosing Groovy or Kotlin.
  3. No option at all for choosing between Groovy or Kotlin and we just switch when Gradle Script Kotlin reaches a tipping point (if it fulfils its potential, I think reaching that tipping point is inevitable)

@snicoll
Copy link
Contributor

snicoll commented Jun 11, 2017

@bclozel @snicoll and I were discussing this a bit again today, and apparently I've changed my mind a bit from what I said in January.

Did you? Reading back your initial comment, 1. looks exactly like it to me.

@sdeleuze sdeleuze changed the title Support Gradle Script Kotlin builds Support Gradle Kotlin DSL Jun 19, 2017
@sdeleuze sdeleuze changed the title Support Gradle Kotlin DSL Support Gradle with Kotlin DSL Jun 19, 2017
@sdeleuze
Copy link
Contributor Author

More information about the new name: gradle/kotlin-dsl-samples#182 (comment).

@wilkinsona
Copy link
Contributor

Did you? Reading back your initial comment, 1. looks exactly like it to me.

Wow, ok, so I haven't changed my mind after all. Sorry for the noise.

@sdeleuze sdeleuze changed the title Support Gradle with Kotlin DSL Support Gradle Kotlin DSL Aug 16, 2017
@jhvhs
Copy link

jhvhs commented Feb 26, 2018

@snicoll @sdeleuze @wilkinsona Has this issue been forgotten?
Every time I start a project, I have to convert the build.gradle to build.gradle.kts
by hand. It probably does make sense to enable it by default for Kotlin projects.
E.g. if I'm creating a Kotlin project, I would prefer Kotlin gradle build files. Unlike
the groovy ones, they provide proper syntax support within IntelliJ.

On the other hand, I don't know whether eclipse/vim/other developers would
gain any value from that.

I'd be more than happy to contribute.

@sdeleuze
Copy link
Contributor Author

Before moving forward on this support on initializr side, I tend to think there is a point we should discuss with @wilkinsona and @snicoll.

Gradle Kotlin DSL makes almost mandatory to use the "new" Gradle plugins block instead of the current buildscript + apply plugin ones in order to generates static accessors that allow a syntax close to Groovy DSL.

Switching to plugins blocks could also be appealing for Groovy DSL users, since it seems to be best practice recommended by Gradle team. But I tend to consider gradle/gradle#3902 as a blocker for start.spring.io.

Any thoughts? What about creating a dedicated issue here to discuss migration to plugins block for Gradle builds (Groovy DSL for now, later Kotlin DSL as well) and contacting Gradle team to highlight that gradle/gradle#3902 is blocking us for both plugins and Kotlin DSL support?

@wilkinsona
Copy link
Contributor

I agree with your assessment, @sdeleuze. We need the, apparently arbitrary, -SNAPSHOT restriction to be removed before we can make progress here.

@snicoll snicoll added status: blocked and removed status: waiting-for-feedback We need additional information before we can continue labels Mar 12, 2018
@sdeleuze
Copy link
Contributor Author

I have dropped a note on Gradle side to mention this is blocking for us, and worked on what could look like the generated Gradle configuration using plugins { } block.

Gradle Groovy DSL

plugins {
	id 'java'
	id 'eclipse'
	id 'org.springframework.boot' version '2.0.0.RELEASE' 
	id 'io.spring.dependency-management' version '1.0.4.RELEASE'
}

// We could use `ext { }` but IMO better to be consistent and use brackets since dependency management requires this syntax due to the dot into the name
ext['springCloudVersion'] = 'Finchley.M8'

// Overriding dependency management
ext['jackson.version'] = '2.9.4'

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
	mavenCentral()
	maven { url "https://repo.spring.io/milestone" }
}

dependencies {
	compile('org.springframework.boot:spring-boot-starter-web')
	compile('org.springframework.cloud:spring-cloud-stream')
	testCompile('org.springframework.boot:spring-boot-starter-test')
	testCompile('org.springframework.cloud:spring-cloud-stream-test-support')
}

dependencyManagement {
	imports {
		mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
	}
}

Gradle Kotlin DSL

plugins {
	id("java")
	id ("eclipse")
	id("org.springframework.boot") version "2.0.0.RELEASE" 
	id("io.spring.dependency-management") version "1.0.4.RELEASE"
}

// For ext properties, we need to use `val springCloudVersion by extra("Finchley.M8")` syntax
// For just defining a local value, `val springCloudVersion = "Finchley.M8"` is enough
// See also https://github.com/gradle/kotlin-dsl/issues/678
val springCloudVersion = "Finchley.M8"

// Overriding dependency management
extra["jackson.version"] = "2.9.4"

group = "com.example"
version = "0.0.1-SNAPSHOT"

java {
    sourceCompatibility = JavaVersion.VERSION_1_8
}

repositories {
	mavenCentral()
	maven("https://repo.spring.io/milestone")
}

dependencies {
	compile("org.springframework.boot:spring-boot-starter-web")
	compile("org.springframework.cloud:spring-cloud-stream")
	testCompile("org.springframework.boot:spring-boot-starter-test")
	testCompile("org.springframework.cloud:spring-cloud-stream-test-support")
}

dependencyManagement {
	imports {
		mavenBom("org.springframework.cloud:spring-cloud-dependencies:$springCloudVersion")
	}
}

Properties management may evolve in Gradle Kotlin DSL before 1.0, see gradle/kotlin-dsl-samples#678.

@sdeleuze
Copy link
Contributor Author

I have sent a pull request that adds support for snapshot plugin version to Gradle.

After discussion with the Gradle team, it seems that Gradle Kotlin DSL will be usable from a performance POV (which is let's be honest a pain currently) as of Gradle 4.10 and IDEA 2018.2 by leveraging Kotlin 1.2.50 scripting improvements (among other things).

@sdavids
Copy link

sdavids commented Aug 28, 2018

https://docs.gradle.org/4.10/release-notes.html#use-snapshot-plugin-versions-with-the-plugins-%7B%7D-block

@eriwen
Copy link

eriwen commented Oct 11, 2018

I'm not sure what the current plan is here, but know that I am happy to contribute this given a bit of guidance.

@sdeleuze
Copy link
Contributor Author

sdeleuze commented Feb 15, 2019

Hey, quick summary to move forward. @eskatos contributed https://github.com/eskatos/start.spring.io-builds/tree/master/new-gradle-kotlin-dsl, which is a good starting point. Also regular Gradle builds now uses the new Gradle plugin thanks to the latest improvements shipped recently by the Boot team.

Could we agree on the design in order to allow me, another contributor from Gradle or the community to move forward on submitting a pull request?

Currently we have the following key -> value project types:

  • maven-project -> "Maven Project"
  • gradle-project -> "Gradle Project"

With Gradle Kotlin DSL support, I think I am still in favor of "just" introducing it as a new project type.

  • maven-project -> "Maven Project"
  • gradle-project -> "Gradle Project"
  • gradle-kts-project -> "Gradle Kotlin DSL Project"

@snicoll @wilkinsona Could you discuss that point to provide guidelines for those who will work on the pull request? Also since Gradle Kotlin DSL requires latest 5.x for first class support, do you plan to switch to Gradle 5.x at Boot 2.2 timeframe or should we use 5.x only for the Gradle Kotlin DSL?

@daggerok
Copy link

daggerok commented Feb 21, 2019

Hi all,

I'm very interested into this feature and would like to help here somehow.
Please let me know if I can do something valuable, like add proper **/build.gradle.kts.gen files, tests or anything else needed


Regards,
Maksim

@snicoll
Copy link
Contributor

snicoll commented Feb 27, 2019

@sdeleuze we've just discussed this one and there is an interest to have Kotlin DSL support for Gradle. We're aware of the work @eskatos has contributed (very helpful!).

We need to switch to Gradle 5 for Spring Boot 2.2, I've created #847. As for the implementation itself, I am not sure I understand what you'd like us to do upfront. If someone wants to work on this, they can join us on Gitter and we can take it from there.

@snicoll
Copy link
Contributor

snicoll commented May 20, 2019

Closing in favor of #851

@snicoll snicoll closed this as completed May 20, 2019
@snicoll snicoll removed this from the 0.8.0 milestone May 20, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants