有兩種任務類型,可操作任務和生命週期任務。

Gradle 中的可操作任務是執行實際工作的任務,例如編譯程式碼。生命週期任務是不執行工作的任務。這些任務沒有動作,而是將可操作任務組合起來,並作為建置的目標

writing tasks 6

井然有序的生命週期任務設定可讓新使用者更輕鬆存取您的建置,並簡化與 CI 的整合。

生命週期任務

生命週期任務對於在使用者或機器(CI 與本機)之間區分工作特別有幫助。例如,本機上的開發人員可能不希望在每次變更時執行整個建置。

讓我們以標準的 app 為例,它套用 base 外掛程式。

Gradle base 外掛定義了幾個生命週期任務,包括 buildassemblecheck

我們透過將下列行加入 app 建置指令碼來將 buildcheck 任務和 run 任務分組

app/build.gradle.kts
tasks.build {
    group = myBuildGroup
}

tasks.check {
    group = myBuildGroup
    description = "Runs checks (including tests)."
}

tasks.named("run") {
    group = myBuildGroup
}
app/build.gradle
tasks.build {
    group = myBuildGroup
}

tasks.check {
    group = myBuildGroup
    description = "Runs checks (including tests)."
}

tasks.named('run') {
    group = myBuildGroup
}

如果我們現在查看 app:tasks 清單,我們可以看到這三個任務都可用

$ ./gradlew :app:tasks

> Task :app:tasks

------------------------------------------------------------
Tasks runnable from project ':app'
------------------------------------------------------------

My app build tasks
------------------
build - Assembles and tests this project.
check - Runs checks (including tests).
run - Runs this project as a JVM application
tasksAll - Show additional tasks.

如果標準生命週期任務已足夠,這已經很有用了。移動群組有助於釐清您預期在建置中使用的任務。

在許多情況下,有更多您想要處理的特定需求。一個常見的場景是在不執行測試的情況下執行品質檢查。目前,:check 任務會執行測試和程式碼品質檢查。我們想要隨時執行程式碼品質檢查,但不要執行冗長的測試。

若要新增品質檢查生命週期任務,我們會引入一個稱為 qualityCheck 的額外生命週期任務和一個稱為 spotbugs 的外掛。

若要新增生命週期任務,請使用 tasks.register()。您只需要提供一個名稱。將此任務放入我們的群組中,並使用 dependsOn() 方法連接屬於此新生命週期任務的可執行動作任務

app/build.gradle.kts
plugins {
    id("com.github.spotbugs") version "6.0.7"           // spotbugs plugin
}

tasks.register("qualityCheck") {                        // qualityCheck task
    group = myBuildGroup                                // group
    description = "Runs checks (excluding tests)."      // description
    dependsOn(tasks.classes, tasks.spotbugsMain)        // dependencies
    dependsOn(tasks.testClasses, tasks.spotbugsTest)    // dependencies
}
app/build.gradle
plugins {
    id 'com.github.spotbugs' version '6.0.7'            // spotbugs plugin
}

tasks.register('qualityCheck') {                        // qualityCheck task
    group = myBuildGroup                                // group
    description = 'Runs checks (excluding tests).'      // description
    dependsOn tasks.classes, tasks.spotbugsMain         // dependencies
    dependsOn tasks.testClasses, tasks.spotbugsTest     // dependencies
}

請注意,您不需要列出 Gradle 將執行的所有任務。只要在此處指定您想要收集的目標即可。Gradle 將確定它需要呼叫哪些其他任務才能達成這些目標。

在範例中,我們新增 classes 任務(一個編譯所有生產程式碼的生命週期任務)和 spotbugsMain 任務(檢查我們的生產程式碼)。

我們還會新增一個說明,它會顯示在任務清單中,有助於更好地區分兩個檢查任務。

現在,如果執行 './gradlew :app:tasks',我們可以看到我們的 qualityCheck 新生命週期任務可用

$ ./gradlew :app:tasks

> Task :app:tasks

