diff --git a/build.gradle.kts b/build.gradle.kts index a3b640a4..ca674f5f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,16 +1,15 @@ -import org.jetbrains.dokka.gradle.DokkaTask -import java.net.URL import com.code42.version.Version +import com.diffplug.gradle.spotless.SpotlessExtension +import org.jetbrains.dokka.gradle.DokkaTask -val kotlinVersion = "1.9.22" +val kotlinVersion = "1.9.23" plugins { base - kotlin("jvm") version "1.9.22" + kotlin("jvm") version "1.9.23" id("idea") - // maven plugin removed (invalid here) `maven-publish` - // Spotless plugin disabled + id("com.diffplug.spotless").version("6.25.0") id("org.jetbrains.dokka").version("1.9.0") id("io.gitlab.arturbosch.detekt").version("1.23.0") jacoco @@ -21,43 +20,68 @@ val baseProjectName = "pipelinekt" val publishedProjects = listOf("core", "internal", "dsl") val activeProjects = publishedProjects +val ktlintVersion = "1.1.1" +val kotlinRules = mapOf( + "max_line_length" to "150", +) + allprojects { group = "com.code42" version = Version.getVersion() repositories { mavenCentral() + maven { url = uri("https://jitpack.io") } } -} -tasks.named("dokkaGfm") { - outputDirectory.set(file("${project.rootDir}/docs/dokka")) - dokkaSourceSets { - named("main") { - sourceLink { - localDirectory.set(file("./")) - remoteUrl.set(URL("https://github.com/$githubRepo/tree/master")) - remoteLineSuffix.set("#L") - } + tasks.withType { + kotlinOptions { + jvmTarget = "17" // Using JDK 17 which is supported by detekt } } + + tasks.withType { + sourceCompatibility = "17" + targetCompatibility = "17" + } +} + +// Root-level spotless configuration +spotless { + kotlin { + target("**/*.kt") + ktlint(ktlintVersion).editorConfigOverride(kotlinRules) + trimTrailingWhitespace() + endWithNewline() + } + kotlinGradle { + target("**/*.gradle.kts") + ktlint(ktlintVersion).editorConfigOverride(kotlinRules) + trimTrailingWhitespace() + endWithNewline() + } } tasks { - register("incrementVersion") { + create("incrementVersion") { doLast { Version.incrementVersion() } } } -tasks.build { - finalizedBy("dokkaGfm") +tasks.named("build") { + // Don't finalize with dokka as it's a top-level task that doesn't exist + // finalizedBy("dokka") } subprojects { apply(plugin = "org.jetbrains.kotlin.jvm") + if (!base.archivesName.get().startsWith("pipelinekt-")) { + base.archivesName.set("pipelinekt-${base.archivesName.get()}") + } + dependencies { implementation(kotlin("stdlib-jdk8", kotlinVersion)) implementation(kotlin("reflect", kotlinVersion)) @@ -65,23 +89,18 @@ subprojects { testImplementation("org.jetbrains.kotlin:kotlin-test-junit") } - java { - toolchain { - languageVersion.set(JavaLanguageVersion.of(21)) + // Skip the example module for spotless check + if (project.name == "examples") { + tasks.withType { + enabled = false } } - tasks.withType { - kotlinOptions { - jvmTarget = "21" - } - } - tasks.withType { // Temporarily disable tests until we update them enabled = false } - + tasks.withType { if (this.name.contains("Test")) { enabled = false @@ -89,23 +108,59 @@ subprojects { } if (publishedProjects.contains(project.name)) { - apply(plugin = "org.gradle.maven-publish") - // Spotless fully disabled + apply(plugin = "org.gradle.maven-publish") + apply(plugin = "com.diffplug.spotless") apply(plugin = "io.gitlab.arturbosch.detekt") apply(plugin = "org.gradle.jacoco") apply(plugin = "org.jetbrains.dokka") - val sourcesJar by tasks.registering(Jar::class) { + configure { + kotlin { + target("src/**/*.kt") + ktlint(ktlintVersion).editorConfigOverride(kotlinRules) + trimTrailingWhitespace() + endWithNewline() + } + kotlinGradle { + target("*.gradle.kts") + ktlint(ktlintVersion).editorConfigOverride(kotlinRules) + trimTrailingWhitespace() + endWithNewline() + } + } + + val sourcesJar by tasks.creating(Jar::class) { archiveClassifier.set("sources") from(sourceSets.main.get().allSource) } jacoco { - toolVersion = "0.8.10" + toolVersion = "0.8.7" + } + + tasks.register("dokkaKdoc", org.jetbrains.dokka.gradle.DokkaTask::class) { + outputDirectory.set(file("$buildDir/kdoc")) + dokkaSourceSets { + named("main") { + sourceLink { + localDirectory.set(file("./")) + remoteUrl.set(uri("https://github.com/$githubRepo/tree/master").toURL()) + remoteLineSuffix.set("#L") + } + } + } + } + + val kdocJar by tasks.creating(Jar::class) { + group = JavaBasePlugin.DOCUMENTATION_GROUP + dependsOn(tasks.named("dokkaKdoc")) + archiveClassifier.set("javadoc") + from("$buildDir/kdoc") } artifacts { - add("archives", sourcesJar.get()) + add("archives", sourcesJar) + add("archives", kdocJar) } tasks.withType { @@ -113,7 +168,7 @@ subprojects { xml.required.set(false) csv.required.set(false) html.required.set(true) - html.outputLocation.set(layout.buildDirectory.dir("reports/coverage").get().asFile) + html.outputLocation.set(file("$buildDir/reports/coverage")) } } @@ -121,16 +176,6 @@ subprojects { finalizedBy("jacocoTestReport") } - // spotless { - // kotlin { - // ktlint() - // } - // kotlinGradle { - // target("*.gradle.kts'", "additionalScripts/*.gradle.kts") - // ktlint() - // } - // } - detekt { source.setFrom(files("src/main/kotlin", "src/test/kotlin")) baseline = file("detekt-${project.name}-baseline.xml") @@ -140,46 +185,45 @@ subprojects { tasks.withType { exclude(".*/resources/.*,.*/build/.*") - jvmTarget = "19" + jvmTarget = "17" // Use JDK 17 instead of 21 for detekt config.setFrom(files("${project.rootDir}/config/detekt/detekt.yml")) - // Skip detekt for now until we can fix the baselines + // Skip this task to make the build work for now enabled = false } + val tag = System.getProperty("tag") + val libVersion = if (tag.isNullOrEmpty()) project.version.toString() else tag + "-SNAPSHOT" + println("PUBLISHING- groupId: $group version: $libVersion artifactId: ${base.archivesName.get()}") publishing { publications { create("maven") { groupId = group.toString() - version = project.version.toString() - artifactId = "pipelinekt-${project.name}" + version = libVersion + artifactId = base.archivesName.get() from(components["java"]) - artifact(sourcesJar.get()) + artifact(sourcesJar) + artifact(kdocJar) } } repositories { mavenLocal() maven { - name = "GitHubPackages" - url = uri("https://maven.pkg.github.com/$githubRepo") - val token = System.getenv("GITHUB_TOKEN") - if (token != null) { - credentials(HttpHeaderCredentials::class) { - name = "Authorization" - value = "Bearer ${token}" - } - authentication { - create("header") - } - } else { - credentials { - username = System.getProperty("github.packages.username") ?: System.getenv("GITHUBUSER") - password = System.getProperty("github.packages.token") ?: System.getenv("GITHUBTOKEN") - } + name = "Snapshot" + url = uri("https://artifactory.corp.code42.com/artifactory/libs-snapshot-local/") + credentials { + username = System.getProperty("gradle.wrapperUser") + password = System.getProperty("gradle.wrapperPassword") + } + } + maven { + name = "Release" + url = uri("https://artifactory.corp.code42.com/artifactory/libs-release-local/") + credentials { + username = System.getProperty("gradle.wrapperUser") + password = System.getProperty("gradle.wrapperPassword") } } } } } } - - diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index b22ed732..876c922b 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -4,4 +4,4 @@ plugins { repositories { mavenCentral() -} \ No newline at end of file +} diff --git a/buildSrc/src/main/kotlin/com/code42/version/Version.kt b/buildSrc/src/main/kotlin/com/code42/version/Version.kt index ba72d44e..69ccedee 100644 --- a/buildSrc/src/main/kotlin/com/code42/version/Version.kt +++ b/buildSrc/src/main/kotlin/com/code42/version/Version.kt @@ -6,18 +6,18 @@ object Version { fun incrementVersion() { val versionFile = File("version.txt") val version = versionFile.readText() - .split(".") - .let {versionString -> - val versions = versionString.mapNotNull { it.toIntOrNull() } - if(versions.size != 3) { - throw IllegalArgumentException("version.txt should contain a version property with 3 parts, but contained $versionString") - } - val major = versions[0] - val minor = versions[1] - val patch = versions[2] + 1 - - "$major.$minor.${patch}" + .split(".") + .let { versionString -> + val versions = versionString.mapNotNull { it.toIntOrNull() } + if (versions.size != 3) { + throw IllegalArgumentException("version.txt should contain a version property with 3 parts, but contained $versionString") } + val major = versions[0] + val minor = versions[1] + val patch = versions[2] + 1 + + "$major.$minor.$patch" + } versionFile.writeText("$version") } @@ -25,4 +25,4 @@ object Version { fun getVersion(): String { return File("version.txt").readText() } -} \ No newline at end of file +} diff --git a/core/build.gradle.kts b/core/build.gradle.kts index e69de29b..9991deef 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -0,0 +1 @@ +// Core module - no additional dependencies required diff --git a/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/Pipeline.kt b/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/Pipeline.kt index ffa570e5..696f30bd 100644 --- a/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/Pipeline.kt +++ b/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/Pipeline.kt @@ -7,12 +7,7 @@ import com.code42.jenkins.pipelinekt.core.writer.GroovyWriter import com.code42.jenkins.pipelinekt.core.writer.ext.toGroovy import java.io.File -fun generatePipeline( - pipeline: Pipeline, - outFile: String, - indentStr: String = " ", - imports: List = emptyList() -) { +fun generatePipeline(pipeline: Pipeline, outFile: String, indentStr: String = " ", imports: List = emptyList()) { val dir = outFile.substringBeforeLast('/') File(dir).mkdirs() val writer = GroovyWriter.forFile(File(outFile), indentStr) @@ -33,7 +28,7 @@ data class Pipeline( val methods: List = emptyList(), val post: Post = Post(), val customWorkspace: String? = null, - val useMultibranchWorkspace: Boolean = true + val useMultibranchWorkspace: Boolean = true, ) : GroovyScript { override fun toGroovy(writer: GroovyWriter) { if (methods.isNotEmpty()) { @@ -57,28 +52,34 @@ data class Pipeline( if (parameters.isNotEmpty()) { writer.closure("parameters", parameters::toGroovy) } - + // Handle custom workspace logic - if (customWorkspace != null || useMultibranchWorkspace) { + if (customWorkspace != null) { // If a specific custom workspace is provided, use it directly - if (customWorkspace != null) { - writer.writeln("def customPath = \"$customWorkspace\"") - writer.closure("ws(customPath)") { wsWriter -> - wsWriter.writeln("checkout scm") - wsWriter.closure("stages", stages::toGroovy) - post.toGroovy(wsWriter) - } - } else if (useMultibranchWorkspace) { - // Generate multibranch workspace path calculation - writer.writeln("def rootDir = new File(env.WORKSPACE).parentFile.parent") - writer.writeln("def safeBranch = (env.BRANCH_NAME ?: 'unknown').replaceAll(/[^A-Za-z0-9._-]/, '_')") - writer.writeln("def customPath = \"${"\${rootDir}/${"\${env.JOB_NAME}-\${safeBranch}"}"}\"") - writer.closure("ws(customPath)") { wsWriter -> + writer.writeln("def customPath = \"$customWorkspace\"") + writer.closure("ws(customPath)") { wsWriter -> + wsWriter.writeln("checkout scm") + wsWriter.closure("stages", stages::toGroovy) + post.toGroovy(wsWriter) + } + } else if (useMultibranchWorkspace) { + // Check if this is a multibranch pipeline at runtime and use custom workspace if so + writer.closure("if (env.BRANCH_NAME)") { ifWriter -> + ifWriter.writeln("// Calculate multibranch-specific workspace path") + ifWriter.writeln("def rootDir = new File(env.WORKSPACE).parentFile.parent") + ifWriter.writeln("def safeBranch = (env.BRANCH_NAME ?: 'unknown').replaceAll(/[^A-Za-z0-9._-]/, '_')") + ifWriter.writeln("def customPath = \"${"\${rootDir}/${"\${env.JOB_NAME}-\${safeBranch}"}"}\"") + ifWriter.closure("ws(customPath)") { wsWriter -> wsWriter.writeln("checkout scm") wsWriter.closure("stages", stages::toGroovy) post.toGroovy(wsWriter) } } + writer.closure("else") { elseWriter -> + elseWriter.writeln("// Not a multibranch pipeline, use default workspace") + elseWriter.closure("stages", stages::toGroovy) + post.toGroovy(elseWriter) + } } else { // Regular pipeline without custom workspace writer.closure("stages", stages::toGroovy) diff --git a/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/Post.kt b/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/Post.kt index 3242bae0..d2c8a852 100644 --- a/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/Post.kt +++ b/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/Post.kt @@ -15,20 +15,23 @@ data class Post( val aborted: Step = Void, val unsuccessful: Step = Void, val unstable: Step = Void, - val failure: Step = Void + val failure: Step = Void, ) : GroovyScript { override fun toGroovy(writer: GroovyWriter) { - if (listOf(always, - success, - cleanup, - changed, - fixed, - regression, - aborted, - unstable, - unstable, - failure).any { !it.isEmpty() }) { + if (listOf( + always, + success, + cleanup, + changed, + fixed, + regression, + aborted, + unstable, + unstable, + failure, + ).any { !it.isEmpty() } + ) { writer.closure("post") { writer -> toGroovy("success", success, writer) toGroovy("always", always, writer) @@ -49,16 +52,16 @@ data class Post( } } - fun merge(other: Post): Post = - this.copy( - always = always.andThen(other.always), - success = success.andThen(other.success), - cleanup = cleanup.andThen(other.cleanup), - changed = changed.andThen(other.changed), - fixed = fixed.andThen(other.fixed), - regression = regression.andThen(other.regression), - aborted = aborted.andThen(other.aborted), - unsuccessful = unsuccessful.andThen(other.unsuccessful), - unstable = unstable.andThen(other.unstable), - failure = failure.andThen(other.failure)) + fun merge(other: Post): Post = this.copy( + always = always.andThen(other.always), + success = success.andThen(other.success), + cleanup = cleanup.andThen(other.cleanup), + changed = changed.andThen(other.changed), + fixed = fixed.andThen(other.fixed), + regression = regression.andThen(other.regression), + aborted = aborted.andThen(other.aborted), + unsuccessful = unsuccessful.andThen(other.unsuccessful), + unstable = unstable.andThen(other.unstable), + failure = failure.andThen(other.failure), + ) } diff --git a/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/agent/DockerAgent.kt b/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/agent/DockerAgent.kt index dd1fcb7b..575c9faf 100644 --- a/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/agent/DockerAgent.kt +++ b/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/agent/DockerAgent.kt @@ -19,7 +19,7 @@ sealed class DockerAgent : Agent { override val customWorkspace: Var.Literal.Str? = null, override val registryUrl: Var.Literal.Str? = null, override val registryCredentialsId: Var.Literal.Str? = null, - override val reuseNode: Var.Literal.Bool? = null + override val reuseNode: Var.Literal.Bool? = null, ) : DockerAgent() { override fun toGroovy(writer: GroovyWriter) { writer.closure("agent") { writer -> @@ -45,7 +45,7 @@ sealed class DockerAgent : Agent { override val customWorkspace: Var.Literal.Str? = null, override val registryUrl: Var.Literal.Str? = null, override val registryCredentialsId: Var.Literal.Str? = null, - override val reuseNode: Var.Literal.Bool? = null + override val reuseNode: Var.Literal.Bool? = null, ) : DockerAgent() { override fun toGroovy(writer: GroovyWriter) { writer.closure("agent") { writer -> diff --git a/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/credentials/File.kt b/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/credentials/File.kt index 3e5f46cd..4f5932a0 100644 --- a/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/credentials/File.kt +++ b/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/credentials/File.kt @@ -4,8 +4,10 @@ import com.code42.jenkins.pipelinekt.core.vars.Var data class File(val credentialsId: Var, val variable: Var.Literal.Str) : JenkinsCredentials { override fun toGroovy(): List { - return listOf("\$class: 'FileBinding',", - "credentialsId: ${credentialsId.toGroovy()},", - "variable: ${variable.toGroovy()}") + return listOf( + "\$class: 'FileBinding',", + "credentialsId: ${credentialsId.toGroovy()},", + "variable: ${variable.toGroovy()}", + ) } } diff --git a/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/credentials/SshUserPrivateKey.kt b/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/credentials/SshUserPrivateKey.kt index 2a01fb3b..fa3187b0 100644 --- a/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/credentials/SshUserPrivateKey.kt +++ b/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/credentials/SshUserPrivateKey.kt @@ -6,14 +6,16 @@ data class SshUserPrivateKey( val keyFileVariable: Var.Environment, val credentialsId: Var.Literal.Str, val passphraseVariable: Var.Environment? = null, - val usernameVariable: Var.Environment? = null + val usernameVariable: Var.Environment? = null, ) : JenkinsCredentials { override fun toGroovy(): List { - return listOf("\$class: 'SSHUserPrivateKeyBinding',", - "credentialsId: ${credentialsId.toGroovy()},", - "keyFileVariable: '${keyFileVariable.name}',", - usernameVariable?.let { "usernameVariable: '${it.name}'," }, - passphraseVariable?.let { "passphraseVariable: '${it.name}'" }) - .mapNotNull { it } + return listOf( + "\$class: 'SSHUserPrivateKeyBinding',", + "credentialsId: ${credentialsId.toGroovy()},", + "keyFileVariable: '${keyFileVariable.name}',", + usernameVariable?.let { "usernameVariable: '${it.name}'," }, + passphraseVariable?.let { "passphraseVariable: '${it.name}'" }, + ) + .mapNotNull { it } } } diff --git a/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/credentials/Text.kt b/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/credentials/Text.kt index 8715c1a9..82e57d71 100644 --- a/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/credentials/Text.kt +++ b/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/credentials/Text.kt @@ -4,8 +4,10 @@ import com.code42.jenkins.pipelinekt.core.vars.Var data class Text(val credentialsId: Var, val variable: Var.Literal.Str) : JenkinsCredentials { override fun toGroovy(): List { - return listOf("\$class: 'StringBinding',", - "credentialsId: ${credentialsId.toGroovy()},", - "variable: ${variable.toGroovy()}") + return listOf( + "\$class: 'StringBinding',", + "credentialsId: ${credentialsId.toGroovy()},", + "variable: ${variable.toGroovy()}", + ) } } diff --git a/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/credentials/UsernamePassword.kt b/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/credentials/UsernamePassword.kt index d8feb787..8919f7cb 100644 --- a/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/credentials/UsernamePassword.kt +++ b/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/credentials/UsernamePassword.kt @@ -5,14 +5,14 @@ import com.code42.jenkins.pipelinekt.core.vars.Var data class UsernamePassword( val credentialsId: Var, val usernameVariable: Var.Literal.Str, - val passwordVariable: Var.Literal.Str + val passwordVariable: Var.Literal.Str, ) : JenkinsCredentials { override fun toGroovy(): List { return listOf( "\$class: 'UsernamePasswordMultiBinding',", "credentialsId: ${credentialsId.toGroovy()},", "usernameVariable: ${usernameVariable.toGroovy()},", - "passwordVariable: ${passwordVariable.toGroovy()}" + "passwordVariable: ${passwordVariable.toGroovy()}", ) } } diff --git a/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/method/PipelineMethod.kt b/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/method/PipelineMethod.kt index a094a74f..c7b68d38 100644 --- a/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/method/PipelineMethod.kt +++ b/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/method/PipelineMethod.kt @@ -6,7 +6,7 @@ import com.code42.jenkins.pipelinekt.core.writer.GroovyWriter data class PipelineMethod( val name: String, - val steps: Step + val steps: Step, ) : GroovyScript { companion object { diff --git a/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/method/PipelineMethodException.kt b/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/method/PipelineMethodException.kt index 85ce56e5..d686ebed 100644 --- a/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/method/PipelineMethodException.kt +++ b/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/method/PipelineMethodException.kt @@ -4,5 +4,5 @@ import com.code42.jenkins.pipelinekt.core.vars.Var data class PipelineMethodException( val invocationValues: Map, - override val message: String + override val message: String, ) : Exception() diff --git a/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/secrets/VaultSecrets.kt b/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/secrets/VaultSecrets.kt index 9d234a12..15455e89 100644 --- a/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/secrets/VaultSecrets.kt +++ b/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/secrets/VaultSecrets.kt @@ -9,7 +9,7 @@ package com.code42.jenkins.pipelinekt.core.secrets data class VaultSecrets( val path: String, val engineVersion: String, - val secrets: List + val secrets: List, ) : Secrets { override fun toGroovy(): String { @@ -19,7 +19,7 @@ data class VaultSecrets( while (listIterator.hasNext()) { builder.append( " " + listIterator.next().toGroovy() + - (if (listIterator.hasNext()) ",\n" else "\n") + (if (listIterator.hasNext()) ",\n" else "\n"), ) } builder.append(" ]]]") diff --git a/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/stage/MatrixAxis.kt b/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/stage/MatrixAxis.kt index 5086b883..68b9331c 100644 --- a/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/stage/MatrixAxis.kt +++ b/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/stage/MatrixAxis.kt @@ -6,7 +6,7 @@ import com.code42.jenkins.pipelinekt.core.writer.GroovyWriter data class MatrixAxis( val name: Var.Literal.Str, - val values: List + val values: List, ) : GroovyScript { override fun toGroovy(writer: GroovyWriter) { writer.closure("axis") { diff --git a/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/stage/MatrixBody.kt b/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/stage/MatrixBody.kt index 8744c43e..3bb26433 100644 --- a/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/stage/MatrixBody.kt +++ b/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/stage/MatrixBody.kt @@ -17,7 +17,7 @@ data class MatrixBody( val whenBlock: List = emptyList(), val tools: List = emptyList(), val options: List = emptyList(), - val post: Post = Post() + val post: Post = Post(), ) : GroovyScript { override fun toGroovy(writer: GroovyWriter) { writer.closure("matrix") { writer -> diff --git a/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/stage/Stage.kt b/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/stage/Stage.kt index c41598af..c0c45087 100644 --- a/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/stage/Stage.kt +++ b/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/stage/Stage.kt @@ -20,6 +20,7 @@ sealed class Stage : GroovyScript { abstract val whenBlock: List? abstract val tools: List abstract val options: List + /** * Execute stages in parallel * @@ -33,11 +34,10 @@ sealed class Stage : GroovyScript { override val whenBlock: List = emptyList(), override val tools: List = emptyList(), override val options: List = emptyList(), - override val post: Post = Post() + override val post: Post = Post(), ) : Stage() { override fun toGroovy(writer: GroovyWriter) { - writer.closure("stage(${name.toGroovy()})") { writer -> agent?.toGroovy(writer) @@ -65,7 +65,7 @@ sealed class Stage : GroovyScript { override val whenBlock: List = emptyList(), override val tools: List = emptyList(), override val options: List = emptyList(), - override val post: Post = Post() + override val post: Post = Post(), ) : Stage() { override fun toGroovy(writer: GroovyWriter) { @@ -104,7 +104,7 @@ sealed class Stage : GroovyScript { override val whenBlock: List = emptyList(), override val tools: List = emptyList(), override val options: List = emptyList(), - override val post: Post = Post() + override val post: Post = Post(), ) : Stage() { override fun toGroovy(writer: GroovyWriter) { @@ -131,7 +131,7 @@ sealed class Stage : GroovyScript { val matrixBody: MatrixBody, override val whenBlock: List = emptyList(), override val options: List = emptyList(), - override val post: Post = Post() + override val post: Post = Post(), ) : Stage() { override val agent: Agent? = null override val tools: List = emptyList() diff --git a/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/step/NestedStep.kt b/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/step/NestedStep.kt index 32c06114..7a60d749 100644 --- a/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/step/NestedStep.kt +++ b/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/step/NestedStep.kt @@ -5,8 +5,7 @@ interface NestedStep : Step { override fun isEmpty(): Boolean = steps.isEmpty() - override fun contains(other: Step): Boolean = - this.equals(other) || this.steps.contains(other) + override fun contains(other: Step): Boolean = this.equals(other) || this.steps.contains(other) override fun any(fn: (Step) -> Boolean): Boolean = fn(this) || steps.any(fn) } diff --git a/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/step/Sequence.kt b/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/step/Sequence.kt index fb4e59b3..bf1ad28f 100644 --- a/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/step/Sequence.kt +++ b/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/step/Sequence.kt @@ -7,19 +7,17 @@ data class Sequence(val steps: List) : DeclarativeStep { override fun isEmpty(): Boolean = steps.isEmpty() || steps.all { it.isEmpty() } - override fun andThen(next: Step): Step = - when (next) { - is Sequence -> this.copy(steps = steps + next.steps) - is Void -> this - else -> this.copy(steps = steps + next) - } - - override fun precededBy(previous: Step): Step = - when (previous) { - is Sequence -> this.copy(steps = previous.steps + steps) - is Void -> this - else -> this.copy(steps = listOf(previous) + steps) - } + override fun andThen(next: Step): Step = when (next) { + is Sequence -> this.copy(steps = steps + next.steps) + is Void -> this + else -> this.copy(steps = steps + next) + } + + override fun precededBy(previous: Step): Step = when (previous) { + is Sequence -> this.copy(steps = previous.steps + steps) + is Void -> this + else -> this.copy(steps = listOf(previous) + steps) + } override fun contains(other: Step): Boolean = this.steps.any { it.contains(other) } override fun toGroovy(writer: GroovyWriter) { @@ -28,11 +26,10 @@ data class Sequence(val steps: List) : DeclarativeStep { override fun any(fn: (Step) -> Boolean): Boolean = fn(this) || steps.any(fn) - fun flatten(): Step = - steps.fold(Void, { flattendSteps, step -> - when (step) { - is Sequence -> flattendSteps.andThen(step.flatten()) - else -> flattendSteps.andThen(step) - } - }) + fun flatten(): Step = steps.fold(Void, { flattendSteps, step -> + when (step) { + is Sequence -> flattendSteps.andThen(step.flatten()) + else -> flattendSteps.andThen(step) + } + }) } diff --git a/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/step/Step.kt b/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/step/Step.kt index bf84fa20..fe223913 100644 --- a/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/step/Step.kt +++ b/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/step/Step.kt @@ -5,19 +5,17 @@ import com.code42.jenkins.pipelinekt.core.writer.GroovyScript interface Step : GroovyScript { fun andThen(next: () -> Step) = andThen(next()) - fun andThen(next: Step): Step = - when (next) { - is Sequence -> next.precededBy(this) - is Void -> this - else -> Sequence(listOf(this, next)) - } + fun andThen(next: Step): Step = when (next) { + is Sequence -> next.precededBy(this) + is Void -> this + else -> Sequence(listOf(this, next)) + } - fun precededBy(previous: Step): Step = - when (previous) { - is Sequence -> previous.andThen(this) - is Void -> this - else -> Sequence(listOf(previous, this)) - } + fun precededBy(previous: Step): Step = when (previous) { + is Sequence -> previous.andThen(this) + is Void -> this + else -> Sequence(listOf(previous, this)) + } fun isEmpty(): Boolean fun contains(other: Step): Boolean fun any(fn: (Step) -> Boolean): Boolean diff --git a/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/utils/WorkspacePath.kt b/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/utils/WorkspacePath.kt index 6641261e..252030f5 100644 --- a/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/utils/WorkspacePath.kt +++ b/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/utils/WorkspacePath.kt @@ -1,10 +1,9 @@ package com.code42.jenkins.pipelinekt.core.utils -import com.code42.jenkins.pipelinekt.core.vars.Var -import com.code42.jenkins.pipelinekt.core.vars.ext.strSingle -import com.code42.jenkins.pipelinekt.core.vars.ext.strDouble import com.code42.jenkins.pipelinekt.core.vars.Var.Environment import com.code42.jenkins.pipelinekt.core.vars.Var.Literal.Str +import com.code42.jenkins.pipelinekt.core.vars.ext.strDouble +import com.code42.jenkins.pipelinekt.core.vars.ext.strSingle /** * Utility functions for working with workspace paths @@ -20,7 +19,7 @@ object WorkspacePath { val branchVar = Environment(branchEnvVar) return "\${basePath}-\${${branchVar.toGroovy()}}".strDouble() } - + /** * Generates a workspace path for a specific directory * @param basePath The base path to use @@ -30,4 +29,4 @@ object WorkspacePath { fun forDir(basePath: String, subDir: String): Str { return "$basePath/$subDir".strSingle() } -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/vars/Var.kt b/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/vars/Var.kt index 7969f4d8..34818bfe 100644 --- a/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/vars/Var.kt +++ b/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/vars/Var.kt @@ -20,8 +20,7 @@ sealed class Var { } } data class ClosureInvocation(val name: String, val arguments: List = emptyList()) : Var() { - override fun toGroovy(): String = - "$name(${arguments.map { it.toGroovy()}.allButLast { "$it, "}.joinToString("")})" + override fun toGroovy(): String = "$name(${arguments.map { it.toGroovy()}.allButLast { "$it, "}.joinToString("")})" } /** diff --git a/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/vars/ext/Ext.kt b/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/vars/ext/Ext.kt index 1974e545..35b2362e 100644 --- a/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/vars/ext/Ext.kt +++ b/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/vars/ext/Ext.kt @@ -17,12 +17,14 @@ fun Boolean.boolVar(): Var.Literal.Bool = Var.Literal.Bool(this) * convert to a Jenkinsfile single quoted string var */ fun String.strSingle(): Var.Literal.Str.Single = Var.Literal.Str.Single(this) + /** * convert to a Jenkinsfile double quoted string var */ fun String.strDouble(): Var.Literal.Str.Double = Var.Literal.Str.Double(this) fun String.multline(): Var.Literal.Str.Multiline = Var.Literal.Str.Multiline(this) + /** * Inlines a literal groovy string; Be careful */ diff --git a/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/writer/ext/Ext.kt b/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/writer/ext/Ext.kt index 0ec0acf8..9a51a607 100644 --- a/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/writer/ext/Ext.kt +++ b/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/writer/ext/Ext.kt @@ -19,7 +19,7 @@ fun List.toGroovy(writer: GroovyWriter) { fun Map.toGroovy(writer: GroovyWriter) { writer.writeln("[") this.map { "${writer.indentStr}${it.key.toGroovy()}: ${it.value.toGroovy()}" } - .allButLast { str -> "$str," } - .forEach(writer::writeln) + .allButLast { str -> "$str," } + .forEach(writer::writeln) writer.writeln("]") } diff --git a/core/src/test/kotlin/com/code42/jenkins/pipelinekt/core/GroovyScriptTest.kt b/core/src/test/kotlin/com/code42/jenkins/pipelinekt/core/GroovyScriptTest.kt index 3bea64c8..7c1ba843 100644 --- a/core/src/test/kotlin/com/code42/jenkins/pipelinekt/core/GroovyScriptTest.kt +++ b/core/src/test/kotlin/com/code42/jenkins/pipelinekt/core/GroovyScriptTest.kt @@ -1,9 +1,9 @@ package com.code42.jenkins.pipelinekt.core import com.code42.jenkins.pipelinekt.core.writer.GroovyWriter +import org.junit.Before import java.io.PrintWriter import java.io.StringWriter -import org.junit.Before abstract class GroovyScriptTest { var out: StringWriter = StringWriter() diff --git a/core/src/test/kotlin/com/code42/jenkins/pipelinekt/core/PipelineWorkspaceTest.kt b/core/src/test/kotlin/com/code42/jenkins/pipelinekt/core/PipelineWorkspaceTest.kt new file mode 100644 index 00000000..27cacdac --- /dev/null +++ b/core/src/test/kotlin/com/code42/jenkins/pipelinekt/core/PipelineWorkspaceTest.kt @@ -0,0 +1,96 @@ +package com.code42.jenkins.pipelinekt.core + +import com.code42.jenkins.pipelinekt.core.stage.Stage +import com.code42.jenkins.pipelinekt.core.vars.ext.strDouble +import com.code42.jenkins.pipelinekt.core.writer.GroovyWriter +import org.junit.Test +import java.io.PrintWriter +import java.io.StringWriter +import kotlin.test.assertTrue + +class PipelineWorkspaceTest { + + @Test + fun `pipeline with useMultibranchWorkspace true generates runtime check`() { + val pipeline = Pipeline( + stages = listOf( + Stage.Steps( + name = "Build".strDouble(), + steps = TestStep("echo 'build'"), + ), + ), + useMultibranchWorkspace = true, + ) + + val stringWriter = StringWriter() + val writer = GroovyWriter(PrintWriter(stringWriter), 0, indentStr = " ") + pipeline.toGroovy(writer) + val result = stringWriter.toString() + + println("=== Generated Jenkinsfile with useMultibranchWorkspace=true ===") + println(result) + + // Verify it contains the runtime check + assertTrue(result.contains("if (env.BRANCH_NAME)"), "Should check for BRANCH_NAME") + assertTrue(result.contains("def rootDir = new File(env.WORKSPACE).parentFile.parent")) + assertTrue(result.contains("def safeBranch = (env.BRANCH_NAME ?: 'unknown').replaceAll(/[^A-Za-z0-9._-]/, '_')")) + assertTrue(result.contains("def customPath")) + assertTrue(result.contains("ws(customPath)")) + assertTrue(result.contains("checkout scm")) + assertTrue(result.contains("else {"), "Should have else block for non-multibranch") + } + + @Test + fun `pipeline with custom workspace uses it directly`() { + val pipeline = Pipeline( + stages = listOf( + Stage.Steps( + name = "Build".strDouble(), + steps = TestStep("echo 'build'"), + ), + ), + customWorkspace = "/my/custom/workspace", + ) + + val stringWriter = StringWriter() + val writer = GroovyWriter(PrintWriter(stringWriter), 0, indentStr = " ") + pipeline.toGroovy(writer) + val result = stringWriter.toString() + + println("\n=== Generated Jenkinsfile with customWorkspace ===") + println(result) + + // Verify it uses custom workspace directly + assertTrue(result.contains("def customPath = \"/my/custom/workspace\"")) + assertTrue(result.contains("ws(customPath)")) + assertTrue(result.contains("checkout scm")) + assertTrue(!result.contains("if (env.BRANCH_NAME)"), "Should NOT check for BRANCH_NAME when custom workspace is set") + } + + @Test + fun `pipeline with useMultibranchWorkspace false uses default workspace`() { + val pipeline = Pipeline( + stages = listOf( + Stage.Steps( + name = "Build".strDouble(), + steps = TestStep("echo 'build'"), + ), + ), + useMultibranchWorkspace = false, + ) + + val stringWriter = StringWriter() + val writer = GroovyWriter(PrintWriter(stringWriter), 0, indentStr = " ") + pipeline.toGroovy(writer) + val result = stringWriter.toString() + + println("\n=== Generated Jenkinsfile with useMultibranchWorkspace=false ===") + println(result) + + // Verify it doesn't use any workspace wrapping + assertTrue(!result.contains("ws("), "Should NOT use ws() wrapper") + assertTrue(!result.contains("customPath"), "Should NOT have customPath") + assertTrue(!result.contains("checkout scm"), "Should NOT have checkout scm") + assertTrue(result.contains("stages {"), "Should have stages block directly") + } +} diff --git a/core/src/test/kotlin/com/code42/jenkins/pipelinekt/core/agent/DockerAgentTest.kt b/core/src/test/kotlin/com/code42/jenkins/pipelinekt/core/agent/DockerAgentTest.kt index 38cccec4..c22897dd 100644 --- a/core/src/test/kotlin/com/code42/jenkins/pipelinekt/core/agent/DockerAgentTest.kt +++ b/core/src/test/kotlin/com/code42/jenkins/pipelinekt/core/agent/DockerAgentTest.kt @@ -3,8 +3,8 @@ package com.code42.jenkins.pipelinekt.core.agent import com.code42.jenkins.pipelinekt.core.GroovyScriptTest import com.code42.jenkins.pipelinekt.core.vars.ext.boolVar import com.code42.jenkins.pipelinekt.core.vars.ext.strDouble -import kotlin.test.assertEquals import org.junit.Test +import kotlin.test.assertEquals class DockerAgentTest : GroovyScriptTest() { @Test @@ -25,9 +25,15 @@ class DockerAgentTest : GroovyScriptTest() { @Test fun dockerImage_Serializes_allFields() { - val agent = DockerAgent.Image("my.image:123".strDouble(), "my args".strDouble(), "mylabel".strDouble(), - "custom/worksapce".strDouble(), "https://custom.registry".strDouble(), "reg-creds".strDouble(), - false.boolVar()) + val agent = DockerAgent.Image( + "my.image:123".strDouble(), + "my args".strDouble(), + "mylabel".strDouble(), + "custom/worksapce".strDouble(), + "https://custom.registry".strDouble(), + "reg-creds".strDouble(), + false.boolVar(), + ) val expected = """ agent { @@ -66,15 +72,16 @@ class DockerAgentTest : GroovyScriptTest() { @Test fun dockerFile_Serializes_allFields() { val agent = DockerAgent.File( - "agent.Dockerfile".strDouble(), - "ci/".strDouble(), - "build args".strDouble(), - "my args".strDouble(), - "mylabel".strDouble(), - "custom/worksapce".strDouble(), - "https://custom.registry".strDouble(), - "reg-creds".strDouble(), - false.boolVar()) + "agent.Dockerfile".strDouble(), + "ci/".strDouble(), + "build args".strDouble(), + "my args".strDouble(), + "mylabel".strDouble(), + "custom/worksapce".strDouble(), + "https://custom.registry".strDouble(), + "reg-creds".strDouble(), + false.boolVar(), + ) val expected = """ agent { diff --git a/core/src/test/kotlin/com/code42/jenkins/pipelinekt/core/credentials/JenkinsCredentialsTest.kt b/core/src/test/kotlin/com/code42/jenkins/pipelinekt/core/credentials/JenkinsCredentialsTest.kt index b618bf36..30f6457e 100644 --- a/core/src/test/kotlin/com/code42/jenkins/pipelinekt/core/credentials/JenkinsCredentialsTest.kt +++ b/core/src/test/kotlin/com/code42/jenkins/pipelinekt/core/credentials/JenkinsCredentialsTest.kt @@ -2,8 +2,8 @@ package com.code42.jenkins.pipelinekt.core.credentials import com.code42.jenkins.pipelinekt.core.vars.ext.environmentVar import com.code42.jenkins.pipelinekt.core.vars.ext.strSingle -import kotlin.test.assertEquals import org.junit.Test +import kotlin.test.assertEquals class JenkinsCredentialsTest { @Test fun usernameAndPassword() { @@ -11,10 +11,11 @@ class JenkinsCredentialsTest { val usernameVariable = "CREDS_USERNAME".strSingle() val passwordVariable = "CREDS_PASSWORD".strSingle() val expected = listOf( - "\$class: 'UsernamePasswordMultiBinding',", - "credentialsId: ${credentialsId.toGroovy()},", - "usernameVariable: ${usernameVariable.toGroovy()},", - "passwordVariable: ${passwordVariable.toGroovy()}") + "\$class: 'UsernamePasswordMultiBinding',", + "credentialsId: ${credentialsId.toGroovy()},", + "usernameVariable: ${usernameVariable.toGroovy()},", + "passwordVariable: ${passwordVariable.toGroovy()}", + ) val actual = UsernamePassword(credentialsId, usernameVariable, passwordVariable).toGroovy() assertEquals(expected, actual) } @@ -23,9 +24,10 @@ class JenkinsCredentialsTest { val credentialsId = "my-creds".strSingle() val variable = "CREDS_USERNAME".strSingle() val expected = listOf( - "\$class: 'StringBinding',", - "credentialsId: ${credentialsId.toGroovy()},", - "variable: ${variable.toGroovy()}") + "\$class: 'StringBinding',", + "credentialsId: ${credentialsId.toGroovy()},", + "variable: ${variable.toGroovy()}", + ) val actual = Text(credentialsId, variable).toGroovy() assertEquals(expected, actual) } @@ -34,9 +36,10 @@ class JenkinsCredentialsTest { val credentialsId = "my-creds".strSingle() val variable = "CREDS_USERNAME".strSingle() val expected = listOf( - "\$class: 'FileBinding',", - "credentialsId: ${credentialsId.toGroovy()},", - "variable: ${variable.toGroovy()}") + "\$class: 'FileBinding',", + "credentialsId: ${credentialsId.toGroovy()},", + "variable: ${variable.toGroovy()}", + ) val actual = File(credentialsId, variable).toGroovy() assertEquals(expected, actual) } @@ -49,11 +52,16 @@ class JenkinsCredentialsTest { val actual = SshUserPrivateKey(keyFileVariable, credentialsId, passphraseVariable, usernameVariable).toGroovy() - assertEquals(listOf("\$class: 'SSHUserPrivateKeyBinding',", + assertEquals( + listOf( + "\$class: 'SSHUserPrivateKeyBinding',", "credentialsId: ${credentialsId.toGroovy()},", "keyFileVariable: '${keyFileVariable.name}',", "usernameVariable: '${usernameVariable.name}',", - "passphraseVariable: '${passphraseVariable.name}'"), actual) + "passphraseVariable: '${passphraseVariable.name}'", + ), + actual, + ) } @Test fun userSshKeyWithDefaults() { @@ -62,8 +70,13 @@ class JenkinsCredentialsTest { val actual = SshUserPrivateKey(keyFileVariable, credentialsId).toGroovy() - assertEquals(listOf("\$class: 'SSHUserPrivateKeyBinding',", + assertEquals( + listOf( + "\$class: 'SSHUserPrivateKeyBinding',", "credentialsId: ${credentialsId.toGroovy()},", - "keyFileVariable: '${keyFileVariable.name}',"), actual) + "keyFileVariable: '${keyFileVariable.name}',", + ), + actual, + ) } } diff --git a/core/src/test/kotlin/com/code42/jenkins/pipelinekt/core/notifications/RecipientProviderTest.kt b/core/src/test/kotlin/com/code42/jenkins/pipelinekt/core/notifications/RecipientProviderTest.kt index 64fdb607..6c10853f 100644 --- a/core/src/test/kotlin/com/code42/jenkins/pipelinekt/core/notifications/RecipientProviderTest.kt +++ b/core/src/test/kotlin/com/code42/jenkins/pipelinekt/core/notifications/RecipientProviderTest.kt @@ -1,7 +1,7 @@ package com.code42.jenkins.pipelinekt.core.notifications -import kotlin.test.assertEquals import org.junit.Test +import kotlin.test.assertEquals class RecipientProviderTest { @Test fun hasCulpritsAndRequester() { diff --git a/core/src/test/kotlin/com/code42/jenkins/pipelinekt/core/post/PostTest.kt b/core/src/test/kotlin/com/code42/jenkins/pipelinekt/core/post/PostTest.kt index 8e8acb2b..a1d561fd 100644 --- a/core/src/test/kotlin/com/code42/jenkins/pipelinekt/core/post/PostTest.kt +++ b/core/src/test/kotlin/com/code42/jenkins/pipelinekt/core/post/PostTest.kt @@ -3,8 +3,8 @@ package com.code42.jenkins.pipelinekt.core.post import com.code42.jenkins.pipelinekt.core.GroovyScriptTest import com.code42.jenkins.pipelinekt.core.Post import com.code42.jenkins.pipelinekt.core.TestStep -import kotlin.test.assertEquals import org.junit.Test +import kotlin.test.assertEquals class PostTest : GroovyScriptTest() { @Test fun emptyPost() { @@ -17,10 +17,10 @@ class PostTest : GroovyScriptTest() { val post = Post(always = TestStep("hello")) post.toGroovy(writer) val expected = "post {\n" + - "\talways {\n" + - "\t\thello\n" + - "\t}\n" + - "}\n" + "\talways {\n" + + "\t\thello\n" + + "\t}\n" + + "}\n" assertEquals(expected, out.toString()) } @@ -28,10 +28,10 @@ class PostTest : GroovyScriptTest() { val post = Post(success = TestStep("hello")) post.toGroovy(writer) val expected = "post {\n" + - "\tsuccess {\n" + - "\t\thello\n" + - "\t}\n" + - "}\n" + "\tsuccess {\n" + + "\t\thello\n" + + "\t}\n" + + "}\n" assertEquals(expected, out.toString()) } @@ -39,10 +39,10 @@ class PostTest : GroovyScriptTest() { val post = Post(failure = TestStep("hello")) post.toGroovy(writer) val expected = "post {\n" + - "\tfailure {\n" + - "\t\thello\n" + - "\t}\n" + - "}\n" + "\tfailure {\n" + + "\t\thello\n" + + "\t}\n" + + "}\n" assertEquals(expected, out.toString()) } @@ -50,10 +50,10 @@ class PostTest : GroovyScriptTest() { val post = Post(cleanup = TestStep("hello")) post.toGroovy(writer) val expected = "post {\n" + - "\tcleanup {\n" + - "\t\thello\n" + - "\t}\n" + - "}\n" + "\tcleanup {\n" + + "\t\thello\n" + + "\t}\n" + + "}\n" assertEquals(expected, out.toString()) } } diff --git a/core/src/test/kotlin/com/code42/jenkins/pipelinekt/core/secrets/SecretsTest.kt b/core/src/test/kotlin/com/code42/jenkins/pipelinekt/core/secrets/SecretsTest.kt index 057df109..2193703e 100644 --- a/core/src/test/kotlin/com/code42/jenkins/pipelinekt/core/secrets/SecretsTest.kt +++ b/core/src/test/kotlin/com/code42/jenkins/pipelinekt/core/secrets/SecretsTest.kt @@ -11,13 +11,13 @@ class SecretsTest : GroovyScriptTest() { path = "some/vault/path", engineVersion = "1", secrets = listOf( - VaultSecret(envVar = "VAR_1", vaultKey = "KEY_1") - ) + VaultSecret(envVar = "VAR_1", vaultKey = "KEY_1"), + ), ) val expected = " vaultSecrets: [[path: \"some/vault/path\", engineVersion: 1, secretValues: [\n" + - " [envVar: 'VAR_1', vaultKey: 'KEY_1']\n" + - " ]]]" + " [envVar: 'VAR_1', vaultKey: 'KEY_1']\n" + + " ]]]" val out = secrets1.toGroovy() assertEquals(expected, out) } @@ -29,14 +29,14 @@ class SecretsTest : GroovyScriptTest() { engineVersion = "1", secrets = listOf( VaultSecret(envVar = "VAR_1", vaultKey = "KEY_1"), - VaultSecret(envVar = "VAR_2", vaultKey = "KEY_2") - ) + VaultSecret(envVar = "VAR_2", vaultKey = "KEY_2"), + ), ) val expected = " vaultSecrets: [[path: \"some/vault/path\", engineVersion: 1, secretValues: [\n" + - " [envVar: 'VAR_1', vaultKey: 'KEY_1'],\n" + - " [envVar: 'VAR_2', vaultKey: 'KEY_2']\n" + - " ]]]" + " [envVar: 'VAR_1', vaultKey: 'KEY_1'],\n" + + " [envVar: 'VAR_2', vaultKey: 'KEY_2']\n" + + " ]]]" val out = secrets1.toGroovy() assertEquals(expected, out) } diff --git a/core/src/test/kotlin/com/code42/jenkins/pipelinekt/core/stage/MatrixStageTest.kt b/core/src/test/kotlin/com/code42/jenkins/pipelinekt/core/stage/MatrixStageTest.kt index e8101125..b9000556 100644 --- a/core/src/test/kotlin/com/code42/jenkins/pipelinekt/core/stage/MatrixStageTest.kt +++ b/core/src/test/kotlin/com/code42/jenkins/pipelinekt/core/stage/MatrixStageTest.kt @@ -9,8 +9,8 @@ import com.code42.jenkins.pipelinekt.core.Tool import com.code42.jenkins.pipelinekt.core.When import com.code42.jenkins.pipelinekt.core.vars.ext.strDouble import com.code42.jenkins.pipelinekt.core.writer.GroovyWriter -import kotlin.test.assertEquals import org.junit.Test +import kotlin.test.assertEquals class MatrixStageTest : GroovyScriptTest() { @@ -18,37 +18,45 @@ class MatrixStageTest : GroovyScriptTest() { @Suppress("LongMethod") fun matrixStage() { Stage.Matrix( - name = "matrix stage".strDouble(), - matrixBody = MatrixBody( - axes = listOf( - MatrixAxis( - "OS".strDouble(), - listOf("mac", "windows", "linux").map { it.strDouble() }), - MatrixAxis( - "BROWSER".strDouble(), - listOf("ie", "safari", "chrome", "firefox").map { it.strDouble() }) - ), - excludes = listOf( - MatrixExclude(listOf( - ExcludeAxis.Values("OS".strDouble(), listOf("linux".strDouble())), - ExcludeAxis.NotValues( - "BROWSER".strDouble(), - listOf("chrome".strDouble(), "firefox".strDouble())) - )) + name = "matrix stage".strDouble(), + matrixBody = MatrixBody( + axes = listOf( + MatrixAxis( + "OS".strDouble(), + listOf("mac", "windows", "linux").map { it.strDouble() }, + ), + MatrixAxis( + "BROWSER".strDouble(), + listOf("ie", "safari", "chrome", "firefox").map { it.strDouble() }, + ), + ), + excludes = listOf( + MatrixExclude( + listOf( + ExcludeAxis.Values("OS".strDouble(), listOf("linux".strDouble())), + ExcludeAxis.NotValues( + "BROWSER".strDouble(), + listOf("chrome".strDouble(), "firefox".strDouble()), + ), ), - stages = listOf(Stage.Steps( - name = "nested stage".strDouble(), - steps = TestStep("nested") - )), - agent = TestAgent, - whenBlock = listOf(TestWhen("matrix")), - tools = listOf(TestTool), - options = listOf(TestOption), - post = Post(always = TestStep("postAlwaysMatrix()")) + ), + ), + stages = listOf( + Stage.Steps( + name = "nested stage".strDouble(), + steps = TestStep("nested"), + ), ), - whenBlock = listOf(TestWhen("stage")), + agent = TestAgent, + whenBlock = listOf(TestWhen("matrix")), + tools = listOf(TestTool), options = listOf(TestOption), - post = Post(always = TestStep("postAlways()"))).toGroovy(writer) + post = Post(always = TestStep("postAlwaysMatrix()")), + ), + whenBlock = listOf(TestWhen("stage")), + options = listOf(TestOption), + post = Post(always = TestStep("postAlways()")), + ).toGroovy(writer) val expected = """ stage("matrix stage") { @@ -110,7 +118,7 @@ class MatrixStageTest : GroovyScriptTest() { ${writer.indentStr.repeat(2)}} ${writer.indentStr}} } - + """.trimIndent() assertEquals(expected, out.toString()) } diff --git a/core/src/test/kotlin/com/code42/jenkins/pipelinekt/core/stage/StageTest.kt b/core/src/test/kotlin/com/code42/jenkins/pipelinekt/core/stage/StageTest.kt index d328134c..4413b459 100644 --- a/core/src/test/kotlin/com/code42/jenkins/pipelinekt/core/stage/StageTest.kt +++ b/core/src/test/kotlin/com/code42/jenkins/pipelinekt/core/stage/StageTest.kt @@ -11,19 +11,21 @@ import kotlin.test.assertEquals class StageTest : GroovyScriptTest() { @Test fun nestedSequenceTest() { val stage1 = Stage.Steps( - "my stage".strSingle(), - steps = TestStep("hello there") + "my stage".strSingle(), + steps = TestStep("hello there"), ) val stage2 = Stage.Sequence( - "my sequence".strSingle(), - stages = listOf( - Stage.Steps("sequence 1".strSingle(), steps = TestStep("hello again")), - Stage.Steps("sequence 2".strSingle(), steps = TestStep("hello again again"))) + "my sequence".strSingle(), + stages = listOf( + Stage.Steps("sequence 1".strSingle(), steps = TestStep("hello again")), + Stage.Steps("sequence 2".strSingle(), steps = TestStep("hello again again")), + ), ) val rootStage = Stage.Sequence( - "root".strSingle(), - listOf(stage1, stage2)) + "root".strSingle(), + listOf(stage1, stage2), + ) val expected = """ stage('root') { @@ -49,7 +51,7 @@ class StageTest : GroovyScriptTest() { ${indentStr.repeat(2)}} ${indentStr.repeat(1)}} } - + """.trimIndent() rootStage.toGroovy(writer) assertEquals(expected, out.toString()) @@ -57,19 +59,21 @@ class StageTest : GroovyScriptTest() { @Test fun topLevelSequenceTest() { val stage1 = Stage.Steps( - "my stage".strSingle(), - steps = TestStep("hello there") + "my stage".strSingle(), + steps = TestStep("hello there"), ) val stage2 = Stage.Sequence( - "my sequence".strSingle(), - stages = listOf( - Stage.Steps("sequence 1".strSingle(), steps = TestStep("hello again")), - Stage.Steps("sequence 2".strSingle(), steps = TestStep("hello again again"))) + "my sequence".strSingle(), + stages = listOf( + Stage.Steps("sequence 1".strSingle(), steps = TestStep("hello again")), + Stage.Steps("sequence 2".strSingle(), steps = TestStep("hello again again")), + ), ) val rootStage = Stage.Sequence( - "root".strSingle(), - listOf(stage1, stage2)) + "root".strSingle(), + listOf(stage1, stage2), + ) val expected = """ stage('root') { @@ -95,7 +99,7 @@ class StageTest : GroovyScriptTest() { ${indentStr.repeat(2)}} ${indentStr.repeat(1)}} } - + """.trimIndent() rootStage.toGroovy(writer) assertEquals(expected, out.toString()) @@ -103,19 +107,21 @@ class StageTest : GroovyScriptTest() { @Test fun parallelTest() { val stage1 = Stage.Steps( - "my stage".strSingle(), - steps = TestStep("hello there") + "my stage".strSingle(), + steps = TestStep("hello there"), ) val stage2 = Stage.Sequence( - "my sequence".strSingle(), - stages = listOf( - Stage.Steps("sequence 1".strSingle(), steps = TestStep("hello again")), - Stage.Steps("sequence 2".strSingle(), steps = TestStep("hello again again"))) + "my sequence".strSingle(), + stages = listOf( + Stage.Steps("sequence 1".strSingle(), steps = TestStep("hello again")), + Stage.Steps("sequence 2".strSingle(), steps = TestStep("hello again again")), + ), ) val rootStage = Stage.Parallel( - "root".strSingle(), - listOf(stage1, stage2)) + "root".strSingle(), + listOf(stage1, stage2), + ) val expected = """ stage('root') { @@ -141,7 +147,7 @@ class StageTest : GroovyScriptTest() { ${indentStr.repeat(2)}} ${indentStr.repeat(1)}} } - + """.trimIndent() rootStage.toGroovy(writer) assertEquals(expected, out.toString()) @@ -152,19 +158,23 @@ class StageTest : GroovyScriptTest() { writer.writeln(text) } } + @Test fun stageWithWhen() { val name = "before".strSingle() val stage1 = Stage.Steps( - name = name, - steps = TestStep("hello there"), - whenBlock = listOf( - TestWhen("someStatement"))) + name = name, + steps = TestStep("hello there"), + whenBlock = listOf( + TestWhen("someStatement"), + ), + ) val rootStage = Stage.Parallel( - "root".strSingle(), - listOf(stage1)) + "root".strSingle(), + listOf(stage1), + ) val expected = """ stage('root') { diff --git a/core/src/test/kotlin/com/code42/jenkins/pipelinekt/core/var/ClosureInvocationTest.kt b/core/src/test/kotlin/com/code42/jenkins/pipelinekt/core/var/ClosureInvocationTest.kt index a0460e07..40e39eac 100644 --- a/core/src/test/kotlin/com/code42/jenkins/pipelinekt/core/var/ClosureInvocationTest.kt +++ b/core/src/test/kotlin/com/code42/jenkins/pipelinekt/core/var/ClosureInvocationTest.kt @@ -1,3 +1,5 @@ +@file:Suppress("PackageName") + package com.code42.jenkins.pipelinekt.core.`var` import com.code42.jenkins.pipelinekt.core.vars.Var @@ -5,8 +7,8 @@ import com.code42.jenkins.pipelinekt.core.vars.ext.groovyVariable import com.code42.jenkins.pipelinekt.core.vars.ext.intVar import com.code42.jenkins.pipelinekt.core.vars.ext.strDouble import com.code42.jenkins.pipelinekt.core.vars.ext.strSingle -import kotlin.test.assertEquals import org.junit.Test +import kotlin.test.assertEquals class ClosureInvocationTest { @Test fun noArgs_toGroovy() { diff --git a/dsl/build.gradle.kts b/dsl/build.gradle.kts index 04135a79..cb83d0e2 100644 --- a/dsl/build.gradle.kts +++ b/dsl/build.gradle.kts @@ -1,4 +1,4 @@ dependencies { api(project(":core")) implementation(project(":internal")) -} \ No newline at end of file +} diff --git a/dsl/src/main/kotlin/com/code42/jenkins/pipelinekt/dsl/ConfigurationContextDsl.kt b/dsl/src/main/kotlin/com/code42/jenkins/pipelinekt/dsl/ConfigurationContextDsl.kt deleted file mode 100644 index d483047b..00000000 --- a/dsl/src/main/kotlin/com/code42/jenkins/pipelinekt/dsl/ConfigurationContextDsl.kt +++ /dev/null @@ -1 +0,0 @@ -package com.code42.jenkins.pipelinekt.dsl diff --git a/dsl/src/main/kotlin/com/code42/jenkins/pipelinekt/dsl/PipelineContext.kt b/dsl/src/main/kotlin/com/code42/jenkins/pipelinekt/dsl/PipelineContext.kt index 183346ad..79e07258 100644 --- a/dsl/src/main/kotlin/com/code42/jenkins/pipelinekt/dsl/PipelineContext.kt +++ b/dsl/src/main/kotlin/com/code42/jenkins/pipelinekt/dsl/PipelineContext.kt @@ -20,7 +20,7 @@ data class PipelineContext( val optionContext: DslContext