Task adalah unit kerja utama di Gradle. Setiap kali kita menjalankan ./gradlew build, sekitar 20-30 task dijalankan secara berurutan: kompilasi, test, validasi, packaging. Memahami daftar task yang tersedia, cara menulis task custom, serta perbedaan doLast dan doFirst menjadi modal untuk mengotomasi langkah-langkah khusus seperti generate kode, menjalankan script, atau mengemas artefak. Pada chapter ini kita akan membahas task bawaan plugin Kotlin, custom task, serta cara mengirim parameter lewat command line.

Task Bawaan Plugin Kotlin #

Plugin kotlin("jvm") (bersama plugin java yang otomatis diterapkan) menambah task-task berikut:

TaskTujuan
compileKotlinKompilasi src/main/kotlin → build/classes/kotlin/main
compileTestKotlinKompilasi src/test/kotlin
compileJavaKompilasi src/main/java (bila ada)
processResourcesSalin src/main/resources ke build/resources/main
testJalankan unit test via JUnit Platform
jarKemas class + resources → build/libs/<nama>-<versi>.jar
assembleAgregat task packaging (dependsOn jar)
checkAgregat task verifikasi (dependsOn test)
buildAgregat: assemble + check
cleanHapus build/

Untuk melihat daftar lengkap task di proyek, jalankan ./gradlew tasks --group kotlin atau ./gradlew tasks --all.

Custom Task #

Task custom dideklarasikan dengan tasks.register(...). Lambda yang diberikan dijalankan saat configuration phase; aksi aktual didefinisikan di blok doLast (atau doFirst) yang dijalankan saat execution phase.

kotlin build.gradle.kts — custom task
tasks.register("hello") {
    group = "demo"
    description = "Mencetak salam ke konsol"
    doLast {
        println("Halo dari task hello")
    }
}

Setelah mendaftarkan task, kita dapat memanggilnya dengan:

bash
./gradlew hello

doLast vs doFirst #

Setiap task memiliki list of actions. Saat task dijalankan, Gradle mengeksekusi actions dalam urutan: pertama semua doFirst, lalu actions default (mis. copy untuk task Copy), lalu semua doLast. Kedua blok ini menerima lambda yang dijalankan saat execution phase.

kotlin doFirst / doLast
tasks.register("urutanDemo") {
    doLast {
        println("[doLast 1] berjalan paling akhir")
    }
    doFirst {
        println("[doFirst 1] berjalan paling awal")
    }
    doLast {
        println("[doLast 2] berjalan sebelum doLast 1")
    }
}

Urutan eksekusi: doFirst 1 → doLast 2 → doLast 1. Pola ini berguna saat kita perlu hook sebelum atau sesudah aksi default sebuah task bawaan.

Demonstrasi Task Gradle #

Kode berikut mencantumkan task bawaan plugin Kotlin serta contoh deklarasi custom task sebagai referensi.

kotlin
fun main() {
    println("=== Demo Task Gradle ===")
    println()
    println("Task bawaan plugin Kotlin:")
    println("  compileKotlin       : kompilasi src/main/kotlin")
    println("  compileTestKotlin   : kompilasi src/test/kotlin")
    println("  test                : jalankan seluruh unit test (JUnit Platform)")
    println("  jar                 : kemas class + resources ke build/libs/*.jar")
    println("  build               : agregat: assemble + check")
    println("  clean               : hapus direktori build/")
    println()
    println("Custom task sederhana:")
    println("  tasks.register(\"hello\") {")
    println("      doLast { println(\"Halo dari task hello\") }")
    println("  }")
    println()
    println("Eksekusi:")
    println("  ./gradlew hello         -> \"Halo dari task hello\"")
    println("  ./gradlew hello --quiet  -> hanya output task")
    println()
    println("Task berparameter (input):")
    println("  tasks.register(\"sapa\") {")
    println("      val nama = providers.gradleProperty(\"nama\").getOrElse(\"Budi\")")
    println("      doLast { println(\"Halo, \$nama!\") }")
    println("  }")
    println("  ./gradlew sapa -Pnama=Siti    -> \"Halo, Siti!\"")
}