------------------------------------------------------------
Tasks runnable from project ':app'
------------------------------------------------------------

My app build tasks
------------------
build - Assembles and tests this project.
check - Runs checks (including tests).
qualityCheck - Runs checks (excluding tests).
run - Runs this project as a JVM application
tasksAll - Show additional tasks.

如果我們執行它,我們可以看到它會執行 checkstyle,但不會執行測試

$ ./gradlew :app:qualityCheck

> Task :buildSrc:checkKotlinGradlePluginConfigurationErrors
> Task :buildSrc:generateExternalPluginSpecBuilders UP-TO-DATE
> Task :buildSrc:extractPrecompiledScriptPluginPlugins UP-TO-DATE
> Task :buildSrc:compilePluginsBlocks UP-TO-DATE
> Task :buildSrc:generatePrecompiledScriptPluginAccessors UP-TO-DATE
> Task :buildSrc:generateScriptPluginAdapters UP-TO-DATE
> Task :buildSrc:compileKotlin UP-TO-DATE
> Task :buildSrc:compileJava NO-SOURCE
> Task :buildSrc:compileGroovy NO-SOURCE
> Task :buildSrc:pluginDescriptors UP-TO-DATE
> Task :buildSrc:processResources UP-TO-DATE
> Task :buildSrc:classes UP-TO-DATE
> Task :buildSrc:jar UP-TO-DATE
> Task :app:processResources NO-SOURCE
> Task :app:processTestResources NO-SOURCE
> Task :list:compileJava UP-TO-DATE
> Task :utilities:compileJava UP-TO-DATE
> Task :app:compileJava
> Task :app:classes
> Task :app:compileTestJava
> Task :app:testClasses
> Task :app:spotbugsTest
> Task :app:spotbugsMain
> Task :app:qualityCheck

BUILD SUCCESSFUL in 1s
16 actionable tasks: 5 executed, 11 up-to-date

到目前為止,我們已經查看了個別子專案中的任務,這對於您在一個子專案中處理程式碼時進行本地開發很有用。

有了這個設定,開發人員只需要知道他們可以使用 :subproject-name:tasks 呼叫 Gradle,就能查看對他們來說有哪些可用且有用的工作。

全域生命週期工作

另一個呼叫生命週期工作的場合是在根目錄建置中;這對於持續整合 (CI) 來說特別有用。

Gradle 工作在 CI 或 CD 系統中扮演著至關重要的角色,這些系統通常會執行編譯所有程式碼、執行測試或建置和封裝完整應用程式的活動。為了達成此目的,您可以納入跨越多個子專案的生命週期工作。

Gradle 已經存在很長一段時間,您會經常看到根目錄中的建置檔案用於各種目的。在較舊的 Gradle 版本中,許多工作都是在根目錄 Gradle 建置檔案中定義的,這會導致各種問題。因此,在決定這個檔案的內容時要小心謹慎。

應該放在根目錄建置檔案中的少數元素之一就是全域生命週期工作。

讓我們繼續使用 Gradle init Java 應用程式多專案作為範例。

這次,我們在根專案中加入建置指令碼。我們會為全域生命週期工作建立兩個群組:一個是與在地開發相關的工作,例如執行所有檢查,另一個則專門用於我們的 CI 系統。

我們再次將列出的工作縮小到我們特定的群組

build.gradle.kts
val globalBuildGroup = "My global build"
val ciBuildGroup = "My CI build"

tasks.named<TaskReportTask>("tasks") {
    displayGroups = listOf<String>(globalBuildGroup, ciBuildGroup)
}
build.gradle
def globalBuildGroup = "My global build"
def ciBuildGroup = "My CI build"

tasks.named(TaskReportTask, "tasks") {
    displayGroups = [globalBuildGroup, ciBuildGroup]
}

如果您想隱藏 CI 工作,您可以透過更新 displayGroups 來執行。

目前,根專案沒有公開任何工作

$ ./gradlew :tasks

> Task :tasks

------------------------------------------------------------
Tasks runnable from root project 'gradle-project'
------------------------------------------------------------

