Slide 1

Slide 1 text

Managing tasks to Kotlin Kentaro Takiguchi @rejasupotaro

Slide 2

Slide 2 text

About me • Kentaro Takiguchi @ Cookpad • Visited Asian countries, US, Middle East, Europe, … => Settle down to a new life in UK

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

How much time can you take only for coding?

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

Task manegement was chaos • Make, Rake, … Gradle? • How it’s managed depends on the project • How about your project?

Slide 9

Slide 9 text

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…

Slide 10

Slide 10 text

No content

Slide 11

Slide 11 text

It changed my mind • We have to choose from Java or Groovy • => Now Kotlin is a realistic option • There are few plugins/libraries • => Opportunity

Slide 12

Slide 12 text

It’s a good time to learn Gradle tasks

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

1. Build script (Groovy) 2. buildSrc (JVM languages) 3. Standalone project (JVM languages) How to define Gradle tasks

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

Method 1-2 // app/build.gradle task("hello") {
 doLast {
 println "Hello"
 }
 }

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

Method 1-4 // app/build.gradle
 task hello(type: HelloTask) 
 class HelloTask extends DefaultTask {
 @TaskAction
 def hello() {
 println “Hello”
 }
 }

Slide 21

Slide 21 text

No content

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

buildSrc project 1. Create buildSrc directory 2. Add `build.gradle` 3. Create `src/main/groovy/your/package/ HelloTask.groovy`

Slide 25

Slide 25 text

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”)
 }
 }

Slide 26

Slide 26 text

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”)
 }
 }

Slide 27

Slide 27 text

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”)
 }
 }

Slide 28

Slide 28 text

Write tests for buildSrc class HelloTaskTest {
 @Test
 fun hello() {
 val project = ProjectBuilder.builder().build()
 val task = project.task("hello")
 assertTrue(task is HelloTask)
 }
 }

Slide 29

Slide 29 text

Isn’t it better than 1. Build script? • We can write Kotlin • We can test • It’s still unavailable outside the project

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

3. Add properties file

Slide 33

Slide 33 text

4. Define Plugin // plugin/src/main/kotlin/your/package/HelloPlugin.kt class YourPlugin : Plugin {
 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)
 }
 }
 }

Slide 34

Slide 34 text

Create extension (if needed) // plugin/src/main/kotlin/your/package/HelloPlugin.kt class YourPlugin : Plugin {
 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)
 }
 }
 }

Slide 35

Slide 35 text

Extension open class OneskyExtension {
 var apiKey: String = ""
 var apiSecret: String = ""
 var projectId: Int = 0
 var locales: Set = setOf()
 
 fun locales(locales: Array) {
 this.locales = locales.toSet()
 }
 } // app/build.gradle onesky {
 apiKey oneskyApiKey
 apiSecret oneskyApiSecret
 projectId oneskyProjectId locales “es”, “ar”, …
 }

Slide 36

Slide 36 text

5. Add tasks // plugin/src/main/kotlin/your/package/HelloPlugin.kt class YourPlugin : Plugin {
 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)
 }
 }
 }

Slide 37

Slide 37 text

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”) }
 }

Slide 38

Slide 38 text

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)
 }
 }

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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`

Slide 42

Slide 42 text

1. Build script (Kotlin) 2. buildSrc (Kotlin) 3. Standalone project (Kotlin) Everything is Kotlin app (Kotlin)

Slide 43

Slide 43 text

Everything is Kotlin

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

Kentaro Takiguchi @rejasupotaro Let’s automate Thank you for listening!