Output yang Dihasilkan:

text
=== Demo Task Gradle ===

Task bawaan plugin Kotlin:
  compileKotlin       : kompilasi src/main/kotlin
  compileTestKotlin   : kompilasi src/test/kotlin
  test                : jalankan seluruh unit test (JUnit Platform)
  jar                 : kemas class + resources ke build/libs/*.jar
  build               : agregat: assemble + check
  clean               : hapus direktori build/

Custom task sederhana:
  tasks.register("hello") {
      doLast { println("Halo dari task hello") }
  }

Eksekusi:
  ./gradlew hello         -> "Halo dari task hello"
  ./gradlew hello --quiet  -> hanya output task

Task berparameter (input):
  tasks.register("sapa") {
      val nama = providers.gradleProperty("nama").getOrElse("Budi")
      doLast { println("Halo, $nama!") }
  }
  ./gradlew sapa -Pnama=Siti    -> "Halo, Siti!"

Mari kita telaah kode di atas:

  1. Daftar task bawaan: setiap baris menjelaskan satu task. Pembaca dapat memverifikasi di proyek mereka dengan ./gradlew tasks.
  2. tasks.register("hello"): deklarasi task custom. Lambda konfigurasi dijalankan saat configuration phase; lambda doLast dijalankan saat task di-execute.
  3. --quiet: flag Gradle yang menekan log non-task. Berguna saat output task adalah satu-satunya yang penting (mis. untuk parsing CI).
  4. providers.gradleProperty("nama"): API lazy yang membaca properti -Pnama=.... getOrElse memberi nilai default bila properti tidak diberikan.

Task Berparameter (Input) #

Untuk menerima input dari command line, Gradle menyediakan dua mekanisme:

  • -Pkey=value: properti proyek; dibaca dengan providers.gradleProperty("key") atau project.findProperty("key").
  • -Dkey=value: properti sistem (JVM); dibaca dengan System.getProperty("key") di dalam task.
kotlin build.gradle.kts — task berparameter
tasks.register("cetakInfo") {
    val env = providers.gradleProperty("env").getOrElse("dev")
    val debug = providers.gradleProperty("debug").orElse("false").get().toBoolean()
    doLast {
        println("Environment: $env")
        println("Debug mode: $debug")
    }
}

Eksekusi: ./gradlew cetakInfo -Penv=prod -Pdebug=true.

Task dengan Input/Output Deklaratif #

Untuk task yang menghasilkan file, deklarasikan inputs dan outputs agar Gradle dapat memeriksa up-to-date:

kotlin Task dengan input/output
tasks.register("generateVersion") {
    val outputFile = layout.buildDirectory.file("generated/version.txt")
    outputs.file(outputFile)  // untuk up-to-date checking

    doLast {
        outputFile.get().asFile.apply {
            parentFile.mkdirs()
            writeText("version=${project.version}")
        }
    }
}

Saat task dijalankan ulang tanpa perubahan, Gradle mencetak UP-TO-DATE dan melewati eksekusi.

Penyusunan Dependensi Task #

Task dapat bergantung satu sama lain via dependsOn:

kotlin
tasks.register("buildAll") {
    dependsOn("clean", "build")
}

Saat ./gradlew buildAll dijalankan, Gradle menjalankan clean dan build sesuai urutan dependensi yang ditentukan DAG-nya.

Referensi Lanjutan #

  • Gradle — panduan resmi Kotlin + Gradle untuk mendefinisikan task kustom di build.gradle.kts
  • Gradle User Guide — buku panduan Gradle yang merinci task API, input/output, dan up-to-date checking

Penutup #

Task adalah unit komposisi build Gradle. Kombinasi task bawaan plugin Kotlin dengan task custom memungkinkan kita mengotomasi langkah apa pun yang dibutuhkan proyek. Pada chapter berikutnya kita akan menelusuri lifecycle build Gradle secara mendalam: kapan configuration phase berjalan, kapan execution phase dijalankan, serta cara kerja up-to-date checking.