No tasks
在這個檔案中,我們沒有套用外掛程式!

讓我們新增一個 qualityCheckApp 工作,在 app 子專案中執行所有程式碼品質檢查。類似地,對於 CI 目的,我們實作一個 checkAll 工作,執行所有測試

build.gradle.kts
tasks.register("qualityCheckApp") {
    group = globalBuildGroup
    description = "Runs checks on app (globally)"
    dependsOn(":app:qualityCheck" )
}

tasks.register("checkAll") {
    group = ciBuildGroup
    description = "Runs checks for all projects (CI)"
    dependsOn(subprojects.map { ":${it.name}:check" })
    dependsOn(gradle.includedBuilds.map { it.task(":checkAll") })
}
build.gradle
tasks.register("qualityCheckApp") {
    group = globalBuildGroup
    description = "Runs checks on app (globally)"
    dependsOn(":app:qualityCheck")
}

tasks.register("checkAll") {
    group = ciBuildGroup
    description = "Runs checks for all projects (CI)"
    dependsOn subprojects.collect { ":${it.name}:check" }
    dependsOn gradle.includedBuilds.collect { it.task(":checkAll") }
}

因此,我們現在可以要求 Gradle 為我們顯示根專案的工作,而且預設情況下,它只會向我們顯示 qualityCheckAll 工作(以及根據 displayGroups 的值,選擇性地顯示 checkAll 工作)。

使用者應該在本地端執行什麼應該很清楚

$ ./gradlew :tasks

> Task :tasks

------------------------------------------------------------
Tasks runnable from root project 'gradle-project'
------------------------------------------------------------

My CI build tasks
-----------------
checkAll - Runs checks for all projects (CI)

My global build tasks
---------------------
qualityCheckApp - Runs checks on app (globally)

如果我們執行 :checkAll 工作,我們會看到它編譯所有程式碼並執行程式碼品質檢查(包括 spotbug

$ ./gradlew :checkAll

> Task :buildSrc:checkKotlinGradlePluginConfigurationErrors
> Task :buildSrc:generateExternalPluginSpecBuilders UP-TO-DATE
> Task :buildSrc:extractPrecompiledScriptPluginPlugins UP-TO-DATE
> Task :buildSrc:compilePluginsBlocks UP-TO-DATE
> Task :buildSrc:generatePrecompiledScriptPluginAccessors UP-TO-DATE
> Task :buildSrc:generateScriptPluginAdapters UP-TO-DATE
> Task :buildSrc:compileKotlin UP-TO-DATE
> Task :buildSrc:compileJava NO-SOURCE
> Task :buildSrc:compileGroovy NO-SOURCE
> Task :buildSrc:pluginDescriptors UP-TO-DATE
> Task :buildSrc:processResources UP-TO-DATE
> Task :buildSrc:classes UP-TO-DATE
> Task :buildSrc:jar UP-TO-DATE
> Task :utilities:processResources NO-SOURCE
> Task :app:processResources NO-SOURCE
> Task :utilities:processTestResources NO-SOURCE
> Task :app:processTestResources NO-SOURCE
> Task :list:compileJava
> Task :list:processResources NO-SOURCE
> Task :list:classes
> Task :list:jar
> Task :utilities:compileJava
> Task :utilities:classes
> Task :utilities:jar
> Task :utilities:compileTestJava NO-SOURCE
> Task :utilities:testClasses UP-TO-DATE
> Task :utilities:test NO-SOURCE
> Task :utilities:check UP-TO-DATE
> Task :list:compileTestJava
> Task :list:processTestResources NO-SOURCE
> Task :list:testClasses
> Task :app:compileJava
> Task :app:classes
> Task :app:compileTestJava
> Task :app:testClasses
> Task :list:test
> Task :list:check
> Task :app:test
> Task :app:spotbugsTest
> Task :app:spotbugsMain
> Task :app:check
> Task :checkAll

BUILD SUCCESSFUL in 1s
21 actionable tasks: 12 executed, 9 up-to-date