Kotlin コードを実行する
オートメーション DSL は Kotlin に基づいているため、ジョブステップ内で任意の Kotlin コードを実行できます。コンテナーの場合は、コードを kotlinScript
ブロック内に置く必要があります。例:
job("Build and publish") {
container(displayName = "Run publish script", image = "gradle:6.1.1-jre11") {
kotlinScript { api ->
api.gradle("build")
try {
api.gradle("publish")
} catch (ex: Exception) {
println("Publishing failed")
}
}
}
}
内部での動作 (一部簡略化してあります): Space はスクリプトを .jar ファイルにコンパイルし、java -jar script.jar
のようなコマンドで実行します。これはスクリプトの実行に使用するイメージには JRE/JDK が含まれている必要があります (バージョン 11 以降) を意味します。
kotlinScript
ブロックは、さまざまなヘルパー API を提供します。
ビルドツールの使用 (現時点では Gradle のみ)。
ビルド関連の情報と機能へのアクセス: Git ブランチ、スクリプト実行番号の取得、ファイル共有へのアクセスなど。
Kotlin コードからさまざまな Space モジュール (チャット、ドキュメント、課題など) に直接アクセスします。詳細
API の完全なリストはここで参照してください。
以下の例では、api.gradlew()
を使用して Gradle ラッパーを使用してコマンドを実行し、api.gitBranch()
を使用して現在のブランチの名前を取得します。
job("Example") {
container(image = "gradle:7.1-jre11", displayName = "Use helper APIs") {
kotlinScript { api ->
api.gradlew("build")
// run publish task for release branches
if (api.gitBranch().contains("release")) {
api.gradlew("publish")
}
}
}
}
Maven ライブラリを使用する
kotlinScript
を使用すると、外部パッケージの関数を使用できます。これを行うには、@file:DependsOn("$package_name")
アノテーションを使用して必要なパッケージを参照する必要があります。$package_name
は、Maven セントラル(英語)で使用できるパッケージの名前です。
例: 次のスクリプトは、OkHttp クライアントを使用して example.com
のコンテンツを取得し、それをジョブのログに出力します。
@file:DependsOn("com.squareup.okhttp:okhttp:2.7.4")
import com.squareup.okhttp.*
job("Get example.com") {
container(image = "amazoncorretto:17-alpine") {
kotlinScript {
val client = OkHttpClient()
val request = Request.Builder().url("http://example.com").build()
val response = client.newCall(request).execute()
println(response)
}
}
}
Kotlin を最大限に活用する
オートメーションスクリプトの最も優れた点の 1 つは、フル機能の Kotlin を使用できることです。.space.kts
では、クラス、拡張メソッドの作成、コルーチンの使用などを行うことができます。
例: 次のジョブは、複数のファイル (ビルドアーティファクトなど) を HTTP 経由で外部サーバーにアップロードします。これには時間がかかる可能性があるため、ジョブは Kotlin コルーチンを使用してファイルを非同期的にアップロードします。
この例では Ktor HTTP クライアント(英語)を使用します。HTTP リクエストの送信に関する詳細。
@file:DependsOn("io.ktor:ktor-client-core:1.6.0",
"org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0",
"org.jetbrains.kotlinx:kotlinx-coroutines:0.19.2")
import io.ktor.client.*
import io.ktor.client.call.*
import io.ktor.client.request.*
import io.ktor.http.*
import java.io.File
import io.ktor.client.request.forms.*
import io.ktor.client.statement.*
import io.ktor.utils.io.core.*
import kotlinx.coroutines.async
import kotlinx.coroutines.runBlocking
job("Use Kotlin coroutines") {
container(image = "amazoncorretto:17-alpine", displayName = "Upload files to external server") {
// get auth token from a project secret
env["TOKEN"] = "{{ project:test-secret }}"
kotlinScript {
val url = "https://external-service.url/upload"
val token = System.getenv("TOKEN")
// generate random text files
// in real life, this could be build artifacts
println("Generating files...")
val files = FileGenerator.getTxtFiles(10, 100000, "log")
// run a coroutine
val client = HttpClient()
coroutineScope {
println("Starting upload...")
files.map { file ->
launch {
val response = client.uploadFile(url, token, file)
println("Response from server: ${response.body<String>()}")
}
}.joinAll()
}
}
}
}
// upload a file to a remote server
suspend fun HttpClient.uploadFile(url: String, authToken: String, file: File): HttpResponse {
return this.post("$url/$authToken") {
headers {
append("Authorization", "Bearer $authToken")
}
setBody(MultiPartFormDataContent(formData {
this.appendInput(
key = file.name, headers = Headers.build {
append(HttpHeaders.ContentDisposition, "filename=${file.name}")
}, size = file.length()
) {
buildPacket {
writeFully(file.readBytes())
}
}
}))
}
}
// put all file generation activity in one place
object FileGenerator {
// create text files with random content
// these files emulate output of a build script
fun getTxtFiles(numberOfFiles: Int, length: Int, name: String): List<File> {
return (0..numberOfFiles)
.map {
val file = File("$name$it.txt")
file.writeText(getRandomString(length))
file
}
}
private fun getRandomString(length: Int) : String {
val chars = ('A'..'Z') + ('a'..'z') + ('0'..'9')
return (1..length)
.map { chars.random() }
.joinToString("")
}
}