Managing tasks to Kotlin

Managing tasks to Kotlin

666ef10ec14e5a23d0fcf05bd2665575?s=128

rejasupotaro

June 21, 2017
Tweet

Transcript

  1. Managing tasks to Kotlin Kentaro Takiguchi @rejasupotaro

  2. About me • Kentaro Takiguchi @ Cookpad • Visited Asian

    countries, US, Middle East, Europe, … => Settle down to a new life in UK
  3. None
  4. My motivation of automation • This project is unique and

    challenging (= fun) • Product: Cultural difference, linguistic difference, … • Development: Remote team, different opinions and backgrounds, … • Many problems I want to solve => I want to make myself more productive
  5. A day of mine • Have coffee • Code review

    • Talk about technical issues • Talk about hiring • Lunch • Write code • Work on translation • Release • Monitor errors • Analyze logs • Create slides • Go to gym • Write a blog post
  6. How much time can you take only for coding?

  7. Make machines work instead of humans • Report lint warnings

    instead members review code carefully and leave comments on GitHub • Display test coverage on each PR to encourage members to write tests instead of saying “please add tests” • Download/Upload translation instead members open a translation tool and click some buttons
  8. Task manegement was chaos • Make, Rake, … Gradle? •

    How it’s managed depends on the project • How about your project?
  9. How to manage tasks • Rake > Gradle? • There

    are many gems such as Fastlane, GitHub, DeployGate, OneSky, Slack… • Gradle • We can (have to) choose from Java or Groovy • There are few plugins/libraries • But…
  10. None
  11. It changed my mind • We have to choose from

    Java or Groovy • => Now Kotlin is a realistic option • There are few plugins/libraries • => Opportunity
  12. It’s a good time to learn Gradle tasks

  13. Gradle • Build automation system • Gradle uses a directed

    a cyclic graph (DAG) to determine the order of tasks • Stable release: 4.0 • Gradle’s Build Cache is now production-ready which makes Gradle builds up to 100x faster than Maven
  14. 1. Build script (Groovy) 2. buildSrc (JVM languages) 3. Standalone

    project (JVM languages) How to define Gradle tasks
  15. Build script • Define tasks directly in the build.gradle •

    The task class is automatically compiled and included in the class path of the build script • The task class is not visible outside the build script
  16. Method 1-1 // app/build.gradle
 task yourTaskName {
 doLast { //

    What you want to do
 }
 }
  17. Method 1-1 // app/build.gradle
 task hello {
 doLast { println

    “Hello”
 }
 } ./gradlew hello => “Hello”
  18. Method 1-2 // app/build.gradle task("hello") {
 doLast {
 println "Hello"


    }
 }
  19. Method 1-3 // app/build.gradle tasks.create(name: “hello”) {
 doLast {
 println

    "hello"
 }
 }
  20. Method 1-4 // app/build.gradle
 task hello(type: HelloTask) 
 class HelloTask

    extends DefaultTask {
 @TaskAction
 def hello() {
 println “Hello”
 }
 }
  21. None
  22. Many ways… • No need to remember everything but should

    unify how to define tasks in the same project • We have to write tasks in Groovy when we go with 1. Build script
  23. buildSrc project • Define the task class in `rootProject/buildSrc` •

    Gradle will take care of compiling and testing the task class and making it available on the class path of the build script
  24. buildSrc project 1. Create buildSrc directory 2. Add `build.gradle` 3.

    Create `src/main/groovy/your/package/ HelloTask.groovy`
  25. Method 2 (Groovy) // app/build.gradle task hello(type: HelloTask) // buildSrc/src/main/groovy/your/package/HelloTask.groovy


    class HelloTask extends DefaultTask {
 @TaskAction
 def hello() {
 println(“Hello”)
 }
 }
  26. Method 2 (Java) // app/build.gradle task hello(type: HelloTask) // buildSrc/src/main/java/your/package/HelloTask.java

    public class HelloTask extends DefaultTask {
 @TaskAction
 def hello() {
 System.out.println(“Hello”)
 }
 }
  27. Method 2 (Kotlin) // app/build.gradle task hello(type: HelloTask) // buildSrc/src/main/kotlin/your/package/HelloTask.kt

    open class HelloTask : DefaultTask() {
 @TaskAction
 fun hello() {
 println(“Hello”)
 }
 }
  28. Write tests for buildSrc class HelloTaskTest {
 @Test
 fun hello()

    {
 val project = ProjectBuilder.builder().build()
 val task = project.task("hello")
 assertTrue(task is HelloTask)
 }
 }
  29. Isn’t it better than 1. Build script? • We can

    write Kotlin • We can test • It’s still unavailable outside the project
  30. Standalone project = Gradle Plugin • This project produces and

    publishes a JAR which you can use in multiple builds and share with others • The JAR might bundle several related task classes into a single library
  31. How to write Gradle Plugin in Kotlin 1. Create Java

    library project 2. Apply “Convert Java File to Kotlin File” 3. Add properties file 4. Define Plugin 5. Add tasks (We already known!) 6. Add tests (We already known!) 7. Publish
  32. 3. Add properties file

  33. 4. Define Plugin // plugin/src/main/kotlin/your/package/HelloPlugin.kt class YourPlugin : Plugin<Project> {


    override fun apply(project: Project) {
 with(project) {
 extensions.create(“yourExtension", YourExtension::class.java)
 tasks.create("yourTask1", YourTask1::class.java)
 tasks.create("yourTask2", YourTask2::class.java)
 tasks.create("yourTask3", YourTask3::class.java)
 }
 }
 }
  34. Create extension (if needed) // plugin/src/main/kotlin/your/package/HelloPlugin.kt class YourPlugin : Plugin<Project>

    {
 override fun apply(project: Project) {
 with(project) {
 extensions.create(“yourExtension", YourExtension::class.java)
 tasks.create("yourTask1", YourTask1::class.java)
 tasks.create("yourTask2", YourTask2::class.java)
 tasks.create("yourTask3", YourTask3::class.java)
 }
 }
 }
  35. Extension open class OneskyExtension {
 var apiKey: String = ""


    var apiSecret: String = ""
 var projectId: Int = 0
 var locales: Set<String> = setOf()
 
 fun locales(locales: Array<String>) {
 this.locales = locales.toSet()
 }
 } // app/build.gradle onesky {
 apiKey oneskyApiKey
 apiSecret oneskyApiSecret
 projectId oneskyProjectId locales “es”, “ar”, …
 }
  36. 5. Add tasks // plugin/src/main/kotlin/your/package/HelloPlugin.kt class YourPlugin : Plugin<Project> {


    override fun apply(project: Project) {
 with(project) {
 extensions.create(“yourExtension", YourExtension::class.java)
 tasks.create("yourTask1", YourTask1::class.java)
 tasks.create("yourTask2", YourTask2::class.java)
 tasks.create("yourTask3", YourTask3::class.java)
 }
 }
 }
  37. 5. Add tasks We can reuse // app/build.gradle apply plugin:

    ”your.plugin” // plugin/src/main/kotlin/your/package/HelloTask.kt open class HelloTask : DefaultTask() {
 @TaskAction
 fun hello() {
 println(“Hello”) }
 }
  38. 6. Add tests We can reuse class HelloTaskTest {
 @Test


    fun hello() {
 val project = ProjectBuilder.builder().build()
 val task = project.task("hello")
 assertTrue(task is HelloTask)
 }
 }
  39. 1. Create Java library project 2. Convert to Kotlin 3.

    Add properties file 4. Define Plugin 5. Add tasks 6. Add tests 7. Publish 1. Build script 2. buildSrc 3. Standalone project 1. Create buildSrc directory 2. Add `build.gradle` 3. Add tasks 4. (Add tests) 1. Add tasks
  40. It depends on your requirement • 1. Build script: I

    would recommend this only for small tasks • 2. buildSrc project: Suitable for project specific tasks • 3. Standalone project: You can use in multiple builds and share with other projects
  41. Gradle Script Kotlin Could be an option? • Could be

    when it becomes stable • We would be able to write tasks in Kotlin in `build.gradle.kts`
  42. 1. Build script (Kotlin) 2. buildSrc (Kotlin) 3. Standalone project

    (Kotlin) Everything is Kotlin app (Kotlin)
  43. Everything is Kotlin

  44. Off topic: Kotin migration of Cookpad Started migrating Java to

    Kotlin 2016/11 2017/5 40% done Migrated from Rake to Gradle 2017/6 Migrated tests 2016/12
  45. Kentaro Takiguchi @rejasupotaro Let’s automate Thank you for listening!